1. gweis
  2. ordf

Commits

William Waites  committed a058b99

improve cached_object_predicate and make some tests for skos...

  • Participants
  • Parent commits ca37be1
  • Branches default

Comments (0)

Files changed (4)

File docs/index.rst

View file
     * PyPi: http://pypi.python.org/pypi/ordf/
     * Mercurial: http://ordf.org/src/
 
-It is based on RDFLib_ and contains support
+It is based on RDFLib_ and contains an object-description mapper, support 
 for multiple back-end indices, message passing, revision history and
-provenance, a namespace library and a variety of helper functions and
+provenance, a namespace library and  a variety of helper functions and
 modules to ease integration with the Pylons_ framework.
 
 Contents:

File ordf/tests/test_skos.py

View file
+from ordf.namespace import register_ns, Namespace
+register_ns("ont", Namespace("http://www.example.org/ontology#"))
+register_ns("data", Namespace("http://www.example.org/data#"))
+from ordf.graph import Graph
+from ordf.namespace import ONT, DATA, SKOS
+from ordf.vocab.skos import ConceptScheme, Concept
+
+class Food(ConceptScheme):
+    def __init__(self, *av, **kw):
+        super(Food, self).__init__(ONT.Food, *av, **kw)
+
+class Fruit(Concept):
+    def __init__(self, *av, **kw):
+        kwa = kw.copy()
+        kwa["skipClassMembership"] = True
+        super(Fruit, self).__init__(*av, **kwa)
+        if not kw.get("skipClassMembership"):
+            self.type = ONT.Fruit
+
+class Veg(Concept):
+    def __init__(self, *av, **kw):
+        kwa = kw.copy()
+        kwa["skipClassMembership"] = True
+        super(Veg, self).__init__(*av, **kwa)
+        if not kw.get("skipClassMembership"):
+            self.type = ONT.Veg
+
+def test_skos():
+    ontology = Graph()
+    data = Graph()
+
+    food = Food(graph=ontology, factoryGraph=data)
+
+    fruit = Concept(ONT.Fruit, graph=ontology, factoryGraph=data, factoryClass=Fruit)
+    fruit.inScheme = food
+    food.topConcept = fruit
+    fruit.label = "fruit"
+
+    veg = Concept(ONT.Veg, graph=ontology, factoryGraph=data, factoryClass=Veg)
+    veg.inScheme = food
+    food.topConcept = veg
+
+    apple = fruit.get_or_create(DATA.apple)
+    apple.broader = fruit
+
+    carrot = veg.get_or_create(DATA.carrot)
+    carrot.broader = veg
+
+    assert veg in carrot.broader
+    assert fruit in apple.broader
+
+    assert veg in food.topConcept
+    assert food in veg.inScheme
+
+    assert fruit in food.topConcept
+    assert food in veg.inScheme

File ordf/vocab/owl.py

View file
         if isinstance(self._cls, basestring):
             self._cls = self._globals[self._cls]
         for identifier in super(object_predicate, self)._get(obj):
-            yield self._cls(identifier, graph=obj.graph)
+            yield self._cls(identifier, graph=obj.graph, factoryGraph=obj.factoryGraph, 
+                            skipClassMembership=True)
 
 class cached_predicate(predicate):
     """
     >>> bob.graph.remove((bob.identifier, None, None))
     >>> for pet in bob.pet: print [str(x) for x in pet.label]
     ['Max']
+    >>> # prove that it is the *same* object
+    >>> for pet in bob.pet:
+    ...     assert id(pet) == id(max)
+    ...
     """
     def __init__(self, term, implementation=None, globals=None):
         if implementation is None:
     def _set(self, obj, value):
         if not isinstance(value, list) and not isinstance(value, tuple):
             value = [value]
+        cached_values = self._get(obj)
         for x in value:
             if isinstance(x, URIRef) or isinstance(x, BNode):
                 x = self._cls(value, graph=obj.graph)
             assert isinstance(x, Individual), "expected an Individual, got an %s" % x
