[z3-checkins] r9176 - in z3/zemantic/trunk: . data doc ftests lib

michelp at codespeak.net michelp at codespeak.net
Sun Feb 13 08:30:08 MET 2005


Author: michelp
Date: Sun Feb 13 08:30:08 2005
New Revision: 9176

Added:
   z3/zemantic/trunk/doc/WALKTHROUGH.txt
   z3/zemantic/trunk/doc/ZONTOLOGY.txt
   z3/zemantic/trunk/zont_view.pt
Removed:
   z3/zemantic/trunk/ftests/
Modified:
   z3/zemantic/trunk/browser.py
   z3/zemantic/trunk/configure.zcml
   z3/zemantic/trunk/data/ontologies.py
   z3/zemantic/trunk/doc/README.txt
   z3/zemantic/trunk/interfaces.py
   z3/zemantic/trunk/lib/IOZODBBackend.py
   z3/zemantic/trunk/ont_view.pt
   z3/zemantic/trunk/utils.py
   z3/zemantic/trunk/viz_view.pt
   z3/zemantic/trunk/zemantic.py
   z3/zemantic/trunk/zontology.py
Log:
0.5 rc

Modified: z3/zemantic/trunk/browser.py
==============================================================================
--- z3/zemantic/trunk/browser.py	(original)
+++ z3/zemantic/trunk/browser.py	Sun Feb 13 08:30:08 2005
@@ -36,6 +36,7 @@
 
 from zope.i18nmessageid import MessageIDFactory
 from zope.app import zapi
+from zope.security.proxy import removeSecurityProxy
 
 from rdflib.URIRef import URIRef
 from rdflib.BNode import BNode
@@ -44,12 +45,12 @@
 from utils import ZemanticToDotAdapter
 from query import Query
 import popen2
-import urllib, os
+import urllib, os, time
 from tempfile import NamedTemporaryFile
 from StringIO import StringIO
 
 from resources import FileResource, DirectoryResource
-from zontology import Ontology
+from zontology import Ontology, split_URI
 from result import ResultSet
 
 _ = MessageIDFactory('zemantic')
@@ -133,28 +134,120 @@
 
 
     def loadstuff(self):
-        dir = DirectoryResource('data')
-        for name in dir.list():
-            if name.endswith('.rdf'):
+        print 'getting directory'
+        directory = urllib.urlopen('http://www.schemaweb.info/DirectoryMeta.aspx')
+        print 'got directory'
+        z = Ontology()
+        z.parse(directory)
+        self.context['schemaweb'] = z
+        #import pdb; pdb.set_trace()
+        n = 0
+        for result in z.query(Query(Any, u'<http://www.schemaweb.info/schemas/meta/rdf/rdf-meta>', Any)):
+            if result is not None:
+                time.sleep(1)
                 try:
-                    f = FileResource(os.path.join(dir.path(), name)).open()
-                    z = Ontology()
-                    z.parse(f)
-                    self.context[name[:-4]] = z
-                    get_transaction().commit(1)
+                    print 'fetching %s' % result.object
+                    f = urllib.urlopen(result.object)
+                    y = Ontology()
+                    y.parse(f)
+                    for result2 in y.query(Query(Any, u'<http://www.schemaweb.info/schemas/meta/rdf/namespace>', Any)):
+
+                        u2 = 'http://www.schemaweb.info/webservices/rest/GetRDF.aspx?namespace=%s' % urllib.quote_plus(result2.object)
+                        print 'fetching %s' % u2
+                        f = urllib.urlopen(u2)
+                        x = Ontology()
+                        print 'parsing'
+                        x.parse(f)
+                        for result3 in y.query(Query(result2.subject, u'<http://www.schemaweb.info/schemas/meta/rdf/name>', Any)):
+                            if result3 is not None:
+                                print "adding %s triples from %s" % (len(x), result3.object)
+                                self.context[removeSecurityProxy(result3.object.n3()[1:-1])] = x
+                        get_transaction().commit()
                 except:
-                    print "could not load %s" % name
+                    print "could not load %s" % result.subject
 
         self.request.response.redirect('contents.html')
 
 
+    def getClassNames(self):
+        for name, child in self.context.items():
+            for klass in self.child.classes.keys():
+                yield klass
+
+    def getPropertyNames(self):
+        for name, child in self.context.items():
+            for prop in self.child.properties.keys():
+                yield prop
+
+    def getClassLen(self):
+        return 0 # too expensive
+        s = 0
+        for name, child in self.context.items():
+            s += len(child.classes)
+        return s
+
+    def getPropertyLen(self):
+        return 0 # too expensive
+        s = 0
+        for name, child in self.context.items():
+            s += len(child.properties)
+        return s
+
+    def getUniqueSubjectLen(self):
+        s = 0
+        for name, child in self.context.items():
+            s += len(list(child.uniqueSubjects()))
+        return s
+
+
+    def getUniquePredicateLen(self):
+        s = 0
+        for name, child in self.context.items():
+            s += len(list(child.uniquePredicates()))
+        return s
+
+
+    def getUniqueObjectLen(self):
+        s = 0
+        for name, child in self.context.items():
+            s += len(list(child.uniqueObjects()))
+        return s
+
+
+    def getTotalTriples(self):
+        s = 0
+        for name, child in self.context.items():
+            s += len(child)
+        return s
+
+    def getTotalSchemas(self):
+        return len(self.context)
+
 class OntologyView:
 
     def getClassNames(self):
-        return self.context.classes().keys()
+        return self.context.classes.keys()
 
     def getPropertyNames(self):
-        return self.context.properties().keys()
+        return self.context.properties.keys()
+
+    def getClassLen(self):
+        return len(self.getClassNames())
+
+    def getPropertyLen(self):
+        return len(self.getPropertyNames())
+
+    def getUniqueSubjectLen(self):
+        return len(list(self.context.uniqueSubjects()))
+
+    def getUniquePredicateLen(self):
+        return len(list(self.context.uniquePredicates()))
+
+    def getUniqueObjectLen(self):
+        return len(list(self.context.uniqueObjects()))
+
+    def getTotalTriples(self):
+        return len(self.context)
 
 # Get the output from a shell command into a string.
 # The exit status is ignored; a trailing newline is stripped.

Modified: z3/zemantic/trunk/configure.zcml
==============================================================================
--- z3/zemantic/trunk/configure.zcml	(original)
+++ z3/zemantic/trunk/configure.zcml	Sun Feb 13 08:30:08 2005
@@ -188,7 +188,20 @@
     permission="zope.ManageContent"
     />
 
+
   <browser:page
+    for=".interfaces.IZontology"
+    name="ontology.html"
+    class=".browser.ZontologyView"
+    template="zont_view.pt"
+    menu="zmi_views"
+    title="Zontology"
+    permission="zope.ManageContent"
+    />
+
+<!--
+
+  < browser:page
     for=".interfaces.IZemantic"
     name="viz.html"
     class=".browser.ZemanticView"
@@ -198,6 +211,8 @@
     permission="zope.ManageContent"
     />
 
+-->
+
   <browser:resourceDirectory
     name="lib"
     permission="zope.ManageContent"
@@ -212,5 +227,11 @@
       permission="zope.ManageContent"
 />
 
+<adapter
+    factory=".zemantic.ZemanticSized"
+    provides="zope.app.size.interfaces.ISized"
+    for=".interfaces.IZemantic"
+    />
+
 </configure>
 

Modified: z3/zemantic/trunk/data/ontologies.py
==============================================================================
--- z3/zemantic/trunk/data/ontologies.py	(original)
+++ z3/zemantic/trunk/data/ontologies.py	Sun Feb 13 08:30:08 2005
@@ -13,19 +13,6 @@
     'cerif' : ('CERIF (Common European Research Information Format)', 'http://www.eurocris.org/cerif/domainontology/cerif.daml#'),
     'charette' : ('Charette Relationship Set', 'http://www.charette.com/crs/0.1#'),
     'conference' : ('Conference Ontology', 'http://www.mindswap.org/~golbeck/web/www04photo.owl#'),
