Module peprock.models

General purpose model classes.

Expand source code
"""General purpose model classes."""

# noinspection PyProtectedMember
from peprock._version import __version__

from .measurement import Measurement
from .metric_prefix import MetricPrefix
from .unit import Unit

__all__ = [
    "__version__",
    "Measurement",
    "MetricPrefix",
    "Unit",
]

Sub-modules

peprock.models.measurement

Generic measurement model …

peprock.models.metric_prefix

Metric prefix model …

peprock.models.unit

Unit of measurement model …

Classes

class Measurement (magnitude: _MagnitudeT, prefix: MetricPrefix = <MetricPrefix.NONE: 0>, unit: Unit | str | None = None)

Measurement model supporting conversion and arithmetic operations.

Expand source code
@dataclasses.dataclass(frozen=True)
class Measurement(typing.Generic[_MagnitudeT]):
    """Measurement model supporting conversion and arithmetic operations."""

    magnitude: _MagnitudeT
    prefix: MetricPrefix = MetricPrefix.NONE
    unit: Unit | str | None = None

    @functools.cached_property
    def _unit_symbol(self: Self) -> str:
        match self.unit:
            case None | Unit.one:
                return ""
            case Unit():
                return self.unit.symbol
            case _:
                return self.unit

    def __format__(self: Self, format_spec: str) -> str:
        """Format measurement and return str."""
        if self.prefix.symbol or (self.unit and self.unit is not Unit.one):
            return (
                f"{self.magnitude:{format_spec}} "
                f"{self.prefix.symbol}{self._unit_symbol}"
            )

        return format(self.magnitude, format_spec)

    @functools.cached_property
    def _str(self: Self) -> str:
        return format(self)

    def __str__(self: Self) -> str:
        """Return str(self)."""
        return self._str

    @classmethod
    @functools.cache
    def _init_field_names(cls: type[Self]) -> tuple[str, ...]:
        return tuple(field.name for field in dataclasses.fields(cls) if field.init)

    def replace(self: Self, **changes: typing.Any) -> Self:
        """Return a new object replacing specified fields with new values."""
        return type(self)(
            **{
                field_name: changes[field_name]
                if field_name in changes
                else getattr(self, field_name)
                for field_name in self._init_field_names()
            },
        )

    @typing.overload
    def _apply_operator(
        self: Self,
        __other: Measurement[_MagnitudeS],
        __operator: collections.abc.Callable[
            [_MagnitudeT | float, _MagnitudeS | float],
            _T,
        ],
        /,
        *,
        wrap_in_measurement: typing.Literal[False] = False,
    ) -> _T:
        ...

    @typing.overload
    def _apply_operator(
        self: Self,
        __other: object,
        __operator: collections.abc.Callable[[_MagnitudeT | float, object], _T],
        /,
        *,
        wrap_in_measurement: typing.Literal[False] = False,
    ) -> _T:
        ...

    @typing.overload
    def _apply_operator(
        self: Self,
        __other: Measurement[_MagnitudeS],
        __operator: collections.abc.Callable[
            [_MagnitudeT | float, _MagnitudeS | float],
            _T,
        ],
        /,
        *,
        wrap_in_measurement: typing.Literal[True],
    ) -> Self:
        ...

    def _apply_operator(  # noqa: PLR0911
        self,
        __other,
        __operator,
        /,
        *,
        wrap_in_measurement=False,
    ):
        if isinstance(__other, Measurement) and self.unit == __other.unit:
            if (diff := self.prefix - __other.prefix) == 0:
                magnitude = __operator(
                    self.magnitude,
                    __other.magnitude,
                )

                if wrap_in_measurement:
                    return self.replace(
                        magnitude=magnitude,
                    )

                return magnitude

            if diff < 0:
                magnitude = __operator(
                    self.magnitude,
                    __other.prefix.convert(__other.magnitude, to=self.prefix),
                )

                if wrap_in_measurement:
                    return self.replace(
                        magnitude=magnitude,
                    )

                return magnitude

            magnitude = __operator(
                self.prefix.convert(self.magnitude, to=__other.prefix),
                __other.magnitude,
            )

            if wrap_in_measurement:
                return self.replace(
                    magnitude=magnitude,
                    prefix=__other.prefix,
                )

            return magnitude

        return NotImplemented

    def __lt__(self: Self, other: Measurement) -> bool:
        """Return self < other."""
        return self._apply_operator(other, operator.lt)

    def __le__(self: Self, other: Measurement) -> bool:
        """Return self <= other."""
        return self._apply_operator(other, operator.le)

    def __eq__(self: Self, other: object) -> bool:
        """Return self == other."""
        return self._apply_operator(other, operator.eq)

    def __ne__(self: Self, other: object) -> bool:
        """Return self != other."""
        return self._apply_operator(other, operator.ne)

    def __gt__(self: Self, other: Measurement) -> bool:
        """Return self > other."""
        return self._apply_operator(other, operator.gt)

    def __ge__(self: Self, other: Measurement) -> bool:
        """Return self >= other."""
        return self._apply_operator(other, operator.ge)

    @functools.cached_property
    def _hash(self: Self) -> int:
        return hash((self.prefix.convert(self.magnitude), self.unit))

    def __hash__(self: Self) -> int:
        """Return hash(self)."""
        return self._hash

    def __abs__(self: Self) -> Self:
        """Return abs(self)."""
        return self.replace(
            magnitude=abs(self.magnitude),
        )

    @typing.overload
    def __add__(
        self: Measurement[int],
        other: Measurement[int],
    ) -> Measurement[int] | Measurement[float]:
        ...

    @typing.overload
    def __add__(
        self: Measurement[int] | Measurement[float] | Measurement[fractions.Fraction],
        other: Measurement[float],
    ) -> Measurement[float]:
        ...

    @typing.overload
    def __add__(
        self: Measurement[float],
        other: Measurement[int] | Measurement[float] | Measurement[fractions.Fraction],
    ) -> Measurement[float]:
        ...

    @typing.overload
    def __add__(
        self: Measurement[int] | Measurement[decimal.Decimal],
        other: Measurement[decimal.Decimal],
    ) -> Measurement[decimal.Decimal]:
        ...

    @typing.overload
    def __add__(
        self: Measurement[decimal.Decimal],
        other: Measurement[int] | Measurement[decimal.Decimal],
    ) -> Measurement[decimal.Decimal]:
        ...

    @typing.overload
    def __add__(
        self: Measurement[int] | Measurement[fractions.Fraction],
        other: Measurement[fractions.Fraction],
    ) -> Measurement[fractions.Fraction]:
        ...

    @typing.overload
    def __add__(
        self: Measurement[fractions.Fraction],
        other: Measurement[int] | Measurement[fractions.Fraction],
    ) -> Measurement[fractions.Fraction]:
        ...

    def __add__(self, other):
        """Return self + other."""
        return self._apply_operator(other, operator.add, wrap_in_measurement=True)

    @typing.overload
    def __floordiv__(
        self: Measurement[int] | Measurement[fractions.Fraction],
        other: int | fractions.Fraction,
    ) -> Measurement[int]:
        ...

    @typing.overload
    def __floordiv__(
        self: Measurement[int] | Measurement[float] | Measurement[fractions.Fraction],
        other: float,
    ) -> Measurement[float]:
        ...

    @typing.overload
    def __floordiv__(
        self: Measurement[float],
        other: float | fractions.Fraction,
    ) -> Measurement[float]:
        ...

    @typing.overload
    def __floordiv__(
        self: Measurement[int] | Measurement[decimal.Decimal],
        other: decimal.Decimal,
    ) -> Measurement[decimal.Decimal]:
        ...

    @typing.overload
    def __floordiv__(
        self: Measurement[decimal.Decimal],
        other: int | decimal.Decimal,
    ) -> Measurement[decimal.Decimal]:
        ...

    @typing.overload
    def __floordiv__(
        self: Measurement[int] | Measurement[fractions.Fraction],
        other: Measurement[int] | Measurement[fractions.Fraction],
    ) -> int:
        ...

    @typing.overload
    def __floordiv__(
        self: Measurement[int] | Measurement[float] | Measurement[fractions.Fraction],
        other: Measurement[float],
    ) -> float:
        ...

    @typing.overload
    def __floordiv__(
        self: Measurement[float],
        other: Measurement[int] | Measurement[float] | Measurement[fractions.Fraction],
    ) -> float:
        ...

    @typing.overload
    def __floordiv__(
        self: Measurement[int] | Measurement[decimal.Decimal],
        other: Measurement[decimal.Decimal],
    ) -> decimal.Decimal:
        ...

    @typing.overload
    def __floordiv__(
        self: Measurement[decimal.Decimal],
        other: Measurement[int] | Measurement[decimal.Decimal],
    ) -> decimal.Decimal:
        ...

    def __floordiv__(self, other):
        """Return self // other."""
        match other:
            case int() | float() | decimal.Decimal() | fractions.Fraction():
                return self.replace(
                    magnitude=self.magnitude // other,
                )

        return self._apply_operator(other, operator.floordiv)

    @typing.overload
    def __mod__(
        self: Measurement[int],
        other: Measurement[int],
    ) -> Measurement[int]:
        ...

    @typing.overload
    def __mod__(
        self: Measurement[int] | Measurement[float] | Measurement[fractions.Fraction],
        other: Measurement[float],
    ) -> Measurement[float]:
        ...

    @typing.overload
    def __mod__(
        self: Measurement[float],
        other: Measurement[int] | Measurement[float] | Measurement[fractions.Fraction],
    ) -> Measurement[float]:
        ...

    @typing.overload
    def __mod__(
        self: Measurement[int] | Measurement[decimal.Decimal],
        other: Measurement[decimal.Decimal],
    ) -> Measurement[decimal.Decimal]:
        ...

    @typing.overload
    def __mod__(
        self: Measurement[decimal.Decimal],
        other: Measurement[int] | Measurement[decimal.Decimal],
    ) -> Measurement[decimal.Decimal]:
        ...

    @typing.overload
    def __mod__(
        self: Measurement[int] | Measurement[fractions.Fraction],
        other: Measurement[fractions.Fraction],
    ) -> Measurement[fractions.Fraction]:
        ...

    @typing.overload
    def __mod__(
        self: Measurement[fractions.Fraction],
        other: Measurement[int] | Measurement[fractions.Fraction],
    ) -> Measurement[fractions.Fraction]:
        ...

    def __mod__(self, other):
        """Return self % other."""
        return self._apply_operator(other, operator.mod, wrap_in_measurement=True)

    @typing.overload
    def __mul__(
        self: Measurement[int],
        other: int,
    ) -> Measurement[int]:
        ...

    @typing.overload
    def __mul__(
        self: Measurement[int] | Measurement[float] | Measurement[fractions.Fraction],
        other: float,
    ) -> Measurement[float]:
        ...

    @typing.overload
    def __mul__(
        self: Measurement[float],
        other: float | fractions.Fraction,
    ) -> Measurement[float]:
        ...

    @typing.overload
    def __mul__(
        self: Measurement[int] | Measurement[decimal.Decimal],
        other: decimal.Decimal,
    ) -> Measurement[decimal.Decimal]:
        ...

    @typing.overload
    def __mul__(
        self: Measurement[decimal.Decimal],
        other: int | decimal.Decimal,
    ) -> Measurement[decimal.Decimal]:
        ...

    @typing.overload
    def __mul__(
        self: Measurement[int] | Measurement[fractions.Fraction],
        other: fractions.Fraction,
    ) -> Measurement[fractions.Fraction]:
        ...

    @typing.overload
    def __mul__(
        self: Measurement[fractions.Fraction],
        other: int | fractions.Fraction,
    ) -> Measurement[fractions.Fraction]:
        ...

    def __mul__(self, other):
        """Return self * other."""
        match other:
            case int() | float() | decimal.Decimal() | fractions.Fraction():
                return self.replace(
                    magnitude=self.magnitude * other,
                )

        return NotImplemented

    @typing.overload
    def __rmul__(
        self: Measurement[int],
        other: int,
    ) -> Measurement[int]:
        ...

    @typing.overload
    def __rmul__(
        self: Measurement[int] | Measurement[float] | Measurement[fractions.Fraction],
        other: float,
    ) -> Measurement[float]:
        ...

    @typing.overload
    def __rmul__(
        self: Measurement[float],
        other: float | fractions.Fraction,
    ) -> Measurement[float]:
        ...

    @typing.overload
    def __rmul__(
        self: Measurement[int] | Measurement[decimal.Decimal],
        other: decimal.Decimal,
    ) -> Measurement[decimal.Decimal]:
        ...

    @typing.overload
    def __rmul__(
        self: Measurement[decimal.Decimal],
        other: int | decimal.Decimal,
    ) -> Measurement[decimal.Decimal]:
        ...

    @typing.overload
    def __rmul__(
        self: Measurement[int] | Measurement[fractions.Fraction],
        other: fractions.Fraction,
    ) -> Measurement[fractions.Fraction]:
        ...

    @typing.overload
    def __rmul__(
        self: Measurement[fractions.Fraction],
        other: int | fractions.Fraction,
    ) -> Measurement[fractions.Fraction]:
        ...

    def __rmul__(self, other):
        """Return other * self."""
        return self.__mul__(other)

    def __neg__(self: Self) -> Self:
        """Return -self."""
        return self.replace(
            magnitude=-self.magnitude,
        )

    def __pos__(self: Self) -> Self:
        """Return +self."""
        return self.replace(
            magnitude=+self.magnitude,
        )

    @typing.overload
    def __sub__(
        self: Measurement[int],
        other: Measurement[int],
    ) -> Measurement[int] | Measurement[float]:
        ...

    @typing.overload
    def __sub__(
        self: Measurement[int] | Measurement[float] | Measurement[fractions.Fraction],
        other: Measurement[float],
    ) -> Measurement[float]:
        ...

    @typing.overload
    def __sub__(
        self: Measurement[float],
        other: Measurement[int] | Measurement[float] | Measurement[fractions.Fraction],
    ) -> Measurement[float]:
        ...

    @typing.overload
    def __sub__(
        self: Measurement[int] | Measurement[decimal.Decimal],
        other: Measurement[decimal.Decimal],
    ) -> Measurement[decimal.Decimal]:
        ...

    @typing.overload
    def __sub__(
        self: Measurement[decimal.Decimal],
        other: Measurement[int] | Measurement[decimal.Decimal],
    ) -> Measurement[decimal.Decimal]:
        ...

    @typing.overload
    def __sub__(
        self: Measurement[int] | Measurement[fractions.Fraction],
        other: Measurement[fractions.Fraction],
    ) -> Measurement[fractions.Fraction]:
        ...

    @typing.overload
    def __sub__(
        self: Measurement[fractions.Fraction],
        other: Measurement[int] | Measurement[fractions.Fraction],
    ) -> Measurement[fractions.Fraction]:
        ...

    def __sub__(self, other):
        """Return self - other."""
        return self._apply_operator(other, operator.sub, wrap_in_measurement=True)

    @typing.overload
    def __truediv__(
        self: Measurement[int] | Measurement[float],
        other: float,
    ) -> Measurement[float]:
        ...

    @typing.overload
    def __truediv__(
        self: Measurement[float],
        other: fractions.Fraction,
    ) -> Measurement[float]:
        ...

    @typing.overload
    def __truediv__(
        self: Measurement[fractions.Fraction],
        other: float,
    ) -> Measurement[float]:
        ...

    @typing.overload
    def __truediv__(
        self: Measurement[int] | Measurement[decimal.Decimal],
        other: decimal.Decimal,
    ) -> Measurement[decimal.Decimal]:
        ...

    @typing.overload
    def __truediv__(
        self: Measurement[decimal.Decimal],
        other: int | decimal.Decimal,
    ) -> Measurement[decimal.Decimal]:
        ...

    @typing.overload
    def __truediv__(
        self: Measurement[int] | Measurement[fractions.Fraction],
        other: fractions.Fraction,
    ) -> Measurement[fractions.Fraction]:
        ...

    @typing.overload
    def __truediv__(
        self: Measurement[fractions.Fraction],
        other: int | fractions.Fraction,
    ) -> Measurement[fractions.Fraction]:
        ...

    @typing.overload
    def __truediv__(
        self: Measurement[int] | Measurement[float],
        other: Measurement[int] | Measurement[float],
    ) -> float:
        ...

    @typing.overload
    def __truediv__(
        self: Measurement[float],
        other: Measurement[fractions.Fraction],
    ) -> float:
        ...

    @typing.overload
    def __truediv__(
        self: Measurement[fractions.Fraction],
        other: Measurement[float],
    ) -> float:
        ...

    @typing.overload
    def __truediv__(
        self: Measurement[int] | Measurement[decimal.Decimal],
        other: Measurement[decimal.Decimal],
    ) -> decimal.Decimal:
        ...

    @typing.overload
    def __truediv__(
        self: Measurement[decimal.Decimal],
        other: Measurement[int] | Measurement[decimal.Decimal],
    ) -> decimal.Decimal:
        ...

    @typing.overload
    def __truediv__(
        self: Measurement[int] | Measurement[fractions.Fraction],
        other: Measurement[fractions.Fraction],
    ) -> fractions.Fraction:
        ...

    @typing.overload
    def __truediv__(
        self: Measurement[fractions.Fraction],
        other: Measurement[int] | Measurement[fractions.Fraction],
    ) -> fractions.Fraction:
        ...

    def __truediv__(self, other):
        """Return self / other."""
        match other:
            case int() | float() | decimal.Decimal() | fractions.Fraction():
                return self.replace(
                    magnitude=self.magnitude / other,
                )

        return self._apply_operator(other, operator.truediv)

    def __bool__(self: Self) -> bool:
        """Return True if magnitude is nonzero; otherwise return False."""
        return bool(self.magnitude)

    def __int__(self: Self) -> int:
        """Return int(self)."""
        return int(
            self.magnitude
            if self.prefix is MetricPrefix.NONE
            else self.prefix.convert(self.magnitude),
        )

    def __float__(self: Self) -> float:
        """Return float(self)."""
        return float(
            self.magnitude
            if self.prefix is MetricPrefix.NONE
            else self.prefix.convert(self.magnitude),
        )

    @typing.overload
    def __round__(
        self: Self,
    ) -> Measurement[int]:
        ...

    @typing.overload
    def __round__(
        self: Self,
        __ndigits: typing.SupportsIndex,
    ) -> Self:
        ...

    def __round__(
        self,
        __ndigits=None,
    ):
        """Return round(self)."""
        return self.replace(
            magnitude=round(self.magnitude, __ndigits),
        )

