예제 #1
0
def is_ncname(value):
    __doc__ = format_doctest_out("""
    BNode identifiers must be valid NCNames.

    From the `W3C RDF Syntax doc <http://www.w3.org/TR/REC-rdf-syntax/#section-blank-nodeid-event>`_

    "The value is a function of the value of the ``identifier`` accessor. 
    The string value begins with "_:" and the entire value MUST match 
    the `N-Triples nodeID <http://www.w3.org/TR/2004/REC-rdf-testcases-20040210/#nodeID>`_ production".

    The nodeID production is specified to be a `name <http://www.w3.org/TR/2004/REC-rdf-testcases-20040210/#name>`_

        name    ::= [A-Za-z][A-Za-z0-9]*

    >>> assert is_ncname('') == False
    >>> assert is_ncname('999') == False
    >>> assert is_ncname('x') == True
    >>> assert is_ncname(%(u)s'x') == True
    >>> assert is_ncname(%(u)s'Michèle') == True
    
    However, vanilla uuid4s are not necessarily NCNames:

    >>> assert is_ncname('6fa459ea-ee8a-3ca4-894e-db77e160355e') == False

    So this has to be finessed with an appropriate prefix ...

    >>> assert is_ncname("urn:uuid:"+str(uuid4())) == True
    >>> from rdflib import BNode
    >>> assert is_ncname(BNode(_sn_gen=bnode_uuid(), _prefix="urn:uuid:")) == True 
    """)
    ncnameexp = re.compile('[A-Za-z][A-Za-z0-9]*')
    if ncnameexp.match(value):
        return True
    else:
        return False
예제 #2
0
class URIPattern(unicode):

    __doc__ = format_doctest_out("""
    Utility class for creating URIs according to some pattern
    This supports either new style formatting with .format
    or old-style with %% operator

    >>> u=URIPattern("http://example.org/%%s/%%d/resource")
    >>> u%%('books', 12345)
    rdflib.term.URIRef(%(u)s'http://example.org/books/12345/resource')

    """)

    def __new__(cls, value):
        try:
            rt = unicode.__new__(cls, value)
        except UnicodeDecodeError:
            rt = unicode.__new__(cls, value, 'utf-8')
        return rt

    def __mod__(self, *args, **kwargs):
        return URIRef(unicode(self).__mod__(*args, **kwargs))

    def format(self, *args, **kwargs):
        return URIRef(unicode.format(self, *args, **kwargs))

    def __repr__(self):
        return "URIPattern(%r)" % unicode.__repr__(self)
예제 #3
0
class Namespace(unicode):

    __doc__ = format_doctest_out("""
    Utility class for quickly generating URIRefs with a common prefix

    >>> from rdflib import Namespace
    >>> n = Namespace("http://example.org/")
    >>> n.Person # as attribute
    rdflib.term.URIRef(%(u)s'http://example.org/Person')
    >>> n['first-name'] # as item - for things that are not valid python identifiers
    rdflib.term.URIRef(%(u)s'http://example.org/first-name')

    """)

    def __new__(cls, value):
        try:
            rt = unicode.__new__(cls, value)
        except UnicodeDecodeError:
            rt = unicode.__new__(cls, value, 'utf-8')
        return rt

    @property
    def title(self):
        # overrides unicode.title to allow DCTERMS.title for example
        return URIRef(self + 'title')

    def term(self, name):
        # need to handle slices explicitly because of __getitem__ override
        return URIRef(self + (name if isinstance(name, basestring) else ''))

    def __getitem__(self, key, default=None):
        return self.term(key)

    def __getattr__(self, name):
        if name.startswith("__"):  # ignore any special Python names!
            raise AttributeError
        else:
            return self.term(name)

    def __repr__(self):
        return "Namespace(%s)" % unicode.__repr__(self)
