shacl (Python)
Python bindings for the SHACL validation engine, built with PyO3 and maturin.
Building
pip install maturin
cd crates/shacl-python
maturin develop --release # build and install into the current venv
maturin build --release # produce a wheel in target/wheels
The extension targets the stable ABI (abi3-py39), so one wheel serves every
CPython from 3.9 upwards.
Usage
import shacl
# Compile once, validate many: shapes are fixed while data changes, and
# compiling is a meaningful share of a small run.
shapes = shacl.Shapes.from_file("shapes.ttl")
report = shapes.validate_file("data.ttl")
if not report.conforms:
for r in report.results:
print(r.severity, r.component, r.focus_node, r.value)
Report is truthy when the data conforms and len() gives the result count, so
the common case reads plainly:
if shapes.validate_file("data.ttl"):
print("ok")
For a one-off, or for a self-describing document that carries its own shapes:
shacl.validate("data.ttl") # shapes come from the data graph
shacl.validate("data.ttl", "shapes.ttl")
Turtle can also be passed directly, which is convenient for tests:
shapes = shacl.Shapes.from_turtle(shapes_text)
report = shapes.validate_turtle(data_text)
Notes
Terms are returned as strings in N-Triples syntax — <http://ex/a>,
"42"^^<http://www.w3.org/2001/XMLSchema#integer> — rather than as objects.
That keeps the binding free of a dependency on any particular Python RDF
library; parse them with whichever one you already use.
Threading
A Shapes object is immutable and safe to share. Validation releases the GIL
and clones the term store per run rather than locking a shared one, so
concurrent callers do not serialise on each other.
Measured on stock CPython 3.14 with the GIL enabled — 16 validations of a
69k-triple graph through one shared Shapes:
| threads | throughput |
|---|---|
| 1 | 7.8 runs/s |
| 4 | 26.9 runs/s |
| 8 | 27.8 runs/s |
It plateaus at four because each validation already parses across threads internally, so the cores are busy either way.
Free-threaded builds
The module declares gil_used = false, so it will not force the GIL back on
when imported into a free-threaded interpreter (python3.14t). Note that
free-threading is a separate build, not something a version number brings: a
stock 3.14 still reports sys._is_gil_enabled() == True.
There is little to gain from it here. The GIL is already released around the
work, which is why the table above scales. Free-threading would only help code
doing significant Python-level work in parallel as well — and it costs the
single abi3 wheel, since abi3 is a no-op on free-threaded builds and PyO3
falls back to a version-specific one.
The report as RDF
SHACL defines the validation report as a graph — a sh:ValidationReport — not
as a list of strings. The attributes above are a convenience for reading it from
Python; serialize is what to hand to another RDF tool.
print(shapes.validate_file("data.ttl").serialize())
_:r0 a sh:ValidationReport ;
sh:conforms false ;
sh:result _:r1 .
_:r1 a sh:ValidationResult ;
sh:focusNode <http://ex/a> ;
sh:resultPath <http://ex/age> ;
sh:resultSeverity sh:Violation ;
sh:sourceConstraintComponent sh:DatatypeConstraintComponent ;
sh:value "old" .
Release files for shacl 0.3.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| shacl-0.3.2.tar.gz | 194.7 kB | Details |
Built distributions (wheels)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| shacl-0.3.2-cp39-abi3-win_amd64.whl | CPython 3.9 | abi3 | Windows x86-64 | Details |
| shacl-0.3.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl | CPython 3.9 | abi3 | Linux glibc 2.17+ x86-64 | Details |
| shacl-0.3.2-cp39-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl | CPython 3.9 | abi3 | macOS 10.12+ x86-64, macOS 11.0+ ARM64, macOS 10.12+ universal2 (ARM64, x86-64) | Details |
Total release size: 9.3 MB
Release files / shacl-0.3.2.tar.gz
| Download URL | shacl-0.3.2.tar.gz |
|---|---|
| Size | 194.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
500e7136ae7806249d2533d1bb0c3b8c8f042db8a52e766cdbc875e2c0c1f0e8
|
|
BLAKE2b-256 checksum How to use checksums |
7be599c43145e1615986bce0b69ded89085c039600345fa2046db9e8fb0fbd0c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 23, 2026.
Transparency logRelease files / shacl-0.3.2-cp39-abi3-win_amd64.whl
| Download URL | shacl-0.3.2-cp39-abi3-win_amd64.whl |
|---|---|
| Size | 2.4 MB |
| Tags | CPython 3.9 Windows x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
af0ddad3b0797e4ff6daf4ea2407675fe0787246ebb3368fcc59ac2ebf39f76b
|
|
BLAKE2b-256 checksum How to use checksums |
d76d33ea1154f5a59bc46fae95bbdcbb9c6254864d3af95b08ace28e0f4900b0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 23, 2026.
Transparency logRelease files / shacl-0.3.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | shacl-0.3.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 2.3 MB |
| Tags | CPython 3.9 Linux glibc 2.17+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
8de2f89901b09d9d9b1642ac227f17dcf110ad5a2cebca87150bffdf89e3fe6f
|
|
BLAKE2b-256 checksum How to use checksums |
0179f9fdcad82b056280e8633b5d8d64190ee175eb536c8b2363b89008ed6878
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 23, 2026.
Transparency logRelease files / shacl-0.3.2-cp39-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl
| Download URL | shacl-0.3.2-cp39-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl |
|---|---|
| Size | 4.4 MB |
| Tags | CPython 3.9 abi3 macOS 10.12+ universal2 (ARM64, x86-64) macOS 10.12+ x86-64 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
d66c37ac1a9de5b11111fb3344eb3943e655a7c3e7e362709b690e3e60e0ee6b
|
|
BLAKE2b-256 checksum How to use checksums |
20518fe1a1f539796a2b7b3e5fefe1b8e1e8a5cd753669fd3b74bb86990b5a12
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 23, 2026.
Transparency log