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,384 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
from .Value import (
|
|
4
|
+
Value,
|
|
5
|
+
Schema,
|
|
6
|
+
OneOf,
|
|
7
|
+
TypeMapper,
|
|
8
|
+
TypeEncoder,
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
from .Types import (
|
|
12
|
+
Boolean,
|
|
13
|
+
Integer,
|
|
14
|
+
Number,
|
|
15
|
+
String,
|
|
16
|
+
Binary,
|
|
17
|
+
Array,
|
|
18
|
+
Object,
|
|
19
|
+
Properties,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
from dataclasses import is_dataclass, MISSING, asdict
|
|
23
|
+
from json import dumps, loads
|
|
24
|
+
from typing import (
|
|
25
|
+
Type,
|
|
26
|
+
Any,
|
|
27
|
+
Union,
|
|
28
|
+
Sequence,
|
|
29
|
+
Iterable,
|
|
30
|
+
Annotated,
|
|
31
|
+
get_origin,
|
|
32
|
+
get_args,
|
|
33
|
+
get_type_hints,
|
|
34
|
+
ForwardRef,
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
__all__ = (
|
|
38
|
+
'SchemaToDataObject',
|
|
39
|
+
'DataObjectToSchema',
|
|
40
|
+
'DataObjectToObject',
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def SchemaToDataObject(o: Schema, name: str = None) -> object:
|
|
45
|
+
# TODO : make dataclass according to schema dynamically
|
|
46
|
+
raise NotImplementedError('SchemaToDataObject is not implemented yet')
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class DataObjectToSchema(object):
|
|
50
|
+
def __init__(self, mapper: TypeMapper = None):
|
|
51
|
+
self.mapper = mapper
|
|
52
|
+
return
|
|
53
|
+
def __value__(
|
|
54
|
+
self,
|
|
55
|
+
o: type,
|
|
56
|
+
format: Union[type, Sequence[type]] = None,
|
|
57
|
+
description: str = None,
|
|
58
|
+
required: bool = True,
|
|
59
|
+
default: Any = MISSING,
|
|
60
|
+
metadata: Any = None,
|
|
61
|
+
) -> Union[Value, Schema]:
|
|
62
|
+
args = get_args(o)
|
|
63
|
+
o = get_origin(o) if get_origin(o) else o
|
|
64
|
+
if args:
|
|
65
|
+
if len(args) == 1:
|
|
66
|
+
if o is list:
|
|
67
|
+
return self.__value__(
|
|
68
|
+
list,
|
|
69
|
+
format=args[0],
|
|
70
|
+
description=description,
|
|
71
|
+
required=required,
|
|
72
|
+
default=default,
|
|
73
|
+
metadata=metadata,
|
|
74
|
+
)
|
|
75
|
+
if o is tuple:
|
|
76
|
+
return self.__value__(
|
|
77
|
+
tuple,
|
|
78
|
+
format=args[0],
|
|
79
|
+
description=description,
|
|
80
|
+
required=required,
|
|
81
|
+
default=default,
|
|
82
|
+
metadata=metadata,
|
|
83
|
+
)
|
|
84
|
+
if o is set:
|
|
85
|
+
return self.__value__(
|
|
86
|
+
set,
|
|
87
|
+
format=args[0],
|
|
88
|
+
description=description,
|
|
89
|
+
required=required,
|
|
90
|
+
default=default,
|
|
91
|
+
metadata=metadata,
|
|
92
|
+
)
|
|
93
|
+
if o is Union:
|
|
94
|
+
return self.__value__(
|
|
95
|
+
Union,
|
|
96
|
+
format=args[0],
|
|
97
|
+
description=description,
|
|
98
|
+
required=required,
|
|
99
|
+
default=default,
|
|
100
|
+
metadata=metadata,
|
|
101
|
+
)
|
|
102
|
+
raise TypeError('{} is not a supported type'.format(o))
|
|
103
|
+
if len(args) == 2:
|
|
104
|
+
if o is Union:
|
|
105
|
+
if args[0] is type(None): # Union[type, None]
|
|
106
|
+
return self.__value__(
|
|
107
|
+
args[1],
|
|
108
|
+
description=description,
|
|
109
|
+
required=False,
|
|
110
|
+
default=None,
|
|
111
|
+
metadata=metadata,
|
|
112
|
+
)
|
|
113
|
+
if args[1] is type(None): # Union[None, type]
|
|
114
|
+
return self.__value__(
|
|
115
|
+
args[0],
|
|
116
|
+
description=description,
|
|
117
|
+
required=False,
|
|
118
|
+
default=None,
|
|
119
|
+
metadata=metadata,
|
|
120
|
+
)
|
|
121
|
+
# Union[type, type]
|
|
122
|
+
return self.__value__(
|
|
123
|
+
o,
|
|
124
|
+
format=(args[0], args[1]),
|
|
125
|
+
description=description,
|
|
126
|
+
required=required,
|
|
127
|
+
default=default,
|
|
128
|
+
metadata=metadata,
|
|
129
|
+
)
|
|
130
|
+
if o is dict: # Dict[type, type]
|
|
131
|
+
return self.__value__(
|
|
132
|
+
dict,
|
|
133
|
+
description=description,
|
|
134
|
+
required=required,
|
|
135
|
+
default=default,
|
|
136
|
+
metadata=metadata,
|
|
137
|
+
)
|
|
138
|
+
if o is Annotated:
|
|
139
|
+
if isinstance(args[1], str):
|
|
140
|
+
return self.__value__(
|
|
141
|
+
args[0],
|
|
142
|
+
description=args[1],
|
|
143
|
+
required=required,
|
|
144
|
+
default=default,
|
|
145
|
+
)
|
|
146
|
+
return self.__value__(
|
|
147
|
+
args[0],
|
|
148
|
+
description=description,
|
|
149
|
+
required=required,
|
|
150
|
+
default=default,
|
|
151
|
+
metadata=args[1],
|
|
152
|
+
)
|
|
153
|
+
raise TypeError('{} is not a supported type'.format(o))
|
|
154
|
+
if o is Union:
|
|
155
|
+
fs= [self.__value__(f) for f in args]
|
|
156
|
+
return OneOf(*fs, required=required)
|
|
157
|
+
if o is Annotated:
|
|
158
|
+
if isinstance(args[1], str):
|
|
159
|
+
return self.__value__(
|
|
160
|
+
args[0],
|
|
161
|
+
description=args[1],
|
|
162
|
+
required=required,
|
|
163
|
+
default=default,
|
|
164
|
+
metadata=args[2] if isinstance(args[2], dict) else args[2:],
|
|
165
|
+
)
|
|
166
|
+
if isinstance(args[2], str):
|
|
167
|
+
return self.__value__(
|
|
168
|
+
args[0],
|
|
169
|
+
description=args[2],
|
|
170
|
+
required=required,
|
|
171
|
+
default=default,
|
|
172
|
+
metadata=args[1],
|
|
173
|
+
)
|
|
174
|
+
return self.__value__(
|
|
175
|
+
args[0],
|
|
176
|
+
description=description,
|
|
177
|
+
required=required,
|
|
178
|
+
default=default,
|
|
179
|
+
metadata=args[1:],
|
|
180
|
+
)
|
|
181
|
+
raise TypeError('{} is not a supported type'.format(o))
|
|
182
|
+
if o is bool:
|
|
183
|
+
kwargs = {
|
|
184
|
+
'description': description,
|
|
185
|
+
'required': required,
|
|
186
|
+
}
|
|
187
|
+
if default is not MISSING:
|
|
188
|
+
kwargs['default'] = default
|
|
189
|
+
if metadata and isinstance(metadata, dict):
|
|
190
|
+
if 'description' in metadata.keys(): kwargs['description'] = metadata['description']
|
|
191
|
+
if 'required' in metadata.keys(): kwargs['required'] = metadata['required']
|
|
192
|
+
return Boolean(**kwargs)
|
|
193
|
+
if o is int:
|
|
194
|
+
kwargs = {
|
|
195
|
+
'description': description,
|
|
196
|
+
'required': required,
|
|
197
|
+
}
|
|
198
|
+
if default is not MISSING:
|
|
199
|
+
kwargs['default'] = default
|
|
200
|
+
if metadata and isinstance(metadata, dict):
|
|
201
|
+
if 'description' in metadata.keys(): kwargs['description'] = metadata['description']
|
|
202
|
+
if 'required' in metadata.keys(): kwargs['required'] = metadata['required']
|
|
203
|
+
if 'format' in metadata.keys(): kwargs['format'] = metadata['format']
|
|
204
|
+
if 'min' in metadata.keys(): kwargs['min'] = metadata['min']
|
|
205
|
+
if 'max' in metadata.keys(): kwargs['max'] = metadata['max']
|
|
206
|
+
if 'enum' in metadata.keys(): kwargs['enum'] = metadata['enum']
|
|
207
|
+
return Integer(**kwargs)
|
|
208
|
+
if o is float:
|
|
209
|
+
kwargs = {
|
|
210
|
+
'description': description,
|
|
211
|
+
'required': required,
|
|
212
|
+
}
|
|
213
|
+
if default is not MISSING:
|
|
214
|
+
kwargs['default'] = default
|
|
215
|
+
if metadata and isinstance(metadata, dict):
|
|
216
|
+
if 'description' in metadata.keys(): kwargs['description'] = metadata['description']
|
|
217
|
+
if 'required' in metadata.keys(): kwargs['required'] = metadata['required']
|
|
218
|
+
if 'format' in metadata.keys(): kwargs['format'] = metadata['format']
|
|
219
|
+
if 'min' in metadata.keys(): kwargs['min'] = metadata['min']
|
|
220
|
+
if 'max' in metadata.keys(): kwargs['max'] = metadata['max']
|
|
221
|
+
if 'enum' in metadata.keys(): kwargs['enum'] = metadata['enum']
|
|
222
|
+
return Number(**kwargs)
|
|
223
|
+
if o is str:
|
|
224
|
+
kwargs = {
|
|
225
|
+
'description': description,
|
|
226
|
+
'required': required,
|
|
227
|
+
}
|
|
228
|
+
if default is not MISSING:
|
|
229
|
+
kwargs['default'] = default
|
|
230
|
+
if metadata and isinstance(metadata, dict):
|
|
231
|
+
if 'description' in metadata.keys(): kwargs['description'] = metadata['description']
|
|
232
|
+
if 'required' in metadata.keys(): kwargs['required'] = metadata['required']
|
|
233
|
+
if 'format' in metadata.keys(): kwargs['format'] = metadata['format']
|
|
234
|
+
if 'min' in metadata.keys(): kwargs['min'] = metadata['min']
|
|
235
|
+
if 'max' in metadata.keys(): kwargs['max'] = metadata['max']
|
|
236
|
+
if 'enum' in metadata.keys(): kwargs['enum'] = metadata['enum']
|
|
237
|
+
return String(**kwargs)
|
|
238
|
+
if o is bytes:
|
|
239
|
+
kwargs = {
|
|
240
|
+
'description': description,
|
|
241
|
+
'required': required,
|
|
242
|
+
}
|
|
243
|
+
if default is not MISSING:
|
|
244
|
+
kwargs['default'] = default
|
|
245
|
+
if metadata and isinstance(metadata, dict):
|
|
246
|
+
if 'description' in metadata.keys(): kwargs['description'] = metadata['description']
|
|
247
|
+
if 'required' in metadata.keys(): kwargs['required'] = metadata['required']
|
|
248
|
+
return Binary(**kwargs)
|
|
249
|
+
if o is list:
|
|
250
|
+
kwargs = {
|
|
251
|
+
'description': description,
|
|
252
|
+
'required': required,
|
|
253
|
+
}
|
|
254
|
+
if default is not MISSING:
|
|
255
|
+
kwargs['default'] = default
|
|
256
|
+
if metadata and isinstance(metadata, dict):
|
|
257
|
+
if 'description' in metadata.keys(): kwargs['description'] = metadata['description']
|
|
258
|
+
if 'required' in metadata.keys(): kwargs['required'] = metadata['required']
|
|
259
|
+
if 'format' in metadata.keys():
|
|
260
|
+
if not isinstance(metadata['format'], Iterable):
|
|
261
|
+
metadata['format'] = [metadata['format']]
|
|
262
|
+
if len(metadata['format']) == 1:
|
|
263
|
+
metadata['format'] = self.__value__(metadata['format'][0])
|
|
264
|
+
fs = [self.__value__(f) for f in metadata['format']]
|
|
265
|
+
kwargs['format'] = OneOf(*fs)
|
|
266
|
+
if format:
|
|
267
|
+
if not isinstance(format, Iterable):
|
|
268
|
+
format = [format]
|
|
269
|
+
if len(format) == 1:
|
|
270
|
+
f = self.__value__(format[0])
|
|
271
|
+
return Array(format=f, **kwargs)
|
|
272
|
+
fs = [self.__value__(f) for f in format]
|
|
273
|
+
return Array(format=OneOf(*fs), **kwargs)
|
|
274
|
+
else:
|
|
275
|
+
return Array(**kwargs)
|
|
276
|
+
if o is tuple:
|
|
277
|
+
kwargs = {
|
|
278
|
+
'description': description,
|
|
279
|
+
'required': required,
|
|
280
|
+
}
|
|
281
|
+
if default is not MISSING:
|
|
282
|
+
kwargs['default'] = default
|
|
283
|
+
if metadata and isinstance(metadata, dict):
|
|
284
|
+
if 'description' in metadata.keys(): kwargs['description'] = metadata['description']
|
|
285
|
+
if 'required' in metadata.keys(): kwargs['required'] = metadata['required']
|
|
286
|
+
return Array(**kwargs)
|
|
287
|
+
if o is set:
|
|
288
|
+
kwargs = {
|
|
289
|
+
'description': description,
|
|
290
|
+
'required': required,
|
|
291
|
+
}
|
|
292
|
+
if default is not MISSING:
|
|
293
|
+
kwargs['default'] = default
|
|
294
|
+
if metadata and isinstance(metadata, dict):
|
|
295
|
+
if 'description' in metadata.keys(): kwargs['description'] = metadata['description']
|
|
296
|
+
if 'required' in metadata.keys(): kwargs['required'] = metadata['required']
|
|
297
|
+
return Array(**kwargs)
|
|
298
|
+
if o is dict:
|
|
299
|
+
kwargs = {
|
|
300
|
+
'description': description,
|
|
301
|
+
'required': required,
|
|
302
|
+
}
|
|
303
|
+
if default is not MISSING:
|
|
304
|
+
kwargs['default'] = default
|
|
305
|
+
if metadata and isinstance(metadata, dict):
|
|
306
|
+
if 'description' in metadata.keys(): kwargs['description'] = metadata['description']
|
|
307
|
+
if 'required' in metadata.keys(): kwargs['required'] = metadata['required']
|
|
308
|
+
return Object(**kwargs)
|
|
309
|
+
if o is Union:
|
|
310
|
+
kwargs = {}
|
|
311
|
+
if default is not MISSING:
|
|
312
|
+
kwargs['default'] = default
|
|
313
|
+
if not format:
|
|
314
|
+
raise TypeError('Union type must have format')
|
|
315
|
+
if not isinstance(format, Iterable):
|
|
316
|
+
format = [format]
|
|
317
|
+
return OneOf(*[self.__value__(f) for f in format], **kwargs)
|
|
318
|
+
if is_dataclass(o):
|
|
319
|
+
return self.__call__(o, required=required)
|
|
320
|
+
if isinstance(o, ForwardRef):
|
|
321
|
+
if o.__forward_arg__ in globals():
|
|
322
|
+
return self.__value__(globals()[o.__forward_arg__], description=description, required=required, default=default, metadata=metadata)
|
|
323
|
+
if o.__forward_arg__ in locals():
|
|
324
|
+
return self.__value__(locals()[o.__forward_arg__], description=description, required=required, default=default, metadata=metadata)
|
|
325
|
+
raise TypeError('Cannot resolve schema forward reference: ' + o.__forward_arg__)
|
|
326
|
+
if self.mapper:
|
|
327
|
+
V, kws = self.mapper(o)
|
|
328
|
+
if V:
|
|
329
|
+
if not issubclass(V, Value):
|
|
330
|
+
raise TypeError('{} is not a Value'.format(V))
|
|
331
|
+
kwargs = {
|
|
332
|
+
'description': description,
|
|
333
|
+
'required': required,
|
|
334
|
+
}
|
|
335
|
+
if default is not MISSING:
|
|
336
|
+
kwargs['default'] = default
|
|
337
|
+
if metadata and isinstance(metadata, dict):
|
|
338
|
+
if 'description' in metadata.keys(): kwargs['description'] = metadata['description']
|
|
339
|
+
if 'required' in metadata.keys(): kwargs['required'] = metadata['required']
|
|
340
|
+
if V in (Integer, Number, String):
|
|
341
|
+
if 'format' in metadata.keys(): kwargs['format'] = metadata['format']
|
|
342
|
+
if 'min' in metadata.keys(): kwargs['min'] = metadata['min']
|
|
343
|
+
if 'max' in metadata.keys(): kwargs['max'] = metadata['max']
|
|
344
|
+
if 'enum' in metadata.keys(): kwargs['enum'] = metadata['enum']
|
|
345
|
+
kwargs.update(kws)
|
|
346
|
+
return V(**kwargs)
|
|
347
|
+
raise TypeError('{} is not a supported type'.format(o))
|
|
348
|
+
|
|
349
|
+
def __call__(self, o: Type[object], description: str = None, required: bool = True) -> Schema:
|
|
350
|
+
if not is_dataclass(o):
|
|
351
|
+
raise TypeError('{} is not a DataObject(dataclass).'.format(o.__name__))
|
|
352
|
+
hints = get_type_hints(o, include_extras=True)
|
|
353
|
+
return Schema(
|
|
354
|
+
name=description or o.__name__,
|
|
355
|
+
format=Object(
|
|
356
|
+
description=description or o.__name__,
|
|
357
|
+
properties=Properties(
|
|
358
|
+
**{
|
|
359
|
+
f.name: self.__value__(
|
|
360
|
+
hints[f.name],
|
|
361
|
+
required=True if f.default is MISSING and f.default_factory is MISSING else False,
|
|
362
|
+
default=f.default_factory() if f.default_factory is not MISSING else f.default,
|
|
363
|
+
) for f in o.__dataclass_fields__.values()
|
|
364
|
+
}
|
|
365
|
+
),
|
|
366
|
+
required=required,
|
|
367
|
+
)
|
|
368
|
+
)
|
|
369
|
+
|
|
370
|
+
|
|
371
|
+
class DataObjectToObject(object):
|
|
372
|
+
def __init__(self, encoder: TypeEncoder = None):
|
|
373
|
+
self.encoder = encoder
|
|
374
|
+
return
|
|
375
|
+
|
|
376
|
+
def __call__(self, o: object):
|
|
377
|
+
if not is_dataclass(o):
|
|
378
|
+
raise TypeError('{} is not a DataObject(dataclass).'.format(o.__class__.__name__))
|
|
379
|
+
_ = dumps(
|
|
380
|
+
asdict(o),
|
|
381
|
+
default=self.encoder,
|
|
382
|
+
ensure_ascii=False,
|
|
383
|
+
)
|
|
384
|
+
return loads(_)
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
from .Value import Descriptor, Type, Value, Condition, Schema
|
|
4
|
+
from typing import Optional, Union, Sequence, Any, Dict, Iterable
|
|
5
|
+
from enum import Enum
|
|
6
|
+
|
|
7
|
+
__all__ = (
|
|
8
|
+
'Boolean',
|
|
9
|
+
'IntegerFormat',
|
|
10
|
+
'Integer',
|
|
11
|
+
'NumberFormat',
|
|
12
|
+
'Number',
|
|
13
|
+
'StringFormat',
|
|
14
|
+
'String',
|
|
15
|
+
'Binary',
|
|
16
|
+
'BinaryBase64Encoded',
|
|
17
|
+
'Array',
|
|
18
|
+
'Object',
|
|
19
|
+
'Properties',
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class Boolean(Value):
|
|
24
|
+
def __init__(
|
|
25
|
+
self,
|
|
26
|
+
description: str = None,
|
|
27
|
+
default: Any = None,
|
|
28
|
+
required: bool = True,
|
|
29
|
+
):
|
|
30
|
+
super().__init__(
|
|
31
|
+
type=Type.Boolean,
|
|
32
|
+
description=description,
|
|
33
|
+
default=default,
|
|
34
|
+
required=required,
|
|
35
|
+
)
|
|
36
|
+
return
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class IntegerFormat(str, Enum):
|
|
40
|
+
int32 = 'int32'
|
|
41
|
+
int64 = 'int64'
|
|
42
|
+
uint32 = 'uint32'
|
|
43
|
+
uint64 = 'uint64'
|
|
44
|
+
byte = 'byte'
|
|
45
|
+
uuid = 'uuid'
|
|
46
|
+
datetime = 'date-time'
|
|
47
|
+
def __str__(self): return self.value
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class Integer(Value):
|
|
51
|
+
def __init__(
|
|
52
|
+
self,
|
|
53
|
+
description: str = None,
|
|
54
|
+
format: Union[str, IntegerFormat] = None,
|
|
55
|
+
min: Any = None,
|
|
56
|
+
max: Any = None,
|
|
57
|
+
default: Any = None,
|
|
58
|
+
enum: Optional[Sequence[str]] = None,
|
|
59
|
+
required: bool = True,
|
|
60
|
+
):
|
|
61
|
+
super().__init__(
|
|
62
|
+
type=Type.Integer,
|
|
63
|
+
description=description,
|
|
64
|
+
format=str(format) if format and isinstance(format, IntegerFormat) else format,
|
|
65
|
+
min=min,
|
|
66
|
+
max=max,
|
|
67
|
+
default=default,
|
|
68
|
+
enum=enum,
|
|
69
|
+
required=required,
|
|
70
|
+
)
|
|
71
|
+
return
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
class NumberFormat(str, Enum):
|
|
75
|
+
float = 'float'
|
|
76
|
+
double = 'double'
|
|
77
|
+
decimal = 'decimal'
|
|
78
|
+
def __str__(self): return self.value
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
class Number(Value):
|
|
82
|
+
def __init__(
|
|
83
|
+
self,
|
|
84
|
+
description: str = None,
|
|
85
|
+
format: Union[str, NumberFormat] = None,
|
|
86
|
+
min: Any = None,
|
|
87
|
+
max: Any = None,
|
|
88
|
+
default: Any = None,
|
|
89
|
+
enum: Optional[Sequence[str]] = None,
|
|
90
|
+
required: bool = True,
|
|
91
|
+
):
|
|
92
|
+
super().__init__(
|
|
93
|
+
type=Type.Number,
|
|
94
|
+
description=description,
|
|
95
|
+
format=str(format) if format and isinstance(format, NumberFormat) else format,
|
|
96
|
+
min=min,
|
|
97
|
+
max=max,
|
|
98
|
+
default=default,
|
|
99
|
+
enum=enum,
|
|
100
|
+
required=required,
|
|
101
|
+
)
|
|
102
|
+
return
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
class StringFormat(str, Enum):
|
|
106
|
+
datetime = 'date-time' # date-time, ISO 8601
|
|
107
|
+
date = 'date' # date, ISO 8601
|
|
108
|
+
time = 'time' # time, ISO 8601
|
|
109
|
+
password = 'password' # password
|
|
110
|
+
byte = 'byte' # byte, base64 encoded
|
|
111
|
+
binary = 'binary' # binary
|
|
112
|
+
email = 'email' # email
|
|
113
|
+
uuid = 'uuid' # uuid
|
|
114
|
+
uri = 'uri' # uri
|
|
115
|
+
hostname = 'hostname' # hostname
|
|
116
|
+
ipv4 = 'ipv4' # ipv4
|
|
117
|
+
ipv6 = 'ipv6' # ipv6
|
|
118
|
+
regex = 'regex' # regex
|
|
119
|
+
xml = 'xml' # xml
|
|
120
|
+
def __str__(self): return self.value
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
class String(Value):
|
|
124
|
+
def __init__(
|
|
125
|
+
self,
|
|
126
|
+
description: str = None,
|
|
127
|
+
format: Union[str, StringFormat] = None,
|
|
128
|
+
min: Any = None,
|
|
129
|
+
max: Any = None,
|
|
130
|
+
default: Any = None,
|
|
131
|
+
enum: Optional[Sequence[str]] = None,
|
|
132
|
+
required: bool = True,
|
|
133
|
+
):
|
|
134
|
+
super().__init__(
|
|
135
|
+
type=Type.String,
|
|
136
|
+
description=description,
|
|
137
|
+
format=str(format) if format and isinstance(format, StringFormat) else format,
|
|
138
|
+
min=min,
|
|
139
|
+
max=max,
|
|
140
|
+
default=default,
|
|
141
|
+
enum=enum,
|
|
142
|
+
required=required,
|
|
143
|
+
)
|
|
144
|
+
if min is not None:
|
|
145
|
+
del self['minimum']
|
|
146
|
+
self['minLength'] = min
|
|
147
|
+
if max is not None:
|
|
148
|
+
del self['maximum']
|
|
149
|
+
self['maxLength'] = max
|
|
150
|
+
return
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
class BinaryBase64Encoded(String):
|
|
154
|
+
def __init__(
|
|
155
|
+
self,
|
|
156
|
+
description: str = None,
|
|
157
|
+
default: str = None,
|
|
158
|
+
required: bool = True,
|
|
159
|
+
):
|
|
160
|
+
super().__init__(
|
|
161
|
+
description=description,
|
|
162
|
+
format=StringFormat.byte,
|
|
163
|
+
default=default,
|
|
164
|
+
required=required,
|
|
165
|
+
)
|
|
166
|
+
return
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
class Binary(String):
|
|
170
|
+
def __init__(
|
|
171
|
+
self,
|
|
172
|
+
description: str = None,
|
|
173
|
+
default: bytes = None,
|
|
174
|
+
required: bool = True,
|
|
175
|
+
):
|
|
176
|
+
super().__init__(
|
|
177
|
+
description=description,
|
|
178
|
+
format=StringFormat.binary,
|
|
179
|
+
default=default,
|
|
180
|
+
required=required,
|
|
181
|
+
)
|
|
182
|
+
return
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
class Properties(Descriptor):
|
|
186
|
+
def __init__(self, **kwargs: Dict[str, Union[Value, Condition, Schema]]):
|
|
187
|
+
for k, v in kwargs.items():
|
|
188
|
+
kwargs[k] = v.format if isinstance(v, Schema) else v
|
|
189
|
+
super().__init__(**kwargs)
|
|
190
|
+
return
|
|
191
|
+
class Object(Descriptor):
|
|
192
|
+
def __init__(
|
|
193
|
+
self,
|
|
194
|
+
description: Optional[str] = None,
|
|
195
|
+
properties: Optional[Properties] = None,
|
|
196
|
+
default: Dict = None,
|
|
197
|
+
required: bool = True,
|
|
198
|
+
):
|
|
199
|
+
properties = properties if properties is not None else Properties()
|
|
200
|
+
super().__init__(
|
|
201
|
+
type=Type.Object,
|
|
202
|
+
properties=properties,
|
|
203
|
+
)
|
|
204
|
+
if description: self['description'] = description
|
|
205
|
+
self['required'] = []
|
|
206
|
+
for k, v in properties.items():
|
|
207
|
+
if hasattr(v, 'required') and getattr(v, 'required'):
|
|
208
|
+
self['required'].append(k)
|
|
209
|
+
if default is not None: self['default'] = default
|
|
210
|
+
self.required = required
|
|
211
|
+
return
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
class Array(Descriptor):
|
|
215
|
+
def __init__(
|
|
216
|
+
self,
|
|
217
|
+
description: str = None,
|
|
218
|
+
format: Optional[Union[Value, Condition, Schema]] = None,
|
|
219
|
+
default: Iterable = None,
|
|
220
|
+
required: bool = True,
|
|
221
|
+
):
|
|
222
|
+
super().__init__(
|
|
223
|
+
type=Type.Array,
|
|
224
|
+
)
|
|
225
|
+
if description: self['description'] = description
|
|
226
|
+
if format: self['items'] = format.format if isinstance(format, Schema) else format
|
|
227
|
+
if default is not None: self['default'] = default
|
|
228
|
+
self.required = required
|
|
229
|
+
return
|