예제 #4
0
__doc__ = py3compat.format_doctest_out("""
The :class:`~rdflib.resource.Resource` class wraps a
:class:`~rdflib.graph.Graph`
and a resource reference (i.e. a :class:`rdflib.term.URIRef` or
:class:`rdflib.term.BNode`) to support a resource-oriented way of
working with a graph.

It contains methods directly corresponding to those methods of the Graph
interface that relate to reading and writing data. The difference is that a
Resource also binds a resource identifier, making it possible to work without
tracking both the graph and a current subject. This makes for a "resource
oriented" style, as compared to the triple orientation of the Graph API.

Resulting generators are also wrapped so that any resource reference values
(:class:`rdflib.term.URIRef`s and :class:`rdflib.term.BNode`s) are in turn
wrapped as Resources. (Note that this behaviour differs from the corresponding
methods in :class:`~rdflib.graph.Graph`, where no such conversion takes place.)


Basic Usage Scenario
--------------------

Start by importing things we need and define some namespaces::

    >>> from rdflib import *
    >>> FOAF = Namespace("http://xmlns.com/foaf/0.1/")
    >>> CV = Namespace("http://purl.org/captsolo/resume-rdf/0.2/cv#")

Load some RDF data::

    >>> graph = Graph().parse(format='n3', data='''
    ... @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
    ... @prefix xsd: <http://www.w3.org/2001/XMLSchema#>.
    ... @prefix foaf: <http://xmlns.com/foaf/0.1/> .
    ... @prefix cv: <http://purl.org/captsolo/resume-rdf/0.2/cv#> .
    ...
    ... @base <http://example.org/> .
    ...
    ... </person/some1#self> a foaf:Person;
    ...     rdfs:comment "Just a Python & RDF hacker."@en;
    ...     foaf:depiction </images/person/some1.jpg>;
    ...     foaf:homepage <http://example.net/>;
    ...     foaf:name "Some Body" .
    ...
    ... </images/person/some1.jpg> a foaf:Image;
    ...     rdfs:label "some 1"@en;
    ...     rdfs:comment "Just an image"@en;
    ...     foaf:thumbnail </images/person/some1-thumb.jpg> .
    ...
    ... </images/person/some1-thumb.jpg> a foaf:Image .
    ...
    ... [] a cv:CV;
    ...     cv:aboutPerson </person/some1#self>;
    ...     cv:hasWorkHistory [ cv:employedIn </#company>;
    ...             cv:startDate "2009-09-04"^^xsd:date ] .
    ... ''')

Create a Resource::

    >>> person = Resource(
    ...     graph, URIRef("http://example.org/person/some1#self"))

Retrieve some basic facts::

    >>> person.identifier
    rdflib.term.URIRef(%(u)s'http://example.org/person/some1#self')

    >>> person.value(FOAF.name)
    rdflib.term.Literal(%(u)s'Some Body')

    >>> person.value(RDFS.comment)
    rdflib.term.Literal(%(u)s'Just a Python & RDF hacker.', lang=%(u)s'en')

Resources as unicode are represented by their identifiers as unicode::

    >>> %(unicode)s(person)  #doctest: +SKIP
    %(u)s'Resource(http://example.org/person/some1#self'

Resource references are also Resources, so you can easily get e.g. a qname
for the type of a resource, like::

    >>> person.value(RDF.type).qname()
    %(u)s'foaf:Person'

Or for the predicates of a resource::

    >>> sorted(
    ...     p.qname() for p in person.predicates()
    ... )  #doctest: +NORMALIZE_WHITESPACE +SKIP
    [%(u)s'foaf:depiction', %(u)s'foaf:homepage',
     %(u)s'foaf:name', %(u)s'rdf:type', %(u)s'rdfs:comment']

Follow relations and get more data from their Resources as well::

    >>> for pic in person.objects(FOAF.depiction):
    ...     print((pic.identifier))
    ...     print((pic.value(RDF.type).qname()))
    ...     print((pic.label()))
    ...     print((pic.comment()))
    ...     print((pic.value(FOAF.thumbnail).identifier))
    http://example.org/images/person/some1.jpg
    foaf:Image
    some 1
    Just an image
    http://example.org/images/person/some1-thumb.jpg

    >>> for cv in person.subjects(CV.aboutPerson):
    ...     work = list(cv.objects(CV.hasWorkHistory))[0]
    ...     print((work.value(CV.employedIn).identifier))
    ...     print((work.value(CV.startDate)))
    http://example.org/#company
    2009-09-04

It's just as easy to work with the predicates of a resource::

    >>> for s, p in person.subject_predicates():
    ...     print((s.value(RDF.type).qname()))
    ...     print((p.qname()))
    ...     for s, o in p.subject_objects():
    ...         print((s.value(RDF.type).qname()))
    ...         print((o.value(RDF.type).qname()))
    cv:CV
    cv:aboutPerson
    cv:CV
    foaf:Person

This is useful for e.g. inspection::

    >>> thumb_ref = URIRef("http://example.org/images/person/some1-thumb.jpg")
    >>> thumb = Resource(graph, thumb_ref)
    >>> for p, o in thumb.predicate_objects():
    ...     print((p.qname()))
    ...     print((o.qname()))
    rdf:type
    foaf:Image

Similarly, adding, setting and removing data is easy::

    >>> thumb.add(RDFS.label, Literal("thumb"))
    >>> print((thumb.label()))
    thumb
    >>> thumb.set(RDFS.label, Literal("thumbnail"))
    >>> print((thumb.label()))
    thumbnail
    >>> thumb.remove(RDFS.label)
    >>> list(thumb.objects(RDFS.label))
    []


Schema Example
--------------

With this artificial schema data::

    >>> graph = Graph().parse(format='n3', data='''
    ... @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
    ... @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
    ... @prefix owl: <http://www.w3.org/2002/07/owl#> .
    ... @prefix v: <http://example.org/def/v#> .
    ...
    ... v:Artifact a owl:Class .
    ...
    ... v:Document a owl:Class;
    ...     rdfs:subClassOf v:Artifact .
    ...
    ... v:Paper a owl:Class;
    ...     rdfs:subClassOf v:Document .
    ...
    ... v:Choice owl:oneOf (v:One v:Other) .
    ...
    ... v:Stuff a rdf:Seq; rdf:_1 v:One; rdf:_2 v:Other .
    ...
    ... ''')

From this class::

    >>> artifact = Resource(graph, URIRef("http://example.org/def/v#Artifact"))

we can get at subclasses::

    >>> subclasses = list(artifact.transitive_subjects(RDFS.subClassOf))
    >>> [c.qname() for c in subclasses]
    [%(u)s'v:Artifact', %(u)s'v:Document', %(u)s'v:Paper']

and superclasses from the last subclass::

    >>> [c.qname() for c in subclasses[-1].transitive_objects(RDFS.subClassOf)]
    [%(u)s'v:Paper', %(u)s'v:Document', %(u)s'v:Artifact']

Get items from the Choice::

    >>> choice = Resource(graph, URIRef("http://example.org/def/v#Choice"))
    >>> [it.qname() for it in list(choice.value(OWL.oneOf).items())]
    [%(u)s'v:One', %(u)s'v:Other']

And the sequence of Stuff::

    >>> stuff = Resource(graph, URIRef("http://example.org/def/v#Stuff"))
    >>> [it.qname() for it in stuff.seq()]
    [%(u)s'v:One', %(u)s'v:Other']

On add, other resources are auto-unboxed:
    >>> paper = Resource(graph, URIRef("http://example.org/def/v#Paper"))
    >>> paper.add(RDFS.subClassOf, artifact)
    >>> artifact in paper.objects(RDFS.subClassOf) # checks Resource instance
    True
    >>> (paper._identifier, RDFS.subClassOf, artifact._identifier) in graph
    True


Technical Details
-----------------

Comparison is based on graph and identifier::

    >>> g1 = Graph()
    >>> t1 = Resource(g1, URIRef("http://example.org/thing"))
    >>> t2 = Resource(g1, URIRef("http://example.org/thing"))
    >>> t3 = Resource(g1, URIRef("http://example.org/other"))
    >>> t4 = Resource(Graph(), URIRef("http://example.org/other"))

    >>> t1 is t2
    False

    >>> t1 == t2
    True
    >>> t1 != t2
    False

    >>> t1 == t3
    False
    >>> t1 != t3
    True

    >>> t3 != t4
    True

    >>> t3 < t1 and t1 > t3
    True
    >>> t1 >= t1 and t1 >= t3
    True
    >>> t1 <= t1 and t3 <= t1
    True

    >>> t1 < t1 or t1 < t3 or t3 > t1 or t3 > t3
    False

Hash is computed from graph and identifier::

    >>> g1 = Graph()
    >>> t1 = Resource(g1, URIRef("http://example.org/thing"))

    >>> hash(t1) == hash(Resource(g1, URIRef("http://example.org/thing")))
    True

    >>> hash(t1) == hash(Resource(Graph(), t1.identifier))
    False
    >>> hash(t1) == hash(Resource(Graph(), URIRef("http://example.org/thing")))
    False

The Resource class is suitable as a base class for mapper toolkits. For
example, consider this utility for accessing RDF properties via qname-like
attributes::

    >>> class Item(Resource):
    ...
    ...     def __getattr__(self, p):
    ...         return list(self.objects(self._to_ref(*p.split('_', 1))))
    ...
    ...     def _to_ref(self, pfx, name):
    ...         return URIRef(self._graph.store.namespace(pfx) + name)

It works as follows::

    >>> graph = Graph().parse(format='n3', data='''
    ... @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
    ... @prefix foaf: <http://xmlns.com/foaf/0.1/> .
    ...
    ... @base <http://example.org/> .
    ... </person/some1#self>
    ...     foaf:name "Some Body";
    ...     foaf:depiction </images/person/some1.jpg> .
    ... </images/person/some1.jpg> rdfs:comment "Just an image"@en .
    ... ''')

    >>> person = Item(graph, URIRef("http://example.org/person/some1#self"))

    >>> print((person.foaf_name[0]))
    Some Body

The mechanism for wrapping references as resources cooperates with subclasses.
Therefore, accessing referenced resources automatically creates new ``Item``
objects::

    >>> isinstance(person.foaf_depiction[0], Item)
    True

    >>> print((person.foaf_depiction[0].rdfs_comment[0]))
    Just an image

""")
예제 #5
0
__doc__ = py3compat.format_doctest_out("""
The ``Resource`` class wraps a ``Graph`` and a resource reference (i.e. an
``URIRef`` or ``BNode``), to support a resource oriented way of working with a
graph.

It contains methods directly corresponding to those methods of the Graph
interface that relate to reading and writing data. The difference is that a
Resource also binds a resource identifier, making it possible to work without
tracking both the graph and a current subject. This makes for a "resource
oriented" style, as compared to the triple orientation of the Graph API.

Resulting generators are also wrapped so that any resource reference values
(``URIRef``s and ``BNode``s) are in turn wrapped as Resources. (Note that this
behaviour differs from the corresponding methods in Graph, were no such
conversion takes place.)


Basic Usage Scenario
--------------------

Start by importing things we need and define some namespaces::

    >>> from rdflib import *
    >>> FOAF = Namespace("http://xmlns.com/foaf/0.1/")
    >>> CV = Namespace("http://purl.org/captsolo/resume-rdf/0.2/cv#")

Load some RDF data::

    >>> graph = Graph().parse(format='n3', data='''
    ... @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
    ... @prefix xsd: <http://www.w3.org/2001/XMLSchema#>.
    ... @prefix foaf: <http://xmlns.com/foaf/0.1/> .
    ... @prefix cv: <http://purl.org/captsolo/resume-rdf/0.2/cv#> .
    ...
    ... @base <http://example.org/> .
    ...
    ... </person/some1#self> a foaf:Person;
    ...     rdfs:comment "Just a Python & RDF hacker."@en;
    ...     foaf:depiction </images/person/some1.jpg>;
    ...     foaf:homepage <http://example.net/>;
    ...     foaf:name "Some Body" .
    ...
    ... </images/person/some1.jpg> a foaf:Image;
    ...     rdfs:label "some 1"@en;
    ...     rdfs:comment "Just an image"@en;
    ...     foaf:thumbnail </images/person/some1-thumb.jpg> .
    ...
    ... </images/person/some1-thumb.jpg> a foaf:Image .
    ...
    ... [] a cv:CV;
    ...     cv:aboutPerson </person/some1#self>;
    ...     cv:hasWorkHistory [ cv:employedIn </#company>;
    ...             cv:startDate "2009-09-04"^^xsd:date ] .
    ... ''')

Create a Resource::

    >>> person = Resource(graph, URIRef("http://example.org/person/some1#self"))

Retrieve some basic facts::

    >>> person.identifier
    rdflib.term.URIRef('http://example.org/person/some1#self')

    >>> person.value(FOAF.name)
    rdflib.term.Literal(%(u)s'Some Body')

    >>> person.value(RDFS.comment)
    rdflib.term.Literal(%(u)s'Just a Python & RDF hacker.', lang=%(u)s'en')

Resources as unicode are represented by their identifiers as unicode::

    >>> unicode(person)
    %(u)s'http://example.org/person/some1#self'

Resource references are also Resources, so you can easily get e.g. a qname
for the type of a resource, like::

    >>> person.value(RDF.type).qname()
    %(u)s'foaf:Person'

Or for the predicates of a resource::

    >>> sorted(p.qname() for p in person.predicates())
    [%(u)s'foaf:depiction', %(u)s'foaf:homepage', %(u)s'foaf:name', %(u)s'rdf:type', %(u)s'rdfs:comment']

Follow relations and get more data from their Resources as well::

    >>> for pic in person.objects(FOAF.depiction):
    ...     print(pic.identifier)
    ...     print(pic.value(RDF.type).qname())
    ...     print(pic.label())
    ...     print(pic.comment())
    ...     print(pic.value(FOAF.thumbnail).identifier)
    http://example.org/images/person/some1.jpg
    foaf:Image
    some 1
    Just an image
    http://example.org/images/person/some1-thumb.jpg

    >>> for cv in person.subjects(CV.aboutPerson):
    ...     work = list(cv.objects(CV.hasWorkHistory))[0]
    ...     print(work.value(CV.employedIn).identifier)
    ...     print(work.value(CV.startDate))
    http://example.org/#company
    2009-09-04

It's just as easy to work with the predicates of a resource::

    >>> for s, p in person.subject_predicates():
    ...     print(s.value(RDF.type).qname())
    ...     print(p.qname())
    ...     for s, o in p.subject_objects():
    ...         print(s.value(RDF.type).qname())
    ...         print(o.value(RDF.type).qname())
    cv:CV
    cv:aboutPerson
    cv:CV
    foaf:Person

This is useful for e.g. inspection::

    >>> thumb_ref = URIRef("http://example.org/images/person/some1-thumb.jpg")
    >>> thumb = Resource(graph, thumb_ref)
    >>> for p, o in thumb.predicate_objects():
    ...     print(p.qname())
    ...     print(o.qname())
    rdf:type
    foaf:Image

Similarly, adding, setting and removing data is easy::

    >>> thumb.add(RDFS.label, Literal("thumb"))
    >>> print(thumb.label())
    thumb
    >>> thumb.set(RDFS.label, Literal("thumbnail"))
    >>> print(thumb.label())
    thumbnail
    >>> thumb.remove(RDFS.label)
    >>> list(thumb.objects(RDFS.label))
    []


Schema Example
--------------

With this artificial schema data::

    >>> graph = Graph().parse(format='n3', data='''
    ... @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
    ... @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
    ... @prefix owl: <http://www.w3.org/2002/07/owl#> .
    ... @prefix v: <http://example.org/def/v#> .
    ...
    ... v:Artifact a owl:Class .
    ...
    ... v:Document a owl:Class;
    ...     rdfs:subClassOf v:Artifact .
    ...
    ... v:Paper a owl:Class;
    ...     rdfs:subClassOf v:Document .
    ...
    ... v:Choice owl:oneOf (v:One v:Other) .
    ...
    ... v:Stuff a rdf:Seq; rdf:_1 v:One; rdf:_2 v:Other .
    ...
    ... ''')

From this class::

    >>> artifact = Resource(graph, URIRef("http://example.org/def/v#Artifact"))

we can get at subclasses::

    >>> subclasses = list(artifact.transitive_subjects(RDFS.subClassOf))
    >>> [c.qname() for c in subclasses]
    [%(u)s'v:Artifact', %(u)s'v:Document', %(u)s'v:Paper']

and superclasses from the last subclass::

    >>> [c.qname() for c in subclasses[-1].transitive_objects(RDFS.subClassOf)]
    [%(u)s'v:Paper', %(u)s'v:Document', %(u)s'v:Artifact']

Get items from the Choice::

    >>> choice = Resource(graph, URIRef("http://example.org/def/v#Choice"))
    >>> [it.qname() for it in choice.value(OWL.oneOf).items()]
    [%(u)s'v:One', %(u)s'v:Other']

And the sequence of Stuff::

    >>> stuff = Resource(graph, URIRef("http://example.org/def/v#Stuff"))
    >>> [it.qname() for it in stuff.seq()]
    [%(u)s'v:One', %(u)s'v:Other']


Technical Details
-----------------

Comparison is based on graph and identifier::

    >>> g1 = Graph()
    >>> t1 = Resource(g1, URIRef("http://example.org/thing"))
    >>> t2 = Resource(g1, URIRef("http://example.org/thing"))
    >>> t3 = Resource(g1, URIRef("http://example.org/other"))
    >>> t4 = Resource(Graph(), URIRef("http://example.org/other"))

    >>> t1 is t2
    False

    >>> t1 == t2
    True
    >>> t1 != t2
    False

    >>> t1 == t3
    False
    >>> t1 != t3
    True

    >>> t3 != t4
    True

    >>> t3 < t1 and t1 > t3
    True
    >>> t1 >= t1 and t1 >= t3
    True
    >>> t1 <= t1 and t3 <= t1
    True

    >>> t1 < t1 or t1 < t3 or t3 > t1 or t3 > t3
    False

Hash is computed from graph and identifier::

    >>> g1 = Graph()
    >>> t1 = Resource(g1, URIRef("http://example.org/thing"))

    >>> hash(t1) == hash(Resource(g1, URIRef("http://example.org/thing")))
    True

    >>> hash(t1) == hash(Resource(Graph(), t1.identifier))
    False
    >>> hash(t1) == hash(Resource(Graph(), URIRef("http://example.org/thing")))
    False

The Resource class is suitable as a base class for mapper toolkits. For
example, consider this utility for accessing RDF properties via qname-like
attributes::

    >>> class Item(Resource):
    ...
    ...     def __getattr__(self, p):
    ...         return list(self.objects(self._to_ref(*p.split('_', 1))))
    ...
    ...     def _to_ref(self, pfx, name):
    ...         return URIRef(self._graph.store.namespace(pfx) + name)

It works as follows::

    >>> graph = Graph().parse(format='n3', data='''
    ... @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
    ... @prefix foaf: <http://xmlns.com/foaf/0.1/> .
    ...
    ... @base <http://example.org/> .
    ... </person/some1#self>
    ...     foaf:name "Some Body";
    ...     foaf:depiction </images/person/some1.jpg> .
    ... </images/person/some1.jpg> rdfs:comment "Just an image"@en .
    ... ''')

    >>> person = Item(graph, URIRef("http://example.org/person/some1#self"))

    >>> print(person.foaf_name[0])
    Some Body

The mechanism for wrapping references as resources cooperates with subclasses.
Therefore, accessing referenced resources automatically creates new ``Item``
objects::

    >>> isinstance(person.foaf_depiction[0], Item)
    True

    >>> print(person.foaf_depiction[0].rdfs_comment[0])
    Just an image

""")
예제 #6
0
__doc__ = format_doctest_out("""

This module implements the SPARQL 1.1 Property path operators, as
defined in:

http://www.w3.org/TR/sparql11-query/#propertypaths

In SPARQL the syntax is as follows:

+--------------------+-------------------------------------------------+
|Syntax              | Matches                                         |
+====================+=================================================+
|iri                 | An IRI. A path of length one.                   |
+--------------------+-------------------------------------------------+
|^elt                | Inverse path (object to subject).               |
+--------------------+-------------------------------------------------+
|elt1 / elt2         | A sequence path of elt1 followed by elt2.       |
+--------------------+-------------------------------------------------+
|elt1 | elt2         | A alternative path of elt1 or elt2              |
|                    | (all possibilities are tried).                  |
+--------------------+-------------------------------------------------+
|elt*                | A path that connects the subject and object     |
|                    | of the path by zero or more matches of elt.     |
+--------------------+-------------------------------------------------+
|elt+                | A path that connects the subject and object     |
|                    | of the path by one or more matches of elt.      |
+--------------------+-------------------------------------------------+
|elt?                | A path that connects the subject and object     |
|                    | of the path by zero or one matches of elt.      |
+--------------------+-------------------------------------------------+
|!iri or             | Negated property set. An IRI which is not one of|
|!(iri\ :sub:`1`\ |  | iri\ :sub:`1`...iri\ :sub:`n`.                  |
|... |iri\ :sub:`n`) | !iri is short for !(iri).                       |
+--------------------+-------------------------------------------------+
|!^iri or            | Negated property set where the excluded matches |
|!(^iri\ :sub:`1`\ | | are based on reversed path. That is, not one of |
|... |^iri\ :sub:`n`)| iri\ :sub:`1`...iri\ :sub:`n` as reverse paths. |
|                    | !^iri is short for !(^iri).                     |
+--------------------+-------------------------------------------------+
|!(iri\ :sub:`1`\ |  | A combination of forward and reverse            |
|...|iri\ :sub:`j`\ || properties in a negated property set.           |
|^iri\ :sub:`j+1`\ | |                                                 |
|... |^iri\ :sub:`n`)|                                                 |
+--------------------+-------------------------------------------------+
|(elt)               | A group path elt, brackets control precedence.  |
+--------------------+-------------------------------------------------+

This module is used internally be the SPARQL engine, but they property paths
can also be used to query RDFLib Graphs directly.

Where possible the SPARQL syntax is mapped to python operators, and property
path objects can be constructed from existing URIRefs.

>>> from rdflib import Graph, Namespace

>>> foaf=Namespace('http://xmlns.com/foaf/0.1/')

>>> ~foaf.knows
Path(~http://xmlns.com/foaf/0.1/knows)

>>> foaf.knows/foaf.name
Path(http://xmlns.com/foaf/0.1/knows / http://xmlns.com/foaf/0.1/name)

>>> foaf.name|foaf.firstName
Path(http://xmlns.com/foaf/0.1/name | http://xmlns.com/foaf/0.1/firstName)

Modifiers (?, *, +) are done using * (the multiplication operator) and
the strings '*', '?', '+', also defined as constants in this file.

>>> foaf.knows*OneOrMore
Path(http://xmlns.com/foaf/0.1/knows+)

The path objects can also be used with the normal graph methods.

First some example data:

>>> g=Graph()

>>> g=g.parse(data='''
... @prefix : <ex:> .
...
... :a :p1 :c ; :p2 :f .
... :c :p2 :e ; :p3 :g .
... :g :p3 :h ; :p2 :j .
... :h :p3 :a ; :p2 :g .
...
... :q :px :q .
...
... ''', format='n3') # doctest: +ELLIPSIS

>>> e=Namespace('ex:')

Graph contains:
>>> (e.a, e.p1/e.p2, e.e) in g
True

Graph generator functions, triples, subjects, objects, etc. :

>>> list(g.objects(e.c, (e.p3*OneOrMore)/e.p2)) # doctest: +NORMALIZE_WHITESPACE
[rdflib.term.URIRef(%(u)s'ex:j'), rdflib.term.URIRef(%(u)s'ex:g'), 
    rdflib.term.URIRef(%(u)s'ex:f')]

A more complete set of tests:

>>> list(evalPath(g, (None, e.p1/e.p2, None)))==[(e.a, e.e)]
True
>>> list(evalPath(g, (e.a, e.p1|e.p2, None)))==[(e.a,e.c), (e.a,e.f)]
True
>>> list(evalPath(g, (e.c, ~e.p1, None))) == [ (e.c, e.a) ]
True
>>> list(evalPath(g, (e.a, e.p1*ZeroOrOne, None))) == [(e.a, e.a), (e.a, e.c)]
True
>>> list(evalPath(g, (e.c, e.p3*OneOrMore, None))) == [
...     (e.c, e.g), (e.c, e.h), (e.c, e.a)]
True
>>> list(evalPath(g, (e.c, e.p3*ZeroOrMore, None))) == [(e.c, e.c),
...     (e.c, e.g), (e.c, e.h), (e.c, e.a)]
True
>>> list(evalPath(g, (e.a, -e.p1, None))) == [(e.a, e.f)]
True
>>> list(evalPath(g, (e.a, -(e.p1|e.p2), None))) == []
True
>>> list(evalPath(g, (e.g, -~e.p2, None))) == [(e.g, e.j)]
True
>>> list(evalPath(g, (e.e, ~(e.p1/e.p2), None))) == [(e.e, e.a)]
True
>>> list(evalPath(g, (e.a, e.p1/e.p3/e.p3, None))) == [(e.a, e.h)]
True

>>> list(evalPath(g, (e.q, e.px*OneOrMore, None)))
[(rdflib.term.URIRef(%(u)s'ex:q'), rdflib.term.URIRef(%(u)s'ex:q'))]

>>> list(evalPath(g, (None, e.p1|e.p2, e.c)))
[(rdflib.term.URIRef(%(u)s'ex:a'), rdflib.term.URIRef(%(u)s'ex:c'))]

>>> list(evalPath(g, (None, ~e.p1, e.a))) == [ (e.c, e.a) ]
True
>>> list(evalPath(g, (None, e.p1*ZeroOrOne, e.c))) # doctest: +NORMALIZE_WHITESPACE
[(rdflib.term.URIRef(%(u)s'ex:c'), rdflib.term.URIRef(%(u)s'ex:c')),
 (rdflib.term.URIRef(%(u)s'ex:a'), rdflib.term.URIRef(%(u)s'ex:c'))]

>>> list(evalPath(g, (None, e.p3*OneOrMore, e.a))) # doctest: +NORMALIZE_WHITESPACE
[(rdflib.term.URIRef(%(u)s'ex:h'), rdflib.term.URIRef(%(u)s'ex:a')),
 (rdflib.term.URIRef(%(u)s'ex:g'), rdflib.term.URIRef(%(u)s'ex:a')),
 (rdflib.term.URIRef(%(u)s'ex:c'), rdflib.term.URIRef(%(u)s'ex:a'))]

>>> list(evalPath(g, (None, e.p3*ZeroOrMore, e.a))) # doctest: +NORMALIZE_WHITESPACE
[(rdflib.term.URIRef(%(u)s'ex:a'), rdflib.term.URIRef(%(u)s'ex:a')),
 (rdflib.term.URIRef(%(u)s'ex:h'), rdflib.term.URIRef(%(u)s'ex:a')),
 (rdflib.term.URIRef(%(u)s'ex:g'), rdflib.term.URIRef(%(u)s'ex:a')),
 (rdflib.term.URIRef(%(u)s'ex:c'), rdflib.term.URIRef(%(u)s'ex:a'))]

>>> list(evalPath(g, (None, -e.p1, e.f))) == [(e.a, e.f)]
True
>>> list(evalPath(g, (None, -(e.p1|e.p2), e.c))) == []
True
>>> list(evalPath(g, (None, -~e.p2, e.j))) == [(e.g, e.j)]
True
>>> list(evalPath(g, (None, ~(e.p1/e.p2), e.a))) == [(e.e, e.a)]
True
>>> list(evalPath(g, (None, e.p1/e.p3/e.p3, e.h))) == [(e.a, e.h)]
True

>>> list(evalPath(g, (e.q, e.px*OneOrMore, None)))
[(rdflib.term.URIRef(%(u)s'ex:q'), rdflib.term.URIRef(%(u)s'ex:q'))]

>>> list(evalPath(g, (e.c, (e.p2|e.p3)*ZeroOrMore, e.j)))
[(rdflib.term.URIRef(%(u)s'ex:c'), rdflib.term.URIRef(%(u)s'ex:j'))]

No vars specified:

>>> sorted(list(evalPath(g, (None, e.p3*OneOrMore, None)))) #doctest: +NORMALIZE_WHITESPACE
[(rdflib.term.URIRef(%(u)s'ex:c'), rdflib.term.URIRef(%(u)s'ex:a')),
 (rdflib.term.URIRef(%(u)s'ex:c'), rdflib.term.URIRef(%(u)s'ex:g')),
 (rdflib.term.URIRef(%(u)s'ex:c'), rdflib.term.URIRef(%(u)s'ex:h')),
 (rdflib.term.URIRef(%(u)s'ex:g'), rdflib.term.URIRef(%(u)s'ex:a')),
 (rdflib.term.URIRef(%(u)s'ex:g'), rdflib.term.URIRef(%(u)s'ex:h')),
 (rdflib.term.URIRef(%(u)s'ex:h'), rdflib.term.URIRef(%(u)s'ex:a'))]

.. versionadded:: 4.0

""")
예제 #7
0
__doc__ = format_doctest_out("""
===================
Namespace Utilities
===================

RDFLib provides mechanisms for managing Namespaces.

In particular, there is a :class:`~rdflib.namespace.Namespace` class that takes as its argument the base URI of the namespace.

.. code-block:: pycon

    >>> from rdflib.namespace import Namespace
    >>> fuxi = Namespace('http://metacognition.info/ontologies/FuXi.n3#')

Fully qualified URIs in the namespace can be constructed either by attribute or by dictionary access on Namespace instances:

.. code-block:: pycon

    >>> fuxi.ruleBase
    rdflib.term.URIRef(u'http://metacognition.info/ontologies/FuXi.n3#ruleBase')
    >>> fuxi['ruleBase']
    rdflib.term.URIRef(u'http://metacognition.info/ontologies/FuXi.n3#ruleBase')

Automatic handling of unknown predicates
-----------------------------------------

As a programming convenience, a namespace binding is automatically created when :class:`rdflib.term.URIRef` predicates are added to the graph:

.. code-block:: pycon

    >>> from rdflib import Graph, URIRef
    >>> g = Graph()
    >>> g.add((URIRef("http://example0.com/foo"),
    ...        URIRef("http://example1.com/bar"),
    ...        URIRef("http://example2.com/baz")))
    >>> print(g.serialize(format="n3"))
    @prefix ns1: <http://example1.com/> .
    <BLANKLINE>
    <http://example0.com/foo> ns1:bar <http://example2.com/baz> .
    <BLANKLINE>
    <BLANKLINE>
    >>> 

Importable namespaces
-----------------------

The following namespaces are available by directly importing from rdflib:

* RDF
* RDFS
* OWL
* XSD

.. code-block:: pycon

    >>> from rdflib import OWL
    >>> OWL.seeAlso
    rdflib.term.URIRef(u'http://www.w3.org/2002/07/owl#seeAlso')

""")
예제 #8
0
__doc__ = format_doctest_out("""
===================
Namespace Utilities
===================

RDFLib provides mechanisms for managing Namespaces.

In particular, there is a :class:`~rdflib.namespace.Namespace` class
that takes as its argument the base URI of the namespace.

.. code-block:: pycon

    >>> from rdflib.namespace import Namespace
    >>> owl = Namespace('http://www.w3.org/2002/07/owl#')

Fully qualified URIs in the namespace can be constructed either by attribute
or by dictionary access on Namespace instances:

.. code-block:: pycon

    >>> owl.seeAlso
    rdflib.term.URIRef(%(u)s'http://www.w3.org/2002/07/owl#seeAlso')
    >>> owl['seeAlso']
    rdflib.term.URIRef(%(u)s'http://www.w3.org/2002/07/owl#seeAlso')


Automatic handling of unknown predicates
-----------------------------------------

As a programming convenience, a namespace binding is automatically
created when :class:`rdflib.term.URIRef` predicates are added to the graph.

Importable namespaces
-----------------------

The following namespaces are available by directly importing from rdflib:

* RDF
* RDFS
* OWL
* XSD
* FOAF
* SKOS
* DOAP
* DC
* DCTERMS
* VOID

.. code-block:: pycon

    >>> from rdflib import OWL
    >>> OWL.seeAlso
    rdflib.term.URIRef(%(u)s'http://www.w3.org/2002/07/owl#seeAlso')

""")
예제 #9
0
__doc__ = format_doctest_out("""
===================
Namespace Utilities
===================

RDFLib provides mechanisms for managing Namespaces.

In particular, there is a :class:`~rdflib.namespace.Namespace` class
that takes as its argument the base URI of the namespace.

.. code-block:: pycon

    >>> from rdflib.namespace import Namespace
    >>> owl = Namespace('http://www.w3.org/2002/07/owl#')

Fully qualified URIs in the namespace can be constructed either by attribute
or by dictionary access on Namespace instances:

.. code-block:: pycon

    >>> owl.seeAlso
    rdflib.term.URIRef(%(u)s'http://www.w3.org/2002/07/owl#seeAlso')
    >>> owl['seeAlso']
    rdflib.term.URIRef(%(u)s'http://www.w3.org/2002/07/owl#seeAlso')


Automatic handling of unknown predicates
-----------------------------------------

As a programming convenience, a namespace binding is automatically
created when :class:`rdflib.term.URIRef` predicates are added to the graph.

Importable namespaces
-----------------------

The following namespaces are available by directly importing from rdflib:

* RDF
* RDFS
* OWL
* XSD
* FOAF
* SKOS
* DOAP
* DC
* DCTERMS
* VOID

.. code-block:: pycon

    >>> from rdflib import OWL
    >>> OWL.seeAlso
    rdflib.term.URIRef(%(u)s'http://www.w3.org/2002/07/owl#seeAlso')

""")
예제 #10
0
파일: describer.py 프로젝트: kod3r/rdflib
__doc__ = py3compat.format_doctest_out("""
A Describer is a stateful utility for creating RDF statements in a
semi-declarative manner. It has methods for creating literal values, rel and
rev resource relations (somewhat resembling RDFa).

The `rel` and ``rev`` methods return a context manager which sets the current
about to the referenced resource for the context scope (for use with the
``with`` statement).

Full example in the ``to_rdf`` method below::

    >>> import datetime
    >>> from rdflib.graph import Graph
    >>> from rdflib.namespace import Namespace, RDFS
    >>>
    >>> ORG_URI = "http://example.org/"
    >>>
    >>> FOAF = Namespace("http://xmlns.com/foaf/0.1/")
    >>> CV = Namespace("http://purl.org/captsolo/resume-rdf/0.2/cv#")
    >>>
    >>> class Person(object):
    ...     def __init__(self):
    ...         self.first_name = %(u)s"Some"
    ...         self.last_name = %(u)s"Body"
    ...         self.username = "******"
    ...         self.presentation = %(u)s"Just a Python & RDF hacker."
    ...         self.image = "/images/persons/" + self.username + ".jpg"
    ...         self.site = "http://example.net/"
    ...         self.start_date = datetime.date(2009, 9, 4)
    ...     def get_full_name(self):
    ...         return %(u)s" ".join([self.first_name, self.last_name])
    ...     def get_absolute_url(self):
    ...         return "/persons/" + self.username
    ...     def get_thumbnail_url(self):
    ...         return self.image.replace('.jpg', '-thumb.jpg')
    ...
    ...     def to_rdf(self):
    ...         graph = Graph()
    ...         graph.bind('foaf', FOAF)
    ...         graph.bind('cv', CV)
    ...         lang = 'en'
    ...         d = Describer(graph, base=ORG_URI)
    ...         d.about(self.get_absolute_url()+'#person')
    ...         d.rdftype(FOAF.Person)
    ...         d.value(FOAF.name, self.get_full_name())
    ...         d.value(FOAF.firstName, self.first_name)
    ...         d.value(FOAF.surname, self.last_name)
    ...         d.rel(FOAF.homepage, self.site)
    ...         d.value(RDFS.comment, self.presentation, lang=lang)
    ...         with d.rel(FOAF.depiction, self.image):
    ...             d.rdftype(FOAF.Image)
    ...             d.rel(FOAF.thumbnail, self.get_thumbnail_url())
    ...         with d.rev(CV.aboutPerson):
    ...             d.rdftype(CV.CV)
    ...             with d.rel(CV.hasWorkHistory):
    ...                 d.value(CV.startDate, self.start_date)
    ...                 d.rel(CV.employedIn, ORG_URI+"#company")
    ...         return graph
    ...
    >>> person_graph = Person().to_rdf()
    >>> expected = Graph().parse(data='''<?xml version="1.0" encoding="utf-8"?>
    ... <rdf:RDF
    ...   xmlns:foaf="http://xmlns.com/foaf/0.1/"
    ...   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    ...   xmlns:cv="http://purl.org/captsolo/resume-rdf/0.2/cv#"
    ...   xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#">
    ...   <foaf:Person rdf:about="http://example.org/persons/some1#person">
    ...     <foaf:name>Some Body</foaf:name>
    ...     <foaf:firstName>Some</foaf:firstName>
    ...     <foaf:surname>Body</foaf:surname>
    ...     <foaf:depiction>
    ...       <foaf:Image
    ...         rdf:about=
    ...             "http://example.org/images/persons/some1.jpg">
    ...         <foaf:thumbnail
    ...         rdf:resource=
    ...             "http://example.org/images/persons/some1-thumb.jpg"/>
    ...       </foaf:Image>
    ...     </foaf:depiction>
    ...     <rdfs:comment xml:lang="en">
    ...             Just a Python &amp; RDF hacker.
    ...     </rdfs:comment>
    ...     <foaf:homepage rdf:resource="http://example.net/"/>
    ...   </foaf:Person>
    ...   <cv:CV>
    ...     <cv:aboutPerson
    ...         rdf:resource="http://example.org/persons/some1#person">
    ...     </cv:aboutPerson>
    ...     <cv:hasWorkHistory>
    ...       <rdf:Description>
    ...         <cv:startDate
    ...             rdf:datatype="http://www.w3.org/2001/XMLSchema#date"
    ...             >2009-09-04</cv:startDate>
    ...         <cv:employedIn rdf:resource="http://example.org/#company"/>
    ...       </rdf:Description>
    ...     </cv:hasWorkHistory>
    ...   </cv:CV>
    ... </rdf:RDF>
    ... ''')
    >>>
    >>> from rdflib.compare import isomorphic
    >>> isomorphic(person_graph, expected)  #doctest: +SKIP
    True
""")
예제 #11
0
class Collection(object):
    __doc__ = format_doctest_out("""
    See 3.3.5 Emulating container types: http://docs.python.org/ref/sequence-types.html#l2h-232

    >>> from rdflib.graph import Graph    
    >>> listName = BNode()
    >>> g = Graph('IOMemory')
    >>> listItem1 = BNode()
    >>> listItem2 = BNode()
    >>> g.add((listName,RDF.first,Literal(1)))
    >>> g.add((listName,RDF.rest,listItem1))
    >>> g.add((listItem1,RDF.first,Literal(2)))
    >>> g.add((listItem1,RDF.rest,listItem2))
    >>> g.add((listItem2,RDF.rest,RDF.nil))
    >>> g.add((listItem2,RDF.first,Literal(3)))
    >>> c=Collection(g,listName)
    >>> print(list(c))
    [rdflib.term.Literal(%(u)s'1', datatype=rdflib.term.URIRef(%(u)s'http://www.w3.org/2001/XMLSchema#integer')), rdflib.term.Literal(%(u)s'2', datatype=rdflib.term.URIRef(%(u)s'http://www.w3.org/2001/XMLSchema#integer')), rdflib.term.Literal(%(u)s'3', datatype=rdflib.term.URIRef(%(u)s'http://www.w3.org/2001/XMLSchema#integer'))]
    >>> 1 in c
    True
    >>> len(c)
    3
    >>> c._get_container(1) == listItem1
    True
    >>> c.index(Literal(2)) == 1
    True
    """)
    def __init__(self, graph, uri, seq=[]):
        self.graph = graph
        self.uri = uri or BNode()
        for item in seq:
            self.append(item)

    def n3(self):
        """
        >>> from rdflib.graph import Graph    
        >>> listName = BNode()
        >>> g = Graph('IOMemory')
        >>> listItem1 = BNode()
        >>> listItem2 = BNode()
        >>> g.add((listName,RDF.first,Literal(1)))
        >>> g.add((listName,RDF.rest,listItem1))
        >>> g.add((listItem1,RDF.first,Literal(2)))
        >>> g.add((listItem1,RDF.rest,listItem2))
        >>> g.add((listItem2,RDF.rest,RDF.nil))
        >>> g.add((listItem2,RDF.first,Literal(3)))
        >>> c=Collection(g,listName)
        >>> print(c.n3())
        ( "1"^^<http://www.w3.org/2001/XMLSchema#integer> "2"^^<http://www.w3.org/2001/XMLSchema#integer> "3"^^<http://www.w3.org/2001/XMLSchema#integer> )
        """
        return "( %s )"%(' '.join([i.n3() for i in self]))

    def _get_container(self, index):
        """Gets the first, rest holding node at index."""
        assert isinstance(index, int)
        graph = self.graph
        container = self.uri
        i = 0
        while i<index:
            i += 1
            container = graph.value(container, RDF.rest)
            if container is None:
                break
        return container

    def __len__(self):
        """length of items in collection."""
        count = 0
        links=set()
        for item in self.graph.items(self.uri):
            assert item not in links,"There is a loop in the RDF list! (%s has been processed before)"%item
            links.add(item)
            count += 1
        return count

    def index(self, item):
        """
        Returns the 0-based numerical index of the item in the list          
        """
        listName = self.uri
        index = 0
        while True:
            if (listName,RDF.first,item) in self.graph:
                return index
            else:
                newLink = list(self.graph.objects(listName,RDF.rest))
                index += 1
                if newLink == [RDF.nil]:
                    raise ValueError("%s is not in %s"%(item,self.uri))
                elif not newLink:
                    raise Exception("Malformed RDF Collection: %s"%self.uri)
                else:
                    assert len(newLink)==1, "Malformed RDF Collection: %s"%self.uri
                    listName = newLink[0]

    def __getitem__(self, key):
        """TODO"""
        c = self._get_container(key)
        if c:
            v = self.graph.value(c, RDF.first)
            if v:
                return v
            else:
                raise KeyError, key
        else:
            raise IndexError, key

    def __setitem__(self, key, value):
        """TODO"""
        c = self._get_container(key)
        if c:
            self.graph.add((c, RDF.first, value))
        else:
            raise IndexError, key


    def __delitem__(self, key):
        """
        >>> from rdflib.namespace import RDF, RDFS
        >>> from rdflib import Graph
        >>> from pprint import pformat
        >>> g=Graph()
        >>> a=BNode('foo')
        >>> b=BNode('bar')
        >>> c=BNode('baz')
        >>> g.add((a,RDF.first,RDF.type))
        >>> g.add((a,RDF.rest,b))
        >>> g.add((b,RDF.first,RDFS.label))
        >>> g.add((b,RDF.rest,c))
        >>> g.add((c,RDF.first,RDFS.comment))
        >>> g.add((c,RDF.rest,RDF.nil))
        >>> len(g)
        6
        >>> def listAncestry(node,graph):
        ...   for i in graph.subjects(RDF.rest,node): 
        ...     yield i
        >>> [str(node.n3()) for node in g.transitiveClosure(listAncestry,RDF.nil)]
        ['_:baz', '_:bar', '_:foo']
        >>> lst=Collection(g,a)
        >>> len(lst)
        3
        >>> b==lst._get_container(1)
        True
        >>> c==lst._get_container(2)
        True
        >>> del lst[1]
        >>> len(lst)
        2
        >>> len(g)
        4
        
        """
        self[key] # to raise any potential key exceptions
        graph = self.graph
        current = self._get_container(key)
        assert current
        if len(self)==1 and key>0:
            pass
        elif key==len(self)-1:
            #the tail
            priorLink = self._get_container(key-1)
            self.graph.set((priorLink,RDF.rest,RDF.nil))
            graph.remove((current, None, None))
        else:
            next = self._get_container(key+1)
            prior = self._get_container(key-1)
            assert next and prior
            graph.remove((current, None, None))
            graph.set((prior, RDF.rest, next))

    def __iter__(self):
        """Iterator over items in Collections"""
        return self.graph.items(self.uri)

    def append(self, item):
        """
        >>> from rdflib.graph import Graph    
        >>> listName = BNode()
        >>> g = Graph()
        >>> c=Collection(g,listName,[Literal(1),Literal(2)])
        >>> links = [list(g.subjects(object=i,predicate=RDF.first))[0] for i in c]
        >>> len([i for i in links if (i,RDF.rest,RDF.nil) in g])
        1
        
        """
        container = self.uri
        graph = self.graph
        #iterate to the end of the linked list
        rest = graph.value(container, RDF.rest)
        while rest:
            if rest == RDF.nil:
                #the end, append to the end of the linked list
                node = BNode()
                graph.set((container, RDF.rest, node))
                container=node                
                break
            else:
                #move down one link
                if container != self.uri:
                    rest = graph.value(rest, RDF.rest)
                if not rest == RDF.nil:
                    container=rest
        graph.add((container, RDF.first, item))
        graph.add((container, RDF.rest, RDF.nil))

    def clear(self):
        container = self.uri
        graph = self.graph
        while container:
            rest = graph.value(container, RDF.rest)
            graph.remove((container, RDF.first, None))
            graph.remove((container, RDF.rest, None))
            container = rest
