Maintaining State for Domain Objects
+Maintaining State for Domain Objects
Certain attributes of PgefObject are used solely to maintain the local state of a domain object instance, especially for the purpose of reflecting state when they are viewed and edited in PanGalaxianObject. Some of those @@ -773,8 +1074,8 @@
Versioning of Domain Objects
+Versioning of Domain Objects
The PanGalactic ontological Class pgef:Versionable is the Class of objects for which versions must be tracked and managed. The most important PanGalactic domain Classes (Part, Model, Document, and @@ -842,8 +1143,8 @@
Versioning of PanGalactic Meta Objects
+Versioning of PanGalactic Meta Objects
PanGalactic Meta Objects can be edited, versioned, and managed in the same way as domain objects in PGEF. However, new versions of meta objects are only deployed within the context of a full configuration of the Ontology version @@ -866,15 +1167,28 @@ Foo 1.1 namespace (say, "http://www.foo.org/20051001/").
Repository Services: The PanGalactic Entropy Reverser (PGER)
+Repository Services: The PanGalactic Entropy Reverser (PGER)
The PanGalactic Core Ontology provides the basis for the database structures of the The PanGalactic Entropy Reverser (PGER) (also known more prosaically as the PanGalactic Engineering Repository). The layer that translates the domain Classes and Properties of the ontology to the structure of the database is the Chronosynclastic Infundibulum.
-O-R Mapping: The Chronosynclastic Infundibulum
+The Chronosynclastic Infundibulum
+Features:
+++
+- uses Twisted adbapi, which provides a non-blocking database API +that returns "deferred" place-holders that are called back with +results when they become available.
+- generates its database schema from the application ontology. The +default schema is generated from the PanGalactic Core Ontology, +which applications can extend by adding other ontologies and/or +ontological classes).
+- provides a flexible O-R mapping
+
The O-R Mapping used by PGER is implemented in the Chronosynclastic Infundibulum (the pangalactic.repo.chronosynclastic module). Chronosynclastic makes extensive use of the PanGalactic Meta Object @@ -959,13 +1273,13 @@
Notes on the PGER XML-RPC Service Interface
+Notes on the PGER XML-RPC Service Interface
[Only the search interface is discussed here ... see PgerXmlrpcService API documentation for more info.]
Syntax:
-search(schemaid, refs, subtypes, args) +search(schemaid, refs, subtypes, args, spec) ... where: @@ -985,6 +1299,10 @@ - for strings, '=' means exact match, and 'like' means case-insensitive match on the value as a substring + +spec = specification of attributes to be returned (a list of names of + attributes). A non-null spec implies that the result should + come back as a data set rather than extracts of objects.
Some examples of valid 'args' lists:
@@ -1007,7 +1325,7 @@ ('validated_flag', 'boolean', 0)] Note: for boolean searches, the operator must be 'boolean' - (case-insensitive) and the value must be 1 or 0. + (case-insensitive) and the value must be 1 or 0. [('parent_oid', 'in', ['admin.1086874967.03', 'admin.1086874967.16', @@ -1020,20 +1338,20 @@
The PGEF GUI: PanGalaxian
+The PGEF GUI: PanGalaxian
This section describes the PanGalactic GUI, PanGalaxian. PanGalaxian is a wxPython application, and is designed to be the desktop "control center" for a PanGalactic Node.
-Global State
+Global State
State in PanGalaxian is persisted in the PanGalactic UberORB -- see that section for more information.
User Preferences
+User Preferences
User preferences in PanGalaxian are persisted in the PanGalactic -UberORB as a module-level dictionary, pangalactic.node.uberorb.prefs. +UberORB as a module-level dictionary (pangalactic.node.uberorb.prefs). The contents of the prefs dictionary include:
@@ -1063,8 +1381,8 @@
PanGalaxianObject
+PanGalaxianObject
PanGalaxianObject is the late-bound viewer/editor for PanGalactic Domain Objects (in the PanGalactic Ontology, subclasses of pgef:PanGalacticObject). Each time a PanGalaxianObject instance is @@ -1574,8 +1892,8 @@
Building a self-extracting executable of PanGalaxian
+Building a self-extracting executable of PanGalaxian
Build the executable on a Windows W2K machine.
You must have the following software installed in order to build an executable:
@@ -1654,8 +1972,8 @@Test Driving PanGalaxian
+Test Driving PanGalaxian
Before you start this simple walk-through, make sure you have removed any client data and the state file (in the pangalactic/node dir, execute rm data/* and rm state.json).
@@ -1734,7 +2052,7 @@[TODO: Reference PanGalactic/pangalactic/node/kb/pgef.owl as the PanGalactic Ontology. ]
-$Id: PgefManual.html,v 1.28 2006/01/09 06:42:35 waterbug Exp $
+$Id: PgefManual.html,v 1.29 2006/07/17 05:37:37 waterbug Exp $
\n' % (name) - output += 'Base Interface(s): %s
\n' % ( + output += 'Base Class(s): %s
\n' % ( str([getattr(b, '__name__', 'None') for b in bases]) ) Index: PanGalactic/pangalactic/node/io/owlport.py diff -u PanGalactic/pangalactic/node/io/owlport.py:1.15 PanGalactic/pangalactic/node/io/owlport.py:1.16 --- PanGalactic/pangalactic/node/io/owlport.py:1.15 Thu Jan 5 01:03:59 2006 +++ PanGalactic/pangalactic/node/io/owlport.py Mon Jul 17 15:27:37 2006 @@ -1,12 +1,12 @@ -# $Id: owlport.py,v 1.15 2006/01/05 06:03:59 waterbug Exp $ +# $Id: owlport.py,v 1.16 2006/07/17 19:27:37 waterbug Exp $ """ OWL import/export module. Reads and writes OWL graphs. Such graphs are sets of statements (known in RDF as "triples": node-arc-node or subject-predicate-object). -@version: $Revision: 1.15 $ +@version: $Revision: 1.16 $ """ -__version__ = "$Revision: 1.15 $"[11:-2] +__version__ = "$Revision: 1.16 $"[11:-2] # Python modules import base64 @@ -104,7 +104,8 @@ # gDay # gMonth # hexBinary - 'http://www.w3.org/2001/XMLSchema#base64Binary': (base64.decodestring, lambda i:base64.encodestring(i)[:-1]), + 'http://www.w3.org/2001/XMLSchema#base64Binary': (base64.decodestring, + lambda i:base64.encodestring(i)[:-1]), 'http://www.w3.org/2001/XMLSchema#anyURI': ('str', str), } From waterbug at step.nasa.gov Sun Jul 23 14:51:27 2006 From: waterbug at step.nasa.gov (waterbug CVS) Date: Sun Jul 23 14:51:28 2006 Subject: [pangalactic-commits] Add plugins directory. Message-ID: <200607231851.k6NIpR9N030115@ned.gsfc.nasa.gov> Modified files: PanGalactic/installpger 1.2 1.3 Log message: Add plugins directory. Index: PanGalactic/installpger diff -u PanGalactic/installpger:1.2 PanGalactic/installpger:1.3 --- PanGalactic/installpger:1.2 Thu Dec 15 04:16:23 2005 +++ PanGalactic/installpger Sun Jul 23 14:51:25 2006 @@ -1,5 +1,5 @@ #!/bin/bash -# $Id: installpger,v 1.2 2005/12/15 09:16:23 waterbug Exp $ +# $Id: installpger,v 1.3 2006/07/23 18:51:25 waterbug Exp $ # This script installs some directories and files needed by PGER @@ -35,7 +35,11 @@ echo echo "Setting up PGEFHOME directories/files in $dir ..." cd pangalactic/node -for subdir in bin kb logs ssl vault web +# create local directories +# note: don't need to create 'data' or 'registry' directories here because they +# are created by the cache (ZODB datastore) and the registry, respectively. +# TODO: probably 'pger' should create the 'vault' directory, as needed. +for subdir in bin kb logs plugins ssl vault web do mkdir $dir/${subdir} cp -r ${subdir}/* $dir/${subdir} From waterbug at step.nasa.gov Sun Jul 23 23:38:03 2006 From: waterbug at step.nasa.gov (waterbug CVS) Date: Sun Jul 23 23:38:05 2006 Subject: [pangalactic-commits] Not a good place for this -- it's just test data! Message-ID: <200607240338.k6O3c3Yo032221@ned.gsfc.nasa.gov> Modified files: PanGalactic/pangalactic/node/kb/space_mission.owl 1.1 None Log message: Not a good place for this -- it's just test data! From waterbug at step.nasa.gov Mon Jul 24 00:12:58 2006 From: waterbug at step.nasa.gov (waterbug CVS) Date: Mon Jul 24 00:12:59 2006 Subject: [pangalactic-commits] Don't need the whole registry report spewed out every time. Message-ID: <200607240412.k6O4Cwfo000379@ned.gsfc.nasa.gov> Modified files: PanGalactic/pangalactic/test/test_registry.py 1.15 1.16 Log message: Don't need the whole registry report spewed out every time. Index: PanGalactic/pangalactic/test/test_registry.py diff -u PanGalactic/pangalactic/test/test_registry.py:1.15 PanGalactic/pangalactic/test/test_registry.py:1.16 --- PanGalactic/pangalactic/test/test_registry.py:1.15 Fri Nov 11 03:12:35 2005 +++ PanGalactic/pangalactic/test/test_registry.py Mon Jul 24 00:12:56 2006 @@ -7,7 +7,6 @@ from pangalactic.meta.registry import PanGalacticRegistry r = PanGalacticRegistry() -print r.report() f = open('registry.html', 'w') print >> f, r.reportHtml() f.close() From waterbug at step.nasa.gov Mon Jul 24 00:44:50 2006 From: waterbug at step.nasa.gov (waterbug CVS) Date: Mon Jul 24 00:44:52 2006 Subject: [pangalactic-commits] Progress toward integrating "application ontologies". Message-ID: <200607240444.k6O4ioCj001038@ned.gsfc.nasa.gov> Modified files: PanGalactic/TODO 1.49 1.50 PanGalactic/installpger 1.3 1.4 PanGalactic/pangalactic/meta/registry.py 1.97 1.98 PanGalactic/pangalactic/node/io/owlport.py 1.16 1.17 Log message: Progress toward integrating "application ontologies". Index: PanGalactic/installpger diff -u PanGalactic/installpger:1.3 PanGalactic/installpger:1.4 --- PanGalactic/installpger:1.3 Sun Jul 23 14:51:25 2006 +++ PanGalactic/installpger Mon Jul 24 00:44:47 2006 @@ -1,5 +1,5 @@ #!/bin/bash -# $Id: installpger,v 1.3 2006/07/23 18:51:25 waterbug Exp $ +# $Id: installpger,v 1.4 2006/07/24 04:44:47 waterbug Exp $ # This script installs some directories and files needed by PGER @@ -42,7 +42,9 @@ for subdir in bin kb logs plugins ssl vault web do mkdir $dir/${subdir} - cp -r ${subdir}/* $dir/${subdir} + if [[ -d $subdir ]]; then + cp -r ${subdir}/* $dir/${subdir} + fi done find $dir -name 'CVS' -exec rm -r {} ';' echo "Done." Index: PanGalactic/pangalactic/meta/registry.py diff -u PanGalactic/pangalactic/meta/registry.py:1.97 PanGalactic/pangalactic/meta/registry.py:1.98 --- PanGalactic/pangalactic/meta/registry.py:1.97 Sun Jul 23 14:27:56 2006 +++ PanGalactic/pangalactic/meta/registry.py Mon Jul 24 00:44:47 2006 @@ -1,9 +1,9 @@ -# $Id: registry.py,v 1.97 2006/07/23 18:27:56 waterbug Exp $ +# $Id: registry.py,v 1.98 2006/07/24 04:44:47 waterbug Exp $ """ Pan Galactic Meta Object Registry -@version: $Revision: 1.97 $ +@version: $Revision: 1.98 $ The C{PanGalacticRegistry} maintains an in-memory cache of the PanGalactic ('pgef') core ontology (the C{Interface} instances that are the C{_schema}s of @@ -12,8 +12,9 @@ L{pangalactic.node.uberorb.URB} to deserialize domain objects in a PanGalactic application. """ -__version__ = "$Revision: 1.97 $"[11:-2] +__version__ = "$Revision: 1.98 $"[11:-2] +import glob import imp import os import re @@ -105,16 +106,30 @@ else: # if not, build 'pgef' interfaces from the OWL files in the node/kb # directory - self.kb = KB() + kbpath = os.path.join(PGEFHOME, 'kb') + self.kb = KB(kbpath) self.interfaces = {} self.properties = {} self.extracts = {} - self.importInterfaces(self.kb, 'pgef') + self.buildInterfaces(self.kb, 'pgef') # add in application-specific ontologies, if any are found in the # plugins/ontologies directory ... - # app_i, app_p, app_e = self.importInterfaces(self.kb, - # 'space_mission') + # TODO: the addition of owl files should be supported by a GUI dialog + # that allows them to be selected, does some simple validation of the + # contents, then adds the ontology to the PGEF runtime (building + # interfaces, adding tables to the repository, etc. ... yeehah! :). + app_kb_dir = os.path.join(PGEFHOME, 'plugins', 'owl') + app_owl_filepaths = glob.glob(os.path.join(app_kb_dir, '*.owl')) + if app_owl_filepaths: + # build app-specific interfaces + print ' -> [registry] aha, found an owl file!' + # TODO: figure out how to get the app ontology name (namespace) -- + # maybe interactively? e.g.: show the namespaces KB finds in the + # OWL or RDF file and let user select the one they want? Hard-code + # it for now ... + app_ontology_name = 'space_mission' + self.addInterfaces(KB(app_kb_dir), app_ontology_name) # self.read_only = list(READ_ONLY) # DELETE -- not used! for p in self.properties: @@ -334,7 +349,7 @@ self.properties = properties self.extracts = extracts - def importInterfaces(self, source, nsprefix, module=None): + def buildInterfaces(self, source, nsprefix, module=None): """ Build a dictionary of C{Interface} instances corresponding to the set of named, schema-like data structures in a specified namespace contained @@ -360,6 +375,10 @@ properties = {} extracts = {} module_name = module or 'pangalactic.meta.names' + # note that base_order is only deterministic to the extent of requiring + # that in the list, a given Interface's bases appear before the + # Interface -- obviously this allows more than one ordering to be valid. + # That's okay for our purposes. base_order = ['Thing', 'Class', 'Property'] cnames = source.getClassNames(nsprefix) # print 'cnames:', cnames @@ -376,7 +395,7 @@ # print ' base cnames:', Set( # source.getBaseNames(nsprefix, cname)) # print ' ... base order unchanged:', base_order - if not Set(cnames).difference(Set(base_order)): + if Set(cnames).issubset(Set(base_order)): break base_order.remove('Thing') base_order.remove('Class') @@ -482,6 +501,52 @@ self.properties.update(properties) self.extracts.update(extracts) + def addInterfaces(self, source, nsprefix, module=None): + """ + Add C{Interface} instances corresponding to the set of named, + schema-like data structures in the application's namespace -- the + application's data structures will be read from the 'plugins' directory + (for now, just from any OWL files found in the 'owl' subdirectory). + + @param source: an object that provides the C{ISchemaSource} interface, + and that contains a collection of schema-like data structures + @type source: doesn't matter, but it must provide the + L{pangalactic.meta.interfaces.ISchemaSource} interface. + + @param nsprefix: the name (a.k.a. "prefix") of a namespace + @type nsprefix: C{str} or C{unicode} + + @param module: a name to be used as the C{__module__} attribute for the + C{Interface} instances that will be created + @type module: C{str} + + @return: a dictionary mapping names to C{Interface} instances + @rtype: C{dict} of L{zope.interface.Interface} instances + """ + base_order = ['Thing', 'Class', 'Property'] + base_order.extend(self.interface_base_order) + cnames = source.getClassNames(nsprefix) + # print 'cnames:', cnames + # print '... finding base_order of cnames ...' + while 1: + for cname in cnames: + # print ' - cname:', cname + if (Set(source.getBaseNames(nsprefix, cname)).issubset( + Set(base_order)) + and cname not in base_order): + base_order.append(cname) + # print ' ... appended.' + # else: + # print ' base cnames:', Set( + # source.getBaseNames(nsprefix, cname)) + # print ' ... base order unchanged:', base_order + if Set(cnames).issubset(Set(base_order)): + break + base_order.remove('Thing') + base_order.remove('Class') + base_order.remove('Property') + print base_order + def registerInterface(self, interface): """ Make an C{Interface} known to the registry. Index: PanGalactic/TODO diff -u PanGalactic/TODO:1.49 PanGalactic/TODO:1.50 --- PanGalactic/TODO:1.49 Mon Jul 17 09:48:24 2006 +++ PanGalactic/TODO Mon Jul 24 00:44:47 2006 @@ -68,6 +68,10 @@ PGEF objects and store them in PGER, along with appropriate DataSet collection objects to identify the source and target data sets. [*] create a test set-up script that populates test data, etc. +[-] re-write tests as real python unit tests, and make sure that the test + environment is self-contained, returns itself to initial state, etc. +[-] more unit tests, integration tests, and stress tests +[-] twisted-style unit tests for services, using 'trial' [-] create a 'demo mode' that creates a sandbox for the user to play in [-] write up and test demo scenario(s), runnable by users [-] p21 file upload / EE map / show assembly @@ -95,10 +99,8 @@ [-] set up regular 'ANALYZE' process for Chronosynclastic [-] admin interface (user management, db ops, etc.) [-] new demo script(s) -[-] twisted-style unit tests for services, using 'trial' [*] searches, gets w/ refd objs (may be different) [-] Pixies for XSL-FO (maybe) -[-] more unit tests, integration tests, and stress tests -------------------------------------------- To Do After Release (in no particular order) @@ -196,5 +198,5 @@ [+] one-many (aggregate attrs) -------------------------------------------------------------------------- -# $Id: TODO,v 1.49 2006/07/17 13:48:24 waterbug Exp $ +# $Id: TODO,v 1.50 2006/07/24 04:44:47 waterbug Exp $ Index: PanGalactic/pangalactic/node/io/owlport.py diff -u PanGalactic/pangalactic/node/io/owlport.py:1.16 PanGalactic/pangalactic/node/io/owlport.py:1.17 --- PanGalactic/pangalactic/node/io/owlport.py:1.16 Mon Jul 17 15:27:37 2006 +++ PanGalactic/pangalactic/node/io/owlport.py Mon Jul 24 00:44:48 2006 @@ -1,12 +1,12 @@ -# $Id: owlport.py,v 1.16 2006/07/17 19:27:37 waterbug Exp $ +# $Id: owlport.py,v 1.17 2006/07/24 04:44:48 waterbug Exp $ """ OWL import/export module. Reads and writes OWL graphs. Such graphs are sets of statements (known in RDF as "triples": node-arc-node or subject-predicate-object). -@version: $Revision: 1.16 $ +@version: $Revision: 1.17 $ """ -__version__ = "$Revision: 1.16 $"[11:-2] +__version__ = "$Revision: 1.17 $"[11:-2] # Python modules import base64 @@ -162,19 +162,22 @@ Property node to the corresponding node. """ - def __init__(self): + def __init__(self, kbpath): """ Create a KB instance. + + @param kbpath: path to a directory containing RDF and/or OWL files. + @type kbpath: C{str} """ TripleStore.__init__(self) # read in RDF files from current knowledgebase (kb) - kbpath = os.path.join( - os.path.split(pangalactic.node.__file__)[0], - 'kb') self.rdfpath = os.path.join(kbpath, '*.rdf') self.owlpath = os.path.join(kbpath, '*.owl') + f = open('test.log', 'w') for filepath in glob.glob(self.rdfpath)+glob.glob(self.owlpath): + f.write('reading kb file: %s\n' % str(filepath)) self.readRdf(filepath) + f.close() def readRdf(self, filepath, name=''): """ @@ -183,11 +186,11 @@ from its Class and Property nodes. @param filepath: path to an RDF/XML file. - @type filepath: str + @type filepath: C{str} @param name: name of the graph (default is the base name of the RDF/XML file) - @type name: str + @type name: C{str} """ graph = TripleStore() if not name: From waterbug at step.nasa.gov Tue Jul 25 01:10:12 2006 From: waterbug at step.nasa.gov (waterbug CVS) Date: Tue Jul 25 01:10:14 2006 Subject: [pangalactic-commits] Got domain ontologies! Yay! Message-ID: <200607250510.k6P5ACZI018604@ned.gsfc.nasa.gov> Modified files: PanGalactic/pangalactic/meta/registry.py 1.98 1.99 Log message: Got domain ontologies! Yay! However, not getting 'bases' for domain Classes or the correct ranges for domain Properties. Eh, details! Index: PanGalactic/pangalactic/meta/registry.py diff -u PanGalactic/pangalactic/meta/registry.py:1.98 PanGalactic/pangalactic/meta/registry.py:1.99 --- PanGalactic/pangalactic/meta/registry.py:1.98 Mon Jul 24 00:44:47 2006 +++ PanGalactic/pangalactic/meta/registry.py Tue Jul 25 01:10:10 2006 @@ -1,9 +1,9 @@ -# $Id: registry.py,v 1.98 2006/07/24 04:44:47 waterbug Exp $ +# $Id: registry.py,v 1.99 2006/07/25 05:10:10 waterbug Exp $ """ Pan Galactic Meta Object Registry -@version: $Revision: 1.98 $ +@version: $Revision: 1.99 $ The C{PanGalacticRegistry} maintains an in-memory cache of the PanGalactic ('pgef') core ontology (the C{Interface} instances that are the C{_schema}s of @@ -12,7 +12,7 @@ L{pangalactic.node.uberorb.URB} to deserialize domain objects in a PanGalactic application. """ -__version__ = "$Revision: 1.98 $"[11:-2] +__version__ = "$Revision: 1.99 $"[11:-2] import glob import imp @@ -40,6 +40,7 @@ from pangalactic.meta.utils import getDefault from pangalactic.node.io.owlport import KB from pangalactic.utils.safe import safe_eval +from pangalactic.utils.pgefexceptions import RequiredDataError PGEFHOME = os.environ.get('PGEFHOME', '') @@ -97,7 +98,11 @@ # add to repository for metaclasses self.allspace = allspace self.allprefix = allprefix - # check whether there is a saved set of interfaces + # Check whether there is a cached set of interfaces: the core 'pgef' + # interfaces will only be rebuilt if the cache (i.e., the 'registry' + # subdirectory) does not exist. Domain interfaces (built from any OWL + # files found in the 'plugins/owl' subdirectory) will be rebuilt whether + # they have been cached or not. (TODO: make this user-selectable.) if os.path.exists(os.path.join(PGEFHOME, 'registry', 'Classes', @@ -124,13 +129,10 @@ if app_owl_filepaths: # build app-specific interfaces print ' -> [registry] aha, found an owl file!' - # TODO: figure out how to get the app ontology name (namespace) -- - # maybe interactively? e.g.: show the namespaces KB finds in the - # OWL or RDF file and let user select the one they want? Hard-code - # it for now ... - app_ontology_name = 'space_mission' - self.addInterfaces(KB(app_kb_dir), app_ontology_name) - + # NOTE: if OWL file(s) are found in 'plugins/owl', the domain + # interfaces will always be rebuilt. (TODO: make this + # user-selectable.) + self.addInterfaces(KB(app_kb_dir)) # self.read_only = list(READ_ONLY) # DELETE -- not used! for p in self.properties: # TODO: READ_ONLY -- the list of Properties that are computed, for @@ -332,16 +334,16 @@ del td['_schema_name'] del td['bases'] interface_attrs[TAGGED_DATA] = td - module_name = module or 'pangalactic.meta.names' # construct the Interface - interfaces[name] = InterfaceClass(name, - __module__=module_name, - bases=interface_bases, - attrs=interface_attrs - ) + interfaces[name] = InterfaceClass( + name, + __module__='pangalactic.meta.names', + bases=interface_bases, + attrs=interface_attrs + ) # try to fudge sys.modules so that PgefObject instances are # picklable - setattr(sys.modules[module_name], name, + setattr(sys.modules['pangalactic.meta.names'], name, interfaces[name]) extracts = dict(interface_extracts) extracts.update(property_extracts) @@ -349,7 +351,7 @@ self.properties = properties self.extracts = extracts - def buildInterfaces(self, source, nsprefix, module=None): + def buildInterfaces(self, source, nsprefix): """ Build a dictionary of C{Interface} instances corresponding to the set of named, schema-like data structures in a specified namespace contained @@ -363,10 +365,6 @@ @param nsprefix: the name (a.k.a. "prefix") of a namespace @type nsprefix: C{str} or C{unicode} - @param module: a name to be used as the C{__module__} attribute for the - C{Interface} instances that will be created - @type module: C{str} - @return: a dictionary mapping names to C{Interface} instances @rtype: C{dict} of L{zope.interface.Interface} instances """ @@ -374,7 +372,6 @@ interfaces = {} properties = {} extracts = {} - module_name = module or 'pangalactic.meta.names' # note that base_order is only deterministic to the extent of requiring # that in the list, a given Interface's bases appear before the # Interface -- obviously this allows more than one ordering to be valid. @@ -397,27 +394,17 @@ # print ' ... base order unchanged:', base_order if Set(cnames).issubset(Set(base_order)): break - base_order.remove('Thing') - base_order.remove('Class') - base_order.remove('Property') + # lose 'Thing', 'Class', and 'Property' + feh = lambda x: x not in ['Thing', 'Class', 'Property'] + base_order = filter(feh, base_order) # print base_order - pnames = source.getPropertyNames(nsprefix) # create registry cache directories if not os.path.exists(os.path.join(PGEFHOME, 'registry')): os.mkdir(os.path.join(PGEFHOME, 'registry'), 0755) - if not os.path.exists(os.path.join(PGEFHOME, - 'registry', - 'Namespaces')): - os.mkdir(os.path.join(PGEFHOME, 'registry', 'Namespaces'), 0755) - if not os.path.exists(os.path.join(PGEFHOME, - 'registry', - 'Classes')): - os.mkdir(os.path.join(PGEFHOME, 'registry', 'Classes'), 0755) - if not os.path.exists(os.path.join(PGEFHOME, - 'registry', - 'Properties')): - os.mkdir(os.path.join(PGEFHOME, 'registry', 'Properties'), 0755) + for subdir in ['Namespaces', 'Classes', 'Properties']: + os.mkdir(os.path.join(PGEFHOME, 'registry', subdir), 0755) + pnames = source.getPropertyNames(nsprefix) for pname in pnames: kw = source.getPropertyAttrs(nsprefix, pname) if kw['domain'] == 'Thing': @@ -429,13 +416,7 @@ extracts[pname] = extr for cname in base_order: # print '- constructing interface for', cname - base_names = source.getBaseNames(nsprefix, cname) - if 'Thing' in base_names: - base_names.remove('Thing') - if 'Class' in base_names: - base_names.remove('Class') - if 'Property' in base_names: - base_names.remove('Property') + base_names = filter(feh, source.getBaseNames(nsprefix, cname)) interface_bases = [interfaces[bn] for bn in base_names] # print ' bases ...', interface_bases interface_props = filter(lambda p: p.domain == cname, @@ -456,20 +437,17 @@ extr['bases'] = base_names extracts[cname] = extr # construct the Interface - interfaces[cname] = InterfaceClass(cname, - __module__=module_name, - bases=interface_bases, - attrs=interface_attrs - ) + interfaces[cname] = InterfaceClass( + cname, + __module__='pangalactic.meta.names', + bases=interface_bases, + attrs=interface_attrs + ) # try to fudge sys.modules so that PgefObject instances are # picklable setattr(sys.modules['pangalactic.meta.names'], cname, interfaces[cname]) - # save Interface and Property extracts; note that if there are any - # reused 'pgef' Interface or Property names in an application ontology, - # the pgef versions will be overridden by them. - # FIXME: There need to be some checks to make sure essential 'pgef' - # Interfaces and Properties are not overridden. + # save 'pgef' Interface and Property extracts for i in interfaces: f = open(os.path.join(PGEFHOME, 'registry', 'Classes', i), 'w') pprint(extracts[i], f) @@ -501,7 +479,7 @@ self.properties.update(properties) self.extracts.update(extracts) - def addInterfaces(self, source, nsprefix, module=None): + def addInterfaces(self, source, domain_prefix=None, module=None): """ Add C{Interface} instances corresponding to the set of named, schema-like data structures in the application's namespace -- the @@ -513,8 +491,9 @@ @type source: doesn't matter, but it must provide the L{pangalactic.meta.interfaces.ISchemaSource} interface. - @param nsprefix: the name (a.k.a. "prefix") of a namespace - @type nsprefix: C{str} or C{unicode} + @param domain_prefix: the short name (a.k.a. "prefix") of the domain + ontology for which interfaces are being added + @type domain_prefix: C{str} or C{unicode} @param module: a name to be used as the C{__module__} attribute for the C{Interface} instances that will be created @@ -523,29 +502,133 @@ @return: a dictionary mapping names to C{Interface} instances @rtype: C{dict} of L{zope.interface.Interface} instances """ + # check whether the pgef ontology has been cached; if not, raise an + # error + if not os.path.exists(os.path.join(PGEFHOME, + 'registry', + 'Classes', + 'PanGalacticObject')): + raise RequiredDataError, 'pgef ontology must be built first.' + # TODO: figure out how to get the app ontology name (namespace) -- + # maybe interactively? e.g.: show the namespaces KB finds in the + # OWL or RDF file and let user select the one they want? Hard-code + # it to use the 'space_mission' test case for now ... + domain_prefix = domain_prefix or 'space_mission' base_order = ['Thing', 'Class', 'Property'] base_order.extend(self.interface_base_order) - cnames = source.getClassNames(nsprefix) + cnames = source.getClassNames(domain_prefix) # print 'cnames:', cnames # print '... finding base_order of cnames ...' while 1: for cname in cnames: # print ' - cname:', cname - if (Set(source.getBaseNames(nsprefix, cname)).issubset( + if (Set(source.getBaseNames(domain_prefix, cname)).issubset( Set(base_order)) and cname not in base_order): base_order.append(cname) # print ' ... appended.' # else: # print ' base cnames:', Set( - # source.getBaseNames(nsprefix, cname)) + # source.getBaseNames(domain_prefix, cname)) # print ' ... base order unchanged:', base_order if Set(cnames).issubset(Set(base_order)): break - base_order.remove('Thing') - base_order.remove('Class') - base_order.remove('Property') + # lose 'Thing', 'Class', and 'Property' + feh = lambda x: x not in ['Thing', 'Class', 'Property'] + base_order = filter(feh, base_order) print base_order + namespaces = {} + interfaces = {} + properties = {} + extracts = {} + pnames = source.getPropertyNames(domain_prefix) + for pname in pnames: + kw = source.getPropertyAttrs(domain_prefix, pname) + if kw['domain'] == 'Thing': + kw['domain'] = 'Identifiable' + p = PgefProperty(**kw) + properties[pname] = p + extr = p.extract() + extr['_schema_name'] = 'PanGalacticProperty' + extracts[pname] = extr + for cname in base_order[len(self.interface_base_order):]: + print '- constructing interface for', cname + base_names = filter(feh, source.getBaseNames(domain_prefix, cname)) + interface_bases = [interfaces[bn] for bn in base_names] + # print ' bases ...', interface_bases + interface_props = filter(lambda p: p.domain == cname, + properties.values()) + # print ' properties:' + # for p in interface_props: + # print ' - %s (%s), range: %s' % (p.id, type(p.id), + # p.range) + # for a in p._schema: + # print ' + %s ... %s (%s)' % (a, getattr(p, a), + # type(getattr(p, a))) + interface_attrs = dict([(p.id, p) for p in interface_props]) + interface_attrs[TAGGED_DATA] = source.getSchemaAttrs(domain_prefix, + cname) + # create an extract of the Interface + extr = dict(interface_attrs[TAGGED_DATA]) + extr['_schema_name'] = 'PanGalacticInterface' + extr['bases'] = base_names + extracts[cname] = extr + # construct the Interface + interfaces[cname] = InterfaceClass( + cname, + __module__='pangalactic.meta.names', + bases=interface_bases, + attrs=interface_attrs + ) + # try to fudge sys.modules so that PgefObject instances are + # picklable + setattr(sys.modules['pangalactic.meta.names'], cname, + interfaces[cname]) + # save Interface and Property extracts; note that if there are any + # reused 'pgef' Interface or Property names in an application ontology, + # the pgef versions will be overridden by them. + # FIXME: There need to be some checks to make sure essential 'pgef' + # Interfaces and Properties are not overridden. + + # *** BEWARE! *** + # everything from here to the end is copied/pasted from buildInterfaces! + # CHECK IT CAREFULLY!! + + # save Interface and Property extracts (even though they are not used + # for anything at the moment, since the domain interfaces are rebuilt + # every time the registry starts up ... it's nice to see the serialized + # extracts there, anyway :). + for i in interfaces: + f = open(os.path.join(PGEFHOME, 'registry', 'Classes', i), 'w') + pprint(extracts[i], f) + f.close() + for p in properties: + f = open(os.path.join(PGEFHOME, 'registry', 'Properties', p), 'w') + pprint(extracts[p], f) + f.close() + # save namespaces as extracts of PanGalacticNamespace objects + for n, ns in allspace.items(): + complete = False + # ignore local namespace + if n: + if n == domain_prefix: + complete = True + pgns = PgefObject( + _schema=self.interfaces['PanGalacticNamespace'], + id=str(ns.id), uri=str(ns.uri), + names=[str(nom) for nom in ns.names], + complete=complete) + nsextr = pgns.extract() + f = open(os.path.join(PGEFHOME, + 'registry', + 'Namespaces', + str(n)), + 'w') + pprint(nsextr, f) + f.close() + self.interfaces.update(interfaces) + self.properties.update(properties) + self.extracts.update(extracts) def registerInterface(self, interface): """ From waterbug at step.nasa.gov Wed Jul 26 00:23:58 2006 From: waterbug at step.nasa.gov (waterbug CVS) Date: Wed Jul 26 00:24:00 2006 Subject: [pangalactic-commits] Valid OWL test data file. Message-ID: <200607260423.k6Q4Nw72001279@ned.gsfc.nasa.gov> Modified files: PanGalactic/sandbox/onto/space_mission.owl None 1.1 Log message: Valid OWL test data file. From waterbug at step.nasa.gov Wed Jul 26 02:34:13 2006 From: waterbug at step.nasa.gov (waterbug CVS) Date: Wed Jul 26 02:34:14 2006 Subject: [pangalactic-commits] PanGalaxian can create Spacecraft and Instrument ... Message-ID: <200607260634.k6Q6YDiN001594@ned.gsfc.nasa.gov> Modified files: PanGalactic/pangalactic/meta/registry.py 1.99 1.100 PanGalactic/pangalactic/meta/utils.py 1.16 1.17 Log message: PanGalaxian can create Spacecraft and Instrument ... however, PanGalaxianObject doesn't display them correctly. This will require some work on handling of Properties (mass is a 'float' -- which is foreign to most of PanGalactic's property-handling code right now). Need to make property support more flexible / extensible. Index: PanGalactic/pangalactic/meta/registry.py diff -u PanGalactic/pangalactic/meta/registry.py:1.99 PanGalactic/pangalactic/meta/registry.py:1.100 --- PanGalactic/pangalactic/meta/registry.py:1.99 Tue Jul 25 01:10:10 2006 +++ PanGalactic/pangalactic/meta/registry.py Wed Jul 26 02:34:11 2006 @@ -1,9 +1,9 @@ -# $Id: registry.py,v 1.99 2006/07/25 05:10:10 waterbug Exp $ +# $Id: registry.py,v 1.100 2006/07/26 06:34:11 waterbug Exp $ """ Pan Galactic Meta Object Registry -@version: $Revision: 1.99 $ +@version: $Revision: 1.100 $ The C{PanGalacticRegistry} maintains an in-memory cache of the PanGalactic ('pgef') core ontology (the C{Interface} instances that are the C{_schema}s of @@ -12,7 +12,7 @@ L{pangalactic.node.uberorb.URB} to deserialize domain objects in a PanGalactic application. """ -__version__ = "$Revision: 1.99 $"[11:-2] +__version__ = "$Revision: 1.100 $"[11:-2] import glob import imp @@ -128,7 +128,7 @@ app_owl_filepaths = glob.glob(os.path.join(app_kb_dir, '*.owl')) if app_owl_filepaths: # build app-specific interfaces - print ' -> [registry] aha, found an owl file!' + # print ' -> [registry] aha, found an owl file!' # NOTE: if OWL file(s) are found in 'plugins/owl', the domain # interfaces will always be rebuilt. (TODO: make this # user-selectable.) @@ -518,7 +518,7 @@ base_order.extend(self.interface_base_order) cnames = source.getClassNames(domain_prefix) # print 'cnames:', cnames - # print '... finding base_order of cnames ...' + # print '... finding base_order of <%s> cnames ...' % domain_prefix while 1: for cname in cnames: # print ' - cname:', cname @@ -536,7 +536,7 @@ # lose 'Thing', 'Class', and 'Property' feh = lambda x: x not in ['Thing', 'Class', 'Property'] base_order = filter(feh, base_order) - print base_order + # print base_order namespaces = {} interfaces = {} properties = {} @@ -552,9 +552,10 @@ extr['_schema_name'] = 'PanGalacticProperty' extracts[pname] = extr for cname in base_order[len(self.interface_base_order):]: - print '- constructing interface for', cname + # print '- constructing interface for', cname base_names = filter(feh, source.getBaseNames(domain_prefix, cname)) - interface_bases = [interfaces[bn] for bn in base_names] + print 'base_names:', base_names + interface_bases = [self.interfaces[bn] for bn in base_names] # print ' bases ...', interface_bases interface_props = filter(lambda p: p.domain == cname, properties.values()) @@ -563,8 +564,8 @@ # print ' - %s (%s), range: %s' % (p.id, type(p.id), # p.range) # for a in p._schema: - # print ' + %s ... %s (%s)' % (a, getattr(p, a), - # type(getattr(p, a))) + # print ' + %s ... %s (%s)' % (a, getattr(p, a), + # type(getattr(p, a))) interface_attrs = dict([(p.id, p) for p in interface_props]) interface_attrs[TAGGED_DATA] = source.getSchemaAttrs(domain_prefix, cname) Index: PanGalactic/pangalactic/meta/utils.py diff -u PanGalactic/pangalactic/meta/utils.py:1.16 PanGalactic/pangalactic/meta/utils.py:1.17 --- PanGalactic/pangalactic/meta/utils.py:1.16 Mon Dec 5 16:39:49 2005 +++ PanGalactic/pangalactic/meta/utils.py Wed Jul 26 02:34:11 2006 @@ -2,7 +2,7 @@ PGEF meta utilities """ -# $Id: utils.py,v 1.16 2005/12/05 21:39:49 waterbug Exp $ +# $Id: utils.py,v 1.17 2006/07/26 06:34:11 waterbug Exp $ def getDefault(prop): @@ -13,6 +13,7 @@ values must be stored 'encoded' in one particular datatype (strings are used), so they will have to be cast to the correct datatype. """ + # TODO: man, this *really* needs to be completely redesigned!! if type(prop) is dict: if prop.get('functional', True): if prop['range'] == 'str': @@ -22,6 +23,11 @@ retval = int(prop['default']) else: retval = 0 + elif prop['range'] == 'float': + if prop.get('default'): + retval = float(prop['default']) + else: + retval = 0.0 elif prop['range'] == 'bool': retval = bool(prop.get('default', '')) elif prop['range'] == 'datetime': @@ -35,7 +41,7 @@ e = 'Unknown range: %s' % prop['range'] raise ValueError, e else: - if (prop['range'] not in ['str', 'int', 'bool', 'datetime'] + if (prop['range'] not in ['str', 'int', 'float', 'bool', 'datetime'] and prop.get('property_type', 'datatype') != 'object'): msg = 'Unknown range: %s' % prop['range'] raise ValueError, msg @@ -51,6 +57,11 @@ retval = int(prop.__dict__['default']) else: retval = 0 + elif prop.range == 'float': + if prop.__dict__.get('default'): + retval = float(prop.__dict__['default']) + else: + retval = 0.0 elif prop.range == 'bool': if prop.__dict__.get('default'): if prop.__dict__['default'] in ['False', 'false', '0']: @@ -68,7 +79,7 @@ else: raise ValueError, 'Unknown Property range' else: - if (prop.range not in ['str', 'int', 'bool', 'datetime'] + if (prop.range not in ['str', 'int', 'float', 'bool', 'datetime'] and prop.__dict__.get('property_type', 'datatype') != 'object'): raise ValueError, 'Unknown Property range' else: From waterbug at step.nasa.gov Thu Jul 27 09:58:34 2006 From: waterbug at step.nasa.gov (waterbug CVS) Date: Thu Jul 27 09:58:36 2006 Subject: [pangalactic-commits] Some mods to pgxnobject for testing purposes. Message-ID: <200607271358.k6RDwYE0018825@ned.gsfc.nasa.gov> Modified files: PanGalactic/pangalactic/node/gui/widgets/pgxnobject.py 1.87 1.88 Log message: Some mods to pgxnobject for testing purposes. Index: PanGalactic/pangalactic/node/gui/widgets/pgxnobject.py diff -u PanGalactic/pangalactic/node/gui/widgets/pgxnobject.py:1.87 PanGalactic/pangalactic/node/gui/widgets/pgxnobject.py:1.88 --- PanGalactic/pangalactic/node/gui/widgets/pgxnobject.py:1.87 Mon Jan 30 02:47:23 2006 +++ PanGalactic/pangalactic/node/gui/widgets/pgxnobject.py Thu Jul 27 09:58:32 2006 @@ -1,10 +1,10 @@ -# $Id: pgxnobject.py,v 1.87 2006/01/30 07:47:23 waterbug Exp $ +# $Id: pgxnobject.py,v 1.88 2006/07/27 13:58:32 waterbug Exp $ """ PanGalaxianObject (a C{PgefObject} viewer/editor) -@version: $Revision: 1.87 $ +@version: $Revision: 1.88 $ """ -__version__ = "$Revision: 1.87 $"[11:-2] +__version__ = "$Revision: 1.88 $"[11:-2] from pprint import pprint @@ -284,8 +284,8 @@ _icon.CopyFromBitmap(toolkitimages.getPanGalacticon16Bitmap()) self.SetIcon(_icon) self.groups = display_maps[self.obj._schema.__name__]['groups'] - # print ' - groups are:' - # pprint(self.groups) + print ' - groups are:' + pprint(self.groups) self.notebook = PgxnPropertybook(self) self.initPropertybook() vbox = wx.BoxSizer(wx.VERTICAL) @@ -689,7 +689,7 @@ if __name__ == '__main__': - p = PgefObject(_schema=URB.interfaces['PanGalacticObject']) + p = PgefObject(_schema=URB.interfaces['Spacecraft']) # id='Test-1') app = wx.App() frame = PanGalaxianObject(parent=None, obj=p) From waterbug at step.nasa.gov Thu Jul 27 15:43:26 2006 From: waterbug at step.nasa.gov (waterbug CVS) Date: Thu Jul 27 15:43:27 2006 Subject: [pangalactic-commits] Add Product, Process, and Activity to the pgef ontology. Message-ID: <200607271943.k6RJhQxn026087@ned.gsfc.nasa.gov> Modified files: PanGalactic/pangalactic/node/kb/pgef.owl 1.25 1.26 Log message: Add Product, Process, and Activity to the pgef ontology. Index: PanGalactic/pangalactic/node/kb/pgef.owl diff -u PanGalactic/pangalactic/node/kb/pgef.owl:1.25 PanGalactic/pangalactic/node/kb/pgef.owl:1.26 --- PanGalactic/pangalactic/node/kb/pgef.owl:1.25 Thu Jun 15 11:55:41 2006 +++ PanGalactic/pangalactic/node/kb/pgef.owl Thu Jul 27 15:43:24 2006 @@ -4,9 +4,8 @@ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#" xmlns:owl="http://www.w3.org/2002/07/owl#" - xmlns="http://pangalactic.us/pgef/" xml:base="http://pangalactic.us/pgef/"> -