-    'conontoaction' : ('ConOnto Action', 'http://www.site.uottawa.ca/~mkhedr/Ontologies/Action#'),
-    'conontoactivity' : ('ConOnto Activity', 'http://www.site.uottawa.ca/~mkhedr/Ontologies/Activity#'),
-    'conontoclnp' : ('ConOnto CLNP', 'http://www.site.uottawa.ca/~mkhedr/Ontologies/CLNP#'),
-    'conontoconfoaf' : ('ConOnto ConFOAF', 'http://www.site.uottawa.ca/~mkhedr/Ontologies/Confoaf#'),
-    'conontodevice' : ('ConOnto Device', 'http://www.site.uottawa.ca/~mkhedr/Ontologies/Device#'),
-    'conontofuzzy' : ('ConOnto Fuzzy', 'http://www.site.uottawa.ca/~mkhedr/Ontologies/Fuzzy#'),
-    'conontohardwareprofile' : ('ConOnto Hardware Profile', 'http://www.site.uottawa.ca/~mkhedr/Ontologies/HardwareProfile#'),
-    'conontolocation' : ('ConOnto Location', 'http://www.site.uottawa.ca/~mkhedr/Ontologies/Location#'),
-    'conontonetworkprofile' : ('ConOnto Network Profile', 'http://www.site.uottawa.ca/~mkhedr/Ontologies/NetworkProfile#'),
-    'cononto' : ('ConOnto Process', 'http://www.site.uottawa.ca/~mkhedr/Ontologies/Process#'),
-    'cononto' : ('ConOnto Rule', 'http://www.site.uottawa.ca/~mkhedr/Ontologies/Rule#'),
-    'cononto' : ('ConOnto Software Profile', 'http://www.site.uottawa.ca/~mkhedr/Ontologies/SoftwareProfile'),
-    'cononto' : ('ConOnto Time', 'http://www.site.uottawa.ca/~mkhedr/Ontologies/Time#'),
     'cc' : ('Creative Commons', 'http://web.resource.org/cc/'),
     'damloil' : ('DAML+OIL', 'http://www.daml.org/2001/03/daml+oil#'),
     'dpdesc' : ('Digital Picture Description', 'http://kanzaki.com/ns/dpd#'),
@@ -82,16 +69,6 @@
     'owlsprof' : ('OWL-S Profile', 'http://www.daml.org/services/owl-s/1.1/Profile.owl#'),
     'owlsserv' : ('OWL-S Service', 'http://www.daml.org/services/owl-s/1.1/Service.owl#'),
     'papager' : ('Paper Ontology', 'http://lby.net9.org/ontology'),
-    'pagent' : ('PERVASIVE-SO Agent', 'http://pervasive.semanticweb.org/ont/2004/01/agent#'),
-    'pdocument' : ('PERVASIVE-SO Document', 'http://pervasive.semanticweb.org/ont/2004/01/document#'),
-    'plightcontrol' : ('PERVASIVE-SO Light Control', 'http://pervasive.semanticweb.org/ont/2004/01/lightcontrol#'),
-    'pmeeting' : ('PERVASIVE-SO Meeting', 'http://pervasive.semanticweb.org/ont/2004/01/meeting#'),
-    'pschedule' : ('PERVASIVE-SO Meeting Schedule', 'http://pervasive.semanticweb.org/ont/2004/01/schedule#'),
-    'pperson' : ('PERVASIVE-SO Person Ontology', 'http://pervasive.semanticweb.org/ont/2004/01/person#'),
-    'ppreference' : ('PERVASIVE-SO Preference', 'http://pervasive.semanticweb.org/ont/2004/01/preference#'),
-    'pregion' : ('PERVASIVE-SO Region Connection Calculus', 'http://pervasive.semanticweb.org/ont/2004/01/rcc#'),
-    'pspace' : ('PERVASIVE-SO Space', 'http://pervasive.semanticweb.org/ont/2004/01/space#'),
-    'ptime' : ('PERVASIVE-SO Time', 'http://pervasive.semanticweb.org/ont/2004/01/time#'),
     'pets' : ('Pet Profile Ontology', 'http://purl.org/stuff/pets/'),
     'phototech' : ('Photo RDF (Technical)', 'http://www.w3.org/2000/PhotoRDF/technical-1-0#'),
     'photo' : ('Photography Vocabulary', 'http://purl.org/net/vocab/2003/11/photo#'),

