Skip to main content

Runner for Object-flow Programming Language workflows.

Project description

ofplang run

CI PyPI

A runner for Object-flow Programming Language v0 — a YAML-based dataflow workflow IR with linear Object tracking. The language is defined in the ofplang/spec repository.

The runner drives an ofplang v0 workflow to completion against an execution backend, emitting an execution status document (spec §6/§7) as it progresses and routing typed view values through the workflow. It runs on a simulator — a simulated physical backend — so a full workflow can be exercised end to end without real hardware; the same dispatch contract targets real hardware later.

Status: the simulator, the runner, and a typed (dummy) value layer are implemented.

  • Simulator (ofplang.run.simulator) — a physical backend: devices, spots, transporters, and timed operations advanced on a virtual clock. It validates every dispatch (an inconsistent plan is rejected), models timed device up/down and injected operation failure, and at completion produces each operation's output view values via a device model (the built-in default_device_model fills type defaults and carries Object outputs through from their objects.map inputs; a custom / real model computes them).
  • Runner (ofplang.run.runner) — two ways to drive a backend:
    • replay runs a given execution plan (spec §6) on the backend verbatim.
    • run is a rolling-horizon loop: it calls ofplang.schedule each tick, dispatches the work that can start now, advances the clock, and polls — replanning from the committed history as it goes. It re-routes around a downed device, polls at a fixed interval with completion-time estimation, absorbs duration variance (an operation running longer or shorter than planned), and stops the whole run if any activity fails (marking the abandoned work cancelled). Device up/down, operation failure, and duration variance are scenario concerns injected from Python (not CLI flags).
  • Value layer — the runner resolves each port's type and view schema (§7), routes typed view values along the workflow's arcs (producer output → consumer input, across nested composites), contract-checks them, and assembles the whole-workflow outputs. A caller supplies the whole-workflow I/O as a single run boundary (--boundary): one document with a per-port {spot, view} descriptor — spot places a boundary Object (§6.8), view supplies an input value — for the workflow's entry inputs and final outputs. Unsupplied entry views default. A workflow-embedded static literal (bind: {port: {value: …}}, §11) is seeded as that consumer input's value in place of a default. At run end the produced output views are echoed back into a result boundary of the same schema (--boundary-out). Non-script values are typed but still dummy — a real device backend plugs into the same seam later.
  • Python script processes (spec §22, python_script_processes) — an atomic Pure-Data process may carry a script: {language: python, code: …} section. The built-in device model runs it: the input port values are bound as locals, the code returns a mapping of the declared outputs, and those become the operation's computed output values — the first genuine (non-dummy) computation in the value layer. A script that raises, returns the wrong output names, or returns a non-conformant value fails runtime verification (§22.2) and stops the run gracefully like any other activity failure (the failed activity is marked failed, its unstarted successors cancelled, exit 1). The script runs inline in real time but advances no simulation time; its outputs appear when the operation completes at its end, and the environment mode's duration is the scheduler's estimate of the compute cost. Scripts run with full Python builtins and no import restriction (§22.3 permits an implementation to restrict these; this one does not).
  • Contracts (spec §9) — an atomic process may declare contracts with requires (preconditions over inputs.*.view) and ensures (postconditions over inputs.*.view and outputs.*.view). The runner evaluates them at runtime against the actual view values: requires before the operation runs (a violation stops it before dispatch), ensures after it completes. An atomic requires that references only run/graph-phase inputs (§5.6) is knowable at run start, so it is checked there as a preflight — before any work is dispatched — rather than waiting for that (possibly late) operation. A violation — or a runtime evaluation error — stops the run gracefully like any activity failure (failed + downstream cancelled, exit 1). Static / graph-time contract checking (a fully-constant contract that is statically false, type errors, bad references) is ofplang-validate's job and is not repeated here. Contracts are checked on atomic processes and on the top-level entry composite (main): the entry composite's requires is evaluated at run start over the whole-workflow inputs (a violation stops the run before any work runs) and its ensures at run end over the whole-workflow inputs and outputs (a violation marks the completed run failed). Nested composite contracts are checked too, at each composite invocation's value boundary: its requires once its inputs are available (for an input fed by an upstream process this is mid-run, before the composite's body runs) and its ensures once its outputs are, a violation stopping the run gracefully at the composite boundary (its not-yet-run body cancelled). Because non-script process outputs are still typed defaults, ensures bites mainly on script processes and boundary-supplied inputs until a real device backend computes physical outputs.
  • Failure observability — when a run stops (an injected activity failure, a script error, or a contract violation), the reason is exposed as a structured RollingRunner.failure (a machine-readable kind code, e.g. contract_requires / script_error, plus a human-readable detail, the subject, and the time), and the CLI prints it to stderr. The status document itself stays a valid §6 document (the reason is out of band). An optional contract_observer callback is invoked for every contract check (held or violated) — a trace hook for debugging.
  • Static view values (spec §7.4) — a type whose view field declares a value: fixes that field to a constant for every value of the type. The runner projects it onto every view record it routes, so a Python script reading the field and a contract referencing it both see the static value (not a runtime default). A value that carries a conflicting one is forced to the static value.

