Skip to content

Commit

Permalink
Type StringBasedConstraintBase
Browse files Browse the repository at this point in the history
Note: Extra type assertions are entered because broader type in
`StringBasedConstraintBase` can't be narrowed in child classes.

Signed-off-by: Alex Nelson <[email protected]>
  • Loading branch information
ajnelson-nist committed Oct 4, 2024
1 parent 162827a commit 48bfbcd
Showing 1 changed file with 24 additions and 12 deletions.
36 changes: 24 additions & 12 deletions pyshacl/constraints/core/string_based_constraints.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"""
https://www.w3.org/TR/shacl/#core-components-string
"""
import logging
import re
from typing import Dict, List

Expand All @@ -11,7 +12,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 GraphLike, RDFNode, SHACLExecutor
from pyshacl.rdfutil import stringify_node
from pyshacl.shape import Shape

Expand All @@ -38,9 +39,9 @@ class StringBasedConstraintBase(ConstraintComponent):

shacl_constraint_component = rdflib.URIRef("urn:notimplemented")

def __init__(self, shape):
def __init__(self, shape: Shape) -> None:
super(StringBasedConstraintBase, self).__init__(shape)
self.string_rules = []
self.string_rules: List[RDFNode] = []
self.allow_multi_rules = True

@classmethod
Expand Down Expand Up @@ -260,18 +261,19 @@ class PatternConstraintComponent(StringBasedConstraintBase):

def __init__(self, shape: Shape) -> None:
super(PatternConstraintComponent, self).__init__(shape)
patterns_found = list(self.shape.objects(SH_pattern))
patterns_found: List[RDFNode] = []
for pattern_found in self.shape.objects(SH_pattern):
if not isinstance(pattern_found, rdflib.Literal):
raise ConstraintLoadError(
"PatternConstraintComponent sh:pattern must be a RDF Literal node.",
"https://www.w3.org/TR/shacl/#PatternConstraintComponent",
)
patterns_found.append(pattern_found)
if len(patterns_found) < 1:
raise ConstraintLoadError(
"PatternConstraintComponent must have at least one sh:pattern predicate.",
"https://www.w3.org/TR/shacl/#PatternConstraintComponent",
)
for p in patterns_found:
if not isinstance(p, rdflib.Literal):
raise ConstraintLoadError(
"PatternConstraintComponent sh:pattern must be a RDF Literal node.",
"https://www.w3.org/TR/shacl/#PatternConstraintComponent",
)
self.string_rules = patterns_found
flags_found = set(self.shape.objects(SH_flags))
if len(flags_found) > 0:
Expand All @@ -290,9 +292,19 @@ def constraint_name(cls):

def make_generic_messages(self, datagraph: GraphLike, 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))
string_rule = self.string_rules[0]
assert isinstance(string_rule, rdflib.Literal)
m = "Value does not match pattern '{}'".format(str(string_rule.value))
else:
rules = "', '".join(str(c.value) for c in self.string_rules)
# Inform type system that all the string rules are Literals.
_string_rules: List[rdflib.Literal] = []
for string_rule in self.string_rules:
if not isinstance(string_rule, rdflib.Literal):
logging.debug("string_rule = %r.", string_rule)
logging.debug("type(string_rule) = %r.", type(string_rule))
raise TypeError("Non-Literal entered string_rules list.")
_string_rules.append(string_rule)
rules = "', '".join(str(c.value) for c in _string_rules)
m = "Value does not match every pattern in ('{}')".format(rules)
return [rdflib.Literal(m)]

Expand Down

0 comments on commit 48bfbcd

Please sign in to comment.