diff options
Diffstat (limited to 'creactistore/_templates/lib/rdflib/graph.py')
-rw-r--r-- | creactistore/_templates/lib/rdflib/graph.py | 1486 |
1 files changed, 0 insertions, 1486 deletions
diff --git a/creactistore/_templates/lib/rdflib/graph.py b/creactistore/_templates/lib/rdflib/graph.py deleted file mode 100644 index 638a9e2..0000000 --- a/creactistore/_templates/lib/rdflib/graph.py +++ /dev/null @@ -1,1486 +0,0 @@ -"""Instantiating Graphs with default store (IOMemory) and default identifier -(a BNode): - - >>> g = Graph() - >>> g.store.__class__ - <class 'rdflib.plugins.memory.IOMemory'> - >>> g.identifier.__class__ - <class 'rdflib.term.BNode'> - -Instantiating Graphs with a specific kind of store (IOMemory) and a default -identifier (a BNode): - -Other store kinds: Sleepycat, MySQL, SQLite - - >>> store = plugin.get('IOMemory', Store)() - >>> store.__class__.__name__ - 'IOMemory' - >>> graph = Graph(store) - >>> graph.store.__class__ - <class 'rdflib.plugins.memory.IOMemory'> - -Instantiating Graphs with Sleepycat store and an identifier - -<http://rdflib.net>: - - >>> g = Graph('IOMemory', URIRef("http://rdflib.net")) - >>> g.identifier - rdflib.term.URIRef('http://rdflib.net') - >>> str(g) - "<http://rdflib.net> a rdfg:Graph;rdflib:storage [a rdflib:Store;rdfs:label 'IOMemory']." - -Creating a ConjunctiveGraph - The top level container for all named Graphs -in a 'database': - - >>> g = ConjunctiveGraph() - >>> str(g.default_context) - "[a rdfg:Graph;rdflib:storage [a rdflib:Store;rdfs:label 'IOMemory']]." - -Adding / removing reified triples to Graph and iterating over it directly or -via triple pattern: - - >>> g = Graph('IOMemory') - >>> statementId = BNode() - >>> print(len(g)) - 0 - >>> g.add((statementId, RDF.type, RDF.Statement)) - >>> g.add((statementId, RDF.subject, URIRef('http://rdflib.net/store/ConjunctiveGraph'))) - >>> g.add((statementId, RDF.predicate, RDFS.label)) - >>> g.add((statementId, RDF.object, Literal("Conjunctive Graph"))) - >>> print(len(g)) - 4 - >>> for s, p, o in g: - ... print(type(s)) - ... - <class 'rdflib.term.BNode'> - <class 'rdflib.term.BNode'> - <class 'rdflib.term.BNode'> - <class 'rdflib.term.BNode'> - - >>> for s, p, o in g.triples((None, RDF.object, None)): - ... print(o) - ... - Conjunctive Graph - >>> g.remove((statementId, RDF.type, RDF.Statement)) - >>> print(len(g)) - 3 - -``None`` terms in calls to :meth:`~rdflib.graph.Graph.triples` can be thought of as "open variables". - -Graph Aggregation - ConjunctiveGraphs and ReadOnlyGraphAggregate within -the same store: - - >>> store = plugin.get('IOMemory', Store)() - >>> g1 = Graph(store) - >>> g2 = Graph(store) - >>> g3 = Graph(store) - >>> stmt1 = BNode() - >>> stmt2 = BNode() - >>> stmt3 = BNode() - >>> g1.add((stmt1, RDF.type, RDF.Statement)) - >>> g1.add((stmt1, RDF.subject, URIRef('http://rdflib.net/store/ConjunctiveGraph'))) - >>> g1.add((stmt1, RDF.predicate, RDFS.label)) - >>> g1.add((stmt1, RDF.object, Literal("Conjunctive Graph"))) - >>> g2.add((stmt2, RDF.type, RDF.Statement)) - >>> g2.add((stmt2, RDF.subject, URIRef('http://rdflib.net/store/ConjunctiveGraph'))) - >>> g2.add((stmt2, RDF.predicate, RDF.type)) - >>> g2.add((stmt2, RDF.object, RDFS.Class)) - >>> g3.add((stmt3, RDF.type, RDF.Statement)) - >>> g3.add((stmt3, RDF.subject, URIRef('http://rdflib.net/store/ConjunctiveGraph'))) - >>> g3.add((stmt3, RDF.predicate, RDFS.comment)) - >>> g3.add((stmt3, RDF.object, Literal("The top-level aggregate graph - The sum of all named graphs within a Store"))) - >>> len(list(ConjunctiveGraph(store).subjects(RDF.type, RDF.Statement))) - 3 - >>> len(list(ReadOnlyGraphAggregate([g1,g2]).subjects(RDF.type, RDF.Statement))) - 2 - -ConjunctiveGraphs have a :meth:`~rdflib.graph.ConjunctiveGraph.quads` method which returns quads instead of -triples, where the fourth item is the Graph (or subclass thereof) instance -in which the triple was asserted: - - >>> uniqueGraphNames = set([graph.identifier for s, p, o, graph in ConjunctiveGraph(store).quads((None, RDF.predicate, None))]) - >>> len(uniqueGraphNames) - 3 - >>> unionGraph = ReadOnlyGraphAggregate([g1, g2]) - >>> uniqueGraphNames = set([graph.identifier for s, p, o, graph in unionGraph.quads((None, RDF.predicate, None))]) - >>> len(uniqueGraphNames) - 2 - -Parsing N3 from StringIO - - >>> from StringIO import StringIO - >>> g2 = Graph() - >>> src = ''' - ... @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> . - ... @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . - ... [ a rdf:Statement ; - ... rdf:subject <http://rdflib.net/store#ConjunctiveGraph>; - ... rdf:predicate rdfs:label; - ... rdf:object "Conjunctive Graph" ] . - ... ''' - >>> g2 = g2.parse(StringIO(src), format='n3') - >>> print(len(g2)) - 4 - -Using Namespace class: - - >>> RDFLib = Namespace('http://rdflib.net') - >>> RDFLib.ConjunctiveGraph - rdflib.term.URIRef('http://rdflib.netConjunctiveGraph') - >>> RDFLib['Graph'] - rdflib.term.URIRef('http://rdflib.netGraph') - -""" - -from __future__ import generators - -import logging -_logger = logging.getLogger(__name__) - -#import md5 -import random -import warnings - -try: - from hashlib import md5 -except ImportError: - from md5 import md5 - -try: - from io import BytesIO -except ImportError: - try: - from cStringIO import StringIO as BytesIO - except ImportError: - from StringIO import StringIO as BytesIO - -# # Can't use this approach any longer, this function will raise an ImportError -# # because the sparql module has been moved to the RDFExtras package. - -# def describe(terms,bindings,graph): -# """ -# Default DESCRIBE returns all incomming and outgoing statements about the given terms -# """ -# from rdflib.sparql.sparqlOperators import getValue -# g=Graph() -# terms=[getValue(i)(bindings) for i in terms] -# for s,p,o in graph.triples_choices((terms,None,None)): -# g.add((s,p,o)) -# for s,p,o in graph.triples_choices((None,None,terms)): -# g.add((s,p,o)) -# return g - -from rdflib.namespace import RDF, RDFS, SKOS - -from rdflib import plugin, exceptions, query -#, sparql - -from rdflib.term import Node -from rdflib.term import URIRef -from rdflib.term import BNode -from rdflib.term import Literal # required for doctests -from rdflib.namespace import Namespace # required for doctests -from rdflib.store import Store -from rdflib.serializer import Serializer -from rdflib.parser import Parser -from rdflib.parser import create_input_source -from rdflib.namespace import NamespaceManager -from rdflib.resource import Resource -from rdflib import py3compat -b = py3compat.b - -import tempfile, shutil, os -from urlparse import urlparse - -__all__ = ['Graph', 'ConjunctiveGraph', 'QuotedGraph', 'GraphValue', 'Seq', 'BackwardCompatGraph', 'ModificationException', 'UnSupportedAggregateOperation', 'ReadOnlyGraphAggregate'] - -class Graph(Node): - """An RDF Graph - - The constructor accepts one argument, the 'store' - that will be used to store the graph data (see the 'store' - package for stores currently shipped with rdflib). - - Stores can be context-aware or unaware. Unaware stores take up - (some) less space but cannot support features that require - context, such as true merging/demerging of sub-graphs and - provenance. - - The Graph constructor can take an identifier which identifies the Graph - by name. If none is given, the graph is assigned a BNode for its - identifier. - For more on named graphs, see: http://www.w3.org/2004/03/trix/ - - Ontology for __str__ provenance terms:: - - @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> . - @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . - @prefix : <http://rdflib.net/store#> . - @prefix rdfg: <http://www.w3.org/2004/03/trix/rdfg-1/>. - @prefix owl: <http://www.w3.org/2002/07/owl#>. - @prefix log: <http://www.w3.org/2000/10/swap/log#>. - @prefix xsd: <http://www.w3.org/2001/XMLSchema#>. - - :Store a owl:Class; - rdfs:subClassOf <http://xmlns.com/wordnet/1.6/Electronic_database>; - rdfs:subClassOf - [a owl:Restriction; - owl:onProperty rdfs:label; - owl:allValuesFrom [a owl:DataRange; - owl:oneOf ("IOMemory" - "Sleepcat" - "MySQL" - "Redland" - "REGEXMatching" - "ZODB" - "AuditableStorage" - "Memory")] - ]. - - :ConjunctiveGraph a owl:Class; - rdfs:subClassOf rdfg:Graph; - rdfs:label "The top-level graph within the store - the union of all the Graphs within." - rdfs:seeAlso <http://rdflib.net/rdf_store/#ConjunctiveGraph>. - - :DefaultGraph a owl:Class; - rdfs:subClassOf rdfg:Graph; - rdfs:label "The 'default' subgraph of a conjunctive graph". - - - :identifier a owl:Datatypeproperty; - rdfs:label "The store-associated identifier of the formula. ". - rdfs:domain log:Formula - rdfs:range xsd:anyURI; - - :storage a owl:ObjectProperty; - rdfs:domain [ - a owl:Class; - owl:unionOf (log:Formula rdfg:Graph :ConjunctiveGraph) - ]; - rdfs:range :Store. - - :default_context a owl:FunctionalProperty; - rdfs:label "The default context for a conjunctive graph"; - rdfs:domain :ConjunctiveGraph; - rdfs:range :DefaultGraph. - - - {?cg a :ConjunctiveGraph;:storage ?store} - => {?cg owl:sameAs ?store}. - - {?subGraph rdfg:subGraphOf ?cg;a :DefaultGraph} - => {?cg a :ConjunctiveGraph;:default_context ?subGraphOf} . - - """ - - def __init__(self, store='default', identifier=None, - namespace_manager=None): - super(Graph, self).__init__() - self.__identifier = identifier or BNode() - if not isinstance(store, Store): - # TODO: error handling - self.__store = store = plugin.get(store, Store)() - else: - self.__store = store - self.__namespace_manager = namespace_manager - self.context_aware = False - self.formula_aware = False - - def __get_store(self): - return self.__store - store = property(__get_store) - - def __get_identifier(self): - return self.__identifier - identifier = property(__get_identifier) - - def _get_namespace_manager(self): - if self.__namespace_manager is None: - self.__namespace_manager = NamespaceManager(self) - return self.__namespace_manager - - def _set_namespace_manager(self, nm): - self.__namespace_manager = nm - namespace_manager = property(_get_namespace_manager, _set_namespace_manager) - - def __repr__(self): - return "<Graph identifier=%s (%s)>" % (self.identifier, type(self)) - - def __str__(self): - if isinstance(self.identifier,URIRef): - return "%s a rdfg:Graph;rdflib:storage [a rdflib:Store;rdfs:label '%s']."%(self.identifier.n3(),self.store.__class__.__name__) - else: - return "[a rdfg:Graph;rdflib:storage [a rdflib:Store;rdfs:label '%s']]."%(self.store.__class__.__name__) - - def destroy(self, configuration): - """Destroy the store identified by `configuration` if supported""" - self.__store.destroy(configuration) - - #Transactional interfaces (optional) - def commit(self): - """Commits active transactions""" - self.__store.commit() - - def rollback(self): - """Rollback active transactions""" - self.__store.rollback() - - def open(self, configuration, create=False): - """Open the graph store - - Might be necessary for stores that require opening a connection to a - database or acquiring some resource. - """ - return self.__store.open(configuration, create) - - def close(self, commit_pending_transaction=False): - """Close the graph store - - Might be necessary for stores that require closing a connection to a - database or releasing some resource. - """ - self.__store.close(commit_pending_transaction=commit_pending_transaction) - - def add(self, (s, p, o)): - """Add a triple with self as context""" - self.__store.add((s, p, o), self, quoted=False) - - def addN(self, quads): - """Add a sequence of triple with context""" - self.__store.addN([(s, p, o, c) for s, p, o, c in quads - if isinstance(c, Graph) - and c.identifier is self.identifier]) - - def remove(self, (s, p, o)): - """Remove a triple from the graph - - If the triple does not provide a context attribute, removes the triple - from all contexts. - """ - self.__store.remove((s, p, o), context=self) - - def triples(self, (s, p, o)): - """Generator over the triple store - - Returns triples that match the given triple pattern. If triple pattern - does not provide a context, all contexts will be searched. - """ - for (s, p, o), cg in self.__store.triples((s, p, o), context=self): - yield (s, p, o) - - def __len__(self): - """Returns the number of triples in the graph - - If context is specified then the number of triples in the context is - returned instead. - """ - return self.__store.__len__(context=self) - - def __iter__(self): - """Iterates over all triples in the store""" - return self.triples((None, None, None)) - - def __contains__(self, triple): - """Support for 'triple in graph' syntax""" - for triple in self.triples(triple): - return True - return False - - def __hash__(self): - return hash(self.identifier) - - def md5_term_hash(self): - d = md5(str(self.identifier)) - d.update("G") - return d.hexdigest() - - def __cmp__(self, other): - if other is None: - return -1 - elif isinstance(other, Graph): - return cmp(self.identifier, other.identifier) - else: - #Note if None is considered equivalent to owl:Nothing - #Then perhaps a graph with length 0 should be considered - #equivalent to None (if compared to it)? - return 1 - - def __eq__(self, other): - return isinstance(other, Graph) and self.identifier == other.identifier - - def __lt__(self, other): - return (other is None) or (isinstance(other, Graph) and \ - self.identifier < other.identifier) - def __le__(self, other): return self < other or self == other - - def __gt__(self, other): - return (isinstance(other, Graph) and self.identifier > other.identifier) \ - or (other is not None) - def __ge__(self, other): return self > other or self == other - - def __iadd__(self, other): - """Add all triples in Graph other to Graph""" - for triple in other: - self.add(triple) - return self - - def __isub__(self, other): - """Subtract all triples in Graph other from Graph""" - for triple in other: - self.remove(triple) - return self - - def __add__(self,other) : - """Set-theoretic union""" - retval = Graph() - for x in self: - retval.add(x) - for y in other: - retval.add(y) - return retval - - def __mul__(self,other) : - """Set-theoretic intersection""" - retval = Graph() - for x in other: - if x in self: - retval.add(x) - return retval - - def __sub__(self,other) : - """Set-theoretic difference""" - retval = Graph() - for x in self: - if not x in other : - retval.add(x) - return retval - - def __xor__(self,other): - """Set-theoretic XOR""" - return (self - other) + (other - self) - - __or__ = __add__ - __and__ = __mul__ - - # Conv. methods - - def set(self, (subject, predicate, object)): - """Convenience method to update the value of object - - Remove any existing triples for subject and predicate before adding - (subject, predicate, object). - """ - self.remove((subject, predicate, None)) - self.add((subject, predicate, object)) - - def subjects(self, predicate=None, object=None): - """A generator of subjects with the given predicate and object""" - for s, p, o in self.triples((None, predicate, object)): - yield s - - def predicates(self, subject=None, object=None): - """A generator of predicates with the given subject and object""" - for s, p, o in self.triples((subject, None, object)): - yield p - - def objects(self, subject=None, predicate=None): - """A generator of objects with the given subject and predicate""" - for s, p, o in self.triples((subject, predicate, None)): - yield o - - def subject_predicates(self, object=None): - """A generator of (subject, predicate) tuples for the given object""" - for s, p, o in self.triples((None, None, object)): - yield s, p - - def subject_objects(self, predicate=None): - """A generator of (subject, object) tuples for the given predicate""" - for s, p, o in self.triples((None, predicate, None)): - yield s, o - - def predicate_objects(self, subject=None): - """A generator of (predicate, object) tuples for the given subject""" - for s, p, o in self.triples((subject, None, None)): - yield p, o - - def triples_choices(self, (subject, predicate, object_),context=None): - for (s, p, o), cg in self.store.triples_choices( - (subject, predicate, object_), context=self): - yield (s, p, o) - - def value(self, subject=None, predicate=RDF.value, object=None, - default=None, any=True): - """Get a value for a pair of two criteria - - Exactly one of subject, predicate, object must be None. Useful if one - knows that there may only be one value. - - It is one of those situations that occur a lot, hence this - 'macro' like utility - - Parameters: - subject, predicate, object -- exactly one must be None - default -- value to be returned if no values found - any -- if True, return any value in the case there is more than one, - else, raise UniquenessError - """ - retval = default - - if (subject is None and predicate is None) or \ - (subject is None and object is None) or \ - (predicate is None and object is None): - return None - - if object is None: - values = self.objects(subject, predicate) - if subject is None: - values = self.subjects(predicate, object) - if predicate is None: - values = self.predicates(subject, object) - - try: - retval = values.next() - except StopIteration, e: - retval = default - else: - if any is False: - try: - values.next() - msg = ("While trying to find a value for (%s, %s, %s) the" - " following multiple values where found:\n" % - (subject, predicate, object)) - triples = self.store.triples( - (subject, predicate, object), None) - for (s, p, o), contexts in triples: - msg += "(%s, %s, %s)\n (contexts: %s)\n" % ( - s, p, o, list(contexts)) - raise exceptions.UniquenessError(msg) - except StopIteration, e: - pass - return retval - - def label(self, subject, default=''): - """Query for the RDFS.label of the subject - - Return default if no label exists - """ - if subject is None: - return default - return self.value(subject, RDFS.label, default=default, any=True) - - @py3compat.format_doctest_out - def preferredLabel(self, subject, lang=None, default=[], - labelProperties=(SKOS.prefLabel, RDFS.label)): - """ Find the preferred label for subject. - - By default prefers skos:prefLabels over rdfs:labels. In case at least - one prefLabel is found returns those, else returns labels. In case a - language string (e.g., 'en', 'de' or even '' for no lang-tagged - literals) is given, only such labels will be considered. - - Return a list of (labelProp, label) pairs, where labelProp is either - skos:prefLabel or rdfs:label. - - >>> g = ConjunctiveGraph() - >>> u = URIRef('http://example.com/foo') - >>> g.add([u, RDFS.label, Literal('foo')]) - >>> g.add([u, RDFS.label, Literal('bar')]) - >>> sorted(g.preferredLabel(u)) #doctest: +NORMALIZE_WHITESPACE - [(rdflib.term.URIRef('http://www.w3.org/2000/01/rdf-schema#label'), - rdflib.term.Literal(%(u)s'bar')), - (rdflib.term.URIRef('http://www.w3.org/2000/01/rdf-schema#label'), - rdflib.term.Literal(%(u)s'foo'))] - >>> g.add([u, SKOS.prefLabel, Literal('bla')]) - >>> g.preferredLabel(u) #doctest: +NORMALIZE_WHITESPACE - [(rdflib.term.URIRef('http://www.w3.org/2004/02/skos/core#prefLabel'), - rdflib.term.Literal(%(u)s'bla'))] - >>> g.add([u, SKOS.prefLabel, Literal('blubb', lang='en')]) - >>> sorted(g.preferredLabel(u)) #doctest: +NORMALIZE_WHITESPACE - [(rdflib.term.URIRef('http://www.w3.org/2004/02/skos/core#prefLabel'), - rdflib.term.Literal(%(u)s'blubb', lang='en')), - (rdflib.term.URIRef('http://www.w3.org/2004/02/skos/core#prefLabel'), - rdflib.term.Literal(%(u)s'bla'))] - >>> g.preferredLabel(u, lang='') #doctest: +NORMALIZE_WHITESPACE - [(rdflib.term.URIRef('http://www.w3.org/2004/02/skos/core#prefLabel'), - rdflib.term.Literal(%(u)s'bla'))] - >>> g.preferredLabel(u, lang='en') #doctest: +NORMALIZE_WHITESPACE - [(rdflib.term.URIRef('http://www.w3.org/2004/02/skos/core#prefLabel'), - rdflib.term.Literal(%(u)s'blubb', lang='en'))] - """ - - # setup the language filtering - if lang != None: - if lang == '': # we only want not language-tagged literals - langfilter = lambda l: l.language == None - else: - langfilter = lambda l: l.language == lang - else: # we don't care about language tags - langfilter = lambda l: True - - for labelProp in labelProperties: - labels = filter(langfilter, self.objects(subject, labelProp)) - if len(labels) == 0: - continue - else: - return [(labelProp, l) for l in labels] - return default - - def comment(self, subject, default=''): - """Query for the RDFS.comment of the subject - - Return default if no comment exists - """ - if subject is None: - return default - return self.value(subject, RDFS.comment, default=default, any=True) - - def items(self, list): - """Generator over all items in the resource specified by list - - list is an RDF collection. - """ - while list: - item = self.value(list, RDF.first) - if item: - yield item - list = self.value(list, RDF.rest) - - def transitiveClosure(self,func,arg): - """ - Generates transitive closure of a user-defined - function against the graph - - >>> from rdflib.collection import Collection - >>> 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)) - >>> def topList(node,g): - ... for s in g.subjects(RDF.rest,node): - ... yield s - >>> def reverseList(node,g): - ... for f in g.objects(node,RDF.first): - ... print(f) - ... for s in g.subjects(RDF.rest,node): - ... yield s - - >>> [rt for rt in g.transitiveClosure(topList,RDF.nil)] - [rdflib.term.BNode('baz'), rdflib.term.BNode('bar'), rdflib.term.BNode('foo')] - - >>> [rt for rt in g.transitiveClosure(reverseList,RDF.nil)] - http://www.w3.org/2000/01/rdf-schema#comment - http://www.w3.org/2000/01/rdf-schema#label - http://www.w3.org/1999/02/22-rdf-syntax-ns#type - [rdflib.term.BNode('baz'), rdflib.term.BNode('bar'), rdflib.term.BNode('foo')] - - """ - for rt in func(arg,self): - yield rt - for rt_2 in self.transitiveClosure(func,rt): - yield rt_2 - - def transitive_objects(self, subject, property, remember=None): - """Transitively generate objects for the ``property`` relationship - - Generated objects belong to the depth first transitive closure of the - ``property`` relationship starting at ``subject``. - """ - if remember is None: - remember = {} - if subject in remember: - return - remember[subject] = 1 - yield subject - for object in self.objects(subject, property): - for o in self.transitive_objects(object, property, remember): - yield o - - def transitive_subjects(self, predicate, object, remember=None): - """Transitively generate objects for the ``property`` relationship - - Generated objects belong to the depth first transitive closure of the - ``property`` relationship starting at ``subject``. - """ - if remember is None: - remember = {} - if object in remember: - return - remember[object] = 1 - yield object - for subject in self.subjects(predicate, object): - for s in self.transitive_subjects(predicate, subject, remember): - yield s - - def seq(self, subject): - """Check if subject is an rdf:Seq - - If yes, it returns a Seq class instance, None otherwise. - """ - if (subject, RDF.type, RDF.Seq) in self: - return Seq(self, subject) - else: - return None - - def qname(self, uri): - return self.namespace_manager.qname(uri) - - def compute_qname(self, uri, generate=True): - return self.namespace_manager.compute_qname(uri, generate) - - def bind(self, prefix, namespace, override=True): - """Bind prefix to namespace - - If override is True will bind namespace to given prefix if namespace - was already bound to a different prefix. - """ - return self.namespace_manager.bind( - prefix, namespace, override=override) - - def namespaces(self): - """Generator over all the prefix, namespace tuples""" - for prefix, namespace in self.namespace_manager.namespaces(): - yield prefix, namespace - - def absolutize(self, uri, defrag=1): - """Turn uri into an absolute URI if it's not one already""" - return self.namespace_manager.absolutize(uri, defrag) - - def serialize( - self, destination=None, format="xml", - base=None, encoding=None, **args): - """Serialize the Graph to destination - - If destination is None serialize method returns the serialization as a - string. Format defaults to xml (AKA rdf/xml). - - Format support can be extended with plugins, - but 'xml', 'n3', 'turtle', 'nt', 'pretty-xml', trix' are built in. - """ - serializer = plugin.get(format, Serializer)(self) - if destination is None: - stream = BytesIO() - serializer.serialize(stream, base=base, encoding=encoding, **args) - return stream.getvalue() - if hasattr(destination, "write"): - stream = destination - serializer.serialize(stream, base=base, encoding=encoding, **args) - else: - location = destination - scheme, netloc, path, params, query, fragment = urlparse(location) - if netloc!="": - print("WARNING: not saving as location" + \ - "is not a local file reference") - return - fd, name = tempfile.mkstemp() - stream = os.fdopen(fd) - serializer.serialize(stream, base=base, encoding=encoding, **args) - stream.close() - if hasattr(shutil,"move"): - shutil.move(name, path) - else: - shutil.copy(name, path) - os.remove(name) - - def parse(self, source=None, publicID=None, format=None, - location=None, file=None, data=None, **args): - """ - Parse source adding the resulting triples to the Graph. - - The source is specified using one of source, location, file or - data. - - :Parameters: - - - `source`: An InputSource, file-like object, or string. In the case - of a string the string is the location of the source. - - `location`: A string indicating the relative or absolute URL of the - source. Graph's absolutize method is used if a relative location - is specified. - - `file`: A file-like object. - - `data`: A string containing the data to be parsed. - - `format`: Used if format can not be determined from source. - Defaults to rdf/xml. Format support can be extended with plugins, - but 'xml', 'n3', 'nt', 'trix', 'rdfa' are built in. - - `publicID`: the logical URI to use as the document base. If None - specified the document location is used (at least in the case where - there is a document location). - - :Returns: - - - self, the graph instance. - - Examples: - - >>> my_data = ''' - ... <rdf:RDF - ... xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#' - ... xmlns:rdfs='http://www.w3.org/2000/01/rdf-schema#' - ... > - ... <rdf:Description> - ... <rdfs:label>Example</rdfs:label> - ... <rdfs:comment>This is really just an example.</rdfs:comment> - ... </rdf:Description> - ... </rdf:RDF> - ... ''' - >>> import tempfile - >>> fd, file_name = tempfile.mkstemp() - >>> f = os.fdopen(fd, 'w') - >>> dummy = f.write(my_data) # Returns num bytes written on py3 - >>> f.close() - - >>> g = Graph() - >>> result = g.parse(data=my_data, format="application/rdf+xml") - >>> len(g) - 2 - - >>> g = Graph() - >>> result = g.parse(location=file_name, format="application/rdf+xml") - >>> len(g) - 2 - - >>> g = Graph() - >>> result = g.parse(file=open(file_name, "r"), format="application/rdf+xml") - >>> len(g) - 2 - - >>> os.remove(file_name) - - """ - - if format=="xml": - # warn... backward compat. - format = "application/rdf+xml" - source = create_input_source(source=source, publicID=publicID, - location=location, file=file, - data=data, format=format) - if format is None: - format = source.content_type - if format is None: - #raise Exception("Could not determine format for %r. You can" + \ - # "expicitly specify one with the format argument." % source) - format = "application/rdf+xml" - parser = plugin.get(format, Parser)() - parser.parse(source, self, **args) - return self - - def load(self, source, publicID=None, format="xml"): - self.parse(source, publicID, format) - - def query(self, query_object, processor='sparql', result='sparql', initNs={}, initBindings={}, use_store_provided=True, **kwargs): - """ - """ - - - - if hasattr(self.store, "query") and use_store_provided: - return self.store.query(self,query_object, initNs, initBindings, **kwargs) - - if not isinstance(result, query.Result): - result = plugin.get(result, query.Result) - if not isinstance(processor, query.Processor): - processor = plugin.get(processor, query.Processor)(self) - - return result(processor.query(query_object, initBindings, initNs, **kwargs)) - - - def n3(self): - """return an n3 identifier for the Graph""" - return "[%s]" % self.identifier.n3() - - def __reduce__(self): - return (Graph, (self.store, self.identifier,)) - - def isomorphic(self, other): - # TODO: this is only an approximation. - if len(self) != len(other): - return False - for s, p, o in self: - if not isinstance(s, BNode) and not isinstance(o, BNode): - if not (s, p, o) in other: - return False - for s, p, o in other: - if not isinstance(s, BNode) and not isinstance(o, BNode): - if not (s, p, o) in self: - return False - # TODO: very well could be a false positive at this point yet. - return True - - def connected(self): - """Check if the Graph is connected - - The Graph is considered undirectional. - - Performs a search on the Graph, starting from a random node. Then - iteratively goes depth-first through the triplets where the node is - subject and object. Return True if all nodes have been visited and - False if it cannot continue and there are still unvisited nodes left. - """ - all_nodes = list(self.all_nodes()) - discovered = [] - - # take a random one, could also always take the first one, doesn't - # really matter. - if not all_nodes: - return False - - visiting = [all_nodes[random.randrange(len(all_nodes))]] - while visiting: - x = visiting.pop() - if x not in discovered: - discovered.append(x) - for new_x in self.objects(subject=x): - if new_x not in discovered and new_x not in visiting: - visiting.append(new_x) - for new_x in self.subjects(object=x): - if new_x not in discovered and new_x not in visiting: - visiting.append(new_x) - - # optimisation by only considering length, since no new objects can - # be introduced anywhere. - if len(all_nodes) == len(discovered): - return True - else: - return False - - def all_nodes(self): - obj = set(self.objects()) - allNodes = obj.union(set(self.subjects())) - return allNodes - - def resource(self, identifier): - """Create a new ``Resource`` instance. - - Parameters: - - - ``identifier``: a URIRef or BNode instance. - - Example:: - - >>> graph = Graph() - >>> uri = URIRef("http://example.org/resource") - >>> resource = graph.resource(uri) - >>> assert isinstance(resource, Resource) - >>> assert resource.identifier is uri - >>> assert resource.graph is graph - - """ - return Resource(self, identifier) - - -class ConjunctiveGraph(Graph): - """ - A ConjunctiveGraph is an (unamed) aggregation of all the named graphs - within the Store. It has a ``default`` graph, whose name is associated - with the ConjunctiveGraph throughout its life. All methods work against - this default graph. Its constructor can take an identifier to use as the - name of this default graph or it will assign a BNode. - - In practice, it is typical to instantiate a ConjunctiveGraph if you want - to add triples to the Store but don't care to mint a URI for the graph. - Any triples in the graph can still be addressed. - """ - - def __init__(self, store='default', identifier=None): - super(ConjunctiveGraph, self).__init__(store) - assert self.store.context_aware, ("ConjunctiveGraph must be backed by" - " a context aware store.") - self.context_aware = True - self.default_context = Graph(store=self.store, - identifier=identifier or BNode()) - - def __str__(self): - pattern = ("[a rdflib:ConjunctiveGraph;rdflib:storage " - "[a rdflib:Store;rdfs:label '%s']]") - return pattern % self.store.__class__.__name__ - - def __contains__(self, triple_or_quad): - """Support for 'triple/quad in graph' syntax""" - context = None - if len(triple_or_quad) == 4: - context = triple_or_quad[3] - for t in self.triples(triple_or_quad[:3], context=context): - return True - return False - - def add(self, (s, p, o)): - """Add the triple to the default context""" - self.store.add((s, p, o), context=self.default_context, quoted=False) - - def addN(self, quads): - """Add a sequence of triples with context""" - self.store.addN([quad for quad in quads if quad not in self]) - - def remove(self, (s, p, o)): - """Removes from all its contexts""" - self.store.remove((s, p, o), context=None) - - def triples(self, (s, p, o), context=None): - """Iterate over all the triples in the entire conjunctive graph""" - for (s, p, o), cg in self.store.triples((s, p, o), context=context): - yield s, p, o - - def quads(self,(s,p,o)): - """Iterate over all the quads in the entire conjunctive graph""" - for (s, p, o), cg in self.store.triples((s, p, o), context=None): - for ctx in cg: - yield s, p, o, ctx - - def triples_choices(self, (s, p, o)): - """Iterate over all the triples in the entire conjunctive graph""" - for (s1, p1, o1), cg in self.store.triples_choices((s, p, o), - context=None): - yield (s1, p1, o1) - - def __len__(self): - """Number of triples in the entire conjunctive graph""" - return self.store.__len__() - - def contexts(self, triple=None): - """Iterate over all contexts in the graph - - If triple is specified, iterate over all contexts the triple is in. - """ - for context in self.store.contexts(triple): - if isinstance(context, Graph): - yield context - else: - yield self.get_context(context) - - def get_context(self, identifier, quoted=False): - """Return a context graph for the given identifier - - identifier must be a URIRef or BNode. - """ - return Graph(store=self.store, identifier=identifier, - namespace_manager=self) - - def remove_context(self, context): - """Removes the given context from the graph""" - self.store.remove((None, None, None), context) - - def context_id(self, uri, context_id=None): - """URI#context""" - uri = uri.split("#", 1)[0] - if context_id is None: - context_id = "#context" - return URIRef(context_id, base=uri) - - def parse(self, source=None, publicID=None, format="xml", - location=None, file=None, data=None, **args): - """ - Parse source adding the resulting triples to its own context - (sub graph of this graph). - - See :meth:`rdflib.graph.Graph.parse` for documentation on arguments. - - :Returns: - - The graph into which the source was parsed. In the case of n3 - it returns the root context. - """ - - source = create_input_source(source=source, publicID=publicID, - location=location, file=file, data=data, format=format) - - #id = self.context_id(self.absolutize(source.getPublicId())) - context = Graph(store=self.store, identifier= - publicID and URIRef(publicID) or source.getPublicId()) - context.remove((None, None, None)) - context.parse(source, publicID=publicID, format=format, - location=location, file=file, data=data, **args) - return context - - def __reduce__(self): - return (ConjunctiveGraph, (self.store, self.identifier)) - - -class QuotedGraph(Graph): - """ - Quoted Graphs are intended to implement Notation 3 formulae. They are - associated with a required identifier that the N3 parser *must* provide - in order to maintain consistent formulae identification for scenarios - such as implication and other such processing. - """ - def __init__(self, store, identifier): - super(QuotedGraph, self).__init__(store, identifier) - - def add(self, triple): - """Add a triple with self as context""" - self.store.add(triple, self, quoted=True) - - def addN(self,quads): - """Add a sequence of triple with context""" - self.store.addN([(s,p,o,c) for s,p,o,c in quads - if isinstance(c, QuotedGraph) - and c.identifier is self.identifier]) - - def n3(self): - """Return an n3 identifier for the Graph""" - return "{%s}" % self.identifier.n3() - - def __str__(self): - identifier = self.identifier.n3() - label = self.store.__class__.__name__ - pattern = ("{this rdflib.identifier %s;rdflib:storage " - "[a rdflib:Store;rdfs:label '%s']}") - return pattern % (identifier, label) - - def __reduce__(self): - return (QuotedGraph, (self.store, self.identifier)) - - -class GraphValue(QuotedGraph): - def __init__(self, store, identifier=None, graph=None): - if graph is not None: - assert identifier is None - np = store.node_pickler - identifier = md5() - s = list(graph.triples((None, None, None))) - s.sort() - for t in s: - identifier.update(b("^").join((np.dumps(i) for i in t))) - identifier = URIRef("data:%s" % identifier.hexdigest()) - super(GraphValue, self).__init__(store, identifier) - for t in graph: - store.add(t, context=self) - else: - super(GraphValue, self).__init__(store, identifier) - - - def add(self, triple): - raise Exception("not mutable") - - def remove(self, triple): - raise Exception("not mutable") - - def __reduce__(self): - return (GraphValue, (self.store, self.identifier,)) - - -class Seq(object): - """Wrapper around an RDF Seq resource - - It implements a container type in Python with the order of the items - returned corresponding to the Seq content. It is based on the natural - ordering of the predicate names _1, _2, _3, etc, which is the - 'implementation' of a sequence in RDF terms. - """ - - def __init__(self, graph, subject): - """Parameters: - - - graph: - the graph containing the Seq - - - subject: - the subject of a Seq. Note that the init does not - check whether this is a Seq, this is done in whoever - creates this instance! - """ - - _list = self._list = list() - LI_INDEX = URIRef(str(RDF) + "_") - for (p, o) in graph.predicate_objects(subject): - if p.startswith(LI_INDEX): #!= RDF.Seq: # - i = int(p.replace(LI_INDEX, '')) - _list.append((i, o)) - - # here is the trick: the predicates are _1, _2, _3, etc. Ie, - # by sorting the keys (by integer) we have what we want! - _list.sort() - - def __iter__(self): - """Generator over the items in the Seq""" - for _, item in self._list: - yield item - - def __len__(self): - """Length of the Seq""" - return len(self._list) - - def __getitem__(self, index): - """Item given by index from the Seq""" - index, item = self._list.__getitem__(index) - return item - - -class BackwardCompatGraph(ConjunctiveGraph): - - def __init__(self, backend='default'): - warnings.warn("Use ConjunctiveGraph instead. " - "( from rdflib.graph import ConjunctiveGraph )", - DeprecationWarning, stacklevel=2) - super(BackwardCompatGraph, self).__init__(store=backend) - - def __get_backend(self): - return self.store - backend = property(__get_backend) - - def open(self, configuration, create=True): - return ConjunctiveGraph.open(self, configuration, create) - - def add(self, (s, p, o), context=None): - """Add to to the given context or to the default context""" - if context is not None: - c = self.get_context(context) - assert c.identifier == context, "%s != %s" % \ - (c.identifier, context) - else: - c = self.default_context - self.store.add((s, p, o), context=c, quoted=False) - - def remove(self, (s, p, o), context=None): - """Remove from the given context or from the default context""" - if context is not None: - context = self.get_context(context) - self.store.remove((s, p, o), context) - - def triples(self, (s, p, o), context=None): - """Iterate over all the triples in the entire graph""" - if context is not None: - c = self.get_context(context) - assert c.identifier == context - else: - c = None - for (s, p, o), cg in self.store.triples((s, p, o), c): - yield (s, p, o) - - def __len__(self, context=None): - """Number of triples in the entire graph""" - if context is not None: - context = self.get_context(context) - return self.store.__len__(context) - - def get_context(self, identifier, quoted=False): - """Return a context graph for the given identifier - - identifier must be a URIRef or BNode. - """ - assert isinstance(identifier, URIRef) or \ - isinstance(identifier, BNode), type(identifier) - if quoted: - assert False - return QuotedGraph(self.store, identifier) - #return QuotedGraph(self.store, Graph(store=self.store, - # identifier=identifier)) - else: - return Graph(store=self.store, identifier=identifier, - namespace_manager=self) - #return Graph(self.store, Graph(store=self.store, - # identifier=identifier)) - - def remove_context(self, context): - """Remove the given context from the graph""" - self.store.remove((None, None, None), self.get_context(context)) - - def contexts(self, triple=None): - """Iterate over all contexts in the graph - - If triple is specified, iterate over all contexts the triple is in. - """ - for context in self.store.contexts(triple): - yield context.identifier - - def subjects(self, predicate=None, object=None, context=None): - """Generate subjects with the given predicate and object""" - for s, p, o in self.triples((None, predicate, object), context): - yield s - - def predicates(self, subject=None, object=None, context=None): - """Generate predicates with the given subject and object""" - for s, p, o in self.triples((subject, None, object), context): - yield p - - def objects(self, subject=None, predicate=None, context=None): - """Generate objects with the given subject and predicate""" - for s, p, o in self.triples((subject, predicate, None), context): - yield o - - def subject_predicates(self, object=None, context=None): - """Generate (subject, predicate) tuples for the given object""" - for s, p, o in self.triples((None, None, object), context): - yield s, p - - def subject_objects(self, predicate=None, context=None): - """Generate (subject, object) tuples for the given predicate""" - for s, p, o in self.triples((None, predicate, None), context): - yield s, o - - def predicate_objects(self, subject=None, context=None): - """Generate (predicate, object) tuples for the given subject""" - for s, p, o in self.triples((subject, None, None), context): - yield p, o - - def __reduce__(self): - return (BackwardCompatGraph, (self.store, self.identifier)) - - def save(self, destination, format="xml", base=None, encoding=None): - warnings.warn("Use serialize method instead. ", - DeprecationWarning, stacklevel=2) - self.serialize(destination=destination, format=format, base=base, - encoding=encoding) - -class ModificationException(Exception): - - def __init__(self): - pass - - def __str__(self): - return ("Modifications and transactional operations not allowed on " - "ReadOnlyGraphAggregate instances") - -class UnSupportedAggregateOperation(Exception): - - def __init__(self): - pass - - def __str__(self): - return ("This operation is not supported by ReadOnlyGraphAggregate " - "instances") - -class ReadOnlyGraphAggregate(ConjunctiveGraph): - """Utility class for treating a set of graphs as a single graph - - Only read operations are supported (hence the name). Essentially a - ConjunctiveGraph over an explicit subset of the entire store. - """ - - def __init__(self, graphs,store='default'): - if store is not None: - super(ReadOnlyGraphAggregate, self).__init__(store) - Graph.__init__(self, store) - self.__namespace_manager = None - - assert isinstance(graphs, list) and graphs\ - and [g for g in graphs if isinstance(g, Graph)],\ - "graphs argument must be a list of Graphs!!" - self.graphs = graphs - - def __repr__(self): - return "<ReadOnlyGraphAggregate: %s graphs>" % len(self.graphs) - - def destroy(self, configuration): - raise ModificationException() - - #Transactional interfaces (optional) - def commit(self): - raise ModificationException() - - def rollback(self): - raise ModificationException() - - def open(self, configuration, create=False): - # TODO: is there a use case for this method? - for graph in self.graphs: - graph.open(self, configuration, create) - - def close(self): - for graph in self.graphs: - graph.close() - - def add(self, (s, p, o)): - raise ModificationException() - - def addN(self, quads): - raise ModificationException() - - def remove(self, (s, p, o)): - raise ModificationException() - - def triples(self, (s, p, o)): - for graph in self.graphs: - for s1, p1, o1 in graph.triples((s, p, o)): - yield (s1, p1, o1) - - def __contains__(self, triple_or_quad): - context = None - if len(triple_or_quad) == 4: - context = triple_or_quad[3] - for graph in self.graphs: - if context is None or graph.identifier == context.identifier: - if triple_or_quad[:3] in graph: - return True - return False - - def quads(self,(s,p,o)): - """Iterate over all the quads in the entire aggregate graph""" - for graph in self.graphs: - for s1, p1, o1 in graph.triples((s, p, o)): - yield (s1, p1, o1, graph) - - def __len__(self): - return reduce(lambda x, y: x + y, [len(g) for g in self.graphs]) - - def __hash__(self): - raise UnSupportedAggregateOperation() - - def __cmp__(self, other): - if other is None: - return -1 - elif isinstance(other, Graph): - return -1 - elif isinstance(other, ReadOnlyGraphAggregate): - return cmp(self.graphs, other.graphs) - else: - return -1 - - def __iadd__(self, other): - raise ModificationException() - - def __isub__(self, other): - raise ModificationException() - - # Conv. methods - - def triples_choices(self, (subject, predicate, object_), context=None): - for graph in self.graphs: - choices = graph.triples_choices((subject, predicate, object_)) - for (s, p, o) in choices: - yield (s, p, o) - - def qname(self, uri): - if hasattr(self,'namespace_manager') and self.namespace_manager: - return self.namespace_manager.qname(uri) - raise UnSupportedAggregateOperation() - - def compute_qname(self, uri, generate=True): - if hasattr(self,'namespace_manager') and self.namespace_manager: - return self.namespace_manager.compute_qname(uri, generate) - raise UnSupportedAggregateOperation() - - def bind(self, prefix, namespace, override=True): - raise UnSupportedAggregateOperation() - - def namespaces(self): - if hasattr(self,'namespace_manager'): - for prefix, namespace in self.namespace_manager.namespaces(): - yield prefix, namespace - else: - for graph in self.graphs: - for prefix, namespace in graph.namespaces(): - yield prefix, namespace - - def absolutize(self, uri, defrag=1): - raise UnSupportedAggregateOperation() - - def parse(self, source, publicID=None, format="xml", **args): - raise ModificationException() - - def n3(self): - raise UnSupportedAggregateOperation() - - def __reduce__(self): - raise UnSupportedAggregateOperation() - - -def test(): - import doctest - doctest.testmod() - -if __name__ == '__main__': - test() |