diff options
author | Matthias Baumgartner <dev@igsor.net> | 2022-12-18 14:15:18 +0100 |
---|---|---|
committer | Matthias Baumgartner <dev@igsor.net> | 2022-12-18 14:15:18 +0100 |
commit | e19c8f9d0818a147832df0945188ea14de9c7690 (patch) | |
tree | 6a1e388af7ace081fbe516b0c56e28ff1f1e48db /bsfs/schema/schema.py | |
parent | 58496960926a56149c10d64e01b6df7d048eed0e (diff) | |
download | bsfs-e19c8f9d0818a147832df0945188ea14de9c7690.tar.gz bsfs-e19c8f9d0818a147832df0945188ea14de9c7690.tar.bz2 bsfs-e19c8f9d0818a147832df0945188ea14de9c7690.zip |
documentation, types, and style fixes
Diffstat (limited to 'bsfs/schema/schema.py')
-rw-r--r-- | bsfs/schema/schema.py | 56 |
1 files changed, 41 insertions, 15 deletions
diff --git a/bsfs/schema/schema.py b/bsfs/schema/schema.py index b6f37a7..c5d4571 100644 --- a/bsfs/schema/schema.py +++ b/bsfs/schema/schema.py @@ -25,11 +25,28 @@ __all__: typing.Sequence[str] = ( ## code ## class Schema(): - """ + """Graph schema. + + Use `Schema.Empty()` to create a new, empty Schema rather than construct + it directly. + + The schema is defined by three sets: Predicates, Nodes, and Literals. + + The Schema class guarantees two properties: completeness and consistency. + Completeness means that the schema covers all class that are referred to + by any other class in the schema. Consistency means that each class is + identified by a unique URI and all classes that use that URI consequently + use the same definition. + """ + # node classes. _nodes: typing.Dict[URI, types.Node] + + # literal classes. _literals: typing.Dict[URI, types.Literal] + + # predicate classes. _predicates: typing.Dict[URI, types.Predicate] def __init__( @@ -47,7 +64,8 @@ class Schema(): literals = set(literals) predicates = set(predicates) # include parents in predicates set - predicates |= {par for pred in predicates for par in pred.parents()} + # TODO: review type annotations and ignores for python >= 3.11 (parents is _Type but should be typing.Self) + predicates |= {par for pred in predicates for par in pred.parents()} # type: ignore [misc] # include predicate domain in nodes set nodes |= {pred.domain for pred in predicates} # include predicate range in nodes and literals sets @@ -57,8 +75,8 @@ class Schema(): # include parents in nodes and literals sets # NOTE: Must be done after predicate domain/range was handled # so that their parents are included as well. - nodes |= {par for node in nodes for par in node.parents()} - literals |= {par for lit in literals for par in lit.parents()} + nodes |= {par for node in nodes for par in node.parents()} # type: ignore [misc] + literals |= {par for lit in literals for par in lit.parents()} # type: ignore [misc] # assign members self._nodes = {node.uri: node for node in nodes} self._literals = {lit.uri: lit for lit in literals} @@ -153,9 +171,7 @@ class Schema(): return self.diff(other) def consistent_with(self, other: 'Schema') -> bool: - """Checks if two schemas have different definitions for the same uri. - Tests nodes, literals, and predicates. - """ + """Checks if two schemas have different predicate, node, or literal definitions for the same uri.""" # check arg if not isinstance(other, Schema): raise TypeError(other) @@ -181,7 +197,10 @@ class Schema(): return True @classmethod - def Union(cls, *args: typing.Union['Schema', typing.Iterable['Schema']]) -> 'Schema': + def Union( # pylint: disable=invalid-name # capitalized classmethod + cls, + *args: typing.Union['Schema', typing.Iterable['Schema']] + ) -> 'Schema': """Combine multiple Schema instances into a single one. As argument, you can either pass multiple Schema instances, or a single iterable over Schema instances. Any abc.Iterable will be accepted. @@ -200,7 +219,7 @@ class Schema(): if isinstance(args[0], cls): # args is sequence of Schema instances pass elif len(args) == 1 and isinstance(args[0], abc.Iterable): # args is a single iterable - args = args[0] + args = args[0] # type: ignore [assignment] # we checked and thus know that args[0] is an iterable else: raise TypeError(f'expected multiple Schema instances or a single Iterable, found {args}') @@ -237,25 +256,31 @@ class Schema(): ## getters ## - # FIXME: which of the getters below are actually needed? + # FIXME: nodes, predicates, literals could be properties # FIXME: interchangeability of URI and _Type?! def has_node(self, node: URI) -> bool: + """Return True if a Node with URI *node* is part of the schema.""" return node in self._nodes def has_literal(self, lit: URI) -> bool: + """Return True if a Literal with URI *lit* is part of the schema.""" return lit in self._literals def has_predicate(self, pred: URI) -> bool: + """Return True if a Predicate with URI *pred* is part of the schema.""" return pred in self._predicates - def nodes(self) -> typing.Iterator[types.Node]: # FIXME: type annotation + def nodes(self) -> typing.Iterable[types.Node]: + """Return an iterator over Node classes.""" return self._nodes.values() - def literals(self) -> typing.Iterator[types.Literal]: # FIXME: type annotation + def literals(self) -> typing.Iterable[types.Literal]: + """Return an iterator over Literal classes.""" return self._literals.values() - def predicates(self) -> typing.Iterator[types.Predicate]: # FIXME: type annotation + def predicates(self) -> typing.Iterable[types.Predicate]: + """Return an iterator over Predicate classes.""" return self._predicates.values() def node(self, uri: URI) -> types.Node: @@ -275,7 +300,8 @@ class Schema(): @classmethod - def Empty(cls) -> 'Schema': + def Empty(cls) -> 'Schema': # pylint: disable=invalid-name # capitalized classmethod + """Return a minimal Schema.""" node = types.Node(ns.bsfs.Node, None) literal = types.Literal(ns.bsfs.Literal, None) predicate = types.Predicate( @@ -289,7 +315,7 @@ class Schema(): @classmethod - def from_string(cls, schema: str) -> 'Schema': + def from_string(cls, schema: str) -> 'Schema': # pylint: disable=invalid-name # capitalized classmethod """Load and return a Schema from a string.""" # parse string into rdf graph graph = rdflib.Graph() |