Modified: z3/zemantic/trunk/doc/README.txt
==============================================================================
--- z3/zemantic/trunk/doc/README.txt	(original)
+++ z3/zemantic/trunk/doc/README.txt	Sun Feb 13 08:30:08 2005
@@ -18,7 +18,8 @@
 Once data is cataloged into Zemantic it can be queried using either
 the Python query interface or a TALES-based RDF query expression
 language.  Results of a query can be either a generator of result
-records or RDF in xml or NT format.
+records or RDF in xml or NT format.  Future query languages can be
+easily adapted to Zemantic's IQuery interface.
 
 Zemantic has two main components that are both configured as a local
 Zope 3 site utility.  The Zemantic utility is the actual catalog of

Added: z3/zemantic/trunk/doc/WALKTHROUGH.txt
==============================================================================
--- (empty file)
+++ z3/zemantic/trunk/doc/WALKTHROUGH.txt	Sun Feb 13 08:30:08 2005
@@ -0,0 +1,34 @@
+
+Quick walk-through to get you started.
+
+Put etc/zemantic-configure.zcml and
+examples/library/etc/library-configure.zcml into your Zope X3.0
+etc/site-packages/ folder.  Restart Zope 3.
+
+Go to your Zope 3 site management folder and add a 'Zemantic' and a
+'Zontology' utility.  They don't need a name or any other parameters.
+After adding the Zontology utility, click on the "Load sample
+ontologes" button.  This will import some common RDF ontologies like
+dublin core, which is used in this example.
+
+After adding the Zemantic utility leave your browser on the empty
+"Zemantic" tab and in another tab or window go back to the root folder
+and add some 'Book' objects.  These objects have a dublin core
+interface.  Add a few.  Go back to the Zemantic tab on the other
+screen and reload the page.  Your books' meta-data has been cataloged.
+Remove a book, the data goes away.  Change a book, the data is
+updated.
+
+Create a page template in the root folder next to all your book.  Add
+this code:
+
+  <html>
+  <body>
+   <p>The library contains the following titles:</p>
+    <ul><li tal:repeat="book zemantic: Any, path('zon/dc/title'), Any"
+            tal:content="book/object"/>
+    </ul>
+  </body>
+  </html>
+
+This will render a list of book titles that you added.

Added: z3/zemantic/trunk/doc/ZONTOLOGY.txt
==============================================================================
--- (empty file)
+++ z3/zemantic/trunk/doc/ZONTOLOGY.txt	Sun Feb 13 08:30:08 2005
@@ -0,0 +1,30 @@
+
+Zontology is a folderish object that holds a bunch of zemantic
+catalogs inside it.  Eac catalog generally maps to one ""ontology" be
+that what it may.  A good way to get started with zontologis is to
+create a new Zontology in your site managment folder named
+"Zontology", then visit the following URL:
+
+
+http://localhost:8080/++etc++site/default/Zontology/@@loadStuff
+
+You may have to adjust the URL to point to your Zontology.  This will
+kick in the load script that pulls in the entire schema database at
+www.schemaweb.info.  It's interesting to note that the loadStuff
+script pulls in and parses RDF from schemaweb's REST HTTP query
+interface.  See browser.py for that code.
+
+This script loads 202 ontologies totalling 104323 triples into
+Zontology.  Your database will grow by about 42MB.  This breaks down
+to about 409 bytes per triple, which is quite efficient.
+
+Note that even with the use of sub-transactions this load will require
+at least 450MB of process size and several megabytes of internet
+bandwidth to load all of the RDF.  Do these heavy loads sparingly so
+as not to overburden schemaweb.info.  I have intentionally added a one
+second sleep to the load to prevent this.
+
+The first load requires lost of process space, but after restarting
+Zope it will not require more than 200MB at most, this mass-cataloging
+memory growth problem is symptomatic of ZODB and does not reflect the
+long-term memory needs of Zemantic.

