1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273
|
"""
pint.registry
~~~~~~~~~~~~~
Defines the UnitRegistry, a class to contain units and their relations.
This registry contains all pint capabilities, but you can build your
customized registry by picking only the features that you actually
need.
:copyright: 2022 by Pint Authors, see AUTHORS for more details.
:license: BSD, see LICENSE for more details.
"""
from __future__ import annotations
from typing import Generic
from . import facets, registry_helpers
from .compat import TypeAlias
from .util import logger, pi_theorem
# To build the Quantity and Unit classes
# we follow the UnitRegistry bases
# but
class Quantity(
Generic[facets.MagnitudeT],
facets.SystemRegistry.Quantity[facets.MagnitudeT],
facets.ContextRegistry.Quantity[facets.MagnitudeT],
facets.DaskRegistry.Quantity[facets.MagnitudeT],
facets.NumpyRegistry.Quantity[facets.MagnitudeT],
facets.MeasurementRegistry.Quantity[facets.MagnitudeT],
facets.NonMultiplicativeRegistry.Quantity[facets.MagnitudeT],
facets.PlainRegistry.Quantity[facets.MagnitudeT],
):
pass
class Unit(
facets.SystemRegistry.Unit,
facets.ContextRegistry.Unit,
facets.DaskRegistry.Unit,
facets.NumpyRegistry.Unit,
facets.MeasurementRegistry.Unit,
facets.NonMultiplicativeRegistry.Unit,
facets.PlainRegistry.Unit,
):
pass
class GenericUnitRegistry(
Generic[facets.QuantityT, facets.UnitT],
facets.GenericSystemRegistry[facets.QuantityT, facets.UnitT],
facets.GenericContextRegistry[facets.QuantityT, facets.UnitT],
facets.GenericDaskRegistry[facets.QuantityT, facets.UnitT],
facets.GenericNumpyRegistry[facets.QuantityT, facets.UnitT],
facets.GenericMeasurementRegistry[facets.QuantityT, facets.UnitT],
facets.GenericNonMultiplicativeRegistry[facets.QuantityT, facets.UnitT],
facets.GenericPlainRegistry[facets.QuantityT, facets.UnitT],
):
pass
class UnitRegistry(GenericUnitRegistry[Quantity[facets.MagnitudeT], Unit]):
"""The unit registry stores the definitions and relationships between units.
Parameters
----------
filename :
path of the units definition file to load or line-iterable object.
Empty string to load the default definition file. (default)
None to leave the UnitRegistry empty.
force_ndarray : bool
convert any input, scalar or not to a numpy.ndarray.
(Default: False)
force_ndarray_like : bool
convert all inputs other than duck arrays to a numpy.ndarray.
(Default: False)
default_as_delta :
In the context of a multiplication of units, interpret
non-multiplicative units as their *delta* counterparts.
(Default: False)
autoconvert_offset_to_baseunit :
If True converts offset units in quantities are
converted to their plain units in multiplicative
context. If False no conversion happens. (Default: False)
on_redefinition : str
action to take in case a unit is redefined.
'warn', 'raise', 'ignore' (Default: 'raise')
auto_reduce_dimensions :
If True, reduce dimensionality on appropriate operations.
(Default: False)
autoconvert_to_preferred :
If True, converts preferred units on appropriate operations.
(Default: False)
preprocessors :
list of callables which are iteratively ran on any input expression
or unit string or None for no preprocessor.
(Default=None)
fmt_locale :
locale identifier string, used in `format_babel` or None.
(Default=None)
case_sensitive : bool, optional
Control default case sensitivity of unit parsing. (Default: True)
cache_folder : str or pathlib.Path or None, optional
Specify the folder in which cache files are saved and loaded from.
If None, the cache is disabled. (default)
"""
Quantity: TypeAlias = Quantity
Unit: TypeAlias = Unit
def __init__(
self,
filename="",
force_ndarray: bool = False,
force_ndarray_like: bool = False,
default_as_delta: bool = True,
autoconvert_offset_to_baseunit: bool = False,
on_redefinition: str = "warn",
system=None,
auto_reduce_dimensions=False,
autoconvert_to_preferred=False,
preprocessors=None,
fmt_locale=None,
non_int_type=float,
case_sensitive: bool = True,
cache_folder=None,
):
super().__init__(
filename=filename,
force_ndarray=force_ndarray,
force_ndarray_like=force_ndarray_like,
on_redefinition=on_redefinition,
default_as_delta=default_as_delta,
autoconvert_offset_to_baseunit=autoconvert_offset_to_baseunit,
system=system,
auto_reduce_dimensions=auto_reduce_dimensions,
autoconvert_to_preferred=autoconvert_to_preferred,
preprocessors=preprocessors,
fmt_locale=fmt_locale,
non_int_type=non_int_type,
case_sensitive=case_sensitive,
cache_folder=cache_folder,
)
def pi_theorem(self, quantities):
"""Builds dimensionless quantities using the Buckingham π theorem
Parameters
----------
quantities : dict
mapping between variable name and units
Returns
-------
list
a list of dimensionless quantities expressed as dicts
"""
return pi_theorem(quantities, self)
def setup_matplotlib(self, enable: bool = True) -> None:
"""Set up handlers for matplotlib's unit support.
Parameters
----------
enable : bool
whether support should be enabled or disabled (Default value = True)
"""
# Delays importing matplotlib until it's actually requested
from .matplotlib import setup_matplotlib_handlers
setup_matplotlib_handlers(self, enable)
wraps = registry_helpers.wraps
check = registry_helpers.check
class LazyRegistry(Generic[facets.QuantityT, facets.UnitT]):
def __init__(self, args=None, kwargs=None):
self.__dict__["params"] = args or (), kwargs or {}
def __init(self):
args, kwargs = self.__dict__["params"]
kwargs["on_redefinition"] = "raise"
self.__class__ = UnitRegistry
self.__init__(*args, **kwargs)
self._after_init()
def __getattr__(self, item):
if item == "_on_redefinition":
return "raise"
self.__init()
return getattr(self, item)
def __setattr__(self, key, value):
if key == "__class__":
super().__setattr__(key, value)
else:
self.__init()
setattr(self, key, value)
def __getitem__(self, item):
self.__init()
return self[item]
def __call__(self, *args, **kwargs):
self.__init()
return self(*args, **kwargs)
class ApplicationRegistry:
"""A wrapper class used to distribute changes to the application registry."""
__slots__ = ["_registry"]
def __init__(self, registry):
self._registry = registry
def get(self):
"""Get the wrapped registry"""
return self._registry
def set(self, new_registry):
"""Set the new registry
Parameters
----------
new_registry : ApplicationRegistry or LazyRegistry or UnitRegistry
The new registry.
See Also
--------
set_application_registry
"""
if isinstance(new_registry, type(self)):
new_registry = new_registry.get()
if not isinstance(new_registry, (LazyRegistry, UnitRegistry)):
raise TypeError("Expected UnitRegistry; got %s" % type(new_registry))
logger.debug(
"Changing app registry from %r to %r.", self._registry, new_registry
)
self._registry = new_registry
def __getattr__(self, name):
return getattr(self._registry, name)
def __setattr__(self, name, value):
if name in self.__slots__:
super().__setattr__(name, value)
else:
setattr(self._registry, name, value)
def __dir__(self):
return dir(self._registry)
def __getitem__(self, item):
return self._registry[item]
def __call__(self, *args, **kwargs):
return self._registry(*args, **kwargs)
def __contains__(self, item):
return self._registry.__contains__(item)
def __iter__(self):
return iter(self._registry)
|