Add a Config Field#
Every TOML knob in HydroModPy is backed by a Pydantic v2 model with
ConfigDict(extra="forbid"). This page describes how to add a new
field to an existing section, or how to add a brand-new section.
Find the right model#
Sections live close to the package they configure:
TOML section |
Pydantic model |
File |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Pydantic invariants#
Every model in HydroModPy must:
inherit from
HydroModelBase(or a model that does);declare
model_config = ConfigDict(extra="forbid");use
Annotatedfor unit-bearing fields (see below);carry a
Profileannotation on every field;ship a
Field(..., description="...")and at least one example for documented fields.
Pick a unit type#
Quantitative fields use the unit aliases declared in
hydromodpy/core/units/types.py:
Alias |
Canonical unit |
Use for |
|---|---|---|
|
m |
Lengths, distances, depths |
|
m² |
Surfaces |
|
m³ |
Volumes |
|
s |
Durations |
|
m³/s |
Discharges |
|
m/s |
Fluxes, recharge rates |
|
m/s |
K |
|
1/m |
Ss |
|
dimensionless |
Sy |
|
dimensionless |
Pure ratios |
Bare numbers are interpreted in the canonical SI unit; users can also
pass strings such as "50 m" or "0.36 m/h" and Pydantic will
auto-convert.
Pick a Profile#
hydromodpy/core/config_kit/profile.py declares three visibility
levels:
class Profile(IntEnum):
USER = 1 # hydrogeologist: physics, paths, project I/O
DEV = 2 # developer: tolerances, backends, cache
EXPERT = 3 # MODFLOW / Boussinesq / pint internals
Default to Profile.USER. Demote to DEV or EXPERT only
when the field is genuinely irrelevant for non-developer users.
Template generation, JSON Schema export, and frontend forms all respect the chosen Profile.
Add a field to an existing section#
# hydromodpy/physics/flow/flow_config.py
from typing import Annotated
from pydantic import Field
from hydromodpy.core.config_kit.profile import Profile
from hydromodpy.core.units import HydraulicConductivity
class FlowConfig(ProcessSpatialConfig):
# ... existing fields ...
k_aquifer: Annotated[HydraulicConductivity, Profile.USER] = Field(
default=1e-5,
description="Aquifer hydraulic conductivity (canonical: m/s).",
examples=[1e-4, "0.36 m/h"],
)
In TOML, both forms work:
[flow]
k_aquifer = 1e-4 # interpreted as m/s
# or
k_aquifer = "0.36 m/h" # auto-converted to m/s
Tracked input files#
If the field carries a path, annotate it with InputFile from
hydromodpy/core/tracking/input_file.py:
from hydromodpy.core.tracking.input_file import InputFile
dem_path: Annotated[Path, InputFile(role="dem", category="data", portable=True)] = ...
The reproducibility manifest will list the file, its canonical path, and its SHA-256 automatically.
Cross-field validators#
Use @field_validator(mode="before") for normalisation
(parse-then-validate) and @model_validator(mode="after") for
cross-field invariants. Keep them small and explicit.
Add a brand-new section#
Create the Pydantic model in the appropriate package.
Add the field to
HydroModPyConfiginhydromodpy/config/hydromodpy_config.py(typically asAnnotated[NewConfig | None, Profile.USER] = None).If a launcher should dispatch on the new section, wire it through
hydromodpy/cli/workflows.py(or the equivalent dispatcher).Refresh the JSON Schema export with
hmp schema export --output ./schema/and commit the diff if the project pins generated artefacts.
Tests to add#
Unit under
tests/unit/config/for accept / reject cases (extra fields rejected, units parsed, validators raised on bad combos).Integration if the field changes the dispatched workflow.
Run hmp config check <toml> to validate any candidate TOML
against the new model.
Pitfalls flagged by the layer matrix#
The Pydantic model lives in the same layer as the package it configures. Do not move it to
config/:config/is the root composition only.schema/andconfig/may both import any other layer; new cross-edges should still be justified.Generated TOML templates and JSON Schema exports must stay in sync with the source models. Re-run the export after every field addition.
See also#
config for the configuration root.
core for
Profile, units, and tracking helpers.Build a Frontend if your field powers a UI widget.
Configuration overview for the user-facing TOML reference (auto-generated from these models).