Source code for easydata.parsers.choice

from abc import ABC
from functools import cached_property
from typing import Any, List, Optional

from easytxt import text

from easydata.data import DataBag
from easydata.parsers.base import Base
from easydata.parsers.has import Has
from easydata.parsers.text import Text
from easydata.queries.base import QuerySearchBase
from easydata.utils import mix

__all__ = (
    "BaseLookups",
    "Choice",
)


class BaseLookups(Base, ABC):
    def __init__(
        self,
        lookups: Optional[Any] = None,
        source: Optional[str] = None,
    ):

        self._lookups = lookups
        self._source = source or "main"

    def _parse_lookups(
        self,
        data: Any,
        parent_data: Any = None,
        with_parent_data: bool = False,
    ):

        lookup_data = parent_data if with_parent_data else data

        if not self._lookups:
            if isinstance(lookup_data, DataBag):
                lookup_data = lookup_data[self._source]

            return [text.to_str(lookup_data)]

        lookup_values = []

        for lookup in self._initialized_lookups:
            if isinstance(lookup, str):
                lookup_value = data.get(lookup)
            else:
                lookup_value = lookup.parse(data)

            if lookup_value:
                lookup_values.append(text.to_str(lookup_value))

        return lookup_values

    @cached_property
    def _initialized_lookups(self):
        initialized_lookups = []

        if not isinstance(self._lookups, (list, tuple)):
            lookups = [self._lookups]
        else:
            lookups = self._lookups

        for lookup in lookups:
            if isinstance(lookup, QuerySearchBase):
                lookup = Text(query=lookup, source=self._source)

            if isinstance(lookup, Base):
                mix.validate_parser(lookup)

                lookup.init_config(self.config)

            initialized_lookups.append(lookup)

        return initialized_lookups


[docs]class Choice(BaseLookups): def __init__( self, choices: list, default_choice: Optional[str] = None, **kwargs, ): self._choices = choices self._default_choice = default_choice super().__init__(**kwargs) def parse( self, data: Any, parent_data: Any = None, with_parent_data: bool = False, ) -> Optional[str]: lookup_values = self._parse_lookups( data=data, parent_data=parent_data, with_parent_data=with_parent_data, ) return self._get_choice_value(lookup_values, data) or self._default_choice def _get_choice_value( self, lookup_values: List[str], data: Any, ) -> Optional[str]: lookup_value = " ".join(lookup_values) for choice_data in self._choices: choice_value, choice_search_data = choice_data if isinstance(choice_search_data, Has): choice_search_data.init_config(self.config) if choice_search_data.parse(data=data): return choice_value elif lookup_value and text.contains(lookup_value, choice_search_data): return choice_value return None