pintext.pydantic#
The pydantic integration (pydantic v2). Requires the pydantic extra:
python -m pip install "pintext[pydantic]"
See also
- class pintext.pydantic.Units(units=None, *, convert=False)[source]#
Pydantic annotation turning a field into a Pint quantity.
Use it as
Annotatedmetadata:radius: Annotated[pint.Quantity, Units(ureg.m)]This is the spelling static type checkers understand.
quantity()is a more concise equivalent, at the cost of being a function call in an annotation, which type checkers reject.- Parameters:
units (
Unit|UnitGenerator|str|None) – Units attached to the field. AUnitGenerator(e.g. obtained fromUnitContext.deferred()) defers unit evaluation to validation time, which makes unit contexts apply. Strings are interpreted using the registry returned byget_unit_registry(). IfNone, any quantity is accepted, no default units are applied and no compatibility check is performed.convert (
bool) – IfTrue, quantities are converted tounitsinstead of being passed through unchanged.
- pintext.pydantic.quantity(units, *, convert=False)[source]#
Build an annotated type for a field holding a Pint quantity with declared units.
Values are interpreted as follows:
mappings and xarray DataArrays are first passed to
to_quantity();strings are parsed by
ensure_units(), which means that those carrying no units are attachedunits;unitless values are attached
units;quantities are checked for unit compatibility with
check_units().
- Parameters:
units (
Unit|UnitGenerator|str) – Units attached to the field. AUnitGenerator(e.g. obtained fromUnitContext.deferred()) defers unit evaluation to validation time, which makes unit contexts effective. Strings are interpreted using the registry returned byget_unit_registry().convert (
bool) – IfTrue, quantities are converted tounitsinstead of being passed through unchanged.
- Return type:
- Returns:
An
Annotatedalias usable as a pydantic field type.
Note
Because this is a function call, static type checkers reject it inside an annotation. Use the equivalent
Unitsspelling (Annotated[pint.Quantity, Units(ureg.m)]) where static checking matters.Examples
>>> from pydantic import BaseModel >>> class Sphere(BaseModel): ... radius: quantity(ureg.m) >>> Sphere(radius=1.0).radius <Quantity(1.0, 'meter')> >>> Sphere(radius={"value": 2.0, "units": "km"}).radius <Quantity(2.0, 'kilometer')>
Incompatible units are rejected:
>>> Sphere(radius=1.0 * ureg.s) Traceback (most recent call last): ... pydantic_core._pydantic_core.ValidationError: ...
Units declared through a unit context are evaluated at validation time:
>>> uctx = UnitContext({"length": ureg.m}) >>> class Sphere(BaseModel): ... radius: quantity(uctx.deferred("length")) >>> with uctx.override(length="km"): ... Sphere(radius=1.0).radius <Quantity(1.0, 'kilometer')>
Serialization round-trips through the mapping form read by
to_quantity():>>> Sphere(radius=1.0).model_dump_json() '{"radius":{"value":1.0,"units":"meter"}}'
- pintext.pydantic.Quantity#
Any Pint quantity. Mappings and xarray DataArrays are interpreted with
to_quantity(); no default units are applied and no compatibility check is performed. A value that cannot be interpreted as a quantity (e.g. barefloat) is rejected.Use
Unitsorquantity()instead when the field has declared units.See also
alias of
Annotated[Quantity, Units(None, convert=False)]