Skip to main content

Determa State — Python reference implementation of the Determa statechart engine

Project description

determa-state

Reference implementation (Python) of the Determa State statechart engine.

The normative SPEC.md, the JSON Schema for machine YAML, and the cross-language conformance suite live in the spec repo. This repository implements that spec in Python and is correct iff it passes the conformance suite.

Implements the Determa State spec v0.0.6 (early alpha; all Determa State repos share one synchronized version).

Status: passing the full conformance suite — all 31 engine cases (conformance/0131) plus conformance/cli/0103. Implements YAML 1.2 loading

  • validation, the full statechart semantics (RTC dispatch, hierarchy, orthogonal regions + done, shallow/deep history, choice pseudostates, submachine states, esvs, CEL guards, structured actions, active objects + bus, defer, timers, faults), static contracts, snapshot round-trip + safe-point migration, Mermaid export, and the §13 CLI. Built up the build order in issue #3.

Conformance suite

The cross-language conformance suite is the single source of truth for correctness; this repository is correct iff it passes it. The suite lives in fruwehq/determa-state-conformance; the test harness fetches it at the matching release tag (v0.0.6) into a gitignored .cache/ — no git submodule. The normative SPEC.md and JSON Schema live in fruwehq/determa-state-spec; the schema-drift test fetches the schema at the same tag.

For offline work, point the harness at a local checkout:

export DETERMA_CONFORMANCE_DIR=/path/to/determa-state-conformance   # the suite
export DETERMA_SPEC_DIR=/path/to/determa-state-spec                        # the schema (optional)

Scope (per the spec)

  • Load and validate machine YAML against schema/machine.schema.json, parsed under the YAML 1.2 core schema (only true/false are booleans).
  • Execute statecharts per SPEC.md: run-to-completion; hierarchy; orthogonal regions (+ done); shallow/deep history; initial transitions; esvs (extended-state variables declared in states, hierarchical) including external esvs + the env event and refresh; defer (deferred-set, edge-triggered); timers via an injected clock; active-object spawning; publish (directed / by subscription / scoped); and faults (the error event).
  • Guards in CEL (e.g. cel-python); structured actions (assign/publish/refresh/spawn/stop) with CEL values.
  • Adapters — bus / queue / clock / store / observer (SPEC §8), each with a simple in-memory default for tests.
  • An export command that renders a machine (and an instance's current state_config) to Mermaid stateDiagram-v2 (SPEC §12), behind a pluggable exporter interface so more formats (PlantUML, SCXML, …) can be added later.
  • A test harness that runs the upstream conformance cases against this engine.

Use as a library

The CLI (determa-state …) is a thin wrapper over a programmatic API; an engine can be embedded in a host program without the CLI or the file-backed store (SPEC §2):

import determa.state as ds

defs = ds.load_definitions(open("gate.yaml").read())
ds.validate(defs[0].raw)                     # raises ValidationError if invalid

host = ds.Host()
host.register_all(defs)
inst = host.create_root(host.machines["gate"], "g1", external={"fare": 50})
host.run_to_quiescence()

host.deliver("g1", "coin", {"amount": 100})     # typed event; False if rejected
host.run_to_quiescence()
assert inst.active_leaf_names() == ["unlocked"]
assert inst.resolved_esvs()["fare"] == 50
assert inst.status is ds.Status.ACTIVE

host.advance("30s")                             # virtual clock
snaps = host.snapshot_all()                     # persist / round-trip (§8)
host.restore_all(snaps)

load_definitions also accepts a native mapping (or a list of them for a multi-document machine) instead of YAML text, so a host can build machines in code without serializing — through the same validate() path:

import determa.state as ds

gate = {
    "id": "gate",
    "events": {"coin": {"payload": {"amount": {"type": "int", "required": True}}}},
    "top": {
        "esvs": {"fare": {"type": "int", "external": True}},
        "initial": {"transition_to": "locked"},
        "states": {
            "locked": {"on_events": {"coin": {"transition_to": "unlocked",
                                              "guard": "event.payload.amount >= fare"}}},
            "unlocked": {"on_events": {"push": {"transition_to": "locked"}}},
        },
    },
}

defs = ds.load_definitions(gate)                 # dict, not a YAML string
host = ds.Host()
host.register_all(defs)
inst = host.create_root(host.machines["gate"], "g1", external={"fare": 50})
host.run_to_quiescence()

The public surface is everything exported from the determa.state package (determa.state.__all__): Host, Instance, Definition, Machine, Status, Event, load_definitions / load_definition, validate / collect_errors, and the error types. See tests/test_library_api.py.

Observing transitions (SPEC §8)

Pass an observer — a passive callback invoked once per RTC step (automatic or manual) with { instance, event, transition, entered, exited, published, spawned, faulted }. Built-ins: JsonlObserver(stream) (a drop-in transition log) and CollectingObserver (records to a list).

import sys
import determa.state as ds
host = ds.Host(observer=ds.JsonlObserver(sys.stdout))  # one JSON line per step

The Observer is domain observability (what the machine did). For operational diagnostics the engine also emits standard-library logging under the determa.state logger (dispatch/transition at DEBUG, faults/dead-letter at WARNING). It is silent by default (a NullHandler is attached); enable it from the host app:

import logging
logging.basicConfig(level=logging.DEBUG)   # or logging.getLogger("determa.state").setLevel(...)

Layout

  • src/determa/state/ — the package.
  • tests/ — the implementation's own unit tests (hermetic, offline).
  • conformance/ — the harness that runs the external conformance suite black-box against this implementation (kept separate from the unit tests).

Develop

python -m venv .venv && . .venv/bin/activate
pip install -e '.[dev]'

make check        # ruff + mypy + unit tests (hermetic, offline) — the PR gate
make conformance  # download & run the language-agnostic conformance suite

Equivalently: pytest runs the unit tests only; pytest conformance runs the conformance suite (it fetches determa-state-conformance into .cache/ on first run — set DETERMA_CONFORMANCE_DIR to use a local checkout offline). The two are separate: unit tests never touch the network; conformance is opt-in.

License

MIT — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

determa_state-0.0.6.tar.gz (59.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

determa_state-0.0.6-py3-none-any.whl (47.7 kB view details)

Uploaded Python 3

File details

Details for the file determa_state-0.0.6.tar.gz.

File metadata

  • Download URL: determa_state-0.0.6.tar.gz
  • Upload date:
  • Size: 59.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for determa_state-0.0.6.tar.gz
Algorithm Hash digest
SHA256 e545b7545a14dd0c72f2aaf394f34288396f492528d57dae3a947a62c14cd87a
MD5 e12069ddf6047735db8ca52cae5eecb2
BLAKE2b-256 907d2cf0b787bc8915984b8cc7fe65b7e51c955709f4292678a0fce070b53d68

See more details on using hashes here.

Provenance

The following attestation bundles were made for determa_state-0.0.6.tar.gz:

Publisher: release.yml on fruwehq/determa-state-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file determa_state-0.0.6-py3-none-any.whl.

File metadata

  • Download URL: determa_state-0.0.6-py3-none-any.whl
  • Upload date:
  • Size: 47.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for determa_state-0.0.6-py3-none-any.whl
Algorithm Hash digest
SHA256 e7c54a47a6319b0d1d3bbc9d89b5113347269bb7acea59c6888f0dd350e31513
MD5 379a4a3f9597c98504913d3446d984ca
BLAKE2b-256 3077b53f5919938bdfa5bf40cd39df278a1c5ceb9719c221b98c7b512577af9c

See more details on using hashes here.

Provenance

The following attestation bundles were made for determa_state-0.0.6-py3-none-any.whl:

Publisher: release.yml on fruwehq/determa-state-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page