Modified: z3/zemantic/trunk/interfaces.py
==============================================================================
--- z3/zemantic/trunk/interfaces.py	(original)
+++ z3/zemantic/trunk/interfaces.py	Sun Feb 13 08:30:08 2005
@@ -194,6 +194,10 @@
 
     def rdfnt():
         """ Returns rdf nt representation of store. """
+
+    def __len__():
+        """ Return the total number of triples in the store.  Might be
+        expensive."""
     
 
 

Modified: z3/zemantic/trunk/lib/IOZODBBackend.py
==============================================================================
--- z3/zemantic/trunk/lib/IOZODBBackend.py	(original)
+++ z3/zemantic/trunk/lib/IOZODBBackend.py	Sun Feb 13 08:30:08 2005
@@ -54,6 +54,8 @@
         # reverse index of forward
         self.reverse = OIBTree()
 
+        self.count = 0
+
     def intToIdentifier(self, (si, pi, oi)):
         """ Resolve an integer triple into identifers. """
         return (self.forward[si], self.forward[pi], self.forward[oi])
@@ -145,6 +147,8 @@
             p = sp[si] = IOBTree()
         p[pi] = 1
 
+        self.count = self.count + 1
+
     def remove(self, (subject, predicate, object)):
         for subject, predicate, object in self.triples((subject, predicate, object)):
             si, pi, oi = self.identifierToInt((subject, predicate, object))
@@ -154,6 +158,8 @@
             del self.pos[pi][oi][si]
             del self.osp[oi][si][pi]
 
+            self.count = self.count - 1
+
             # grr!! hafta ref-count these before you can collect them dumbass!
 #             del f[si]
 #             del f[pi]
@@ -232,6 +238,7 @@
 
     def __len__(self):
         #@@ optimize
+        return self.count
         i = 0
         for triple in self.triples((None, None, None)):
             i += 1

Modified: z3/zemantic/trunk/ont_view.pt
==============================================================================
--- z3/zemantic/trunk/ont_view.pt	(original)
+++ z3/zemantic/trunk/ont_view.pt	Sun Feb 13 08:30:08 2005
@@ -14,16 +14,14 @@
 
    <div metal:fill-slot="body">
 
-      <p>Classes</p>
-	<ul>
-	<li tal:repeat="i view/getClassNames"><b tal:content="i"/>
-	(<span tal:replace="python: path('context/'+i).n3()"/>)</li>
-	</ul>
-      <p>Properties</p>
-	<ul>
-	<li tal:repeat="i view/getPropertyNames"><b tal:content="i"/>
-	(<span tal:replace="python: path('context/'+i).n3()"/>)</li>
-	</ul>
+      <p>Total Triples <span tal:content="view/getTotalTriples"/></p>
+      <p>Unique Subjects <span tal:content="view/getUniqueSubjectLen"/></p>
+      <p>Unique Predicates <span tal:content="view/getUniquePredicateLen"/></p>
+      <p>Unique Objects <span tal:content="view/getUniqueObjectLen"/></p>
+
+      <p tal:condition="view/getClassLen">Classes <span tal:content="view/getClassLen"/></p>
+      <p  tal:condition="view/getPropertyLen">Properties <span tal:content="view/getPropertyLen"/></p>
+
    </div>
 
 </body>

Modified: z3/zemantic/trunk/utils.py
==============================================================================
--- z3/zemantic/trunk/utils.py	(original)
+++ z3/zemantic/trunk/utils.py	Sun Feb 13 08:30:08 2005
@@ -35,7 +35,7 @@
 from lib.ZODBBackend import ZODBBackend
 from interfaces import IZemantic
 from zope.interface import implements
-from urllib import quote
+from urllib import quote, quote_plus
 
 from rdflib.Literal import Literal
 from rdflib.BNode import BNode
