Skip to content

feat(cli): export one JSON Schema for v1 and v2 model files - #901

Open
Mearman wants to merge 9 commits into
pywr:mainfrom
Nexsys-Analytics:feat/schema-union-export
Open

Mearman wants to merge 9 commits into
pywr:mainfrom
Nexsys-Analytics:feat/schema-union-export

Conversation

@Mearman

@Mearman Mearman commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

Adds pywr-cli export-schema --union, which writes one JSON Schema that accepts a Pywr v1 model, a v1 multi-model, a v2 model or a v2 multi-network model. The four formats are told apart by their identifying top-level key (nodes, models, network, networks), and each side's definitions sit under a v1_ or v2_ prefix so shared names such as Node and Parameter do not collide. Without the flag the output is unchanged.

The branch is chosen with if/then on the identifying key, so a document that fails reports the errors of its own kind (a v2 model missing timestepper says so) instead of a single "not valid under any of the given schemas". A document with none of the keys, or with two of them, is rejected. pywr_model_schema returns a Result with JsonSchemaError instead of panicking.

The v1 half uses the json_schema module added to pywr-v1-schema in pywr/pywr-v1-schema#300, which first shipped in 0.25.1, so the workspace requirement is raised to 0.25.1 ("0.25" would still admit 0.25.0, which lacks the module) and the lockfile resolves it from crates.io. #900, the derives for the multi-network types, is already in this branch's base.

Against the published crate, the union accepts every v1 and v2 model in the test directories through its own branch only, and rejects documents with no identifying key, two of them, a mistyped field or a bad v1 edge. The tests assert those rejections, and renaming the branch $ref key, dropping the forbidden sibling keys or pointing a branch at the wrong root each fail one. The default export-schema output is byte-identical to main.

One commit adds a workflow that attaches pywr-v2.schema.json and the union pywr.schema.json to a published release (re-runs replace the assets). It has been run on a fork release, not here, so please drop it if a release-asset step is not wanted.

export-schema --union combines the Pywr v1 schema, generated by pywr-v1-schema, with the v2
model and multi-network schemas. Each version's definitions are namespaced and the document kind
is selected by its identifying property: nodes, models, network or networks.
Every v2 model, including the multi-network ones, and every v1 conversion input must validate,
and a document that mixes the v1 and v2 identifying properties, or has none, must be rejected.
A new workflow exports the v2 schema and the combined v1 and v2 schema with pywr-cli and uploads
them to the release that was published, so that each version has its schemas at a stable URL.
pywr_model_schema returns a Result with a JsonSchemaError instead of panicking when a schema
generator produces an unexpected shape, and the CLI reports it with context.

Both v2 document types are generated by one SchemaGenerator, so they share a single definition
namespace and cannot number a clashing definition name differently. Root definitions are named
from JsonSchema::schema_name rather than from the schema's title, which a doc comment heading or
a schemars attribute can change.

The help text of --union now says what the default export covers and how v1 custom types are
treated.
…hema

The union selected its document kind with a oneOf over four alternatives, so any invalid document
failed with a bare "not valid under any of the given schemas" and the whole document echoed back.
The kind is now chosen by an `if`/`then` on its identifying property, with a oneOf of bare
`required` clauses enforcing that exactly one of them is present. The set of accepted documents is
unchanged, and a document with a missing or mistyped field reports that field.

The tests now reject invalid documents: none or two identifying properties, a missing `time` or
`timestepper`, mistyped fields, an unknown v2 node type and a bad v1 edge. Each of the schema's
parts is needed by one of them. A further test compares the v2 half of the union with the
standalone v2 schema.
gh release upload fails on an asset that already exists, so re-running the job on a release
failed. With --clobber the assets are replaced.
CI builds with --locked, which fails when the lock file lacks the entries for a dependency the
manifest declares.
@Mearman
Mearman marked this pull request as ready for review October 17, 2026 04:54
@Mearman

Mearman commented Oct 17, 2026

Copy link
Copy Markdown
Contributor Author

@jetuk this exports one JSON Schema for v1 and v2 model files (pywr-cli export-schema --union). It needs pywr-v1-schema 0.25.1 from crates.io, and CI is green. Could you take a look when you have time? The release-asset workflow commit is optional, so drop it if you'd rather not carry it.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant