pintext#
The core API depends on Pint alone.
Unit contexts#
- class pintext.UnitGenerator(units)[source]#
A callable object which returns units objects. Stored units can be contextually overridden using the
override()method.Examples
>>> ugen = UnitGenerator(ureg.m) >>> ugen() <Unit('meter')>
Stored units can be modified, including temporarily:
>>> with ugen.override(ureg.km): ... ugen() <Unit('kilometer')> >>> ugen() <Unit('meter')>
See also
- override(units)[source]#
Temporarily override the value of
units. The initial value ofunitsis restored upon leaving context.- Parameters:
units (
Unit|Callable[[],Unit] |str) – Temporary replacement forunits. String values are interpreted based on the unit registry of currently stored units.- Return type:
Note
This context manager mutates the generator in-place and is therefore not thread-safe.
- class pintext.UnitContext(registry=<factory>, interpret_str=False, ureg=None, key_converter=<function identity>)[source]#
An overridable registry of
UnitGeneratorobjects.This class maintains a registry of
UnitGeneratorinstances. StoredUnitGeneratorobjects can be conveniently overridden using theoverride()context manager.- Parameters:
registry (
dict[Hashable,UnitGenerator|Unit|str]) –Unit generator registry. Keys can be any hashable type, but
strorEnumare recommended. Defaults to an empty dictionary.Note
The initialization sequence will make repeated calls to
register()and will consequently apply the same key and value conversion rules.interpret_str (
bool) – IfTrue, attempt string-to-units interpretation when specifying unit generators asstr. Defaults toFalse.ureg (
UnitRegistry|None) – Unit registry used for string-to-units interpretation. IfNone, the default registry is used (seeget_unit_registry()).key_converter (
Callable[[Hashable],Hashable]) – Converter used for keys. Defaults to a no-op.
- deferred(key)[source]#
Return the
UnitGeneratorregistered with a given key.- Parameters:
key (
Hashable) – Key to theUnitGeneratorto return. Thekey_converteris applied.- Return type:
- Returns:
Unit generator.
- get(key)[source]#
Evaluate
UnitGeneratorinstance registered askey.- Parameters:
key (
Hashable) – Key to theUnitGeneratorto evaluate. Thekey_converteris applied.- Return type:
- Returns:
Evaluated units.
- get_all()[source]#
Evaluate all registered
UnitGeneratorinstance.
- override(*args, **kwargs)[source]#
Temporarily override underlying unit generators. This method acts as a convenience proxy for
UnitGenerator.override().Override specifications can take multiple forms:
an arbitrary number of dictionaries can be passed as positional arguments;
key-value pairs may also be specified as keyword arguments.
Both approaches can be mixed.
Note
When using the keyword argument specification, passed values will systematically be strings. Consequently, either
registry keys must be strings;
or the
key_convertermust provide the conversion protocol for string-valued keys.
- register(key, value)[source]#
Add or update an entry in the registry. Conversion rules are applied as follows:
keyis applied thekey_converterconverter;valueis converted to aUnitGenerator.
In addition, if
interpret_strisTrue,valuecan be specified as a string. In that case, it will be converted to apint.Unitusing the unit registry returned byget_unit_registry().- Parameters:
key (
Hashable) – Key to the registered entry.value (
UnitGenerator|Unit|str) – Object to register.
- Return type:
- update(d)[source]#
Update the registry with a dictionary.
- Parameters:
d (
dict) – Dictionary used to applyregister()for each of its key-value pairs.- Return type:
- ureg: UnitRegistry | None#
Unit registry used for string-to-units interpretation.
Unit registry#
- pintext.get_unit_registry()[source]#
Get the default unit registry. By default, Pintext uses the application registry.
- Return type:
- Returns:
The registry currently used as a default by Pintext.
- pintext.set_unit_registry(ureg)[source]#
Set the default unit registry. By default, Pintext uses the application registry.
- Parameters:
ureg (
UnitRegistry|ApplicationRegistry) – Unit registry.- Raises:
TypeErrorifuregis not apint.UnitRegistry.- Return type:
Converters#
- pintext.ensure_units(maybe_value=NOTHING, *, default_units, convert=False)[source]#
Ensure that a value is wrapped in a Pint quantity container.
This converter can be used in two modes:
Immediate mode: Pass a value to convert it directly.
Deferred mode: Omit the value to get a converter function.
- Parameters:
maybe_value (
Any) – Value to ensure the wrapping of. If not supplied, this function returns a converter with the signaturef(x: Any) -> Anythat is effectivelyfunctools.partial(ensure_units, default_units=default_units, convert=convert).default_units (
Unit|Callable[[],Unit]) – Units to use to initialize thepint.Quantityifmaybe_valueis not apint.Quantity. A callable can be passed; in this case, the applied units will bedefault_units().convert (
bool) – IfTrue,maybe_valuewill also be converted todefault_unitsif it is apint.Quantity.
- Return type:
- Returns:
Converted
maybe_valueif specified; otherwise, a converter function.- Raises:
pint.UndefinedUnitError – If
maybe_valueis a string Pint cannot parse.
Examples
Immediate mode. Convert a value directly:
>>> ensure_units(100.0, default_units=ureg.m) <Quantity(100.0, 'meter')>
By default, quantities with units are passed through unchanged:
>>> ensure_units(100.0 * ureg.km, default_units=ureg.m) <Quantity(100.0, 'kilometer')>
Set
convert=Trueto force conversion to the default units:>>> ensure_units(100.0 * ureg.km, default_units=ureg.m, convert=True) <Quantity(100000.0, 'meter')>
Strings are parsed by the default registry; those that carry no units are treated as unitless values:
>>> ensure_units("2 m", default_units=ureg.km) <Quantity(2, 'meter')> >>> ensure_units("2", default_units=ureg.km) <Quantity(2, 'kilometer')>
Deferred mode: Create a converter function:
>>> converter = ensure_units(default_units=ureg.km) >>> converter(5.0) <Quantity(5.0, 'kilometer')> >>> converter(100.0 * ureg.m) <Quantity(100.0, 'meter')>
Deferred units are reevaluated on every call, which allows leveraging unit context overrides dynamically:
>>> generator = UnitGenerator(ureg.m) >>> converter = ensure_units(default_units=generator) >>> converter(1.0) <Quantity(1.0, 'meter')> >>> with generator.override(ureg.km): ... converter(1.0) <Quantity(1.0, 'kilometer')>
- pintext.to_quantity(value, strict=False)[source]#
Attempts turning an object into a Pint quantity.
Values for which conversion fails are passed through, unless
strictmode is active.This converter is useful for loading data from serialized formats (JSON, YAML) or working with xarray DataArrays that carry units in a Pint-compatible format.
The following types are supported:
pint.Quantity: passed through unchanged.dict(or, more generally, mappings): the magnitude (resp. units) must be supplied as thevalue,magnitudeormkeys (resp.units,unitoru).xarray.DataArray: the magnitude is the underlying data array (converted to a NumPy array) and units are read from theunitsattribute. If theunitsattribute is missing, the DataArray is returned unchanged. If the xarray dependency is not installed, conversion is skipped.Other types are tentatively converted by Pint. This, in particular, parses unit-carrying strings and applies dimensionless units to unitless values.
Warning
This converter uses the global unit registry from func:~pintext.get_unit_registry.
Extra keys in dictionaries will raise a
ValueError.
- Parameters:
- Raises:
ValueError – When converting a dictionary, if a magnitude or unit key is missing.
ValueError – When converting a dictionary, if unhandled keys are supplied.
ValueError – When conversion to a quantity fails and
strictisTrue.
- Return type:
Examples
Converting dictionaries: Useful for loading from JSON or YAML files:
>>> to_quantity({"value": 1.0, "units": "m"}) <Quantity(1.0, 'meter')> >>> to_quantity({"magnitude": 2.5, "units": "km"}) <Quantity(2.5, 'kilometer')>
Shorter key names are also supported:
>>> to_quantity({"m": 100.0, "u": "cm"}) <Quantity(100.0, 'centimeter')>
Converting xarray DataArrays: Extracts data and units from DataArrays following CF conventions (requires xarray):
>>> data = xr.DataArray([1.0, 2.0, 3.0], attrs={"units": "m"}) >>> to_quantity(data) <Quantity([1. 2. 3.], 'meter')>
DataArrays without units are passed through:
>>> data = xr.DataArray([1.0, 2.0]) >>> to_quantity(data) <xarray.DataArray (dim_0: 2)>...
Converting other types: unit-carrying strings are parsed, unitless values become dimensionless quantities:
>>> to_quantity("2 m") <Quantity(2, 'meter')> >>> to_quantity(42.0) <Quantity(42.0, 'dimensionless')>
Values Pint cannot interpret pass through, unless
strictisTrue:>>> to_quantity("text") 'text' >>> to_quantity("text", strict=True) Traceback (most recent call last): ... ValueError: Conversion of value to quantity failed (got 'text')
Utilities#
- pintext.units_compatible(unit1, unit2)[source]#
Check if two units are compatible. Accounts for angle units.
- Parameters:
- Return type:
- Returns:
Trueifunit1andunit2have the same dimensionality,Falseotherwise.
Examples
>>> units_compatible(ureg.m, ureg.km) True >>> units_compatible(ureg.m, ureg.s) False
Angles are deliberately not considered compatible with dimensionless values, even though Pint converts between them:
>>> units_compatible(ureg.rad, ureg.dimensionless) False >>> units_compatible(ureg.sr, ureg.rad) False
- pintext.check_units(value, units, name=None)[source]#
Check that a value carries units compatible (in the sense of
units_compatible()) withunits.This is the framework-agnostic unit check shared by the attrs and pydantic integrations.
- Parameters:
value – Value to check. Expected to be a
pint.Quantity.units (
Unit) – Unitsvaluemust be compatible with.name (
str|None) – Name of the field being checked, used to build the error message. IfNone, a generic message is produced.
- Raises:
UnitsError – If units are incompatible, or if a unitless value is provided.
- Return type:
Examples
>>> check_units(1.0 * ureg.km, ureg.m)An incompatible value raises:
>>> check_units(1.0 * ureg.s, ureg.m) Traceback (most recent call last): ... pintext.exceptions.UnitsError: Cannot convert from 'second' to 'meter': ...