Skip to main content

Petrus: an embedded Petri net workflow engine for Python.

Petrus executes workflows defined as Petri nets. You describe the structure of a workflow — places, transitions, and arcs — and provide the behavior separately as plain Python callables. The engine takes care of token flow, enabling rules, guards, timed transitions, and a full state history with time travel.

What you can do with Petrus?

  1. Define nets in JSON files (editable by tooling or a visual editor) or with a concise Python DSL.
  2. Keep structure and behavior separate: transitions reference guards and handlers by name; you bind the callables at runtime.
  3. Flow typed payloads through the net with colored tokens — guards and handlers declare typed parameters and the engine extracts the right payload automatically.
  4. Compose nets from reusable subnets via file references, with input/output/awaiting interface places marking the boundaries.
  5. Travel in time: every fire is recorded, so you can undo, redo, and branch from any past state.
  6. Drive long-running workflows with split-phase firing, designed to await async handlers — with zero runtime dependency on any workflow platform.

How to use it?

Install from PyPI:

uv add petrus-engine        # or: pip install petrus-engine

Build a net with the DSL, bind behavior, and run it:

from petrus.dsl import Net
from petrus.engine import PetriNetRuntime

net = Net("approval")
p, t = net.p, net.t
p.pending(initial=1) > t.validate > p.validated
p.validated > t.approve(guard="is_approved") > p.approved
p.validated > t.reject(guard="is_rejected") > p.rejected

guards = {
    "is_approved": lambda d: d.value == "approve",
    "is_rejected": lambda d: d.value == "reject",
}

rt = PetriNetRuntime.from_schema(net.build(), guards=guards)

rt.fire(abs(net.t.validate))

A transition is enabled when its input places hold enough tokens, its inhibitor and read arcs are satisfied, and its guard (if any) returns True for the payloads peeked from the input tokens. Firing consumes the input tokens and deposits a merged output token in every output place.

Loading nets from JSON files

Nets can live in JSON files (fileVersion: "2" flat format) and reference other net files as subnets. Resolve a root file and hand the schema to the engine:

from petrus.schema import FlatNet

net = FlatNet.from_filename("nets/net_approval.json")
rt = PetriNetRuntime.from_schema(net.to_schema(), guards=guards, handlers=handlers)

CLI tools

# Generate a .pyi stub from a module exposing SCHEMA (for IDE autocomplete)
petrus-cli gen-stub myapp.nets -o nets/__init__.pyi

# Validate and canonically format net JSON files in-place (pre-commit friendly)
python -m petrus.cli.format_json --fail-on-change nets/net_*.json

Stub generation formats its output with black; install the cli extra to use it:

uv add "petrus-engine[cli]"

Timed transitions

petrus.timers.TimerManager syncs timer tasks with the net's enabled timed transitions. It is clock- and sleep-agnostic: by default it uses the system UTC clock and asyncio.sleep, and you can inject your own primitives — to control time in tests, or to integrate with a scheduling runtime:

from petrus.timers import TimerManager

tm = TimerManager()  # system UTC clock + asyncio.sleep
tm = TimerManager(now=my_clock, sleep=my_sleep)  # custom primitives

Thank you to Routable

Routable sponsored the development of this library. Working at Routable is an awesome experience, with a developer-first culture that fosters innovation and growth. If you're interested in joining a dynamic team, check out our job opportunities here!

Authors

Metadata

Release files for petrus-engine 0.1.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 petrus-engine 0.1.0
File Size Uploaded Provenance
petrus_engine-0.1.0.tar.gz 73.3 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for petrus-engine 0.1.0
File Interpreter ABI Platform
petrus_engine-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 110.9 kB

Release files / petrus_engine-0.1.0.tar.gz

Download URL petrus_engine-0.1.0.tar.gz
Size 73.3 kB
Tags Source
SHA-256 checksum
How to use checksums
dccfeee55a02c683c74891876342a73a72ed94c5de05dcbd72b0e43c7728bb8b
BLAKE2b-256 checksum
How to use checksums
ef5b157c32f047c10074f06cbfe75cd72fe00a0800bf1d3a0b4907b0c247205a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.19 {"installer":{"name":"uv","version":"0.11.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / petrus_engine-0.1.0-py3-none-any.whl

Download URL petrus_engine-0.1.0-py3-none-any.whl
Size 37.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
8706d1ce8dba160b973ee7505c0d4f1725e83d39444ec06e521d53939f14f577
BLAKE2b-256 checksum
How to use checksums
13050bd55c144317ccd8d63fd2af94cae6fa582e59617c8e83ead11e2b766dd5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.19 {"installer":{"name":"uv","version":"0.11.19","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Security for petrus-engine 0.1.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.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files No provenance

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