diffable-rdf
Deterministic, diff-stable serialization for rdflib graphs. Produces byte-identical Turtle across runs so version-controlled RDF artifacts (OWL ontologies, SHACL shapes, JSON-LD contexts) show minimal, meaningful diffs instead of blank-node churn.
Why
RDF serializers assign blank-node identifiers (_:c14nN, _:Nb1e2…) based on
process-dependent ordering. Regenerating an ontology therefore produces large,
spurious diffs even when nothing semantically changed. diffable-rdf fixes this
with a standards-based pipeline:
- RDFC-1.0 (W3C RDF Dataset Canonicalization) via pyoxigraph — isomorphic inputs produce identical triple sets.
- Weisfeiler-Lehman structural hashing — replaces sequential
_:c14nNidentifiers with content-based hashes that depend only on graph structure, so adding/removing a triple only touches the directly involved blank nodes. - Idiomatic rdflib re-serialization — inline blank nodes (
[ … ]), collection syntax (( … )), and filtered prefixes (only prefixes actually used are declared).
All triples are preserved; only syntactic form changes.
Install
pip install diffable-rdf
# or
uv add diffable-rdf
Requires Python 3.10+, rdflib>=6, and pyoxigraph>=0.4.
Usage
from rdflib import Graph
from diffable_rdf import deterministic_turtle
g = Graph().parse("ontology.ttl")
ttl = deterministic_turtle(g) # diff-stable, idiomatic Turtle
open("ontology.ttl", "w", newline="\n").write(ttl)
Other entry points:
from diffable_rdf import canonicalize_rdf_graph, deterministic_json, well_known_prefix_map
canonicalize_rdf_graph(graph, "turtle") # lower-level RDFC-1.0 canonical form
deterministic_json(obj) # recursively key/list-sorted JSON(-LD)
well_known_prefix_map() # namespace IRI -> standard prefix name
API
| Function | Purpose |
|---|---|
deterministic_turtle(graph) -> str |
Diff-stable, idiomatic Turtle (RDFC-1.0 + WL hashing + rdflib re-serialize). |
canonicalize_rdf_graph(graph, output_format="turtle") -> str |
RDFC-1.0 canonical serialization (with rdflib fallback for non-standard RDF). |
deterministic_json(obj, indent=3, preserve_list_order_keys=None) -> str |
Recursively sorted JSON; preserves JSON-LD ordered keys (@context, @list, …). |
well_known_prefix_map() -> dict[str, str] |
rdflib's curated namespace→prefix bindings. |
Provenance
Extracted from the diff-stabilization work in
ASCS-eV/linkml#1 (itself a
review-ready rework of upstream linkml/linkml#3295)
into a small, tool-agnostic library so LinkML, ShapeChange output, and other RDF
toolchains can share one canonicalizer.
License
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
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 diffable_rdf-0.0.1.tar.gz.
File metadata
- Download URL: diffable_rdf-0.0.1.tar.gz
- Upload date:
- Size: 15.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bf8abf1681d20a9cfcbf83eb908941cc8013f03f173d222c1fb48204b7268f23
|
|
| MD5 |
c2b1124cdbe6b58320db1fc0d515fba4
|
|
| BLAKE2b-256 |
e19e0be351306d5260ec91a645073002be6c9de67591957e3d431356b0b69533
|
Provenance
The following attestation bundles were made for diffable_rdf-0.0.1.tar.gz:
Publisher:
publish.yml on ASCS-eV/diffable-rdf
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
diffable_rdf-0.0.1.tar.gz -
Subject digest:
bf8abf1681d20a9cfcbf83eb908941cc8013f03f173d222c1fb48204b7268f23 - Sigstore transparency entry: 2280644447
- Sigstore integration time:
-
Permalink:
ASCS-eV/diffable-rdf@2ed0e19306d045703545f0810e8f35e64a37cb13 -
Branch / Tag:
refs/tags/v0.0.1 - Owner: https://github.com/ASCS-eV
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@2ed0e19306d045703545f0810e8f35e64a37cb13 -
Trigger Event:
release
-
Statement type:
File details
Details for the file diffable_rdf-0.0.1-py3-none-any.whl.
File metadata
- Download URL: diffable_rdf-0.0.1-py3-none-any.whl
- Upload date:
- Size: 16.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5ca14a5dfa29c2d503ee717d68e5dfecadd15e7a94459c176d76c4ab2085c2e6
|
|
| MD5 |
6c1bfa7be8b6005729d6684c97ceabf9
|
|
| BLAKE2b-256 |
e0279e7043ae0b57eacfb37bc6b675df2f1788ac65491cfe37c7240845d0d201
|
Provenance
The following attestation bundles were made for diffable_rdf-0.0.1-py3-none-any.whl:
Publisher:
publish.yml on ASCS-eV/diffable-rdf
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
diffable_rdf-0.0.1-py3-none-any.whl -
Subject digest:
5ca14a5dfa29c2d503ee717d68e5dfecadd15e7a94459c176d76c4ab2085c2e6 - Sigstore transparency entry: 2280644450
- Sigstore integration time:
-
Permalink:
ASCS-eV/diffable-rdf@2ed0e19306d045703545f0810e8f35e64a37cb13 -
Branch / Tag:
refs/tags/v0.0.1 - Owner: https://github.com/ASCS-eV
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@2ed0e19306d045703545f0810e8f35e64a37cb13 -
Trigger Event:
release
-
Statement type: