Provium
Provium helps you build processing workflows whose results explain where they came from. Store a result as an artifact, use that artifact as input to another step, and save the new outputs as artifacts of their own. Provium records those relationships automatically as your workflow runs.
Each processing step is represented by a versioned procedure. When a procedure reads existing artifacts and creates new ones, Provium links the outputs to the procedure and its inputs. That lineage travels with every result, including its full upstream history, so a final artifact can be traced back through every intermediate result and the procedures that produced them.
This keeps provenance out of your application logic: you work with inputs, perform the computation, and write outputs inside a procedure execution. Provium handles the dependency graph, integrity metadata, and lifecycle of those artifacts for you.
Features
- Typed readers and writers for application-specific binary formats
- Automatic input, output, and procedure lineage
- SHA-256 payload integrity checks
- Streaming, body-relative binary I/O
- Runtime artifact discovery through Python entry points
- Optional configuration snapshots, including Pydantic v2 models
- No required runtime dependencies
Installation
Provium requires Python 3.12 or newer.
python -m pip install provium
Quick start
Define an artifact that stores a signed 64-bit integer:
import struct
from provium import Artifact, ArtifactReader, ArtifactWriter
INTEGER = struct.Struct(">q")
class IntegerReader(ArtifactReader):
def read_value(self) -> int:
return INTEGER.unpack(self.body.read(INTEGER.size))[0]
class IntegerWriter(ArtifactWriter):
def write_value(self, value: int) -> None:
self.body.write(INTEGER.pack(value))
class IntegerArtifact(Artifact[IntegerReader, IntegerWriter]):
reader = IntegerReader
writer = IntegerWriter
Create and consume artifacts inside procedure executions:
from provium import Procedure
from your_package.artifacts import IntegerArtifact
SOURCE = Procedure(name="source", version="1")
ADD = Procedure(name="add", version="1")
with SOURCE.execute():
left = IntegerArtifact.create("left.pa")
left.write_value(2)
right = IntegerArtifact.create("right.pa")
right.write_value(3)
with ADD.execute():
left = IntegerArtifact.open("left.pa")
right = IntegerArtifact.open("right.pa")
total = IntegerArtifact.create("sum.pa")
total.write_value(left.read_value() + right.read_value())
Registration is optional. Without it, Provium stores the artifact class's full
path, such as your_package.artifacts.IntegerArtifact, as its identifier. Typed
calls such as IntegerArtifact.open() can read these artifacts directly.
Register the artifact when you want a stable custom identifier, aliases, or
dynamic loading through provium.open_artifact():
from provium import ArtifactCatalog
from .artifacts import IntegerArtifact
catalog = ArtifactCatalog()
catalog.register("example.IntegerV1", IntegerArtifact)
Expose that catalog from pyproject.toml so Provium can discover it:
[project.entry-points."provium.catalogs"]
example = "your_package.catalog:catalog"
When each context exits successfully, Provium closes its handles and finalizes
its output files. sum.pa contains the value 5 and records the add execution,
both of its integer inputs, and their producing execution. If a context exits
with an exception, its pending outputs are not committed.
Rendering the lineage for sum.pa produces a graph like this (identities are
shortened here for readability):
flowchart LR
source(["source<br/>Version: 1"])
left["IntegerArtifact<br/>2"]
right["IntegerArtifact<br/>3"]
add(["add<br/>Version: 1"])
total["IntegerArtifact<br/>5"]
source --> left
source --> right
left --> add
right --> add
add --> total
Readers and writers are bound to the execution that created them and cannot be used after that context exits. Nested execution contexts are also rejected.
Inspecting provenance
Every reader exposes the artifact header and lineage:
from provium import Procedure
from your_package.artifacts import IntegerArtifact
with Procedure("inspect", "1").execute():
artifact = IntegerArtifact.open("sum.pa")
print(artifact.read_value())
print(artifact.identity)
print(artifact.artifact_identifier)
print(artifact.lineage.to_json())
Use provium.open_artifact() when the concrete type should be resolved from the
identifier stored in the file rather than selected in advance.
Command-line tools
Inspect an artifact's generic metadata without loading its concrete artifact type:
provium inspect result.pa
Generate Mermaid or Graphviz source for an artifact's complete lineage:
provium graph --renderer mermaid result.pa lineage.mmd
provium graph --renderer graphviz result.pa lineage.dot
Image output supports SVG, PNG, and PDF and defaults to the Mermaid renderer:
provium graph result.pa lineage.svg
provium graph --renderer graphviz result.pa lineage.png
Mermaid image rendering requires the official mmdc executable. Graphviz
rendering requires the optional Python package and Graphviz system package:
npm install --global @mermaid-js/mermaid-cli
python -m pip install 'provium[visualization]'
The output type is inferred from its extension. Library callers can use the
functions in provium.tool to produce Mermaid or DOT source and to receive
rendered images as bytes.
Development
Create a virtual environment and install the project with its test dependencies:
python3 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -e '.[test]'
Run the test suite:
pytest
This also runs Ruff linting and ruff format --check over src and test.
The project requires 100% statement and branch coverage for the provium
package.
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 provium-0.2.0.tar.gz.
File metadata
- Download URL: provium-0.2.0.tar.gz
- Upload date:
- Size: 23.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
19c25b4f1989a1f7b03f7d78e4f437a2caa250ea8750ecb32edc9d47295c48f9
|
|
| MD5 |
c44323e74520d0b4762365fb7685a7e0
|
|
| BLAKE2b-256 |
57cb86931eb6b75b6219ab5246f9f8105597aeeb721c98d6a4be8617eace0b69
|
Provenance
The following attestation bundles were made for provium-0.2.0.tar.gz:
Publisher:
release.yml on SirDavidLudwig/provium
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
provium-0.2.0.tar.gz -
Subject digest:
19c25b4f1989a1f7b03f7d78e4f437a2caa250ea8750ecb32edc9d47295c48f9 - Sigstore transparency entry: 2451295937
- Sigstore integration time:
-
Permalink:
SirDavidLudwig/provium@d67a1a1f46c22592f27caf16a87047f8253cb4d2 -
Branch / Tag:
refs/heads/master - Owner: https://github.com/SirDavidLudwig
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@d67a1a1f46c22592f27caf16a87047f8253cb4d2 -
Trigger Event:
push
-
Statement type:
File details
Details for the file provium-0.2.0-py3-none-any.whl.
File metadata
- Download URL: provium-0.2.0-py3-none-any.whl
- Upload date:
- Size: 28.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1578d6e1b4cd0f35f05596060dac2c6a497357cef8fd6b78d1f402fee470a9b2
|
|
| MD5 |
6ee401329a9535f8b1cd3fb05e4bd191
|
|
| BLAKE2b-256 |
4b28659f23062568efa40cf3c68567eaf761440a5459f361accd2b4adfb5f425
|
Provenance
The following attestation bundles were made for provium-0.2.0-py3-none-any.whl:
Publisher:
release.yml on SirDavidLudwig/provium
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
provium-0.2.0-py3-none-any.whl -
Subject digest:
1578d6e1b4cd0f35f05596060dac2c6a497357cef8fd6b78d1f402fee470a9b2 - Sigstore transparency entry: 2451296042
- Sigstore integration time:
-
Permalink:
SirDavidLudwig/provium@d67a1a1f46c22592f27caf16a87047f8253cb4d2 -
Branch / Tag:
refs/heads/master - Owner: https://github.com/SirDavidLudwig
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@d67a1a1f46c22592f27caf16a87047f8253cb4d2 -
Trigger Event:
push
-
Statement type: