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.2.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.2-cp39-abi3-win_amd64.whl (2.6 MB view details)

Uploaded CPython 3.9+Windows x86-64

pyshifty-0.1.2-cp39-abi3-musllinux_1_2_x86_64.whl (29.1 MB view details)

Uploaded CPython 3.9+musllinux: musl 1.2+ x86-64

pyshifty-0.1.2-cp39-abi3-musllinux_1_2_aarch64.whl (28.7 MB view details)

Uploaded CPython 3.9+musllinux: musl 1.2+ ARM64

pyshifty-0.1.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (29.1 MB view details)

Uploaded CPython 3.9+manylinux: glibc 2.17+ x86-64

pyshifty-0.1.2-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (28.7 MB view details)

Uploaded CPython 3.9+manylinux: glibc 2.17+ ARM64

pyshifty-0.1.2-cp39-abi3-macosx_11_0_arm64.whl (2.7 MB view details)

Uploaded CPython 3.9+macOS 11.0+ ARM64

File details

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

File metadata

  • Download URL: pyshifty-0.1.2.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.2.tar.gz
Algorithm Hash digest
SHA256 db0e5d40faca08a9b923bbafc7d74d183e7bdda1f65ffd1fabb83fb8f407b816
MD5 b83ac5c15e13d50654cee555f4431151
BLAKE2b-256 6eb482faec44ec5132e26d4f7a47ab11b05014c259c30c1eecfe4af995b963da

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyshifty-0.1.2.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.2-cp39-abi3-win_amd64.whl.

File metadata

  • Download URL: pyshifty-0.1.2-cp39-abi3-win_amd64.whl
  • Upload date:
  • Size: 2.6 MB
  • Tags: CPython 3.9+, 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.2-cp39-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 89d059220c3af488505633f1d37714e2fa1e6a8aaf9e45bacefcf3cd5706452c
MD5 25161a7c04562ea56c253f03ff3cb1ce
BLAKE2b-256 d980590b9d10b8400ea083f2f219855680f6a57e89dd51656f1f98dacbf3c00c

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyshifty-0.1.2-cp39-abi3-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.2-cp39-abi3-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for pyshifty-0.1.2-cp39-abi3-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 d47d796c4958e8297193d29ac14cc1ae6e3f2aeab8ed7b8310b04d68145c48c3
MD5 1ec5972be8f7e2e665b59d9fbd3f5dd5
BLAKE2b-256 90b81427845e87d141a2af347d2d1a2cb20a9e69f75bef155c3182dc3a31562f

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyshifty-0.1.2-cp39-abi3-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.2-cp39-abi3-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for pyshifty-0.1.2-cp39-abi3-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 0277aff7338b6fde0af8d9f310929baf482891239d4396f604acdce1752ccb96
MD5 f007a5e226f729f075b5a0b3798366e3
BLAKE2b-256 d57032c9bcf57d2bbd8cbf494de3e4b6dce493962be5ac11eaf3788a7e94e4ab

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyshifty-0.1.2-cp39-abi3-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.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for pyshifty-0.1.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 202c8f4a0132b33ed4739a0a8e0f3997362caff89d41bfdac4bec45fc0737fe6
MD5 f8e10249e3e67cf8fee4d76902cb6e96
BLAKE2b-256 2d2ec3a016f17ebbc84abf7d9d6dea9c5a4144a228a23df85a86b0fed36bb51c

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyshifty-0.1.2-cp39-abi3-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.2-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for pyshifty-0.1.2-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 f0d4de484e0067b0282326fe3e1c24d57246f3078a3a7f6a21a1b37ea652a006
MD5 a73892ceb2d7c725bdab298f26024284
BLAKE2b-256 5a505d702b7f8d7dc638ba179de7f1b1eab4326623d48c62522a2bdc9e54fd4c

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyshifty-0.1.2-cp39-abi3-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.2-cp39-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for pyshifty-0.1.2-cp39-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 68eeb249811373727858a6931a94f2f105b85a1f2918e57850affc580717f184
MD5 855503647c297a451e0cc0b155986e26
BLAKE2b-256 a4cab366cbd7e9e84bf3d8623e58b197c34efb0d4c140a6838de0369d4919acb

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyshifty-0.1.2-cp39-abi3-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