@@ -59,8 +59,8 @@
         bcount = 0
         lcount = 0
         out.append('digraph "%s" {' % self.title)
-        out.append('node [fontname="Courier",fontsize=10,color=Black,fontcolor=Blue];')
-        out.append('edge [fontname="Courier",fontsize=10,color=Darkgreen,fontcolor=Red];')
+#        out.append('node [fontname="Courier",fontsize=10,color=Black,fontcolor=Blue];')
+#        out.append('edge [fontname="Courier",fontsize=10,color=Darkgreen,fontcolor=Red];')
         out.append('rankdir=LR;')
         cat = self.cat
         for r in cat.query(Query()):

Modified: z3/zemantic/trunk/viz_view.pt
==============================================================================
--- z3/zemantic/trunk/viz_view.pt	(original)
+++ z3/zemantic/trunk/viz_view.pt	Sun Feb 13 08:30:08 2005
@@ -20,13 +20,9 @@
 		 reset python: subject or predicate or obj;">
 
 
-      <p>Download the catalog in <a href="./@@graph.dot">DOT Format</a>.</p>
-      <p>Download the catalog in <a href="./@@graph.svg">SVG</a>.</p>
-      <p>Download the catalog in <a href="./@@graph.jpg">JPG</a>.</p>
-
-
-     <EMBED SRC="./@@graph.svg" WIDTH="100%" HEIGHT="100%"  NAME="SVGEmbed" TYPE="image/svg-xml" PLUGINSPAGE="http://www.adobe.com/svg/viewer/install/"/>
-
+      <p>Download the catalog graph in <a href="./@@graph.dot">DOT Format</a>.</p>
+      <p>Download the catalog graph in <a href="./@@graph.svg">SVG</a>.</p>
+      <p>Download the catalog graph in <a href="./@@graph.jpg">JPG</a>.</p>
 </div>
 </body>
 </html>

Modified: z3/zemantic/trunk/zemantic.py
==============================================================================
--- z3/zemantic/trunk/zemantic.py	(original)
+++ z3/zemantic/trunk/zemantic.py	Sun Feb 13 08:30:08 2005
@@ -48,6 +48,7 @@
 
 from zope.interface import implements
 from zope.interface.verify import verifyClass
+from zope.app.size.interfaces import ISized
 
 class Zemantic(Persistent):
     """
@@ -67,11 +68,12 @@
     implements(IZemantic)
 
     _v_store = backend = __parent__ = __name__ = None
+    notify = False
 
-    def __init__(self):
-        self.backend = IOZODBBackend()
-        self.schemata = PersistentDict()
-        self.notify = False
+    def __init__(self, backend=None):
+        if backend is None:
+            backend = IOZODBBackend()
+        self.backend = backend
 
     def clear(self):
         """
