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:ruleevaluation (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:sparqlconstraints 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 API —
validate()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 or passed as None, shapes are expected to be embedded in the data graph. Do not pass an empty rdflib.Graph() for embedded shapes; that is treated as an explicit empty shapes graph.
To validate a shapes graph against itself, pass it once. The embedded path parses and plans one graph without constructing separate data and shapes graphs:
result = shifty.validate_algebra("shapes.ttl", infer=False)
conforms, report_graph, results_text = shifty.validate("shapes.ttl", infer=False)
pathlib.Path inputs are parsed directly in Rust. rdflib.Graph inputs are
transferred as N-Triples.
Reuse prepared shapes
For multiple data graphs using the same shapes, cache parsing, normalization,
and planning with PreparedValidator:
validator = shifty.PreparedValidator(shapes)
result = validator.validate_algebra(data, infer=False)
conforms, report_graph, results_text = validator.validate(data)
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
print(result.results_text) # human-readable summary (built and cached on first access)
for v in result.violations:
print(v.focus_node) # IRI of the failing focus node
print(v.shape_name) # IRI of the violated shape, or None
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
Set infer=False when validation should not first run embedded SHACL-AF rules
to a fixed point.
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
If rules are embedded in the data graph, omit the second argument or pass
None:
result = shifty.infer(combined_data_and_rules)
result = shifty.infer(combined_data_and_rules, None)
Passing rdflib.Graph() as the second argument means “run with an explicit
empty rules graph,” so no embedded rules will be parsed.
graph_mode
validate() and validate_algebra() 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")
When shacl_graph is omitted, all three modes are equivalent because focus
discovery and evaluation use the same embedded graph. infer() does not accept
graph_mode.
File inputs
import pathlib
conforms, report, text = shifty.validate(
pathlib.Path("data.ttl"),
pathlib.Path("shapes.ttl"),
)
Witnesses (symbolic repair)
RepairSession exposes the witnessing layer: for each statement it reports why
a focus node fails (a FocusWitness) or why it holds (a FocusSatisfaction),
the structured input to repair synthesis. The session is immutable; it computes
and gates but decides nothing.
shapes = """
@prefix sh: <http://www.w3.org/ns/shacl#> .
@prefix ex: <http://example.org/> .
ex:PersonShape a sh:NodeShape ;
sh:targetClass ex:Person ;
sh:property [ sh:path ex:name ; sh:minCount 1 ] .
"""
data = """
@prefix ex: <http://example.org/> .
ex:carol a ex:Person ; ex:name "Carol" . # passes ex:PersonShape
ex:dan a ex:Person . # fails: no ex:name
"""
session = shifty.RepairSession(shapes, data, infer=False)
The whole horizon
witnesses() returns one FocusWitness per (focus node, failed statement)
across the entire schema. Empty ⟺ the graph conforms.
for w in session.witnesses():
print(w.focus) # '<http://example.org/dan>'
print(w.statement) # 0 — index into the schema's statements
print(w.target) # 'class(<http://example.org/Person>)' — rendered selector
Structured access (strings and objects)
Everything that has a readable string also has a structured, inspectable form, so
you can branch and process externally instead of parsing text. w.target is the
rendered selector; w.selector is the same thing decomposed:
sel = w.selector
print(sel.kind) # TargetKind.Class — an enumerated discriminant
print(sel.value) # '<http://example.org/Person>' — N-Triples, round-trips
print(sel.render) # 'class(<http://example.org/Person>)' == w.target
print(str(sel)) # same rendered string
if sel.kind == shifty.TargetKind.Class:
... # dispatch on the kind, not on a substring
kind fields are real enums, not bare strings — so the valid set is discoverable
at runtime and usable in match/comparisons:
shifty.TargetKind # Class | SubjectsOf | ObjectsOf | Node | Path | Sparql
shifty.WitnessKind # Atom | Relational | Closed | CountLow | CountHigh | Not | Opaque
shifty.SatKind # Atom | Match | Not | Blocked | Coinductive
shifty.ChoiceKind # Any | Repeat
Scope to one shape
witnesses_for(shape_iri) narrows the horizon to the statements that target a
single shape, matched against the schema's shape IRIs (angle brackets optional).
It raises ValueError if no shape is named shape_iri.
for w in session.witnesses_for("http://example.org/PersonShape"):
# flat bag of failing leaves (AND/OR structure dropped)
for a in w.summary(): # a is a WitnessAtom
print(a.kind, a.path, a.detail) # WitnessKind.CountLow <…/name> have 0, need 1
if a.kind == shifty.WitnessKind.CountLow:
...
print(w.explain()) # indented witness tree:
# CountLow along <…/name>: have 0, need 1
tree = w.repair_tree() # synthesize the repair space for this violation
print(tree.is_blocked) # False — a data repair exists in scope
Passing nodes and the values that satisfied them
satisfactions_for(shape_iri) is the dual: one FocusSatisfaction per passing
focus node for that shape. Each records why the node conforms, including the
values matched along every checked path — the satisfaction-side mirror of
witnesses_for.
for fs in session.satisfactions_for("http://example.org/PersonShape"):
print(fs.focus) # '<http://example.org/carol>'
print(fs.statement) # 0
print(fs.target) # same rendered selector as the witness side
print(fs.selector.kind) # TargetKind.Class — same structured selector too
for a in fs.summary(): # a is a SatAtom
# one Match leaf per value that satisfied a checked path
if a.kind == shifty.SatKind.Match:
print(a.path, a.value) # <…/name> "Carol"
print(fs.explain()) # CountHeld: 1 match(es)
witnesses_for and satisfactions_for partition the targeted focus nodes:
every node that fails appears in one, every node that holds in the other. For
closed, relational (sh:equals/sh:lessThan/…), and opaque-SPARQL
constraints a satisfaction leaf is reported as SatKind.Blocked — the node
holds, but no enumerable value set is exposed.
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:
docs/00-formalism.md— path algebra π, shape grammar φ, selectors, reference semanticsdocs/01-gap-analysis.md— W3C SHACL/SHACL-AF coverage and known gapsdocs/02-roadmap.md— layered build plan (Layer 0 → 7)
License
BSD-3-Clause
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pyshifty-0.2.1.tar.gz.
File metadata
- Download URL: pyshifty-0.2.1.tar.gz
- Upload date:
- Size: 285.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
af4dab4e42d9c78327793b20d535da3a021704435c3110529b5db2c7641df9b6
|
|
| MD5 |
fd9d9d21d17f01aaaa7e315e0f8090e6
|
|
| BLAKE2b-256 |
8b6673954e91cbb81058c1d7f7270d2fdf073d016b9f76dacc30b54bea73e50c
|
Provenance
The following attestation bundles were made for pyshifty-0.2.1.tar.gz:
Publisher:
release.yml on gtfierro/shifty
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyshifty-0.2.1.tar.gz -
Subject digest:
af4dab4e42d9c78327793b20d535da3a021704435c3110529b5db2c7641df9b6 - Sigstore transparency entry: 1941332303
- Sigstore integration time:
-
Permalink:
gtfierro/shifty@7fff453743a1165bcd018beee7592777f578a42e -
Branch / Tag:
refs/tags/v0.2.1 - Owner: https://github.com/gtfierro
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@7fff453743a1165bcd018beee7592777f578a42e -
Trigger Event:
push
-
Statement type:
File details
Details for the file pyshifty-0.2.1-cp39-abi3-win_amd64.whl.
File metadata
- Download URL: pyshifty-0.2.1-cp39-abi3-win_amd64.whl
- Upload date:
- Size: 3.0 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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d938d1487577bd6357af4336f9104f97e3028da50314c8ec57b4f270bfae5f33
|
|
| MD5 |
67db027a7d4c6877f60712f8178c9511
|
|
| BLAKE2b-256 |
c5467407a161f1ec3ccb757c345380a9609a08fa64f8dc083cc438eea56cc162
|
Provenance
The following attestation bundles were made for pyshifty-0.2.1-cp39-abi3-win_amd64.whl:
Publisher:
release.yml on gtfierro/shifty
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyshifty-0.2.1-cp39-abi3-win_amd64.whl -
Subject digest:
d938d1487577bd6357af4336f9104f97e3028da50314c8ec57b4f270bfae5f33 - Sigstore transparency entry: 1941332853
- Sigstore integration time:
-
Permalink:
gtfierro/shifty@7fff453743a1165bcd018beee7592777f578a42e -
Branch / Tag:
refs/tags/v0.2.1 - Owner: https://github.com/gtfierro
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@7fff453743a1165bcd018beee7592777f578a42e -
Trigger Event:
push
-
Statement type:
File details
Details for the file pyshifty-0.2.1-cp39-abi3-musllinux_1_2_x86_64.whl.
File metadata
- Download URL: pyshifty-0.2.1-cp39-abi3-musllinux_1_2_x86_64.whl
- Upload date:
- Size: 33.3 MB
- Tags: CPython 3.9+, musllinux: musl 1.2+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5e0dd5455e20ef686e1edc6fd0981afe782bbfb30ea95bef522bbcf1e677d94a
|
|
| MD5 |
f73df740a744f24b376d8dcc968aac4a
|
|
| BLAKE2b-256 |
5d9a436775a40f592f03e08dcdc9dc65ff2c5ba43cb74f64c532c64db75c8422
|
Provenance
The following attestation bundles were made for pyshifty-0.2.1-cp39-abi3-musllinux_1_2_x86_64.whl:
Publisher:
release.yml on gtfierro/shifty
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyshifty-0.2.1-cp39-abi3-musllinux_1_2_x86_64.whl -
Subject digest:
5e0dd5455e20ef686e1edc6fd0981afe782bbfb30ea95bef522bbcf1e677d94a - Sigstore transparency entry: 1941332987
- Sigstore integration time:
-
Permalink:
gtfierro/shifty@7fff453743a1165bcd018beee7592777f578a42e -
Branch / Tag:
refs/tags/v0.2.1 - Owner: https://github.com/gtfierro
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@7fff453743a1165bcd018beee7592777f578a42e -
Trigger Event:
push
-
Statement type:
File details
Details for the file pyshifty-0.2.1-cp39-abi3-musllinux_1_2_aarch64.whl.
File metadata
- Download URL: pyshifty-0.2.1-cp39-abi3-musllinux_1_2_aarch64.whl
- Upload date:
- Size: 32.7 MB
- Tags: CPython 3.9+, musllinux: musl 1.2+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8bafbd5edc8e9ecfecde69604de32fe7c49a8959d38534a3722e63b6681eff1a
|
|
| MD5 |
9ea2cbc5d3697f50e020cf64a9db4328
|
|
| BLAKE2b-256 |
1e4f12552ae62964f96951ee6c4eeb61160f19628b7592eaeffe11e5013c59ea
|
Provenance
The following attestation bundles were made for pyshifty-0.2.1-cp39-abi3-musllinux_1_2_aarch64.whl:
Publisher:
release.yml on gtfierro/shifty
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyshifty-0.2.1-cp39-abi3-musllinux_1_2_aarch64.whl -
Subject digest:
8bafbd5edc8e9ecfecde69604de32fe7c49a8959d38534a3722e63b6681eff1a - Sigstore transparency entry: 1941332457
- Sigstore integration time:
-
Permalink:
gtfierro/shifty@7fff453743a1165bcd018beee7592777f578a42e -
Branch / Tag:
refs/tags/v0.2.1 - Owner: https://github.com/gtfierro
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@7fff453743a1165bcd018beee7592777f578a42e -
Trigger Event:
push
-
Statement type:
File details
Details for the file pyshifty-0.2.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: pyshifty-0.2.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 33.3 MB
- Tags: CPython 3.9+, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8c71c56538f86e5bda1747b74c86fd9e004a346671ea7b92a44053810296cce2
|
|
| MD5 |
584995c113f4bd9d0a68781ea3f31504
|
|
| BLAKE2b-256 |
05625261925ce2cd006538b1c2a052323c913b71e63073981f1dc684943cf780
|
Provenance
The following attestation bundles were made for pyshifty-0.2.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:
Publisher:
release.yml on gtfierro/shifty
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyshifty-0.2.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl -
Subject digest:
8c71c56538f86e5bda1747b74c86fd9e004a346671ea7b92a44053810296cce2 - Sigstore transparency entry: 1941332757
- Sigstore integration time:
-
Permalink:
gtfierro/shifty@7fff453743a1165bcd018beee7592777f578a42e -
Branch / Tag:
refs/tags/v0.2.1 - Owner: https://github.com/gtfierro
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@7fff453743a1165bcd018beee7592777f578a42e -
Trigger Event:
push
-
Statement type:
File details
Details for the file pyshifty-0.2.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.
File metadata
- Download URL: pyshifty-0.2.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- Upload date:
- Size: 32.8 MB
- Tags: CPython 3.9+, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
340b8afed6697022ebec26e5904861bbadd2b6f60dd152ada2e7241bc9333dc4
|
|
| MD5 |
0fcdfffd03e2ab8c9832bb5d9b1d855d
|
|
| BLAKE2b-256 |
ae17afa68f62b541aa5a095c7938ffe981c8be21b54306cbb9adec2b002c999b
|
Provenance
The following attestation bundles were made for pyshifty-0.2.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:
Publisher:
release.yml on gtfierro/shifty
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyshifty-0.2.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl -
Subject digest:
340b8afed6697022ebec26e5904861bbadd2b6f60dd152ada2e7241bc9333dc4 - Sigstore transparency entry: 1941332635
- Sigstore integration time:
-
Permalink:
gtfierro/shifty@7fff453743a1165bcd018beee7592777f578a42e -
Branch / Tag:
refs/tags/v0.2.1 - Owner: https://github.com/gtfierro
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@7fff453743a1165bcd018beee7592777f578a42e -
Trigger Event:
push
-
Statement type:
File details
Details for the file pyshifty-0.2.1-cp39-abi3-macosx_11_0_arm64.whl.
File metadata
- Download URL: pyshifty-0.2.1-cp39-abi3-macosx_11_0_arm64.whl
- Upload date:
- Size: 3.1 MB
- Tags: CPython 3.9+, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8e3097519f141a81192731fde1f9a4e8aea2a5c154a8f2653cf2193ff3bd4818
|
|
| MD5 |
ef3ce4ea9ea18a7593f1b4fbd29d23bf
|
|
| BLAKE2b-256 |
e77e67143cb797a7356c1faac88965b543078661eef6794e09052dd039117e28
|
Provenance
The following attestation bundles were made for pyshifty-0.2.1-cp39-abi3-macosx_11_0_arm64.whl:
Publisher:
release.yml on gtfierro/shifty
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyshifty-0.2.1-cp39-abi3-macosx_11_0_arm64.whl -
Subject digest:
8e3097519f141a81192731fde1f9a4e8aea2a5c154a8f2653cf2193ff3bd4818 - Sigstore transparency entry: 1941332548
- Sigstore integration time:
-
Permalink:
gtfierro/shifty@7fff453743a1165bcd018beee7592777f578a42e -
Branch / Tag:
refs/tags/v0.2.1 - Owner: https://github.com/gtfierro
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@7fff453743a1165bcd018beee7592777f578a42e -
Trigger Event:
push
-
Statement type: