aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bsfs/graph/graph.py5
-rw-r--r--bsfs/query/__init__.py20
-rw-r--r--bsfs/query/ast/__init__.py24
-rw-r--r--bsfs/query/ast/filter_.py30
-rw-r--r--bsfs/query/validator.py35
-rw-r--r--bsfs/triple_store/base.py8
-rw-r--r--bsfs/triple_store/sparql/__init__.py18
-rw-r--r--bsfs/triple_store/sparql/sparql.py (renamed from bsfs/triple_store/sparql.py)3
-rw-r--r--test/graph/test_graph.py2
-rw-r--r--test/query/__init__.py0
-rw-r--r--test/query/ast/__init__.py0
-rw-r--r--test/query/ast/test_filter_.py28
-rw-r--r--test/query/test_validator.py30
-rw-r--r--test/triple_store/sparql/__init__.py0
-rw-r--r--test/triple_store/sparql/test_sparql.py (renamed from test/triple_store/test_sparql.py)4
15 files changed, 206 insertions, 1 deletions
diff --git a/bsfs/graph/graph.py b/bsfs/graph/graph.py
index b7b9f1c..10e5904 100644
--- a/bsfs/graph/graph.py
+++ b/bsfs/graph/graph.py
@@ -9,6 +9,7 @@ import os
import typing
# bsfs imports
+from bsfs.query import ast
from bsfs.schema import Schema
from bsfs.triple_store import TripleStoreBase
from bsfs.utils import URI, typename
@@ -110,4 +111,8 @@ class Graph():
type_ = self.schema.node(node_type)
return _nodes.Nodes(self._backend, self._user, type_, {guid})
+ def get(self, node_type: URI, subject: ast.filter.FilterExpression) -> Nodes:
+ """Return a `Nodes` instance over all nodes of type *node_type* that match the *subject* query."""
+ raise NotImplementedError()
+
## EOF ##
diff --git a/bsfs/query/__init__.py b/bsfs/query/__init__.py
new file mode 100644
index 0000000..21c7389
--- /dev/null
+++ b/bsfs/query/__init__.py
@@ -0,0 +1,20 @@
+"""
+
+Part of the BlackStar filesystem (bsfs) module.
+A copy of the license is provided with the project.
+Author: Matthias Baumgartner, 2022
+"""
+# imports
+import typing
+
+# inner-module imports
+from . import ast
+from . import validator as validate
+
+# exports
+__all__: typing.Sequence[str] = (
+ 'ast',
+ 'validate',
+ )
+
+## EOF ##
diff --git a/bsfs/query/ast/__init__.py b/bsfs/query/ast/__init__.py
new file mode 100644
index 0000000..0ee7385
--- /dev/null
+++ b/bsfs/query/ast/__init__.py
@@ -0,0 +1,24 @@
+"""Query AST components.
+
+The query AST consists of a Filter syntax tree.
+
+Classes beginning with an underscore (_) represent internal type hierarchies
+and should not be used for parsing. Note that the AST structures do not
+(and cannot) check semantic validity or consistency with a given schema.
+
+Part of the BlackStar filesystem (bsfs) module.
+A copy of the license is provided with the project.
+Author: Matthias Baumgartner, 2022
+"""
+# imports
+import typing
+
+# inner-module imports
+from . import filter_ as filter
+
+# exports
+__all__: typing.Sequence[str] = (
+ 'filter',
+ )
+
+## EOF ##
diff --git a/bsfs/query/ast/filter_.py b/bsfs/query/ast/filter_.py
new file mode 100644
index 0000000..4086fc1
--- /dev/null
+++ b/bsfs/query/ast/filter_.py
@@ -0,0 +1,30 @@
+"""Filter AST.
+
+Part of the BlackStar filesystem (bsfs) module.
+A copy of the license is provided with the project.
+Author: Matthias Baumgartner, 2022
+"""
+# imports
+from collections import abc
+import typing
+
+# exports
+__all__ : typing.Sequence[str] = []
+
+
+## code ##
+
+class _Expression(abc.Hashable):
+ def __repr__(self) -> str:
+ """Return the expressions's string representation."""
+ return f'{typename(self)}()'
+
+ def __hash__(self) -> int:
+ """Return the expression's integer representation."""
+ return hash(type(self))
+
+ def __eq__(self, other: typing.Any) -> bool:
+ """Return True if *self* and *other* are equivalent."""
+ return isinstance(other, type(self))
+
+## EOF ##
diff --git a/bsfs/query/validator.py b/bsfs/query/validator.py
new file mode 100644
index 0000000..ac3789a
--- /dev/null
+++ b/bsfs/query/validator.py
@@ -0,0 +1,35 @@
+"""
+
+Part of the BlackStar filesystem (bsfs) module.
+A copy of the license is provided with the project.
+Author: Matthias Baumgartner, 2022
+"""
+# imports
+import typing
+
+# bsfs imports
+from bsfs import schema as bsc
+
+# inner-module imports
+from . import ast
+
+# exports
+__all__ : typing.Sequence[str] = (
+ 'Filter',
+ )
+
+
+## code ##
+
+class Filter():
+
+ # schema to validate against.
+ schema: bsc.Schema
+
+ def __init__(self, schema: bsc.Schema):
+ self.schema = schema
+
+ def parse(self, node: ast.filter.FilterExpression):
+ raise NotImplementedError()
+
+## EOF ##
diff --git a/bsfs/triple_store/base.py b/bsfs/triple_store/base.py
index 6561262..28ebb86 100644
--- a/bsfs/triple_store/base.py
+++ b/bsfs/triple_store/base.py
@@ -109,6 +109,14 @@ class TripleStoreBase(abc.ABC):
"""
@abc.abstractmethod
+ def get(
+ self,
+ node_type: bsc.Node,
+ query: ast.filter.FilterExpression,
+ ) -> typing.Iterator[URI]:
+ """Return guids of nodes of type *node_type* that match the *query*."""
+
+ @abc.abstractmethod
def exists(
self,
node_type: _schema.Node,
diff --git a/bsfs/triple_store/sparql/__init__.py b/bsfs/triple_store/sparql/__init__.py
new file mode 100644
index 0000000..285334a
--- /dev/null
+++ b/bsfs/triple_store/sparql/__init__.py
@@ -0,0 +1,18 @@
+"""
+
+Part of the BlackStar filesystem (bsfs) module.
+A copy of the license is provided with the project.
+Author: Matthias Baumgartner, 2022
+"""
+# imports
+import typing
+
+# inner-module imports
+from .sparql import SparqlStore
+
+# exports
+__all__: typing.Sequence[str] = (
+ 'SparqlStore',
+ )
+
+## EOF ##
diff --git a/bsfs/triple_store/sparql.py b/bsfs/triple_store/sparql/sparql.py
index 7516dff..fff540a 100644
--- a/bsfs/triple_store/sparql.py
+++ b/bsfs/triple_store/sparql/sparql.py
@@ -11,6 +11,7 @@ import rdflib
# bsfs imports
from bsfs import schema as bsc
+from bsfs.query import ast
from bsfs.utils import errors, URI
# inner-module imports
@@ -152,6 +153,8 @@ class SparqlStore(base.TripleStoreBase):
# migrate schema
self._schema = schema
+ def get(self, node_type: bsc.Node, query: ast.filter.FilterExpression) -> typing.Iterator[URI]:
+ raise NotImplementedError()
def _has_type(self, subject: URI, node_type: bsc.Node) -> bool:
"""Return True if *subject* is a node of class *node_type* or a subclass thereof."""
diff --git a/test/graph/test_graph.py b/test/graph/test_graph.py
index 33cf6aa..0a3fd5b 100644
--- a/test/graph/test_graph.py
+++ b/test/graph/test_graph.py
@@ -192,6 +192,8 @@ class TestGraph(unittest.TestCase):
bsfs:unique "true"^^xsd:boolean .
'''))
+ def test_get(self):
+ raise NotImplementedError()
## main ##
diff --git a/test/query/__init__.py b/test/query/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/query/__init__.py
diff --git a/test/query/ast/__init__.py b/test/query/ast/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/query/ast/__init__.py
diff --git a/test/query/ast/test_filter_.py b/test/query/ast/test_filter_.py
new file mode 100644
index 0000000..cc815e3
--- /dev/null
+++ b/test/query/ast/test_filter_.py
@@ -0,0 +1,28 @@
+"""
+
+Part of the tagit test suite.
+A copy of the license is provided with the project.
+Author: Matthias Baumgartner, 2022
+"""
+# imports
+import unittest
+
+# bsfs imports
+
+# objects to test
+from bsfs.query.ast.filter_ import _Expression
+
+
+## code ##
+
+class TestExpression(unittest.TestCase):
+ def test_essentials(self):
+ raise NotImplementedError()
+
+
+## main ##
+
+if __name__ == '__main__':
+ unittest.main()
+
+## EOF ##
diff --git a/test/query/test_validator.py b/test/query/test_validator.py
new file mode 100644
index 0000000..0e88ad3
--- /dev/null
+++ b/test/query/test_validator.py
@@ -0,0 +1,30 @@
+"""
+
+Part of the tagit test suite.
+A copy of the license is provided with the project.
+Author: Matthias Baumgartner, 2022
+"""
+# imports
+import unittest
+
+# bsfs imports
+
+# objects to test
+from bsfs.query.validator import Filter
+
+
+## code ##
+
+class TestFilter(unittest.TestCase):
+ def test_parse(self):
+ raise NotImplementedError()
+
+ # FIXME: subtests for individual functions
+
+
+## main ##
+
+if __name__ == '__main__':
+ unittest.main()
+
+## EOF ##
diff --git a/test/triple_store/sparql/__init__.py b/test/triple_store/sparql/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/triple_store/sparql/__init__.py
diff --git a/test/triple_store/test_sparql.py b/test/triple_store/sparql/test_sparql.py
index 8d98749..0bf664a 100644
--- a/test/triple_store/test_sparql.py
+++ b/test/triple_store/sparql/test_sparql.py
@@ -14,7 +14,7 @@ from bsfs.namespace import ns
from bsfs.utils import errors, URI
# objects to test
-from bsfs.triple_store.sparql import SparqlStore
+from bsfs.triple_store.sparql.sparql import SparqlStore
## code ##
@@ -455,6 +455,8 @@ class TestSparqlStore(unittest.TestCase):
(rdflib.URIRef('http://example.com/me/entity#4321'), rdflib.URIRef(p_filesize.uri), rdflib.Literal(1234, datatype=rdflib.XSD.integer)),
})
+ def test_get(self):
+ raise NotImplementedError()
def test_exists(self):
# store setup