@@ -113,6 +115,7 @@
         """
         t = (subject, predicate, object)
         self.store.add(t)
+
         if self.notify:
             afterAdd(t)
 
@@ -123,7 +126,7 @@
         t = (subject, predicate, object)
         if self.notify:
             beforeRemove(t)
-            
+
         self.store.remove(t)
 
     def triples(self, (subject, predicate, object)):
@@ -183,3 +186,19 @@
 
     def rdfnt(self):
         return self.store.serialize("nt")
+
+    def __len__(self):
+        return len(self.store)
+
+
+class ZemanticSized(object):
+    implements(ISized)
+
+    def __init__(self, zemantic):
+        self._zemantic = zemantic
+
+    def sizeForSorting(self):
+        return ('item', len(self._zemantic))
+
+    def sizeForDisplay(self):
+        return str(len(self._zemantic)) + ' triples'

Added: z3/zemantic/trunk/zont_view.pt
==============================================================================
--- (empty file)
+++ z3/zemantic/trunk/zont_view.pt	Sun Feb 13 08:30:08 2005
@@ -0,0 +1,34 @@
+<html metal:use-macro="context/@@standard_macros/view">
+<body>pp
+
+   <p>Schemata</p>
+
+   <p id="error"
+      tal:condition="request/error | nothing"
+      tal:content="request/error" />
+
+   <p id="message"
+      tal:condition="request/message | nothing"
+      tal:content="request/message" />
+
+
+   <div metal:fill-slot="body">
+
+      <p>Total Triples <span tal:content="view/getTotalTriples"/></p>
+      <p>Total Schemas <span tal:content="view/getTotalSchemas"/></p>
+      <p>Unique Subjects <span tal:content="view/getUniqueSubjectLen"/></p>
+      <p>Unique Predicates <span tal:content="view/getUniquePredicateLen"/></p>
+      <p>Unique Objects <span tal:content="view/getUniqueObjectLen"/></p>
+
+   <p>Clicking "Load Stuff" will snarf down 200+ ontologies from <a
+   href="http://schemaweb.info">schemaweb.info</a>.  This could take
+   several minutes to load the 100K+ triples.</p>
+
+   <form action="./@@loadStuff">
+     <input type="submit" name="loadStuff" value="Load Stuff">
+   </form>
+
+   </div>
+
+</body>
+</html>

Modified: z3/zemantic/trunk/zontology.py
==============================================================================
--- z3/zemantic/trunk/zontology.py	(original)
+++ z3/zemantic/trunk/zontology.py	Sun Feb 13 08:30:08 2005
@@ -71,43 +71,66 @@
 
     implements(IOntology, IZemantic)
 
-    def properties(self):
+    _v_props = _v_classes = None
 
-        # implement _v_caching of properties
-        r = {}
-        q = self.query(Query(Any, TYPE, PROPERTY))
-        for p in q:
-            if p is not None:
-                v, k = split_URI(p.subject)
-                r[k] = p.subject
-        return r
-
-    def classes(self):
-
-        # implement _v_caching of classes
-        r = {}
-        q = self.query(Query(Any, TYPE, RDFS_CLASS))
-        for p in q:
-            if p is not None:
-                v, k = split_URI(p.subject)
-                r[k] = p.subject
-
-        q = self.query(Query(Any, RDFS_SUBCLASSOF, Any))
-        for p in q:
-            if p is not None:
-                v, k = split_URI(p.subject)
-                r[k] = p.subject
-        return r
+    def add(self, (subject, predicate, object)):
+        self._v_props = self._v_classes = None
+        Zemantic.add(self, (subject, predicate, object))
+
+    def remove(self, (subject, predicate, object)):
+        self._v_props = self._v_classes = None
+        Zemantic.remove(self, (subject, predicate, object))
+
+    def getProperties(self):
+
+        if self._v_props is None:
+            self._v_props = {}
+            q = self.query(Query(Any, TYPE, PROPERTY))
+            for p in q:
+                if p is not None:
+                    try:
+                        v, k = split_URI(p.subject)
+                    except:
+                        continue
+                    self._v_props[k] = p.subject
+        return self._v_props
+        
+    properties = property(getProperties)
+
+    def getClasses(self):
+
+        if self._v_classes is None:
+            self._v_classes = {}
+            q = self.query(Query(Any, TYPE, RDFS_CLASS))
+            for p in q:
+                if p is not None:
+                    try:
+                        v, k = split_URI(p.subject)
+                    except:
+                        continue
+                    self._v_classes[k] = p.subject
+
+            q = self.query(Query(Any, RDFS_SUBCLASSOF, Any))
+            for p in q:
+                if p is not None:
+                    try:
+                        v, k = split_URI(p.subject)
+                    except:
+                        continue
+                    self._v_classes[k] = p.subject
+        return self._v_classes
+
+    classes = property(getClasses)
 
     def hasProperty(self, name):
-        return self.properties().has_key(name)
+        return self.properties.has_key(name)
 
     def hasClass(self, name):
-        return self.classes().has_key(name)
+        return self.classes.has_key(name)
 
     def __getitem__(self, attr):
-        cls = self.classes()
-        prs = self.properties()
+        cls = self.classes
+        prs = self.properties
 
         if cls.has_key(attr):
             return cls[attr]


More information about the z3-checkins mailing list