aboutsummaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/triple_store/sparql/test_parse_fetch.py263
-rw-r--r--test/triple_store/sparql/test_parse_filter.py150
-rw-r--r--test/triple_store/sparql/test_sparql.py70
-rw-r--r--test/triple_store/sparql/test_utils.py155
-rw-r--r--test/triple_store/test_base.py3
5 files changed, 566 insertions, 75 deletions
diff --git a/test/triple_store/sparql/test_parse_fetch.py b/test/triple_store/sparql/test_parse_fetch.py
new file mode 100644
index 0000000..0961789
--- /dev/null
+++ b/test/triple_store/sparql/test_parse_fetch.py
@@ -0,0 +1,263 @@
+"""
+
+Part of the bsfs test suite.
+A copy of the license is provided with the project.
+Author: Matthias Baumgartner, 2022
+"""
+# imports
+import rdflib
+import unittest
+
+# bsie imports
+from bsfs import schema
+from bsfs.namespace import Namespace, ns
+from bsfs.query import ast
+from bsfs.utils import errors, URI
+
+# objects to test
+from bsfs.triple_store.sparql.parse_fetch import Fetch
+
+
+## code ##
+
+bsfs = Namespace('http://bsfs.ai/schema', fsep='/')
+bse = Namespace('http://bsfs.ai/schema/Entity')
+bst = Namespace('http://bsfs.ai/schema/Tag')
+bsc = Namespace('http://bsfs.ai/schema/Collection')
+
+class TestParseFetch(unittest.TestCase):
+
+ def setUp(self):
+ self.schema = schema.from_string('''
+ prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
+ prefix xsd: <http://www.w3.org/2001/XMLSchema#>
+
+ prefix bsfs: <http://bsfs.ai/schema/>
+ prefix bse: <http://bsfs.ai/schema/Entity#>
+ prefix bst: <http://bsfs.ai/schema/Tag#>
+ prefix bsc: <http://bsfs.ai/schema/Collection#>
+
+ # nodes
+ bsfs:Entity rdfs:subClassOf bsfs:Node .
+ bsfs:Tag rdfs:subClassOf bsfs:Node .
+ bsfs:Collection rdfs:subClassOf bsfs:Node .
+
+ # literals
+ xsd:integer rdfs:subClassOf bsfs:Literal .
+ xsd:string rdfs:subClassOf bsfs:Literal .
+
+ # predicates
+ bse:tag rdfs:subClassOf bsfs:Predicate ;
+ rdfs:domain bsfs:Entity ;
+ rdfs:range bsfs:Tag .
+
+ bse:collection rdfs:subClassOf bsfs:Predicate ;
+ rdfs:domain bsfs:Entity ;
+ rdfs:range bsfs:Collection .
+
+ bse:filename rdfs:subClassOf bsfs:Predicate ;
+ rdfs:domain bsfs:Entity ;
+ rdfs:range xsd:string .
+
+ bse:rank rdfs:subClassOf bsfs:Predicate ;
+ rdfs:domain bsfs:Entity ;
+ rdfs:range xsd:integer .
+
+ bst:main rdfs:subClassOf bsfs:Predicate ;
+ rdfs:domain bsfs:Tag ;
+ rdfs:range bsfs:Entity .
+
+ bst:label rdfs:subClassOf bsfs:Predicate ;
+ rdfs:domain bsfs:Tag ;
+ rdfs:range xsd:string .
+
+ bsc:tag rdfs:subClassOf bsfs:Predicate ;
+ rdfs:domain bsfs:Collection ;
+ rdfs:range bsfs:Tag .
+
+ bsc:label rdfs:subClassOf bsfs:Predicate ;
+ rdfs:domain bsfs:Collection ;
+ rdfs:range xsd:string .
+
+ bsc:rating rdfs:subClassOf bsfs:Predicate ;
+ rdfs:domain bsfs:Collection ;
+ rdfs:range xsd:integer .
+
+ ''')
+
+ # graph to test queries
+ self.graph = rdflib.Graph()
+ # schema hierarchies
+ self.graph.add((rdflib.URIRef('http://bsfs.ai/schema/Entity'), rdflib.RDFS.subClassOf, rdflib.URIRef('http://bsfs.ai/schema/Node')))
+ self.graph.add((rdflib.URIRef('http://bsfs.ai/schema/Collection'), rdflib.RDFS.subClassOf, rdflib.URIRef('http://bsfs.ai/schema/Node')))
+ self.graph.add((rdflib.URIRef('http://bsfs.ai/schema/Tag'), rdflib.RDFS.subClassOf, rdflib.URIRef('http://bsfs.ai/schema/Node')))
+ # entities
+ self.graph.add((rdflib.URIRef('http://example.com/entity#1234'), rdflib.RDF.type, rdflib.URIRef('http://bsfs.ai/schema/Entity')))
+ self.graph.add((rdflib.URIRef('http://example.com/entity#4321'), rdflib.RDF.type, rdflib.URIRef('http://bsfs.ai/schema/Entity')))
+ # tags
+ self.graph.add((rdflib.URIRef('http://example.com/tag#1234'), rdflib.RDF.type, rdflib.URIRef('http://bsfs.ai/schema/Tag')))
+ self.graph.add((rdflib.URIRef('http://example.com/tag#4321'), rdflib.RDF.type, rdflib.URIRef('http://bsfs.ai/schema/Tag')))
+ # collections
+ self.graph.add((rdflib.URIRef('http://example.com/collection#1234'), rdflib.RDF.type, rdflib.URIRef('http://bsfs.ai/schema/Collection')))
+ self.graph.add((rdflib.URIRef('http://example.com/collection#4321'), rdflib.RDF.type, rdflib.URIRef('http://bsfs.ai/schema/Collection')))
+ # entity literals
+ self.graph.add((rdflib.URIRef('http://example.com/entity#1234'), rdflib.URIRef(bse.rank), rdflib.Literal('1234', datatype=rdflib.XSD.integer)))
+ self.graph.add((rdflib.URIRef('http://example.com/entity#1234'), rdflib.URIRef(bse.filename), rdflib.Literal('filename_1234', datatype=rdflib.XSD.string)))
+ #self.graph.add((rdflib.URIRef('http://example.com/entity#4321'), rdflib.URIRef(bse.rank), rdflib.Literal('4321', datatype=rdflib.XSD.integer)))
+ self.graph.add((rdflib.URIRef('http://example.com/entity#4321'), rdflib.URIRef(bse.filename), rdflib.Literal('filename_4321', datatype=rdflib.XSD.string)))
+ # tag literals
+ self.graph.add((rdflib.URIRef('http://example.com/tag#1234'), rdflib.URIRef(bst.label), rdflib.Literal('tag_label_1234', datatype=rdflib.XSD.string)))
+ self.graph.add((rdflib.URIRef('http://example.com/tag#4321'), rdflib.URIRef(bst.label), rdflib.Literal('tag_label_4321', datatype=rdflib.XSD.string)))
+ # collection literals
+ self.graph.add((rdflib.URIRef('http://example.com/collection#1234'), rdflib.URIRef(bsc.label), rdflib.Literal('collection_label_1234', datatype=rdflib.XSD.string)))
+ self.graph.add((rdflib.URIRef('http://example.com/collection#1234'), rdflib.URIRef(bsc.rating), rdflib.Literal('1234', datatype=rdflib.XSD.integer)))
+ self.graph.add((rdflib.URIRef('http://example.com/collection#4321'), rdflib.URIRef(bsc.label), rdflib.Literal('collection_label_4321', datatype=rdflib.XSD.string)))
+ self.graph.add((rdflib.URIRef('http://example.com/collection#4321'), rdflib.URIRef(bsc.rating), rdflib.Literal('4321', datatype=rdflib.XSD.integer)))
+ # entity-tag links
+ self.graph.add((rdflib.URIRef('http://example.com/entity#1234'), rdflib.URIRef(bse.tag), rdflib.URIRef('http://example.com/tag#1234')))
+ self.graph.add((rdflib.URIRef('http://example.com/entity#4321'), rdflib.URIRef(bse.tag), rdflib.URIRef('http://example.com/tag#4321')))
+ # entity-collection links
+ self.graph.add((rdflib.URIRef('http://example.com/entity#1234'), rdflib.URIRef(bse.collection), rdflib.URIRef('http://example.com/collection#1234')))
+ self.graph.add((rdflib.URIRef('http://example.com/entity#4321'), rdflib.URIRef(bse.collection), rdflib.URIRef('http://example.com/collection#4321')))
+ # collection-tag links
+ self.graph.add((rdflib.URIRef('http://example.com/collection#1234'), rdflib.URIRef(bsc.tag), rdflib.URIRef('http://example.com/tag#1234')))
+ self.graph.add((rdflib.URIRef('http://example.com/collection#4321'), rdflib.URIRef(bsc.tag), rdflib.URIRef('http://example.com/tag#4321')))
+ # tag-entity links # NOTE: cross-over
+ self.graph.add((rdflib.URIRef('http://example.com/tag#1234'), rdflib.URIRef(bst.main), rdflib.URIRef('http://example.com/entity#4321')))
+ self.graph.add((rdflib.URIRef('http://example.com/tag#4321'), rdflib.URIRef(bst.main), rdflib.URIRef('http://example.com/entity#1234')))
+
+ # default parser
+ self.parser = Fetch(self.schema)
+ self.ent = self.schema.node(ns.bsfs.Entity)
+
+
+ def test_call(self):
+ # NOTE: The individual ast components are considered in the respective tests. Here, we test __call__ specifics.
+
+ # __call__ requires a valid root type
+ self.assertRaises(errors.BackendError, self.parser, self.schema.literal(ns.bsfs.Literal), ast.fetch.This('this'))
+ self.assertRaises(errors.ConsistencyError, self.parser, self.schema.node(ns.bsfs.Node).child(ns.bsfs.Invalid), ast.fetch.This('this'))
+ # __call__ requires a parseable root
+ self.assertRaises(errors.BackendError, self.parser, self.ent, ast.filter.FilterExpression())
+ # __call__ returns an executable query
+ q = self.parser(self.ent, ast.fetch.Fetch(bse.tag, ast.fetch.Value(bst.label, 'label')))
+ self.assertSetEqual(set(q(self.graph)), {
+ (rdflib.URIRef('http://example.com/entity#1234'), rdflib.Literal('tag_label_1234', datatype=rdflib.XSD.string)),
+ (rdflib.URIRef('http://example.com/entity#4321'), rdflib.Literal('tag_label_4321', datatype=rdflib.XSD.string)),
+ })
+
+
+ def test_routing(self):
+ self.assertRaises(errors.BackendError, self.parser._parse_fetch_expression, self.ent, ast.fetch.FetchExpression(), '?head')
+
+
+ def test_all(self):
+ # multiple values query
+ q = self.parser(self.ent, ast.fetch.All(
+ ast.fetch.Value(bse.filename, name='filename'),
+ ast.fetch.Value(bse.rank, name='rank')),
+ )
+ self.assertSetEqual(set(q.names), {'filename', 'rank'})
+ if q.names == ('filename', 'rank'):
+ self.assertSetEqual(set(q(self.graph)), {
+ (rdflib.URIRef('http://example.com/entity#1234'), rdflib.Literal('filename_1234', datatype=rdflib.XSD.string), rdflib.Literal('1234', datatype=rdflib.XSD.integer)),
+ (rdflib.URIRef('http://example.com/entity#4321'), rdflib.Literal('filename_4321', datatype=rdflib.XSD.string), None),
+ })
+ else:
+ self.assertSetEqual(set(q(self.graph)), {
+ (rdflib.URIRef('http://example.com/entity#1234'), rdflib.Literal('1234', datatype=rdflib.XSD.integer), rdflib.Literal('filename_1234', datatype=rdflib.XSD.string)),
+ (rdflib.URIRef('http://example.com/entity#4321'), None, rdflib.Literal('filename_4321', datatype=rdflib.XSD.string)),
+ })
+ # mixed values and node query
+ q = self.parser(self.ent, ast.fetch.All(
+ ast.fetch.Value(bse.filename, name='filename'),
+ ast.fetch.Node(bse.tag, name='tag'),
+ ))
+ self.assertSetEqual(set(q.names), {'filename', 'tag'})
+ if q.names == ('filename', 'tag'):
+ self.assertSetEqual(set(q(self.graph)), {
+ (rdflib.URIRef('http://example.com/entity#1234'), rdflib.Literal('filename_1234', datatype=rdflib.XSD.string), rdflib.URIRef('http://example.com/tag#1234')),
+ (rdflib.URIRef('http://example.com/entity#4321'), rdflib.Literal('filename_4321', datatype=rdflib.XSD.string), rdflib.URIRef('http://example.com/tag#4321')),
+ })
+ else:
+ self.assertSetEqual(set(q(self.graph)), {
+ (rdflib.URIRef('http://example.com/entity#1234'), rdflib.URIRef('http://example.com/tag#1234'), rdflib.Literal('filename_1234', datatype=rdflib.XSD.string)),
+ (rdflib.URIRef('http://example.com/entity#4321'), rdflib.URIRef('http://example.com/tag#4321'), rdflib.Literal('filename_4321', datatype=rdflib.XSD.string)),
+ })
+ # multiple values and second hop
+ q = self.parser(self.ent, ast.fetch.Fetch(bse.tag, ast.fetch.All(
+ ast.fetch.This(name='tag'),
+ ast.fetch.Value(bst.label, name='label'),
+ )))
+ self.assertSetEqual(set(q.names), {'tag', 'label'})
+ if q.names == ('tag', 'label'):
+ self.assertSetEqual(set(q(self.graph)), {
+ (rdflib.URIRef('http://example.com/entity#1234'), rdflib.URIRef('http://example.com/tag#1234'), rdflib.Literal('tag_label_1234', datatype=rdflib.XSD.string)),
+ (rdflib.URIRef('http://example.com/entity#4321'), rdflib.URIRef('http://example.com/tag#4321'), rdflib.Literal('tag_label_4321', datatype=rdflib.XSD.string)),
+ })
+ else:
+ self.assertSetEqual(set(q(self.graph)), {
+ (rdflib.URIRef('http://example.com/entity#1234'), rdflib.Literal('tag_label_1234', datatype=rdflib.XSD.string), rdflib.URIRef('http://example.com/tag#1234')),
+ (rdflib.URIRef('http://example.com/entity#4321'), rdflib.Literal('tag_label_4321', datatype=rdflib.XSD.string), rdflib.URIRef('http://example.com/tag#4321')),
+ })
+
+
+
+ def test_fetch(self):
+ # two-hop query
+ q = self.parser(self.ent, ast.fetch.Fetch(bse.tag, ast.fetch.Value(bst.label, 'tag_label')))
+ self.assertSetEqual(set(q(self.graph)), {
+ (rdflib.URIRef('http://example.com/entity#1234'), rdflib.Literal('tag_label_1234', datatype=rdflib.XSD.string)),
+ (rdflib.URIRef('http://example.com/entity#4321'), rdflib.Literal('tag_label_4321', datatype=rdflib.XSD.string)),
+ })
+ # three-hop-query
+ q = self.parser(self.ent, ast.fetch.Fetch(bse.tag, ast.fetch.Fetch(bst.main, ast.fetch.Value(bse.rank, 'entity_rank'))))
+ self.assertSetEqual(set(q(self.graph)), {
+ (rdflib.URIRef('http://example.com/entity#1234'), None),
+ (rdflib.URIRef('http://example.com/entity#4321'), rdflib.Literal('1234', datatype=rdflib.XSD.integer)),
+ })
+
+
+ def test_node(self):
+ # cannot use the internal hop name
+ self.assertRaises(errors.BackendError, self.parser, self.ent, ast.fetch.Node(bse.tag, self.parser.ngen.prefix[1:] + '123'))
+ # a simple Node statement
+ q = self.parser(self.ent, ast.fetch.Node(bse.tag, 'tag'))
+ self.assertSetEqual(set(q.names), {'tag'})
+ self.assertSetEqual(set(q(self.graph)), {
+ (rdflib.URIRef('http://example.com/entity#1234'), rdflib.URIRef('http://example.com/tag#1234')),
+ (rdflib.URIRef('http://example.com/entity#4321'), rdflib.URIRef('http://example.com/tag#4321')),
+ })
+
+
+ def test_value(self):
+ # cannot use the internal hop name
+ self.assertRaises(errors.BackendError, self.parser, self.schema.node(ns.bsfs.Entity), ast.fetch.Value(bse.filename, self.parser.ngen.prefix[1:] + '123'))
+ # a simple Value statement
+ q = self.parser(self.ent, ast.fetch.Value(bse.filename, 'filename'))
+ self.assertSetEqual(set(q.names), {'filename'})
+ self.assertSetEqual(set(q(self.graph)), {
+ (rdflib.URIRef('http://example.com/entity#1234'), rdflib.Literal('filename_1234', datatype=rdflib.XSD.string)),
+ (rdflib.URIRef('http://example.com/entity#4321'), rdflib.Literal('filename_4321', datatype=rdflib.XSD.string)),
+ })
+
+
+ def test_this(self):
+ # cannot use the internal hop name
+ self.assertRaises(errors.BackendError, self.parser, self.ent, ast.fetch.This(self.parser.ngen.prefix[1:] + '123'))
+ # a simple This statement
+ self.assertEqual(self.parser._this(self.ent, ast.fetch.This('this'), '?head'),
+ ({('?head', 'this')}, ''))
+ q = self.parser(self.ent, ast.fetch.This('this'))
+ self.assertSetEqual(set(q(self.graph)), {
+ (rdflib.URIRef('http://example.com/entity#1234'), rdflib.URIRef('http://example.com/entity#1234')),
+ (rdflib.URIRef('http://example.com/entity#4321'), rdflib.URIRef('http://example.com/entity#4321')),
+ })
+
+
+## main ##
+
+if __name__ == '__main__':
+ unittest.main()
+
+## EOF ##
diff --git a/test/triple_store/sparql/test_parse_filter.py b/test/triple_store/sparql/test_parse_filter.py
index 8764535..6fa0cd3 100644
--- a/test/triple_store/sparql/test_parse_filter.py
+++ b/test/triple_store/sparql/test_parse_filter.py
@@ -149,13 +149,13 @@ class TestParseFilter(unittest.TestCase):
ast.filter.Or(
ast.filter.Is('http://example.com/entity#1234'),
ast.filter.Is('http://example.com/entity#5678')))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)}, {'http://example.com/entity#1234'})
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)}, {'http://example.com/entity#1234'})
# root is optional
q = self.parser(self.schema.node(ns.bsfs.Entity))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)},
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)},
{'http://example.com/entity#1234', 'http://example.com/entity#4321', 'http://example.com/image#1234', 'http://example.com/image#4321'})
q = self.parser(self.schema.node(ns.bsfs.Tag))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)},
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)},
{'http://example.com/tag#1234', 'http://example.com/tag#4321'})
@@ -164,7 +164,7 @@ class TestParseFilter(unittest.TestCase):
self.assertRaises(errors.BackendError, self.parser._is, self.schema.literal(ns.bsfs.Literal), ast.filter.Is('http://example.com/entity#1234'), '?ent')
# a single Is statement
q = self.parser(self.schema.node(ns.bsfs.Entity), ast.filter.Is('http://example.com/entity#1234'))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)},
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)},
{'http://example.com/entity#1234'})
# an aggregate of Is statements
q = self.parser(self.schema.node(ns.bsfs.Entity),
@@ -172,7 +172,7 @@ class TestParseFilter(unittest.TestCase):
ast.filter.Is('http://example.com/entity#1234'),
ast.filter.Is('http://example.com/entity#4321'),
))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)},
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)},
{'http://example.com/entity#1234', 'http://example.com/entity#4321'})
# combined with other filters
q = self.parser(self.schema.node(ns.bsfs.Entity),
@@ -185,12 +185,12 @@ class TestParseFilter(unittest.TestCase):
ast.filter.Equals('Me, Myself, and I')
),
))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)},
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)},
{'http://example.com/entity#1234'})
# as argument of Any/All
q = self.parser(self.schema.node(ns.bsfs.Entity),
ast.filter.Any(ns.bse.tag, ast.filter.Is('http://example.com/tag#1234')))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)},
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)},
{'http://example.com/entity#1234', 'http://example.com/image#1234'})
@@ -199,15 +199,15 @@ class TestParseFilter(unittest.TestCase):
self.assertRaises(errors.BackendError, self.parser._equals, self.schema.node(ns.bsfs.Entity), ast.filter.Equals('hello world'), '?ent')
# a single Equals statement
q = self.parser(self.schema.node(ns.bsfs.Entity), ast.filter.Any(ns.bse.comment, ast.filter.Equals('hello world')))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)},
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)},
{'http://example.com/entity#1234', 'http://example.com/entity#4321'})
# a single Equals statement that includes subtypes
q = self.parser(self.schema.node(ns.bsfs.Entity), ast.filter.Any(ns.bse.comment, ast.filter.Equals('Me, Myself, and I')))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)},
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)},
{'http://example.com/entity#1234', 'http://example.com/image#1234'})
# an Equals statement on an integer
q = self.parser(self.schema.node(ns.bsfs.Entity), ast.filter.Any(ns.bse.filesize, ast.filter.Equals(4321)))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)},
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)},
{'http://example.com/entity#4321', 'http://example.com/image#4321'})
@@ -216,18 +216,18 @@ class TestParseFilter(unittest.TestCase):
self.assertRaises(errors.BackendError, self.parser._substring, self.schema.node(ns.bsfs.Entity), ast.filter.Substring('hello world'), '?ent')
# a single Substring statement
q = self.parser(self.schema.node(ns.bsfs.Entity), ast.filter.Any(ns.bse.comment, ast.filter.Substring('hello')))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)},
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)},
{'http://example.com/entity#1234', 'http://example.com/entity#4321'})
q = self.parser(self.schema.node(ns.bsfs.Entity), ast.filter.Any(ns.bse.comment, ast.filter.Substring('lo wo')))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)},
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)},
{'http://example.com/entity#1234', 'http://example.com/entity#4321'})
# a single Substring statement that includes subtypes
q = self.parser(self.schema.node(ns.bsfs.Entity), ast.filter.Any(ns.bse.comment, ast.filter.Substring('Myself')))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)},
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)},
{'http://example.com/entity#1234', 'http://example.com/image#1234'})
# an Substring statement on an integer
q = self.parser(self.schema.node(ns.bsfs.Entity), ast.filter.Any(ns.bse.filesize, ast.filter.Substring('32')))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)},
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)},
{'http://example.com/entity#4321', 'http://example.com/image#4321'})
@@ -236,15 +236,15 @@ class TestParseFilter(unittest.TestCase):
self.assertRaises(errors.BackendError, self.parser._starts_with, self.schema.node(ns.bsfs.Entity), ast.filter.StartsWith('hello world'), '?ent')
# a single StartsWith statement
q = self.parser(self.schema.node(ns.bsfs.Entity), ast.filter.Any(ns.bse.comment, ast.filter.StartsWith('hello')))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)},
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)},
{'http://example.com/entity#1234', 'http://example.com/entity#4321'})
# a single StartsWith statement that includes subtypes
q = self.parser(self.schema.node(ns.bsfs.Entity), ast.filter.Any(ns.bse.comment, ast.filter.StartsWith('Me, Mys')))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)},
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)},
{'http://example.com/entity#1234', 'http://example.com/image#1234'})
# an StartsWith statement on an integer
q = self.parser(self.schema.node(ns.bsfs.Entity), ast.filter.Any(ns.bse.filesize, ast.filter.StartsWith(432)))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)},
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)},
{'http://example.com/entity#4321', 'http://example.com/image#4321'})
@@ -253,15 +253,15 @@ class TestParseFilter(unittest.TestCase):
self.assertRaises(errors.BackendError, self.parser._ends_with, self.schema.node(ns.bsfs.Entity), ast.filter.EndsWith('hello world'), '?ent')
# a single EndsWith statement
q = self.parser(self.schema.node(ns.bsfs.Entity), ast.filter.Any(ns.bse.comment, ast.filter.EndsWith('orld')))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)},
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)},
{'http://example.com/entity#1234', 'http://example.com/entity#4321'})
# a single EndsWith statement that includes subtypes
q = self.parser(self.schema.node(ns.bsfs.Entity), ast.filter.Any(ns.bse.comment, ast.filter.EndsWith('and I')))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)},
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)},
{'http://example.com/entity#1234', 'http://example.com/image#1234'})
# an EndsWith statement on an integer
q = self.parser(self.schema.node(ns.bsfs.Entity), ast.filter.Any(ns.bse.filesize, ast.filter.EndsWith(321)))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)},
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)},
{'http://example.com/entity#4321', 'http://example.com/image#4321'})
@@ -270,22 +270,22 @@ class TestParseFilter(unittest.TestCase):
self.assertRaises(errors.BackendError, self.parser._less_than, self.schema.node(ns.bsfs.Entity), ast.filter.LessThan(2000), '?ent')
# a single LessThan statement
q = self.parser(self.schema.node(ns.bsfs.Image), ast.filter.Any(ns.bse.iso, ast.filter.LessThan(2000)))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)},
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)},
{'http://example.com/image#1234'})
# _less_than respects boundary
q = self.parser(self.schema.node(ns.bsfs.Image), ast.filter.Any(ns.bse.iso, ast.filter.LessThan(1234, strict=True)))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)}, set())
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)}, set())
q = self.parser(self.schema.node(ns.bsfs.Image), ast.filter.Any(ns.bse.iso, ast.filter.LessThan(1234, strict=False)))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)},
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)},
{'http://example.com/image#1234'})
# a single LessThan statement that includes subtypes
q = self.parser(self.schema.node(ns.bsfs.Entity), ast.filter.Any(ns.bse.filesize, ast.filter.LessThan(2000)))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)},
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)},
{'http://example.com/entity#1234', 'http://example.com/image#1234'})
# an LessThan statement on a string
# always negative; note that http://example.com/tag#4321 is also not returned although its comment is a pure number
q = self.parser(self.schema.node(ns.bsfs.Entity), ast.filter.Any(ns.bse.comment, ast.filter.LessThan(10_000)))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)}, set())
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)}, set())
def test_greater_than(self):
@@ -293,22 +293,22 @@ class TestParseFilter(unittest.TestCase):
self.assertRaises(errors.BackendError, self.parser._greater_than, self.schema.node(ns.bsfs.Entity), ast.filter.GreaterThan(2000), '?ent')
# a single GreaterThan statement
q = self.parser(self.schema.node(ns.bsfs.Image), ast.filter.Any(ns.bse.iso, ast.filter.GreaterThan(2000)))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)},
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)},
{'http://example.com/image#4321'})
# _greater_than respects boundary
q = self.parser(self.schema.node(ns.bsfs.Image), ast.filter.Any(ns.bse.iso, ast.filter.GreaterThan(4321, strict=True)))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)}, set())
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)}, set())
q = self.parser(self.schema.node(ns.bsfs.Image), ast.filter.Any(ns.bse.iso, ast.filter.GreaterThan(4321, strict=False)))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)},
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)},
{'http://example.com/image#4321'})
# a single GreaterThan statement that includes subtypes
q = self.parser(self.schema.node(ns.bsfs.Entity), ast.filter.Any(ns.bse.filesize, ast.filter.GreaterThan(2000)))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)},
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)},
{'http://example.com/entity#4321', 'http://example.com/image#4321'})
# an GreaterThan statement on a string
# always positive
q = self.parser(self.schema.node(ns.bsfs.Entity), ast.filter.Any(ns.bse.comment, ast.filter.GreaterThan(0)))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)},
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)},
{'http://example.com/entity#1234', 'http://example.com/entity#4321', 'http://example.com/image#1234'})
@@ -331,7 +331,7 @@ class TestParseFilter(unittest.TestCase):
ast.filter.Any(ns.bse.filesize, ast.filter.Equals(1234)),
ast.filter.Any(ns.bse.comment, ast.filter.Equals('Me, Myself, and I')),
))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)},
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)},
{'http://example.com/entity#1234'})
# all conditions have to match
q = self.parser(self.schema.node(ns.bsfs.Entity),
@@ -340,21 +340,21 @@ class TestParseFilter(unittest.TestCase):
ast.filter.Any(ns.bse.filesize, ast.filter.Equals(1234)),
ast.filter.Any(ns.bse.comment, ast.filter.Equals('Me, Myself, and I')),
))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)}, set())
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)}, set())
q = self.parser(self.schema.node(ns.bsfs.Entity),
ast.filter.And(
ast.filter.Is('http://example.com/entity#1234'),
ast.filter.Any(ns.bse.filesize, ast.filter.Equals(4321)),
ast.filter.Any(ns.bse.comment, ast.filter.Equals('Me, Myself, and I')),
))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)}, set())
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)}, set())
q = self.parser(self.schema.node(ns.bsfs.Entity),
ast.filter.And(
ast.filter.Is('http://example.com/entity#1234'),
ast.filter.Any(ns.bse.filesize, ast.filter.Equals(1234)),
ast.filter.Any(ns.bse.comment, ast.filter.Equals('foobar')),
))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)}, set())
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)}, set())
# And can be nested
q = self.parser(self.schema.node(ns.bsfs.Entity),
ast.filter.And(
@@ -364,7 +364,7 @@ class TestParseFilter(unittest.TestCase):
ast.filter.Any(ns.bse.comment, ast.filter.Equals('Me, Myself, and I')),
),
))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)},
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)},
{'http://example.com/entity#1234'})
@@ -387,7 +387,7 @@ class TestParseFilter(unittest.TestCase):
ast.filter.Any(ns.bse.filesize, ast.filter.Equals(4321)),
ast.filter.Any(ns.bse.comment, ast.filter.Equals('Me, Myself, and I')),
))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)},
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)},
{'http://example.com/entity#1234', 'http://example.com/image#1234', 'http://example.com/entity#4321', 'http://example.com/image#4321'})
# at least one condition has to match
q = self.parser(self.schema.node(ns.bsfs.Entity),
@@ -396,14 +396,14 @@ class TestParseFilter(unittest.TestCase):
ast.filter.Any(ns.bse.filesize, ast.filter.Equals(8765)),
ast.filter.Any(ns.bse.comment, ast.filter.Equals('foobar')),
))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)}, set())
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)}, set())
q = self.parser(self.schema.node(ns.bsfs.Entity),
ast.filter.Or(
ast.filter.Is('http://example.com/entity#1234'),
ast.filter.Any(ns.bse.filesize, ast.filter.Equals(8765)),
ast.filter.Any(ns.bse.comment, ast.filter.Equals('foobar')),
))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)},
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)},
{'http://example.com/entity#1234'})
q = self.parser(self.schema.node(ns.bsfs.Entity),
ast.filter.Or(
@@ -411,7 +411,7 @@ class TestParseFilter(unittest.TestCase):
ast.filter.Any(ns.bse.filesize, ast.filter.Equals(4321)),
ast.filter.Any(ns.bse.comment, ast.filter.Equals('foobar')),
))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)},
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)},
{'http://example.com/entity#4321', 'http://example.com/image#4321'})
q = self.parser(self.schema.node(ns.bsfs.Entity),
ast.filter.Or(
@@ -419,7 +419,7 @@ class TestParseFilter(unittest.TestCase):
ast.filter.Any(ns.bse.filesize, ast.filter.Equals(8765)),
ast.filter.Any(ns.bse.comment, ast.filter.Equals('Me, Myself, and I')),
))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)},
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)},
{'http://example.com/entity#1234', 'http://example.com/image#1234'})
# Or can be nested
q = self.parser(self.schema.node(ns.bsfs.Entity),
@@ -430,7 +430,7 @@ class TestParseFilter(unittest.TestCase):
ast.filter.Any(ns.bse.comment, ast.filter.Equals('Me, Myself, and I')),
),
))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)},
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)},
{'http://example.com/entity#1234', 'http://example.com/image#1234', 'http://example.com/entity#4321', 'http://example.com/image#4321'})
@@ -451,14 +451,14 @@ class TestParseFilter(unittest.TestCase):
# _any returns a valid query
q = self.parser(self.schema.node(ns.bsfs.Entity),
ast.filter.Any(ns.bse.filesize, ast.filter.Equals(1234)))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)},
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)},
{'http://example.com/entity#1234', 'http://example.com/image#1234'})
# _any can be nested
q = self.parser(self.schema.node(ns.bsfs.Entity),
ast.filter.Any(ns.bse.tag,
ast.filter.Any(ns.bse.representative,
ast.filter.Is('http://example.com/image#1234'))))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)},
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)},
{'http://example.com/entity#1234', 'http://example.com/image#1234'})
@@ -468,12 +468,12 @@ class TestParseFilter(unittest.TestCase):
# All Nodes
q = self.parser(self.schema.node(ns.bsfs.Entity),
ast.filter.All(ns.bse.tag, ast.filter.Is('http://example.com/tag#1234')))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)},
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)},
{'http://example.com/entity#1234', 'http://example.com/image#1234'})
# All values
q = self.parser(self.schema.node(ns.bsfs.Entity),
ast.filter.All(ns.bse.comment, ast.filter.Equals('hello world')))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)},
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)},
{'http://example.com/entity#4321'})
# All on value within Or branch
# entity#1234 is selected because all of its comments are in ("hello world", "Me, Myself, and I")
@@ -481,12 +481,12 @@ class TestParseFilter(unittest.TestCase):
ast.filter.All(ns.bse.comment, ast.filter.Or(
ast.filter.Equals('hello world'),
ast.filter.Equals('Me, Myself, and I'))))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)},
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)},
{'http://example.com/entity#1234', 'http://example.com/entity#4321', 'http://example.com/image#1234'})
# All requires at least one predicate/value
q = self.parser(self.schema.node(ns.bsfs.Entity),
ast.filter.All(ns.bse.comment, ast.filter.Equals('Me, Myself, and I')))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)},
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)},
{'http://example.com/image#1234'})
# All within a statement
q = self.parser(self.schema.node(ns.bsfs.Entity),
@@ -498,18 +498,18 @@ class TestParseFilter(unittest.TestCase):
))
)
)
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)},
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)},
{'http://example.com/entity#1234', 'http://example.com/image#1234'})
# All with reversed Predicate
q = self.parser(self.schema.node(ns.bsfs.Tag),
ast.filter.All(ast.filter.Predicate(ns.bse.tag, reverse=True), ast.filter.Is('http://example.com/entity#4321')))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)},
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)},
{'http://example.com/tag#4321'})
# All with multiple predicates
q = self.parser(self.schema.node(ns.bsfs.Entity),
ast.filter.All(ast.filter.OneOf(ns.bse.tag, ns.bse.buddy), # entity#1234 (tag:tag#1234), entity#1234 (buddy:image#1234), image#1234(tag:tag#1234)
ast.filter.Any(ns.bse.comment, ast.filter.Equals('Me, Myself, and I')))) # entity#1234, image#1234, tag#1234
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)},
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)},
{'http://example.com/entity#1234', 'http://example.com/image#1234'})
@@ -518,22 +518,22 @@ class TestParseFilter(unittest.TestCase):
# Not applies on conditions
q = self.parser(self.schema.node(ns.bsfs.Entity),
ast.filter.Not(ast.filter.Is('http://example.com/entity#1234')))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)},
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)},
{'http://example.com/image#1234', 'http://example.com/entity#4321', 'http://example.com/image#4321'})
# Not applies on conditions within branches
q = self.parser(self.schema.node(ns.bsfs.Entity),
ast.filter.Any(ns.bse.comment, ast.filter.Not(ast.filter.Equals('Me, Myself, and I'))))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)},
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)},
{'http://example.com/entity#1234', 'http://example.com/entity#4321'})
# Not applies on branches
q = self.parser(self.schema.node(ns.bsfs.Entity),
ast.filter.Not(ast.filter.Any(ns.bse.comment, ast.filter.Equals('Me, Myself, and I'))))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)},
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)},
{'http://example.com/entity#4321', 'http://example.com/image#4321'})
# Double Not cancel each other
q = self.parser(self.schema.node(ns.bsfs.Entity),
ast.filter.Not(ast.filter.Not(ast.filter.Is('http://example.com/entity#1234'))))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)},
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)},
{'http://example.com/entity#1234'})
# Not works within aggregation (and)
q = self.parser(self.schema.node(ns.bsfs.Entity),
@@ -541,7 +541,7 @@ class TestParseFilter(unittest.TestCase):
ast.filter.Not(ast.filter.Is('http://example.com/entity#1234')),
ast.filter.Any(ns.bse.comment, ast.filter.Equals('hello world')),
))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)},
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)},
{'http://example.com/entity#4321'})
# Not works within aggregation (or)
q = self.parser(self.schema.node(ns.bsfs.Entity),
@@ -549,7 +549,7 @@ class TestParseFilter(unittest.TestCase):
ast.filter.Not(ast.filter.Is('http://example.com/entity#1234')),
ast.filter.Any(ns.bse.comment, ast.filter.Equals('Me, Myself, and I')),
))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)},
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)},
{'http://example.com/entity#1234', 'http://example.com/entity#4321', 'http://example.com/image#1234', 'http://example.com/image#4321'})
# Not works outside aggregation (and)
q = self.parser(self.schema.node(ns.bsfs.Entity),
@@ -558,7 +558,7 @@ class TestParseFilter(unittest.TestCase):
ast.filter.Is('http://example.com/entity#1234'),
ast.filter.Any(ns.bse.comment, ast.filter.Equals('hello world')),
)))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)},
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)},
{'http://example.com/entity#4321', 'http://example.com/image#1234', 'http://example.com/image#4321'})
# Not works outside aggregation (or)
q = self.parser(self.schema.node(ns.bsfs.Entity),
@@ -567,7 +567,7 @@ class TestParseFilter(unittest.TestCase):
ast.filter.Is('http://example.com/entity#4321'),
ast.filter.Any(ns.bse.comment, ast.filter.Equals('Me, Myself, and I')),
)))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)},
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)},
{'http://example.com/image#4321'})
# Not mixed with branch, aggregation, id, and value
q = self.parser(self.schema.node(ns.bsfs.Entity),
@@ -580,7 +580,7 @@ class TestParseFilter(unittest.TestCase):
),
ast.filter.Any(ns.bse.comment, ast.filter.Not(ast.filter.Equals('foobar'))), # entity#1234, entity#4321, image#1234
))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)},
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)},
{'http://example.com/image#1234'})
@@ -590,21 +590,21 @@ class TestParseFilter(unittest.TestCase):
# Has with GreaterThan constraint
q = self.parser(self.schema.node(ns.bsfs.Entity),
ast.filter.Has(ns.bse.comment, ast.filter.GreaterThan(0)))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)},
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)},
{'http://example.com/entity#1234', 'http://example.com/entity#4321', 'http://example.com/image#1234'})
q = self.parser(self.schema.node(ns.bsfs.Entity),
ast.filter.Has(ns.bse.comment, ast.filter.GreaterThan(1)))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)},
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)},
{'http://example.com/entity#1234'})
# Has with Equals constraint
q = self.parser(self.schema.node(ns.bsfs.Entity),
ast.filter.Has(ns.bse.comment, 1))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)},
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)},
{'http://example.com/entity#4321', 'http://example.com/image#1234'})
# Has with LessThan constraint
q = self.parser(self.schema.node(ns.bsfs.Entity),
ast.filter.Has(ns.bse.comment, ast.filter.LessThan(2)))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)},
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)},
{'http://example.com/entity#4321', 'http://example.com/image#1234', 'http://example.com/image#4321'})
# Has with multiple constraints
self.graph.add((rdflib.URIRef('http://example.com/entity#1234'), rdflib.URIRef(ns.bse.comment), rdflib.Literal('extra1', datatype=rdflib.XSD.string)))
@@ -616,17 +616,17 @@ class TestParseFilter(unittest.TestCase):
self.graph.add((rdflib.URIRef('http://example.com/entity#4321'), rdflib.URIRef(ns.bse.comment), rdflib.Literal('extra2', datatype=rdflib.XSD.string)))
q = self.parser(self.schema.node(ns.bsfs.Entity), ast.filter.Has(ns.bse.comment,
ast.filter.And(ast.filter.GreaterThan(1), ast.filter.LessThan(5))))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)},
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)},
{'http://example.com/entity#4321'})
# Has with OneOf predicate
q = self.parser(self.schema.node(ns.bsfs.Entity), ast.filter.Has(ast.filter.OneOf(ns.bse.tag, ns.bse.buddy),
ast.filter.GreaterThan(1)))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)},
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)},
{'http://example.com/entity#1234', 'http://example.com/entity#4321'})
# Has with reversed predicate
q = self.parser(self.schema.node(ns.bsfs.Tag), ast.filter.Has(ast.filter.Predicate(ns.bse.tag, reverse=True),
ast.filter.GreaterThan(1)))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)},
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)},
{'http://example.com/tag#1234'})
@@ -643,23 +643,23 @@ class TestParseFilter(unittest.TestCase):
self.assertRaises(errors.ConsistencyError, self.parser._distance, self.schema.literal(ns.bsfs.Colors), ast.filter.Distance([1,2,3,4,5], 1), '')
# _distance respects threshold
q = self.parser(self.schema.node(ns.bsfs.Entity), ast.filter.Any(ns.bse.colors, ast.filter.Distance([2,4,3,1], 4)))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)},
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)},
{'http://example.com/entity#1234', 'http://example.com/entity#4321', 'http://example.com/image#1234'})
q = self.parser(self.schema.node(ns.bsfs.Entity), ast.filter.Any(ns.bse.colors, ast.filter.Distance([2,4,3,1], 3)))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)},
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)},
{'http://example.com/entity#4321', 'http://example.com/image#1234'})
q = self.parser(self.schema.node(ns.bsfs.Entity), ast.filter.Any(ns.bse.colors, ast.filter.Distance([2,4,3,1], 2)))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)},
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)},
{'http://example.com/image#1234'})
# result set can be empty
q = self.parser(self.schema.node(ns.bsfs.Entity), ast.filter.Any(ns.bse.colors, ast.filter.Distance([2,4,3,1], 1)))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)}, set())
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)}, set())
# _distance respects strict
q = self.parser(self.schema.node(ns.bsfs.Entity), ast.filter.Any(ns.bse.colors, ast.filter.Distance([1,2,3,4], 0, False)))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)},
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)},
{'http://example.com/entity#1234'})
q = self.parser(self.schema.node(ns.bsfs.Entity), ast.filter.Any(ns.bse.colors, ast.filter.Distance([1,2,3,4], 0, True)))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)}, set())
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)}, set())
def test_one_of(self):
# _one_of expects a node
@@ -725,7 +725,7 @@ class TestParseFilter(unittest.TestCase):
ast.filter.Any(ast.filter.OneOf(ns.bse.tag, ns.bse.buddy),
ast.filter.Any(ast.filter.OneOf(ns.bse.comment),
ast.filter.Equals('Me, Myself, and I'))))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)},
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)},
{'http://example.com/entity#1234', 'http://example.com/image#1234'})
@@ -757,13 +757,13 @@ class TestParseFilter(unittest.TestCase):
ast.filter.Any(ns.bse.representative,
ast.filter.Any(ns.bse.filesize,
ast.filter.Equals(1234)))))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)},
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)},
{'http://example.com/entity#1234', 'http://example.com/image#1234'})
q = self.parser(self.schema.node(ns.bsfs.Tag),
ast.filter.Any(ast.filter.Predicate(ns.bse.tag, reverse=True),
ast.filter.Any(ns.bse.filesize,
ast.filter.LessThan(2000))))
- self.assertSetEqual({str(guid) for guid, in self.graph.query(q)},
+ self.assertSetEqual({str(guid) for guid, in q(self.graph)},
{'http://example.com/tag#1234'})
diff --git a/test/triple_store/sparql/test_sparql.py b/test/triple_store/sparql/test_sparql.py
index 7fbfb65..c58fae3 100644
--- a/test/triple_store/sparql/test_sparql.py
+++ b/test/triple_store/sparql/test_sparql.py
@@ -556,6 +556,76 @@ class TestSparqlStore(unittest.TestCase):
self.assertSetEqual(set(q), tag_ids)
+ def test_fetch(self):
+ # store setup
+ store = SparqlStore.Open()
+ store.schema = self.schema
+ # add instances
+ ent_type = self.schema.node(ns.bsfs.Entity)
+ tag_type = self.schema.node(ns.bsfs.Tag)
+ ent_ids = {URI('http://example.com/me/entity#1234'), URI('http://example.com/me/entity#4321')}
+ tag_ids = {URI('http://example.com/me/tag#1234'), URI('http://example.com/me/tag#4321')}
+ store.create(ent_type, ent_ids)
+ store.create(tag_type, tag_ids)
+ store.set(ent_type, ent_ids, self.schema.predicate(ns.bse.tag), tag_ids)
+ store.set(ent_type, {URI('http://example.com/me/entity#1234')}, self.schema.predicate(ns.bse.filesize), {1234})
+ store.set(ent_type, {URI('http://example.com/me/entity#4321')}, self.schema.predicate(ns.bse.filesize), {4321})
+ store.set(ent_type, {URI('http://example.com/me/entity#1234')}, self.schema.predicate(ns.bse.comment), {'hello world'})
+ # node_type must be a node from the schema
+ self.assertRaises(errors.ConsistencyError, list, store.fetch(self.schema.literal(ns.bsfs.Literal),
+ ast.filter.FilterExpression(), ast.fetch.FetchExpression()))
+ self.assertRaises(errors.ConsistencyError, list, store.fetch(self.schema.node(ns.bsfs.Node).child(ns.bsfs.Invalid),
+ ast.filter.FilterExpression(), ast.fetch.FetchExpression()))
+ # requires a filter and a fetch query
+ self.assertRaises(TypeError, list, store.fetch(self.schema.node(ns.bsfs.Entity), None, ast.fetch.FetchExpression()))
+ self.assertRaises(TypeError, list, store.fetch(self.schema.node(ns.bsfs.Entity), 1234, ast.fetch.FetchExpression()))
+ self.assertRaises(TypeError, list, store.fetch(self.schema.node(ns.bsfs.Entity), 'hello', ast.fetch.FetchExpression()))
+ self.assertRaises(TypeError, list, store.fetch(self.schema.node(ns.bsfs.Entity), ast.filter.FilterExpression(), None))
+ self.assertRaises(TypeError, list, store.fetch(self.schema.node(ns.bsfs.Entity), ast.filter.FilterExpression(), 1234))
+ self.assertRaises(TypeError, list, store.fetch(self.schema.node(ns.bsfs.Entity), ast.filter.FilterExpression(), 'hello'))
+ # fetch emits triples
+ self.assertSetEqual(set(store.fetch(self.schema.node(ns.bsfs.Entity),
+ ast.filter.Is('http://example.com/me/entity#1234'),
+ ast.fetch.Value(ns.bse.filesize, 'filesize'),
+ )), {
+ (URI('http://example.com/me/entity#1234'), 'filesize', 1234),
+ })
+ # fetch respects filter query
+ self.assertSetEqual(set(store.fetch(self.schema.node(ns.bsfs.Entity),
+ ast.filter.IsIn('http://example.com/me/entity#1234', 'http://example.com/me/entity#4321'),
+ ast.fetch.Value(ns.bse.filesize, 'filesize'),
+ )), {
+ (URI('http://example.com/me/entity#1234'), 'filesize', 1234),
+ (URI('http://example.com/me/entity#4321'), 'filesize', 4321),
+ })
+ # fetch ignores missing data
+ self.assertSetEqual(set(store.fetch(self.schema.node(ns.bsfs.Entity),
+ ast.filter.IsIn('http://example.com/me/entity#1234', 'http://example.com/me/entity#4321'),
+ ast.fetch.Value(ns.bse.comment, 'comment'),
+ )), {
+ (URI('http://example.com/me/entity#1234'), 'comment', 'hello world'),
+ })
+ # fetch emits all triples
+ self.assertSetEqual(set(store.fetch(self.schema.node(ns.bsfs.Entity),
+ ast.filter.Is('http://example.com/me/entity#1234'),
+ ast.fetch.All(
+ ast.fetch.Value(ns.bse.filesize, 'filesize'),
+ ast.fetch.Node(ns.bse.tag, 'tag'),
+ )
+ )), {
+ (URI('http://example.com/me/entity#1234'), 'filesize', 1234),
+ (URI('http://example.com/me/entity#1234'), 'tag', URI('http://example.com/me/tag#1234')),
+ (URI('http://example.com/me/entity#1234'), 'tag', URI('http://example.com/me/tag#4321')),
+ })
+ # triples do not repeat
+ triples = list(store.fetch(self.schema.node(ns.bsfs.Entity), ast.filter.Is('http://example.com/me/entity#1234'),
+ ast.fetch.All(
+ ast.fetch.Value(ns.bse.filesize, 'filesize'),
+ ast.fetch.Node(ns.bse.tag, 'tag'),
+ )
+ ))
+ self.assertEqual(len(triples), 3)
+
def test_exists(self):
# store setup
store = SparqlStore.Open()
diff --git a/test/triple_store/sparql/test_utils.py b/test/triple_store/sparql/test_utils.py
new file mode 100644
index 0000000..073b8f8
--- /dev/null
+++ b/test/triple_store/sparql/test_utils.py
@@ -0,0 +1,155 @@
+"""
+
+Part of the bsfs test suite.
+A copy of the license is provided with the project.
+Author: Matthias Baumgartner, 2022
+"""
+# standard imports
+import operator
+import re
+import unittest
+
+# external imports
+import rdflib
+
+# bsie imports
+from bsfs.namespace import ns
+
+# objects to test
+from bsfs.triple_store.sparql.utils import GenHopName, Query
+
+
+## code ##
+
+class TestGenHopName(unittest.TestCase):
+ def test_next(self):
+ # baseline
+ self.assertEqual(next(GenHopName(prefix='?foo', start=123)), '?foo123')
+ # respects prefix
+ self.assertEqual(next(GenHopName(prefix='?bar', start=123)), '?bar123')
+ # respects start
+ self.assertEqual(next(GenHopName(prefix='?foo', start=321)), '?foo321')
+ # counts up
+ cnt = GenHopName(prefix='?foo', start=998)
+ self.assertEqual(next(cnt), '?foo998')
+ self.assertEqual(next(cnt), '?foo999')
+ self.assertEqual(next(cnt), '?foo1000')
+ self.assertEqual(next(cnt), '?foo1001')
+
+ def test_essentials(self):
+ # can get the prefix
+ self.assertEqual(GenHopName(prefix='?foo', start=123).prefix, '?foo')
+ # can get the counter
+ self.assertEqual(GenHopName(prefix='?foo', start=123).curr, 122)
+
+
+class TestQuery(unittest.TestCase):
+ def setUp(self):
+ self.root_type = 'http://bsfs.ai/schema/Entity'
+ self.root_head = '?root'
+ self.select = (('?head', 'name'), )
+ self.where = f'?root <{ns.bse.tag}> ?head'
+
+ def test_essentials(self):
+ # can access members
+ q = Query(self.root_type, self.root_head, self.select, self.where)
+ self.assertEqual(q.root_type, self.root_type)
+ self.assertEqual(q.root_head, self.root_head)
+ self.assertEqual(q.select, self.select)
+ self.assertEqual(q.where, self.where)
+ # comparison
+ self.assertEqual(q, Query(self.root_type, self.root_head, self.select, self.where))
+ self.assertEqual(hash(q), hash(Query(self.root_type, self.root_head, self.select, self.where)))
+ # comparison respects root_type
+ self.assertNotEqual(q, Query('http://bsfs.ai/schema/Tag', self.root_head, self.select, self.where))
+ self.assertNotEqual(hash(q), hash(Query('http://bsfs.ai/schema/Tag', self.root_head, self.select, self.where)))
+ # comparison respects root_head
+ self.assertNotEqual(q, Query(self.root_type, '?foo', self.select, self.where))
+ self.assertNotEqual(hash(q), hash(Query(self.root_type, '?foo', self.select, self.where)))
+ # comparison respects select
+ self.assertNotEqual(q, Query(self.root_type, self.root_head, (('?head', 'foo'), ), self.where))
+ self.assertNotEqual(hash(q), hash(Query(self.root_type, self.root_head, (('?head', 'foo'), ), self.where)))
+ # comparison respects where
+ self.assertNotEqual(q, Query(self.root_type, self.root_head, self.select, '?root bse:filename ?head'))
+ self.assertNotEqual(hash(q), hash(Query(self.root_type, self.root_head, self.select, '?root bse:filename ?head')))
+ # string conversion
+ self.assertEqual(str(q), q.query)
+ self.assertEqual(repr(q), "Query(http://bsfs.ai/schema/Entity, ?root, (('?head', 'name'),), ?root <http://bsfs.ai/schema/Entity#tag> ?head)")
+
+ def test_add(self):
+ q = Query(self.root_type, self.root_head, self.select, self.where)
+ # can only add a query
+ self.assertRaises(TypeError, operator.add, q, 1234)
+ self.assertRaises(TypeError, operator.add, q, 'foobar')
+ # root type and head must match
+ self.assertRaises(ValueError, operator.add, q, Query('http://bsfs.ai/schema/Tag', self.root_head))
+ self.assertRaises(ValueError, operator.add, q, Query(self.root_type, '?foobar'))
+ # select and were are combined
+ combo = q + Query(self.root_type, self.root_head, (('?foo', 'bar'), ), f'?root <{ns.bse.filename}> ?foo')
+ self.assertEqual(combo.select, (('?head', 'name'), ('?foo', 'bar')))
+ self.assertEqual(combo.where, f'?root <{ns.bse.tag}> ?head . ?root <{ns.bse.filename}> ?foo')
+ # select can be empty
+ combo = q + Query(self.root_type, self.root_head, None, f'?root <{ns.bse.filename}> ?foo')
+ self.assertEqual(combo.select, (('?head', 'name'), ))
+ combo = Query(self.root_type, self.root_head, None, f'?root <{ns.bse.filename}> ?foo') + q
+ self.assertEqual(combo.select, (('?head', 'name'), ))
+ combo = Query(self.root_type, self.root_head, None, self.where) + Query(self.root_type, self.root_head, None, f'?root <{ns.bse.filename}> ?foo')
+ self.assertEqual(combo.select, tuple())
+ # where can be empty
+ combo = q + Query(self.root_type, self.root_head, (('?foo', 'bar'), ))
+ self.assertEqual(combo.where, self.where)
+ combo = Query(self.root_type, self.root_head, (('?foo', 'bar'), )) + q
+ self.assertEqual(combo.where, self.where)
+ combo = Query(self.root_type, self.root_head, self.select) + Query(self.root_type, self.root_head, (('?foo', 'bar'), ))
+ self.assertEqual(combo.where, '')
+
+ def test_names(self):
+ self.assertEqual(Query(self.root_type, self.root_head, (('?head', 'name'), ), self.where).names,
+ ('name', ))
+ self.assertEqual(Query(self.root_type, self.root_head, (('?head', 'name'), ('?foo', 'bar')), self.where).names,
+ ('name', 'bar'))
+
+ def test_query(self):
+ def normalize(value):
+ value = value.strip()
+ value = value.lower()
+ value = value.replace(r'\n', ' ')
+ value, _ = re.subn('\s\s+', ' ', value)
+ return value
+ # query composes a valid query
+ q = Query(self.root_type, self.root_head, self.select, self.where)
+ self.assertEqual(normalize(q.query), normalize(f'select ?root (?head as ?name) where {{ ?root <{ns.rdf.type}>/<{ns.rdfs.subClassOf}>* <http://bsfs.ai/schema/Entity> . ?root <{ns.bse.tag}> ?head }}'))
+ # select and where are optional
+ q = Query(self.root_type, self.root_head)
+ self.assertEqual(normalize(q.query), normalize(f'select ?root where {{ ?root <{ns.rdf.type}>/<{ns.rdfs.subClassOf}>* <http://bsfs.ai/schema/Entity> . }}'))
+ # select and where need not to correspond
+ q = Query(self.root_type, self.root_head, (('?head', 'name'), ))
+ self.assertEqual(normalize(q.query), normalize(f'select ?root (?head as ?name) where {{ ?root <{ns.rdf.type}>/<{ns.rdfs.subClassOf}>* <http://bsfs.ai/schema/Entity> . }}'))
+ # query is used for string representation
+ self.assertEqual(str(q), q.query)
+
+ def test_call(self):
+ graph = rdflib.Graph()
+ # schema
+ graph.add((rdflib.URIRef('http://bsfs.ai/schema/Document'), rdflib.URIRef(ns.rdfs.subClassOf), rdflib.URIRef('http://bsfs.ai/schema/Entity')))
+ # nodes
+ graph.add((rdflib.URIRef('http://example.com/entity#1234'), rdflib.URIRef(ns.rdf.type), rdflib.URIRef('http://bsfs.ai/schema/Entity')))
+ graph.add((rdflib.URIRef('http://example.com/doc#1234'), rdflib.URIRef(ns.rdf.type), rdflib.URIRef('http://bsfs.ai/schema/Document')))
+ # links
+ graph.add((rdflib.URIRef('http://example.com/entity#1234'), rdflib.URIRef(ns.bse.tag), rdflib.Literal('tag#1234', datatype=rdflib.XSD.string)))
+ graph.add((rdflib.URIRef('http://example.com/doc#1234'), rdflib.URIRef(ns.bse.tag), rdflib.Literal('tag#1234', datatype=rdflib.XSD.string)))
+ # run query on a given graph
+ query = Query(self.root_type, self.root_head, self.select, self.where)
+ self.assertSetEqual(set(query(graph)), {
+ (rdflib.URIRef('http://example.com/entity#1234'), rdflib.Literal('tag#1234', datatype=rdflib.XSD.string)),
+ (rdflib.URIRef('http://example.com/doc#1234'), rdflib.Literal('tag#1234', datatype=rdflib.XSD.string)),
+ })
+ # query actually considers the passed graph
+ self.assertSetEqual(set(query(rdflib.Graph())), set())
+
+## main ##
+
+if __name__ == '__main__':
+ unittest.main()
+
+## EOF ##
diff --git a/test/triple_store/test_base.py b/test/triple_store/test_base.py
index a0c3260..56a2539 100644
--- a/test/triple_store/test_base.py
+++ b/test/triple_store/test_base.py
@@ -38,6 +38,9 @@ class DummyBase(TripleStoreBase):
def get(self, node_type, query):
pass
+ def fetch(self, node_type, filter, fetch):
+ pass
+
def exists(self, node_type, guids):
pass