Skip to content

Commit f1c0cfd

Browse files
committed
fix(shacl): 🐛 build property shape subgraph by reachability
Rebuild `ShapesList.get_shape_property_graph` to include only triples reachable from the target property shape (constraints and RDF lists used by sh:and/sh:or/sh:xone) plus the `sh:property` link triple, instead of subtracting sibling properties from the node-shape graph. The previous subtractive approach could leak shared blank nodes and risked breaking sibling constructs in the merged shapes graph.
1 parent f3a7e6d commit f1c0cfd

1 file changed

Lines changed: 11 additions & 8 deletions

File tree

  • rocrate_validator/requirements/shacl

rocrate_validator/requirements/shacl/utils.py

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -190,20 +190,23 @@ def get_shape_graph(self, shape_node: Node) -> Graph:
190190

191191
def get_shape_property_graph(self, shape_node: Node, shape_property: Node) -> Graph:
192192
"""
193-
Get the subgraph of the given shape node excluding the given property
193+
Get the subgraph of a property shape nested inside a node shape.
194+
195+
Includes only triples reachable from `shape_property` (its constraints
196+
and any RDF lists used by `sh:and`/`sh:or`/`sh:xone`), plus the link
197+
triple `(shape_node, sh:property, shape_property)`. Nothing reachable
198+
only via sibling properties is included, so subtracting this graph
199+
from the merged shapes graph cannot break sibling constructs.
194200
"""
195201
node_graph = self.get_shape_graph(shape_node)
196202
assert node_graph is not None, "The shape graph cannot be None"
197203

198204
property_graph = Graph()
199-
shacl_ns = Namespace(SHACL_NS)
200-
nested_properties_to_exclude = [o for (_, _, o) in node_graph.triples(
201-
(shape_node, shacl_ns.property, None)) if o != shape_property]
202-
triples_to_exclude = [(s, _, o) for (s, _, o) in node_graph.triples((None, None, None))
203-
if s in nested_properties_to_exclude
204-
or o in nested_properties_to_exclude]
205+
for s, p, o in __extract_related_triples__(node_graph, shape_property):
206+
property_graph.add((s, p, o))
205207

206-
property_graph += node_graph - triples_to_exclude
208+
shacl_ns = Namespace(SHACL_NS)
209+
property_graph.add((shape_node, shacl_ns.property, shape_property))
207210

208211
return property_graph
209212

0 commit comments

Comments
 (0)