Install

pip install ofplang-run

Requires Python 3.10+. Runtime dependencies (pulled in automatically) are PyYAML, the sibling ofplang-schedule that run (rolling-horizon) calls each tick, and ofplang-validate used by the CLI front door. The runner library never imports validate (and the per-tick replans never re-validate), so it stays a one-shot CLI front door.

For development, install editable with the test extra from a clone:

pip install -e ".[test]"

Command line

ofp-run run <workflow> --env <env>
    [--boundary DOC] [--boundary-out FILE]
    [--poll-interval D] [--margin M] [--seed N] [-o OUT]
ofp-run replay <plan> --env <env> [-o OUT]

run drives a v0 workflow to completion by replanning as it goes: each tick it renders the committed history as a status, calls the scheduler, and dispatches the newly-runnable work. --boundary supplies the whole-workflow I/O as one document — a boundary: mapping with a {spot, view} descriptor per entry input / final output port. spot places a boundary Object on an environment spot (spec §6.8; Object ports only); view supplies an input's view value (unsupplied entry views default). The runner projects it into the scheduler's interface (spots only, so the scheduler stays value-independent) and the seeded input values. --boundary-out writes the result boundary — the same schema with each produced output's view filled in — a run-local artifact, separate from the value-free status document. On completion each pinned Object output is checked to have reached its declared spot. --poll-interval sets the fixed polling interval (default 1). replay runs a plan produced by ofp-schedule verbatim on the simulator (no value layer). Both write the final execution status as YAML (-o, else stdout). Exit codes: 0 success, 1 execution failed (an activity failed, or a replan is infeasible), 2 usage/input error.

This tool is also intended to be exposed as the run subcommand of the umbrella ofp CLI (a separate repository in the ofplang organization).

The package lives under the ofplang PEP 420 namespace (ofplang.run), shared across the organization's tools.

Tests

pytest

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

ofplang_run-0.1.1.tar.gz (137.3 kB view details)

Uploaded Source

Built Distribution

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

ofplang_run-0.1.1-py3-none-any.whl (74.3 kB view details)

Uploaded Python 3

File details

Details for the file ofplang_run-0.1.1.tar.gz.

File metadata

  • Download URL: ofplang_run-0.1.1.tar.gz
  • Upload date:
  • Size: 137.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for ofplang_run-0.1.1.tar.gz
Algorithm Hash digest
SHA256 237e3a0615298e055f0c6f8e2c8d094c6a2194d2428f8ad30c79aa497d030af2
MD5 8df938947be3727a2c1384361c035959
BLAKE2b-256 50f58c7d774253dcfdbc08aba313961005686c9686b4de84dd945a71561cfd9f

See more details on using hashes here.

Provenance

The following attestation bundles were made for ofplang_run-0.1.1.tar.gz:

Publisher: publish.yml on ofplang/run

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

File details

Details for the file ofplang_run-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: ofplang_run-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 74.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for ofplang_run-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 01507414e621aa64a07d45ffce40ac0841dd81bd6c86dbb1f8d65a3fa7b51eab
MD5 f04e1c90bfaf9490a61049bb22d8c68e
BLAKE2b-256 ccb95dae097b4c2dbda292db0a31a01f001112d2038a62833ab6d259eea26376

See more details on using hashes here.

Provenance

The following attestation bundles were made for ofplang_run-0.1.1-py3-none-any.whl:

Publisher: publish.yml on ofplang/run

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