Skip to main content

Python bindings for the shifty SHACL engine

Project description

shifty

A formalism-first SHACL validation and SHACL-AF inference engine written in Rust, grounded in the algebraic treatment of Common Foundations for SHACL, ShEx, and PG-Schema (arXiv:2502.01295). Available as a command-line tool and as Python bindings (pyshifty).

Features

  • Full SHACL Core validation — node and property shapes, all standard constraint components
  • SHACL-AF inference — forward-chaining sh:rule evaluation (Triple Rules, SPARQL Construct Rules) to a fixed point, with stratification analysis for recursive rulesets
  • Algebraic IR — shapes are lowered to a path algebra (π) and shape grammar (φ) before evaluation; the same IR drives both validation and inference
  • Native SPARQL execution — a subset of sh:sparql constraints and SPARQL Construct rules runs directly over an indexed dataset without a full SPARQL engine, with automatic fallback to Spareval for unsupported constructs
  • Multi-layer pipeline — parsing → algebraic lowering → normalization/CSE → physical planning → execution; each layer is independently inspectable
  • pyshifty-compatible Python APIvalidate() returns (conforms, report_graph, results_text) matching pyshifty's interface

Installation

CLI

cargo install --path crates/shifty-cli

Or build from source:

cargo build --release -p shifty-cli
# binary at target/release/shifty

Python

pip install pyshifty

The package installs as pyshifty but is imported as shifty:

import shifty

To build from source (requires Rust and maturin):

cd python
pip install maturin
maturin develop

CLI usage

Validate

shifty validate --shapes shapes.ttl --data data.ttl
conforms: false
violations: 1
  <http://example.org/bob>  [target: ∃ rdf:type .⊤]
      - (ex:name) 123 → expected datatype xsd:string

Emit a W3C sh:ValidationReport in Turtle:

shifty validate --shapes shapes.ttl --data data.ttl --report

JSON output:

shifty validate --shapes shapes.ttl --data data.ttl --format json

Graph mode controls which triples are visible to path traversal and SPARQL evaluation:

# default: focus nodes from data; paths/SPARQL use data ∪ shapes
shifty validate --shapes shapes.ttl --data data.ttl --graph-mode union

# focus nodes and evaluation use data only
shifty validate --shapes shapes.ttl --data data.ttl --graph-mode data

# focus nodes and evaluation both use data ∪ shapes
shifty validate --shapes shapes.ttl --data data.ttl --graph-mode union-all

Infer

Run SHACL-AF rules to a fixed point, then print the derived triples:

shifty infer --shapes rules.ttl --data data.ttl
inferred 3 triple(s):
  <http://example.org/r1> <http://example.org/area> "6"^^<http://www.w3.org/2001/XMLSchema#integer>
  ...

Inspect

Inspect how a shapes graph looks at each stage of the pipeline:

# Raw triples after parsing
shifty inspect --stage rdf shapes.ttl

# Lowered algebraic IR (φ/π notation)
shifty inspect --stage algebra shapes.ttl

# After normalization and common-subexpression elimination
shifty inspect --stage normalized shapes.ttl

# Stratification analysis (recursion detection)
shifty inspect --stage strata shapes.ttl

# Physical plan: focus sources + cost-ordered shape checks
shifty inspect --stage plan shapes.ttl

# SPARQL constraint capability: which queries run native vs. Spareval
shifty inspect --stage capability shapes.ttl

All stages support --format text (default), --format json; the algebra and normalized stages also support --format dot for Graphviz output.

Shapes files and data files may be local paths or HTTP/HTTPS URLs. Both --shapes and --data are repeatable to merge multiple files.

Python usage

import shifty

Validate (pyshifty-compatible)

shapes = """
@prefix sh:  <http://www.w3.org/ns/shifty#> .
@prefix ex:  <http://example.org/> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .

ex:PersonShape a sh:NodeShape ;
    sh:targetClass ex:Person ;
    sh:property [
        sh:path ex:name ;
        sh:minCount 1 ;
        sh:datatype xsd:string ;
    ] ;
    sh:property [
        sh:path ex:age ;
        sh:maxCount 1 ;
        sh:datatype xsd:integer ;
    ] .
"""

data = """
@prefix ex: <http://example.org/> .

ex:Alice a ex:Person ; ex:name "Alice" ; ex:age 30 .
ex:Bob   a ex:Person .
"""

conforms, report_graph, results_text = shifty.validate(data, shapes)
# conforms → False
# report_graph → rdflib.Graph with sh:ValidationReport
# results_text → human-readable summary

Graph inputs can be a string, bytes, pathlib.Path, or rdflib.Graph. If shacl_graph is omitted, shapes are expected to be embedded in the data graph.

Validate with structured result

validate_algebra returns an AlgebraResult with typed Violation objects instead of an RDF report graph:

result = shifty.validate_algebra(data, shapes)
print(result.conforms)        # False
for v in result.violations:
    print(v.focus)            # IRI of the failing focus node
    for r in v.reasons:
        print(r.message)      # human-readable failure description
        print(r.path)         # path that was checked, if applicable
        print(r.value)        # the offending value node

Infer

Run SHACL-AF rules to a fixed point:

rules = """
@prefix sh: <http://www.w3.org/ns/shifty#> .
@prefix ex: <http://example.org/> .

ex:RectangleShape a sh:NodeShape ;
    sh:targetClass ex:Rectangle ;
    sh:rule [
        a sh:TripleRule ;
        sh:subject sh:this ;
        sh:predicate ex:area ;
        sh:object [ sh:path ex:width ] ;
    ] .
"""

data = """
@prefix ex: <http://example.org/> .
ex:r1 a ex:Rectangle ; ex:width 3 ; ex:height 2 .
"""