-            obj.graph.add((obj.identifier, self.term, x.identifier))
-        _cache = self._cache(obj)
-        if self.term in _cache: del _cache[self.term]
+            if x not in cached_values:
+                cached_values.append(x)
+                obj.graph.add((obj.identifier, self.term, x.identifier))
+
     def _get(self, obj):
         if isinstance(self._cls, basestring):
             self._cls = self._globals[self._cls]
         if self.term in _cache:
             return _cache[self.term]
         results = [
-            self._cls(x, graph=obj.graph)
+            self._cls(x, graph=obj.graph, factoryGraph=obj.factorGraph,
+                      skipClassMembership=True)
             for x in super(cached_object_predicate, self)._get(obj)
             ]
         _cache[self.term] = results
     .. automethod:: replace
     .. automethod:: serialize
     """
-    def __init__(self, identifier=None, graph=None, factoryGraph=None):
+    def __init__(self, identifier=None, graph=None, factoryGraph=None, **kw):
         self.__identifier = identifier is not None and identifier or BNode()
         if factoryGraph is not None:
             self.factoryGraph = factoryGraph
 
         Similarly for *rdfs:seeAlso*
     """
-    def __init__(self, identifier, graph=None, factoryGraph=None):
-        super(AnnotatibleTerms, self).__init__(identifier, graph=graph, factoryGraph=factoryGraph)
-
     label = predicate(RDFS.label)
     comment = predicate(RDFS.comment)
     seeAlso = predicate(RDFS.seeAlso)
                 else:
                     return BooleanClass(classOrIdentifier(c),operator=p,graph=graph)
             #assert (classOrIdentifier(c),RDF.type,OWL.Class) in graph
-            return Class(classOrIdentifier(c),graph=graph,skipOWLClassMembership=True)
+            return Class(classOrIdentifier(c),graph=graph,skipClassMembership=True)
     
 class Class(AnnotatibleTerms):
     """
     def __init__(self, identifier=None, graph=None, factoryGraph=None, factoryClass=Individual,
                  subClassOf=None,equivalentClass=None,
                  disjointWith=None,complementOf=None,
-                 skipOWLClassMembership=False,comment=None):
+                 skipClassMembership=False,
+                 comment=None):
         super(Class, self).__init__(identifier, graph=graph, factoryGraph=factoryGraph)
-        if not skipOWLClassMembership and (self.identifier,RDF.type,OWL.Class) not in self.graph and \
+        if not skipClassMembership and (self.identifier,RDF.type,OWL.Class) not in self.graph and \
            (self.identifier,RDF.type,OWL.Restriction) not in self.graph:
             self.graph.add((self.identifier,RDF.type,OWL.Class))
         self.factoryClass    = factoryClass
             class _xClass(Individual):
                 def __new__(self, *av, **kw):
                     kwa=kw.copy()
-                    kwa["skipOWLClassMembership"] = True
+                    kwa["skipClassMembership"] = True
                     return Class(*av, **kwa)
             super(self.__class__, self).__init__(RDFS.subClassOf, _xClass)
     subClassOf = _subClassOf()
         
 #    def __iter__(self):
 #        for s in self.graph.subjects(predicate=RDFS.subClassOf,object=self.identifier):
-#            yield Class(s,skipOWLClassMembership=True)
+#            yield Class(s,skipClassMembership=True)
     
     def __repr__(self,full=False,normalization=True):
         """
                  identifier=None):
         super(Restriction, self).__init__(identifier,
                                           graph=graph,
-                                          skipOWLClassMembership=True)
+                                          skipClassMembership=True)
         if (self.identifier,
             OWL.onProperty,
             propertyOrIdentifier(onProperty)) not in graph:

File ordf/vocab/skos.py

View file
 from ordf.graph import Graph
-from ordf.vocab.owl import predicate, cached_predicate, Class, Individual, AnnotatibleTerms
+from ordf.vocab.owl import cached_predicate, cached_object_predicate, Class, Individual, AnnotatibleTerms
 from logging import getLogger
 
 log = getLogger(__name__)
     prefLabel = cached_predicate(SKOS.prefLabel)
     altLabel = cached_predicate(SKOS.altLabel)
     notation = cached_predicate(SKOS.notation)
-            
+
 class ConceptScheme(Class, _Common):
+    topConcept = cached_object_predicate(SKOS.topConcept, "Concept", globals())
+
     def __init__(self, *av, **kw):
         kwa = kw.copy()