Ancestors

  • typing.Generic

Class variables

var magnitude : ~_MagnitudeT
var prefixMetricPrefix
var unitUnit | str | None

Methods

def replace(self: Self, **changes: typing.Any) ‑> Self

Return a new object replacing specified fields with new values.

Expand source code
def replace(self: Self, **changes: typing.Any) -> Self:
    """Return a new object replacing specified fields with new values."""
    return type(self)(
        **{
            field_name: changes[field_name]
            if field_name in changes
            else getattr(self, field_name)
            for field_name in self._init_field_names()
        },
    )
class MetricPrefix (value, names=None, *, module=None, qualname=None, type=None, start=1)

MetricPrefix IntEnum with symbol and conversion support.

Expand source code
class MetricPrefix(enum.IntEnum):
    """MetricPrefix IntEnum with symbol and conversion support."""

    quetta = 30
    ronna = 27
    yotta = 24
    zetta = 21
    exa = 18
    peta = 15
    tera = 12
    giga = 9
    mega = 6
    kilo = 3
    hecto = 2
    deca = 1
    NONE = 0
    deci = -1
    centi = -2
    milli = -3
    micro = -6
    nano = -9
    pico = -12
    femto = -15
    atto = -18
    zepto = -21
    yocto = -24
    ronto = -27
    quecto = -30

    @classmethod
    def from_symbol(cls: type[MetricPrefix], symbol: str, /) -> MetricPrefix:
        """Return MetricPrefix by symbol."""
        return cls._by_symbol()[symbol]

    @functools.cached_property
    def symbol(self: MetricPrefix) -> str:
        """Metric prefix symbol, e.g. G for giga."""
        return self._symbols()[self]

    def __str__(self: MetricPrefix) -> str:
        """Return symbol."""
        return self.symbol

    @typing.overload
    def to(
        self: MetricPrefix,
        __other: MetricPrefix | int,
        /,
        *,
        number_type: type[int] = int,
    ) -> int | float:
        ...

    @typing.overload
    def to(
        self: MetricPrefix,
        __other: MetricPrefix | int,
        /,
        *,
        number_type: type[ComplexT],
    ) -> ComplexT:
        ...

    def to(
        self: MetricPrefix,
        __other: MetricPrefix | int,
        /,
        *,
        number_type: type[int | ComplexT] = int,
    ) -> int | ComplexT:
        """Calculate conversion factor between self and other."""
        return number_type(_BASE) ** (self - __other)

    @typing.overload
    def convert(
        self: MetricPrefix,
        __value: int,
        /,
        to: MetricPrefix = NONE,  # type: ignore[assignment]
    ) -> int | float:
        ...

    @typing.overload
    def convert(
        self: MetricPrefix,
        __value: ComplexT,
        /,
        to: MetricPrefix = NONE,  # type: ignore[assignment]
    ) -> ComplexT:
        ...

    def convert(
        self,
        __value,
        /,
        to=NONE,
    ):
        """Convert value from metric prefix self to to."""
        if self is to:
            return __value

        return __value * self.to(to, number_type=type(__value))

    @staticmethod
    @functools.cache
    def _symbols() -> types.MappingProxyType[MetricPrefix, str]:
        return types.MappingProxyType(
            {
                MetricPrefix.quetta: "Q",
                MetricPrefix.ronna: "R",
                MetricPrefix.yotta: "Y",
                MetricPrefix.zetta: "Z",
                MetricPrefix.exa: "E",
                MetricPrefix.peta: "P",
                MetricPrefix.tera: "T",
                MetricPrefix.giga: "G",
                MetricPrefix.mega: "M",
                MetricPrefix.kilo: "k",
                MetricPrefix.hecto: "h",
                MetricPrefix.deca: "da",
                MetricPrefix.NONE: "",
                MetricPrefix.deci: "d",
                MetricPrefix.centi: "c",
                MetricPrefix.milli: "m",
                MetricPrefix.micro: "μ",
                MetricPrefix.nano: "n",
                MetricPrefix.pico: "p",
                MetricPrefix.femto: "f",
                MetricPrefix.atto: "a",
                MetricPrefix.zepto: "z",
                MetricPrefix.yocto: "y",
                MetricPrefix.ronto: "r",
                MetricPrefix.quecto: "q",
            },
        )

    @classmethod
    @functools.cache
    def _by_symbol(
        cls: type[MetricPrefix],
    ) -> types.MappingProxyType[str, MetricPrefix]:
        return types.MappingProxyType(
            {symbol: metric_prefix for metric_prefix, symbol in cls._symbols().items()},
        )

