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.
Files changed (62) hide show
  1. alpha/__init__.py +0 -0
  2. alpha/adapters/__init__.py +0 -0
  3. alpha/adapters/sqla_unit_of_work.py +120 -0
  4. alpha/domain/__init__.py +0 -0
  5. alpha/domain/models/__init__.py +0 -0
  6. alpha/domain/models/base_model.py +25 -0
  7. alpha/encoder.py +62 -0
  8. alpha/exceptions.py +99 -0
  9. alpha/factories/__init__.py +0 -0
  10. alpha/factories/_type_conversion_matrix.py +233 -0
  11. alpha/factories/_type_mapping.py +29 -0
  12. alpha/factories/class_factories.py +496 -0
  13. alpha/factories/default_field_factory.py +50 -0
  14. alpha/factories/field_iterator.py +188 -0
  15. alpha/factories/logging_handler_factory.py +86 -0
  16. alpha/factories/model_class_factory.py +176 -0
  17. alpha/factories/models/__init__.py +0 -0
  18. alpha/factories/models/factory_classes.py +20 -0
  19. alpha/factories/request_factory.py +211 -0
  20. alpha/factories/response_factory.py +186 -0
  21. alpha/factories/type_factories.py +204 -0
  22. alpha/infra/__init__.py +0 -0
  23. alpha/infra/database/__init__.py +0 -0
  24. alpha/infra/database/sql_alchemy_database.py +159 -0
  25. alpha/infra/database/sql_alchemy_view.py +48 -0
  26. alpha/infra/models/__init__.py +0 -0
  27. alpha/infra/models/filter_operators.py +98 -0
  28. alpha/infra/models/json_patch.py +21 -0
  29. alpha/infra/models/order_by.py +69 -0
  30. alpha/infra/models/query_clause.py +45 -0
  31. alpha/infra/models/search_filter.py +586 -0
  32. alpha/interfaces/__init__.py +0 -0
  33. alpha/interfaces/attrs_instance.py +10 -0
  34. alpha/interfaces/dataclass_instance.py +11 -0
  35. alpha/interfaces/factories.py +102 -0
  36. alpha/interfaces/openapi_model.py +21 -0
  37. alpha/interfaces/patchable.py +8 -0
  38. alpha/interfaces/sql_database.py +36 -0
  39. alpha/interfaces/sql_mapper.py +23 -0
  40. alpha/interfaces/sql_repository.py +380 -0
  41. alpha/interfaces/token_factory.py +56 -0
  42. alpha/interfaces/unit_of_work.py +53 -0
  43. alpha/interfaces/updateable.py +7 -0
  44. alpha/py.typed +0 -0
  45. alpha/repositories/__init__.py +0 -0
  46. alpha/repositories/default_sql_repository.py +679 -0
  47. alpha/repositories/models/__init__.py +0 -0
  48. alpha/repositories/models/repository_model.py +16 -0
  49. alpha/services/__init__.py +0 -0
  50. alpha/services/authentication_service.py +71 -0
  51. alpha/utils/__init__.py +0 -0
  52. alpha/utils/_http_codes.py +148 -0
  53. alpha/utils/is_attrs.py +18 -0
  54. alpha/utils/logging_configurator.py +133 -0
  55. alpha/utils/logging_level_checker.py +26 -0
  56. alpha/utils/response_object.py +26 -0
  57. alpha/utils/version_check.py +17 -0
  58. alpha_python-0.1.0.dist-info/METADATA +22 -0
  59. alpha_python-0.1.0.dist-info/RECORD +62 -0
  60. alpha_python-0.1.0.dist-info/WHEEL +5 -0
  61. alpha_python-0.1.0.dist-info/licenses/LICENSE +21 -0
  62. alpha_python-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,188 @@
