Skip to main content

pmprov

Ask DeepWiki

Analytic provenance tracking middleware for exploratory process mining notebooks.

pmprov automatically records every meaningful decision an analyst makes during a Jupyter or Marimo session — which functions were called, with what arguments, on which data, and how the data changed — without requiring any modification to analyst code.


How it works

Your cell code  →  AST rewriter  →  trace_step()  →  DuckDB/SQLite + Parquet
                   (transparent)     (non-blocking)

Every top-level function call is intercepted at the AST level, wrapped with a lightweight tracer, and recorded as a node in a provenance tree. The analyst's variables contain exactly the same values they would without the middleware.


Getting started

Prerequisites: Python ≥ 3.13, uv

git clone https://github.com/alvarobernal2412/pmprov.git
cd pmprov
uv pip install -e ".[full]"

In a Jupyter notebook:

from tracker import init_jupyter, operation_type
import pandas as pd
import pm4py

# Register semantic labels for third-party functions (optional but recommended)
operation_type("data_loading",      pd.read_csv)
operation_type("process_discovery", pm4py.discover_petri_net_inductive)

# Start tracking — one call, no other changes to your code
rt = init_jupyter(history_name="My analysis")

# Your normal analysis code below — provenance is captured automatically
event_log = pd.read_csv("data/log.csv", parse_dates=["time:timestamp"])
net, im, fm = pm4py.discover_petri_net_inductive(event_log)

Resuming a history: calling init_jupyter/init_marimo again with the same history_name (and the same db_path) resumes the prior history by default — your kernel restarted, but the analysis lineage picks up where it left off. Pass fresh=True to force a brand-new history instead. Calling with no history_name always starts fresh, unaffected by this. Note this isn't safe across two kernels running concurrently against the same db_path + history_name — they'd race on whose writes "win".

In a Marimo notebook:

Marimo support requires a one-time setup step. The middleware patches Marimo's AST compiler at Python startup via sitecustomize.py, which must be placed in your virtual environment (already in place if installed via uv).

Structural requirement: Marimo's reactive DAG is built from the original cell code before the AST rewriter runs. This means the rewriter cannot inject dependency edges automatically. To guarantee that init_marimo() runs before any tracked cell, combine your path setup and init_marimo() call in one cell and export all imports (pd, constants, etc.) from it. Downstream cells then depend on those names naturally, which implicitly orders them after init — no need to add rt to every cell's parameters.

# ── Setup + init (one cell) ───────────────────────────────────────────────────
@app.cell
def _():
    import sys, pandas as pd
    from pathlib import Path
    from tracker import init_marimo, operation_type

    # ... path setup ...

    rt = init_marimo(history_name="My analysis")
    operation_type("data_loading", pd.read_csv)

    def settle():
        rt.storage._executor.submit(lambda: None).result()

    return pd, rt, settle, DATA_FILE  # export everything downstream cells need


# ── Analysis cells — no `rt` needed in params ─────────────────────────────────
@app.cell
def _(DATA_FILE, pd):          # depends on pd + DATA_FILE → init already ran
    event_log = pd.read_csv(DATA_FILE, parse_dates=["time:timestamp"])
    return (event_log,)

Run with:

uv run marimo run examples/marimo/provenance_demo.py
# or for interactive editing:
uv run marimo edit examples/marimo/provenance_demo.py

Note: Provenance capture works in Marimo. Some introspection features (interactive widget, manual checkout) are not yet validated in the Marimo environment.

Inspect the provenance graph:

rt.list_states()           # table of all recorded steps
rt.show_graph()            # static matplotlib tree
rt.show_graph_widget()     # interactive Jupyter widget (Jupyter only)

Branch from a past state:

branch = rt.checkout("paste-state-id-here", branch_name="experiment-v2")

See examples/jupyter/provenance_demo.ipynb for a full Jupyter walkthrough and examples/marimo/provenance_demo.py for the Marimo equivalent, both using the RTFM dataset.


Optional extras

Extra What it adds
duckdb DuckDB storage backend (preferred)
parquet DataFrame artifact persistence via pyarrow
graph show_graph() via networkx + matplotlib
widgets show_graph_widget() interactive panel
marimo Marimo notebook support
full Everything above
uv pip install -e ".[full]"

Project structure

models/    Pydantic v2 domain models (provenance entities)
tracker/   Runtime middleware (AST rewriter, tracer, storage)
examples/  Demo notebook + RTFM dataset helpers

Running tests

uv sync --all-extras --dev
uv run pytest

Git hooks (optional)

Enforces the test suite and conventional commit format (≤ 45 chars) on every commit:

uv run pre-commit install && uv run pre-commit install --hook-type commit-msg

Skip this step if you prefer to run checks manually.


Contributing

See CONTRIBUTING.md.

License

Apache 2.0 — see LICENSE.

Metadata

Release files for pmprov 0.6.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pmprov 0.6.0
File Size Uploaded Provenance Actions
pmprov-0.6.0.tar.gz 82.3 kB Without provenance Details for pmprov-0.6.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for pmprov 0.6.0
File Interpreter ABI Platform Actions
pmprov-0.6.0-py3-none-any.whl Python 3 none any Details for pmprov-0.6.0-py3-none-any.whl

Total release size: 176.1 kB

Release files / pmprov-0.6.0.tar.gz

Download URL pmprov-0.6.0.tar.gz
Size 82.3 kB
Tags Source
SHA-256 checksum
How to use checksums
8b12c37c730df7016d3616a6447f6ea2b7daa947261251a269206fe85882d945
BLAKE2b-256 checksum
How to use checksums
ca32515ef4c26fb4e9e73db053c8877f04093ac9e8d74cb8cd8420b8799858fa
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.5 {"installer":{"name":"uv","version":"0.13.5","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}

Release files / pmprov-0.6.0-py3-none-any.whl

Download URL pmprov-0.6.0-py3-none-any.whl
Size 93.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
042bb64577f528cacac09d6f34811608d3ea35a249449953c4192e8052acde0f
BLAKE2b-256 checksum
How to use checksums
5c2275e30ebd41626eb3758b14a22a137dfb6d1b9ffb8045c8e8224a9365c16a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.5 {"installer":{"name":"uv","version":"0.13.5","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}

Security for pmprov 0.6.0

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.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page