Ancestors

  • enum.IntEnum
  • builtins.int
  • enum.Enum

Class variables

var NONE
var atto
var centi
var deca
var deci
var exa
var femto
var giga
var hecto
var kilo
var mega
var micro
var milli
var nano
var peta
var pico
var quecto
var quetta
var ronna
var ronto
var tera
var yocto
var yotta
var zepto
var zetta

Static methods

def from_symbol(symbol: str, /) ‑> MetricPrefix

Return MetricPrefix by symbol.

Expand source code
@classmethod
def from_symbol(cls: type[MetricPrefix], symbol: str, /) -> MetricPrefix:
    """Return MetricPrefix by symbol."""
    return cls._by_symbol()[symbol]

Instance variables

var symbol

Metric prefix symbol, e.g. G for giga.

Expand source code
def __get__(self, instance, owner=None):
    if instance is None:
        return self
    if self.attrname is None:
        raise TypeError(
            "Cannot use cached_property instance without calling __set_name__ on it.")
    try:
        cache = instance.__dict__
    except AttributeError:  # not all objects have __dict__ (e.g. class defines slots)
        msg = (
            f"No '__dict__' attribute on {type(instance).__name__!r} "
            f"instance to cache {self.attrname!r} property."
        )
        raise TypeError(msg) from None
    val = cache.get(self.attrname, _NOT_FOUND)
    if val is _NOT_FOUND:
        with self.lock:
            # check if another thread filled cache while we awaited lock
            val = cache.get(self.attrname, _NOT_FOUND)
            if val is _NOT_FOUND:
                val = self.func(instance)
                try:
                    cache[self.attrname] = val
                except TypeError:
                    msg = (
                        f"The '__dict__' attribute on {type(instance).__name__!r} instance "
                        f"does not support item assignment for caching {self.attrname!r} property."
                    )
                    raise TypeError(msg) from None
    return val

