aboutsummaryrefslogtreecommitdiff
path: root/python/cru/_type.py
blob: 1f81da37504ca5c2ccf1a73d0aaaea581b320e45 (plain)
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
from collections.abc import Iterable
from typing import Any

from ._error import CruException, CruLogicError
from ._iter import CruIterator


class CruTypeCheckError(CruException):
    pass


DEFAULT_NONE_ERR_MSG = "None is not allowed here."
DEFAULT_TYPE_ERR_MSG = "Object of this type is not allowed here."


class CruTypeSet(set[type]):
    def __init__(self, *types: type):
        type_set = CruIterator(types).filter(lambda t: t is not None).to_set()
        if not CruIterator(type_set).all(lambda t: isinstance(t, type)):
            raise CruLogicError("TypeSet can only contain type.")
        super().__init__(type_set)

    def check_value(
        self,
        value: Any,
        /,
        allow_none: bool = False,
        empty_allow_all: bool = True,
    ) -> None:
        if value is None:
            if allow_none:
                return
            else:
                raise CruTypeCheckError(DEFAULT_NONE_ERR_MSG)
        if len(self) == 0 and empty_allow_all:
            return
        if not CruIterator(self).any(lambda t: isinstance(value, t)):
            raise CruTypeCheckError(DEFAULT_TYPE_ERR_MSG)

    def check_value_list(
        self,
        values: Iterable[Any],
        /,
        allow_none: bool = False,
        empty_allow_all: bool = True,
    ) -> None:
        for value in values:
            self.check_value(
                value,
                allow_none,
                empty_allow_all,
            )