ofplang validate
A validator 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 validator checks that a document is well-formed portable v0: structure and types, the feature model, linear Object tracking, structured nodes, contracts, and scheduling policies. It reports findings as stable error codes rather than free text, so results are easy to consume in tests and tooling.
Install
pip install ofplang-validate
Requires Python 3.10+. The only runtime dependency is PyYAML. For development, install editable with the test extra from a clone:
pip install -e ".[test]"
Command line
ofp-validate <file>... # or: python -m ofplang.validate <file>...
ofp-validate --mode extension-tolerant doc.yaml
ofp-validate --format json doc.yaml
Options: --mode {strict,extension-tolerant}, --format {text,json},
-q/--quiet, --no-color.
Exit codes: 0 all valid, 1 validation errors found, 2 usage/input error.
$ ofp-validate workflow.yaml
workflow.yaml:7:15: error unknown_type processes.main.inputs.x.type unknown type in 'Foo'
1 error in 1 of 1 file
Diagnostics carry a file:line:col source position (an imported fragment's own
file when the problem is inside an $import); --format json includes
file/line/col fields.
A finding is an error or a warning. A warning reports something the specification states as a condition rather than as a rule, so it never makes a document invalid and never changes the exit code:
$ ofp-validate survey.yaml
survey.yaml:9:23: warning array_output_length_not_derivable processes.survey.outputs.hits ...
all valid (1 file), 1 warning
The one warning defined today is array_output_length_not_derivable: an atomic
process's Array output port whose length nothing in the document relates to
its inputs. Spec 1.1 makes its resource bound conditional on there being no
such port.
A port is accounted for by objects.map / objects.transform /
object_identity_map, which relate its length to an input's, or by an
ensures clause that bounds its .view.length from above against something
reachable — an input Array's length, a run phase scalar, a literal, or
arithmetic over those:
contracts:
ensures:
- expr: "outputs.readings.view.length == inputs.plates.view.length"
What a clean run means. No warnings says every Array output is accounted
for, by derivation or by claim — not that a bound is proved. A contract is
checked at run time (spec 9.3), so reading one here trusts it the way spec 14.1
trusts an objects.map. And a warning says this validator can see no bound,
not that none exists: a bound needing algebra to solve for the length, one
stated through another output, or one held by knowledge of the process still
draws it.
This tool is also the validate subcommand of the umbrella ofp CLI
(ofplang), which forwards to it in-process:
ofp validate doc.yaml is the command above, with the same options and the same
exit codes.
Library
from ofplang.validate import validate
result = validate("workflow.yaml", mode="strict")
if not result.ok:
for d in result.diagnostics:
print(d.code, d.path, d.message)
validate(source, *, mode="strict") returns a ValidationResult with .ok and
.diagnostics (each a Diagnostic(code, message, path, file, line, col, severity)). The validator collects all independent findings rather than
stopping at the first; only a YAML parse or $import resolution failure is
terminal.
.ok and .codes look at errors alone, so a document that draws only warnings
is valid. .errors / .warnings split the diagnostics by severity, and
.warning_codes is the warning counterpart of .codes.
source is a path or an already-loaded document (a mapping), so a caller that
builds one in memory — a generator, a notebook, a tool that rewrote a document
before running it — can validate exactly what it holds:
result = validate(document) # the same checks, the same codes
An in-memory document must already be import-expanded (there is no base directory
to resolve a relative $import against — call expand() on the file first), and it
cannot contain a value v0 has no spelling for, such as a datetime; either raises
ValueError. Its diagnostics carry no file:line:col, only path, and no
duplicate_key can arise for it: a mapping holds one value per key.
Expanded document
$import (spec §3) is structural inclusion resolved before any other checks,
so the document that gets validated is the fully expanded one. To obtain that
expanded document — e.g. to hand a downstream tool the exact form it should
schedule or run, instead of re-reading the unexpanded file — use:
from ofplang.validate import validate, expand
# structural expansion only (no validation); raises YamlError on import failure
doc = expand("workflow.yaml")
# validate and get the expanded document in one pass
result = validate("workflow.yaml", mode="extension-tolerant", expand=True)
if result.ok:
run_it(result.document) # exactly what was validated
expand(source, *, base_dir=None) returns the plain-Python document
yaml.safe_load would yield for the resolved tree (fidelity is exact, including
non-string scalar tags). base_dir overrides where the root's relative imports
resolve. validate(..., expand=True) sets ValidationResult.document to that
same value whenever load + $import resolution succeeds (otherwise None).
The package lives under the ofplang PEP 420 namespace (ofplang.validate),
shared across the organization's tools.
Scope
Covers graph-time validation of portable v0. Runtime failures, and run/data-phase
preflight checks, are out of scope (spec §6.2, §25). Two modes are supported:
strict (portable v0) and extension-tolerant (accepts x- extension keys).
v0's seven optional features (spec §4.2) are all checked here, whichever ones the document uses. Whether anything can then act on the document is a separate question: a feature the validator checks may be one the scheduler or the runner does not implement — which §4.1 calls valid v0 but unsupported by that implementation. Their READMEs say which ones they support.
Tests
The behavior is pinned by a spec-derived conformance suite that matches on error codes (see tests/conformance/README.md).
pytest # run everything
OFPLANG_STRICT_TESTS=1 pytest # full contract, no pending escapes
Metadata
Release files for ofplang-validate 0.2.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| ofplang_validate-0.2.2.tar.gz | 210.7 kB | With provenance | Details for ofplang_validate-0.2.2.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| ofplang_validate-0.2.2-py3-none-any.whl | Python 3 | none | any | Details for ofplang_validate-0.2.2-py3-none-any.whl |
Total release size: 337.5 kB
Release files / ofplang_validate-0.2.2.tar.gz
| Download URL | ofplang_validate-0.2.2.tar.gz |
|---|---|
| Size | 210.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
1d4e499e0aa44b654f92a7c4e464cc374d2114c246eb6788a4daae3eb5974688
|
|
BLAKE2b-256 checksum How to use checksums |
ac0489515412ce709c233af2642e4fadd37b83abdf635e9a266d57f849d308a3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 19, 2026.
Transparency logRelease files / ofplang_validate-0.2.2-py3-none-any.whl
| Download URL | ofplang_validate-0.2.2-py3-none-any.whl |
|---|---|
| Size | 126.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
090b8008e6494bc036bef1d68b4483a76e6932f1a30940b3b95391f2e909c3a0
|
|
BLAKE2b-256 checksum How to use checksums |
6b74dfc71c86de35960f63d9118f4e54d8d55328355164782f2d070905610259
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 19, 2026.
Transparency logSecurity for ofplang-validate 0.2.2
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.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for ofplang_validate-0.2.2.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 19, 2026.
Transparency logA 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.