Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions pyshacl/rules/sparql/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,13 @@ def apply(
focus_nodes: Optional[Sequence['RDFNode']] = None,
target_graph_identifier: Optional['URIRef'] = None,
) -> int:
if isinstance(data_graph, (rdflib.Dataset, rdflib.ConjunctiveGraph)):
if target_graph_identifier is not None:
target_graph = data_graph.get_context(target_graph_identifier)
else:
target_graph = data_graph.default_context
else:
target_graph = data_graph
focus_list: Sequence['RDFNode']
if focus_nodes is not None:
focus_list = list(focus_nodes)
Expand Down Expand Up @@ -100,21 +107,14 @@ def apply(
if result_graph is None:
raise ReportableRuntimeError("Query executed by a SHACL SPARQLRule did not return a Graph.")
for i in result_graph:
if not this_added and i not in data_graph:
if not this_added and i not in target_graph:
this_added = True
# We only need to know at least one triple was added, then break!
break
if this_added:
added += 1
construct_graphs.add(result_graph)
if added > 0:
if isinstance(data_graph, (rdflib.Dataset, rdflib.ConjunctiveGraph)):
if target_graph_identifier is not None:
target_graph = data_graph.get_context(target_graph_identifier)
else:
target_graph = data_graph.default_context
else:
target_graph = data_graph
for g in construct_graphs:
data_graph = clone_graph(g, target_graph=target_graph)
all_added += added
Expand Down
71 changes: 71 additions & 0 deletions test/test_sparql_rule.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
"""\
A test which checks that SPARQLRule's generate triples in the default graph of a datasets, even if these triples are
already present in a different graph of that dataset.
"""

from pyshacl import validate
from rdflib import Graph, Dataset, RDFS, URIRef, Literal

shacl_file = '''\
# prefix: ex

@prefix ex: <http://datashapes.org/shasf/tests/expression/sparql-rule.test.shacl#> .
@prefix exOnt: <http://datashapes.org/shasf/tests/expression/sparql-rule.test.ont#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix sh: <http://www.w3.org/ns/shacl#> .

<http://datashapes.org/shasf/tests/expression/sparql-rule.test.shacl>
a owl:Ontology ;
rdfs:label "Test of SPARQLRule in conjunction with datasets" ;
.

ex:rule a sh:SPARQLRule ;
sh:construct """
CONSTRUCT {
$this rdfs:label ?label .
}
WHERE {
$this exOnt:firstName ?firstName .
$this exOnt:lastName ?lastName .
BIND(CONCAT(?firstName, " ", ?lastName) AS ?label)
}
""" ;
.

ex:PersonExpressionShape
a sh:NodeShape ;
sh:targetClass exOnt:Person ;
sh:rule ex:rule ;
.
'''

data_graph = '''
# prefix: ex

@prefix ex: <http://datashapes.org/shasf/tests/expression/sparql-rule.test.data#> .
@prefix exOnt: <http://datashapes.org/shasf/tests/expression/sparql-rule.test.ont#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .

ex:Kate
a exOnt:Person ;
rdfs:label "Kate Jones" ;
exOnt:firstName "Kate" ;
exOnt:lastName "Jones" ;
.
'''

def test_sparql_rule():
dataset = Dataset()
dataset.graph().parse(data=data_graph, format="turtle")
s = Graph().parse(data=shacl_file, format="turtle")
validate(dataset, shacl_graph=s, advanced=True, debug=False, inplace=True)
assert (
URIRef("http://datashapes.org/shasf/tests/expression/sparql-rule.test.data#Kate"),
RDFS.label,
Literal("Kate Jones"),
) in dataset.default_context


if __name__ == "__main__":
exit(test_sparql_rule())