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
|
"""
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, Optional
from ._typing import Magnitude
from .compat import HAS_NUMPY, exp, log, Self # noqa: F401
@dataclass(frozen=True)
class Converter:
"""Base class for value converters."""
# list[type[Converter]]
_subclasses = []
# dict[frozenset[str], type[Converter]]
_param_names_to_subclass = {}
@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) -> Optional[dict[str, Any]]:
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)
|