File: _checker.py

package info (click to toggle)
python-typepy 1.3.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 624 kB
  • sloc: python: 2,886; makefile: 78; sh: 7
file content (90 lines) | stat: -rw-r--r-- 2,485 bytes parent folder | download | duplicates (2)
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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
"""
.. codeauthor:: Tsuyoshi Hombashi <tsuyoshi.hombashi@gmail.com>
"""

import abc

from ._interface import TypeCheckerInterface


class CheckerFactory:
    __slots__ = ("__min_strict_level", "__max_strict_level", "__checker_mapping")

    @property
    def min_strict_level(self):
        return self.__min_strict_level

    @property
    def max_strict_level(self):
        return self.__max_strict_level

    def __init__(self, checker_mapping):
        self.__checker_mapping = checker_mapping

        self.__min_strict_level = min(checker_mapping)
        self.__max_strict_level = max(checker_mapping)
        self.__checker_mapping[None] = self.__max_strict_level

    def get_checker_class(self, strict_level=None):
        checker_class = self.__checker_mapping.get(strict_level)
        if checker_class:
            return checker_class
        if strict_level < self.min_strict_level:
            return self.__checker_mapping[self.min_strict_level]
        if strict_level > self.max_strict_level:
            return self.__checker_mapping[self.max_strict_level]

        raise ValueError(f"unexpected strict level: {strict_level}")


class TypeCheckerBase(TypeCheckerInterface):
    __slots__ = ("_value",)

    def __init__(self, value):
        self._value = value

    @abc.abstractmethod
    def is_instance(self):
        pass

    def is_type(self) -> bool:
        return self.is_instance() and not self.is_exclude_instance()

    def validate(self) -> None:
        """
        :raises TypeError:
            If the value is not matched the type to be expected.
        """

        if self.is_type():
            return

        raise TypeError(f"invalid value type: actual={type(self._value)}")

    def is_exclude_instance(self):
        return False

    def is_valid_after_convert(self, converted_value):
        return True


class TypeCheckerDelegator(TypeCheckerInterface):
    __slots__ = ("__checker",)

    def __init__(self, value, checker_factory, strict_level):
        self.__checker = checker_factory.get_checker_class(strict_level)(value)

    def is_type(self) -> bool:
        return self.__checker.is_type()

    def is_valid_after_convert(self, value):
        return self.__checker.is_valid_after_convert(value)

    def is_instance(self):
        return self.__checker.is_instance()

    def is_exclude_instance(self):
        return self.__checker.is_exclude_instance()

    def validate(self) -> None:
        self.__checker.validate()