Source code for pint.converters
"""
pint.converters
~~~~~~~~~~~~~~~
Functions and classes related to unit conversions.
:copyright: 2016 by Pint Authors, see AUTHORS for more details.
:license: BSD, see LICENSE for more details.
"""
from __future__ import annotations
from dataclasses import dataclass
from dataclasses import fields as dc_fields
from typing import Any, ClassVar
from ._typing import Magnitude
from .compat import HAS_NUMPY, Self, exp, log # noqa: F401
[docs]
@dataclass(frozen=True)
class Converter:
"""Base class for value converters."""
_subclasses: ClassVar[list[type[Converter]]] = []
_param_names_to_subclass: ClassVar[dict[frozenset[str], type[Converter]]] = {}
@property
def is_multiplicative(self) -> bool:
return True
@property
def is_logarithmic(self) -> bool:
return False
def to_reference(self, value: Magnitude, inplace: bool = False) -> Magnitude:
return value
def from_reference(self, value: Magnitude, inplace: bool = False) -> Magnitude:
return value
def __init_subclass__(cls, **kwargs: Any):
# Get constructor parameters
super().__init_subclass__(**kwargs)
cls._subclasses.append(cls)
@classmethod
def get_field_names(cls, new_cls: type) -> frozenset[str]:
return frozenset(p.name for p in dc_fields(new_cls))
@classmethod
def preprocess_kwargs(cls, **kwargs: Any) -> dict[str, Any] | None:
return None
@classmethod
def from_arguments(cls, **kwargs: Any) -> Converter:
kwk = frozenset(kwargs.keys())
try:
new_cls = cls._param_names_to_subclass[kwk]
except KeyError:
for new_cls in cls._subclasses:
p_names = frozenset(p.name for p in dc_fields(new_cls))
if p_names == kwk:
cls._param_names_to_subclass[kwk] = new_cls
break
else:
params = "(" + ", ".join(tuple(kwk)) + ")"
raise ValueError(
f"There is no class registered for parameters {params}"
)
kw = new_cls.preprocess_kwargs(**kwargs)
if kw is None:
return new_cls(**kwargs)
return cls.from_arguments(**kw)