1
+ """Contains Field & FieldIterator class"""
2
+
3
+ import dataclasses
4
+ import attrs
5
+ from typing import Any
6
+
7
+ from alpha.interfaces.attrs_instance import AttrsInstance
8
+ from alpha.interfaces.dataclass_instance import DataclassInstance
9
+ from alpha.utils.is_attrs import is_attrs
10
+
11
+
12
+ class Field:
13
+ """An object which is used in ModelClassFactory & ClassFactory instances
14
+ to share specific values about class attributes
15
+ """
16
+
17
+ def __init__(
18
+ self,
19
+ init: bool,
20
+ name: str,
21
+ type_: Any,
22
+ default: Any,
23
+ default_factory: Any = None,
24
+ ) -> None:
25
+ """Initialize a Field object
26
+
27
+ Parameters
28
+ ----------
29
+ init
30
+ init value
31
+ name
32
+ name value
33
+ type_
34
+ type value. Can be an actual type or the string name of the type
35
+ in which case the value will be evaluated to extract the type
36
+ default
37
+ default value
38
+ default_factory, optional
39
+ default value if present, by default None
40
+ """
41
+ self.init = init
42
+ self.name = name
43
+ self.default = default
44
+ self.default_factory = default_factory
45
+
46
+ if isinstance(type_, str):
47
+ try:
48
+ self.type = eval(type_)
49
+ except NameError as exc:
50
+ raise NameError(
51
+ f"Unable to evaluate '{type_}' as a type: {exc}.\n"
52
+ "A string value is found as type annotation of a class "
53
+ "attribute. This behavure is probably caused by importing "
54
+ "__future__.annotations in the module of a data class. "
55
+ "This behavure is also described in PEP563 "
56
+ "(https://peps.python.org/pep-0563/). Try not importing "
57
+ "__future__.annotations."
58
+ )
59
+ else:
60
+ self.type = type_
61
+
62
+ def __repr__(self) -> str:
63
+ """Creates a string representation of the object
64
+
65
+ Returns
66
+ -------
67
+ string representation of the object
68
+ """
69
+ return (
70
+ "Field("
71
+ f"name={self.name!r},"
72
+ f"type={self.type!r},"
73
+ f"default={self.default!r},"
74
+ f"default_factory={self.default_factory!r},"
75
+ f"init={self.init!r}"
76
+ ")"
77
+ )
78
+
79
+ @classmethod
80
+ def from_dataclass(cls, obj: dataclasses.Field[Any]) -> "Field":
81
+ """Create a Field object from a dataclass Field
82
+
83
+ Parameters
84
+ ----------
85
+ obj
86
+ dataclass Field
87
+
88
+ Returns
89
+ -------
90
+ Field object
91
+ """
92
+ return cls(
93
+ init=obj.init,
94
+ name=obj.name,
95
+ type_=obj.type,
96
+ default=obj.default,
97
+ default_factory=obj.default_factory,
98
+ )
99
+
100
+ @classmethod
101
+ def from_attrs(cls, obj: attrs.Attribute) -> "Field": # type: ignore
102
+ """Create a Field object from a attrs Attribute
103
+
104
+ Parameters
105
+ ----------
106
+ obj
107
+ attrs Attribute
108
+
109
+ Returns
110
+ -------
111
+ Field object
112
+ """
113
+ return cls(
114
+ init=obj.init,
115
+ name=obj.name,
116
+ type_=obj.type, # type: ignore
117
+ default=obj.default, # type: ignore
118
+ )
119
+
120
+
121
+ class FieldIterator:
122
+ """A collection of Field objects"""
123
+
124
+ def __init__(self, obj: DataclassInstance | AttrsInstance) -> None:
125
+ """Initialize a FieldIterator by determining the class type of the
126
+ obj argument
127
+
128
+ Parameters
129
+ ----------
130
+ obj
131
+ Class of the dataclass or attrs type
132
+
133
+ Raises
134
+ ------
135
+ TypeError
136
+ When the obj argument is of an unsupported type
137
+ """
138
+ self._index = 0
139
+
140
+ try:
141
+ if dataclasses.is_dataclass(obj):
142
+ self._fields = [
143
+ Field.from_dataclass(field)
144
+ for field in dataclasses.fields(obj)
145
+ ]
146
+ elif is_attrs(obj):
147
+ self._fields = [
148
+ Field.from_attrs(field) # type: ignore
149
+ for field in attrs.fields(obj) # type: ignore
150
+ ]
151
+ else:
152
+ raise TypeError(
153
+ "Incorrect object type. Only a dataclass- or "
154
+ "attrs class is supported"
155
+ )
156
+ except NameError as exc:
157
+ raise NameError(
158
+ "An error occured while evaluating an attribute of the "
159
+ f"{obj.__name__} class. {exc}" # type: ignore
160
+ )
161
+
162
+ def __iter__(self) -> "FieldIterator":
163
+ """Iter method
164
+
165
+ Returns
166
+ -------
167
+ This object
168
+ """
169
+ return self
170
+
171
+ def __next__(self) -> Field:
172
+ """Next method
173
+
174
+ Returns
175
+ -------
176
+ Next item in the collection
177
+
178
+ Raises
179
+ ------
180
+ StopIteration
181
+ Collection out of range
182
+ """
183
+ if self._index < len(self._fields):
184
+ item = self._fields[self._index]
185
+ self._index += 1
186
+ return item
187
+ else:
188
+ raise StopIteration
@@ -0,0 +1,86 @@
1
+ """Contains LoggerHandlerFactory class"""
2
+
3
+ from typing import Any
4
+
5
+ from alpha import exceptions
6
+
7
+
8
+ class LoggingHandlerFactory:
9
+ """For creating a valid logging handler from a dict object.
10
+
11
+ Supported handlers:
12
+ - logging.StreamHandler
13
+ - logging.FileHandler
14
+ - logging.handlers.RotatingFileHandler
15
+ - logging.handlers.TimedRotatingFileHandler
16
+ - logging.handlers.WatchedFileHandler
17
+ """
18
+
19
+ @classmethod
20
+ def parse(cls, handler: dict[str, Any]) -> dict[str, Any]:
21
+ """Parse a logging handler object.
22
+
23
+ Parameters
24
+ ----------
25
+ handler
26
+ A dictionary with at least the 'type' key. All other keys depend on
27
+ the handler type/class. Use the 'logging.handlers' section of the
28
+ python docs to determine which keys can be used for each handler
29
+ type/class.
30
+
31
+ Returns
32
+ -------
33
+ A handler dictionary which can be used in the handlers section of a
34
+ logging.config.dictConfig compatible dictionary.
35
+
36
+ Raises
37
+ ------
38
+ exceptions.LoggingHandlerException
39
+ - When the 'type' value of the handler is missing or None
40
+ - When a 'FileHandler' is missing the 'filename' value
41
+ """
42
+ type_: str | None = handler.get("type", None)
43
+ if type_ is None:
44
+ raise exceptions.LoggingHandlerException(
45
+ "the logger handler is missing a type attribute"
46
+ )
47
+ *_, class_name = type_.split(".")
48
+
49
+ obj: dict[str, Any] = {
50
+ "class": type_,
51
+ "level": handler.get("level", "DEBUG").upper(),
52
+ "formatter": handler.get("formatter", "default"),
53
+ }
54
+
55
+ if class_name == "StreamHandler":
56
+ obj.update({"stream": handler.get("stream", "ext://sys.stderr")})
57
+ if "FileHandler" in class_name:
58
+ _filename = handler.get("filename")
59
+ if not _filename:
60
+ raise exceptions.LoggingHandlerException(
61
+ "the logger handler is missing a filename attribute"
62
+ )
63
+ obj.update(
64
+ {
65
+ "filename": _filename,
66
+ "encoding": handler.get("encoding"),
67
+ "delay": handler.get("delay", False),
68
+ "errors": handler.get("errors"),
69
+ }
70
+ )
71
+ if "RotatingFileHandler" in class_name:
72
+ obj.update({"backupCount": handler.get("backupCount", 0)})
73
+ if class_name == "RotatingFileHandler":
74
+ obj.update({"maxBytes": handler.get("maxBytes", 0)})
75
+ if class_name == "TimedRotatingFileHandler":
76
+ obj.update(
77
+ {
78
+ "when": handler.get("when", "h"),
79
+ "interval": handler.get("interval", 1),
80
+ "utc": handler.get("utc", False),
81
+ "atTime": handler.get("atTime"),
82
+ }
83
+ )
84
+ else:
85
+ obj.update({"mode": handler.get("mode", "a")})
86
+ return obj
@@ -0,0 +1,176 @@
1
+ """Contains ModelClassFactory class"""
2
+
3
+ import enum
4
+ import types
5
+ import typing
6
+ from typing import Any
7
+
8
+ from alpha import exceptions
9
+ from alpha.factories.class_factories import (
10
+ AnyClassFactory,
11
+ DataclassClassFactory,
12
+ DictClassFactory,
13
+ EnumClassFactory,
14
+ GenericAliasClassFactory,
15
+ IterableClassFactory,
16
+ NativeClassFactory,
17
+ UnionClassFactory,
18
+ )
19
+ from alpha.factories.default_field_factory import DefaultFieldFactory
20
+ from alpha.factories.field_iterator import FieldIterator
21
+ from alpha.factories.models.factory_classes import FactoryClasses
22
+ from alpha.factories.type_factories import (
23
+ GenericTypeFactory,
24
+ DatetimeTypeFactory,
25
+ EnumTypeFactory,
26
+ JsonPatchTypeFactory,
27
+ )
28
+ from alpha.interfaces.attrs_instance import AttrsInstance
29
+ from alpha.interfaces.dataclass_instance import DataclassInstance
30
+ from alpha.interfaces.factories import (
31
+ ClassFactory,
32
+ TypeFactory,
33
+ )
34
+ from alpha.interfaces.openapi_model import OpenAPIModel
35
+ from alpha.utils.version_check import minor_version_gte
36
+
37
+
38
+ CLASS_FACTORIES: dict[str, ClassFactory] = {
39
+ "iterable": IterableClassFactory(),
40
+ "dict": DictClassFactory(),
41
+ "dataclass": DataclassClassFactory(),
42
+ "generic_alias": GenericAliasClassFactory(),
43
+ "union": UnionClassFactory(),
44
+ "native": NativeClassFactory(),
45
+ "enum": EnumClassFactory(),
46
+ "any": AnyClassFactory(),
47
+ }
48
+
49
+
50
+ TYPE_FACTORIES: dict[str, TypeFactory] = {
51
+ "generic": GenericTypeFactory(),
52
+ "datetime": DatetimeTypeFactory(),
53
+ "enum": EnumTypeFactory(),
54
+ "json_patch": JsonPatchTypeFactory(),
55
+ }
56
+
57
+
58
+ TYPING_CLASSES: dict[object, ClassFactory] = {
59
+ getattr(typing, "_GenericAlias"): CLASS_FACTORIES["generic_alias"],
60
+ getattr(typing, "_UnionGenericAlias"): CLASS_FACTORIES["union"],
61
+ getattr(typing, "_SpecialForm"): CLASS_FACTORIES["any"],
62
+ enum.EnumMeta: CLASS_FACTORIES["enum"],
63
+ type: CLASS_FACTORIES["native"],
64
+ }
65
+
66
+ if minor_version_gte(10):
67
+ TYPING_CLASSES.update(
68
+ {
69
+ getattr(types, "UnionType"): CLASS_FACTORIES["union"],
70
+ }
71
+ )
72
+
73
+ if minor_version_gte(11):
74
+ TYPING_CLASSES.update(
75
+ {
76
+ getattr(typing, "_AnyMeta"): CLASS_FACTORIES["any"],
77
+ getattr(types, "GenericAlias"): CLASS_FACTORIES["generic_alias"],
78
+ getattr(enum, "EnumType"): CLASS_FACTORIES["enum"],
79
+ }
80
+ )
81
+
82
+
83
+ FACTORY_CLASSES = FactoryClasses(
84
+ class_factories=CLASS_FACTORIES,
85
+ type_factories=TYPE_FACTORIES,
86
+ default_factory=DefaultFieldFactory(),
87
+ model_class_factory=None,
88
+ )
89
+
90
+
91
+ class ModelClassFactory:
92
+ """The ModelClassFactory can be used to cast OpenAPIModel objects to
93
+ instances of dataclass or attrs classes
94
+ """
95
+
96
+ def __init__(
97
+ self,
98
+ typing_classes: dict[object, ClassFactory] = TYPING_CLASSES,
99
+ factory_classes: FactoryClasses = FACTORY_CLASSES,
100
+ ) -> None:
101
+ """Initializing and setting the self.typing_classes class variable
102
+ which contains typing classes and references to the corresponding
103
+ factory classes. The set of typing classes depend on the python minor
104
+ version.
105
+
106
+ Parameters
107
+ ----------
108
+ typing_classes, optional
109
+ A collection of class types, by default TYPING_CLASSES
110
+ factory_classes, optional
111
+ An instance of FactoryClasses which acts as a toolbox of Factory
112
+ classes, by default FACTORY_CLASSES
113
+ """
114
+ self.typing_classes = typing_classes
115
+ self.factory_classes = factory_classes
116
+
117
+ if self.factory_classes.model_class_factory is None:
118
+ self.factory_classes.model_class_factory = self
119
+
120
+ def process(
121
+ self,
122
+ obj: OpenAPIModel,
123
+ cls: DataclassInstance | AttrsInstance | Any,
124
+ ) -> DataclassInstance | AttrsInstance | None:
125
+ """Creating a new cls instance from a OpenAPIModel object. This class
126
+ uses a compatibele ClassFactory, from the self.typing_classes
127
+ collection, per cls field to process each value.
128
+
129
+ Parameters
130
+ ----------
131
+ obj
132
+ OpenAPIModel object
133
+ cls
134
+ A dataclass or attrs class to create a new instance
135
+
136
+ Returns
137
+ -------
138
+ Dataclass or attrs instance
139
+
140
+ Raises
141
+ ------
142
+ exceptions.ModelClassFactoryException
143
+ When cls is not a dataclass or attrs decorated class
144
+ KeyError
145
+ When the class type is not present in self.typing_classes
146
+ """
147
+
148
+ try:
149
+ fields = FieldIterator(cls)
150
+ except TypeError:
151
+
152
+ raise exceptions.ModelClassFactoryException(
153
+ "cls argument has to be a dataclass or attrs decorated class"
154
+ )
155
+
156
+ params: dict[str, Any] = {}
157
+
158
+ for field in [f for f in fields if f.init]:
159
+ type_class: type | str = "Unknown"
160
+ try:
161
+ type_class = field.type.__class__
162
+ class_factory = self.typing_classes[type_class]
163
+ value: Any = class_factory.process(
164
+ obj=obj,
165
+ field=field,
166
+ factory_classes=self.factory_classes,
167
+ )
168
+ except KeyError as exc:
169
+ raise exceptions.ModelClassFactoryException(
170
+ "The class of this dataclass field is not supported. "
171
+ f"{field.name=}; "
172
+ f"{field.type=}; "
173
+ f"{field.type.__class__=}; "
174
+ ) from exc
175
+ params[field.name] = value
176
+ return cls(**params)
File without changes
@@ -0,0 +1,20 @@
1
+ """Contains FactoryClasses dataclass"""
2
+
3
+ from dataclasses import dataclass
4
+
5
+ from alpha.interfaces.factories import (
6
+ ClassFactory,
7
+ DefaultFactory,
8
+ ModelClassFactoryInstance,
9
+ TypeFactory,
10
+ )
11
+
12
+
13
+ @dataclass
14
+ class FactoryClasses:
15
+ """A FactoryClasses instance acts as a toolbox for Factory classes"""
16
+
17
+ class_factories: dict[str, ClassFactory]
18
+ type_factories: dict[str, TypeFactory]
19
+ default_factory: DefaultFactory
20
+ model_class_factory: ModelClassFactoryInstance | None
@@ -0,0 +1,211 @@
1
+ """Contains RequestFactory class"""
2
+
3
+ import sys
4
+ import types
5
+ import typing
6
+ from enum import Enum
7
+ from typing import Any, Callable, get_args, get_origin
8
+
9
+ from alpha import exceptions
10
+ from alpha.factories._type_conversion_matrix import TYPE_CONVERSION_MATRIX
11
+ from alpha.factories.model_class_factory import (
12
+ ModelClassFactory,
13
+ )
14
+ from alpha.factories.type_factories import (
15
+ EnumTypeFactory,
16
+ GenericTypeFactory,
17
+ JsonPatchTypeFactory,
18
+ )
19
+ from alpha.infra.models.json_patch import JsonPatch
20
+ from alpha.interfaces.dataclass_instance import DataclassInstance
21
+ from alpha.interfaces.factories import (
22
+ ModelClassFactoryInstance,
23
+ TypeFactory,
24
+ )
25
+ from alpha.interfaces.openapi_model import OpenAPIModel
26
+
27
+
28
+ class RequestFactory:
29
+ """This class handles API requests"""
30
+
31
+ def __init__(
32
+ self,
33
+ func: Callable[[Any], Any],
34
+ cast_args: bool = True,
35
+ use_model_class_factory: bool = True,
36
+ model_class_factory: type[
37
+ ModelClassFactoryInstance
38
+ ] = ModelClassFactory,
39
+ generic_type_factory: type[TypeFactory] = GenericTypeFactory,
40
+ enum_type_factory: type[TypeFactory] = EnumTypeFactory,
41
+ json_patch_type_factory: type[TypeFactory] = JsonPatchTypeFactory,
42
+ ) -> None:
43
+ """Initializing the class with a service function
44
+ The service function will be called when calling
45
+ the cls.__call__ function.
46
+
47
+ Parameters
48
+ ----------
49
+ func
50
+ A callable service function
51
+ cast_args, optional
52
+ Make use of the GenericTypeFactory to cast arguments,
53
+ by default True
54
+ use_model_class_factory, optional
55
+ Make use of the ModelClassFactory to map objects to a dataclass,
56
+ by default True
57
+ model_class_factory, optional
58
+ A ModelClassFactory class
59
+ by default ModelClassFactory
60
+ generic_type_factory, optional
61
+ A TypeFactory that can handle generic types
62
+ by default GenericTypeFactory
63
+ enum_type_factory, optional
64
+ A TypeFactory that can handle enum types
65
+ by default EnumTypeFactory
66
+ json_patch_type_factory, optional
67
+ A TypeFactory that can handle a JsonPatch type
68
+ by default JsonPatchTypeFactory
69
+ """
70
+ self.func = func
71
+ self.cast_args = cast_args
72
+ self.use_model_class_factory = use_model_class_factory
73
+ self.model_class_factory = model_class_factory
74
+ self.generic_type_factory = generic_type_factory
75
+ self.enum_type_factory = enum_type_factory
76
+ self.json_patch_type_factory = json_patch_type_factory
77
+
78
+ def __call__(self, **kwargs: dict[str, Any]) -> Any:
79
+ """Calling the service function
80
+ Any keyword argument will be parsed by the self._parse_args function
81
+ Each argument will be mapped on the functions parameter type of the
82
+ corresponding keyword.
83
+
84
+ The keyword arguments need to match the functions parameters.
85
+ Therefore, *args or **kwargs are not allowed as the functions
86
+ parameters.
87
+
88
+ Parameters
89
+ ----------
90
+ kwargs
91
+ Any keyword argument that will be passed to the service function
92
+
93
+ Returns
94
+ -------
95
+ Any
96
+ The returned object of the called service function
97
+ """
98
+ annotations = self.func.__annotations__
99
+ params = {
100
+ k: self._parse_args(key=k, value=v, cls=annotations[k])
101
+ for k, v in kwargs.items()
102
+ }
103
+
104
+ return self.func(**params) # type: ignore
105
+
106
+ def _parse_args(
107
+ self,
108
+ key: str,
109
+ value: Any,
110
+ cls: Any | list[Any],
111
+ ) -> Any:
112
+ """Parsing each keyword argument
113
+
114
+ Parameters
115
+ ----------
116
+ key
117
+ Keyword of the argument
118
+ value
119
+ The argument
120
+ cls
121
+ The class of the corresponding parameter
122
+
123
+ Returns
124
+ -------
125
+ Any
126
+ Mapped objects
127
+
128
+ Raises
129
+ ------
130
+ exceptions.ClassMismatchException
131
+ When the source and destination types are not both of an iterable
132
+ type
133
+ """
134
+ union_types = getattr(typing, "_UnionGenericAlias")
135
+
136
+ if sys.version_info.minor >= 10:
137
+ union_types = (
138
+ getattr(typing, "_UnionGenericAlias") | types.UnionType
139
+ )
140
+
141
+ if isinstance(cls, union_types):
142
+ union_args = get_args(cls)
143
+ if value is None and type(None) in union_args:
144
+ return value
145
+ cls = union_args[0]
146
+
147
+ if get_origin(cls) in [list, set, tuple]:
148
+ if type(value) not in [list, set, tuple]:
149
+ raise exceptions.ClassMismatchException(
150
+ "The targeted object type is an iterable but the source "
151
+ "object is not"
152
+ )
153
+ arg = get_args(cls)[0]
154
+ return [
155
+ self._parse_args(key=key, value=item, cls=arg)
156
+ for item in value
157
+ ]
158
+
159
+ if isinstance(cls, DataclassInstance):
160
+ return self._to_dataclass(value=value, cls=cls)
161
+
162
+ if isinstance(cls, type(Enum)):
163
+ return self.enum_type_factory().process(
164
+ key=key, value=value, cls=cls
165
+ )
166
+
167
+ if cls == JsonPatch:
168
+ return self.json_patch_type_factory().process(
169
+ key=key, value=value, cls=cls
170
+ )
171
+
172
+ if cls in TYPE_CONVERSION_MATRIX.keys() and self.cast_args:
173
+ return self.generic_type_factory().process(
174
+ key=key, value=value, cls=cls
175
+ )
176
+
177
+ return value
178
+
179
+ def _to_dataclass(
180
+ self, value: OpenAPIModel | Any, cls: DataclassInstance
181
+ ) -> Any:
182
+ """Handling the mapping from an OpenAPI Model instance to a dataclass
183
+ The ModelClassFactory will be used if the cls does not have
184
+ a 'from_dict' method
185
+
186
+ Parameters
187
+ ----------
188
+ value
189
+ The argument, which is an OpenAPI Model
190
+ cls
191
+ The class of the corresponding parameter
192
+
193
+ Returns
194
+ -------
195
+ dataclass
196
+ Dataclass object
197
+
198
+ Raises
199
+ ------
200
+ TypeError
201
+ The value is not an instance of the OpenAPI (Base)Model
202
+ """
203
+ if not isinstance(value, OpenAPIModel):
204
+ raise TypeError(f"Unable to map {type(value)} on dataclass model")
205
+
206
+ if hasattr(cls, "from_dict"):
207
+ return getattr(cls, "from_dict")(value.to_dict())
208
+
209
+ if self.use_model_class_factory:
210
+ return self.model_class_factory().process(obj=value, cls=cls)
211
+ return value