Methods

def convert(self, _MetricPrefix__value, /, to=0)

Convert value from metric prefix self to to.

Expand source code
def convert(
    self,
    __value,
    /,
    to=NONE,
):
    """Convert value from metric prefix self to to."""
    if self is to:
        return __value

    return __value * self.to(to, number_type=type(__value))
def to(self: MetricPrefix, _MetricPrefix__other: MetricPrefix | int, /, *, number_type: type[int | ComplexT] = builtins.int) ‑> int | ComplexT

Calculate conversion factor between self and other.

Expand source code
def to(
    self: MetricPrefix,
    __other: MetricPrefix | int,
    /,
    *,
    number_type: type[int | ComplexT] = int,
) -> int | ComplexT:
    """Calculate conversion factor between self and other."""
    return number_type(_BASE) ** (self - __other)
class Unit (value, names=None, *, module=None, qualname=None, type=None, start=1)

Unit Enum with symbol.

Expand source code
class Unit(enum.Enum):
    """Unit Enum with symbol."""

    # metric units, see https://en.wikipedia.org/wiki/List_of_metric_units
    one = "1"  # unit of a quantity of dimension one
    second = "s"  # unit of time
    metre = "m"  # unit of length
    gram = "g"  # unit of mass (actually kilogram in SI)
    ampere = "A"  # unit of electric current
    kelvin = "K"  # unit of thermodynamic temperature
    mole = "mol"  # unit of amount of substance
    candela = "cd"  # unit of luminous intensity
    hertz = "Hz"  # equal to one reciprocal second
    radian = "rad"  # equal to one
    steradian = "sr"  # equal to one
    newton = "N"  # equal to one kilogram-metre per second squared
    pascal = "Pa"  # equal to one newton per square metre
    joule = "J"  # equal to one newton-metre
    watt = "W"  # equal to one joule per second
    coulomb = "C"  # equal to one ampere second
    volt = "V"  # equal to one joule per coulomb
    weber = "Wb"  # equal to one volt-second
    tesla = "T"  # equal to one weber per square metre
    farad = "F"  # equal to one coulomb per volt
    ohm = "Ω"  # equal to one volt per ampere
    siemens = "S"  # equal to one ampere per volt
    henry = "H"  # equal to one volt-second per ampere
    # degree Celsius (°C) is equal to one kelvin
    lumen = "lm"  # equal to one candela-steradian
    lux = "lx"  # equal to one lumen per square metre
    becquerel = "Bq"  # equal to one reciprocal second
    gray = "Gy"  # equal to one joule per kilogram
    sievert = "Sv"  # equal to one joule per kilogram
    katal = "kat"  # equal to one mole per second

    @functools.cached_property
    def symbol(self: Unit) -> str:
        """Get the unit symbol."""
        return self.value