예제 #12
0
class Collection(object):
    __doc__ = format_doctest_out("""
    A tweak of rdflib Connection. This one doesnt update the store when its created.
    """)

    def __init__(self, graph, uri):
        self.graph = graph
        self.uri = uri or BNode()

    def n3(self):
        """
        >>> from rdflib.graph import Graph
        >>> listName = BNode()
        >>> g = Graph('IOMemory')
        >>> listItem1 = BNode()
        >>> listItem2 = BNode()
        >>> g.add((listName, RDF.first, Literal(1)))
        >>> g.add((listName, RDF.rest, listItem1))
        >>> g.add((listItem1, RDF.first, Literal(2)))
        >>> g.add((listItem1, RDF.rest, listItem2))
        >>> g.add((listItem2, RDF.rest, RDF.nil))
        >>> g.add((listItem2, RDF.first, Literal(3)))
        >>> c = Collection(g, listName)
        >>> print(c.n3()) #doctest: +NORMALIZE_WHITESPACE
        ( "1"^^<http://www.w3.org/2001/XMLSchema#integer>
          "2"^^<http://www.w3.org/2001/XMLSchema#integer>
          "3"^^<http://www.w3.org/2001/XMLSchema#integer> )
        """
        return "( %s )" % (' '.join([i.n3() for i in self]))

    def _get_container(self, index):
        """Gets the first, rest holding node at index."""
        assert isinstance(index, int)
        graph = self.graph
        container = self.uri
        i = 0
        while i < index:
            i += 1
            container = graph.value(container, RDF.rest)
            if container is None:
                break
        return container

    def __len__(self):
        """length of items in collection."""
        return len(list(self.graph.items(self.uri)))

    def index(self, item):
        """
        Returns the 0-based numerical index of the item in the list
        """
        listName = self.uri
        index = 0
        while True:
            if (listName, RDF.first, item) in self.graph:
                return index
            else:
                newLink = list(self.graph.objects(listName, RDF.rest))
                index += 1
                if newLink == [RDF.nil]:
                    raise ValueError("%s is not in %s" % (item, self.uri))
                elif not newLink:
                    raise Exception("Malformed RDF Collection: %s" % self.uri)
                else:
                    assert len(newLink) == 1, \
                        "Malformed RDF Collection: %s" % self.uri
                    listName = newLink[0]

    def __getitem__(self, key):
        """TODO"""
        c = self._get_container(key)
        if c:
            v = self.graph.value(c, RDF.first)
            if v:
                return v
            else:
                raise KeyError(key)
        else:
            raise IndexError(key)

    def __setitem__(self, key, value):
        """TODO"""
        c = self._get_container(key)
        if c:
            self.graph.set((c, RDF.first, value))
        else:
            raise IndexError(key)

    def __delitem__(self, key):
        """
        >>> from rdflib.namespace import RDF, RDFS
        >>> from rdflib import Graph
        >>> from pprint import pformat
        >>> g = Graph()
        >>> a = BNode('foo')
        >>> b = BNode('bar')
        >>> c = BNode('baz')
        >>> g.add((a, RDF.first, RDF.type))
        >>> g.add((a, RDF.rest, b))
        >>> g.add((b, RDF.first, RDFS.label))
        >>> g.add((b, RDF.rest, c))
        >>> g.add((c, RDF.first, RDFS.comment))
        >>> g.add((c, RDF.rest, RDF.nil))
        >>> len(g)
        6
        >>> def listAncestry(node, graph):
        ...   for i in graph.subjects(RDF.rest, node):
        ...     yield i
        >>> [str(node.n3())
        ...   for node in g.transitiveClosure(listAncestry, RDF.nil)]
        ['_:baz', '_:bar', '_:foo']
        >>> lst = Collection(g, a)
        >>> len(lst)
        3
        >>> b == lst._get_container(1)
        True
        >>> c == lst._get_container(2)
        True
        >>> del lst[1]
        >>> len(lst)
        2
        >>> len(g)
        4

        """
        self[key]  # to raise any potential key exceptions
        graph = self.graph
        current = self._get_container(key)
        assert current
        if len(self) == 1 and key > 0:
            pass
        elif key == len(self) - 1:
            # the tail
            priorLink = self._get_container(key - 1)
            self.graph.set((priorLink, RDF.rest, RDF.nil))
            graph.remove((current, None, None))
        else:
            next = self._get_container(key + 1)
            prior = self._get_container(key - 1)
            assert next and prior
            graph.remove((current, None, None))
            graph.set((prior, RDF.rest, next))

    def __iter__(self):
        """Iterator over items in Collections"""
        return self.graph.items(self.uri)

    def _end(self):
        # find end of list
        container = self.uri
        while True:
            rest = self.graph.value(container, RDF.rest)
            if rest == None or rest == RDF.nil:
                return container
            else:
                container = rest

    def append(self, item):
        """
        >>> from rdflib.graph import Graph
        >>> listName = BNode()
        >>> g = Graph()
        >>> c = Collection(g,listName,[Literal(1),Literal(2)])
        >>> links = [
        ...     list(g.subjects(object=i, predicate=RDF.first))[0] for i in c]
        >>> len([i for i in links if (i, RDF.rest, RDF.nil) in g])
        1

        """

        end = self._end()
        if (end, RDF.first, None) in self.graph:
            # append new node to the end of the linked list
            node = BNode()
            self.graph.set((end, RDF.rest, node))
            end = node

        self.graph.add((end, RDF.first, item))
        self.graph.add((end, RDF.rest, RDF.nil))

    def __iadd__(self, other):

        end = self._end()
        self.graph.remove((end, RDF.rest, None))

        for item in other:
            if (end, RDF.first, None) in self.graph:
                nxt = BNode()
                self.graph.add((end, RDF.rest, nxt))
                end = nxt

            self.graph.add((end, RDF.first, item))

        self.graph.add((end, RDF.rest, RDF.nil))

    def clear(self):
        container = self.uri
        graph = self.graph
        while container:
            rest = graph.value(container, RDF.rest)
            graph.remove((container, RDF.first, None))
            graph.remove((container, RDF.rest, None))
            container = rest
