from itertools import chain
from rdflib.store import Store, VALID_STORE, NO_STORE
from rdflib.plugins.memory import IOMemory
from rdflib.term import Variable
from .context_common import CONTEXT_IMPORTS
[docs]class ContextStoreException(Exception):
pass
class ContextStore(Store):
context_aware = True
def __init__(self, context=None, include_stored=False, **kwargs):
"""
Parameters
----------
context : PyOpenWorm.context.Context
context
"""
super(ContextStore, self).__init__(**kwargs)
self._memory_store = None
self._include_stored = include_stored
if context is not None:
self._init_store(context)
def open(self, configuration, create=False):
from .context import Contexts
ctx = Contexts.get(configuration)
if ctx is not None:
self._init_store(ctx)
return VALID_STORE
else:
return NO_STORE
def _init_store(self, ctx):
self.ctx = ctx
if self._include_stored:
self._store_store = RDFContextStore(ctx)
else:
self._store_store = None
if self._memory_store is None:
self._memory_store = IOMemory()
self._init_store0(ctx)
def _init_store0(self, ctx, seen=None):
if seen is None:
seen = set()
ctxid = ctx.identifier
if ctxid in seen:
return
seen.add(ctxid)
self._memory_store.addN((s, p, o, ctxid)
for s, p, o
in ctx.contents_triples()
if not (isinstance(s, Variable) or
isinstance(p, Variable) or
isinstance(o, Variable)))
for cctx in ctx.imports:
self._init_store0(cctx, seen)
def close(self, commit_pending_transaction=False):
self.ctx = None
self._memory_store = None
# RDF APIs
def add(self, triple, context, quoted=False):
raise NotImplementedError("This is a query-only store")
def addN(self, quads):
raise NotImplementedError("This is a query-only store")
def remove(self, triple, context=None):
raise NotImplementedError("This is a query-only store")
def triples(self, triple_pattern, context=None):
context = getattr(context, 'identifier', context)
if self._memory_store is None:
raise Exception("Database has not been opened")
context_triples = []
if self._store_store is not None:
context_triples.append(self._store_store.triples(triple_pattern,
context))
return chain(self._memory_store.triples(triple_pattern, context),
*context_triples)
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.
:param context: a graph instance to query or None
"""
if self._memory_store is None:
raise Exception("Database has not been opened")
return len(self._memory_store)
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.
if store is graph_aware, may also return empty contexts
:returns: a generator over Nodes
"""
if self._memory_store is None:
raise Exception("Database has not been opened")
return self._memory_store.contexts(triple)
class RDFContextStore(Store):
# Returns triples imported by the given context
context_aware = True
def __init__(self, context=None, imports_graph=None, **kwargs):
super(RDFContextStore, self).__init__(**kwargs)
self.__graph = context.conf['rdf.graph']
self.__imports_graph = imports_graph
self.__store = self.__graph.store
self.__context = context
self.__context_transitive_imports = None
def __init_contexts(self):
if self.__store is not None and self.__context_transitive_imports is None:
imports = set()
border = set([self.__context.identifier])
while border:
new_border = set()
for b in border:
itr = self.__store.triples((b, CONTEXT_IMPORTS, None),
context=self.__imports_graph)
for t in itr:
new_border.add(t[0][2])
imports |= border
border = new_border
self.__context_transitive_imports = imports
def triples(self, pattern, context=None):
self.__init_contexts()
for t in self.__store.triples(pattern, context):
contexts = set(getattr(c, 'identifier', c) for c in t[1])
inter = self.__context_transitive_imports & contexts
if inter:
yield t[0], inter
def contexts(self, triple=None):
if triple is not None:
for x in self.triples(triple):
for c in x[1]:
yield getattr(c, 'identifier', c)
else:
self.__init_contexts()
for c in self.__context_transitive_imports:
yield c