Ancestors

  • enum.Enum

Class variables

var ampere
var becquerel
var candela
var coulomb
var farad
var gram
var gray
var henry
var hertz
var joule
var katal
var kelvin
var lumen
var lux
var metre
var mole
var newton
var ohm
var one
var pascal
var radian
var second
var siemens
var sievert
var steradian
var tesla
var volt
var watt
var weber

Instance variables

var symbol

Get the unit symbol.

Expand source code
def __get__(self, instance, owner=None):
    if instance is None:
        return self
    if self.attrname is None:
        raise TypeError(
            "Cannot use cached_property instance without calling __set_name__ on it.")
    try:
        cache = instance.__dict__
    except AttributeError:  # not all objects have __dict__ (e.g. class defines slots)
        msg = (
            f"No '__dict__' attribute on {type(instance).__name__!r} "
            f"instance to cache {self.attrname!r} property."
        )
        raise TypeError(msg) from None
    val = cache.get(self.attrname, _NOT_FOUND)
    if val is _NOT_FOUND:
        with self.lock:
            # check if another thread filled cache while we awaited lock
            val = cache.get(self.attrname, _NOT_FOUND)
            if val is _NOT_FOUND:
                val = self.func(instance)
                try:
                    cache[self.attrname] = val
                except TypeError:
                    msg = (
                        f"The '__dict__' attribute on {type(instance).__name__!r} instance "
                        f"does not support item assignment for caching {self.attrname!r} property."
                    )
                    raise TypeError(msg) from None
    return val