aboutsummaryrefslogtreecommitdiffstats
path: root/bsfs/triple_store/sparql.py
diff options
context:
space:
mode:
Diffstat (limited to 'bsfs/triple_store/sparql.py')
-rw-r--r--bsfs/triple_store/sparql.py81
1 files changed, 44 insertions, 37 deletions
diff --git a/bsfs/triple_store/sparql.py b/bsfs/triple_store/sparql.py
index 3eab869..d9ed55a 100644
--- a/bsfs/triple_store/sparql.py
+++ b/bsfs/triple_store/sparql.py
@@ -10,9 +10,8 @@ import typing
import rdflib
# bsfs imports
-from bsfs.utils import URI
-from bsfs.utils import errors
-import bsfs.schema as _schema
+from bsfs import schema as bsc
+from bsfs.utils import errors, URI
# inner-module imports
from . import base
@@ -26,7 +25,7 @@ __all__: typing.Sequence[str] = (
## code ##
-class Transaction():
+class _Transaction():
"""Lightweight rdflib transactions for in-memory databases."""
def __init__(self, graph):
@@ -58,11 +57,20 @@ class SparqlStore(base.TripleStoreBase):
"""
"""
- def __init__(self, uri: typing.Optional[URI] = None):
- super().__init__(uri)
- self.graph = rdflib.Graph()
- self.transaction = Transaction(self.graph)
- self.__schema = _schema.Schema.Empty()
+ # The rdflib graph.
+ _graph: rdflib.Graph
+
+ # Current transaction.
+ _transaction: _Transaction
+
+ # The local schema.
+ _schema: bsc.Schema
+
+ def __init__(self):
+ super().__init__(None)
+ self._graph = rdflib.Graph()
+ self._transaction = _Transaction(self._graph)
+ self._schema = bsc.Schema.Empty()
@classmethod
def Open(
@@ -73,15 +81,14 @@ class SparqlStore(base.TripleStoreBase):
return cls(None)
def commit(self):
- self.transaction.commit()
+ self._transaction.commit()
def rollback(self):
- self.transaction.rollback()
+ self._transaction.rollback()
@property
- def schema(self) -> _schema.Schema:
- """Return the current schema."""
- return self.__schema
+ def schema(self) -> bsc.Schema:
+ return self._schema
@schema.setter
def schema(self, schema: _schema.Schema):
@@ -106,7 +113,7 @@ class SparqlStore(base.TripleStoreBase):
"""
# check args: Schema instanace
- if not isinstance(schema, _schema.Schema):
+ if not isinstance(schema, bsc.Schema):
raise TypeError(schema)
# check compatibility: No contradicting definitions
if not self.schema.consistent_with(schema):
@@ -124,21 +131,21 @@ class SparqlStore(base.TripleStoreBase):
# remove predicate instances
for pred in sub.predicates:
- for src, trg in self.graph.subject_objects(rdflib.URIRef(pred.uri)):
- self.transaction.remove((src, rdflib.URIRef(pred.uri), trg))
+ for src, trg in self._graph.subject_objects(rdflib.URIRef(pred.uri)):
+ self._transaction.remove((src, rdflib.URIRef(pred.uri), trg))
# remove node instances
for node in sub.nodes:
# iterate through node instances
- for inst in self.graph.subjects(rdflib.RDF.type, rdflib.URIRef(node.uri)):
+ for inst in self._graph.subjects(rdflib.RDF.type, rdflib.URIRef(node.uri)):
# remove triples where the instance is in the object position
- for src, pred in self.graph.subject_predicates(inst):
- self.transaction.remove((src, pred, inst))
+ for src, pred in self._graph.subject_predicates(inst):
+ self._transaction.remove((src, pred, inst))
# remove triples where the instance is in the subject position
- for pred, trg in self.graph.predicate_objects(inst):
- self.transaction.remove((inst, pred, trg))
+ for pred, trg in self._graph.predicate_objects(inst):
+ self._transaction.remove((inst, pred, trg))
# remove instance
- self.transaction.remove((inst, rdflib.RDF.type, rdflib.URIRef(node.uri)))
+ self._transaction.remove((inst, rdflib.RDF.type, rdflib.URIRef(node.uri)))
# NOTE: Nothing to do for literals
@@ -146,15 +153,15 @@ class SparqlStore(base.TripleStoreBase):
self.commit()
# migrate schema
- self.__schema = schema
+ self._schema = schema
- def _has_type(self, subject: URI, node_type: _schema.Node) -> bool:
+ def _has_type(self, subject: URI, node_type: bsc.Node) -> bool:
"""Return True if *subject* is a node of class *node_type* or a subclass thereof."""
if node_type not in self.schema.nodes():
raise errors.ConsistencyError(f'{node_type} is not defined in the schema')
- subject_types = list(self.graph.objects(rdflib.URIRef(subject), rdflib.RDF.type))
+ subject_types = list(self._graph.objects(rdflib.URIRef(subject), rdflib.RDF.type))
if len(subject_types) == 0:
return False
elif len(subject_types) == 1:
@@ -170,7 +177,7 @@ class SparqlStore(base.TripleStoreBase):
def exists(
self,
- node_type: _schema.Node,
+ node_type: bsc.Node,
guids: typing.Iterable[URI],
):
"""
@@ -179,7 +186,7 @@ class SparqlStore(base.TripleStoreBase):
def create(
self,
- node_type: _schema.Node,
+ node_type: bsc.Node,
guids: typing.Iterable[URI],
):
"""
@@ -195,13 +202,13 @@ class SparqlStore(base.TripleStoreBase):
# FIXME: node exists and may have a different type! ignore? raise? report?
continue
# add node
- self.transaction.add((guid, rdflib.RDF.type, rdflib.URIRef(node_type.uri)))
+ self._transaction.add((guid, rdflib.RDF.type, rdflib.URIRef(node_type.uri)))
def set(
self,
- node_type: _schema.Node, # FIXME: is the node_type even needed? Couldn't I infer from the predicate?
+ node_type: bsc.Node,
guids: typing.Iterable[URI],
- predicate: _schema.Predicate,
+ predicate: bsc.Predicate,
values: typing.Iterable[typing.Any],
):
# check node_type
@@ -218,7 +225,7 @@ class SparqlStore(base.TripleStoreBase):
return
if predicate.unique and len(values) != 1:
raise ValueError(values)
- if isinstance(predicate.range, _schema.Node):
+ if isinstance(predicate.range, bsc.Node):
values = set(values) # materialize to safeguard against iterators passed as argument
inconsistent = {val for val in values if not self._has_type(val, predicate.range)}
# catches nodes that don't exist and nodes that have an inconsistent type
@@ -236,18 +243,18 @@ class SparqlStore(base.TripleStoreBase):
for guid, value in itertools.product(guids, values):
guid = rdflib.URIRef(guid)
# convert value
- if isinstance(predicate.range, _schema.Literal):
+ if isinstance(predicate.range, bsc.Literal):
value = rdflib.Literal(value, datatype=rdflib.URIRef(predicate.range.uri))
- elif isinstance(predicate.range, _schema.Node):
+ elif isinstance(predicate.range, bsc.Node):
value = rdflib.URIRef(value)
else:
raise errors.UnreachableError()
# clear triples for unique predicates
if predicate.unique:
- for obj in self.graph.objects(guid, pred):
+ for obj in self._graph.objects(guid, pred):
if obj != value:
- self.transaction.remove((guid, pred, obj))
+ self._transaction.remove((guid, pred, obj))
# add triple
- self.transaction.add((guid, pred, value))
+ self._transaction.add((guid, pred, value))
## EOF ##