Handle validation results in code¶
Use validate_algebra() to handle failures as Python objects. For a W3C
report graph, use validate() as shown in Validating a model.
Read individual failures¶
Using the shapes and failing data from the validation tutorial:
from pathlib import Path
import shifty
example_dir = Path(__file__).parent / "quick-start"
result = shifty.validate_algebra(
example_dir / "data.ttl",
example_dir / "shapes.ttl",
)
print("conforms:", result.conforms)
print("violations:", len(result.violations))
for violation in result.violations:
print(violation.focus_node, violation.severity)
for reason in violation.reasons:
print(" ", reason.constraint_kind, reason.path, reason.value)
print(" ", reason.message)
conforms: False
violations: 1
<http://example.org/bob> Violation
ConstraintKind.Cardinality ex:email <http://example.org/bob>
at least 1 value(s) required along ex:email, found 0
ConstraintKind.ValueType ex:name "123"^^<http://www.w3.org/2001/XMLSchema#integer>
test(datatype(xsd:string)) not satisfied
A violation is one failing focus node under one statement. Its reasons describe the individual failures. Bob has one violation with two reasons.
Branch on reason.constraint_kind when handling a failure in code.
reason.message is display text and may change:
import shifty
result = shifty.validate_algebra("data.ttl", "shapes.ttl")
for violation in result.violations:
for reason in violation.reasons:
if reason.constraint_kind == shifty.ConstraintKind.Cardinality:
print("missing or excess values:", reason.path)
elif reason.constraint_kind == shifty.ConstraintKind.ValueType:
print("wrong type:", reason.value, "at", reason.path)
reason.value identifies an offending value when available; for a missing
value, it falls back to the focus node. Prefer
reason.author_message or reason.message to display an authored
sh:message when present.
Apply a severity threshold¶
To retain warnings in the results while only violations make the graph fail:
result = shifty.validate_algebra(
"data.ttl", "shapes.ttl", minimum_severity="violation"
)
print(result.conforms)
for violation in result.violations:
for reason in violation.reasons:
print(reason.severity, reason.message)
conforms applies the threshold. violations still includes findings
below it. Severity belongs to each reason; violation.severity is the most
severe reason for that focus node and statement.
Inspect the compiled constraint¶
Each reason identifies the compiled constraint that produced it:
for violation in result.violations:
for reason in violation.reasons:
print(reason.constraint_id, reason.constraint.render)
print(reason.constraint.definition)
violation.constraint_id identifies the top-level constraint;
reason.constraint_id identifies the nested constraint that failed.
Compare these with Investigate unexpected results to trace a result through the
compiled schema.
See Python API reference for exact result fields and Explain why a node passed or failed for supporting values and evidence trees.