예제 #13
0
__doc__ = format_doctest_out("""

This module implements the SPARQL 1.1 Property path operators, as
defined in:

http://www.w3.org/TR/sparql11-query/#propertypaths

In SPARQL the syntax is as follows:

+--------------------+-------------------------------------------------+
|Syntax              | Matches                                         |
+====================+=================================================+
|iri                 | An IRI. A path of length one.                   |
+--------------------+-------------------------------------------------+
|^elt                | Inverse path (object to subject).               |
+--------------------+-------------------------------------------------+
|elt1 / elt2         | A sequence path of elt1 followed by elt2.       |
+--------------------+-------------------------------------------------+
|elt1 | elt2         | A alternative path of elt1 or elt2              |
|                    | (all possibilities are tried).                  |
+--------------------+-------------------------------------------------+
|elt*                | A path that connects the subject and object     |
|                    | of the path by zero or more matches of elt.     |
+--------------------+-------------------------------------------------+
|elt+                | A path that connects the subject and object     |
|                    | of the path by one or more matches of elt.      |
+--------------------+-------------------------------------------------+
|elt?                | A path that connects the subject and object     |
|                    | of the path by zero or one matches of elt.      |
+--------------------+-------------------------------------------------+
|!iri or             | Negated property set. An IRI which is not one of|
|!(iri\ :sub:`1`\ |  | iri\ :sub:`1`...iri\ :sub:`n`.                  |
|... |iri\ :sub:`n`) | !iri is short for !(iri).                       |
+--------------------+-------------------------------------------------+
|!^iri or            | Negated property set where the excluded matches |
|!(^iri\ :sub:`1`\ | | are based on reversed path. That is, not one of |
|... |^iri\ :sub:`n`)| iri\ :sub:`1`...iri\ :sub:`n` as reverse paths. |
|                    | !^iri is short for !(^iri).                     |
+--------------------+-------------------------------------------------+
|!(iri\ :sub:`1`\ |  | A combination of forward and reverse            |
|...|iri\ :sub:`j`\ || properties in a negated property set.           |
|^iri\ :sub:`j+1`\ | |                                                 |
|... |^iri\ :sub:`n`)|                                                 |
+--------------------+-------------------------------------------------+
|(elt)               | A group path elt, brackets control precedence.  |
+--------------------+-------------------------------------------------+

This module is used internally be the SPARQL engine, but they property paths
can also be used to query RDFLib Graphs directly.

Where possible the SPARQL syntax is mapped to python operators, and property
path objects can be constructed from existing URIRefs.

>>> from rdflib import Graph, Namespace

>>> foaf=Namespace('http://xmlns.com/foaf/0.1/')

>>> ~foaf.knows
Path(~http://xmlns.com/foaf/0.1/knows)

>>> foaf.knows/foaf.name
Path(http://xmlns.com/foaf/0.1/knows / http://xmlns.com/foaf/0.1/name)

>>> foaf.name|foaf.firstName
Path(http://xmlns.com/foaf/0.1/name | http://xmlns.com/foaf/0.1/firstName)

Modifiers (?, *, +) are done using * (the multiplication operator) and
the strings '*', '?', '+', also defined as constants in this file.

>>> foaf.knows*OneOrMore
Path(http://xmlns.com/foaf/0.1/knows+)

The path objects can also be used with the normal graph methods.

First some example data:

>>> g=Graph()

>>> g=g.parse(data='''
... @prefix : <ex:> .
...
... :a :p1 :c ; :p2 :f .
... :c :p2 :e ; :p3 :g .
... :g :p3 :h ; :p2 :j .
... :h :p3 :a ; :p2 :g .
...
... :q :px :q .
...
... ''', format='n3') # doctest: +ELLIPSIS

>>> e=Namespace('ex:')

Graph contains:
>>> (e.a, e.p1/e.p2, e.e) in g
True

Graph generator functions, triples, subjects, objects, etc. :

>>> list(g.objects(e.c, (e.p3*OneOrMore)/e.p2)) # doctest: +NORMALIZE_WHITESPACE
[rdflib.term.URIRef(%(u)s'ex:j'), rdflib.term.URIRef(%(u)s'ex:g'),
    rdflib.term.URIRef(%(u)s'ex:f')]

A more complete set of tests:

>>> list(evalPath(g, (None, e.p1/e.p2, None)))==[(e.a, e.e)]
True
>>> list(evalPath(g, (e.a, e.p1|e.p2, None)))==[(e.a,e.c), (e.a,e.f)]
True
>>> list(evalPath(g, (e.c, ~e.p1, None))) == [ (e.c, e.a) ]
True
>>> list(evalPath(g, (e.a, e.p1*ZeroOrOne, None))) == [(e.a, e.a), (e.a, e.c)]
True
>>> list(evalPath(g, (e.c, e.p3*OneOrMore, None))) == [
...     (e.c, e.g), (e.c, e.h), (e.c, e.a)]
True
>>> list(evalPath(g, (e.c, e.p3*ZeroOrMore, None))) == [(e.c, e.c),
...     (e.c, e.g), (e.c, e.h), (e.c, e.a)]
True
>>> list(evalPath(g, (e.a, -e.p1, None))) == [(e.a, e.f)]
True
>>> list(evalPath(g, (e.a, -(e.p1|e.p2), None))) == []
True
>>> list(evalPath(g, (e.g, -~e.p2, None))) == [(e.g, e.j)]
True
>>> list(evalPath(g, (e.e, ~(e.p1/e.p2), None))) == [(e.e, e.a)]
True
>>> list(evalPath(g, (e.a, e.p1/e.p3/e.p3, None))) == [(e.a, e.h)]
True

>>> list(evalPath(g, (e.q, e.px*OneOrMore, None)))
[(rdflib.term.URIRef(%(u)s'ex:q'), rdflib.term.URIRef(%(u)s'ex:q'))]

>>> list(evalPath(g, (None, e.p1|e.p2, e.c)))
[(rdflib.term.URIRef(%(u)s'ex:a'), rdflib.term.URIRef(%(u)s'ex:c'))]

>>> list(evalPath(g, (None, ~e.p1, e.a))) == [ (e.c, e.a) ]
True
>>> list(evalPath(g, (None, e.p1*ZeroOrOne, e.c))) # doctest: +NORMALIZE_WHITESPACE
[(rdflib.term.URIRef(%(u)s'ex:c'), rdflib.term.URIRef(%(u)s'ex:c')),
 (rdflib.term.URIRef(%(u)s'ex:a'), rdflib.term.URIRef(%(u)s'ex:c'))]

>>> list(evalPath(g, (None, e.p3*OneOrMore, e.a))) # doctest: +NORMALIZE_WHITESPACE
[(rdflib.term.URIRef(%(u)s'ex:h'), rdflib.term.URIRef(%(u)s'ex:a')),
 (rdflib.term.URIRef(%(u)s'ex:g'), rdflib.term.URIRef(%(u)s'ex:a')),
 (rdflib.term.URIRef(%(u)s'ex:c'), rdflib.term.URIRef(%(u)s'ex:a'))]

>>> list(evalPath(g, (None, e.p3*ZeroOrMore, e.a))) # doctest: +NORMALIZE_WHITESPACE
[(rdflib.term.URIRef(%(u)s'ex:a'), rdflib.term.URIRef(%(u)s'ex:a')),
 (rdflib.term.URIRef(%(u)s'ex:h'), rdflib.term.URIRef(%(u)s'ex:a')),
 (rdflib.term.URIRef(%(u)s'ex:g'), rdflib.term.URIRef(%(u)s'ex:a')),
 (rdflib.term.URIRef(%(u)s'ex:c'), rdflib.term.URIRef(%(u)s'ex:a'))]

>>> list(evalPath(g, (None, -e.p1, e.f))) == [(e.a, e.f)]
True
>>> list(evalPath(g, (None, -(e.p1|e.p2), e.c))) == []
True
>>> list(evalPath(g, (None, -~e.p2, e.j))) == [(e.g, e.j)]
True
>>> list(evalPath(g, (None, ~(e.p1/e.p2), e.a))) == [(e.e, e.a)]
True
>>> list(evalPath(g, (None, e.p1/e.p3/e.p3, e.h))) == [(e.a, e.h)]
True

>>> list(evalPath(g, (e.q, e.px*OneOrMore, None)))
[(rdflib.term.URIRef(%(u)s'ex:q'), rdflib.term.URIRef(%(u)s'ex:q'))]

>>> list(evalPath(g, (e.c, (e.p2|e.p3)*ZeroOrMore, e.j)))
[(rdflib.term.URIRef(%(u)s'ex:c'), rdflib.term.URIRef(%(u)s'ex:j'))]

No vars specified:

>>> sorted(list(evalPath(g, (None, e.p3*OneOrMore, None)))) #doctest: +NORMALIZE_WHITESPACE
[(rdflib.term.URIRef(%(u)s'ex:c'), rdflib.term.URIRef(%(u)s'ex:a')),
 (rdflib.term.URIRef(%(u)s'ex:c'), rdflib.term.URIRef(%(u)s'ex:g')),
 (rdflib.term.URIRef(%(u)s'ex:c'), rdflib.term.URIRef(%(u)s'ex:h')),
 (rdflib.term.URIRef(%(u)s'ex:g'), rdflib.term.URIRef(%(u)s'ex:a')),
 (rdflib.term.URIRef(%(u)s'ex:g'), rdflib.term.URIRef(%(u)s'ex:h')),
 (rdflib.term.URIRef(%(u)s'ex:h'), rdflib.term.URIRef(%(u)s'ex:a'))]

.. versionadded:: 4.0

""")
예제 #14
0
__doc__ = format_doctest_out(
    """
===================
Namespace Utilities
===================

RDFLib provides mechanisms for managing Namespaces.

In particular, there is a :class:`~rdflib.namespace.Namespace` class that takes as its argument the base URI of the namespace.

.. code-block:: pycon

    >>> from rdflib.namespace import Namespace
    >>> fuxi = Namespace('http://metacognition.info/ontologies/FuXi.n3#')

Fully qualified URIs in the namespace can be constructed either by attribute or by dictionary access on Namespace instances:

.. code-block:: pycon

    >>> fuxi.ruleBase
    rdflib.term.URIRef(u'http://metacognition.info/ontologies/FuXi.n3#ruleBase')
    >>> fuxi['ruleBase']
    rdflib.term.URIRef(u'http://metacognition.info/ontologies/FuXi.n3#ruleBase')

Automatic handling of unknown predicates
-----------------------------------------

As a programming convenience, a namespace binding is automatically created when :class:`rdflib.term.URIRef` predicates are added to the graph:

.. code-block:: pycon

    >>> from rdflib import Graph, URIRef
    >>> g = Graph()
    >>> g.add((URIRef("http://example0.com/foo"),
    ...        URIRef("http://example1.com/bar"),
    ...        URIRef("http://example2.com/baz")))
    >>> print(g.serialize(format="n3"))
    @prefix ns1: <http://example1.com/> .
    <BLANKLINE>
    <http://example0.com/foo> ns1:bar <http://example2.com/baz> .
    <BLANKLINE>
    <BLANKLINE>
    >>> 

Importable namespaces
-----------------------

The following namespaces are available by directly importing from rdflib:

* RDF
* RDFS
* OWL
* XSD

.. code-block:: pycon

    >>> from rdflib import OWL
    >>> OWL.seeAlso
    rdflib.term.URIRef(u'http://www.w3.org/2002/07/owl#seeAlso')

"""
)
예제 #15
0
class N3RuleStore(Store):
    doc = """
    A specialized Store which maintains order of statements
    and creates N3Filters, Rules, Formula objects, and other facts
    Ensures builtin filters refer to variables that have preceded

    >>> s = N3RuleStore()
    >>> g = Graph(s)
    >>> src = \"\"\"
    ... @prefix : <http://metacognition.info/FuXi/test#>.
    ... @prefix str:   <http://www.w3.org/2000/10/swap/string#>.
    ... @prefix math: <http://www.w3.org/2000/10/swap/math#>.
    ... @prefix log:   <http://www.w3.org/2000/10/swap/log#>.
    ... @prefix m: <http://metacognition.info/FuXi/test#>.
    ... @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.
    ... @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>.
    ... @prefix owl: <http://www.w3.org/2002/07/owl#>.
    ... m:a a rdfs:Class;
    ...    m:prop1 1;
    ...    m:prop2 4.
    ... m:b a owl:Class;
    ...    m:prop1 2;
    ...    m:prop2 4, 1, 5.
    ... (1 2) :relatedTo (3 4).
    ... { ?X a owl:Class. ?X :prop1 ?M. ?X :prop2 ?N. ?N math:equalTo 3 } => { [] :selected (?M ?N) }.\"\"\"
    >>> g = g.parse(data=src, format='n3')
    >>> s._finalize()
    >>> len([pred for subj, pred, obj in s.facts if pred == %(u)s'http://metacognition.info/FuXi/test#relatedTo']) #doctest: +SKIP
    1
    >>> len(s.rules)
    1
    >>> print(len(s.rules[0][RULE_LHS]))
    4
    >>> print(len(s.rules[0][RULE_RHS]))
    5
    >>> print(s.rules[0][RULE_LHS][1])
    (rdflib.term.Variable(%(u)s'X'), rdflib.term.URIRef(%(u)s'http://metacognition.info/FuXi/test#prop1'), rdflib.term.Variable(%(u)s'M'))
    >>> print(s.rules[0][RULE_LHS][-1])
    <http://www.w3.org/2000/10/swap/math#equalTo>(?N, 3)

Description Rule Patterns Compilation
    >>> s = N3RuleStore()
    >>> g = Graph(s)
    >>> src = \"\"\"
    ... @prefix math: <http://www.w3.org/2000/10/swap/math#>.
    ... @prefix : <http://metacognition.info/FuXi/test#>.
    ... @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.
    ... @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>.
    ... @prefix owl: <http://www.w3.org/2002/07/owl#>.
    ... { ?S a [ rdfs:subClassOf ?C ] } => { ?S a ?C }.\"\"\"
    >>> g = g.parse(data=src, format='n3')
    >>> s._finalize()
    >>> assert s.rules
    >>> assert [pattern for pattern in s.rules[0][RULE_LHS] if isinstance(pattern, tuple) and [term for term in pattern if isinstance(term, BNode) ]], repr(s.rules[0][RULE_LHS])


Test single fact with collection

    >>> s = N3RuleStore()
    >>> g = Graph(s)
    >>> src = \"\"\"
    ... @prefix math: <http://www.w3.org/2000/10/swap/math#>.
    ... @prefix : <http://metacognition.info/FuXi/test#>.
    ... @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.
    ... @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>.
    ... @prefix owl: <http://www.w3.org/2002/07/owl#>.
    ... (1 2) :relatedTo owl:Class.\"\"\"
    >>> g = g.parse(data=src, format='n3')
    >>> s._finalize()
    >>> print(len(s.facts))
    5

RHS can only include RDF triples

    >>> s = N3RuleStore()
    >>> g = Graph(s)
    >>> src = \"\"\"
    ... @prefix math: <http://www.w3.org/2000/10/swap/math#>.
    ... @prefix : <http://metacognition.info/FuXi/test#>.
    ... @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.
    ... @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>.
    ... @prefix owl: <http://www.w3.org/2002/07/owl#>.
    ... {} => { 3 math:lessThan 2}.\"\"\"
    >>> g = g.parse(data=src, format='n3')
    >>> try:
    ...   s._finalize()
    ... except Exception as e:
    ...   print(e)
    Rule RHS must only include RDF triples (<http://www.w3.org/2000/10/swap/math#lessThan>(3, 2))

BuiltIn used out of order

    >>> s = N3RuleStore()
    >>> g = Graph(s)
    >>> src = \"\"\"
    ... @prefix math: <http://www.w3.org/2000/10/swap/math#>.
    ... @prefix : <http://metacognition.info/FuXi/test#>.
    ... { ?M math:lessThan ?Z.  ?R :value ?M; :value2 ?Z} => { ?R a :Selected.  }.\"\"\"
    >>> try:
    ...   g = g.parse(data=src, format='n3')
    ... except Exception as e:
    ...   print(e)  #doctest: +SKIP
    Builtin refers to variables without previous reference (<http://www.w3.org/2000/10/swap/math#lessThan>(?M, ?Z))

    Empty LHS & RHS
    >>> s = N3RuleStore()
    >>> g = Graph(s)
    >>> src = \"\"\"
    ... @prefix math: <http://www.w3.org/2000/10/swap/math#>.
    ... @prefix : <http://metacognition.info/FuXi/test#>.
    ... @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.
    ... @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>.
    ... @prefix owl: <http://www.w3.org/2002/07/owl#>.
    ... {} => {rdf:nil :allClasses ?C}.
    ... {?C owl:oneOf ?L. ?X a ?C. ?L :notItem ?X} => {}.\"\"\"
    >>> g = g.parse(data=src, format='n3')
    >>> len(s.formulae)
    2
    >>> s._finalize()
    >>> len(s.rules[0][0])
    0
    >>> len(s.rules[1][-1])
    0
    """

    __doc__ = py3compat.format_doctest_out(doc)

    context_aware = True
    formula_aware = True

    def __init__(self, identifier=None, additionalBuiltins=None):
        self.formulae = {}
        self.facts = []
        self.rootFormula = None
        self._lists = {}
        self.currentList = None
        self._listBuffer = []
        self.rules = []
        self.referencedVariables = set()
        self.nsMgr = {
            'skolem':
            URIRef('http://code.google.com/p/python-dlp/wiki/SkolemTerm#')
        }
        # or https://code.google.com/archive/p/python-dlp/wikis/SkolemTerm.wiki
        self.filters = {}
        self.filters.update(FILTERS)
        if additionalBuiltins:
            self.filters.update(additionalBuiltins)

    def namespace(self, prefix):
        return self.nsMgr.get(prefix)

    def bind(self, prefix, namespace, override=True):
        if override or prefix not in self.nsMgr:
            self.nsMgr[prefix] = namespace

    def prefix(self, namespace):
        return dict([(v, k)
                     for k, v in list(self.nsMgr.items())]).get(namespace)

    def _unrollList(self, l, listName):
        listTriples = []
        lastItemName = None
        for linkItem in l:
            linkName = l.index(linkItem) == 0 and listName or BNode()
            if lastItemName:
                listTriples.append((lastItemName, RDF.rest, linkName))
            listTriples.append((linkName, RDF.first, linkItem))
            lastItemName = linkName
        listTriples.append((lastItemName, RDF.rest, RDF.nil))
        return listTriples

    def _finalize(self):
        def unrollFunc(left, right):
            leftListsToUnroll = []
            rightListsToUnroll = []
            if isinstance(left, tuple):
                s, p, o = left
                leftListsToUnroll = [
                    term for term in [s, o] if term in self._lists
                ]
                if leftListsToUnroll:
                    leftListsToUnroll = reduce(lambda x, y: x + y, [
                        self._unrollList(self._lists[l], l)
                        for l in leftListsToUnroll
                    ])
                left = [left]
            elif isinstance(left, N3Builtin):
                left = [left]
            if isinstance(right, tuple):
                s, p, o = right
                rightListsToUnroll = [
                    term for term in [s, o] if term in self._lists
                ]
                if rightListsToUnroll:
                    rightListsToUnroll = reduce(lambda x, y: x + y, [
                        self._unrollList(self._lists[l], l)
                        for l in rightListsToUnroll
                    ])
                right = [right]
            elif isinstance(right, N3Builtin):
                right = [right]
            return left + leftListsToUnroll + right + rightListsToUnroll

        if len(self.facts) == 1:
            s, p, o = self.facts[0]
            listsToUnroll = [term for term in [s, o] if term in self._lists]
            if listsToUnroll:
                self.facts.extend(
                    reduce(lambda x, y: x + y, [
                        self._unrollList(self._lists[l], l)
                        for l in listsToUnroll
                    ]))
        elif self.facts:
            self.facts = reduce(unrollFunc, self.facts)
        for formula in list(self.formulae.values()):
            if len(formula) == 1:
                if isinstance(formula[0], tuple):
                    s, p, o = formula[0]
                    listsToUnroll = [
                        term for term in [s, o] if term in self._lists
                    ]
                    if listsToUnroll:
                        listTriples = reduce(lambda x, y: x + y, [
                            self._unrollList(self._lists[l], l)
                            for l in listsToUnroll
                        ])
                        formula.extend(listTriples)
            elif len(formula):
                formula.triples = reduce(unrollFunc, [i for i in formula])
        for lhs, rhs in self.rules:
            for item in self.formulae.get(rhs, []):
                assert isinstance(item, tuple), \
                    "Rule RHS must only include RDF triples (%s)" % item
        self.rules = [(self.formulae.get(lhs, Formula(lhs)),
                       self.formulae.get(rhs, Formula(rhs)))
                      for lhs, rhs in self.rules]

    def _checkVariableReferences(self, referencedVariables, terms, funcObj):
        for term in [i for i in terms if isinstance(i, Variable)]:
            if term not in referencedVariables:
                raise Exception(
                    "Builtin refers to variables without previous reference (%s)"
                    % funcObj)

    def add(self, triple, context=None, quoted=False):
        (subject, predicate, obj) = triple
        if predicate == RDF.first and not isinstance(
                subject, Variable) and not isinstance(object, Variable):
            if not self.currentList:
                self._listBuffer.append(obj)
                self.currentList = subject
            else:
                self._listBuffer.append(obj)
        elif predicate == RDF.rest and not isinstance(
                subject, Variable) and not isinstance(object, Variable):
            if obj == RDF.nil:
                self._lists[self.currentList] = [
                    item for item in self._listBuffer
                ]
                self._listBuffer = []
                self.currentList = None
        elif not isinstance(context, QuotedGraph):
            if not self.rootFormula:
                self.rootFormula = context.identifier
            if predicate == LOG.implies:
                self.rules.append(
                    (isinstance(subject, URIRef) and subject
                     or subject.identifier,
                     isinstance(obj,
                                (URIRef, Literal)) and obj or obj.identifier
                     if hasattr(obj, 'identifier') else str(obj)))
            else:
                self.facts.append((subject, predicate, obj))
        else:
            formula = self.formulae.get(context.identifier,
                                        Formula(context.identifier))
            if predicate in self.filters:
                newFilter = N3Builtin(predicate,
                                      self.filters[predicate](subject, obj),
                                      subject, obj)
                # @attention: The non-deterministic parse order of an RDF graph makes this
                # check hard to enforce
                # self._checkVariableReferences(self.referencedVariables, [subject, obj], newFilter)
                formula.append(newFilter)
            else:
                # print("(%s, %s, %s) pattern in %s"%(subject, predicate, obj, context.identifier))
                variables = [
                    arg for arg in [subject, predicate, obj]
                    if isinstance(arg, Variable)
                ]
                self.referencedVariables.update(variables)
                formula.append((subject, predicate, obj))
            self.formulae[context.identifier] = formula

    def __repr__(self):
        return ""

    def __len__(self, context=None):
        return 0

    def optimizeRules(self):
        patternDict = {}
        for lhs, rhs in self.rules:
            for pattern in lhs:
                if not isinstance(pattern, N3Builtin):
                    _hashList = [
                        isinstance(term, (Variable, BNode)) and '\t' or term
                        for term in pattern
                    ]
                    patternDict.setdefault(
                        reduce(lambda x, y: x + y, _hashList),
                        set()).add(pattern)
        for key, vals in list(patternDict.items()):
            if len(vals) > 1:
                print("###### Similar Patterns ######")
                for val in vals:
                    print(val)
                print("##############################")
