From 0704f6ba056cae6c4fceda97b298c8f05b5f1983 Mon Sep 17 00:00:00 2001 From: Alex Nelson Date: Tue, 23 Apr 2024 09:10:47 -0400 Subject: [PATCH] Remove -Likes `GraphLike` and `ConjunctiveLike` appear in several places throughout the pySHACL code, with these definitions in a few files named `pytypes.py`: ```python ConjunctiveLike = Union[ConjunctiveGraph, Dataset] GraphLike = Union[ConjunctiveLike, Graph] ``` In RDFLib 7.0.0 (and according to `git blame`, RDFLib since 2013), the classes referenced in the `Union`s have these subclassing relationships: * `Dataset` is a subclass of `ConjunctiveGraph`. * `ConjunctiveGraph` is a subclass of `Graph`. The RDFLib `Graph` definition designates a few parameters as "-likes" (e.g., `source` in `graph.parse()`), to normalize behaviors around graphs being passed in methods as objects or strings. The Likes in pySHACL do not handle the same use case pattern. This patch replaces the -Likes with their broadest `Union` members, even though a few methods that used `ConjunctiveLike` are described by documentation to prefer `Dataset`. Narrowing this is left for future review. Spelling of `rdflib.Graph` was kept as `rdflib.Graph` for text search purposes. A little cleanup occurs in this patch as well - some type-hinting in comments is mooted by inheritance from function parameters (`validate.py`); `/pyshacl/rdfutil/pytypes.py` is deleted by merit of now being empty; and a `RuntimeError` message has a capitalization typo fixed. Signed-off-by: Alex Nelson --- pyshacl/constraints/advanced/__init__.py | 7 ++-- pyshacl/constraints/constraint_component.py | 11 +++--- .../core/cardinality_constraints.py | 11 +++--- .../constraints/core/logical_constraints.py | 20 ++++++----- pyshacl/constraints/core/other_constraints.py | 14 ++++---- .../core/property_pair_constraints.py | 18 +++++----- .../core/shape_based_constraints.py | 14 ++++---- .../core/string_based_constraints.py | 14 ++++---- pyshacl/constraints/core/value_constraints.py | 14 ++++---- .../core/value_range_constraints.py | 18 +++++----- .../sparql_based_constraint_components.py | 6 ++-- .../sparql/sparql_based_constraints.py | 4 +-- pyshacl/extras/js/constraint.py | 7 ++-- pyshacl/extras/js/constraint_component.py | 7 ++-- pyshacl/extras/js/rules.py | 6 ++-- pyshacl/extras/js/target.py | 5 +-- pyshacl/functions/__init__.py | 8 +++-- pyshacl/functions/shacl_function.py | 6 ++-- pyshacl/helper/expression_helper.py | 4 +-- pyshacl/pytypes.py | 4 +-- pyshacl/rdfutil/clone.py | 12 ++++--- pyshacl/rdfutil/consts.py | 6 +--- pyshacl/rdfutil/inoculate.py | 5 +-- pyshacl/rdfutil/load.py | 7 ++-- pyshacl/rdfutil/pytypes.py | 8 ----- pyshacl/rules/__init__.py | 6 ++-- pyshacl/rules/sparql/__init__.py | 4 +-- pyshacl/rules/triple/__init__.py | 4 +-- pyshacl/shape.py | 5 +-- pyshacl/target.py | 10 ++++-- pyshacl/validate.py | 34 ++++++++++--------- 31 files changed, 154 insertions(+), 145 deletions(-) delete mode 100644 pyshacl/rdfutil/pytypes.py diff --git a/pyshacl/constraints/advanced/__init__.py b/pyshacl/constraints/advanced/__init__.py index 841bdc9..633ba06 100644 --- a/pyshacl/constraints/advanced/__init__.py +++ b/pyshacl/constraints/advanced/__init__.py @@ -7,13 +7,14 @@ import typing from typing import Dict, List +import rdflib from rdflib import Literal from pyshacl.constraints.constraint_component import ConstraintComponent from pyshacl.consts import SH, SH_message from pyshacl.errors import ConstraintLoadError from pyshacl.helper.expression_helper import nodes_from_node_expression -from pyshacl.pytypes import GraphLike, SHACLExecutor +from pyshacl.pytypes import SHACLExecutor SH_expression = SH.expression SH_ExpressionConstraintComponent = SH.ExpressionConstraintComponent @@ -42,11 +43,11 @@ def constraint_parameters(cls): def constraint_name(cls): return "ExpressionConstraintComponent" - def make_generic_messages(self, datagraph: GraphLike, focus_node, value_node) -> List[Literal]: + def make_generic_messages(self, datagraph: rdflib.Graph, focus_node, value_node) -> List[Literal]: return [Literal("Expression evaluation generated constraint did not return true.")] def evaluate( - self, executor: SHACLExecutor, data_graph: GraphLike, focus_value_nodes: Dict, _evaluation_path: List + self, executor: SHACLExecutor, data_graph: rdflib.Graph, focus_value_nodes: Dict, _evaluation_path: List ): """ :type executor: SHACLExecutor diff --git a/pyshacl/constraints/constraint_component.py b/pyshacl/constraints/constraint_component.py index 4794e66..0d6455b 100644 --- a/pyshacl/constraints/constraint_component.py +++ b/pyshacl/constraints/constraint_component.py @@ -8,6 +8,7 @@ import typing from typing import TYPE_CHECKING, Any, Dict, Iterable, List, Optional, Set, Tuple +import rdflib from rdflib import BNode, Literal, URIRef from pyshacl.consts import ( @@ -33,7 +34,7 @@ ) from pyshacl.errors import ConstraintLoadError from pyshacl.parameter import SHACLParameter -from pyshacl.pytypes import GraphLike, SHACLExecutor +from pyshacl.pytypes import SHACLExecutor from pyshacl.rdfutil import stringify_node if TYPE_CHECKING: @@ -78,11 +79,11 @@ def constraint_name(cls): @abc.abstractmethod def evaluate( - self, executor: SHACLExecutor, target_graph: GraphLike, focus_value_nodes: Dict, _evaluation_path: List + self, executor: SHACLExecutor, target_graph: rdflib.Graph, focus_value_nodes: Dict, _evaluation_path: List ): raise NotImplementedError() # pragma: no cover - def make_generic_messages(self, datagraph: GraphLike, focus_node, value_node) -> List[Literal]: + def make_generic_messages(self, datagraph: rdflib.Graph, focus_node, value_node) -> List[Literal]: return [] def __str__(self): @@ -127,7 +128,7 @@ def recursion_triggers(self, _evaluation_path, trigger_depth=3) -> Optional[List def make_v_result_description( self, - datagraph: GraphLike, + datagraph: rdflib.Graph, focus_node: 'RDFNode', severity: URIRef, value_node: Optional['RDFNode'], @@ -209,7 +210,7 @@ def make_v_result_description( def make_v_result( self, - datagraph: GraphLike, + datagraph: rdflib.Graph, focus_node: 'RDFNode', value_node: Optional['RDFNode'] = None, result_path: Optional['RDFNode'] = None, diff --git a/pyshacl/constraints/core/cardinality_constraints.py b/pyshacl/constraints/core/cardinality_constraints.py index 16490b4..65c665d 100644 --- a/pyshacl/constraints/core/cardinality_constraints.py +++ b/pyshacl/constraints/core/cardinality_constraints.py @@ -4,13 +4,14 @@ """ from typing import Dict, List +import rdflib from rdflib.namespace import XSD from rdflib.term import Literal from pyshacl.constraints.constraint_component import ConstraintComponent from pyshacl.consts import SH from pyshacl.errors import ConstraintLoadError -from pyshacl.pytypes import GraphLike, SHACLExecutor +from pyshacl.pytypes import SHACLExecutor from pyshacl.rdfutil import stringify_node XSD_integer = XSD.integer @@ -70,7 +71,7 @@ def constraint_parameters(cls): def constraint_name(cls): return "MinCountConstraintComponent" - def make_generic_messages(self, datagraph: GraphLike, focus_node, value_node) -> List[Literal]: + def make_generic_messages(self, datagraph: rdflib.Graph, focus_node, value_node) -> List[Literal]: p = self.shape.path() if p: p = stringify_node(self.shape.sg.graph, p) @@ -82,7 +83,7 @@ def make_generic_messages(self, datagraph: GraphLike, focus_node, value_node) -> return [Literal(m)] def evaluate( - self, executor: SHACLExecutor, target_graph: GraphLike, focus_value_nodes: Dict, _evaluation_path: List + self, executor: SHACLExecutor, target_graph: rdflib.Graph, focus_value_nodes: Dict, _evaluation_path: List ): """ :type executor: SHACLExecutor @@ -153,7 +154,7 @@ def constraint_parameters(cls): def constraint_name(cls): return "MaxCountConstraintComponent" - def make_generic_messages(self, datagraph: GraphLike, focus_node, value_node) -> List[Literal]: + def make_generic_messages(self, datagraph: rdflib.Graph, focus_node, value_node) -> List[Literal]: p = self.shape.path() if p: p = stringify_node(self.shape.sg.graph, p) @@ -165,7 +166,7 @@ def make_generic_messages(self, datagraph: GraphLike, focus_node, value_node) -> return [Literal(m)] def evaluate( - self, executor: SHACLExecutor, target_graph: GraphLike, focus_value_nodes: Dict, _evaluation_path: List + self, executor: SHACLExecutor, target_graph: rdflib.Graph, focus_value_nodes: Dict, _evaluation_path: List ): """ :type executor: SHACLExecutor diff --git a/pyshacl/constraints/core/logical_constraints.py b/pyshacl/constraints/core/logical_constraints.py index 31ae059..b4338a4 100644 --- a/pyshacl/constraints/core/logical_constraints.py +++ b/pyshacl/constraints/core/logical_constraints.py @@ -10,7 +10,7 @@ from pyshacl.constraints.constraint_component import ConstraintComponent from pyshacl.consts import SH from pyshacl.errors import ConstraintLoadError, ReportableRuntimeError, ShapeRecursionWarning, ValidationFailure -from pyshacl.pytypes import GraphLike, SHACLExecutor +from pyshacl.pytypes import SHACLExecutor from pyshacl.rdfutil import stringify_node SH_not = SH["not"] @@ -55,7 +55,7 @@ def constraint_parameters(cls): def constraint_name(cls): return "NotConstraintComponent" - def make_generic_messages(self, datagraph: GraphLike, focus_node, value_node) -> List[rdflib.Literal]: + def make_generic_messages(self, datagraph: rdflib.Graph, focus_node, value_node) -> List[rdflib.Literal]: if len(self.not_list) == 1: m = f"Node {stringify_node(datagraph, value_node)} conforms to shape {stringify_node(self.shape.sg.graph, self.not_list[0])}" else: @@ -63,7 +63,9 @@ def make_generic_messages(self, datagraph: GraphLike, focus_node, value_node) -> m = f"Node {stringify_node(datagraph, value_node)} conforms to one or more shapes in {nots_list}" return [rdflib.Literal(m)] - def evaluate(self, executor: SHACLExecutor, datagraph: GraphLike, focus_value_nodes: Dict, _evaluation_path: List): + def evaluate( + self, executor: SHACLExecutor, datagraph: rdflib.Graph, focus_value_nodes: Dict, _evaluation_path: List + ): """ :type executor: SHACLExecutor :type datagraph: rdflib.Graph @@ -158,7 +160,7 @@ def constraint_parameters(cls): def constraint_name(cls): return "AndConstraintComponent" - def make_generic_messages(self, datagraph: GraphLike, focus_node, value_node) -> List[rdflib.Literal]: + def make_generic_messages(self, datagraph: rdflib.Graph, focus_node, value_node) -> List[rdflib.Literal]: and_list = " , ".join( stringify_node(self.shape.sg.graph, a_c) for a in self.and_list for a_c in self.shape.sg.graph.items(a) ) @@ -166,7 +168,7 @@ def make_generic_messages(self, datagraph: GraphLike, focus_node, value_node) -> return [rdflib.Literal(m)] def evaluate( - self, executor: SHACLExecutor, target_graph: GraphLike, focus_value_nodes: Dict, _evaluation_path: List + self, executor: SHACLExecutor, target_graph: rdflib.Graph, focus_value_nodes: Dict, _evaluation_path: List ): """ :type executor: SHACLExecutor @@ -254,7 +256,7 @@ def constraint_parameters(cls): def constraint_name(cls): return "OrConstraintComponent" - def make_generic_messages(self, datagraph: GraphLike, focus_node, value_node) -> List[rdflib.Literal]: + def make_generic_messages(self, datagraph: rdflib.Graph, focus_node, value_node) -> List[rdflib.Literal]: or_list = " , ".join( stringify_node(self.shape.sg.graph, o_c) for o in self.or_list for o_c in self.shape.sg.graph.items(o) ) @@ -264,7 +266,7 @@ def make_generic_messages(self, datagraph: GraphLike, focus_node, value_node) -> return [rdflib.Literal(m)] def evaluate( - self, executor: SHACLExecutor, target_graph: GraphLike, focus_value_nodes: Dict, _evaluation_path: List + self, executor: SHACLExecutor, target_graph: rdflib.Graph, focus_value_nodes: Dict, _evaluation_path: List ): """ :type executor: SHACLExecutor @@ -352,7 +354,7 @@ def constraint_parameters(cls): def constraint_name(cls): return "XoneConstraintComponent" - def make_generic_messages(self, datagraph: GraphLike, focus_node, value_node) -> List[rdflib.Literal]: + def make_generic_messages(self, datagraph: rdflib.Graph, focus_node, value_node) -> List[rdflib.Literal]: xone_list = " , ".join( stringify_node(self.shape.sg.graph, a_c) for a in self.xone_nodes for a_c in self.shape.sg.graph.items(a) ) @@ -362,7 +364,7 @@ def make_generic_messages(self, datagraph: GraphLike, focus_node, value_node) -> return [rdflib.Literal(m)] def evaluate( - self, executor: SHACLExecutor, target_graph: GraphLike, focus_value_nodes: Dict, _evaluation_path: List + self, executor: SHACLExecutor, target_graph: rdflib.Graph, focus_value_nodes: Dict, _evaluation_path: List ): """ :type executor: SHACLExecutor diff --git a/pyshacl/constraints/core/other_constraints.py b/pyshacl/constraints/core/other_constraints.py index e4c5db3..710c029 100644 --- a/pyshacl/constraints/core/other_constraints.py +++ b/pyshacl/constraints/core/other_constraints.py @@ -9,7 +9,7 @@ from pyshacl.constraints.constraint_component import ConstraintComponent from pyshacl.consts import RDFS, SH, RDF_type, SH_property from pyshacl.errors import ConstraintLoadError, ReportableRuntimeError -from pyshacl.pytypes import GraphLike, RDFNode, SHACLExecutor +from pyshacl.pytypes import RDFNode, SHACLExecutor from pyshacl.rdfutil import stringify_node SH_InConstraintComponent = SH.InConstraintComponent @@ -61,13 +61,13 @@ def constraint_parameters(cls): def constraint_name(cls): return "InConstraintComponent" - def make_generic_messages(self, datagraph: GraphLike, focus_node, value_node) -> List[rdflib.Literal]: + def make_generic_messages(self, datagraph: rdflib.Graph, focus_node, value_node) -> List[rdflib.Literal]: list1 = [stringify_node(self.shape.sg.graph, val) for val in self.in_vals] m = "Value {} not in list {}".format(stringify_node(datagraph, value_node), list1) return [rdflib.Literal(m)] def evaluate( - self, executor: SHACLExecutor, target_graph: GraphLike, focus_value_nodes: Dict, _evaluation_path: List + self, executor: SHACLExecutor, target_graph: rdflib.Graph, focus_value_nodes: Dict, _evaluation_path: List ): """ :type executor: SHACLExecutor @@ -140,14 +140,14 @@ def constraint_parameters(cls): def constraint_name(cls): return "ClosedConstraintComponent" - def make_generic_messages(self, datagraph: GraphLike, focus_node, value_node) -> List[rdflib.Literal]: + def make_generic_messages(self, datagraph: rdflib.Graph, focus_node, value_node) -> List[rdflib.Literal]: m = "Node {} is closed. It cannot have value: {}".format( stringify_node(datagraph, focus_node), stringify_node(datagraph, value_node) ) return [rdflib.Literal(m)] def evaluate( - self, executor: SHACLExecutor, target_graph: GraphLike, focus_value_nodes: Dict, _evaluation_path: List + self, executor: SHACLExecutor, target_graph: rdflib.Graph, focus_value_nodes: Dict, _evaluation_path: List ): """ :type executor: SHACLExecutor @@ -221,7 +221,7 @@ def constraint_parameters(cls): def constraint_name(cls): return "HasValueConstraintComponent" - def make_generic_messages(self, datagraph: GraphLike, focus_node, value_node) -> List[rdflib.Literal]: + def make_generic_messages(self, datagraph: rdflib.Graph, focus_node, value_node) -> List[rdflib.Literal]: the_set = [stringify_node(self.shape.sg.graph, s) for s in self.has_value_set] p = self.shape.path() if p: @@ -236,7 +236,7 @@ def make_generic_messages(self, datagraph: GraphLike, focus_node, value_node) -> return [rdflib.Literal(m)] def evaluate( - self, executor: SHACLExecutor, target_graph: GraphLike, focus_value_nodes: Dict, _evaluation_path: List + self, executor: SHACLExecutor, target_graph: rdflib.Graph, focus_value_nodes: Dict, _evaluation_path: List ): """ :type executor: SHACLExecutor diff --git a/pyshacl/constraints/core/property_pair_constraints.py b/pyshacl/constraints/core/property_pair_constraints.py index b96deed..809ea8d 100644 --- a/pyshacl/constraints/core/property_pair_constraints.py +++ b/pyshacl/constraints/core/property_pair_constraints.py @@ -9,7 +9,7 @@ from pyshacl.constraints.constraint_component import ConstraintComponent from pyshacl.consts import SH from pyshacl.errors import ConstraintLoadError, ReportableRuntimeError -from pyshacl.pytypes import GraphLike, SHACLExecutor +from pyshacl.pytypes import SHACLExecutor from pyshacl.rdfutil import stringify_node SH_equals = SH.equals @@ -52,7 +52,7 @@ def constraint_parameters(cls): def constraint_name(cls): return "EqualsConstraintComponent" - def make_generic_messages(self, datagraph: GraphLike, focus_node, value_node) -> List[rdflib.Literal]: + def make_generic_messages(self, datagraph: rdflib.Graph, focus_node, value_node) -> List[rdflib.Literal]: if len(self.property_compare_set) < 2: m = "Value of {}->{} != {}".format( stringify_node(datagraph, focus_node), @@ -67,7 +67,7 @@ def make_generic_messages(self, datagraph: GraphLike, focus_node, value_node) -> return [rdflib.Literal(m)] def evaluate( - self, executor: SHACLExecutor, target_graph: GraphLike, focus_value_nodes: Dict, _evaluation_path: List + self, executor: SHACLExecutor, target_graph: rdflib.Graph, focus_value_nodes: Dict, _evaluation_path: List ): """ :type executor: SHACLExecutor @@ -134,7 +134,7 @@ def constraint_parameters(cls): def constraint_name(cls): return "DisjointConstraintComponent" - def make_generic_messages(self, datagraph: GraphLike, focus_node, value_node) -> List[rdflib.Literal]: + def make_generic_messages(self, datagraph: rdflib.Graph, focus_node, value_node) -> List[rdflib.Literal]: if len(self.property_compare_set) < 2: m = "Value of {}->{} == {}".format( stringify_node(datagraph, focus_node), @@ -149,7 +149,7 @@ def make_generic_messages(self, datagraph: GraphLike, focus_node, value_node) -> return [rdflib.Literal(m)] def evaluate( - self, executor: SHACLExecutor, target_graph: GraphLike, focus_value_nodes: Dict, _evaluation_path: List + self, executor: SHACLExecutor, target_graph: rdflib.Graph, focus_value_nodes: Dict, _evaluation_path: List ): """ :type executor: SHACLExecutor @@ -218,7 +218,7 @@ def constraint_parameters(cls): def constraint_name(cls): return "LessThanConstraintComponent" - def make_generic_messages(self, datagraph: GraphLike, focus_node, value_node) -> List[rdflib.Literal]: + def make_generic_messages(self, datagraph: rdflib.Graph, focus_node, value_node) -> List[rdflib.Literal]: if len(self.property_compare_set) < 2: m = "Value of {}->{} <= {}".format( stringify_node(datagraph, focus_node), @@ -233,7 +233,7 @@ def make_generic_messages(self, datagraph: GraphLike, focus_node, value_node) -> return [rdflib.Literal(m)] def evaluate( - self, executor: SHACLExecutor, target_graph: GraphLike, focus_value_nodes: Dict, _evaluation_path: List + self, executor: SHACLExecutor, target_graph: rdflib.Graph, focus_value_nodes: Dict, _evaluation_path: List ): """ :type executor: SHACLExecutor @@ -326,7 +326,7 @@ def constraint_parameters(cls): def constraint_name(cls): return "LessThanOrEqualsConstraintComponent" - def make_generic_messages(self, datagraph: GraphLike, focus_node, value_node) -> List[rdflib.Literal]: + def make_generic_messages(self, datagraph: rdflib.Graph, focus_node, value_node) -> List[rdflib.Literal]: if len(self.property_compare_set) < 2: m = "Value of {}->{} < {}".format( stringify_node(datagraph, focus_node), @@ -341,7 +341,7 @@ def make_generic_messages(self, datagraph: GraphLike, focus_node, value_node) -> return [rdflib.Literal(m)] def evaluate( - self, executor: SHACLExecutor, target_graph: GraphLike, focus_value_nodes: Dict, _evaluation_path: List + self, executor: SHACLExecutor, target_graph: rdflib.Graph, focus_value_nodes: Dict, _evaluation_path: List ): """ :type executor: SHACLExecutor diff --git a/pyshacl/constraints/core/shape_based_constraints.py b/pyshacl/constraints/core/shape_based_constraints.py index 1d935ea..d2af70b 100644 --- a/pyshacl/constraints/core/shape_based_constraints.py +++ b/pyshacl/constraints/core/shape_based_constraints.py @@ -24,7 +24,7 @@ ShapeRecursionWarning, ValidationFailure, ) -from pyshacl.pytypes import GraphLike, SHACLExecutor +from pyshacl.pytypes import SHACLExecutor from pyshacl.rdfutil import stringify_node SH_QualifiedValueCountConstraintComponent = SH.QualifiedValueConstraintComponent @@ -68,11 +68,11 @@ def constraint_parameters(cls): def constraint_name(cls): return "PropertyConstraintComponent" - def make_generic_messages(self, datagraph: GraphLike, focus_node, value_node) -> List[rdflib.Literal]: + def make_generic_messages(self, datagraph: rdflib.Graph, focus_node, value_node) -> List[rdflib.Literal]: raise NotImplementedError("A Property Constraint Component should not be able to generate its own message.") def evaluate( - self, executor: SHACLExecutor, target_graph: GraphLike, focus_value_nodes: Dict, _evaluation_path: List + self, executor: SHACLExecutor, target_graph: rdflib.Graph, focus_value_nodes: Dict, _evaluation_path: List ): """ Entrypoint for constraint evaluation. @@ -156,7 +156,7 @@ def constraint_parameters(cls): def constraint_name(cls): return "NodeConstraintComponent" - def make_generic_messages(self, datagraph: GraphLike, focus_node, value_node) -> List[rdflib.Literal]: + def make_generic_messages(self, datagraph: rdflib.Graph, focus_node, value_node) -> List[rdflib.Literal]: if len(self.node_shapes) < 2: m = "Value does not conform to Shape {}.".format(stringify_node(self.shape.sg.graph, self.node_shapes[0])) else: @@ -166,7 +166,7 @@ def make_generic_messages(self, datagraph: GraphLike, focus_node, value_node) -> return [rdflib.Literal(m)] def evaluate( - self, executor: SHACLExecutor, target_graph: GraphLike, focus_value_nodes: Dict, _evaluation_path: List + self, executor: SHACLExecutor, target_graph: rdflib.Graph, focus_value_nodes: Dict, _evaluation_path: List ): """ :type executor: SHACLExecutor @@ -317,7 +317,7 @@ def constraint_parameters(cls): def constraint_name(cls): return "QualifiedValueShapeConstraintComponent" - def make_generic_messages(self, datagraph: GraphLike, focus_node, value_node) -> List[rdflib.Literal]: + def make_generic_messages(self, datagraph: rdflib.Graph, focus_node, value_node) -> List[rdflib.Literal]: # TODO: # Implement default message for QualifiedValueConstraint (seems messy) shapes_string = ",".join(stringify_node(self.shape.sg.graph, s) for s in self.value_shapes) @@ -331,7 +331,7 @@ def make_generic_messages(self, datagraph: GraphLike, focus_node, value_node) -> return [rdflib.Literal(f"Focus node does not conform to shape{count_message}: {shapes_string}")] def evaluate( - self, executor: SHACLExecutor, target_graph: GraphLike, focus_value_nodes: Dict, _evaluation_path: List + self, executor: SHACLExecutor, target_graph: rdflib.Graph, focus_value_nodes: Dict, _evaluation_path: List ): """ :type executor: SHACLExecutor diff --git a/pyshacl/constraints/core/string_based_constraints.py b/pyshacl/constraints/core/string_based_constraints.py index 5adf9a1..c085963 100644 --- a/pyshacl/constraints/core/string_based_constraints.py +++ b/pyshacl/constraints/core/string_based_constraints.py @@ -11,7 +11,7 @@ from pyshacl.constraints.constraint_component import ConstraintComponent from pyshacl.consts import RDF, SH, XSD_WHOLE_INTEGERS from pyshacl.errors import ConstraintLoadError, ReportableRuntimeError -from pyshacl.pytypes import GraphLike, SHACLExecutor +from pyshacl.pytypes import SHACLExecutor from pyshacl.rdfutil import stringify_node RDF_langString = RDF.langString @@ -67,7 +67,7 @@ def _evaluate_string_rule(self, r, target_graph, f_v_dict): raise NotImplementedError() def evaluate( - self, executor: SHACLExecutor, target_graph: GraphLike, focus_value_nodes: Dict, _evaluation_path: List + self, executor: SHACLExecutor, target_graph: rdflib.Graph, focus_value_nodes: Dict, _evaluation_path: List ): """ :type executor: SHACLExecutor @@ -139,7 +139,7 @@ def constraint_parameters(cls): def constraint_name(cls): return "MinLengthConstraintComponent" - def make_generic_messages(self, datagraph: GraphLike, focus_node, value_node) -> List[rdflib.Literal]: + def make_generic_messages(self, datagraph: rdflib.Graph, focus_node, value_node) -> List[rdflib.Literal]: m = "String length not >= {}".format(stringify_node(datagraph, self.string_rules[0])) return [rdflib.Literal(m)] @@ -219,7 +219,7 @@ def constraint_parameters(cls): def constraint_name(cls): return "MaxLengthConstraintComponent" - def make_generic_messages(self, datagraph: GraphLike, focus_node, value_node) -> List[rdflib.Literal]: + def make_generic_messages(self, datagraph: rdflib.Graph, focus_node, value_node) -> List[rdflib.Literal]: m = "String length not <= {}".format(stringify_node(datagraph, self.string_rules[0])) return [rdflib.Literal(m)] @@ -287,7 +287,7 @@ def constraint_parameters(cls): def constraint_name(cls): return "PatternConstraintComponent" - def make_generic_messages(self, datagraph: GraphLike, focus_node, value_node) -> List[rdflib.Literal]: + def make_generic_messages(self, datagraph: rdflib.Graph, focus_node, value_node) -> List[rdflib.Literal]: if len(self.string_rules) < 2: m = "Value does not match pattern '{}'".format(str(self.string_rules[0].value)) else: @@ -365,7 +365,7 @@ def constraint_parameters(cls): def constraint_name(cls): return "LanguageInConstraintComponent" - def make_generic_messages(self, datagraph: GraphLike, focus_node, value_node) -> List[rdflib.Literal]: + def make_generic_messages(self, datagraph: rdflib.Graph, focus_node, value_node) -> List[rdflib.Literal]: m = "String language is not in {}".format(stringify_node(datagraph, self.string_rules[0])) return [rdflib.Literal(m)] @@ -459,7 +459,7 @@ def constraint_parameters(cls): def constraint_name(cls): return "UniqueLangConstraintComponent" - def make_generic_messages(self, datagraph: GraphLike, focus_node, value_node) -> List[rdflib.Literal]: + def make_generic_messages(self, datagraph: rdflib.Graph, focus_node, value_node) -> List[rdflib.Literal]: return [rdflib.Literal("More than one String shares the same Language")] def _evaluate_string_rule(self, is_unique_lang, target_graph, f_v_dict): diff --git a/pyshacl/constraints/core/value_constraints.py b/pyshacl/constraints/core/value_constraints.py index 28ae7e9..3419c2c 100644 --- a/pyshacl/constraints/core/value_constraints.py +++ b/pyshacl/constraints/core/value_constraints.py @@ -27,7 +27,7 @@ SH_nodeKind, ) from pyshacl.errors import ConstraintLoadError -from pyshacl.pytypes import GraphLike, SHACLExecutor +from pyshacl.pytypes import SHACLExecutor from pyshacl.rdfutil import stringify_node RDF_langString = RDF.langString @@ -77,7 +77,7 @@ def constraint_parameters(cls): def constraint_name(cls): return "ClassConstraintComponent" - def make_generic_messages(self, datagraph: GraphLike, focus_node, value_node) -> List[Literal]: + def make_generic_messages(self, datagraph: rdflib.Graph, focus_node, value_node) -> List[Literal]: if len(self.class_rules) < 2: m = "Value does not have class {}".format(stringify_node(self.shape.sg.graph, self.class_rules[0])) else: @@ -86,7 +86,7 @@ def make_generic_messages(self, datagraph: GraphLike, focus_node, value_node) -> return [Literal(m)] def evaluate( - self, executor: SHACLExecutor, target_graph: GraphLike, focus_value_nodes: Dict, _evaluation_path: List + self, executor: SHACLExecutor, target_graph: rdflib.Graph, focus_value_nodes: Dict, _evaluation_path: List ): """ :type executor: SHACLExecutor @@ -164,12 +164,12 @@ def constraint_parameters(cls): def constraint_name(cls): return "DatatypeConstraintComponent" - def make_generic_messages(self, datagraph: GraphLike, focus_node, value_node) -> List[Literal]: + def make_generic_messages(self, datagraph: rdflib.Graph, focus_node, value_node) -> List[Literal]: m = "Value is not Literal with datatype {}".format(stringify_node(self.shape.sg.graph, self.datatype_rule)) return [Literal(m)] def evaluate( - self, executor: SHACLExecutor, target_graph: GraphLike, focus_value_nodes: Dict, _evaluation_path: List + self, executor: SHACLExecutor, target_graph: rdflib.Graph, focus_value_nodes: Dict, _evaluation_path: List ): """ :type executor: SHACLExecutor @@ -272,12 +272,12 @@ def constraint_parameters(cls): def constraint_name(cls): return "NodeKindConstraintComponent" - def make_generic_messages(self, datagraph: GraphLike, focus_node, value_node) -> List[Literal]: + def make_generic_messages(self, datagraph: rdflib.Graph, focus_node, value_node) -> List[Literal]: m = "Value is not of Node Kind {}".format(stringify_node(self.shape.sg.graph, self.nodekind_rule)) return [Literal(m)] def evaluate( - self, executor: SHACLExecutor, target_graph: GraphLike, focus_value_nodes: Dict, _evaluation_path: List + self, executor: SHACLExecutor, target_graph: rdflib.Graph, focus_value_nodes: Dict, _evaluation_path: List ): """ :type executor: SHACLExecutor diff --git a/pyshacl/constraints/core/value_range_constraints.py b/pyshacl/constraints/core/value_range_constraints.py index a4b285e..357f928 100644 --- a/pyshacl/constraints/core/value_range_constraints.py +++ b/pyshacl/constraints/core/value_range_constraints.py @@ -10,7 +10,7 @@ from pyshacl.constraints.constraint_component import ConstraintComponent from pyshacl.consts import SH from pyshacl.errors import ConstraintLoadError, ReportableRuntimeError -from pyshacl.pytypes import GraphLike, SHACLExecutor +from pyshacl.pytypes import SHACLExecutor from pyshacl.rdfutil import stringify_node from pyshacl.rdfutil.compare import compare_literal @@ -52,7 +52,7 @@ def constraint_parameters(cls): def constraint_name(cls): return "MinExclusiveConstraintComponent" - def make_generic_messages(self, datagraph: GraphLike, focus_node, value_node) -> List[rdflib.Literal]: + def make_generic_messages(self, datagraph: rdflib.Graph, focus_node, value_node) -> List[rdflib.Literal]: if len(self.min_vals) < 2: m = "Value is not > {}".format(stringify_node(self.shape.sg.graph, self.min_vals[0])) else: @@ -61,7 +61,7 @@ def make_generic_messages(self, datagraph: GraphLike, focus_node, value_node) -> return [rdflib.Literal(m)] def evaluate( - self, executor: SHACLExecutor, target_graph: GraphLike, focus_value_nodes: Dict, _evaluation_path: List + self, executor: SHACLExecutor, target_graph: rdflib.Graph, focus_value_nodes: Dict, _evaluation_path: List ): """ :type executor: SHACLExecutor @@ -142,7 +142,7 @@ def constraint_parameters(cls): def constraint_name(cls): return "MinInclusiveConstraintComponent" - def make_generic_messages(self, datagraph: GraphLike, focus_node, value_node) -> List[rdflib.Literal]: + def make_generic_messages(self, datagraph: rdflib.Graph, focus_node, value_node) -> List[rdflib.Literal]: if len(self.min_vals) < 2: m = "Value is not >= {}".format(stringify_node(self.shape.sg.graph, self.min_vals[0])) else: @@ -151,7 +151,7 @@ def make_generic_messages(self, datagraph: GraphLike, focus_node, value_node) -> return [rdflib.Literal(m)] def evaluate( - self, executor: SHACLExecutor, target_graph: GraphLike, focus_value_nodes: Dict, _evaluation_path: List + self, executor: SHACLExecutor, target_graph: rdflib.Graph, focus_value_nodes: Dict, _evaluation_path: List ): """ :type executor: SHACLExecutor @@ -232,7 +232,7 @@ def constraint_parameters(cls): def constraint_name(cls): return "MaxExclusiveConstraintComponent" - def make_generic_messages(self, datagraph: GraphLike, focus_node, value_node) -> List[rdflib.Literal]: + def make_generic_messages(self, datagraph: rdflib.Graph, focus_node, value_node) -> List[rdflib.Literal]: if len(self.max_vals) < 2: m = "Value is not < {}".format(stringify_node(self.shape.sg.graph, self.max_vals[0])) else: @@ -241,7 +241,7 @@ def make_generic_messages(self, datagraph: GraphLike, focus_node, value_node) -> return [rdflib.Literal(m)] def evaluate( - self, executor: SHACLExecutor, target_graph: GraphLike, focus_value_nodes: Dict, _evaluation_path: List + self, executor: SHACLExecutor, target_graph: rdflib.Graph, focus_value_nodes: Dict, _evaluation_path: List ): """ :type executor: SHACLExecutor @@ -322,7 +322,7 @@ def constraint_parameters(cls): def constraint_name(cls): return "MaxInclusiveConstraintComponent" - def make_generic_messages(self, datagraph: GraphLike, focus_node, value_node) -> List[rdflib.Literal]: + def make_generic_messages(self, datagraph: rdflib.Graph, focus_node, value_node) -> List[rdflib.Literal]: if len(self.max_vals) < 2: m = "Value is not <= {}".format(stringify_node(self.shape.sg.graph, self.max_vals[0])) else: @@ -331,7 +331,7 @@ def make_generic_messages(self, datagraph: GraphLike, focus_node, value_node) -> return [rdflib.Literal(m)] def evaluate( - self, executor: SHACLExecutor, target_graph: GraphLike, focus_value_nodes: Dict, _evaluation_path: List + self, executor: SHACLExecutor, target_graph: rdflib.Graph, focus_value_nodes: Dict, _evaluation_path: List ): """ :type executor: SHACLExecutor diff --git a/pyshacl/constraints/sparql/sparql_based_constraint_components.py b/pyshacl/constraints/sparql/sparql_based_constraint_components.py index 92c1ff9..c2d2b88 100644 --- a/pyshacl/constraints/sparql/sparql_based_constraint_components.py +++ b/pyshacl/constraints/sparql/sparql_based_constraint_components.py @@ -11,7 +11,7 @@ from pyshacl.consts import SH, RDF_type, SH_ask, SH_ConstraintComponent, SH_message, SH_select from pyshacl.errors import ConstraintLoadError, ValidationFailure from pyshacl.helper import get_query_helper_cls -from pyshacl.pytypes import GraphLike, SHACLExecutor +from pyshacl.pytypes import SHACLExecutor if typing.TYPE_CHECKING: from pyshacl.shape import Shape @@ -55,11 +55,11 @@ def constraint_parameters(cls): def constraint_name(cls): return "ConstraintComponent" - def make_generic_messages(self, datagraph: GraphLike, focus_node, value_node) -> List[rdflib.Literal]: + def make_generic_messages(self, datagraph: rdflib.Graph, focus_node, value_node) -> List[rdflib.Literal]: return [rdflib.Literal("Parameterised SHACL Query generated constraint validation reports.")] def evaluate( - self, executor: SHACLExecutor, target_graph: GraphLike, focus_value_nodes: Dict, _evaluation_path: List + self, executor: SHACLExecutor, target_graph: rdflib.Graph, focus_value_nodes: Dict, _evaluation_path: List ): """ :type executor: SHACLExecutor diff --git a/pyshacl/constraints/sparql/sparql_based_constraints.py b/pyshacl/constraints/sparql/sparql_based_constraints.py index 4fc8bf4..f87eb16 100644 --- a/pyshacl/constraints/sparql/sparql_based_constraints.py +++ b/pyshacl/constraints/sparql/sparql_based_constraints.py @@ -10,7 +10,7 @@ from pyshacl.consts import SH, SH_deactivated, SH_message, SH_select from pyshacl.errors import ConstraintLoadError, ValidationFailure from pyshacl.helper import get_query_helper_cls -from pyshacl.pytypes import GraphLike, SHACLExecutor +from pyshacl.pytypes import SHACLExecutor SH_sparql = SH.sparql SH_SPARQLConstraintComponent = SH.SPARQLConstraintComponent @@ -89,7 +89,7 @@ def constraint_name(cls): return "SPARQLConstraintComponent" def evaluate( - self, executor: SHACLExecutor, target_graph: GraphLike, focus_value_nodes: Dict, _evaluation_path: List + self, executor: SHACLExecutor, target_graph: rdflib.Graph, focus_value_nodes: Dict, _evaluation_path: List ): """ :type executor: SHACLExecutor diff --git a/pyshacl/extras/js/constraint.py b/pyshacl/extras/js/constraint.py index 1b7b228..07b11f1 100644 --- a/pyshacl/extras/js/constraint.py +++ b/pyshacl/extras/js/constraint.py @@ -3,12 +3,13 @@ import typing from typing import Dict, List +import rdflib from rdflib import Literal from pyshacl.constraints import ConstraintComponent from pyshacl.consts import SH, SH_js, SH_message from pyshacl.errors import ConstraintLoadError -from pyshacl.pytypes import GraphLike, SHACLExecutor +from pyshacl.pytypes import SHACLExecutor from .js_executable import JSExecutable @@ -77,11 +78,11 @@ def constraint_parameters(cls): def constraint_name(cls): return "JSConstraint" - def make_generic_messages(self, datagraph: GraphLike, focus_node, value_node) -> List[Literal]: + def make_generic_messages(self, datagraph: rdflib.Graph, focus_node, value_node) -> List[Literal]: return [Literal("Javascript Function generated constraint validation reports.")] def evaluate( - self, executor: SHACLExecutor, data_graph: GraphLike, focus_value_nodes: Dict, _evaluation_path: List + self, executor: SHACLExecutor, data_graph: rdflib.Graph, focus_value_nodes: Dict, _evaluation_path: List ): """ :type executor: SHACLExecutor diff --git a/pyshacl/extras/js/constraint_component.py b/pyshacl/extras/js/constraint_component.py index defe46c..f4a47d5 100644 --- a/pyshacl/extras/js/constraint_component.py +++ b/pyshacl/extras/js/constraint_component.py @@ -3,13 +3,14 @@ import typing from typing import Any, Dict, List, Tuple, Union +import rdflib from rdflib import Literal from pyshacl.constraints import ConstraintComponent from pyshacl.constraints.constraint_component import CustomConstraintComponent from pyshacl.consts import SH, SH_ConstraintComponent, SH_message from pyshacl.errors import ConstraintLoadError, ReportableRuntimeError, ValidationFailure -from pyshacl.pytypes import GraphLike, SHACLExecutor +from pyshacl.pytypes import SHACLExecutor from .js_executable import JSExecutable @@ -73,11 +74,11 @@ def constraint_parameters(cls): def constraint_name(cls): return "ConstraintComponent" - def make_generic_messages(self, datagraph: GraphLike, focus_node, value_node) -> List[Literal]: + def make_generic_messages(self, datagraph: rdflib.Graph, focus_node, value_node) -> List[Literal]: return [Literal("Parameterised Javascript Function generated constraint validation reports.")] def evaluate( - self, executor: SHACLExecutor, data_graph: GraphLike, focus_value_nodes: Dict, _evaluation_path: List + self, executor: SHACLExecutor, data_graph: rdflib.Graph, focus_value_nodes: Dict, _evaluation_path: List ): """ :type executor: SHACLExecutor diff --git a/pyshacl/extras/js/rules.py b/pyshacl/extras/js/rules.py index 5d2548c..a74ad64 100644 --- a/pyshacl/extras/js/rules.py +++ b/pyshacl/extras/js/rules.py @@ -2,6 +2,8 @@ # import typing +import rdflib + from pyshacl.consts import SH from pyshacl.errors import ReportableRuntimeError from pyshacl.rules.shacl_rule import SHACLRule @@ -9,7 +11,7 @@ from .js_executable import JSExecutable if typing.TYPE_CHECKING: - from pyshacl.pytypes import GraphLike, SHACLExecutor + from pyshacl.pytypes import SHACLExecutor from pyshacl.shape import Shape from pyshacl.shapes_graph import ShapesGraph @@ -24,7 +26,7 @@ def __init__(self, executor: 'SHACLExecutor', shape: 'Shape', rule_node, **kwarg shapes_graph: 'ShapesGraph' = shape.sg self.js_exe = JSExecutable(shapes_graph, rule_node) - def apply(self, data_graph: 'GraphLike') -> int: + def apply(self, data_graph: rdflib.Graph) -> int: focus_nodes = self.shape.focus_nodes(data_graph) # uses target nodes to find focus nodes all_added = 0 iterate_limit = 100 diff --git a/pyshacl/extras/js/target.py b/pyshacl/extras/js/target.py index eaf04d9..b2c8202 100644 --- a/pyshacl/extras/js/target.py +++ b/pyshacl/extras/js/target.py @@ -4,6 +4,7 @@ from typing import Dict, List from warnings import warn +import rdflib from rdflib import URIRef from pyshacl.consts import SH_JSTargetType @@ -13,7 +14,7 @@ from .js_executable import JSExecutable if typing.TYPE_CHECKING: - from pyshacl.pytypes import GraphLike, SHACLExecutor + from pyshacl.pytypes import SHACLExecutor from pyshacl.shape import Shape from pyshacl.shapes_graph import ShapesGraph @@ -47,7 +48,7 @@ def shacl_constraint_class(cls): return SH_JSTargetType def evaluate( - self, executor: 'SHACLExecutor', target_graph: 'GraphLike', focus_value_nodes: Dict, _evaluation_path: List + self, executor: 'SHACLExecutor', target_graph: rdflib.Graph, focus_value_nodes: Dict, _evaluation_path: List ): """ :type executor: SHACLExecutor diff --git a/pyshacl/functions/__init__.py b/pyshacl/functions/__init__.py index f0be125..9a4350e 100644 --- a/pyshacl/functions/__init__.py +++ b/pyshacl/functions/__init__.py @@ -3,6 +3,8 @@ import sys from typing import TYPE_CHECKING, Dict, Sequence, Union +import rdflib + from pyshacl.consts import ( RDF_type, SH_ask, @@ -13,7 +15,7 @@ SH_SHACLFunction, SH_SPARQLFunction, ) -from pyshacl.pytypes import GraphLike, RDFNode, SHACLExecutor +from pyshacl.pytypes import RDFNode, SHACLExecutor if TYPE_CHECKING: from pyshacl.extras.js.function import JSFunction # noqa F401 @@ -99,11 +101,11 @@ def gather_functions( return list(all_fns.values()) -def apply_functions(executor: SHACLExecutor, fns: Sequence, data_graph: GraphLike): +def apply_functions(executor: SHACLExecutor, fns: Sequence, data_graph: rdflib.Graph): for f in fns: f.apply(data_graph) -def unapply_functions(fns: Sequence, data_graph: GraphLike): +def unapply_functions(fns: Sequence, data_graph: rdflib.Graph): for f in fns: f.unapply(data_graph) diff --git a/pyshacl/functions/shacl_function.py b/pyshacl/functions/shacl_function.py index 9702fe8..b0e63b0 100644 --- a/pyshacl/functions/shacl_function.py +++ b/pyshacl/functions/shacl_function.py @@ -3,6 +3,7 @@ import typing from typing import Dict, List +import rdflib from rdflib import XSD, Literal from rdflib.plugins.sparql.operators import register_custom_function, unregister_custom_function from rdflib.plugins.sparql.sparql import SPARQLError @@ -13,7 +14,6 @@ from ..parameter import SHACLParameter if typing.TYPE_CHECKING: - from ..pytypes import GraphLike from ..shapes_graph import ShapesGraph @@ -145,7 +145,7 @@ def execute(self, g, *args): else: return self.execute_select(g, init_bindings) - def execute_select(self, g: 'GraphLike', init_bindings: Dict): + def execute_select(self, g: rdflib.Graph, init_bindings: Dict): s = self._qh.apply_prefixes(self.select) results = g.query(s, initBindings=init_bindings) if results.type != "SELECT" or results.vars is None: @@ -158,7 +158,7 @@ def execute_select(self, g: 'GraphLike', init_bindings: Dict): result = results.bindings[0] return result[rvar] - def execute_ask(self, g: 'GraphLike', init_bindings: Dict): + def execute_ask(self, g: rdflib.Graph, init_bindings: Dict): a = self._qh.apply_prefixes(self.ask) results = g.query(a, initBindings=init_bindings) if results.type != "ASK": diff --git a/pyshacl/helper/expression_helper.py b/pyshacl/helper/expression_helper.py index e9c54b8..169c138 100644 --- a/pyshacl/helper/expression_helper.py +++ b/pyshacl/helper/expression_helper.py @@ -24,7 +24,7 @@ from pyshacl.errors import ReportableRuntimeError, ShapeLoadError if TYPE_CHECKING: - from pyshacl.pytypes import GraphLike, RDFNode + from pyshacl.pytypes import RDFNode from pyshacl.shapes_graph import ShapesGraph @@ -141,7 +141,7 @@ def value_nodes_from_path(sg, focus, path_val, target_graph, recursion=0): def nodes_from_node_expression( - expr, focus_node, data_graph: 'GraphLike', sg: 'ShapesGraph', recurse_depth=0 + expr, focus_node, data_graph: rdflib.Graph, sg: 'ShapesGraph', recurse_depth=0 ) -> Union[Set[Union['RDFNode', None]], List[Union['RDFNode', None]]]: # https://www.w3.org/TR/shacl-af/#node-expressions if expr == SH_this: diff --git a/pyshacl/pytypes.py b/pyshacl/pytypes.py index 2e079dc..8ee838b 100644 --- a/pyshacl/pytypes.py +++ b/pyshacl/pytypes.py @@ -4,11 +4,9 @@ from dataclasses import dataclass from typing import Optional, Union -from rdflib import ConjunctiveGraph, Dataset, Graph, Literal +from rdflib import Literal from rdflib.term import IdentifiedNode, Node -ConjunctiveLike = Union[ConjunctiveGraph, Dataset] -GraphLike = Union[ConjunctiveLike, Graph] RDFNode = Union[IdentifiedNode, Literal] BaseNode = Node diff --git a/pyshacl/rdfutil/clone.py b/pyshacl/rdfutil/clone.py index 8334133..bd78f81 100644 --- a/pyshacl/rdfutil/clone.py +++ b/pyshacl/rdfutil/clone.py @@ -3,19 +3,19 @@ from typing import Optional, Union import rdflib +from rdflib import ConjunctiveGraph from rdflib.collection import Collection from rdflib.graph import DATASET_DEFAULT_GRAPH_ID from rdflib.namespace import NamespaceManager from .consts import OWL, RDF_first -from .pytypes import ConjunctiveLike, GraphLike OWLsameAs = OWL.sameAs -def clone_dataset(source_ds: ConjunctiveLike, target_ds=None): +def clone_dataset(source_ds: ConjunctiveGraph, target_ds=None): if target_ds and not isinstance(target_ds, (rdflib.Dataset, rdflib.ConjunctiveGraph)): - raise RuntimeError("when cloning a dataset, the target_ds must be a conjunctiveGraph or rdflib Dataset.") + raise RuntimeError("when cloning a dataset, the target_ds must be a ConjunctiveGraph or rdflib Dataset.") default_union = source_ds.default_union if target_ds is None: target_ds = rdflib.Dataset(default_union=default_union) @@ -100,7 +100,7 @@ def clone_graph(source_graph, target_graph=None, identifier=None): def mix_datasets( - base_ds: ConjunctiveLike, extra_ds: GraphLike, target_ds: Optional[Union[ConjunctiveLike, str]] = None + base_ds: ConjunctiveGraph, extra_ds: rdflib.Graph, target_ds: Optional[Union[ConjunctiveGraph, str]] = None ): """ Make a clone of base_ds (dataset) and add in the triples from extra_ds (dataset) @@ -205,7 +205,9 @@ def mix_datasets( return target_ds -def mix_graphs(base_graph: GraphLike, extra_graph: GraphLike, target_graph: Optional[Union[GraphLike, str]] = None): +def mix_graphs( + base_graph: rdflib.Graph, extra_graph: rdflib.Graph, target_graph: Optional[Union[rdflib.Graph, str]] = None +): """ Make a clone of base_graph and add in the triples from extra_graph :param base_graph: diff --git a/pyshacl/rdfutil/consts.py b/pyshacl/rdfutil/consts.py index ef3f8a2..837c34c 100644 --- a/pyshacl/rdfutil/consts.py +++ b/pyshacl/rdfutil/consts.py @@ -1,8 +1,6 @@ # -*- coding: utf-8 -*- # -from typing import Union - -from rdflib import RDF, RDFS, ConjunctiveGraph, Dataset, Graph, Namespace +from rdflib import RDF, RDFS, Namespace from rdflib.namespace import OWL from rdflib.term import Node @@ -10,8 +8,6 @@ RDF_first = RDF.first SH = Namespace('http://www.w3.org/ns/shacl#') -ConjunctiveLike = Union[ConjunctiveGraph, Dataset] -GraphLike = Union[ConjunctiveLike, Graph] RDFNode = Node OWL_properties = [ diff --git a/pyshacl/rdfutil/inoculate.py b/pyshacl/rdfutil/inoculate.py index 61bbf85..08bda3d 100644 --- a/pyshacl/rdfutil/inoculate.py +++ b/pyshacl/rdfutil/inoculate.py @@ -2,11 +2,12 @@ from typing import TYPE_CHECKING, Dict, Optional, Union import rdflib +from rdflib import ConjunctiveGraph from rdflib.graph import DATASET_DEFAULT_GRAPH_ID from rdflib.namespace import NamespaceManager from .clone import clone_blank_node, clone_graph, clone_node -from .consts import OWL, RDF, ConjunctiveLike, GraphLike, OWL_classes, OWL_properties, RDFS_classes, RDFS_properties +from .consts import OWL, RDF, OWL_classes, OWL_properties, RDFS_classes, RDFS_properties if TYPE_CHECKING: from rdflib import BNode @@ -108,7 +109,7 @@ def inoculate(data_graph: rdflib.Graph, ontology: rdflib.Graph): def inoculate_dataset( - base_ds: ConjunctiveLike, ontology_ds: GraphLike, target_ds: Optional[Union[ConjunctiveLike, str]] = None + base_ds: ConjunctiveGraph, ontology_ds: rdflib.Graph, target_ds: Optional[Union[ConjunctiveGraph, str]] = None ): """ Make a clone of base_ds (dataset) and add RDFS and OWL triples from ontology_ds diff --git a/pyshacl/rdfutil/load.py b/pyshacl/rdfutil/load.py index 63bf07d..8220c81 100644 --- a/pyshacl/rdfutil/load.py +++ b/pyshacl/rdfutil/load.py @@ -17,9 +17,6 @@ from .clone import clone_dataset, clone_graph -ConjunctiveLike = Union[rdflib.ConjunctiveGraph, rdflib.Dataset] -GraphLike = Union[ConjunctiveLike, rdflib.Graph] - is_windows = platform.system() == "Windows" MAX_OWL_IMPORT_DEPTH = 3 baked_in = {} @@ -113,8 +110,8 @@ def get_rdf_from_web(url: Union[rdflib.URIRef, str]): def load_from_source( - source: Union[GraphLike, BufferedIOBase, TextIOBase, BinaryIO, str, bytes], - g: Optional[GraphLike] = None, + source: Union[rdflib.Graph, BufferedIOBase, TextIOBase, BinaryIO, str, bytes], + g: Optional[rdflib.Graph] = None, rdf_format: Optional[str] = None, multigraph: bool = False, do_owl_imports: Union[bool, int] = False, diff --git a/pyshacl/rdfutil/pytypes.py b/pyshacl/rdfutil/pytypes.py deleted file mode 100644 index 9106ffc..0000000 --- a/pyshacl/rdfutil/pytypes.py +++ /dev/null @@ -1,8 +0,0 @@ -# -*- coding: utf-8 -*- -# -from typing import Union - -from rdflib import ConjunctiveGraph, Dataset, Graph - -ConjunctiveLike = Union[ConjunctiveGraph, Dataset] -GraphLike = Union[ConjunctiveLike, Graph] diff --git a/pyshacl/rules/__init__.py b/pyshacl/rules/__init__.py index f25fd3e..b546e93 100644 --- a/pyshacl/rules/__init__.py +++ b/pyshacl/rules/__init__.py @@ -2,9 +2,11 @@ from collections import defaultdict from typing import TYPE_CHECKING, Any, Dict, List, Tuple, Type, Union +import rdflib + from pyshacl.consts import RDF_type, SH_rule, SH_SPARQLRule, SH_TripleRule from pyshacl.errors import ReportableRuntimeError, RuleLoadError -from pyshacl.pytypes import GraphLike, SHACLExecutor +from pyshacl.pytypes import SHACLExecutor from pyshacl.rules.sparql import SPARQLRule from pyshacl.rules.triple import TripleRule @@ -77,7 +79,7 @@ def gather_rules(executor: SHACLExecutor, shacl_graph: 'ShapesGraph') -> Dict['S return ret_rules -def apply_rules(executor: SHACLExecutor, shapes_rules: Dict, data_graph: GraphLike) -> int: +def apply_rules(executor: SHACLExecutor, shapes_rules: Dict, data_graph: rdflib.Graph) -> int: # short the shapes dict by shapes sh:order before execution sorted_shapes_rules: List[Tuple[Any, Any]] = sorted(shapes_rules.items(), key=lambda x: x[0].order) total_modified = 0 diff --git a/pyshacl/rules/sparql/__init__.py b/pyshacl/rules/sparql/__init__.py index 0d9f23c..10478cd 100644 --- a/pyshacl/rules/sparql/__init__.py +++ b/pyshacl/rules/sparql/__init__.py @@ -13,7 +13,7 @@ from ..shacl_rule import SHACLRule if TYPE_CHECKING: - from pyshacl.pytypes import GraphLike, SHACLExecutor + from pyshacl.pytypes import SHACLExecutor from pyshacl.shape import Shape XSD_string = XSD.string @@ -49,7 +49,7 @@ def __init__(self, executor: 'SHACLExecutor', shape: 'Shape', rule_node: 'rdflib query_helper.collect_prefixes() self._qh = query_helper - def apply(self, data_graph: 'GraphLike') -> int: + def apply(self, data_graph: rdflib.Graph) -> int: focus_nodes = self.shape.focus_nodes(data_graph) # uses target nodes to find focus nodes all_added = 0 SPARQLQueryHelper = get_query_helper_cls() diff --git a/pyshacl/rules/triple/__init__.py b/pyshacl/rules/triple/__init__.py index 88979e8..d45254e 100644 --- a/pyshacl/rules/triple/__init__.py +++ b/pyshacl/rules/triple/__init__.py @@ -12,7 +12,7 @@ if TYPE_CHECKING: from rdflib.term import Node - from pyshacl.pytypes import GraphLike, SHACLExecutor + from pyshacl.pytypes import SHACLExecutor from pyshacl.shape import Shape @@ -50,7 +50,7 @@ def __init__(self, executor: 'SHACLExecutor', shape: 'Shape', rule_node: 'rdflib raise RuntimeError("Too many sh:object") self.o = next(iter(my_object_nodes)) - def apply(self, data_graph: 'GraphLike') -> int: + def apply(self, data_graph: rdflib.Graph) -> int: focus_nodes = self.shape.focus_nodes(data_graph) # uses target nodes to find focus nodes applicable_nodes = self.filter_conditions(focus_nodes, data_graph) all_added = 0 diff --git a/pyshacl/shape.py b/pyshacl/shape.py index edbd9ba..3a61e04 100644 --- a/pyshacl/shape.py +++ b/pyshacl/shape.py @@ -6,6 +6,7 @@ from time import perf_counter from typing import TYPE_CHECKING, List, Optional, Set, Tuple, Type, Union +import rdflib from rdflib import BNode, Literal, URIRef from .consts import ( @@ -38,7 +39,7 @@ from .errors import ConstraintLoadError, ConstraintLoadWarning, ReportableRuntimeError, ShapeLoadError from .helper import get_query_helper_cls from .helper.expression_helper import value_nodes_from_path -from .pytypes import GraphLike, SHACLExecutor +from .pytypes import SHACLExecutor if TYPE_CHECKING: from pyshacl.constraints import ConstraintComponent @@ -423,7 +424,7 @@ def find_custom_constraints(self): def validate( self, executor: SHACLExecutor, - target_graph: GraphLike, + target_graph: rdflib.Graph, focus: Optional[ Union[ Tuple[Union[URIRef, BNode]], diff --git a/pyshacl/target.py b/pyshacl/target.py index 2df6c36..6387971 100644 --- a/pyshacl/target.py +++ b/pyshacl/target.py @@ -2,12 +2,14 @@ from typing import List, Sequence, Type, Union from warnings import warn +import rdflib + from .constraints import ConstraintComponent from .consts import SH, RDF_type, RDFS_subClassOf, SH_parameter, SH_select, SH_SPARQLTargetType from .errors import ConstraintLoadError, ShapeLoadError from .helper import get_query_helper_cls from .parameter import SHACLParameter -from .pytypes import GraphLike, SHACLExecutor +from .pytypes import SHACLExecutor if typing.TYPE_CHECKING: from .shapes_graph import ShapesGraph @@ -117,7 +119,11 @@ def shacl_constraint_class(cls): return SH_SPARQLTargetType def evaluate( - self, executor: SHACLExecutor, target_graph: GraphLike, focus_value_nodes: typing.Dict, _evaluation_path: List + self, + executor: SHACLExecutor, + target_graph: rdflib.Graph, + focus_value_nodes: typing.Dict, + _evaluation_path: List, ): """ :type executor: SHACLExecutor diff --git a/pyshacl/validate.py b/pyshacl/validate.py index 482dd7d..673d548 100644 --- a/pyshacl/validate.py +++ b/pyshacl/validate.py @@ -29,7 +29,7 @@ from .extras import check_extra_installed from .functions import apply_functions, gather_functions, unapply_functions from .monkey import apply_patches, rdflib_bool_patch, rdflib_bool_unpatch -from .pytypes import GraphLike, SHACLExecutor +from .pytypes import SHACLExecutor from .rdfutil import ( add_baked_in, clone_blank_node, @@ -81,7 +81,7 @@ def _load_default_options(cls, options_dict: dict): @classmethod def _run_pre_inference( - cls, target_graph: GraphLike, inference_option: str, logger: Optional[logging.Logger] = None + cls, target_graph: rdflib.Graph, inference_option: str, logger: Optional[logging.Logger] = None ): """ Note, this is the OWL/RDFS pre-inference, @@ -148,7 +148,7 @@ def create_validation_report(cls, sg, conforms: bool, results: List[Tuple]): vr = BNode() vg.add((vr, RDF_type, SH_ValidationReport)) vg.add((vr, SH_conforms, Literal(conforms))) - cloned_nodes: Dict[Tuple[GraphLike, str], Union[BNode, URIRef]] = {} + cloned_nodes: Dict[Tuple[rdflib.Graph, str], Union[BNode, URIRef]] = {} for result in iter(results): _d, _bn, _tr = result v_text += _d @@ -173,10 +173,10 @@ def create_validation_report(cls, sg, conforms: bool, results: List[Tuple]): def __init__( self, - data_graph: GraphLike, + data_graph: rdflib.Graph, *args, - shacl_graph: Optional[GraphLike] = None, - ont_graph: Optional[GraphLike] = None, + shacl_graph: Optional[rdflib.Graph] = None, + ont_graph: Optional[rdflib.Graph] = None, options: Optional[dict] = None, **kwargs, ): @@ -189,9 +189,9 @@ def __init__( self.inplace = options['inplace'] if not isinstance(data_graph, rdflib.Graph): raise RuntimeError("data_graph must be a rdflib Graph object") - self.data_graph = data_graph # type: GraphLike + self.data_graph = data_graph self._target_graph = None - self.ont_graph = ont_graph # type: Optional[GraphLike] + self.ont_graph = ont_graph self.data_graph_is_multigraph = isinstance(self.data_graph, (rdflib.Dataset, rdflib.ConjunctiveGraph)) if self.ont_graph is not None and isinstance(self.ont_graph, (rdflib.Dataset, rdflib.ConjunctiveGraph)): self.ont_graph.default_union = True @@ -378,7 +378,7 @@ def wrapped(*args, **kwargs): @with_metashacl_shacl_graph_cache -def meta_validate(shacl_graph: Union[GraphLike, str], inference: Optional[str] = 'rdfs', **kwargs): +def meta_validate(shacl_graph: Union[rdflib.Graph, str], inference: Optional[str] = 'rdfs', **kwargs): shacl_shacl_graph = meta_validate.graph_cache shacl_graph = load_from_source(shacl_graph, rdf_format=kwargs.pop('shacl_graph_format', None), multigraph=True) _ = kwargs.pop('meta_shacl', None) @@ -386,10 +386,10 @@ def meta_validate(shacl_graph: Union[GraphLike, str], inference: Optional[str] = def validate( - data_graph: Union[GraphLike, BufferedIOBase, TextIOBase, str, bytes], + data_graph: Union[rdflib.Graph, BufferedIOBase, TextIOBase, str, bytes], *args, - shacl_graph: Optional[Union[GraphLike, BufferedIOBase, TextIOBase, str, bytes]] = None, - ont_graph: Optional[Union[GraphLike, BufferedIOBase, TextIOBase, str, bytes]] = None, + shacl_graph: Optional[Union[rdflib.Graph, BufferedIOBase, TextIOBase, str, bytes]] = None, + ont_graph: Optional[Union[rdflib.Graph, BufferedIOBase, TextIOBase, str, bytes]] = None, advanced: Optional[bool] = False, inference: Optional[str] = None, inplace: Optional[bool] = False, @@ -578,7 +578,7 @@ def clean_validation_reports(actual_graph, actual_report, expected_graph, expect return True -def compare_validation_reports(report_graph: GraphLike, expected_graph: GraphLike, expected_result): +def compare_validation_reports(report_graph: rdflib.Graph, expected_graph: rdflib.Graph, expected_result): expected_conforms_i = expected_graph.objects(expected_result, SH_conforms) expected_conforms = set(cast(Iterator[Literal], expected_conforms_i)) if len(expected_conforms) < 1: # pragma: no cover @@ -627,7 +627,9 @@ def compare_validation_reports(report_graph: GraphLike, expected_graph: GraphLik return True -def compare_inferencing_reports(data_graph: GraphLike, expected_graph: GraphLike, expected_results: Union[List, Set]): +def compare_inferencing_reports( + data_graph: rdflib.Graph, expected_graph: rdflib.Graph, expected_results: Union[List, Set] +): all_good = True for expected_result in expected_results: expected_objects = set(expected_graph.objects(expected_result, RDF_object)) @@ -697,7 +699,7 @@ def compare_inferencing_reports(data_graph: GraphLike, expected_graph: GraphLike return all_good -def check_dash_result(validator: Validator, report_graph: GraphLike, expected_result_graph: GraphLike): +def check_dash_result(validator: Validator, report_graph: rdflib.Graph, expected_result_graph: rdflib.Graph): DASH = rdflib.namespace.Namespace('http://datashapes.org/dash#') DASH_GraphValidationTestCase = DASH.GraphValidationTestCase DASH_InferencingTestCase = DASH.InferencingTestCase @@ -804,7 +806,7 @@ def check_dash_result(validator: Validator, report_graph: GraphLike, expected_re return (gv_res or gv_res is None) and (inf_res or inf_res is None) and (fn_res or fn_res is None) -def check_sht_result(report_graph: GraphLike, sht_graph: GraphLike, sht_result_node: Union[URIRef, BNode]): +def check_sht_result(report_graph: rdflib.Graph, sht_graph: rdflib.Graph, sht_result_node: Union[URIRef, BNode]): SHT = rdflib.namespace.Namespace('http://www.w3.org/ns/shacl-test#') types = set(sht_graph.objects(sht_result_node, RDF_type)) expected_failure = sht_result_node == SHT.Failure