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 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
|
"""
.. codeauthor:: Tsuyoshi Hombashi <tsuyoshi.hombashi@gmail.com>
"""
import abc
from typing import Any, Optional
from .._typecode import Typecode
from ..checker._interface import TypeCheckerInterface
from ..converter import ValueConverterInterface
from ..error import TypeConversionError
class AbstractType(TypeCheckerInterface, ValueConverterInterface):
__slots__ = (
"_data",
"_strict_level",
"_params",
"__checker",
"__converter",
"__is_type_result",
)
@abc.abstractproperty
def typecode(self) -> Typecode: # pragma: no cover
pass
@abc.abstractmethod
def _create_type_checker(self): # pragma: no cover
pass
@abc.abstractmethod
def _create_type_converter(self): # pragma: no cover
pass
@property
def typename(self) -> str:
return self.typecode.name
def __init__(self, value: Any, strict_level: int, **kwargs) -> None:
self._data = value
self._strict_level = strict_level
self._params = kwargs
self.__checker = self._create_type_checker()
self.__converter = self._create_type_converter()
self.__is_type_result: Optional[bool] = None
def __repr__(self) -> str:
return ", ".join(
[
f"value={self._data}",
f"typename={self.typename}",
f"strict_level={self._strict_level}",
f"is_type={self.is_type()}",
f"try_convert={self.try_convert()}",
]
)
def is_type(self) -> bool:
"""
:return:
:rtype: bool
"""
if self.__is_type_result is not None:
return self.__is_type_result
self.__is_type_result = self.__is_type()
return self.__is_type_result
def __is_type(self) -> bool:
if self.__checker.is_type():
return True
if self.__checker.is_exclude_instance():
return False
try:
self._converted_value = self.__converter.force_convert()
except TypeConversionError:
return False
if not self.__checker.is_valid_after_convert(self._converted_value):
return False
return True
def validate(self, error_message: Optional[str] = None) -> None:
"""
:raises TypeError:
If the value is not matched the type that the class represented.
"""
if self.is_type():
return
if not error_message:
error_message = "invalid value type"
raise TypeError(f"{error_message}: expected={self.typename}, actual={type(self._data)}")
def convert(self):
"""
:return: Converted value.
:raises typepy.TypeConversionError:
If the value cannot convert.
"""
if self.is_type():
return self.force_convert()
raise TypeConversionError(
"failed to convert {} from {} to {}".format(
self._data, type(self._data).__name__, self.typename
)
)
def force_convert(self):
"""
:return: Converted value.
:raises typepy.TypeConversionError:
If the value cannot convert.
"""
return self.__converter.force_convert()
def try_convert(self):
"""
:return: Converted value. |None| if failed to convert.
"""
try:
return self.convert()
except TypeConversionError:
return None
|