예제 #16
0
파일: describer.py 프로젝트: ccolonna/R2R
__doc__ = py3compat.format_doctest_out("""
A Describer is a stateful utility for creating RDF statements in a
semi-declarative manner. It has methods for creating literal values, rel and
rev resource relations (somewhat resembling RDFa).

The `rel` and ``rev`` methods return a context manager which sets the current
about to the referenced resource for the context scope (for use with the
``with`` statement).

Full example in the ``to_rdf`` method below::

    >>> import datetime
    >>> from rdflib.graph import Graph
    >>> from rdflib.namespace import Namespace, RDFS, FOAF
    >>>
    >>> ORG_URI = "http://example.org/"
    >>>
    >>> CV = Namespace("http://purl.org/captsolo/resume-rdf/0.2/cv#")
    >>>
    >>> class Person(object):
    ...     def __init__(self):
    ...         self.first_name = %(u)s"Some"
    ...         self.last_name = %(u)s"Body"
    ...         self.username = "******"
    ...         self.presentation = %(u)s"Just a Python & RDF hacker."
    ...         self.image = "/images/persons/" + self.username + ".jpg"
    ...         self.site = "http://example.net/"
    ...         self.start_date = datetime.date(2009, 9, 4)
    ...     def get_full_name(self):
    ...         return %(u)s" ".join([self.first_name, self.last_name])
    ...     def get_absolute_url(self):
    ...         return "/persons/" + self.username
    ...     def get_thumbnail_url(self):
    ...         return self.image.replace('.jpg', '-thumb.jpg')
    ...
    ...     def to_rdf(self):
    ...         graph = Graph()
    ...         graph.bind('foaf', FOAF)
    ...         graph.bind('cv', CV)
    ...         lang = 'en'
    ...         d = Describer(graph, base=ORG_URI)
    ...         d.about(self.get_absolute_url()+'#person')
    ...         d.rdftype(FOAF.Person)
    ...         d.value(FOAF.name, self.get_full_name())
    ...         d.value(FOAF.firstName, self.first_name)
    ...         d.value(FOAF.surname, self.last_name)
    ...         d.rel(FOAF.homepage, self.site)
    ...         d.value(RDFS.comment, self.presentation, lang=lang)
    ...         with d.rel(FOAF.depiction, self.image):
    ...             d.rdftype(FOAF.Image)
    ...             d.rel(FOAF.thumbnail, self.get_thumbnail_url())
    ...         with d.rev(CV.aboutPerson):
    ...             d.rdftype(CV.CV)
    ...             with d.rel(CV.hasWorkHistory):
    ...                 d.value(CV.startDate, self.start_date)
    ...                 d.rel(CV.employedIn, ORG_URI+"#company")
    ...         return graph
    ...
    >>> person_graph = Person().to_rdf()
    >>> expected = Graph().parse(data='''<?xml version="1.0" encoding="utf-8"?>
    ... <rdf:RDF
    ...   xmlns:foaf="http://xmlns.com/foaf/0.1/"
    ...   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    ...   xmlns:cv="http://purl.org/captsolo/resume-rdf/0.2/cv#"
    ...   xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#">
    ...   <foaf:Person rdf:about="http://example.org/persons/some1#person">
    ...     <foaf:name>Some Body</foaf:name>
    ...     <foaf:firstName>Some</foaf:firstName>
    ...     <foaf:surname>Body</foaf:surname>
    ...     <foaf:depiction>
    ...       <foaf:Image
    ...         rdf:about=
    ...             "http://example.org/images/persons/some1.jpg">
    ...         <foaf:thumbnail
    ...         rdf:resource=
    ...             "http://example.org/images/persons/some1-thumb.jpg"/>
    ...       </foaf:Image>
    ...     </foaf:depiction>
    ...     <rdfs:comment xml:lang="en">
    ...             Just a Python &amp; RDF hacker.
    ...     </rdfs:comment>
    ...     <foaf:homepage rdf:resource="http://example.net/"/>
    ...   </foaf:Person>
    ...   <cv:CV>
    ...     <cv:aboutPerson
    ...         rdf:resource="http://example.org/persons/some1#person">
    ...     </cv:aboutPerson>
    ...     <cv:hasWorkHistory>
    ...       <rdf:Description>
    ...         <cv:startDate
    ...             rdf:datatype="http://www.w3.org/2001/XMLSchema#date"
    ...             >2009-09-04</cv:startDate>
    ...         <cv:employedIn rdf:resource="http://example.org/#company"/>
    ...       </rdf:Description>
    ...     </cv:hasWorkHistory>
    ...   </cv:CV>
    ... </rdf:RDF>
    ... ''')
    >>>
    >>> from rdflib.compare import isomorphic
    >>> isomorphic(person_graph, expected)  #doctest: +SKIP
    True
""")