File: converters.py

package info (click to toggle)
python-pint 0.25.2-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,940 kB
  • sloc: python: 20,478; makefile: 148
file content (75 lines) | stat: -rw-r--r-- 2,247 bytes parent folder | download
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
"""
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


@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)