Source code for easydata.parsers.price

from abc import ABC, abstractmethod
from typing import Any, Optional, Union

from easydata.parsers.text import Str
from easydata.utils import price

__all__ = (
    "BaseNum",
    "BasePriceFloat",
    "PriceFloat",
    "PriceInt",
    "PriceText",
)


class BaseNum(Str, ABC):
    def __init__(
        self,
        *args,
        decimals: Optional[int] = None,
        min_value: Optional[Union[float, int]] = None,
        max_value: Optional[Union[float, int]] = None,
        normalize: bool = False,
        **kwargs,
    ):

        self.__decimals = decimals
        self.__min_value = min_value
        self.__max_value = max_value

        kwargs["normalize"] = normalize

        super().__init__(
            *args,
            **kwargs,
        )

    @property
    def _decimals(self):
        if isinstance(self.__decimals, int):
            return self.__decimals

        decimals = self.__decimals or self._decimals_config

        return decimals if isinstance(decimals, int) else None

    @property
    def _min_value(self):
        return self.__min_value or self._min_value_config

    @property
    def _max_value(self):
        return self.__max_value or self._max_value_config

    @property
    def _decimals_config(self):
        return None

    @property
    def _min_value_config(self):
        return None

    @property
    def _max_value_config(self):
        return None

    def parse_value(
        self,
        value: Any,
        data: Any,
    ):

        if isinstance(value, (float, int)):
            value = self._parse_num_value(value)
        else:
            value = super().parse_value(value=value, data=data)

            if value is None:
                return None

            value = self._parse_num_value(value)

        if value is None:
            return None

        return price.process_min_max_value(
            value,
            min_value=self._min_value,
            max_value=self._max_value,
        )

    @abstractmethod
    def _parse_num_value(self, value: Any):
        pass


class BasePriceFloat(BaseNum, ABC):
    def __init__(
        self,
        *args,
        currency_hint: Optional[str] = None,
        decimal_separator: Optional[str] = None,
        **kwargs,
    ):

        self._currency_hint = currency_hint
        self._decimal_separator = decimal_separator

        super().__init__(
            *args,
            **kwargs,
        )

    def _parse_num_value(self, value: Any):
        return price.to_float(
            price_value=value,
            decimals=self._decimals,
            currency_hint=self._currency_hint,
            decimal_separator=self._decimal_separator,
        )


[docs]class PriceFloat(BasePriceFloat): @property def _decimals_config(self) -> Optional[int]: return self.config.get("ED_PRICE_DECIMALS") @property def _min_value_config(self) -> Optional[int]: return self.config.get("ED_PRICE_MIN_VALUE") @property def _max_value_config(self) -> Optional[int]: return self.config.get("ED_PRICE_MAX_VALUE")
[docs]class PriceInt(PriceFloat): def parse_value( self, value: Any, data: Any, ): value = super().parse_value(value=value, data=data) return None if value is None else int(value)
[docs]class PriceText(PriceFloat): def parse_value( self, value: Any, data: Any, ): value = super().parse_value(value=value, data=data) return None if value is None else str(value)