-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathbase.py
More file actions
executable file
·151 lines (111 loc) · 4.21 KB
/
Copy pathbase.py
File metadata and controls
executable file
·151 lines (111 loc) · 4.21 KB
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
139
140
141
142
143
144
145
146
147
148
149
150
151
from abc import abstractmethod
from typing import TypeVar, Callable, Any
CAPTURE_EXCEPTIONS = (Exception, )
_ValueType = TypeVar('_ValueType')
def _to_exception(exception) -> Callable[[Any], Exception]:
if hasattr(exception, '__call__'):
return exception
elif isinstance(exception, Exception):
return lambda v: exception
elif isinstance(exception, str):
return lambda v: ValueError(exception)
else:
raise TypeError(
'Unknown type of exception, func, exception or str expected but {actual} found.'.format(
actual=repr(type(exception).__name__)
)
)
def _to_loader(value) -> 'ILoaderClass':
if isinstance(value, ILoaderClass):
return value
elif isinstance(value, tuple):
if len(value) == 2:
_predict, _exception = value
_load = None
elif len(value) == 3:
_predict, _load, _exception = value
else:
raise ValueError('Tuple\'s length should be 2 or 3, but {actual} found.'.format(actual=repr(len(value))))
_exception = _to_exception(_exception)
def _load_tuple(value_):
if not _predict(value_):
raise _exception(value_)
return (_load or (lambda v: v))(value_)
return _to_loader(_load_tuple)
elif isinstance(value, type):
def _load_type(value_):
if not isinstance(value_, value):
raise TypeError(
'type not match, {expect} expected but {actual} found'.format(
expect=repr(value.__name__), actual=repr(type(value_).__name__)
)
)
return value_
return _to_loader(_load_type)
elif hasattr(value, '__call__'):
class _Loader(ILoaderClass):
def _load(self, value_):
return value(value_)
return _Loader()
elif isinstance(value, bool):
return _to_loader((lambda v: value, ValueError('assertion false')))
elif value is None:
return _to_loader(
(
lambda v: v is None, lambda v:
TypeError('type not match, none expected but {actual} found'.format(actual=repr(type(v).__name__)))
)
)
else:
return _to_loader(lambda v: value)
Loader = _to_loader
def _reset_exception(loader, eg: Callable[[Any, Exception], Exception]):
loader = Loader(loader)
def _load(value):
try:
return loader(value)
except CAPTURE_EXCEPTIONS as err:
raise eg(value, err)
return Loader(_load)
class ILoaderClass:
@abstractmethod
def _load(self, value: _ValueType) -> _ValueType:
raise NotImplementedError
def __load(self, value: _ValueType) -> _ValueType:
return self._load(value)
def __check(self, value: _ValueType) -> bool:
try:
self._load(value)
except CAPTURE_EXCEPTIONS:
return False
else:
return True
def load(self, value: _ValueType) -> _ValueType:
return self.__load(value)
def check(self, value: _ValueType) -> bool:
return self.__check(value)
def __call__(self, value: _ValueType) -> _ValueType:
return self.__load(value)
def __and__(self, other) -> 'ILoaderClass':
def _load(value: _ValueType) -> _ValueType:
self.load(value)
return Loader(other).load(value)
return Loader(_load)
def __rand__(self, other) -> 'ILoaderClass':
return Loader(other) & self
def __or__(self, other) -> 'ILoaderClass':
def _load(value: _ValueType) -> _ValueType:
try:
return self.load(value)
except CAPTURE_EXCEPTIONS:
return Loader(other).load(value)
return Loader(_load)
def __ror__(self, other) -> 'ILoaderClass':
return Loader(other) | self
def __rshift__(self, other) -> 'ILoaderClass':
def _load(value: _ValueType) -> _ValueType:
_return_value = self.load(value)
return _to_loader(other).load(_return_value)
return Loader(_load)
def __rrshift__(self, other) -> 'ILoaderClass':
return Loader(other) >> self