rdflib-ocdm
rdflib-ocdm extends RDFLib with provenance tracking based on the OpenCitations Provenance Model.
Its two main classes, OCDMGraph and OCDMDataset, inherit from RDFLib's Graph and Dataset respectively. The OCDM layer adds methods for recording who changed what and when.
Calling generate_provenance() creates timestamped provenance snapshots for entities whose tracked state changed. Snapshot sequence numbers are managed through counter handler backends (in-memory, filesystem, SQLite, Redis). Unlike oc_ocdm, which targets bibliographic data specifically, rdflib-ocdm is domain-agnostic.
Installation
pip install rdflib-ocdm
Usage
Basic usage
from rdflib import Literal, URIRef
from rdflib_ocdm.counter_handler.in_memory_counter_handler import InMemoryCounterHandler
from rdflib_ocdm.ocdm_graph import OCDMGraph
counter_handler = InMemoryCounterHandler()
g = OCDMGraph(counter_handler)
resp_agent = URIRef("https://orcid.org/0000-0002-8420-0696")
primary_source = URIRef("https://api.crossref.org/")
g.add(
(
URIRef("https://example.org/resource"),
URIRef("http://purl.org/dc/terms/title"),
Literal("Example Resource"),
),
resp_agent=resp_agent,
primary_source=primary_source,
)
g.generate_provenance()
print(g.serialize(format="turtle"))
prov = g.get_provenance_graphs()
print(prov.serialize(format="nquads"))
Working with existing data
When working with pre-existing RDF data, you need to establish a baseline from which changes can be tracked. preexisting_finished() marks the current graph state as that baseline and creates an initial provenance snapshot for each entity. When you later call generate_provenance(), the system computes the delta between the baseline and the current state, recording exactly what changed, when, and by whom. Without calling preexisting_finished(), all triples are treated as newly created.
from rdflib import Literal, URIRef
from rdflib_ocdm.counter_handler.in_memory_counter_handler import InMemoryCounterHandler
from rdflib_ocdm.ocdm_graph import OCDMGraph
g = OCDMGraph(InMemoryCounterHandler())
g.parse("existing_data.ttl", format="turtle")
resp_agent = URIRef("https://orcid.org/0000-0002-8420-0696")
primary_source = URIRef("https://example.org/data-source")
g.preexisting_finished(resp_agent=resp_agent, primary_source=primary_source)
g.add(
(
URIRef("https://example.org/resource"),
URIRef("http://purl.org/dc/terms/description"),
Literal("Updated description"),
),
resp_agent=resp_agent,
primary_source=primary_source,
)
g.generate_provenance()
prov_graphs = g.get_provenance_graphs()
For working with SPARQL endpoints, Reader.import_entities_from_triplestore() imports entities from a triplestore into an OCDMGraph or OCDMDataset, while Storer.upload_all() pushes graph changes back as batched update queries.
Running tests
Prerequisites
- UV for dependency management
- Docker for running test databases (storer tests start/stop Virtuoso containers automatically via pytest fixtures)
Setup
git clone https://github.com/opencitations/rdflib-ocdm.git
cd rdflib-ocdm
uv sync --locked --all-extras --dev
Running tests
uv run pytest test/ -v
Run with coverage:
uv run coverage run
uv run coverage report
uv run coverage html
Contributing
Please see CONTRIBUTING.md for guidelines on how to contribute to this project, including commit message conventions and how to trigger different types of releases.
References
- Persiani, S., Daquino, M., Peroni, S. (2022). A Programming Interface for Creating Data According to the SPAR Ontologies and the OpenCitations Data Model. In: Groth, P., et al. The Semantic Web. ESWC 2022. Lecture Notes in Computer Science, vol 13261. Springer, Cham. https://doi.org/10.1007/978-3-031-06981-9_18
License
ISC License
Related projects
-
oc_ocdm: a Python library for creating and managing bibliographic RDF data according to the OpenCitations Data Model.
-
time-agnostic-library: a Python library for time-travel queries over RDF datasets that follow the OpenCitations provenance model.
-
heritrace: an editor for RDF data, with built-in provenance and change tracking.
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 rdflib_ocdm-2.0.1.tar.gz.
File metadata
- Download URL: rdflib_ocdm-2.0.1.tar.gz
- Upload date:
- Size: 91.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.11.30 {"installer":{"name":"uv","version":"0.11.30","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d1aab74285efc245dc2dfe9b1ea95774d9017205f0368757fed30e35eac36459
|
|
| MD5 |
69f9d16159b920c45a47f0c93407cb67
|
|
| BLAKE2b-256 |
e59ef909e17e07b136eb618b40c2debbcf0177bcad705e3a5d502a4056fe53d0
|
File details
Details for the file rdflib_ocdm-2.0.1-py3-none-any.whl.
File metadata
- Download URL: rdflib_ocdm-2.0.1-py3-none-any.whl
- Upload date:
- Size: 28.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.11.30 {"installer":{"name":"uv","version":"0.11.30","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e88d96d00d09d686c8c0b977a4b38ce8bf12fcf2d00014b4b2e21510e6fa4803
|
|
| MD5 |
58307681b46c2bebd1346e4ab008e49d
|
|
| BLAKE2b-256 |
908394991f69b814f72a07e8ba01ba9e5024de8989c59c76f701872a4412b725
|