aboutsummaryrefslogtreecommitdiffstats
path: root/test/triple_store/sparql/test_parse_fetch.py
diff options
context:
space:
mode:
authorMatthias Baumgartner <dev@igsor.net>2023-03-05 19:25:29 +0100
committerMatthias Baumgartner <dev@igsor.net>2023-03-05 19:25:29 +0100
commit48b6081d0092e9c5a1b0ad79bdde2e51649bf61a (patch)
tree634198c34aae3c0306ce30ac7452abd7b53a14e8 /test/triple_store/sparql/test_parse_fetch.py
parent91437ba89d35bf482f3d9671bb99ef2fc69f5985 (diff)
parente4845c627e97a6d125bf33d9e7a4a8d373d7fc4a (diff)
downloadbsfs-0.23.03.tar.gz
bsfs-0.23.03.tar.bz2
bsfs-0.23.03.zip
Merge branch 'develop'v0.23.03
Diffstat (limited to 'test/triple_store/sparql/test_parse_fetch.py')
-rw-r--r--test/triple_store/sparql/test_parse_fetch.py257
1 files changed, 257 insertions, 0 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..1d793e7
--- /dev/null
+++ b/test/triple_store/sparql/test_parse_fetch.py
@@ -0,0 +1,257 @@
+
+# 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 ##
+
+ns.bse = ns.bsfs.Entity()
+ns.bst = ns.bsfs.Tag()
+ns.bsc = ns.bsfs.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: <https://schema.bsfs.io/core/>
+ prefix bse: <https://schema.bsfs.io/core/Entity#>
+ prefix bst: <https://schema.bsfs.io/core/Tag#>
+ prefix bsc: <https://schema.bsfs.io/core/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('https://schema.bsfs.io/core/Entity'), rdflib.RDFS.subClassOf, rdflib.URIRef('https://schema.bsfs.io/core/Node')))
+ self.graph.add((rdflib.URIRef('https://schema.bsfs.io/core/Collection'), rdflib.RDFS.subClassOf, rdflib.URIRef('https://schema.bsfs.io/core/Node')))
+ self.graph.add((rdflib.URIRef('https://schema.bsfs.io/core/Tag'), rdflib.RDFS.subClassOf, rdflib.URIRef('https://schema.bsfs.io/core/Node')))
+ # entities
+ self.graph.add((rdflib.URIRef('http://example.com/entity#1234'), rdflib.RDF.type, rdflib.URIRef('https://schema.bsfs.io/core/Entity')))
+ self.graph.add((rdflib.URIRef('http://example.com/entity#4321'), rdflib.RDF.type, rdflib.URIRef('https://schema.bsfs.io/core/Entity')))
+ # tags
+ self.graph.add((rdflib.URIRef('http://example.com/tag#1234'), rdflib.RDF.type, rdflib.URIRef('https://schema.bsfs.io/core/Tag')))
+ self.graph.add((rdflib.URIRef('http://example.com/tag#4321'), rdflib.RDF.type, rdflib.URIRef('https://schema.bsfs.io/core/Tag')))
+ # collections
+ self.graph.add((rdflib.URIRef('http://example.com/collection#1234'), rdflib.RDF.type, rdflib.URIRef('https://schema.bsfs.io/core/Collection')))
+ self.graph.add((rdflib.URIRef('http://example.com/collection#4321'), rdflib.RDF.type, rdflib.URIRef('https://schema.bsfs.io/core/Collection')))
+ # entity literals
+ self.graph.add((rdflib.URIRef('http://example.com/entity#1234'), rdflib.URIRef(ns.bse.rank), rdflib.Literal('1234', datatype=rdflib.XSD.integer)))
+ self.graph.add((rdflib.URIRef('http://example.com/entity#1234'), rdflib.URIRef(ns.bse.filename), rdflib.Literal('filename_1234', datatype=rdflib.XSD.string)))
+ #self.graph.add((rdflib.URIRef('http://example.com/entity#4321'), rdflib.URIRef(ns.bse.rank), rdflib.Literal('4321', datatype=rdflib.XSD.integer)))
+ self.graph.add((rdflib.URIRef('http://example.com/entity#4321'), rdflib.URIRef(ns.bse.filename), rdflib.Literal('filename_4321', datatype=rdflib.XSD.string)))
+ # tag literals
+ self.graph.add((rdflib.URIRef('http://example.com/tag#1234'), rdflib.URIRef(ns.bst.label), rdflib.Literal('tag_label_1234', datatype=rdflib.XSD.string)))
+ self.graph.add((rdflib.URIRef('http://example.com/tag#4321'), rdflib.URIRef(ns.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(ns.bsc.label), rdflib.Literal('collection_label_1234', datatype=rdflib.XSD.string)))
+ self.graph.add((rdflib.URIRef('http://example.com/collection#1234'), rdflib.URIRef(ns.bsc.rating), rdflib.Literal('1234', datatype=rdflib.XSD.integer)))
+ self.graph.add((rdflib.URIRef('http://example.com/collection#4321'), rdflib.URIRef(ns.bsc.label), rdflib.Literal('collection_label_4321', datatype=rdflib.XSD.string)))
+ self.graph.add((rdflib.URIRef('http://example.com/collection#4321'), rdflib.URIRef(ns.bsc.rating), rdflib.Literal('4321', datatype=rdflib.XSD.integer)))
+ # entity-tag links
+ self.graph.add((rdflib.URIRef('http://example.com/entity#1234'), rdflib.URIRef(ns.bse.tag), rdflib.URIRef('http://example.com/tag#1234')))
+ self.graph.add((rdflib.URIRef('http://example.com/entity#4321'), rdflib.URIRef(ns.bse.tag), rdflib.URIRef('http://example.com/tag#4321')))
+ # entity-collection links
+ self.graph.add((rdflib.URIRef('http://example.com/entity#1234'), rdflib.URIRef(ns.bse.collection), rdflib.URIRef('http://example.com/collection#1234')))
+ self.graph.add((rdflib.URIRef('http://example.com/entity#4321'), rdflib.URIRef(ns.bse.collection), rdflib.URIRef('http://example.com/collection#4321')))
+ # collection-tag links
+ self.graph.add((rdflib.URIRef('http://example.com/collection#1234'), rdflib.URIRef(ns.bsc.tag), rdflib.URIRef('http://example.com/tag#1234')))
+ self.graph.add((rdflib.URIRef('http://example.com/collection#4321'), rdflib.URIRef(ns.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(ns.bst.main), rdflib.URIRef('http://example.com/entity#4321')))
+ self.graph.add((rdflib.URIRef('http://example.com/tag#4321'), rdflib.URIRef(ns.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(ns.bse.tag, ast.fetch.Value(ns.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(ns.bse.filename, name='filename'),
+ ast.fetch.Value(ns.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(ns.bse.filename, name='filename'),
+ ast.fetch.Node(ns.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(ns.bse.tag, ast.fetch.All(
+ ast.fetch.This(name='tag'),
+ ast.fetch.Value(ns.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(ns.bse.tag, ast.fetch.Value(ns.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(ns.bse.tag, ast.fetch.Fetch(ns.bst.main, ast.fetch.Value(ns.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(ns.bse.tag, self.parser.ngen.prefix[1:] + '123'))
+ # a simple Node statement
+ q = self.parser(self.ent, ast.fetch.Node(ns.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(ns.bse.filename, self.parser.ngen.prefix[1:] + '123'))
+ # a simple Value statement
+ q = self.parser(self.ent, ast.fetch.Value(ns.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 ##