Skip to content

Commit

Permalink
Merge pull request #50 from piyush69/master
Browse files Browse the repository at this point in the history
Add support to use SELECT query variables in sh:message
  • Loading branch information
ashleysommer authored May 26, 2021
2 parents 4166ee1 + a43e2af commit c8c65bb
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 4 deletions.
35 changes: 32 additions & 3 deletions pyshacl/constraints/constraint_component.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
https://www.w3.org/TR/shacl/#core-components-value-type
"""
import abc
import re
import typing

from typing import TYPE_CHECKING, Any, Dict, Iterable, List, Optional, Set, Tuple
Expand Down Expand Up @@ -117,8 +118,8 @@ def make_v_result_description(
constraint_component=None,
source_constraint=None,
extra_messages: Optional[Iterable] = None,
bound_vars=None,
):

"""
:param datagraph:
:type datagraph: rdflib.Graph | rdflib.ConjunctiveGraph | rdflib.Dataset
Expand All @@ -131,6 +132,7 @@ def make_v_result_description(
:param messages:
:type messages: List[str]
:param result_path:
:param bound_vars:
:param constraint_component:
:param source_constraint:
:param extra_messages:
Expand Down Expand Up @@ -171,12 +173,18 @@ def make_v_result_description(
if m in messages:
continue
if isinstance(m, Literal):
desc += "\tMessage: {}\n".format(str(m.value))
msg = str(m.value)
if bound_vars is not None:
msg = self._format_sparql_based_result_message(msg, bound_vars)
desc += "\tMessage: {}\n".format(msg)
else: # pragma: no cover
desc += "\tMessage: {}\n".format(str(m))
for m in messages:
if isinstance(m, Literal):
desc += "\tMessage: {}\n".format(str(m.value))
msg = str(m.value)
if bound_vars is not None:
msg = self._format_sparql_based_result_message(msg, bound_vars)
desc += "\tMessage: {}\n".format(msg)
else: # pragma: no cover
desc += "\tMessage: {}\n".format(str(m))
return desc
Expand All @@ -190,6 +198,7 @@ def make_v_result(
constraint_component=None,
source_constraint=None,
extra_messages: Optional[Iterable] = None,
bound_vars=None,
):
"""
:param datagraph:
Expand All @@ -199,6 +208,7 @@ def make_v_result(
:param value_node:
:type value_node: rdflib.term.Identifier | None
:param result_path:
:param bound_vars:
:param constraint_component:
:param source_constraint:
:param extra_messages:
Expand Down Expand Up @@ -228,10 +238,20 @@ def make_v_result(
for m in iter(extra_messages):
if m in messages:
continue
if isinstance(m, Literal):
msg = str(m.value)
if bound_vars is not None:
msg = self._format_sparql_based_result_message(msg, bound_vars)
m = Literal(msg)
r_triples.append((r_node, SH_resultMessage, m))
elif not messages:
messages = self.make_generic_messages(datagraph, focus_node, value_node) or messages
for m in messages:
if isinstance(m, Literal):
msg = str(m.value)
if bound_vars is not None:
msg = self._format_sparql_based_result_message(msg, bound_vars)
m = Literal(msg)
r_triples.append((r_node, SH_resultMessage, m))
desc = self.make_v_result_description(
datagraph,
Expand All @@ -243,10 +263,19 @@ def make_v_result(
constraint_component=constraint_component,
source_constraint=source_constraint,
extra_messages=extra_messages,
bound_vars=bound_vars,
)
self.shape.logger.debug(desc)
return desc, r_node, r_triples

def _format_sparql_based_result_message(self, msg, bound_vars):
if bound_vars is None:
return msg
msg = re.sub('{[?$]this}', str(bound_vars[0]), msg)
msg = re.sub('{[?$]path}', str(bound_vars[1]), msg)
msg = re.sub('{[?$]value}', str(bound_vars[2]), msg)
return msg


SH_nodeValidator = SH.term('nodeValidator')
SH_propertyValidator = SH.term('propertyValidator')
Expand Down
4 changes: 3 additions & 1 deletion pyshacl/constraints/sparql/sparql_based_constraints.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,9 @@ def _evaluate_sparql_constraint(self, sparql_constraint, target_graph, f_v_dict)
t, p, v = v
if v is None:
v = result_val
rept = self.make_v_result(target_graph, t or f, value_node=v, result_path=p, **rept_kwargs)
rept = self.make_v_result(
target_graph, t or f, value_node=v, result_path=p, bound_vars=(t, p, v), **rept_kwargs
)
else:
rept = self.make_v_result(target_graph, f, value_node=v, **rept_kwargs)
reports.append(rept)
Expand Down

0 comments on commit c8c65bb

Please sign in to comment.