Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make MatchItemsModel Generic. Generics are currently not supported by Parametriz... #218

Open
github-actions bot opened this issue Nov 9, 2024 · 0 comments
Labels

Comments

@github-actions
Copy link

github-actions bot commented Nov 9, 2024

# TODO: Make MatchItemsModel Generic. Generics are currently not supported by Parametrized Models.

        return [cls._join_items(cast(list[str], cols)) for cols in data]


class JoinSubitemsToItemsModel(_JoinSubitemsToItemsModel):
    adjust = bind_adjust_model_func(
        _JoinSubitemsToItemsModel.clone_model_cls,
        _JoinSubitemsToItemsModel.Params,
    )


class _JoinItemsByTabParamsMixin:
    @params_dataclass
    class Params(ParamsBase):
        delimiter: str = ('\t')


class JoinColumnsToLinesModel(_JoinItemsByTabParamsMixin, _JoinSubitemsToItemsModel):
    adjust = bind_adjust_model_func(
        _JoinSubitemsToItemsModel.clone_model_cls,
        _JoinItemsByTabParamsMixin.Params,
    )


NestedStrWithListModelsT = TypeVar(
    'NestedStrWithListModelsT', bound='NestedStrWithListModels', default='str')


class ListOfNestedStrModel(Model[list[NestedStrWithListModelsT]],
                           Generic[NestedStrWithListModelsT]):
    ...


NestedStrWithListModels: TypeAlias = str | ListOfNestedStrModel

ListOfNestedStrModel.update_forward_refs()

NestedStrNoListModelsT = TypeVar(
    'NestedStrNoListModelsT', default=str | list['NestedStrNoListModelsT'])  # type: ignore[misc]


class _NestedItemsParamsMixin:
    @params_dataclass
    class Params(ParamsBase):
        delimiters: tuple[str, ...] = ()

    @classmethod
    def _split_data_according_to_delimiters(cls,
                                            data: NestedStrWithListModels,
                                            level: int = 0) -> str | list[NestedStrNoListModelsT]:

        raw_data = cast(str | list[NestedStrWithListModels],
                        data if isinstance(data, str) else data.contents)

        num_delimiters = len(cls.Params.delimiters)

        if level == 0 and len(raw_data) == 0:
            return [] if num_delimiters > 0 else ''

        split_data: list[NestedStrWithListModels]
        if isinstance(raw_data, str):
            if num_delimiters == 0:
                return raw_data

            split_data = cast(list[NestedStrWithListModels],
                              raw_data.split(cls.Params.delimiters[level]))
        else:
            split_data = raw_data

        next_level = level + 1

        if num_delimiters == next_level:
            assert len(split_data) > 1, \
                (f'Data at bottom level (level {level}) must contain at '
                 f'least one delimiter or equivalently be pre-split into '
                 f'more than one item (bottom delimiter: '
                 f'{cls.Params.delimiters[level]}): {split_data}')
        if num_delimiters > next_level:
            split_data_no_list_models = [
                cls._split_data_according_to_delimiters(item, level=next_level)
                for item in split_data
            ]
            return cast(list[NestedStrNoListModelsT], split_data_no_list_models)
        else:
            if num_delimiters == 0:
                assert isinstance(data, str), \
                    'Data must be an string if no delimiters are provided.'
            else:
                assert not any(obj_or_model_contents_isinstance(item, list) for item in data), \
                    (f'Data is nested higher than permitted by the number of delimiters in '
                     f'Params (={num_delimiters}).')

        return cast(list[NestedStrNoListModelsT], split_data)


class _NestedSplitToItemsModel(Model[list[NestedStrNoListModelsT] | str],
                               Generic[NestedStrNoListModelsT],
                               _NestedItemsParamsMixin):
    @classmethod
    def _parse_data(cls,
                    data: list[NestedStrNoListModelsT] | str) -> list[NestedStrNoListModelsT] | str:
        str_parsed_data = Model[NestedStrWithListModels](data).contents
        return cls._split_data_according_to_delimiters(str_parsed_data)


class NestedSplitToItemsModel(_NestedSplitToItemsModel):
    adjust = bind_adjust_model_func(
        cast(Callable[..., type[_NestedSplitToItemsModel]],
             _NestedSplitToItemsModel.clone_model_cls),
        _NestedSplitToItemsModel.Params,
    )


class _NestedJoinItemsModel(Model[str | list[NestedStrNoListModelsT]],
                            Generic[NestedStrNoListModelsT],
                            _NestedItemsParamsMixin):
    @classmethod
    def _join_data_according_to_delimiters(cls,
                                           data: str | list[NestedStrNoListModelsT],
                                           level: int = 0) -> str:
        if isinstance(data, str):
            return data

        num_delimiters = len(cls.Params.delimiters)
        next_level = level + 1
        raw_data: list[str]
        if num_delimiters > next_level:
            raw_data = [
                cls._join_data_according_to_delimiters(
                    cast(str | list[NestedStrNoListModelsT], item), level=next_level)
                for item in data
            ]
        else:
            raw_data = cast(list[str], data)

        return cls.Params.delimiters[level].join(raw_data) if len(raw_data) > 0 else ''

    @classmethod
    def _parse_data(cls, data: str | list[NestedStrNoListModelsT]) -> str:
        str_parsed_data = Model[NestedStrWithListModels](data).contents
        return cls._join_data_according_to_delimiters(
            cls._split_data_according_to_delimiters(str_parsed_data))


class NestedJoinItemsModel(_NestedJoinItemsModel):
    adjust = bind_adjust_model_func(
        cast(Callable[..., type[_NestedJoinItemsModel]], _NestedJoinItemsModel.clone_model_cls),
        _NestedItemsParamsMixin.Params,
    )


# TODO: Make MatchItemsModel Generic. Generics are currently not supported by Parametrized Models.


class _MatchItemsModel(Model[list[str]]):
    @params_dataclass
    class Params(ParamsBase):
        match_functions: tuple[Callable[[str], bool], ...] = ()
        invert_matches: bool = False
        match_all: bool = True

    @classmethod
    def _parse_data(cls, data: list[str]) -> list[str]:
        match_functions = cls.Params.match_functions
        invert_matches = cls.Params.invert_matches

        if len(match_functions) == 0:
            return data

        logic_operator = all if cls.Params.match_all else any

        return [
            item for item in data
            if (logic_operator(match_func(item) for match_func in match_functions) is True)
            ^ invert_matches
        ]


class MatchItemsModel(_MatchItemsModel):
    adjust = bind_adjust_model_func(
        _MatchItemsModel.clone_model_cls,
        _MatchItemsModel.Params,
    )
@github-actions github-actions bot added the todo label Nov 9, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

0 participants