diff options
-rw-r--r-- | bsfs/front/builder.py | 6 | ||||
-rw-r--r-- | bsfs/graph/ac/base.py | 16 | ||||
-rw-r--r-- | bsfs/graph/graph.py | 35 | ||||
-rw-r--r-- | bsfs/graph/nodes.py | 41 | ||||
-rw-r--r-- | test/front/test_bsfs.py | 3 | ||||
-rw-r--r-- | test/front/test_builder.py | 3 | ||||
-rw-r--r-- | test/graph/ac/test_base.py | 83 | ||||
-rw-r--r-- | test/graph/ac/test_null.py | 30 | ||||
-rw-r--r-- | test/graph/test_graph.py | 74 | ||||
-rw-r--r-- | test/graph/test_nodes.py | 151 | ||||
-rw-r--r-- | test/graph/test_walk.py | 4 |
11 files changed, 297 insertions, 149 deletions
diff --git a/bsfs/front/builder.py b/bsfs/front/builder.py index 73f1703..ecdc768 100644 --- a/bsfs/front/builder.py +++ b/bsfs/front/builder.py @@ -8,7 +8,7 @@ Author: Matthias Baumgartner, 2022 import typing # bsfs imports -from bsfs.graph import Graph +from bsfs.graph import Graph, ac from bsfs.triple_store import TripleStoreBase, SparqlStore from bsfs.utils import URI, errors @@ -68,8 +68,10 @@ def build_graph(cfg: typing.Any) -> Graph: if 'backend' not in args: raise errors.ConfigError('required argument "backend" is not provided') backend = build_backend(args['backend']) + # build access controls + access_controls = ac.NullAC(backend, user) # build and return graph cls = _graph_classes[name] - return cls(backend, user) + return cls(backend, access_controls) ## EOF ## diff --git a/bsfs/graph/ac/base.py b/bsfs/graph/ac/base.py index 79b09e5..0b9f988 100644 --- a/bsfs/graph/ac/base.py +++ b/bsfs/graph/ac/base.py @@ -12,7 +12,7 @@ import typing from bsfs import schema from bsfs.query import ast from bsfs.triple_store import TripleStoreBase -from bsfs.utils import URI +from bsfs.utils import URI, typename # exports __all__: typing.Sequence[str] = ( @@ -44,6 +44,20 @@ class AccessControlBase(abc.ABC): self._backend = backend self._user = URI(user) + def __str__(self) -> str: + return f'{typename(self)}({self._user})' + + def __repr__(self) -> str: + return f'{typename(self)}({self._user})' + + def __eq__(self, other: typing.Any) -> bool: + return isinstance(other, type(self)) \ + and self._backend == other._backend \ + and self._user == other._user + + def __hash__(self) -> int: + return hash((type(self), self._backend, self._user)) + @abc.abstractmethod def is_protected_predicate(self, pred: schema.Predicate) -> bool: """Return True if a predicate cannot be modified manually.""" diff --git a/bsfs/graph/graph.py b/bsfs/graph/graph.py index df2e3a5..a74da01 100644 --- a/bsfs/graph/graph.py +++ b/bsfs/graph/graph.py @@ -40,31 +40,42 @@ class Graph(): # link to the triple storage backend. _backend: TripleStoreBase - # user uri. - _user: URI + # access controls. + _ac: ac.AccessControlBase - def __init__(self, backend: TripleStoreBase, user: URI): + # query resolver. + _resolver: resolve.Filter + + # query validator. + _validate: validate.Filter + + def __init__( + self, + backend: TripleStoreBase, + access_control: ac.AccessControlBase, + ): + # store members self._backend = backend - self._user = user + self._ac = access_control + # helper classes self._resolver = resolve.Filter(self._backend.schema) self._validate = validate.Filter(self._backend.schema) - self._ac = ac.NullAC(self._backend, self._user) # ensure Graph schema requirements self.migrate(self._backend.schema) def __hash__(self) -> int: - return hash((type(self), self._backend, self._user)) + return hash((type(self), self._backend, self._ac)) def __eq__(self, other) -> bool: return isinstance(other, type(self)) \ and self._backend == other._backend \ - and self._user == other._user + and self._ac == other._ac def __repr__(self) -> str: - return f'{typename(self)}(backend={repr(self._backend)}, user={self._user})' + return f'{typename(self)}({repr(self._backend)}, {self._ac})' def __str__(self) -> str: - return f'{typename(self)}({str(self._backend)}, {self._user})' + return f'{typename(self)}({str(self._backend)})' @property def schema(self) -> bsc.Schema: @@ -106,7 +117,7 @@ class Graph(): """ type_ = self.schema.node(node_type) # NOTE: Nodes constructor materializes guids. - return _nodes.Nodes(self._backend, self._user, type_, guids) + return _nodes.Nodes(self._backend, self._ac, type_, guids) def node(self, node_type: URI, guid: URI) -> _nodes.Nodes: """Return node *guid* of type *node_type* as a `bsfs.graph.Nodes` instance. @@ -131,14 +142,14 @@ class Graph(): # query the backend guids = self._backend.get(type_, query) # no need to materialize # return Nodes instance - return _nodes.Nodes(self._backend, self._user, type_, guids) + return _nodes.Nodes(self._backend, self._ac, type_, guids) def all(self, node_type: URI) -> _nodes.Nodes: """Return all instances of type *node_type*.""" # get node type type_ = self.schema.node(node_type) guids = self._backend.get(type_, None) # no need to materialize - return _nodes.Nodes(self._backend, self._user, type_, guids) + return _nodes.Nodes(self._backend, self._ac, type_, guids) ## EOF ## diff --git a/bsfs/graph/nodes.py b/bsfs/graph/nodes.py index bc71a32..91cbb5d 100644 --- a/bsfs/graph/nodes.py +++ b/bsfs/graph/nodes.py @@ -37,8 +37,8 @@ class Nodes(): # triple store backend. _backend: TripleStoreBase - # user uri. - _user: URI + # access controls. + _ac: ac.AccessControlBase # node type. _node_type: bsc.Node @@ -49,31 +49,30 @@ class Nodes(): def __init__( self, backend: TripleStoreBase, - user: URI, + access_control: ac.AccessControlBase, node_type: bsc.Node, guids: typing.Iterable[URI], ): # set main members self._backend = backend - self._user = user + self._ac = access_control self._node_type = node_type self._guids = set(guids) # create helper instances # FIXME: Assumes that the schema does not change while the instance is in use! - self._ac = ac.NullAC(self._backend, self._user) def __eq__(self, other: typing.Any) -> bool: return isinstance(other, Nodes) \ and self._backend == other._backend \ - and self._user == other._user \ + and self._ac == other._ac \ and self._node_type == other._node_type \ and self._guids == other._guids def __hash__(self) -> int: - return hash((type(self), self._backend, self._user, self._node_type, tuple(sorted(self._guids)))) + return hash((type(self), self._backend, self._ac, self._node_type, tuple(sorted(self._guids)))) def __repr__(self) -> str: - return f'{typename(self)}({self._backend}, {self._user}, {self._node_type}, {self._guids})' + return f'{typename(self)}({self._backend}, {self._ac}, {self._node_type}, {self._guids})' def __str__(self) -> str: return f'{typename(self)}({self._node_type}, {self._guids})' @@ -94,44 +93,44 @@ class Nodes(): return self._backend.schema def __add__(self, other: typing.Any) -> 'Nodes': - """Concatenate guids. Backend, user, and node type must match.""" + """Concatenate guids. Backend, AC, and node type must match.""" if not isinstance(other, type(self)): return NotImplemented if self._backend != other._backend: raise ValueError(other) - if self._user != other._user: + if self._ac != other._ac: raise ValueError(other) if self.node_type != other.node_type: raise ValueError(other) - return Nodes(self._backend, self._user, self.node_type, self._guids | other._guids) + return Nodes(self._backend, self._ac, self.node_type, self._guids | other._guids) def __or__(self, other: typing.Any) -> 'Nodes': - """Concatenate guids. Backend, user, and node type must match.""" + """Concatenate guids. Backend, AC, and node type must match.""" return self.__add__(other) def __sub__(self, other: typing.Any) -> 'Nodes': - """Subtract guids. Backend, user, and node type must match.""" + """Subtract guids. Backend, AC, and node type must match.""" if not isinstance(other, type(self)): return NotImplemented if self._backend != other._backend: raise ValueError(other) - if self._user != other._user: + if self._ac != other._ac: raise ValueError(other) if self.node_type != other.node_type: raise ValueError(other) - return Nodes(self._backend, self._user, self.node_type, self._guids - other._guids) + return Nodes(self._backend, self._ac, self.node_type, self._guids - other._guids) def __and__(self, other: typing.Any) -> 'Nodes': - """Intersect guids. Backend, user, and node type must match.""" + """Intersect guids. Backend, AC, and node type must match.""" if not isinstance(other, type(self)): return NotImplemented if self._backend != other._backend: raise ValueError(other) - if self._user != other._user: + if self._ac != other._ac: raise ValueError(other) if self.node_type != other.node_type: raise ValueError(other) - return Nodes(self._backend, self._user, self.node_type, self._guids & other._guids) + return Nodes(self._backend, self._ac, self.node_type, self._guids & other._guids) def __len__(self) -> int: """Return the number of guids.""" @@ -140,7 +139,7 @@ class Nodes(): def __iter__(self) -> typing.Iterator['Nodes']: """Iterate over individual guids. Returns `Nodes` instances.""" return iter( - Nodes(self._backend, self._user, self.node_type, {guid}) + Nodes(self._backend, self._ac, self.node_type, {guid}) for guid in self._guids ) @@ -266,12 +265,12 @@ class Nodes(): # process triples for root, name, raw in triples: # get node - node = Nodes(self._backend, self._user, self.node_type, {root}) + node = Nodes(self._backend, self._ac, self.node_type, {root}) # get path path, tail = name2path[name] # covert raw to value if isinstance(tail.range, bsc.Node): - value = Nodes(self._backend, self._user, tail.range, {raw}) + value = Nodes(self._backend, self._ac, tail.range, {raw}) else: value = raw # emit triple diff --git a/test/front/test_bsfs.py b/test/front/test_bsfs.py index 0d7f383..4eb36c3 100644 --- a/test/front/test_bsfs.py +++ b/test/front/test_bsfs.py @@ -9,6 +9,7 @@ import unittest # bsie imports from bsfs.graph import Graph +from bsfs.graph.ac import NullAC from bsfs.triple_store import SparqlStore from bsfs.utils import errors, URI @@ -25,7 +26,7 @@ class TestBSFS(unittest.TestCase): graph = Open(config) self.assertIsInstance(graph, Graph) self.assertIsInstance(graph._backend, SparqlStore) - self.assertEqual(graph._user, URI('http://example.com/me')) + self.assertEqual(graph._ac, NullAC(graph._backend, URI('http://example.com/me'))) # invalid config raises an error self.assertRaises(errors.ConfigError, Open, {}) diff --git a/test/front/test_builder.py b/test/front/test_builder.py index 08f2027..0328a0a 100644 --- a/test/front/test_builder.py +++ b/test/front/test_builder.py @@ -9,6 +9,7 @@ import unittest # bsie imports from bsfs.graph import Graph +from bsfs.graph.ac import NullAC from bsfs.triple_store import SparqlStore from bsfs.utils import errors, URI @@ -40,7 +41,7 @@ class TestBuilder(unittest.TestCase): graph = build_graph({'Graph': {'backend': {'SparqlStore': {}}, 'user': 'http://example.com/me'}}) self.assertIsInstance(graph, Graph) self.assertIsInstance(graph._backend, SparqlStore) - self.assertEqual(graph._user, URI('http://example.com/me')) + self.assertEqual(graph._ac, NullAC(graph._backend, URI('http://example.com/me'))) # cannot create an invalid graph self.assertRaises(errors.ConfigError, build_graph, {'MyGraph': {}}) # must pass a dict diff --git a/test/graph/ac/test_base.py b/test/graph/ac/test_base.py new file mode 100644 index 0000000..ad24e3d --- /dev/null +++ b/test/graph/ac/test_base.py @@ -0,0 +1,83 @@ +""" + +Part of the bsfs test suite. +A copy of the license is provided with the project. +Author: Matthias Baumgartner, 2022 +""" +# imports +import unittest + +# bsie imports +from bsfs import schema as bsc +from bsfs.namespace import ns +from bsfs.query import ast +from bsfs.triple_store import SparqlStore +from bsfs.utils import URI + +# objects to test +from bsfs.graph.ac.base import AccessControlBase + + +## code ## + +class StubAC(AccessControlBase): + def is_protected_predicate(self, pred): + pass + def create(self, node_type, guids): + pass + def link_from_node(self, node_type, guids): + pass + def link_to_node(self, node_type, guids): + pass + def write_literal(self, node_type, guids): + pass + def createable(self, node_type, guids): + pass + def filter_read(self, node_type, query): + pass + def fetch_read(self, node_type, query): + pass + + +class TestAccessControlBase(unittest.TestCase): + def setUp(self): + self.backend = SparqlStore() + self.user = URI('http://www.example.com/me') + + def test_essentials(self): + ac = StubAC(self.backend, self.user) + # equal construction means equal instance + self.assertEqual(StubAC(self.backend, self.user), StubAC(self.backend, self.user)) + self.assertEqual(hash(StubAC(self.backend, self.user)), hash(StubAC(self.backend, self.user))) + self.assertEqual(ac, StubAC(self.backend, self.user)) + self.assertEqual(hash(ac), hash(StubAC(self.backend, self.user))) + # equivalence respects type + class Foo(): pass + self.assertNotEqual(ac, 1234) + self.assertNotEqual(hash(ac), hash(1234)) + self.assertNotEqual(ac, 'hello') + self.assertNotEqual(hash(ac), hash('hello')) + self.assertNotEqual(ac, Foo()) + self.assertNotEqual(hash(ac), hash(Foo())) + # equivalence respects backend + self.assertNotEqual(ac, StubAC(SparqlStore(), self.user)) + self.assertNotEqual(hash(ac), hash(StubAC(SparqlStore(), self.user))) + # equivalence respects user + self.assertNotEqual(ac, StubAC(self.backend, URI('http://www.example.com/you'))) + self.assertNotEqual(hash(ac), hash(StubAC(self.backend, URI('http://www.example.com/you')))) + # string conversion + self.assertEqual(str(ac), f'StubAC({self.user})') + self.assertEqual(repr(ac), f'StubAC({self.user})') + # string conversion respects user + self.assertEqual(str(StubAC(self.backend, URI('http://www.example.com/you'))), + f'StubAC(http://www.example.com/you)') + self.assertEqual(repr(StubAC(self.backend, URI('http://www.example.com/you'))), + f'StubAC(http://www.example.com/you)') + + +## main ## + +if __name__ == '__main__': + unittest.main() + +## EOF ## diff --git a/test/graph/ac/test_null.py b/test/graph/ac/test_null.py index e35852d..7d25980 100644 --- a/test/graph/ac/test_null.py +++ b/test/graph/ac/test_null.py @@ -68,6 +68,36 @@ class TestNullAC(unittest.TestCase): self.ent_type = self.backend.schema.node(ns.bsfs.Entity) self.ent_ids = {URI('http://www.example.com/me/entity#1234'), URI('http://www.example.com/me/entity#4321')} + def test_essentials(self): + ac = NullAC(self.backend, self.user) + # equal construction means equal instance + self.assertEqual(NullAC(self.backend, self.user), NullAC(self.backend, self.user)) + self.assertEqual(hash(NullAC(self.backend, self.user)), hash(NullAC(self.backend, self.user))) + self.assertEqual(ac, NullAC(self.backend, self.user)) + self.assertEqual(hash(ac), hash(NullAC(self.backend, self.user))) + # equivalence respects type + class Foo(): pass + self.assertNotEqual(ac, 1234) + self.assertNotEqual(hash(ac), hash(1234)) + self.assertNotEqual(ac, 'hello') + self.assertNotEqual(hash(ac), hash('hello')) + self.assertNotEqual(ac, Foo()) + self.assertNotEqual(hash(ac), hash(Foo())) + # equivalence respects backend + self.assertNotEqual(ac, NullAC(SparqlStore(), self.user)) + self.assertNotEqual(hash(ac), hash(NullAC(SparqlStore(), self.user))) + # equivalence respects user + self.assertNotEqual(ac, NullAC(self.backend, URI('http://www.example.com/you'))) + self.assertNotEqual(hash(ac), hash(NullAC(self.backend, URI('http://www.example.com/you')))) + # string conversion + self.assertEqual(str(ac), f'NullAC({self.user})') + self.assertEqual(repr(ac), f'NullAC({self.user})') + # string conversion respects user + self.assertEqual(str(NullAC(self.backend, URI('http://www.example.com/you'))), + f'NullAC(http://www.example.com/you)') + self.assertEqual(repr(NullAC(self.backend, URI('http://www.example.com/you'))), + f'NullAC(http://www.example.com/you)') + def test_is_protected_predicate(self): ac = NullAC(self.backend, self.user) self.assertTrue(ac.is_protected_predicate(self.p_created)) diff --git a/test/graph/test_graph.py b/test/graph/test_graph.py index 5db1fd2..d89d346 100644 --- a/test/graph/test_graph.py +++ b/test/graph/test_graph.py @@ -9,6 +9,7 @@ import unittest # bsie imports from bsfs import schema +from bsfs.graph.ac import NullAC from bsfs.graph.nodes import Nodes from bsfs.namespace import ns from bsfs.query import ast @@ -23,94 +24,95 @@ from bsfs.graph.graph import Graph class TestGraph(unittest.TestCase): def setUp(self): - self.user = URI('http://example.com/me') self.backend = SparqlStore.Open() self.backend.schema = schema.from_string(''' prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> prefix bsfs: <http://bsfs.ai/schema/> bsfs:Entity rdfs:subClassOf bsfs:Node . ''') + self.user = URI('http://example.com/me') + self.ac = NullAC(self.backend, self.user) def test_str(self): - self.assertEqual(str(Graph(self.backend, self.user)), - 'Graph(SparqlStore(uri=None), http://example.com/me)') - self.assertEqual(repr(Graph(self.backend, self.user)), - 'Graph(backend=SparqlStore(uri=None), user=http://example.com/me)') + self.assertEqual(str(Graph(self.backend, self.ac)), + 'Graph(SparqlStore(uri=None))') + self.assertEqual(repr(Graph(self.backend, self.ac)), + 'Graph(SparqlStore(uri=None), NullAC(http://example.com/me))') # str respects backend class Foo(SparqlStore): pass - self.assertEqual(str(Graph(Foo.Open(), self.user)), - 'Graph(Foo(uri=None), http://example.com/me)') - self.assertEqual(repr(Graph(Foo.Open(), self.user)), - 'Graph(backend=Foo(uri=None), user=http://example.com/me)') + self.assertEqual(str(Graph(Foo.Open(), self.ac)), + 'Graph(Foo(uri=None))') + self.assertEqual(repr(Graph(Foo.Open(), self.ac)), + 'Graph(Foo(uri=None), NullAC(http://example.com/me))') # str respect user - self.assertEqual(str(Graph(self.backend, URI('http://example.com/you'))), - 'Graph(SparqlStore(uri=None), http://example.com/you)') - self.assertEqual(repr(Graph(self.backend, URI('http://example.com/you'))), - 'Graph(backend=SparqlStore(uri=None), user=http://example.com/you)') + self.assertEqual(str(Graph(self.backend, NullAC(self.backend, URI('http://example.com/you')))), + 'Graph(SparqlStore(uri=None))') + self.assertEqual(repr(Graph(self.backend, NullAC(self.backend, URI('http://example.com/you')))), + 'Graph(SparqlStore(uri=None), NullAC(http://example.com/you))') # str respects type class Bar(Graph): pass - self.assertEqual(str(Bar(self.backend, self.user)), - 'Bar(SparqlStore(uri=None), http://example.com/me)') - self.assertEqual(repr(Bar(self.backend, self.user)), - 'Bar(backend=SparqlStore(uri=None), user=http://example.com/me)') + self.assertEqual(str(Bar(self.backend, self.ac)), + 'Bar(SparqlStore(uri=None))') + self.assertEqual(repr(Bar(self.backend, self.ac)), + 'Bar(SparqlStore(uri=None), NullAC(http://example.com/me))') def test_equality(self): - graph = Graph(self.backend, self.user) + graph = Graph(self.backend, self.ac) # instance is equal to itself self.assertEqual(graph, graph) self.assertEqual(hash(graph), hash(graph)) # instance is equal to a clone - self.assertEqual(graph, Graph(self.backend, self.user)) - self.assertEqual(hash(graph), hash(Graph(self.backend, self.user))) + self.assertEqual(graph, Graph(self.backend, self.ac)) + self.assertEqual(hash(graph), hash(Graph(self.backend, self.ac))) # equality respects backend - self.assertNotEqual(graph, Graph(SparqlStore.Open(), self.user)) - self.assertNotEqual(hash(graph), hash(Graph(SparqlStore.Open(), self.user))) + self.assertNotEqual(graph, Graph(SparqlStore.Open(), self.ac)) + self.assertNotEqual(hash(graph), hash(Graph(SparqlStore.Open(), self.ac))) # equality respects user self.assertNotEqual(graph, Graph(self.backend, URI('http://example.com/you'))) self.assertNotEqual(hash(graph), hash(Graph(self.backend, URI('http://example.com/you')))) def test_essentials(self): - graph = Graph(self.backend, self.user) + graph = Graph(self.backend, self.ac) # schema self.assertEqual(graph.schema, self.backend.schema) self.assertRaises(AttributeError, setattr, graph, 'schema', None) def test_node(self): - graph = Graph(self.backend, self.user) + graph = Graph(self.backend, self.ac) guid = URI('http://example.com/me/entity#1234') # returns a Nodes instance self.assertEqual( graph.node(ns.bsfs.Entity, guid), - Nodes(self.backend, self.user, graph.schema.node(ns.bsfs.Entity), {guid})) + Nodes(self.backend, self.ac, graph.schema.node(ns.bsfs.Entity), {guid})) # node_type must be in the schema self.assertRaises(KeyError, graph.node, ns.bsfs.Invalid, guid) def test_nodes(self): - graph = Graph(self.backend, self.user) + graph = Graph(self.backend, self.ac) guids = {URI('http://example.com/me/entity#1234'), URI('http://example.com/me/entity#4321')} # returns a Nodes instance self.assertEqual( graph.nodes(ns.bsfs.Entity, guids), - Nodes(self.backend, self.user, graph.schema.node(ns.bsfs.Entity), guids)) + Nodes(self.backend, self.ac, graph.schema.node(ns.bsfs.Entity), guids)) # node_type must be in the schema self.assertRaises(KeyError, graph.nodes, ns.bsfs.Invalid, guids) def test_all(self): - graph = Graph(self.backend, self.user) + graph = Graph(self.backend, self.ac) # resulting nodes can be empty self.assertEqual(graph.all(ns.bsfs.Entity), - Nodes(self.backend, self.user, graph.schema.node(ns.bsfs.Entity), set())) + Nodes(self.backend, self.ac, graph.schema.node(ns.bsfs.Entity), set())) # resulting nodes contains all nodes of the respective type guids = {URI('http://example.com/me/entity#1234'), URI('http://example.com/me/entity#4321')} self.backend.create(graph.schema.node(ns.bsfs.Entity), guids) self.assertEqual(graph.all(ns.bsfs.Entity), - Nodes(self.backend, self.user, graph.schema.node(ns.bsfs.Entity), guids)) + Nodes(self.backend, self.ac, graph.schema.node(ns.bsfs.Entity), guids)) # node_type must be in the schema self.assertRaises(KeyError, graph.all, ns.bsfs.Invalid) def test_migrate(self): # setup - graph = Graph(self.backend, self.user) + graph = Graph(self.backend, self.ac) # argument must be a schema class Foo(): pass @@ -162,10 +164,10 @@ class TestGraph(unittest.TestCase): prefix bsfs: <http://bsfs.ai/schema/> prefix bsm: <http://bsfs.ai/schema/Meta#> bsfs:Number rdfs:subClassOf bsfs:Literal . - xsd:integer rdfs:subClassOf bsfs:Number . + xsd:float rdfs:subClassOf bsfs:Number . bsm:t_created rdfs:subClassOf bsfs:Predicate ; rdfs:domain bsfs:Node ; - rdfs:range xsd:integer ; + rdfs:range xsd:float ; bsfs:unique "true"^^xsd:boolean . ''')) @@ -203,16 +205,16 @@ class TestGraph(unittest.TestCase): prefix bsfs: <http://bsfs.ai/schema/> prefix bsm: <http://bsfs.ai/schema/Meta#> bsfs:Number rdfs:subClassOf bsfs:Literal . - xsd:integer rdfs:subClassOf bsfs:Number . + xsd:float rdfs:subClassOf bsfs:Number . bsm:t_created rdfs:subClassOf bsfs:Predicate ; rdfs:domain bsfs:Node ; - rdfs:range xsd:integer ; + rdfs:range xsd:float ; bsfs:unique "true"^^xsd:boolean . ''')) def test_get(self): # setup - graph = Graph(self.backend, self.user) + graph = Graph(self.backend, self.ac) graph.migrate(schema.from_string(''' prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> prefix xsd: <http://www.w3.org/2001/XMLSchema#> diff --git a/test/graph/test_nodes.py b/test/graph/test_nodes.py index 6bb3ef3..9541656 100644 --- a/test/graph/test_nodes.py +++ b/test/graph/test_nodes.py @@ -14,6 +14,7 @@ import rdflib # bsie imports from bsfs import schema as bsc +from bsfs.graph.ac import NullAC from bsfs.graph.walk import Walk from bsfs.namespace import Namespace, ns from bsfs.triple_store.sparql import SparqlStore @@ -107,6 +108,7 @@ class TestNodes(unittest.TestCase): } # Nodes constructor args self.user = URI('http://example.com/me') + self.ac = NullAC(self.backend, self.user) # set args self.tag_type = self.backend.schema.node(ns.bsfs.Tag) self.ent_type = self.backend.schema.node(ns.bsfs.Entity) @@ -128,65 +130,65 @@ class TestNodes(unittest.TestCase): def test_str(self): # str baseline - nodes = Nodes(self.backend, self.user, self.ent_type, self.ent_ids) + nodes = Nodes(self.backend, self.ac, self.ent_type, self.ent_ids) self.assertEqual(str(nodes), f'Nodes({self.ent_type}, {self.ent_ids})') - self.assertEqual(repr(nodes), f'Nodes({self.backend}, {self.user}, {self.ent_type}, {self.ent_ids})') + self.assertEqual(repr(nodes), f'Nodes({self.backend}, {self.ac}, {self.ent_type}, {self.ent_ids})') # str respects node_type - nodes = Nodes(self.backend, self.user, self.tag_type, self.tag_ids) + nodes = Nodes(self.backend, self.ac, self.tag_type, self.tag_ids) self.assertEqual(str(nodes), f'Nodes({self.tag_type}, {self.tag_ids})') - self.assertEqual(repr(nodes), f'Nodes({self.backend}, {self.user}, {self.tag_type}, {self.tag_ids})') + self.assertEqual(repr(nodes), f'Nodes({self.backend}, {self.ac}, {self.tag_type}, {self.tag_ids})') # str respects guids - nodes = Nodes(self.backend, self.user, self.ent_type, {URI('http://example.com/me/entity#foo')}) + nodes = Nodes(self.backend, self.ac, self.ent_type, {URI('http://example.com/me/entity#foo')}) self.assertEqual(str(nodes), f'Nodes({self.ent_type}, {{\'http://example.com/me/entity#foo\'}})') - self.assertEqual(repr(nodes), f'Nodes({self.backend}, {self.user}, {self.ent_type}, {{\'http://example.com/me/entity#foo\'}})') + self.assertEqual(repr(nodes), f'Nodes({self.backend}, {self.ac}, {self.ent_type}, {{\'http://example.com/me/entity#foo\'}})') # repr respects backend class Foo(SparqlStore): pass backend = Foo.Open() backend.schema = self.backend.schema - nodes = Nodes(backend, self.user, self.ent_type, self.ent_ids) - self.assertEqual(repr(nodes), f'Nodes({backend}, {self.user}, {self.ent_type}, {self.ent_ids})') + nodes = Nodes(backend, self.ac, self.ent_type, self.ent_ids) + self.assertEqual(repr(nodes), f'Nodes({backend}, {self.ac}, {self.ent_type}, {self.ent_ids})') # repr respects user - nodes = Nodes(self.backend, URI('http://example.com/you'), self.ent_type, self.ent_ids) - self.assertEqual(repr(nodes), f'Nodes({self.backend}, http://example.com/you, {self.ent_type}, {self.ent_ids})') + nodes = Nodes(self.backend, NullAC(self.backend, URI('http://example.com/you')), self.ent_type, self.ent_ids) + self.assertEqual(repr(nodes), f'Nodes({self.backend}, NullAC(http://example.com/you), {self.ent_type}, {self.ent_ids})') def test_equality(self): - nodes = Nodes(self.backend, self.user, self.ent_type, self.ent_ids) + nodes = Nodes(self.backend, self.ac, self.ent_type, self.ent_ids) # instance is equal to itself self.assertEqual(nodes, nodes) self.assertEqual(hash(nodes), hash(nodes)) # instance is equal to a clone - self.assertEqual(nodes, Nodes(self.backend, self.user, self.ent_type, self.ent_ids)) - self.assertEqual(Nodes(self.backend, self.user, self.ent_type, self.ent_ids), nodes) - self.assertEqual(hash(nodes), hash(Nodes(self.backend, self.user, self.ent_type, self.ent_ids))) + self.assertEqual(nodes, Nodes(self.backend, self.ac, self.ent_type, self.ent_ids)) + self.assertEqual(Nodes(self.backend, self.ac, self.ent_type, self.ent_ids), nodes) + self.assertEqual(hash(nodes), hash(Nodes(self.backend, self.ac, self.ent_type, self.ent_ids))) # equality respects backend backend = SparqlStore.Open() backend.schema = self.backend.schema - self.assertNotEqual(nodes, Nodes(backend, self.user, self.ent_type, self.ent_ids)) - self.assertNotEqual(hash(nodes), hash(Nodes(backend, self.user, self.ent_type, self.ent_ids))) + self.assertNotEqual(nodes, Nodes(backend, self.ac, self.ent_type, self.ent_ids)) + self.assertNotEqual(hash(nodes), hash(Nodes(backend, self.ac, self.ent_type, self.ent_ids))) # equality respects user - self.assertNotEqual(nodes, Nodes(self.backend, URI('http://example.com/you'), self.ent_type, self.ent_ids)) - self.assertNotEqual(hash(nodes), hash(Nodes(self.backend, URI('http://example.com/you'), self.ent_type, self.ent_ids))) + self.assertNotEqual(nodes, Nodes(self.backend, NullAC(self.backend, URI('http://example.com/you')), self.ent_type, self.ent_ids)) + self.assertNotEqual(hash(nodes), hash(Nodes(self.backend, NullAC(self.backend, URI('http://example.com/you')), self.ent_type, self.ent_ids))) # equality respects node_type - self.assertNotEqual(nodes, Nodes(self.backend, self.user, self.tag_type, self.ent_ids)) - self.assertNotEqual(hash(nodes), hash(Nodes(self.backend, self.user, self.tag_type, self.ent_ids))) + self.assertNotEqual(nodes, Nodes(self.backend, self.ac, self.tag_type, self.ent_ids)) + self.assertNotEqual(hash(nodes), hash(Nodes(self.backend, self.ac, self.tag_type, self.ent_ids))) # equality respects guids - self.assertNotEqual(nodes, Nodes(self.backend, self.user, self.ent_type, self.tag_ids)) - self.assertNotEqual(hash(nodes), hash(Nodes(self.backend, self.user, self.ent_type, self.tag_ids))) + self.assertNotEqual(nodes, Nodes(self.backend, self.ac, self.ent_type, self.tag_ids)) + self.assertNotEqual(hash(nodes), hash(Nodes(self.backend, self.ac, self.ent_type, self.tag_ids))) def test_properties(self): # node_type self.assertEqual(self.ent_type, Nodes( - self.backend, self.user, self.ent_type, self.ent_ids).node_type) + self.backend, self.ac, self.ent_type, self.ent_ids).node_type) self.assertEqual(self.tag_type, Nodes( - self.backend, self.user, self.tag_type, self.tag_ids).node_type) + self.backend, self.ac, self.tag_type, self.tag_ids).node_type) # guids self.assertSetEqual(self.ent_ids, set(Nodes( - self.backend, self.user, self.ent_type, self.ent_ids).guids)) + self.backend, self.ac, self.ent_type, self.ent_ids).guids)) self.assertSetEqual(self.tag_ids, set(Nodes( - self.backend, self.user, self.tag_type, self.tag_ids).guids)) + self.backend, self.ac, self.tag_type, self.tag_ids).guids)) def test__ensure_nodes(self): - nodes = Nodes(self.backend, self.user, self.ent_type, self.ent_ids) + nodes = Nodes(self.backend, self.ac, self.ent_type, self.ent_ids) # missing nodes are created self.assertSetEqual(self.ent_ids, nodes._ensure_nodes(self.ent_type, self.ent_ids)) @@ -235,7 +237,7 @@ class TestNodes(unittest.TestCase): def test___set(self): # setup - nodes = Nodes(self.backend, self.user, self.ent_type, {URI('http://example.com/me/entity#1234'), URI('http://example.com/me/entity#4321')}) + nodes = Nodes(self.backend, self.ac, self.ent_type, {URI('http://example.com/me/entity#1234'), URI('http://example.com/me/entity#4321')}) self.assertSetEqual(set(self.backend._graph), self.schema_triples | set()) set_ = nodes._Nodes__set @@ -264,7 +266,7 @@ class TestNodes(unittest.TestCase): }) # set node value - tags = Nodes(self.backend, self.user, self.tag_type, {URI('http://example.com/me/tag#1234'), URI('http://example.com/me/tag#4321')}) + tags = Nodes(self.backend, self.ac, self.tag_type, {URI('http://example.com/me/tag#1234'), URI('http://example.com/me/tag#4321')}) set_(self.p_tag.uri, tags) # get creation time from backend manually time_triples = list(self.backend._graph.objects(rdflib.URIRef('http://example.com/me/tag#1234'), rdflib.URIRef(self.t_created.uri))) @@ -296,11 +298,11 @@ class TestNodes(unittest.TestCase): self.assertRaises(TypeError, set_, self.p_tag.uri, URI('http://example.com/me/tag#1234')) # value's node_type must match the predicate's range self.assertRaises(errors.ConsistencyError, set_, self.p_tag.uri, - Nodes(self.backend, self.user, self.ent_type, self.ent_ids)) + Nodes(self.backend, self.ac, self.ent_type, self.ent_ids)) def test_set(self): self.assertSetEqual(set(self.backend._graph), self.schema_triples | set()) - nodes = Nodes(self.backend, self.user, self.ent_type, self.ent_ids) + nodes = Nodes(self.backend, self.ac, self.ent_type, self.ent_ids) # can set literal values self.assertEqual(nodes, nodes.set(self.p_filesize.uri, 1234)) self.assertTrue(set(self.backend._graph).issuperset({ @@ -312,7 +314,7 @@ class TestNodes(unittest.TestCase): (rdflib.URIRef('http://example.com/me/entity#4321'), rdflib.URIRef(self.p_filesize.uri), rdflib.Literal(1234, datatype=rdflib.XSD.integer)), })) # can set node values - self.assertEqual(nodes, nodes.set(self.p_tag.uri, Nodes(self.backend, self.user, self.tag_type, self.tag_ids))) + self.assertEqual(nodes, nodes.set(self.p_tag.uri, Nodes(self.backend, self.ac, self.tag_type, self.tag_ids))) self.assertTrue(set(self.backend._graph).issuperset({ # nodes exist (rdflib.URIRef('http://example.com/me/entity#1234'), rdflib.RDF.type, rdflib.URIRef('http://bsfs.ai/schema/Entity')), @@ -341,17 +343,17 @@ class TestNodes(unittest.TestCase): self.assertSetEqual(curr, set(self.backend._graph)) # cannot assing multiple values to unique predicate self.assertRaises(ValueError, nodes.set, self.p_author.uri, - Nodes(self.backend, self.user, self.user_type, {URI('http://example.com/me/user#1234'), URI('http://example.com/me/user#4321')})) + Nodes(self.backend, self.ac, self.user_type, {URI('http://example.com/me/user#1234'), URI('http://example.com/me/user#4321')})) self.assertSetEqual(curr, set(self.backend._graph)) def test_set_from_iterable(self): self.assertSetEqual(set(self.backend._graph), self.schema_triples | set()) - nodes = Nodes(self.backend, self.user, self.ent_type, self.ent_ids) + nodes = Nodes(self.backend, self.ac, self.ent_type, self.ent_ids) # can set literal and node values simultaneously self.assertEqual(nodes, nodes.set_from_iterable({ self.p_filesize.uri: 1234, - self.p_tag.uri: Nodes(self.backend, self.user, self.tag_type, self.tag_ids), + self.p_tag.uri: Nodes(self.backend, self.ac, self.tag_type, self.tag_ids), }.items())) self.assertTrue(set(self.backend._graph).issuperset({ # nodes exist @@ -383,24 +385,24 @@ class TestNodes(unittest.TestCase): self.assertSetEqual(curr, set(self.backend._graph)) # cannot assing multiple values to unique predicate self.assertRaises(ValueError, nodes.set_from_iterable, ((self.p_filesize.uri, 1234), - (self.p_author.uri, Nodes(self.backend, self.user, self.user_type, {URI('http://example.com/me/user#1234'), URI('http://example.com/me/user#4321')})))) + (self.p_author.uri, Nodes(self.backend, self.ac, self.user_type, {URI('http://example.com/me/user#1234'), URI('http://example.com/me/user#4321')})))) self.assertSetEqual(curr, set(self.backend._graph)) def test_get(self): # setup: add some instances - Nodes(self.backend, self.user, self.ent_type, {'http://example.com/me/entity#1234'}) \ + Nodes(self.backend, self.ac, self.ent_type, {'http://example.com/me/entity#1234'}) \ .set(ns.bse.comment, 'hello world') \ .set(ns.bse.filesize, 1234) \ - .set(ns.bse.tag, Nodes(self.backend, self.user, self.tag_type, {'http://example.com/me/tag#1234'})) - Nodes(self.backend, self.user, self.ent_type, {'http://example.com/me/entity#4321'}) \ + .set(ns.bse.tag, Nodes(self.backend, self.ac, self.tag_type, {'http://example.com/me/tag#1234'})) + Nodes(self.backend, self.ac, self.ent_type, {'http://example.com/me/entity#4321'}) \ .set(ns.bse.filesize, 4321) \ - .set(ns.bse.tag, Nodes(self.backend, self.user, self.tag_type, {'http://example.com/me/tag#4321'})) - Nodes(self.backend, self.user, self.tag_type, {'http://example.com/me/tag#1234'}) \ + .set(ns.bse.tag, Nodes(self.backend, self.ac, self.tag_type, {'http://example.com/me/tag#4321'})) + Nodes(self.backend, self.ac, self.tag_type, {'http://example.com/me/tag#1234'}) \ .set(bst.label, 'tag_label_1234') - Nodes(self.backend, self.user, self.tag_type, {'http://example.com/me/tag#4321'}) \ + Nodes(self.backend, self.ac, self.tag_type, {'http://example.com/me/tag#4321'}) \ .set(bst.label, 'tag_label_4321') # setup: get nodes instance - nodes = Nodes(self.backend, self.user, self.ent_type, self.ent_ids) + nodes = Nodes(self.backend, self.ac, self.ent_type, self.ent_ids) # must pass at least one path self.assertRaises(AttributeError, nodes.get) # view must be list or dict @@ -409,22 +411,22 @@ class TestNodes(unittest.TestCase): self.assertRaises(ValueError, nodes.get, ns.bse.filesize, view=tuple) # can pass path as URI self.assertDictEqual(nodes.get(ns.bse.filesize), { - Nodes(self.backend, self.user, self.ent_type, {'http://example.com/me/entity#1234'}): 1234, - Nodes(self.backend, self.user, self.ent_type, {'http://example.com/me/entity#4321'}): 4321, + Nodes(self.backend, self.ac, self.ent_type, {'http://example.com/me/entity#1234'}): 1234, + Nodes(self.backend, self.ac, self.ent_type, {'http://example.com/me/entity#4321'}): 4321, }) # can pass path as sequence of URI self.assertDictEqual(nodes.get((ns.bse.tag, bst.label)), { - Nodes(self.backend, self.user, self.ent_type, {'http://example.com/me/entity#1234'}): {'tag_label_1234'}, - Nodes(self.backend, self.user, self.ent_type, {'http://example.com/me/entity#4321'}): {'tag_label_4321'}, + Nodes(self.backend, self.ac, self.ent_type, {'http://example.com/me/entity#1234'}): {'tag_label_1234'}, + Nodes(self.backend, self.ac, self.ent_type, {'http://example.com/me/entity#4321'}): {'tag_label_4321'}, }) # get returns the same path that was passed self.assertCountEqual(list(nodes.get((ns.bse.tag, bst.label), path=True, view=list)), [ - (Nodes(self.backend, self.user, self.ent_type, {'http://example.com/me/entity#1234'}), (ns.bse.tag, bst.label), 'tag_label_1234'), - (Nodes(self.backend, self.user, self.ent_type, {'http://example.com/me/entity#4321'}), (ns.bse.tag, bst.label), 'tag_label_4321'), + (Nodes(self.backend, self.ac, self.ent_type, {'http://example.com/me/entity#1234'}), (ns.bse.tag, bst.label), 'tag_label_1234'), + (Nodes(self.backend, self.ac, self.ent_type, {'http://example.com/me/entity#4321'}), (ns.bse.tag, bst.label), 'tag_label_4321'), ]) self.assertCountEqual(list(nodes.get([ns.bse.tag, bst.label], path=True, view=list)), [ - (Nodes(self.backend, self.user, self.ent_type, {'http://example.com/me/entity#1234'}), [ns.bse.tag, bst.label], 'tag_label_1234'), - (Nodes(self.backend, self.user, self.ent_type, {'http://example.com/me/entity#4321'}), [ns.bse.tag, bst.label], 'tag_label_4321'), + (Nodes(self.backend, self.ac, self.ent_type, {'http://example.com/me/entity#1234'}), [ns.bse.tag, bst.label], 'tag_label_1234'), + (Nodes(self.backend, self.ac, self.ent_type, {'http://example.com/me/entity#4321'}), [ns.bse.tag, bst.label], 'tag_label_4321'), ]) # paths must be URI or sequence thereof self.assertRaises(TypeError, nodes.get, 1234) @@ -435,34 +437,34 @@ class TestNodes(unittest.TestCase): self.assertRaises(errors.ConsistencyError, nodes.get, (ns.bse.tag, bst.invalid)) # can pass multiple paths self.assertDictEqual(nodes.get(ns.bse.filesize, (ns.bse.tag, bst.label)), { - Nodes(self.backend, self.user, self.ent_type, {'http://example.com/me/entity#1234'}): { + Nodes(self.backend, self.ac, self.ent_type, {'http://example.com/me/entity#1234'}): { ns.bse.filesize: 1234, (ns.bse.tag, bst.label): {'tag_label_1234'}, }, - Nodes(self.backend, self.user, self.ent_type, {'http://example.com/me/entity#4321'}): { + Nodes(self.backend, self.ac, self.ent_type, {'http://example.com/me/entity#4321'}): { ns.bse.filesize: 4321, (ns.bse.tag, bst.label): {'tag_label_4321'}, }, }) # get respects view self.assertDictEqual(nodes.get(ns.bse.filesize, view=dict), { - Nodes(self.backend, self.user, self.ent_type, {'http://example.com/me/entity#1234'}): 1234, - Nodes(self.backend, self.user, self.ent_type, {'http://example.com/me/entity#4321'}): 4321, + Nodes(self.backend, self.ac, self.ent_type, {'http://example.com/me/entity#1234'}): 1234, + Nodes(self.backend, self.ac, self.ent_type, {'http://example.com/me/entity#4321'}): 4321, }) self.assertSetEqual(set(nodes.get(ns.bse.filesize, view=list)), { - (Nodes(self.backend, self.user, self.ent_type, {'http://example.com/me/entity#1234'}), 1234), - (Nodes(self.backend, self.user, self.ent_type, {'http://example.com/me/entity#4321'}), 4321), + (Nodes(self.backend, self.ac, self.ent_type, {'http://example.com/me/entity#1234'}), 1234), + (Nodes(self.backend, self.ac, self.ent_type, {'http://example.com/me/entity#4321'}), 4321), }) # get returns Nodes instance when fetching a node self.assertDictEqual(nodes.get(ns.bse.tag), { - Nodes(self.backend, self.user, self.ent_type, {'http://example.com/me/entity#1234'}): - {Nodes(self.backend, self.user, self.tag_type, {'http://example.com/me/tag#1234'})}, - Nodes(self.backend, self.user, self.ent_type, {'http://example.com/me/entity#4321'}): - {Nodes(self.backend, self.user, self.tag_type, {'http://example.com/me/tag#4321'})}, + Nodes(self.backend, self.ac, self.ent_type, {'http://example.com/me/entity#1234'}): + {Nodes(self.backend, self.ac, self.tag_type, {'http://example.com/me/tag#1234'})}, + Nodes(self.backend, self.ac, self.ent_type, {'http://example.com/me/entity#4321'}): + {Nodes(self.backend, self.ac, self.tag_type, {'http://example.com/me/tag#4321'})}, }) # get returns a value when fetching a value and omits missing values self.assertDictEqual(nodes.get(ns.bse.comment), { - Nodes(self.backend, self.user, self.ent_type, {'http://example.com/me/entity#1234'}): {'hello world'}, + Nodes(self.backend, self.ac, self.ent_type, {'http://example.com/me/entity#1234'}): {'hello world'}, }) # FIXME: What if I call `get` with a single predicate and a single node, but @@ -471,7 +473,7 @@ class TestNodes(unittest.TestCase): raise NotImplementedError() def test_getattr(self): - nodes = Nodes(self.backend, self.user, self.ent_type, {'http://example.com/me/entity#1234'}) + nodes = Nodes(self.backend, self.ac, self.ent_type, {'http://example.com/me/entity#1234'}) # can get walks to values self.assertEqual(nodes.filesize, Walk(nodes, (self.p_filesize, ))) # can get walks to nodes @@ -482,11 +484,11 @@ class TestNodes(unittest.TestCase): self.assertRaises(ValueError, getattr, nodes, 'foobar') def test_schema(self): - self.assertEqual(Nodes(self.backend, self.user, self.ent_type, + self.assertEqual(Nodes(self.backend, self.ac, self.ent_type, {URI('http://example.com/me/entity#1234')}).schema, self.backend.schema) def test_operators(self): # __add__, __or__, __sub__, __and__ - gen = partial(Nodes, self.backend, self.user, self.ent_type) + gen = partial(Nodes, self.backend, self.ac, self.ent_type) nodes = gen({URI('http://example.com/me/entity#1234')}) # add/or concatenates guids self.assertEqual( @@ -544,23 +546,24 @@ class TestNodes(unittest.TestCase): self.assertRaises(TypeError, op, nodes, 'hello world') # backend must match self.assertRaises(ValueError, op, nodes, - Nodes(None, self.user, self.ent_type, {URI('http://example.com/me/entity#1234')})) - # user must match + Nodes(None, self.ac, self.ent_type, {URI('http://example.com/me/entity#1234')})) + # ac must match self.assertRaises(ValueError, op, nodes, - Nodes(self.backend, '', self.ent_type, {URI('http://example.com/me/entity#1234')})) + Nodes(self.backend, NullAC(self.backend, ''), + self.ent_type, {URI('http://example.com/me/entity#1234')})) # node type must match self.assertRaises(ValueError, op, nodes, - Nodes(self.backend, self.user, self.tag_type, {URI('http://example.com/me/entity#1234')})) + Nodes(self.backend, self.ac, self.tag_type, {URI('http://example.com/me/entity#1234')})) def test_len(self): - self.assertEqual(1, len(Nodes(self.backend, self.user, self.ent_type, { + self.assertEqual(1, len(Nodes(self.backend, self.ac, self.ent_type, { URI('http://example.com/me/entity#1234'), }))) - self.assertEqual(2, len(Nodes(self.backend, self.user, self.ent_type, { + self.assertEqual(2, len(Nodes(self.backend, self.ac, self.ent_type, { URI('http://example.com/me/entity#1234'), URI('http://example.com/me/entity#4321'), }))) - self.assertEqual(4, len(Nodes(self.backend, self.user, self.ent_type, { + self.assertEqual(4, len(Nodes(self.backend, self.ac, self.ent_type, { URI('http://example.com/me/entity#1234'), URI('http://example.com/me/entity#4321'), URI('http://example.com/me/entity#5678'), @@ -568,8 +571,8 @@ class TestNodes(unittest.TestCase): }))) def test_iter(self): # __iter__ - gen = partial(Nodes, self.backend, self.user, self.ent_type) - self.assertSetEqual(set(Nodes(self.backend, self.user, self.ent_type, { + gen = partial(Nodes, self.backend, self.ac, self.ent_type) + self.assertSetEqual(set(Nodes(self.backend, self.ac, self.ent_type, { URI('http://example.com/me/entity#1234'), URI('http://example.com/me/entity#4321'), URI('http://example.com/me/entity#5678'), diff --git a/test/graph/test_walk.py b/test/graph/test_walk.py index f9dbc7a..e5c8981 100644 --- a/test/graph/test_walk.py +++ b/test/graph/test_walk.py @@ -10,6 +10,7 @@ import unittest # bsfs imports from bsfs import schema as bsc from bsfs.graph import Graph +from bsfs.graph.ac import NullAC from bsfs.namespace import Namespace, ns from bsfs.triple_store.sparql import SparqlStore from bsfs.utils import URI @@ -65,7 +66,8 @@ class TestWalk(unittest.TestCase): ''') self.backend = SparqlStore.Open() self.user = URI('http://example.com/me') - self.graph = Graph(self.backend, self.user) + self.ac = NullAC(self.backend, self.user) + self.graph = Graph(self.backend, self.ac) self.graph.migrate(self.schema) # nodes setup |