diff options
Diffstat (limited to 'creactistore/_templates/lib/rdflib/store.py')
-rw-r--r-- | creactistore/_templates/lib/rdflib/store.py | 291 |
1 files changed, 291 insertions, 0 deletions
diff --git a/creactistore/_templates/lib/rdflib/store.py b/creactistore/_templates/lib/rdflib/store.py new file mode 100644 index 0000000..84adece --- /dev/null +++ b/creactistore/_templates/lib/rdflib/store.py @@ -0,0 +1,291 @@ +""" +============ +rdflib.store +============ + +``Context-aware``: An RDF store capable of storing statements within contexts +is considered context-aware. Essentially, such a store is able to partition +the RDF model it represents into individual, named, and addressable +sub-graphs. + +Relevant Notation3 reference regarding formulae, quoted statements, and such: +http://www.w3.org/DesignIssues/Notation3.html + +``Formula-aware``: An RDF store capable of distinguishing between statements +that are asserted and statements that are quoted is considered formula-aware. + +``Conjunctive Graph``: This refers to the 'top-level' Graph. It is the +aggregation of all the contexts within it and is also the appropriate, +absolute boundary for closed world assumptions / models. + +For the sake of persistence, Conjunctive Graphs must be distinguished by +identifiers (that may not necessarily be RDF identifiers or may be an RDF +identifier normalized - SHA1/MD5 perhaps - for database naming purposes ). + +``Conjunctive Query``: Any query that doesn't limit the store to search +within a named context only. Such a query expects a context-aware store to +search the entire asserted universe (the conjunctive graph). A formula-aware +store is expected not to include quoted statements when matching such a query. +""" + +#Constants representing the state of a Store (returned by the open method) +VALID_STORE = 1 +CORRUPTED_STORE = 0 +NO_STORE = -1 +UNKNOWN = None + +from rdflib.events import Dispatcher, Event + +__all__ = ['StoreCreatedEvent', 'TripleAddedEvent', 'TripleRemovedEvent', 'NodePickler', 'Store'] + +class StoreCreatedEvent(Event): + """ + This event is fired when the Store is created, it has the folloing attribute: + + - 'configuration' string that is used to create the store + + """ + +class TripleAddedEvent(Event): + """ + This event is fired when a triple is added, it has the following attributes: + + - 'triple' added to the graph + - 'context' of the triple if any + - 'graph' that the triple was added to + """ + +class TripleRemovedEvent(Event): + """ + This event is fired when a triple is removed, it has the following attributes: + + - 'triple' removed from the graph + - 'context' of the triple if any + - 'graph' that the triple was removed from + """ + +from cPickle import Pickler, Unpickler, UnpicklingError +try: + from io import BytesIO +except ImportError: + from cStringIO import StringIO as BytesIO + + +class NodePickler(object): + def __init__(self): + self._objects = {} + self._ids = {} + self._get_object = self._objects.__getitem__ + + def _get_ids(self, key): + try: + return self._ids.get(key) + except TypeError, e: + return None + + def register(self, object, id): + self._objects[id] = object + self._ids[object] = id + + def loads(self, s): + up = Unpickler(BytesIO(s)) + up.persistent_load = self._get_object + try: + return up.load() + except KeyError, e: + raise UnpicklingError, "Could not find Node class for %s" % e + + def dumps(self, obj, protocol=None, bin=None): + src = BytesIO() + p = Pickler(src) + p.persistent_id = self._get_ids + p.dump(obj) + return src.getvalue() + + +class Store(object): + #Properties + context_aware = False + formula_aware = False + transaction_aware = False + batch_unification = False + def __init__(self, configuration=None, identifier=None): + """ + identifier: URIRef of the Store. Defaults to CWD + configuration: string containing infomation open can use to + connect to datastore. + """ + self.__node_pickler = None + self.dispatcher = Dispatcher() + if configuration: + self.open(configuration) + + def __get_node_pickler(self): + if self.__node_pickler is None: + from rdflib.term import URIRef + from rdflib.term import BNode + from rdflib.term import Literal + from rdflib.graph import Graph, QuotedGraph, GraphValue + from rdflib.term import Variable + from rdflib.term import Statement + self.__node_pickler = np = NodePickler() + np.register(self, "S") + np.register(URIRef, "U") + np.register(BNode, "B") + np.register(Literal, "L") + np.register(Graph, "G") + np.register(QuotedGraph, "Q") + np.register(Variable, "V") + np.register(Statement, "s") + np.register(GraphValue, "v") + return self.__node_pickler + node_pickler = property(__get_node_pickler) + + #Database management methods + def create(self, configuration): + self.dispatcher.dispatch(StoreCreatedEvent(configuration=configuration)) + + def open(self, configuration, create=False): + """ + Opens the store specified by the configuration string. If + create is True a store will be created if it does not already + exist. If create is False and a store does not already exist + an exception is raised. An exception is also raised if a store + exists, but there is insufficient permissions to open the + store. This should return one of VALID_STORE,CORRUPTED_STORE,or NO_STORE + """ + return UNKNOWN + + def close(self, commit_pending_transaction=False): + """ + This closes the database connection. The commit_pending_transaction parameter specifies whether to + commit all pending transactions before closing (if the store is transactional). + """ + + def destroy(self, configuration): + """ + This destroys the instance of the store identified by the configuration string. + """ + + def gc(self): + """ + Allows the store to perform any needed garbage collection + """ + pass + + #RDF APIs + def add(self, (subject, predicate, object), context, quoted=False): + """ + Adds the given statement to a specific context or to the model. The quoted argument + is interpreted by formula-aware stores to indicate this statement is quoted/hypothetical + It should be an error to not specify a context and have the quoted argument be True. + It should also be an error for the quoted argument to be True when the store is not formula-aware. + """ + self.dispatcher.dispatch(TripleAddedEvent(triple=(subject, predicate, object), context=context)) + + def addN(self, quads): + """ + Adds each item in the list of statements to a specific context. The quoted argument + is interpreted by formula-aware stores to indicate this statement is quoted/hypothetical. + Note that the default implementation is a redirect to add + """ + for s,p,o,c in quads: + assert c is not None, "Context associated with %s %s %s is None!"%(s,p,o) + self.add( + (s,p,o), + c + ) + + def remove(self, (subject, predicate, object), context=None): + """ Remove the set of triples matching the pattern from the store """ + self.dispatcher.dispatch(TripleRemovedEvent(triple=(subject, predicate, object), context=context)) + + def triples_choices(self, (subject, predicate, object_),context=None): + """ + A variant of triples that can take a list of terms instead of a single + term in any slot. Stores can implement this to optimize the response time + from the default 'fallback' implementation, which will iterate + over each term in the list and dispatch to tripless + """ + if isinstance(object_,list): + assert not isinstance(subject,list), "object_ / subject are both lists" + assert not isinstance(predicate,list), "object_ / predicate are both lists" + if object_: + for obj in object_: + for (s1, p1, o1), cg in self.triples((subject,predicate,obj),context): + yield (s1, p1, o1), cg + else: + for (s1, p1, o1), cg in self.triples((subject,predicate,None),context): + yield (s1, p1, o1), cg + + elif isinstance(subject,list): + assert not isinstance(predicate,list), "subject / predicate are both lists" + if subject: + for subj in subject: + for (s1, p1, o1), cg in self.triples((subj,predicate,object_),context): + yield (s1, p1, o1), cg + else: + for (s1, p1, o1), cg in self.triples((None,predicate,object_),context): + yield (s1, p1, o1), cg + + elif isinstance(predicate,list): + assert not isinstance(subject,list), "predicate / subject are both lists" + if predicate: + for pred in predicate: + for (s1, p1, o1), cg in self.triples((subject,pred,object_),context): + yield (s1, p1, o1), cg + else: + for (s1, p1, o1), cg in self.triples((subject,None,object_),context): + yield (s1, p1, o1), cg + + def triples(self, triple_pattern, context=None): + """ + A generator over all the triples matching the pattern. Pattern can + include any objects for used for comparing against nodes in the store, for + example, REGEXTerm, URIRef, Literal, BNode, Variable, Graph, QuotedGraph, Date? DateRange? + + A conjunctive query can be indicated by either providing a value of None + for the context or the identifier associated with the Conjunctive Graph (if it's context aware). + """ + subject, predicate, object = triple_pattern + + # variants of triples will be done if / when optimization is needed + + def __len__(self, context=None): + """ + Number of statements in the store. This should only account for non-quoted (asserted) statements + if the context is not specified, otherwise it should return the number of statements in the formula or context given. + """ + + def contexts(self, triple=None): + """ + Generator over all contexts in the graph. If triple is specified, a generator over all + contexts the triple is in. + """ + + # Optional Namespace methods + + def bind(self, prefix, namespace): + """ """ + + def prefix(self, namespace): + """ """ + + def namespace(self, prefix): + """ """ + + def namespaces(self): + """ """ + if False: + yield None + + # Optional Transactional methods + + def commit(self): + """ """ + + def rollback(self): + """ """ + + + |