result = shifty.infer(data, rules)
print(result.inferred_count)    # number of newly derived triples
g = result.graph()              # rdflib.Graph with original + inferred data

graph_mode

All three functions accept a graph_mode keyword argument:

shifty.validate(data, shapes, graph_mode="union")      # default
shifty.validate(data, shapes, graph_mode="data")
shifty.validate(data, shapes, graph_mode="union-all")

File inputs

import pathlib

conforms, report, text = shifty.validate(
    pathlib.Path("data.ttl"),
    pathlib.Path("shapes.ttl"),
)

Crate structure

crate role
shifty-algebra path algebra π, shape grammar φ, schema arena, rendering
shifty-parse Turtle/RDF → algebraic IR lowering
shifty-opt normalization, stratification, physical planning, native SPARQL lowering
shifty-engine validation + AF inference execution, SPARQL executor
shifty-cli shifty binary
pyshifty (python/) PyO3 bindings, published as pyshifty on PyPI

Design docs

The docs/ directory contains the full design:

License

BSD-3-Clause

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pyshifty-0.1.1.tar.gz (186.3 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

pyshifty-0.1.1-cp312-cp312-win_amd64.whl (2.6 MB view details)

Uploaded CPython 3.12Windows x86-64

pyshifty-0.1.1-cp312-cp312-musllinux_1_2_x86_64.whl (29.2 MB view details)

Uploaded CPython 3.12musllinux: musl 1.2+ x86-64

pyshifty-0.1.1-cp312-cp312-musllinux_1_2_aarch64.whl (28.8 MB view details)

Uploaded CPython 3.12musllinux: musl 1.2+ ARM64

pyshifty-0.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (29.2 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ x86-64

pyshifty-0.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (28.8 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ ARM64

pyshifty-0.1.1-cp312-cp312-macosx_11_0_arm64.whl (2.7 MB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

File details

Details for the file pyshifty-0.1.1.tar.gz.

File metadata

  • Download URL: pyshifty-0.1.1.tar.gz
  • Upload date:
  • Size: 186.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pyshifty-0.1.1.tar.gz
Algorithm Hash digest
SHA256 202933d792bd3051cd2966790c3888de247bb17a89964c189af665007e2457c3
MD5 87bddf74fd1db5da726b471008808be5
BLAKE2b-256 4ea56f7fc0acbff7af8b9b02b7b2e6322d521346b1decf6bf68cf5421c2f55a7

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyshifty-0.1.1.tar.gz:

Publisher: release.yml on gtfierro/shifty

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyshifty-0.1.1-cp312-cp312-win_amd64.whl.

File metadata

  • Download URL: pyshifty-0.1.1-cp312-cp312-win_amd64.whl
  • Upload date:
  • Size: 2.6 MB
  • Tags: CPython 3.12, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pyshifty-0.1.1-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 a95f4b81449edbded3d067d22970b800afe73b54b932536d60c066c6e28fbf7f
MD5 15624be99597af7fd71e1bc6611aed6b
BLAKE2b-256 667e36f1619cfa1cfaf203421210b6d643e009f8b32e6454f67291677bbbf878

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyshifty-0.1.1-cp312-cp312-win_amd64.whl:

Publisher: release.yml on gtfierro/shifty

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyshifty-0.1.1-cp312-cp312-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for pyshifty-0.1.1-cp312-cp312-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 d377275beb8277b05ccf637d66b65664ff5a75730da8a21ace25d607f0e9ddfd
MD5 7dee0bc5964ef0477015b19eda23df65
BLAKE2b-256 61c6346785d3d631da8f0976581d1ff33214d7b9d12f3a72195b745a0341f429

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyshifty-0.1.1-cp312-cp312-musllinux_1_2_x86_64.whl:

Publisher: release.yml on gtfierro/shifty

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyshifty-0.1.1-cp312-cp312-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for pyshifty-0.1.1-cp312-cp312-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 df108d1ca23c8092691a5cf99e852d642c44a34899c94124edfeb8a2e7c35933
MD5 cf715d00bf50492bc4c8b8ff5fd2715e
BLAKE2b-256 ac36aac259b9d00cc28fa307476c7205dd29053e762c28c8b4c2b43579eb6123

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyshifty-0.1.1-cp312-cp312-musllinux_1_2_aarch64.whl:

Publisher: release.yml on gtfierro/shifty

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyshifty-0.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for pyshifty-0.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 311dcff01ada384dbae0383ec5fde0dbb1e7df6d0a575aca3196f66a28c0a915
MD5 41a7fc5d7c0bd1687bffa05047ee9b94
BLAKE2b-256 0f0c0d8a17a6c9ee87d18a9d93e9b5de232a6e970ca5d022c313ffec22d8dbfc

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyshifty-0.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: release.yml on gtfierro/shifty

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyshifty-0.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for pyshifty-0.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 adfa6b43df6cc56659ca5d897bb9aa607fff733cdd1d93c37475eecb8e4f833d
MD5 03bc839738e7ae9a02e4b0dc32558695
BLAKE2b-256 e342fcf178fa45a940bc05e1331373a0a79e3ca76b352691c0e12b2a71f905ba

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyshifty-0.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: release.yml on gtfierro/shifty

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pyshifty-0.1.1-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for pyshifty-0.1.1-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 7faa25e43a3588f96488f057fa1aee5dd93c42303a0413a50da15cf93e32de8a
MD5 287848a78c84744ea7f016d656512747
BLAKE2b-256 93dc5ed50125d9cec358bb48962410bc195a4370a75ec257636a3d0b862af610

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyshifty-0.1.1-cp312-cp312-macosx_11_0_arm64.whl:

Publisher: release.yml on gtfierro/shifty

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page