alpha-python 0.1.0__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.
- alpha/__init__.py +0 -0
- alpha/adapters/__init__.py +0 -0
- alpha/adapters/sqla_unit_of_work.py +120 -0
- alpha/domain/__init__.py +0 -0
- alpha/domain/models/__init__.py +0 -0
- alpha/domain/models/base_model.py +25 -0
- alpha/encoder.py +62 -0
- alpha/exceptions.py +99 -0
- alpha/factories/__init__.py +0 -0
- alpha/factories/_type_conversion_matrix.py +233 -0
- alpha/factories/_type_mapping.py +29 -0
- alpha/factories/class_factories.py +496 -0
- alpha/factories/default_field_factory.py +50 -0
- alpha/factories/field_iterator.py +188 -0
- alpha/factories/logging_handler_factory.py +86 -0
- alpha/factories/model_class_factory.py +176 -0
- alpha/factories/models/__init__.py +0 -0
- alpha/factories/models/factory_classes.py +20 -0
- alpha/factories/request_factory.py +211 -0
- alpha/factories/response_factory.py +186 -0
- alpha/factories/type_factories.py +204 -0
- alpha/infra/__init__.py +0 -0
- alpha/infra/database/__init__.py +0 -0
- alpha/infra/database/sql_alchemy_database.py +159 -0
- alpha/infra/database/sql_alchemy_view.py +48 -0
- alpha/infra/models/__init__.py +0 -0
- alpha/infra/models/filter_operators.py +98 -0
- alpha/infra/models/json_patch.py +21 -0
- alpha/infra/models/order_by.py +69 -0
- alpha/infra/models/query_clause.py +45 -0
- alpha/infra/models/search_filter.py +586 -0
- alpha/interfaces/__init__.py +0 -0
- alpha/interfaces/attrs_instance.py +10 -0
- alpha/interfaces/dataclass_instance.py +11 -0
- alpha/interfaces/factories.py +102 -0
- alpha/interfaces/openapi_model.py +21 -0
- alpha/interfaces/patchable.py +8 -0
- alpha/interfaces/sql_database.py +36 -0
- alpha/interfaces/sql_mapper.py +23 -0
- alpha/interfaces/sql_repository.py +380 -0
- alpha/interfaces/token_factory.py +56 -0
- alpha/interfaces/unit_of_work.py +53 -0
- alpha/interfaces/updateable.py +7 -0
- alpha/py.typed +0 -0
- alpha/repositories/__init__.py +0 -0
- alpha/repositories/default_sql_repository.py +679 -0
- alpha/repositories/models/__init__.py +0 -0
- alpha/repositories/models/repository_model.py +16 -0
- alpha/services/__init__.py +0 -0
- alpha/services/authentication_service.py +71 -0
- alpha/utils/__init__.py +0 -0
- alpha/utils/_http_codes.py +148 -0
- alpha/utils/is_attrs.py +18 -0
- alpha/utils/logging_configurator.py +133 -0
- alpha/utils/logging_level_checker.py +26 -0
- alpha/utils/response_object.py +26 -0
- alpha/utils/version_check.py +17 -0
- alpha_python-0.1.0.dist-info/METADATA +22 -0
- alpha_python-0.1.0.dist-info/RECORD +62 -0
- alpha_python-0.1.0.dist-info/WHEEL +5 -0
- alpha_python-0.1.0.dist-info/licenses/LICENSE +21 -0
- alpha_python-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,496 @@
|
|
|
1
|
+
"""Contains these ClassFactory classes:
|
|
2
|
+
- IterableClassFactory
|
|
3
|
+
- DictClassFactory
|
|
4
|
+
- DataclassClassFactory
|
|
5
|
+
- GenericAliasClassFactory
|
|
6
|
+
- UnionClassFactory
|
|
7
|
+
- NativeClassFactory
|
|
8
|
+
- EnumClassFactory
|
|
9
|
+
- AnyClassFactory
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
import enum
|
|
13
|
+
import sys
|
|
14
|
+
import types
|
|
15
|
+
import typing
|
|
16
|
+
from dataclasses import is_dataclass
|
|
17
|
+
from typing import Any, Iterable, Optional, Union, get_args, get_origin
|
|
18
|
+
|
|
19
|
+
from alpha import exceptions
|
|
20
|
+
from alpha.factories._type_mapping import TYPES
|
|
21
|
+
from alpha.factories.field_iterator import Field
|
|
22
|
+
from alpha.infra.models.json_patch import JsonPatch
|
|
23
|
+
from alpha.interfaces.factories import (
|
|
24
|
+
FactoryClassesInstance,
|
|
25
|
+
)
|
|
26
|
+
from alpha.interfaces.openapi_model import OpenAPIModel
|
|
27
|
+
from alpha.utils.is_attrs import is_attrs
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class IterableClassFactory:
|
|
31
|
+
def process(
|
|
32
|
+
self,
|
|
33
|
+
obj: OpenAPIModel,
|
|
34
|
+
field: Field,
|
|
35
|
+
factory_classes: FactoryClassesInstance,
|
|
36
|
+
) -> Any:
|
|
37
|
+
"""Processing iterable classes. Mapping the items of the corresponding
|
|
38
|
+
OpenAPIModel instance attribute and return them in an iterable of the
|
|
39
|
+
field.type
|
|
40
|
+
|
|
41
|
+
Parameters
|
|
42
|
+
----------
|
|
43
|
+
obj
|
|
44
|
+
OpenAPIModel instance
|
|
45
|
+
field
|
|
46
|
+
Field object of dataclass attribute
|
|
47
|
+
factory_classes
|
|
48
|
+
FactoryClasses instance which acts as a toolbox of Factory classes
|
|
49
|
+
|
|
50
|
+
Returns
|
|
51
|
+
-------
|
|
52
|
+
The new iterable object
|
|
53
|
+
|
|
54
|
+
Raises
|
|
55
|
+
------
|
|
56
|
+
exceptions.TypingFactoryException
|
|
57
|
+
Unable to convert an iterable to a certain iterable type
|
|
58
|
+
"""
|
|
59
|
+
field_type_origin = get_origin(field.type)
|
|
60
|
+
field_args = get_args(field.type)
|
|
61
|
+
|
|
62
|
+
values: Union[Iterable[Any], Any, None] = getattr(
|
|
63
|
+
obj, field.name, None
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
if not isinstance(values, Iterable):
|
|
67
|
+
values = [values]
|
|
68
|
+
|
|
69
|
+
cls = field_args[0]
|
|
70
|
+
|
|
71
|
+
if is_dataclass(cls) or is_attrs(cls):
|
|
72
|
+
if factory_classes.model_class_factory is None:
|
|
73
|
+
raise ValueError(
|
|
74
|
+
"ModelClassFactory instance is not present in "
|
|
75
|
+
"FactoryClasses instance"
|
|
76
|
+
)
|
|
77
|
+
collection = [
|
|
78
|
+
factory_classes.model_class_factory.process(obj=obj, cls=cls)
|
|
79
|
+
for obj in values
|
|
80
|
+
]
|
|
81
|
+
else:
|
|
82
|
+
if not getattr(obj, field.name, None):
|
|
83
|
+
return factory_classes.default_factory.process(field=field)
|
|
84
|
+
|
|
85
|
+
if isinstance(cls, type(enum.Enum)):
|
|
86
|
+
type_factory = factory_classes.type_factories["enum"]
|
|
87
|
+
else:
|
|
88
|
+
try:
|
|
89
|
+
type_factory = TYPES[cls]()
|
|
90
|
+
except KeyError as exc:
|
|
91
|
+
raise exceptions.ClassFactoryException(
|
|
92
|
+
"The class of this object type is not supported. "
|
|
93
|
+
f"{field.type=}; "
|
|
94
|
+
f"{field_type_origin=}; "
|
|
95
|
+
f"{field.type.__class__=}; "
|
|
96
|
+
) from exc
|
|
97
|
+
|
|
98
|
+
collection = [
|
|
99
|
+
type_factory.process(
|
|
100
|
+
key=field.name,
|
|
101
|
+
value=val,
|
|
102
|
+
cls=cls,
|
|
103
|
+
)
|
|
104
|
+
for val in values
|
|
105
|
+
]
|
|
106
|
+
|
|
107
|
+
try:
|
|
108
|
+
if field_type_origin:
|
|
109
|
+
result = field_type_origin(collection)
|
|
110
|
+
return result
|
|
111
|
+
except ValueError as exc:
|
|
112
|
+
raise exceptions.TypingFactoryException(
|
|
113
|
+
"Unable to convert a collection of "
|
|
114
|
+
f"{type(collection[0])} "
|
|
115
|
+
f"instances to a {field_type_origin}: {exc}"
|
|
116
|
+
) from exc
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
class DictClassFactory:
|
|
120
|
+
def process(
|
|
121
|
+
self,
|
|
122
|
+
obj: OpenAPIModel,
|
|
123
|
+
field: Field,
|
|
124
|
+
factory_classes: FactoryClassesInstance,
|
|
125
|
+
) -> Any:
|
|
126
|
+
"""Processing dictionary classes. Considering multiple options to get a
|
|
127
|
+
dictionary from an object.
|
|
128
|
+
|
|
129
|
+
Parameters
|
|
130
|
+
----------
|
|
131
|
+
obj
|
|
132
|
+
OpenAPIModel instance
|
|
133
|
+
field
|
|
134
|
+
Field object of dataclass attribute
|
|
135
|
+
factory_classes
|
|
136
|
+
Unused for this implementation of the ClassFactory interface
|
|
137
|
+
|
|
138
|
+
Returns
|
|
139
|
+
-------
|
|
140
|
+
Dictionary object
|
|
141
|
+
|
|
142
|
+
Raises
|
|
143
|
+
------
|
|
144
|
+
exceptions.ObjectConversionError
|
|
145
|
+
Unable to return a dictionary
|
|
146
|
+
"""
|
|
147
|
+
value: Union[dict[str, Any], Any] = getattr(obj, field.name, None)
|
|
148
|
+
|
|
149
|
+
if isinstance(value, dict):
|
|
150
|
+
return value
|
|
151
|
+
if hasattr(value, "to_dict"):
|
|
152
|
+
return getattr(value, "to_dict")()
|
|
153
|
+
if hasattr(value, "_asdict"):
|
|
154
|
+
return getattr(value, "_asdict")()
|
|
155
|
+
if hasattr(value, "__dict__"):
|
|
156
|
+
return value.__dict__
|
|
157
|
+
try:
|
|
158
|
+
return dict(value)
|
|
159
|
+
except (TypeError, ValueError) as exc:
|
|
160
|
+
raise exceptions.ObjectConversionError(
|
|
161
|
+
f'Unable to convert a(n) "{type(value)}" object to a dict'
|
|
162
|
+
) from exc
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
class DataclassClassFactory:
|
|
166
|
+
def process(
|
|
167
|
+
self,
|
|
168
|
+
obj: OpenAPIModel,
|
|
169
|
+
field: Field,
|
|
170
|
+
factory_classes: FactoryClassesInstance,
|
|
171
|
+
) -> Any:
|
|
172
|
+
"""Processing dataclass classes by using the model_class_factory from
|
|
173
|
+
the factory_class instance
|
|
174
|
+
|
|
175
|
+
Parameters
|
|
176
|
+
----------
|
|
177
|
+
obj
|
|
178
|
+
OpenAPIModel instance
|
|
179
|
+
field
|
|
180
|
+
Field object of dataclass attribute
|
|
181
|
+
factory_classes
|
|
182
|
+
FactoryClasses instance which acts as a toolbox of Factory classes
|
|
183
|
+
|
|
184
|
+
Returns
|
|
185
|
+
-------
|
|
186
|
+
DataclassInterface object
|
|
187
|
+
|
|
188
|
+
Raises
|
|
189
|
+
------
|
|
190
|
+
ValueError
|
|
191
|
+
factory_classes.model_class_factory is None
|
|
192
|
+
"""
|
|
193
|
+
if hasattr(obj, field.name):
|
|
194
|
+
obj = getattr(obj, field.name)
|
|
195
|
+
type_ = field.type
|
|
196
|
+
if factory_classes.model_class_factory is None:
|
|
197
|
+
raise ValueError(
|
|
198
|
+
"ModelClassFactory instance is not present in FactoryClasses "
|
|
199
|
+
"instance"
|
|
200
|
+
)
|
|
201
|
+
return factory_classes.model_class_factory.process(obj=obj, cls=type_)
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
class GenericAliasClassFactory:
|
|
205
|
+
def process(
|
|
206
|
+
self,
|
|
207
|
+
obj: OpenAPIModel,
|
|
208
|
+
field: Field,
|
|
209
|
+
factory_classes: FactoryClassesInstance,
|
|
210
|
+
) -> Any:
|
|
211
|
+
"""Processing generic alias types. Built-in type subclasses from both
|
|
212
|
+
typing._GenericAlias and types.GenericAlias are supported. It uses the
|
|
213
|
+
ClassFactory for iterables and dictionaries, from the class_factories
|
|
214
|
+
attribute of the FactoryClassesInstance, to process each type.
|
|
215
|
+
|
|
216
|
+
These examples are all supported:
|
|
217
|
+
- dict[str, Any]
|
|
218
|
+
- typing.Tuple[int]
|
|
219
|
+
- set[float]
|
|
220
|
+
- list[Object]
|
|
221
|
+
|
|
222
|
+
An exception will be raised when a union argument is used because only
|
|
223
|
+
one argument (two in case of a dict) is supported.
|
|
224
|
+
|
|
225
|
+
Parameters
|
|
226
|
+
----------
|
|
227
|
+
obj
|
|
228
|
+
OpenAPIModel instance
|
|
229
|
+
field
|
|
230
|
+
Field object of dataclass attribute
|
|
231
|
+
factory_classes
|
|
232
|
+
FactoryClasses instance which acts as a toolbox of Factory classes
|
|
233
|
+
|
|
234
|
+
Returns
|
|
235
|
+
-------
|
|
236
|
+
An iterable or a dictionary
|
|
237
|
+
|
|
238
|
+
Raises
|
|
239
|
+
------
|
|
240
|
+
exceptions.MixedArgumentTypesError
|
|
241
|
+
Unable to process a union argument type. eg: list[int | float]
|
|
242
|
+
exceptions.TypingFactoryException
|
|
243
|
+
Catching any future generic alias type
|
|
244
|
+
"""
|
|
245
|
+
field_type = get_origin(field.type)
|
|
246
|
+
field_args = get_args(field.type)
|
|
247
|
+
|
|
248
|
+
arg_classes = [
|
|
249
|
+
getattr(typing, "_UnionGenericAlias"),
|
|
250
|
+
]
|
|
251
|
+
if sys.version_info.minor >= 10: # Backwards compatible with <3.10
|
|
252
|
+
arg_classes.append(getattr(types, "UnionType"))
|
|
253
|
+
|
|
254
|
+
for arg in field_args:
|
|
255
|
+
if arg.__class__ in arg_classes:
|
|
256
|
+
raise exceptions.MixedArgumentTypesError(
|
|
257
|
+
f"Mixed object types in a '{field_type}' are not allowed"
|
|
258
|
+
)
|
|
259
|
+
|
|
260
|
+
if field_type in (list, tuple, set, frozenset):
|
|
261
|
+
return factory_classes.class_factories["iterable"].process(
|
|
262
|
+
obj=obj,
|
|
263
|
+
field=field,
|
|
264
|
+
factory_classes=factory_classes,
|
|
265
|
+
)
|
|
266
|
+
if field_type is dict:
|
|
267
|
+
return factory_classes.class_factories["dict"].process(
|
|
268
|
+
obj=obj,
|
|
269
|
+
field=field,
|
|
270
|
+
factory_classes=factory_classes,
|
|
271
|
+
)
|
|
272
|
+
raise exceptions.TypingFactoryException(
|
|
273
|
+
f"Mapping a '{field_type}' type is not supported"
|
|
274
|
+
)
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
class UnionClassFactory:
|
|
278
|
+
def process(
|
|
279
|
+
self,
|
|
280
|
+
obj: OpenAPIModel,
|
|
281
|
+
field: Field,
|
|
282
|
+
factory_classes: FactoryClassesInstance,
|
|
283
|
+
) -> Any:
|
|
284
|
+
"""Processing union types. Both typing._UnionGenericAlias and
|
|
285
|
+
types.UnionType are supported, eg. `typing.Union[int, float]` or
|
|
286
|
+
`int | float`.
|
|
287
|
+
|
|
288
|
+
These rules are being applied:
|
|
289
|
+
- If the first argument is a dataclass or attrs class all other
|
|
290
|
+
arguments will be ignored
|
|
291
|
+
- If the value is of one of the types in the union arguments the
|
|
292
|
+
value will be returned untouched
|
|
293
|
+
- If the value type is not in the union arguments, the value will
|
|
294
|
+
be processed by the GenericTypeClass, to try to map the
|
|
295
|
+
value to match the type of the first union argument
|
|
296
|
+
|
|
297
|
+
Parameters
|
|
298
|
+
----------
|
|
299
|
+
obj
|
|
300
|
+
OpenAPIModel instance
|
|
301
|
+
field
|
|
302
|
+
Field object of dataclass attribute
|
|
303
|
+
factory_classes
|
|
304
|
+
FactoryClasses instance which acts as a toolbox of Factory classes
|
|
305
|
+
|
|
306
|
+
Returns
|
|
307
|
+
-------
|
|
308
|
+
Any value with a type of one of the union arguments
|
|
309
|
+
|
|
310
|
+
Raises
|
|
311
|
+
------
|
|
312
|
+
ValueError
|
|
313
|
+
factory_classes.model_class_factory is None
|
|
314
|
+
exceptions.UnionArgumentError
|
|
315
|
+
The attributes value of the OpenAPIModel instance is not compatible
|
|
316
|
+
with one of the types in the union type arguments
|
|
317
|
+
"""
|
|
318
|
+
value = getattr(obj, field.name, None)
|
|
319
|
+
if not value:
|
|
320
|
+
return factory_classes.default_factory.process(field=field)
|
|
321
|
+
|
|
322
|
+
args = get_args(field.type)
|
|
323
|
+
cls = args[0]
|
|
324
|
+
|
|
325
|
+
if is_dataclass(cls) or is_attrs(cls):
|
|
326
|
+
if factory_classes.model_class_factory is None:
|
|
327
|
+
raise ValueError(
|
|
328
|
+
"ModelClassFactory instance is not present in "
|
|
329
|
+
"FactoryClasses instance"
|
|
330
|
+
)
|
|
331
|
+
return factory_classes.model_class_factory.process(
|
|
332
|
+
obj=obj, cls=cls
|
|
333
|
+
)
|
|
334
|
+
if type(value) in args:
|
|
335
|
+
return value
|
|
336
|
+
try:
|
|
337
|
+
return factory_classes.type_factories["generic"].process(
|
|
338
|
+
key=field.name, value=value, cls=cls
|
|
339
|
+
)
|
|
340
|
+
except Exception as exc:
|
|
341
|
+
raise exceptions.UnionArgumentError(
|
|
342
|
+
f"{cls} is of a type that is not compatible with the type "
|
|
343
|
+
+ "arguments in the union. Casting the value is not possible"
|
|
344
|
+
) from exc
|
|
345
|
+
|
|
346
|
+
|
|
347
|
+
class NativeClassFactory:
|
|
348
|
+
def process(
|
|
349
|
+
self,
|
|
350
|
+
obj: OpenAPIModel,
|
|
351
|
+
field: Field,
|
|
352
|
+
factory_classes: FactoryClassesInstance,
|
|
353
|
+
) -> Optional[Any]:
|
|
354
|
+
"""Processing native types. Native types are all types that have a
|
|
355
|
+
`type` value for the `__class__` attribute.
|
|
356
|
+
|
|
357
|
+
The supported types are present in the keys of the TYPES constant and
|
|
358
|
+
are processed by their corresponding type factories. A dataclass or
|
|
359
|
+
attrs type class will be processed by the DataclassClassFactory.
|
|
360
|
+
|
|
361
|
+
Parameters
|
|
362
|
+
----------
|
|
363
|
+
obj
|
|
364
|
+
OpenAPIModel instance
|
|
365
|
+
field
|
|
366
|
+
Field object of dataclass attribute
|
|
367
|
+
factory_classes
|
|
368
|
+
FactoryClasses instance which acts as a toolbox of Factory classes
|
|
369
|
+
|
|
370
|
+
Returns
|
|
371
|
+
-------
|
|
372
|
+
Any value which is returned by another Factory
|
|
373
|
+
|
|
374
|
+
Raises
|
|
375
|
+
------
|
|
376
|
+
KeyError
|
|
377
|
+
In case the type is not present in TYPES
|
|
378
|
+
"""
|
|
379
|
+
# Backwards compatibility for python 3.9/10
|
|
380
|
+
if get_args(field.type):
|
|
381
|
+
return factory_classes.class_factories["generic_alias"].process(
|
|
382
|
+
obj=obj, field=field, factory_classes=factory_classes
|
|
383
|
+
)
|
|
384
|
+
|
|
385
|
+
value = getattr(obj, field.name, None)
|
|
386
|
+
cls: type = field.type # type: ignore
|
|
387
|
+
|
|
388
|
+
# return the value untouched if it is an instance of cls
|
|
389
|
+
if isinstance(value, cls):
|
|
390
|
+
return value
|
|
391
|
+
|
|
392
|
+
if is_dataclass(cls) or is_attrs(cls):
|
|
393
|
+
return factory_classes.class_factories["dataclass"].process(
|
|
394
|
+
obj=obj, field=field, factory_classes=factory_classes
|
|
395
|
+
)
|
|
396
|
+
if cls == JsonPatch:
|
|
397
|
+
return factory_classes.class_factories["json_patch"].process(
|
|
398
|
+
obj=obj, field=field, factory_classes=factory_classes
|
|
399
|
+
)
|
|
400
|
+
try:
|
|
401
|
+
if value:
|
|
402
|
+
type_factory = TYPES[cls]
|
|
403
|
+
return type_factory().process(
|
|
404
|
+
key=field.name,
|
|
405
|
+
value=value,
|
|
406
|
+
cls=cls,
|
|
407
|
+
)
|
|
408
|
+
return factory_classes.default_factory.process(field=field)
|
|
409
|
+
except KeyError as exc:
|
|
410
|
+
raise KeyError(
|
|
411
|
+
f"This attributes type is not supported: {field.type}"
|
|
412
|
+
) from exc
|
|
413
|
+
|
|
414
|
+
|
|
415
|
+
class EnumClassFactory:
|
|
416
|
+
def process(
|
|
417
|
+
self,
|
|
418
|
+
obj: OpenAPIModel,
|
|
419
|
+
field: Field,
|
|
420
|
+
factory_classes: FactoryClassesInstance,
|
|
421
|
+
) -> Optional[enum.Enum]:
|
|
422
|
+
"""Processing Enum types. This class acts as an adapter for the
|
|
423
|
+
EnumTypeFactory.
|
|
424
|
+
|
|
425
|
+
Parameters
|
|
426
|
+
----------
|
|
427
|
+
obj
|
|
428
|
+
OpenAPIModel instance
|
|
429
|
+
field
|
|
430
|
+
Field object of dataclass attribute
|
|
431
|
+
factory_classes
|
|
432
|
+
FactoryClasses instance which acts as a toolbox of Factory classes
|
|
433
|
+
|
|
434
|
+
Returns
|
|
435
|
+
-------
|
|
436
|
+
An enum instance
|
|
437
|
+
"""
|
|
438
|
+
return factory_classes.type_factories["enum"].process(
|
|
439
|
+
key=field.name, value=getattr(obj, field.name), cls=field.type
|
|
440
|
+
)
|
|
441
|
+
|
|
442
|
+
|
|
443
|
+
class JsonPatchClassFactory:
|
|
444
|
+
def process(
|
|
445
|
+
self,
|
|
446
|
+
obj: OpenAPIModel,
|
|
447
|
+
field: Field,
|
|
448
|
+
factory_classes: FactoryClassesInstance,
|
|
449
|
+
) -> Optional[JsonPatch]:
|
|
450
|
+
"""Processing JsonPatch types. This class acts as an adapter for the
|
|
451
|
+
JsonPatchTypeFactory.
|
|
452
|
+
|
|
453
|
+
Parameters
|
|
454
|
+
----------
|
|
455
|
+
obj
|
|
456
|
+
OpenAPIModel instance
|
|
457
|
+
field
|
|
458
|
+
Field object of dataclass attribute
|
|
459
|
+
factory_classes
|
|
460
|
+
FactoryClasses instance which acts as a toolbox of Factory classes
|
|
461
|
+
|
|
462
|
+
Returns
|
|
463
|
+
-------
|
|
464
|
+
An JsonPatch instance
|
|
465
|
+
"""
|
|
466
|
+
return factory_classes.type_factories["json_patch"].process(
|
|
467
|
+
key=field.name, value=getattr(obj, field.name), cls=field.type
|
|
468
|
+
)
|
|
469
|
+
|
|
470
|
+
|
|
471
|
+
class AnyClassFactory:
|
|
472
|
+
def process(
|
|
473
|
+
self,
|
|
474
|
+
obj: OpenAPIModel,
|
|
475
|
+
field: Field,
|
|
476
|
+
factory_classes: FactoryClassesInstance,
|
|
477
|
+
) -> Any:
|
|
478
|
+
"""Processing Any types.
|
|
479
|
+
|
|
480
|
+
Parameters
|
|
481
|
+
----------
|
|
482
|
+
obj
|
|
483
|
+
OpenAPIModel instance
|
|
484
|
+
field
|
|
485
|
+
Field object of dataclass attribute
|
|
486
|
+
factory_classes
|
|
487
|
+
FactoryClasses instance which acts as a toolbox of Factory classes
|
|
488
|
+
|
|
489
|
+
Returns
|
|
490
|
+
-------
|
|
491
|
+
Any value
|
|
492
|
+
"""
|
|
493
|
+
value = getattr(obj, field.name, None)
|
|
494
|
+
if not value:
|
|
495
|
+
return factory_classes.default_factory.process(field=field)
|
|
496
|
+
return value
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"""Contains DefaultFieldFactory class"""
|
|
2
|
+
|
|
3
|
+
from dataclasses import _MISSING_TYPE # type: ignore
|
|
4
|
+
from typing import Any, get_args
|
|
5
|
+
|
|
6
|
+
from alpha import exceptions
|
|
7
|
+
from alpha.factories.field_iterator import Field
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class DefaultFieldFactory:
|
|
11
|
+
def process(self, field: Field) -> Any:
|
|
12
|
+
"""Processes the default value from the field object of a dataclass
|
|
13
|
+
attribute
|
|
14
|
+
|
|
15
|
+
Parameters
|
|
16
|
+
----------
|
|
17
|
+
field
|
|
18
|
+
field object of a dataclass attribute
|
|
19
|
+
|
|
20
|
+
Returns
|
|
21
|
+
-------
|
|
22
|
+
The default value found in the field object
|
|
23
|
+
|
|
24
|
+
Raises
|
|
25
|
+
------
|
|
26
|
+
exceptions.DefaultFactoryException
|
|
27
|
+
- When None is allowed by typing but a default value is missing
|
|
28
|
+
- When a default value is missing and the attribute cannot be empty
|
|
29
|
+
- In case of an unknown error
|
|
30
|
+
"""
|
|
31
|
+
if hasattr(field, "default_factory"):
|
|
32
|
+
if callable(field.default_factory):
|
|
33
|
+
return field.default_factory()
|
|
34
|
+
if callable(field.default):
|
|
35
|
+
return field.default()
|
|
36
|
+
if not isinstance(field.default, _MISSING_TYPE):
|
|
37
|
+
return field.default
|
|
38
|
+
if type(None) in get_args(field.type):
|
|
39
|
+
raise exceptions.DefaultFactoryException(
|
|
40
|
+
f'None is allowed by typing for the "{field.name}" '
|
|
41
|
+
"attribute, but a default value is missing"
|
|
42
|
+
)
|
|
43
|
+
if isinstance(field.default, _MISSING_TYPE): # type: ignore
|
|
44
|
+
raise exceptions.DefaultFactoryException(
|
|
45
|
+
f'The source object has no "{field.name}" attribute and no '
|
|
46
|
+
"default value is set"
|
|
47
|
+
)
|
|
48
|
+
raise exceptions.DefaultFactoryException(
|
|
49
|
+
"Unknown default_factory exception"
|
|
50
|
+
)
|