DefStream 0.1.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- DefStream/Broker/Configuration.py +18 -0
- DefStream/Broker/Connection.py +97 -0
- DefStream/Broker/Consumer.py +59 -0
- DefStream/Broker/Errors.py +14 -0
- DefStream/Broker/Event.py +35 -0
- DefStream/Broker/Implements/__init__.py +1 -0
- DefStream/Broker/Policies.py +25 -0
- DefStream/Broker/Protocol.py +45 -0
- DefStream/Broker/__init__.py +47 -0
- DefStream/Descriptor/DataObject.py +384 -0
- DefStream/Descriptor/Types.py +229 -0
- DefStream/Descriptor/Value.py +132 -0
- DefStream/Descriptor/__init__.py +172 -0
- DefStream/Inspector/Extension.py +69 -0
- DefStream/Inspector/Extensions/Console.html +373 -0
- DefStream/Inspector/Extensions/Console.py +396 -0
- DefStream/Inspector/Extensions/Dashboard.html +206 -0
- DefStream/Inspector/Extensions/Dashboard.py +114 -0
- DefStream/Inspector/Extensions/HealthCheck.py +92 -0
- DefStream/Inspector/Extensions/Metrics.py +281 -0
- DefStream/Inspector/Extensions/Specifications.py +160 -0
- DefStream/Inspector/Extensions/__init__.py +13 -0
- DefStream/Inspector/Inspector.py +216 -0
- DefStream/Inspector/Response.py +14 -0
- DefStream/Inspector/__init__.py +9 -0
- DefStream/Validator/Pattern.py +36 -0
- DefStream/Validator/Patterns/Array.py +30 -0
- DefStream/Validator/Patterns/Common.py +93 -0
- DefStream/Validator/Patterns/Compare.py +180 -0
- DefStream/Validator/Patterns/Condition.py +60 -0
- DefStream/Validator/Patterns/DataObject.py +85 -0
- DefStream/Validator/Patterns/DateTime.py +111 -0
- DefStream/Validator/Patterns/Number.py +43 -0
- DefStream/Validator/Patterns/Object.py +150 -0
- DefStream/Validator/Patterns/Size.py +110 -0
- DefStream/Validator/Patterns/String.py +85 -0
- DefStream/Validator/Patterns/Type.py +350 -0
- DefStream/Validator/Patterns/__init__.py +137 -0
- DefStream/Validator/Validate.py +29 -0
- DefStream/Validator/Validator.py +30 -0
- DefStream/Validator/__init__.py +11 -0
- DefStream/Worker/Executor.py +298 -0
- DefStream/Worker/Message.py +103 -0
- DefStream/Worker/Pool.py +203 -0
- DefStream/Worker/Run.py +187 -0
- DefStream/Worker/Specification.py +91 -0
- DefStream/Worker/Worker.py +321 -0
- DefStream/Worker/__init__.py +49 -0
- DefStream/__init__.py +0 -0
- defstream-0.1.2.dist-info/METADATA +1197 -0
- defstream-0.1.2.dist-info/RECORD +54 -0
- defstream-0.1.2.dist-info/WHEEL +5 -0
- defstream-0.1.2.dist-info/licenses/LICENSE +674 -0
- defstream-0.1.2.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
from logging import getLogger
|
|
2
|
+
from socketserver import ThreadingMixIn
|
|
3
|
+
from threading import Thread
|
|
4
|
+
from typing import (
|
|
5
|
+
Callable,
|
|
6
|
+
Dict,
|
|
7
|
+
Iterable,
|
|
8
|
+
Optional,
|
|
9
|
+
Sequence,
|
|
10
|
+
TYPE_CHECKING,
|
|
11
|
+
Tuple,
|
|
12
|
+
)
|
|
13
|
+
from wsgiref.simple_server import (
|
|
14
|
+
WSGIRequestHandler,
|
|
15
|
+
WSGIServer,
|
|
16
|
+
make_server,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
from .Extension import Extension
|
|
20
|
+
from .Response import Response
|
|
21
|
+
|
|
22
|
+
if TYPE_CHECKING:
|
|
23
|
+
from ..Worker.Worker import Worker
|
|
24
|
+
|
|
25
|
+
__all__ = (
|
|
26
|
+
'Inspector',
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
logger = getLogger(__name__)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class Server(
|
|
33
|
+
ThreadingMixIn,
|
|
34
|
+
WSGIServer,
|
|
35
|
+
):
|
|
36
|
+
daemon_threads = True
|
|
37
|
+
block_on_close = False
|
|
38
|
+
|
|
39
|
+
def get_request(self):
|
|
40
|
+
connection, address = super().get_request()
|
|
41
|
+
connection.settimeout(5)
|
|
42
|
+
return connection, address
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class RequestHandler(WSGIRequestHandler):
|
|
46
|
+
def log_message(
|
|
47
|
+
self,
|
|
48
|
+
format: str,
|
|
49
|
+
*args,
|
|
50
|
+
) -> None:
|
|
51
|
+
logger.info(
|
|
52
|
+
'%s - %s',
|
|
53
|
+
self.client_address[0],
|
|
54
|
+
format % args,
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class Inspector:
|
|
59
|
+
def __init__(
|
|
60
|
+
self,
|
|
61
|
+
host: str = '127.0.0.1',
|
|
62
|
+
port: int = 9999,
|
|
63
|
+
exts: Sequence[Extension] = (),
|
|
64
|
+
):
|
|
65
|
+
if isinstance(
|
|
66
|
+
port,
|
|
67
|
+
bool,
|
|
68
|
+
) or not isinstance(
|
|
69
|
+
port,
|
|
70
|
+
int,
|
|
71
|
+
) or not 0 <= port <= 65535:
|
|
72
|
+
raise ValueError('Inspector port must be between 0 and 65535')
|
|
73
|
+
self.host = host
|
|
74
|
+
self.port = port
|
|
75
|
+
self.exts: Dict[str, Extension] = {}
|
|
76
|
+
for ext in exts:
|
|
77
|
+
if not isinstance(
|
|
78
|
+
ext,
|
|
79
|
+
Extension,
|
|
80
|
+
):
|
|
81
|
+
raise TypeError('Inspector extensions must inherit Extension')
|
|
82
|
+
if ext.path in self.exts:
|
|
83
|
+
raise ValueError('Duplicate Inspector path: ' + ext.path)
|
|
84
|
+
self.exts[ext.path] = ext
|
|
85
|
+
self.worker: Optional['Worker'] = None
|
|
86
|
+
self.server: Optional[WSGIServer] = None
|
|
87
|
+
self.thread: Optional[Thread] = None
|
|
88
|
+
|
|
89
|
+
def start(
|
|
90
|
+
self,
|
|
91
|
+
worker: 'Worker',
|
|
92
|
+
) -> None:
|
|
93
|
+
if self.worker is not None:
|
|
94
|
+
raise RuntimeError('Inspector can only be attached and started once')
|
|
95
|
+
self.worker = worker
|
|
96
|
+
for ext in self.exts.values():
|
|
97
|
+
ext.start(self)
|
|
98
|
+
server = make_server(
|
|
99
|
+
self.host,
|
|
100
|
+
self.port,
|
|
101
|
+
self,
|
|
102
|
+
server_class=Server,
|
|
103
|
+
handler_class=RequestHandler,
|
|
104
|
+
)
|
|
105
|
+
self.server = server
|
|
106
|
+
thread = Thread(
|
|
107
|
+
target=self.serve,
|
|
108
|
+
daemon=True,
|
|
109
|
+
)
|
|
110
|
+
self.thread = thread
|
|
111
|
+
try:
|
|
112
|
+
thread.start()
|
|
113
|
+
except BaseException:
|
|
114
|
+
server.server_close()
|
|
115
|
+
raise
|
|
116
|
+
|
|
117
|
+
def serve(self) -> None:
|
|
118
|
+
server = self.server
|
|
119
|
+
if server is None:
|
|
120
|
+
raise RuntimeError('Inspector server is not initialized')
|
|
121
|
+
try:
|
|
122
|
+
server.serve_forever(poll_interval=0.1)
|
|
123
|
+
except Exception:
|
|
124
|
+
logger.exception('Inspector HTTP server failed')
|
|
125
|
+
if self.worker is not None:
|
|
126
|
+
self.worker.stop()
|
|
127
|
+
raise
|
|
128
|
+
|
|
129
|
+
def stop(self) -> None:
|
|
130
|
+
server = self.server
|
|
131
|
+
thread = self.thread
|
|
132
|
+
if server is not None:
|
|
133
|
+
try:
|
|
134
|
+
if thread is not None and thread.is_alive():
|
|
135
|
+
server.shutdown()
|
|
136
|
+
thread.join()
|
|
137
|
+
finally:
|
|
138
|
+
server.server_close()
|
|
139
|
+
|
|
140
|
+
def begin(
|
|
141
|
+
self,
|
|
142
|
+
task: str,
|
|
143
|
+
) -> Tuple[Tuple[Extension, object], ...]:
|
|
144
|
+
return tuple(
|
|
145
|
+
(
|
|
146
|
+
ext,
|
|
147
|
+
ext.begin(task),
|
|
148
|
+
)
|
|
149
|
+
for ext in self.exts.values()
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
def end(
|
|
153
|
+
self,
|
|
154
|
+
task: str,
|
|
155
|
+
contexts: Tuple[Tuple[Extension, object], ...],
|
|
156
|
+
success: Optional[bool],
|
|
157
|
+
) -> None:
|
|
158
|
+
for ext, context in contexts:
|
|
159
|
+
ext.end(
|
|
160
|
+
task,
|
|
161
|
+
context,
|
|
162
|
+
success,
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
def __call__(
|
|
166
|
+
self,
|
|
167
|
+
environ: dict,
|
|
168
|
+
start_response: Callable,
|
|
169
|
+
) -> Iterable[bytes]:
|
|
170
|
+
method = environ['REQUEST_METHOD']
|
|
171
|
+
environ['wsgi.multithread'] = True
|
|
172
|
+
headers = []
|
|
173
|
+
ext = self.exts.get(environ['PATH_INFO'])
|
|
174
|
+
methods = ext.methods if ext is not None else (
|
|
175
|
+
'GET',
|
|
176
|
+
'HEAD',
|
|
177
|
+
)
|
|
178
|
+
if method not in methods:
|
|
179
|
+
response = Response(
|
|
180
|
+
'405 Method Not Allowed',
|
|
181
|
+
b'Method not allowed\n',
|
|
182
|
+
'text/plain; charset=utf-8',
|
|
183
|
+
)
|
|
184
|
+
headers.append((
|
|
185
|
+
'Allow',
|
|
186
|
+
', '.join(methods),
|
|
187
|
+
))
|
|
188
|
+
else:
|
|
189
|
+
response = ext.handle(
|
|
190
|
+
self,
|
|
191
|
+
environ,
|
|
192
|
+
) if ext is not None else Response(
|
|
193
|
+
'404 Not Found',
|
|
194
|
+
b'Not found\n',
|
|
195
|
+
'text/plain; charset=utf-8',
|
|
196
|
+
)
|
|
197
|
+
headers.extend(response.headers)
|
|
198
|
+
headers.extend((
|
|
199
|
+
(
|
|
200
|
+
'Content-Type',
|
|
201
|
+
response.content_type,
|
|
202
|
+
),
|
|
203
|
+
(
|
|
204
|
+
'Content-Length',
|
|
205
|
+
str(len(response.body)),
|
|
206
|
+
),
|
|
207
|
+
(
|
|
208
|
+
'Cache-Control',
|
|
209
|
+
'no-store',
|
|
210
|
+
),
|
|
211
|
+
))
|
|
212
|
+
start_response(
|
|
213
|
+
response.status,
|
|
214
|
+
headers,
|
|
215
|
+
)
|
|
216
|
+
return [b'' if method == 'HEAD' else response.body]
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
from abc import (
|
|
4
|
+
ABC,
|
|
5
|
+
abstractmethod,
|
|
6
|
+
)
|
|
7
|
+
|
|
8
|
+
__all__ = (
|
|
9
|
+
'Pattern',
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class Pattern(ABC):
|
|
14
|
+
"""
|
|
15
|
+
Pattern Interface Class for Validator
|
|
16
|
+
|
|
17
|
+
Sample:
|
|
18
|
+
from operator import eq
|
|
19
|
+
|
|
20
|
+
class SamplePattern(Pattern):
|
|
21
|
+
def __init__(self, compare):
|
|
22
|
+
super(SamplePattern, self).__init__(error)
|
|
23
|
+
self.compare = compare
|
|
24
|
+
return
|
|
25
|
+
|
|
26
|
+
def __call__(self, parameter):
|
|
27
|
+
if not eq(parameter, self.compare):
|
|
28
|
+
raise ValueError('{} is not equal to {}'.format(parameter, self.condition))
|
|
29
|
+
return parameter # if true, return parameter
|
|
30
|
+
"""
|
|
31
|
+
@abstractmethod
|
|
32
|
+
def __call__(self, parameter):
|
|
33
|
+
pass
|
|
34
|
+
|
|
35
|
+
def __repr__(self):
|
|
36
|
+
return '{}()'.format(self.__class__.__name__)
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
from ..Pattern import Pattern
|
|
4
|
+
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
__all__ = (
|
|
8
|
+
'IsElementOf',
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class IsElementOf(Pattern):
|
|
13
|
+
def __init__(self, *args):
|
|
14
|
+
self.patterns = args
|
|
15
|
+
return
|
|
16
|
+
|
|
17
|
+
def __call__(self, parameter: Any) -> Any:
|
|
18
|
+
_ = list(parameter)
|
|
19
|
+
for pattern in self.patterns:
|
|
20
|
+
for i, e in enumerate(_):
|
|
21
|
+
_[i] = pattern(e)
|
|
22
|
+
return type(parameter)(_)
|
|
23
|
+
|
|
24
|
+
def __repr__(self):
|
|
25
|
+
return '{}({})'.format(
|
|
26
|
+
self.__class__.__name__,
|
|
27
|
+
', '.join(
|
|
28
|
+
[repr(p) for p in self.patterns]
|
|
29
|
+
)
|
|
30
|
+
)
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
from ..Pattern import Pattern
|
|
4
|
+
|
|
5
|
+
from operator import eq
|
|
6
|
+
|
|
7
|
+
__all__ = (
|
|
8
|
+
'SetDefault',
|
|
9
|
+
'IsToNone',
|
|
10
|
+
'IsNotToNone',
|
|
11
|
+
'IsNotEmpty',
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class SetDefault(Pattern):
|
|
16
|
+
def __init__(self, default):
|
|
17
|
+
self.default = default
|
|
18
|
+
return
|
|
19
|
+
|
|
20
|
+
def __call__(self, parameter):
|
|
21
|
+
if parameter == None:
|
|
22
|
+
return self.default
|
|
23
|
+
return parameter
|
|
24
|
+
|
|
25
|
+
def __repr__(self):
|
|
26
|
+
return '{}({})'.format(
|
|
27
|
+
self.__class__.__name__,
|
|
28
|
+
self.default
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class IsToNone(Pattern):
|
|
33
|
+
def __init__(self, *args):
|
|
34
|
+
self.patterns = args
|
|
35
|
+
return
|
|
36
|
+
|
|
37
|
+
def __call__(self, parameter):
|
|
38
|
+
if parameter is None:
|
|
39
|
+
return parameter
|
|
40
|
+
for pattern in self.patterns:
|
|
41
|
+
parameter = pattern(parameter)
|
|
42
|
+
return parameter
|
|
43
|
+
|
|
44
|
+
def __repr__(self):
|
|
45
|
+
return '{}({})'.format(
|
|
46
|
+
self.__class__.__name__,
|
|
47
|
+
', '.join([p.__repr__() for p in self.patterns])
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class IsNotToNone(Pattern):
|
|
52
|
+
def __init__(self, *args, error=None):
|
|
53
|
+
self.patterns = args
|
|
54
|
+
self.error = error
|
|
55
|
+
return
|
|
56
|
+
|
|
57
|
+
def __call__(self, parameter):
|
|
58
|
+
if parameter is None:
|
|
59
|
+
if self.error:
|
|
60
|
+
raise self.error
|
|
61
|
+
raise ValueError('{} is None'.format(parameter))
|
|
62
|
+
for pattern in self.patterns:
|
|
63
|
+
parameter = pattern(parameter)
|
|
64
|
+
return parameter
|
|
65
|
+
|
|
66
|
+
def __repr__(self):
|
|
67
|
+
return '{}({})'.format(
|
|
68
|
+
self.__class__.__name__,
|
|
69
|
+
', '.join([p.__repr__() for p in self.patterns])
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
class IsNotEmpty(Pattern):
|
|
74
|
+
def __init__(self, *args, error=None):
|
|
75
|
+
self.patterns = args
|
|
76
|
+
self.error = error
|
|
77
|
+
return
|
|
78
|
+
|
|
79
|
+
def __call__(self, parameter):
|
|
80
|
+
if eq(len(parameter), 0):
|
|
81
|
+
if self.error:
|
|
82
|
+
raise self.error
|
|
83
|
+
raise ValueError('{} must be not empty'.format(parameter))
|
|
84
|
+
for pattern in self.patterns:
|
|
85
|
+
parameter = pattern(parameter)
|
|
86
|
+
return parameter
|
|
87
|
+
|
|
88
|
+
def __repr__(self):
|
|
89
|
+
return '{}({})'.format(
|
|
90
|
+
self.__class__.__name__,
|
|
91
|
+
', '.join([p.__repr__() for p in self.patterns])
|
|
92
|
+
)
|
|
93
|
+
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
from ..Pattern import Pattern
|
|
4
|
+
|
|
5
|
+
from operator import eq, ne, gt, ge, lt, le
|
|
6
|
+
|
|
7
|
+
__all__ = (
|
|
8
|
+
'IsIn',
|
|
9
|
+
'IsNotIn',
|
|
10
|
+
'IsEqualTo',
|
|
11
|
+
'IsNotEqualTo',
|
|
12
|
+
'IsGreaterThan',
|
|
13
|
+
'IsGreaterEqualTo',
|
|
14
|
+
'IsLessThan',
|
|
15
|
+
'IsLessEqualTo',
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class IsIn(Pattern):
|
|
20
|
+
def __init__(self, *args, error=None):
|
|
21
|
+
self.compares = args
|
|
22
|
+
self.error = error
|
|
23
|
+
return
|
|
24
|
+
|
|
25
|
+
def __call__(self, parameter):
|
|
26
|
+
if parameter not in self.compares:
|
|
27
|
+
if self.error:
|
|
28
|
+
raise self.error
|
|
29
|
+
raise ValueError('{} must be in {}'.format(parameter, self.compares))
|
|
30
|
+
return parameter
|
|
31
|
+
|
|
32
|
+
def __repr__(self):
|
|
33
|
+
return '{}({})'.format(
|
|
34
|
+
self.__class__.__name__,
|
|
35
|
+
', '.join(
|
|
36
|
+
[repr(c) for c in self.compares]
|
|
37
|
+
)
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class IsNotIn(Pattern):
|
|
42
|
+
def __init__(self, *args, error=None):
|
|
43
|
+
self.compares = args
|
|
44
|
+
self.error = error
|
|
45
|
+
return
|
|
46
|
+
|
|
47
|
+
def __call__(self, parameter):
|
|
48
|
+
if parameter in self.compares:
|
|
49
|
+
if self.error:
|
|
50
|
+
raise self.error
|
|
51
|
+
raise ValueError('{} must be not in {}'.format(parameter, self.compares))
|
|
52
|
+
return parameter
|
|
53
|
+
|
|
54
|
+
def __repr__(self):
|
|
55
|
+
return '{}({})'.format(
|
|
56
|
+
self.__class__.__name__,
|
|
57
|
+
', '.join(
|
|
58
|
+
[repr(c) for c in self.compares]
|
|
59
|
+
)
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
class IsEqualTo(Pattern):
|
|
64
|
+
def __init__(self, equal, error=None):
|
|
65
|
+
self.equal = equal
|
|
66
|
+
self.error = error
|
|
67
|
+
return
|
|
68
|
+
|
|
69
|
+
def __call__(self, parameter):
|
|
70
|
+
if not eq(parameter, self.equal):
|
|
71
|
+
if self.error:
|
|
72
|
+
raise self.error
|
|
73
|
+
raise ValueError('{} must equal to {}'.format(parameter, self.equal))
|
|
74
|
+
return parameter
|
|
75
|
+
|
|
76
|
+
def __repr__(self):
|
|
77
|
+
return '{}({})'.format(
|
|
78
|
+
self.__class__.__name__,
|
|
79
|
+
self.equal
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
class IsNotEqualTo(Pattern):
|
|
84
|
+
def __init__(self, equal, error=None):
|
|
85
|
+
self.equal = equal
|
|
86
|
+
self.error = error
|
|
87
|
+
return
|
|
88
|
+
|
|
89
|
+
def __call__(self, parameter):
|
|
90
|
+
if not ne(parameter, self.equal):
|
|
91
|
+
if self.error:
|
|
92
|
+
raise self.error
|
|
93
|
+
raise ValueError('{} must not equal to {}'.format(parameter, self.equal))
|
|
94
|
+
return parameter
|
|
95
|
+
|
|
96
|
+
def __repr__(self):
|
|
97
|
+
return '{}({})'.format(
|
|
98
|
+
self.__class__.__name__,
|
|
99
|
+
self.equal
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
class IsGreaterEqualTo(Pattern):
|
|
104
|
+
def __init__(self, compare, error=None):
|
|
105
|
+
self.compare = compare
|
|
106
|
+
self.error = error
|
|
107
|
+
return
|
|
108
|
+
|
|
109
|
+
def __call__(self, parameter):
|
|
110
|
+
if not ge(parameter, self.compare):
|
|
111
|
+
if self.error:
|
|
112
|
+
raise self.error
|
|
113
|
+
raise ValueError('{} must be greater equal to {}'.format(parameter, self.compare))
|
|
114
|
+
return parameter
|
|
115
|
+
|
|
116
|
+
def __repr__(self):
|
|
117
|
+
return '{}({})'.format(
|
|
118
|
+
self.__class__.__name__,
|
|
119
|
+
self.compare
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
class IsGreaterThan(Pattern):
|
|
124
|
+
def __init__(self, compare, error=None):
|
|
125
|
+
self.compare = compare
|
|
126
|
+
self.error = error
|
|
127
|
+
return
|
|
128
|
+
|
|
129
|
+
def __call__(self, parameter):
|
|
130
|
+
if not gt(parameter, self.compare):
|
|
131
|
+
if self.error:
|
|
132
|
+
raise self.error
|
|
133
|
+
raise ValueError('{} must be greater than {}'.format(parameter, self.compare))
|
|
134
|
+
return parameter
|
|
135
|
+
|
|
136
|
+
def __repr__(self):
|
|
137
|
+
return '{}({})'.format(
|
|
138
|
+
self.__class__.__name__,
|
|
139
|
+
self.compare
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
class IsLessEqualTo(Pattern):
|
|
144
|
+
def __init__(self, compare, error=None):
|
|
145
|
+
self.compare = compare
|
|
146
|
+
self.error = error
|
|
147
|
+
return
|
|
148
|
+
|
|
149
|
+
def __call__(self, parameter):
|
|
150
|
+
if not le(parameter, self.compare):
|
|
151
|
+
if self.error:
|
|
152
|
+
raise self.error
|
|
153
|
+
raise ValueError('{} must be less equal to {}'.format(parameter, self.compare))
|
|
154
|
+
return parameter
|
|
155
|
+
|
|
156
|
+
def __repr__(self):
|
|
157
|
+
return '{}({})'.format(
|
|
158
|
+
self.__class__.__name__,
|
|
159
|
+
self.compare
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
class IsLessThan(Pattern):
|
|
164
|
+
def __init__(self, compare, error=None):
|
|
165
|
+
self.compare = compare
|
|
166
|
+
self.error = error
|
|
167
|
+
return
|
|
168
|
+
|
|
169
|
+
def __call__(self, parameter):
|
|
170
|
+
if not lt(parameter, self.compare):
|
|
171
|
+
if self.error:
|
|
172
|
+
raise self.error
|
|
173
|
+
raise ValueError('{} must be less than {}'.format(parameter, self.compare))
|
|
174
|
+
return parameter
|
|
175
|
+
|
|
176
|
+
def __repr__(self):
|
|
177
|
+
return '{}({})'.format(
|
|
178
|
+
self.__class__.__name__,
|
|
179
|
+
self.compare
|
|
180
|
+
)
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
from ..Pattern import Pattern
|
|
4
|
+
|
|
5
|
+
__all__ = (
|
|
6
|
+
'All',
|
|
7
|
+
'Any',
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class All(Pattern):
|
|
12
|
+
def __init__(self, *args, error=None) -> None:
|
|
13
|
+
self.patterns = args
|
|
14
|
+
self.error = error
|
|
15
|
+
return
|
|
16
|
+
|
|
17
|
+
def __call__(self, parameter):
|
|
18
|
+
try:
|
|
19
|
+
for pattern in self.patterns:
|
|
20
|
+
parameter = pattern(parameter)
|
|
21
|
+
return parameter
|
|
22
|
+
except Exception as e:
|
|
23
|
+
if self.error:
|
|
24
|
+
raise self.error
|
|
25
|
+
raise e
|
|
26
|
+
|
|
27
|
+
def __repr__(self):
|
|
28
|
+
return '{}({})'.format(
|
|
29
|
+
self.__class__.__name__,
|
|
30
|
+
', '.join(
|
|
31
|
+
[p.__repr__() for p in self.patterns]
|
|
32
|
+
)
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class Any(Pattern):
|
|
37
|
+
def __init__(self, *args, error=None) -> None:
|
|
38
|
+
self.patterns = args
|
|
39
|
+
self.error = error
|
|
40
|
+
return
|
|
41
|
+
|
|
42
|
+
def __call__(self, parameter):
|
|
43
|
+
for pattern in self.patterns:
|
|
44
|
+
try:
|
|
45
|
+
parameter = pattern(parameter)
|
|
46
|
+
return parameter
|
|
47
|
+
except Exception:
|
|
48
|
+
pass
|
|
49
|
+
if self.error:
|
|
50
|
+
raise self.error
|
|
51
|
+
raise ValueError('{} must be validated in {}'.format(
|
|
52
|
+
parameter,
|
|
53
|
+
', '.join([p.__repr__() for p in self.patterns])
|
|
54
|
+
))
|
|
55
|
+
|
|
56
|
+
def __repr__(self):
|
|
57
|
+
return '{}({})'.format(
|
|
58
|
+
self.__class__.__name__,
|
|
59
|
+
', '.join([p.__repr__() for p in self.patterns])
|
|
60
|
+
)
|