-        kwa.setdefault("skipOWLClassMembership", True)
+        kwa["skipClassMembership"] = True
+        kwa.setdefault("factoryClass", Concept)
         super(ConceptScheme, self).__init__(*av, **kwa)
-        self.type = SKOS.ConceptScheme
-    def get(self, identifier=None, graph=None):
-        if graph is None: graph=self.graph
-        concept = ConceptInstance(identifier, graph=graph)
-        concept.factoryGraph = graph
-        return concept
+        if not kw.get("skipClassMembership"):
+            self.type = SKOS.ConceptScheme
 
-    def addTop(self, concept):
-        self.topConcept = concept
+class Concept(Class, _Common):
+    inScheme = cached_object_predicate(SKOS.inScheme, ConceptScheme)
+    topConceptOf = cached_object_predicate(SKOS.topConceptOf, ConceptScheme)
+    narrower = cached_object_predicate(SKOS.narrower, "Concept", globals())
+    broader = cached_object_predicate(SKOS.broader, "Concept", globals())
 
-    def _get_topConcept(self):
-        for concept in self.graph.distinct_objects(self.identifier, SKOS.topConcept):
-            if self.graph.exists(concept, OWL.subClassOf, SKOS.Concept):
-                yield Concept(concept, graph=self.graph)
-            else:
-                yield ConceptInstance(concept, graph=self.graph)
-    def _set_topConcept(self, concept):
-        self.graph.add((self.identifier, SKOS.topConcept, concept.identifier))
-        concept.graph.add((concept.identifier, SKOS.topConceptOf, self.identifier))
-        concept.inScheme = self
-    topConcept = property(_get_topConcept, _set_topConcept)
-
-class _ConceptCommon(_Common):
-    def _get_inScheme(self):
-        if not hasattr(self, "_inScheme_cache"):
-            self._inScheme_cache = [Scheme(x, self.graph) for x in
-                                    self.graph.distinct_objects(self.identifier, SKOS.inScheme)]
-        return self._inScheme_cache
-    def _set_inScheme(self, what):
-        if isinstance(what, Individual): what = what.identifier
-        self.graph.add((self.identifier, SKOS.inScheme, what))
-        if hasattr(self, "_inScheme_cache"): del self._inScheme_cache
-    inScheme = property(_get_inScheme, _set_inScheme)
-    def _get_narrower(self):
-        if not hasattr(self, "_narrower_cache"):
-            self._narrower_cache = [ConceptInstance(x, self.graph) for x in 
-                                    self.graph.distinct_objects(self.identifier, SKOS.narrower)]
-        return self._narrower_cache
-    def _set_narrower(self, what):
-        if isinstance(what, Individual): what = what.identifier
-        self.graph.add((self.identifier, SKOS.narrower, what))
-        if hasattr(self, "_narrower_cache"): del self._narrower_cache
-    narrower = property(_get_narrower, _set_narrower)
-    def _get_broader(self):
-        if not hasattr(self, "_broader_cache"):
-            self._broader_cache = [ConceptInstance(x, self.graph) for x in 
-                                    self.graph.distinct_objects(self.identifier, SKOS.broader)]
-        return self._broader_cache
-    def _set_broader(self, what):
-        if isinstance(what, Individual): what = what.identifier
-        self.graph.add((self.identifier, SKOS.broader, what))
-        if hasattr(self, "_broader_cache"): del self._broader_cache
-    broader = property(_get_broader, _set_broader)
-
-class Concept(Class, _ConceptCommon):
     def __init__(self, *av, **kw):
         kwa = kw.copy()
-        supers = set(kw.get("subClassOf", []))
-        supers.add(SKOS.Concept)
-        kwa["subClassOf"] = supers
+        kwa["skipClassMembership"] = True
+        kwa.setdefault("factoryClass", Concept)
         super(Concept, self).__init__(*av, **kwa)
-
-class ConceptInstance(AnnotatibleTerms, _ConceptCommon):
-    pass
+        if not kw.get("skipClassMembership"):
+            self.type = SKOS.Concept
 
 class NotationCache(object):
     def __init__(self, store):