Tip
Need help? Please let us know in the SUEWS Community.
Please report issues with the manual on GitHub Issues (or use Report Issue for This Page for page-specific feedback).
Please cite SUEWS with proper information from our Zenodo page.
Schema Development Documentation#
Note
This page is for developers working on the SUEWS data model. Users should refer to YAML Configuration Schema Versioning for the user-facing policy and to Transitioning to YAML-based Configuration for YAML upgrade paths.
Schema Versioning Basics#
Schema labels are CalVer (
YYYY.M), aligned with the SUEWS release in which each shape first shipped. The current label lives inCURRENT_SCHEMA_VERSIONinsrc/supy/data_model/schema/version.py.SUEWS model versions (for example
2026.4.3) track code; schema versions track the YAML structure. One schema usually spans several SUEWS releases.The registry in
src/supy/util/converter/yaml_upgrade.py::_HANDLERSis the single source of truth for compatibility:is_schema_compatible(old, current)returnsTrueiff(old, current)has a registered handler (or the labels match). There is no separate compatibility table (gh#1304).
When a Schema Bump Is Required#
Bump when a PR touches src/supy/data_model/ in a way that prevents
a previously valid YAML from round-tripping:
Rename a public field (for example
DeepSoilTemperature→AnnualMeanAirTemperature).Remove a public field (for example
MinimumVolumeOfDHWinUsedropped in #1242).Change a public field’s type or shape (scalar → profile dict; make a previously optional field required).
Add a required field without a sensible default.
Restructure a nested section (split, merge, or re-key).
Tighten an enum or literal so a previously accepted value is now rejected.
Do not bump for:
Adding an
Optionalfield with a sensible default.Adding an output variable under
src/supy/data_model/output/.Validator rule tightening that rejects scientifically wrong but structurally valid YAMLs (the shape is unchanged).
Internal refactors that leave the YAML surface identical.
Bump Procedure#
When a bump is required, touch every item below in the same PR. The
definitive checklist is in
.claude/rules/python/schema-versioning.md.
Edit
src/supy/data_model/schema/version.py: setCURRENT_SCHEMA_VERSIONto the next CalVer label (shortest form, for example"2026.5"), and add aSCHEMA_VERSIONSentry describing precisely what changed, with issue / PR links.Bump
schema_versioninsrc/supy/sample_data/sample_config.ymlto match.Register a handler in
src/supy/util/converter/yaml_upgrade.py::_HANDLERSkeyed by(previous_schema, new_schema). Express deltas through the rename / drop tables plus any bespoke reshaping. Every drop must carry areasonso Pydantic’sextra="ignore"does not silently swallow the user’s value.Vendor a fixture at
test/fixtures/release_configs/<release-tag>.ymlcapturing the outgoing shape.test_release_compat.pypicks it up automatically via_PACKAGE_TO_SCHEMA.If the bump rides a formal release, add the release tag → schema mapping in
src/supy/util/converter/yaml_upgrade.py::_PACKAGE_TO_SCHEMA.Sync user-facing documentation: update YAML Configuration Schema Versioning (version history and illustrative labels), add a per-release entry in Transitioning to YAML-based Configuration (rename/drop summary + the
suews schema migratecommand), and if a release is involved, note the migration chain in the matchingdocs/source/version-history/v<release>.rst.
Audit Gates#
Two automated gates defend the invariant that a schema bump lands with everything it needs:
- CI workflow: schema-version-audit
.github/workflows/schema-version-audit.ymlruns on every PR that touchessrc/supy/data_model/**,src/supy/sample_data/sample_config.yml, or the schema documentation. It invokesscripts/lint/check_schema_version_bump.py, which fails if either (a) the data model changed butCURRENT_SCHEMA_VERSIONdid not, or (b)CURRENT_SCHEMA_VERSIONmoved but neitherdocs/source/contributing/schema/schema_versioning.rstnordocs/source/inputs/transition_guide.rstwas touched.- Bypass label: 0-ci:schema-audit-ok
For genuinely cosmetic diffs (docstring edits, comment reformatting, non-structural
sample_config.ymltweaks) a maintainer can attach the0-ci:schema-audit-oklabel to the PR. The workflow reads labels before running and short-circuits when the label is present. Contributors should not add the label themselves — the failure message is the prompt to open a review conversation.
The prep-release and audit-pr skills encode the same
checklist so a release or a review-in-progress cannot silently drift
past a missing bump.
Schema Management Commands#
For developers, the suews schema command exposes schema
management operations:
suews schema info # Display schema information
suews schema version files/*.yml # Check schema versions
suews schema migrate old.yml # Migrate between versions
suews schema export # Export JSON Schema
See Schema Management CLI for the full command reference.
Generating JSON Schema#
JSON Schema files can be generated from the Pydantic models for IDE autocomplete and external validation. The authoritative validation is always performed by the Pydantic models at runtime.
Generate locally:
python .github/scripts/generate_schema.py
Python API#
from supy.data_model import SUEWSConfig
# Generate JSON Schema from the Pydantic model
schema = SUEWSConfig.model_json_schema()
# Migrate between versions via the registered handler chain
from supy.data_model.schema.migration import SchemaMigrator
migrator = SchemaMigrator()
upgraded = migrator.migrate(old_config, to_version="2026.4")
Implementation Map#
src/supy/data_model/schema/— schema version registry and compatibility helpers.src/supy/data_model/schema/migration.py—SchemaMigratorthat consults the handler registry.src/supy/util/converter/yaml_upgrade.py— migration handlers and therelease-tag → schemamapping.src/supy/util/converter/__init__.py— unifiedsuews-convertentry point covering both legacy table conversion and schema migration.src/supy/cmd/schema_cli.py—suews schemaCLI entry point.