datamodel-code-generator 0.27.2__py3-none-any.whl → 0.28.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.
Potentially problematic release.
This version of datamodel-code-generator might be problematic. Click here for more details.
- datamodel_code_generator/__init__.py +168 -196
- datamodel_code_generator/__main__.py +146 -189
- datamodel_code_generator/arguments.py +227 -230
- datamodel_code_generator/format.py +77 -129
- datamodel_code_generator/http.py +12 -10
- datamodel_code_generator/imports.py +59 -65
- datamodel_code_generator/model/__init__.py +28 -31
- datamodel_code_generator/model/base.py +100 -144
- datamodel_code_generator/model/dataclass.py +62 -70
- datamodel_code_generator/model/enum.py +34 -30
- datamodel_code_generator/model/imports.py +13 -11
- datamodel_code_generator/model/msgspec.py +116 -138
- datamodel_code_generator/model/pydantic/__init__.py +18 -28
- datamodel_code_generator/model/pydantic/base_model.py +121 -140
- datamodel_code_generator/model/pydantic/custom_root_type.py +2 -2
- datamodel_code_generator/model/pydantic/dataclass.py +6 -4
- datamodel_code_generator/model/pydantic/imports.py +35 -33
- datamodel_code_generator/model/pydantic/types.py +91 -119
- datamodel_code_generator/model/pydantic_v2/__init__.py +21 -18
- datamodel_code_generator/model/pydantic_v2/base_model.py +118 -127
- datamodel_code_generator/model/pydantic_v2/imports.py +5 -3
- datamodel_code_generator/model/pydantic_v2/root_model.py +6 -6
- datamodel_code_generator/model/pydantic_v2/types.py +11 -7
- datamodel_code_generator/model/rootmodel.py +1 -1
- datamodel_code_generator/model/scalar.py +33 -32
- datamodel_code_generator/model/typed_dict.py +41 -51
- datamodel_code_generator/model/types.py +24 -19
- datamodel_code_generator/model/union.py +21 -17
- datamodel_code_generator/parser/__init__.py +16 -12
- datamodel_code_generator/parser/base.py +327 -515
- datamodel_code_generator/parser/graphql.py +87 -119
- datamodel_code_generator/parser/jsonschema.py +438 -607
- datamodel_code_generator/parser/openapi.py +180 -220
- datamodel_code_generator/pydantic_patch.py +8 -9
- datamodel_code_generator/reference.py +199 -297
- datamodel_code_generator/types.py +149 -215
- datamodel_code_generator/util.py +23 -36
- {datamodel_code_generator-0.27.2.dist-info → datamodel_code_generator-0.28.0.dist-info}/METADATA +10 -5
- datamodel_code_generator-0.28.0.dist-info/RECORD +59 -0
- datamodel_code_generator-0.27.2.dist-info/RECORD +0 -59
- {datamodel_code_generator-0.27.2.dist-info → datamodel_code_generator-0.28.0.dist-info}/WHEEL +0 -0
- {datamodel_code_generator-0.27.2.dist-info → datamodel_code_generator-0.28.0.dist-info}/entry_points.txt +0 -0
- {datamodel_code_generator-0.27.2.dist-info → datamodel_code_generator-0.28.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,33 +1,18 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
import re
|
|
2
4
|
from abc import ABC, abstractmethod
|
|
3
5
|
from enum import Enum, auto
|
|
4
6
|
from functools import lru_cache
|
|
5
7
|
from itertools import chain
|
|
6
|
-
from
|
|
7
|
-
|
|
8
|
-
Any,
|
|
9
|
-
Callable,
|
|
10
|
-
ClassVar,
|
|
11
|
-
Dict,
|
|
12
|
-
FrozenSet,
|
|
13
|
-
Iterable,
|
|
14
|
-
Iterator,
|
|
15
|
-
List,
|
|
16
|
-
Optional,
|
|
17
|
-
Pattern,
|
|
18
|
-
Sequence,
|
|
19
|
-
Set,
|
|
20
|
-
Tuple,
|
|
21
|
-
Type,
|
|
22
|
-
TypeVar,
|
|
23
|
-
Union,
|
|
24
|
-
)
|
|
8
|
+
from re import Pattern
|
|
9
|
+
from typing import TYPE_CHECKING, Any, Callable, ClassVar, Optional, Protocol, TypeVar, Union, runtime_checkable
|
|
25
10
|
|
|
26
11
|
import pydantic
|
|
27
12
|
from packaging import version
|
|
28
13
|
from pydantic import StrictBool, StrictInt, StrictStr, create_model
|
|
29
14
|
|
|
30
|
-
from datamodel_code_generator.format import DatetimeClassType, PythonVersion
|
|
15
|
+
from datamodel_code_generator.format import DatetimeClassType, PythonVersion, PythonVersionMin
|
|
31
16
|
from datamodel_code_generator.imports import (
|
|
32
17
|
IMPORT_ABC_MAPPING,
|
|
33
18
|
IMPORT_ABC_SEQUENCE,
|
|
@@ -36,7 +21,6 @@ from datamodel_code_generator.imports import (
|
|
|
36
21
|
IMPORT_FROZEN_SET,
|
|
37
22
|
IMPORT_LIST,
|
|
38
23
|
IMPORT_LITERAL,
|
|
39
|
-
IMPORT_LITERAL_BACKPORT,
|
|
40
24
|
IMPORT_MAPPING,
|
|
41
25
|
IMPORT_OPTIONAL,
|
|
42
26
|
IMPORT_SEQUENCE,
|
|
@@ -45,57 +29,56 @@ from datamodel_code_generator.imports import (
|
|
|
45
29
|
Import,
|
|
46
30
|
)
|
|
47
31
|
from datamodel_code_generator.reference import Reference, _BaseModel
|
|
48
|
-
from datamodel_code_generator.util import
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
)
|
|
32
|
+
from datamodel_code_generator.util import PYDANTIC_V2, ConfigDict
|
|
33
|
+
|
|
34
|
+
if TYPE_CHECKING:
|
|
35
|
+
import builtins
|
|
36
|
+
from collections.abc import Iterable, Iterator, Sequence
|
|
54
37
|
|
|
55
38
|
if PYDANTIC_V2:
|
|
56
39
|
from pydantic import GetCoreSchemaHandler
|
|
57
40
|
from pydantic_core import core_schema
|
|
58
41
|
|
|
59
|
-
T = TypeVar(
|
|
60
|
-
|
|
61
|
-
OPTIONAL =
|
|
62
|
-
OPTIONAL_PREFIX = f
|
|
63
|
-
|
|
64
|
-
UNION =
|
|
65
|
-
UNION_PREFIX = f
|
|
66
|
-
UNION_DELIMITER =
|
|
67
|
-
UNION_PATTERN: Pattern[str] = re.compile(r
|
|
68
|
-
UNION_OPERATOR_DELIMITER =
|
|
69
|
-
UNION_OPERATOR_PATTERN: Pattern[str] = re.compile(r
|
|
70
|
-
NONE =
|
|
71
|
-
ANY =
|
|
72
|
-
LITERAL =
|
|
73
|
-
SEQUENCE =
|
|
74
|
-
FROZEN_SET =
|
|
75
|
-
MAPPING =
|
|
76
|
-
DICT =
|
|
77
|
-
SET =
|
|
78
|
-
LIST =
|
|
79
|
-
STANDARD_DICT =
|
|
80
|
-
STANDARD_LIST =
|
|
81
|
-
STANDARD_SET =
|
|
82
|
-
STR =
|
|
83
|
-
|
|
84
|
-
NOT_REQUIRED =
|
|
85
|
-
NOT_REQUIRED_PREFIX = f
|
|
42
|
+
T = TypeVar("T")
|
|
43
|
+
|
|
44
|
+
OPTIONAL = "Optional"
|
|
45
|
+
OPTIONAL_PREFIX = f"{OPTIONAL}["
|
|
46
|
+
|
|
47
|
+
UNION = "Union"
|
|
48
|
+
UNION_PREFIX = f"{UNION}["
|
|
49
|
+
UNION_DELIMITER = ", "
|
|
50
|
+
UNION_PATTERN: Pattern[str] = re.compile(r"\s*,\s*")
|
|
51
|
+
UNION_OPERATOR_DELIMITER = " | "
|
|
52
|
+
UNION_OPERATOR_PATTERN: Pattern[str] = re.compile(r"\s*\|\s*")
|
|
53
|
+
NONE = "None"
|
|
54
|
+
ANY = "Any"
|
|
55
|
+
LITERAL = "Literal"
|
|
56
|
+
SEQUENCE = "Sequence"
|
|
57
|
+
FROZEN_SET = "FrozenSet"
|
|
58
|
+
MAPPING = "Mapping"
|
|
59
|
+
DICT = "Dict"
|
|
60
|
+
SET = "Set"
|
|
61
|
+
LIST = "List"
|
|
62
|
+
STANDARD_DICT = "dict"
|
|
63
|
+
STANDARD_LIST = "list"
|
|
64
|
+
STANDARD_SET = "set"
|
|
65
|
+
STR = "str"
|
|
66
|
+
|
|
67
|
+
NOT_REQUIRED = "NotRequired"
|
|
68
|
+
NOT_REQUIRED_PREFIX = f"{NOT_REQUIRED}["
|
|
86
69
|
|
|
87
70
|
|
|
88
71
|
class StrictTypes(Enum):
|
|
89
|
-
str =
|
|
90
|
-
bytes =
|
|
91
|
-
int =
|
|
92
|
-
float =
|
|
93
|
-
bool =
|
|
72
|
+
str = "str"
|
|
73
|
+
bytes = "bytes"
|
|
74
|
+
int = "int"
|
|
75
|
+
float = "float"
|
|
76
|
+
bool = "bool"
|
|
94
77
|
|
|
95
78
|
|
|
96
79
|
class UnionIntFloat:
|
|
97
|
-
def __init__(self, value:
|
|
98
|
-
self.value:
|
|
80
|
+
def __init__(self, value: float) -> None:
|
|
81
|
+
self.value: int | float = value
|
|
99
82
|
|
|
100
83
|
def __int__(self) -> int:
|
|
101
84
|
return int(self.value)
|
|
@@ -107,41 +90,41 @@ class UnionIntFloat:
|
|
|
107
90
|
return str(self.value)
|
|
108
91
|
|
|
109
92
|
@classmethod
|
|
110
|
-
def __get_validators__(cls) -> Iterator[Callable[[Any], Any]]:
|
|
93
|
+
def __get_validators__(cls) -> Iterator[Callable[[Any], Any]]: # noqa: PLW3201
|
|
111
94
|
yield cls.validate
|
|
112
95
|
|
|
113
96
|
@classmethod
|
|
114
|
-
def __get_pydantic_core_schema__(
|
|
115
|
-
cls, _source_type: Any, _handler:
|
|
116
|
-
) ->
|
|
117
|
-
from_int_schema = core_schema.chain_schema( # pyright: ignore
|
|
97
|
+
def __get_pydantic_core_schema__( # noqa: PLW3201
|
|
98
|
+
cls, _source_type: Any, _handler: GetCoreSchemaHandler
|
|
99
|
+
) -> core_schema.CoreSchema:
|
|
100
|
+
from_int_schema = core_schema.chain_schema( # pyright: ignore[reportPossiblyUnboundVariable]
|
|
118
101
|
[
|
|
119
|
-
core_schema.union_schema( # pyright: ignore
|
|
120
|
-
[core_schema.int_schema(), core_schema.float_schema()] # pyright: ignore
|
|
102
|
+
core_schema.union_schema( # pyright: ignore[reportPossiblyUnboundVariable]
|
|
103
|
+
[core_schema.int_schema(), core_schema.float_schema()] # pyright: ignore[reportPossiblyUnboundVariable]
|
|
121
104
|
),
|
|
122
|
-
core_schema.no_info_plain_validator_function(cls.validate), # pyright: ignore
|
|
105
|
+
core_schema.no_info_plain_validator_function(cls.validate), # pyright: ignore[reportPossiblyUnboundVariable]
|
|
123
106
|
]
|
|
124
107
|
)
|
|
125
108
|
|
|
126
|
-
return core_schema.json_or_python_schema( # pyright: ignore
|
|
109
|
+
return core_schema.json_or_python_schema( # pyright: ignore[reportPossiblyUnboundVariable]
|
|
127
110
|
json_schema=from_int_schema,
|
|
128
|
-
python_schema=core_schema.union_schema( # pyright: ignore
|
|
111
|
+
python_schema=core_schema.union_schema( # pyright: ignore[reportPossiblyUnboundVariable]
|
|
129
112
|
[
|
|
130
113
|
# check if it's an instance first before doing any further work
|
|
131
|
-
core_schema.is_instance_schema(UnionIntFloat), # pyright: ignore
|
|
114
|
+
core_schema.is_instance_schema(UnionIntFloat), # pyright: ignore[reportPossiblyUnboundVariable]
|
|
132
115
|
from_int_schema,
|
|
133
116
|
]
|
|
134
117
|
),
|
|
135
|
-
serialization=core_schema.plain_serializer_function_ser_schema( # pyright: ignore
|
|
118
|
+
serialization=core_schema.plain_serializer_function_ser_schema( # pyright: ignore[reportPossiblyUnboundVariable]
|
|
136
119
|
lambda instance: instance.value
|
|
137
120
|
),
|
|
138
121
|
)
|
|
139
122
|
|
|
140
123
|
@classmethod
|
|
141
|
-
def validate(cls, v: Any) ->
|
|
124
|
+
def validate(cls, v: Any) -> UnionIntFloat:
|
|
142
125
|
if isinstance(v, UnionIntFloat):
|
|
143
126
|
return v
|
|
144
|
-
|
|
127
|
+
if not isinstance(v, (int, float)): # pragma: no cover
|
|
145
128
|
try:
|
|
146
129
|
int(v)
|
|
147
130
|
return cls(v)
|
|
@@ -153,69 +136,63 @@ class UnionIntFloat:
|
|
|
153
136
|
except (TypeError, ValueError):
|
|
154
137
|
pass
|
|
155
138
|
|
|
156
|
-
|
|
139
|
+
msg = f"{v} is not int or float"
|
|
140
|
+
raise TypeError(msg)
|
|
157
141
|
return cls(v)
|
|
158
142
|
|
|
159
143
|
|
|
160
|
-
def chain_as_tuple(*iterables: Iterable[T]) ->
|
|
144
|
+
def chain_as_tuple(*iterables: Iterable[T]) -> tuple[T, ...]:
|
|
161
145
|
return tuple(chain(*iterables))
|
|
162
146
|
|
|
163
147
|
|
|
164
148
|
@lru_cache
|
|
165
|
-
def _remove_none_from_type(
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
types: List[str] = []
|
|
169
|
-
split_type: str = ''
|
|
149
|
+
def _remove_none_from_type(type_: str, split_pattern: Pattern[str], delimiter: str) -> list[str]:
|
|
150
|
+
types: list[str] = []
|
|
151
|
+
split_type: str = ""
|
|
170
152
|
inner_count: int = 0
|
|
171
153
|
for part in re.split(split_pattern, type_):
|
|
172
154
|
if part == NONE:
|
|
173
155
|
continue
|
|
174
|
-
inner_count += part.count(
|
|
156
|
+
inner_count += part.count("[") - part.count("]")
|
|
175
157
|
if split_type:
|
|
176
158
|
split_type += delimiter
|
|
177
159
|
if inner_count == 0:
|
|
178
160
|
if split_type:
|
|
179
|
-
types.append(f
|
|
161
|
+
types.append(f"{split_type}{part}")
|
|
180
162
|
else:
|
|
181
163
|
types.append(part)
|
|
182
|
-
split_type =
|
|
164
|
+
split_type = ""
|
|
183
165
|
continue
|
|
184
|
-
|
|
185
|
-
split_type += part
|
|
166
|
+
split_type += part
|
|
186
167
|
return types
|
|
187
168
|
|
|
188
169
|
|
|
189
|
-
def _remove_none_from_union(type_: str, use_union_operator: bool) -> str:
|
|
170
|
+
def _remove_none_from_union(type_: str, use_union_operator: bool) -> str: # noqa: FBT001
|
|
190
171
|
if use_union_operator:
|
|
191
|
-
if not re.match(r
|
|
172
|
+
if not re.match(r"^\w+ | ", type_):
|
|
192
173
|
return type_
|
|
193
174
|
return UNION_OPERATOR_DELIMITER.join(
|
|
194
|
-
_remove_none_from_type(
|
|
195
|
-
type_, UNION_OPERATOR_PATTERN, UNION_OPERATOR_DELIMITER
|
|
196
|
-
)
|
|
175
|
+
_remove_none_from_type(type_, UNION_OPERATOR_PATTERN, UNION_OPERATOR_DELIMITER)
|
|
197
176
|
)
|
|
198
177
|
|
|
199
178
|
if not type_.startswith(UNION_PREFIX):
|
|
200
179
|
return type_
|
|
201
|
-
inner_types = _remove_none_from_type(
|
|
202
|
-
type_[len(UNION_PREFIX) :][:-1], UNION_PATTERN, UNION_DELIMITER
|
|
203
|
-
)
|
|
180
|
+
inner_types = _remove_none_from_type(type_[len(UNION_PREFIX) :][:-1], UNION_PATTERN, UNION_DELIMITER)
|
|
204
181
|
|
|
205
182
|
if len(inner_types) == 1:
|
|
206
183
|
return inner_types[0]
|
|
207
|
-
return f
|
|
184
|
+
return f"{UNION_PREFIX}{UNION_DELIMITER.join(inner_types)}]"
|
|
208
185
|
|
|
209
186
|
|
|
210
187
|
@lru_cache
|
|
211
|
-
def get_optional_type(type_: str, use_union_operator: bool) -> str:
|
|
188
|
+
def get_optional_type(type_: str, use_union_operator: bool) -> str: # noqa: FBT001
|
|
212
189
|
type_ = _remove_none_from_union(type_, use_union_operator)
|
|
213
190
|
|
|
214
191
|
if not type_ or type_ == NONE:
|
|
215
192
|
return NONE
|
|
216
193
|
if use_union_operator:
|
|
217
|
-
return f
|
|
218
|
-
return f
|
|
194
|
+
return f"{type_} | {NONE}"
|
|
195
|
+
return f"{OPTIONAL_PREFIX}{type_}]"
|
|
219
196
|
|
|
220
197
|
|
|
221
198
|
@runtime_checkable
|
|
@@ -236,9 +213,9 @@ class DataType(_BaseModel):
|
|
|
236
213
|
if PYDANTIC_V2:
|
|
237
214
|
# TODO[pydantic]: The following keys were removed: `copy_on_model_validation`.
|
|
238
215
|
# Check https://docs.pydantic.dev/dev-v2/migration/#changes-to-config for more information.
|
|
239
|
-
model_config = ConfigDict( # pyright: ignore
|
|
240
|
-
extra=
|
|
241
|
-
revalidate_instances=
|
|
216
|
+
model_config = ConfigDict( # pyright: ignore[reportAssignmentType]
|
|
217
|
+
extra="forbid",
|
|
218
|
+
revalidate_instances="never",
|
|
242
219
|
)
|
|
243
220
|
else:
|
|
244
221
|
if not TYPE_CHECKING:
|
|
@@ -248,41 +225,37 @@ class DataType(_BaseModel):
|
|
|
248
225
|
cls.update_forward_refs()
|
|
249
226
|
|
|
250
227
|
class Config:
|
|
251
|
-
extra =
|
|
252
|
-
copy_on_model_validation = (
|
|
253
|
-
False
|
|
254
|
-
if version.parse(pydantic.VERSION) < version.parse('1.9.2')
|
|
255
|
-
else 'none'
|
|
256
|
-
)
|
|
228
|
+
extra = "forbid"
|
|
229
|
+
copy_on_model_validation = False if version.parse(pydantic.VERSION) < version.parse("1.9.2") else "none"
|
|
257
230
|
|
|
258
|
-
type: Optional[str] = None
|
|
259
|
-
reference: Optional[Reference] = None
|
|
260
|
-
data_types:
|
|
231
|
+
type: Optional[str] = None # noqa: UP045
|
|
232
|
+
reference: Optional[Reference] = None # noqa: UP045
|
|
233
|
+
data_types: list[DataType] = [] # noqa: RUF012
|
|
261
234
|
is_func: bool = False
|
|
262
|
-
kwargs: Optional[
|
|
263
|
-
import_: Optional[Import] = None
|
|
264
|
-
python_version: PythonVersion =
|
|
235
|
+
kwargs: Optional[dict[str, Any]] = None # noqa: UP045
|
|
236
|
+
import_: Optional[Import] = None # noqa: UP045
|
|
237
|
+
python_version: PythonVersion = PythonVersionMin
|
|
265
238
|
is_optional: bool = False
|
|
266
239
|
is_dict: bool = False
|
|
267
240
|
is_list: bool = False
|
|
268
241
|
is_set: bool = False
|
|
269
242
|
is_custom_type: bool = False
|
|
270
|
-
literals:
|
|
243
|
+
literals: list[Union[StrictBool, StrictInt, StrictStr]] = [] # noqa: RUF012, UP007
|
|
271
244
|
use_standard_collections: bool = False
|
|
272
245
|
use_generic_container: bool = False
|
|
273
246
|
use_union_operator: bool = False
|
|
274
|
-
alias: Optional[str] = None
|
|
275
|
-
parent: Optional[Any] = None
|
|
276
|
-
children:
|
|
247
|
+
alias: Optional[str] = None # noqa: UP045
|
|
248
|
+
parent: Optional[Any] = None # noqa: UP045
|
|
249
|
+
children: list[Any] = [] # noqa: RUF012
|
|
277
250
|
strict: bool = False
|
|
278
|
-
dict_key: Optional[
|
|
251
|
+
dict_key: Optional[DataType] = None # noqa: UP045
|
|
279
252
|
|
|
280
|
-
_exclude_fields: ClassVar[
|
|
281
|
-
_pass_fields: ClassVar[
|
|
253
|
+
_exclude_fields: ClassVar[set[str]] = {"parent", "children"}
|
|
254
|
+
_pass_fields: ClassVar[set[str]] = {"parent", "children", "data_types", "reference"}
|
|
282
255
|
|
|
283
256
|
@classmethod
|
|
284
|
-
def from_import(
|
|
285
|
-
cls:
|
|
257
|
+
def from_import( # noqa: PLR0913
|
|
258
|
+
cls: builtins.type[DataTypeT],
|
|
286
259
|
import_: Import,
|
|
287
260
|
*,
|
|
288
261
|
is_optional: bool = False,
|
|
@@ -291,8 +264,8 @@ class DataType(_BaseModel):
|
|
|
291
264
|
is_set: bool = False,
|
|
292
265
|
is_custom_type: bool = False,
|
|
293
266
|
strict: bool = False,
|
|
294
|
-
kwargs:
|
|
295
|
-
) ->
|
|
267
|
+
kwargs: dict[str, Any] | None = None,
|
|
268
|
+
) -> DataTypeT:
|
|
296
269
|
return cls(
|
|
297
270
|
type=import_.import_,
|
|
298
271
|
import_=import_,
|
|
@@ -300,34 +273,25 @@ class DataType(_BaseModel):
|
|
|
300
273
|
is_dict=is_dict,
|
|
301
274
|
is_list=is_list,
|
|
302
275
|
is_set=is_set,
|
|
303
|
-
is_func=
|
|
276
|
+
is_func=bool(kwargs),
|
|
304
277
|
is_custom_type=is_custom_type,
|
|
305
278
|
strict=strict,
|
|
306
279
|
kwargs=kwargs,
|
|
307
280
|
)
|
|
308
281
|
|
|
309
282
|
@property
|
|
310
|
-
def unresolved_types(self) ->
|
|
283
|
+
def unresolved_types(self) -> frozenset[str]:
|
|
311
284
|
return frozenset(
|
|
312
|
-
{
|
|
313
|
-
t.reference.path
|
|
314
|
-
for data_types in self.data_types
|
|
315
|
-
for t in data_types.all_data_types
|
|
316
|
-
if t.reference
|
|
317
|
-
}
|
|
285
|
+
{t.reference.path for data_types in self.data_types for t in data_types.all_data_types if t.reference}
|
|
318
286
|
| ({self.reference.path} if self.reference else set())
|
|
319
287
|
)
|
|
320
288
|
|
|
321
|
-
def replace_reference(self, reference:
|
|
289
|
+
def replace_reference(self, reference: Reference | None) -> None:
|
|
322
290
|
if not self.reference: # pragma: no cover
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
f' when `reference` field is empty.'
|
|
326
|
-
)
|
|
291
|
+
msg = f"`{self.__class__.__name__}.replace_reference()` can't be called when `reference` field is empty."
|
|
292
|
+
raise Exception(msg) # noqa: TRY002
|
|
327
293
|
self_id = id(self)
|
|
328
|
-
self.reference.children = [
|
|
329
|
-
c for c in self.reference.children if id(c) != self_id
|
|
330
|
-
]
|
|
294
|
+
self.reference.children = [c for c in self.reference.children if id(c) != self_id]
|
|
331
295
|
self.reference = reference
|
|
332
296
|
if reference:
|
|
333
297
|
reference.children.append(self)
|
|
@@ -336,7 +300,7 @@ class DataType(_BaseModel):
|
|
|
336
300
|
self.replace_reference(None)
|
|
337
301
|
|
|
338
302
|
@property
|
|
339
|
-
def module_name(self) ->
|
|
303
|
+
def module_name(self) -> str | None:
|
|
340
304
|
if self.reference and isinstance(self.reference.source, Modular):
|
|
341
305
|
return self.reference.source.module_name
|
|
342
306
|
return None # pragma: no cover
|
|
@@ -345,11 +309,11 @@ class DataType(_BaseModel):
|
|
|
345
309
|
def full_name(self) -> str:
|
|
346
310
|
module_name = self.module_name
|
|
347
311
|
if module_name:
|
|
348
|
-
return f
|
|
349
|
-
return self.reference.short_name
|
|
312
|
+
return f"{module_name}.{self.reference.short_name if self.reference else ''}"
|
|
313
|
+
return self.reference.short_name if self.reference else ""
|
|
350
314
|
|
|
351
315
|
@property
|
|
352
|
-
def all_data_types(self) -> Iterator[
|
|
316
|
+
def all_data_types(self) -> Iterator[DataType]:
|
|
353
317
|
for data_type in self.data_types:
|
|
354
318
|
yield from data_type.all_data_types
|
|
355
319
|
yield self
|
|
@@ -367,15 +331,10 @@ class DataType(_BaseModel):
|
|
|
367
331
|
yield self.import_
|
|
368
332
|
|
|
369
333
|
# Define required imports based on type features and conditions
|
|
370
|
-
imports:
|
|
334
|
+
imports: tuple[tuple[bool, Import], ...] = (
|
|
371
335
|
(self.is_optional and not self.use_union_operator, IMPORT_OPTIONAL),
|
|
372
336
|
(len(self.data_types) > 1 and not self.use_union_operator, IMPORT_UNION),
|
|
373
|
-
(
|
|
374
|
-
bool(self.literals),
|
|
375
|
-
IMPORT_LITERAL
|
|
376
|
-
if self.python_version.has_literal_type
|
|
377
|
-
else IMPORT_LITERAL_BACKPORT,
|
|
378
|
-
),
|
|
337
|
+
(bool(self.literals), IMPORT_LITERAL),
|
|
379
338
|
)
|
|
380
339
|
|
|
381
340
|
if self.use_generic_container:
|
|
@@ -418,11 +377,7 @@ class DataType(_BaseModel):
|
|
|
418
377
|
if type_.type == ANY and type_.is_optional:
|
|
419
378
|
if any(t for t in self.data_types if t.type != ANY): # pragma: no cover
|
|
420
379
|
self.is_optional = True
|
|
421
|
-
self.data_types = [
|
|
422
|
-
t
|
|
423
|
-
for t in self.data_types
|
|
424
|
-
if not (t.type == ANY and t.is_optional)
|
|
425
|
-
]
|
|
380
|
+
self.data_types = [t for t in self.data_types if not (t.type == ANY and t.is_optional)]
|
|
426
381
|
break # pragma: no cover
|
|
427
382
|
|
|
428
383
|
for data_type in self.data_types:
|
|
@@ -433,23 +388,21 @@ class DataType(_BaseModel):
|
|
|
433
388
|
self.reference.children.append(self)
|
|
434
389
|
|
|
435
390
|
@property
|
|
436
|
-
def type_hint(self) -> str:
|
|
437
|
-
type_:
|
|
391
|
+
def type_hint(self) -> str: # noqa: PLR0912, PLR0915
|
|
392
|
+
type_: str | None = self.alias or self.type
|
|
438
393
|
if not type_:
|
|
439
394
|
if self.is_union:
|
|
440
|
-
data_types:
|
|
395
|
+
data_types: list[str] = []
|
|
441
396
|
for data_type in self.data_types:
|
|
442
397
|
data_type_type = data_type.type_hint
|
|
443
398
|
if data_type_type in data_types: # pragma: no cover
|
|
444
399
|
continue
|
|
445
400
|
|
|
446
|
-
if
|
|
401
|
+
if data_type_type == NONE:
|
|
447
402
|
self.is_optional = True
|
|
448
403
|
continue
|
|
449
404
|
|
|
450
|
-
non_optional_data_type_type = _remove_none_from_union(
|
|
451
|
-
data_type_type, self.use_union_operator
|
|
452
|
-
)
|
|
405
|
+
non_optional_data_type_type = _remove_none_from_union(data_type_type, self.use_union_operator)
|
|
453
406
|
|
|
454
407
|
if non_optional_data_type_type != data_type_type:
|
|
455
408
|
self.is_optional = True
|
|
@@ -457,28 +410,23 @@ class DataType(_BaseModel):
|
|
|
457
410
|
data_types.append(non_optional_data_type_type)
|
|
458
411
|
if len(data_types) == 1:
|
|
459
412
|
type_ = data_types[0]
|
|
413
|
+
elif self.use_union_operator:
|
|
414
|
+
type_ = UNION_OPERATOR_DELIMITER.join(data_types)
|
|
460
415
|
else:
|
|
461
|
-
|
|
462
|
-
type_ = UNION_OPERATOR_DELIMITER.join(data_types)
|
|
463
|
-
else:
|
|
464
|
-
type_ = f'{UNION_PREFIX}{UNION_DELIMITER.join(data_types)}]'
|
|
416
|
+
type_ = f"{UNION_PREFIX}{UNION_DELIMITER.join(data_types)}]"
|
|
465
417
|
elif len(self.data_types) == 1:
|
|
466
418
|
type_ = self.data_types[0].type_hint
|
|
467
419
|
elif self.literals:
|
|
468
|
-
type_ = f
|
|
420
|
+
type_ = f"{LITERAL}[{', '.join(repr(literal) for literal in self.literals)}]"
|
|
421
|
+
elif self.reference:
|
|
422
|
+
type_ = self.reference.short_name
|
|
469
423
|
else:
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
else:
|
|
473
|
-
# TODO support strict Any
|
|
474
|
-
# type_ = 'Any'
|
|
475
|
-
type_ = ''
|
|
424
|
+
# TODO support strict Any
|
|
425
|
+
type_ = ""
|
|
476
426
|
if self.reference:
|
|
477
427
|
source = self.reference.source
|
|
478
428
|
if isinstance(source, Nullable) and source.nullable:
|
|
479
429
|
self.is_optional = True
|
|
480
|
-
if self.reference and self.python_version == PythonVersion.PY_36:
|
|
481
|
-
type_ = f"'{type_}'"
|
|
482
430
|
if self.is_list:
|
|
483
431
|
if self.use_generic_container:
|
|
484
432
|
list_ = SEQUENCE
|
|
@@ -486,7 +434,7 @@ class DataType(_BaseModel):
|
|
|
486
434
|
list_ = STANDARD_LIST
|
|
487
435
|
else:
|
|
488
436
|
list_ = LIST
|
|
489
|
-
type_ = f
|
|
437
|
+
type_ = f"{list_}[{type_}]" if type_ else list_
|
|
490
438
|
elif self.is_set:
|
|
491
439
|
if self.use_generic_container:
|
|
492
440
|
set_ = FROZEN_SET
|
|
@@ -494,7 +442,7 @@ class DataType(_BaseModel):
|
|
|
494
442
|
set_ = STANDARD_SET
|
|
495
443
|
else:
|
|
496
444
|
set_ = SET
|
|
497
|
-
type_ = f
|
|
445
|
+
type_ = f"{set_}[{type_}]" if type_ else set_
|
|
498
446
|
elif self.is_dict:
|
|
499
447
|
if self.use_generic_container:
|
|
500
448
|
dict_ = MAPPING
|
|
@@ -504,16 +452,16 @@ class DataType(_BaseModel):
|
|
|
504
452
|
dict_ = DICT
|
|
505
453
|
if self.dict_key or type_:
|
|
506
454
|
key = self.dict_key.type_hint if self.dict_key else STR
|
|
507
|
-
type_ = f
|
|
455
|
+
type_ = f"{dict_}[{key}, {type_ or ANY}]"
|
|
508
456
|
else: # pragma: no cover
|
|
509
457
|
type_ = dict_
|
|
510
458
|
if self.is_optional and type_ != ANY:
|
|
511
459
|
return get_optional_type(type_, self.use_union_operator)
|
|
512
|
-
|
|
460
|
+
if self.is_func:
|
|
513
461
|
if self.kwargs:
|
|
514
|
-
kwargs: str =
|
|
515
|
-
return f
|
|
516
|
-
return f
|
|
462
|
+
kwargs: str = ", ".join(f"{k}={v}" for k, v in self.kwargs.items())
|
|
463
|
+
return f"{type_}({kwargs})"
|
|
464
|
+
return f"{type_}()"
|
|
517
465
|
return type_
|
|
518
466
|
|
|
519
467
|
@property
|
|
@@ -523,7 +471,7 @@ class DataType(_BaseModel):
|
|
|
523
471
|
|
|
524
472
|
DataType.model_rebuild()
|
|
525
473
|
|
|
526
|
-
DataTypeT = TypeVar(
|
|
474
|
+
DataTypeT = TypeVar("DataTypeT", bound=DataType)
|
|
527
475
|
|
|
528
476
|
|
|
529
477
|
class EmptyDataType(DataType):
|
|
@@ -568,16 +516,16 @@ class Types(Enum):
|
|
|
568
516
|
|
|
569
517
|
|
|
570
518
|
class DataTypeManager(ABC):
|
|
571
|
-
def __init__(
|
|
519
|
+
def __init__( # noqa: PLR0913, PLR0917
|
|
572
520
|
self,
|
|
573
|
-
python_version: PythonVersion =
|
|
574
|
-
use_standard_collections: bool = False,
|
|
575
|
-
use_generic_container_types: bool = False,
|
|
576
|
-
strict_types:
|
|
577
|
-
use_non_positive_negative_number_constrained_types: bool = False,
|
|
578
|
-
use_union_operator: bool = False,
|
|
579
|
-
use_pendulum: bool = False,
|
|
580
|
-
target_datetime_class:
|
|
521
|
+
python_version: PythonVersion = PythonVersionMin,
|
|
522
|
+
use_standard_collections: bool = False, # noqa: FBT001, FBT002
|
|
523
|
+
use_generic_container_types: bool = False, # noqa: FBT001, FBT002
|
|
524
|
+
strict_types: Sequence[StrictTypes] | None = None,
|
|
525
|
+
use_non_positive_negative_number_constrained_types: bool = False, # noqa: FBT001, FBT002
|
|
526
|
+
use_union_operator: bool = False, # noqa: FBT001, FBT002
|
|
527
|
+
use_pendulum: bool = False, # noqa: FBT001, FBT002
|
|
528
|
+
target_datetime_class: DatetimeClassType | None = None,
|
|
581
529
|
) -> None:
|
|
582
530
|
self.python_version = python_version
|
|
583
531
|
self.use_standard_collections: bool = use_standard_collections
|
|
@@ -588,23 +536,13 @@ class DataTypeManager(ABC):
|
|
|
588
536
|
)
|
|
589
537
|
self.use_union_operator: bool = use_union_operator
|
|
590
538
|
self.use_pendulum: bool = use_pendulum
|
|
591
|
-
self.target_datetime_class: DatetimeClassType =
|
|
592
|
-
target_datetime_class or DatetimeClassType.Datetime
|
|
593
|
-
)
|
|
594
|
-
|
|
595
|
-
if (
|
|
596
|
-
use_generic_container_types and python_version == PythonVersion.PY_36
|
|
597
|
-
): # pragma: no cover
|
|
598
|
-
raise Exception(
|
|
599
|
-
'use_generic_container_types can not be used with target_python_version 3.6.\n'
|
|
600
|
-
' The version will be not supported in a future version'
|
|
601
|
-
)
|
|
539
|
+
self.target_datetime_class: DatetimeClassType = target_datetime_class or DatetimeClassType.Datetime
|
|
602
540
|
|
|
603
541
|
if TYPE_CHECKING:
|
|
604
|
-
self.data_type:
|
|
542
|
+
self.data_type: type[DataType]
|
|
605
543
|
else:
|
|
606
|
-
self.data_type:
|
|
607
|
-
|
|
544
|
+
self.data_type: type[DataType] = create_model(
|
|
545
|
+
"ContextDataType",
|
|
608
546
|
python_version=(PythonVersion, python_version),
|
|
609
547
|
use_standard_collections=(bool, use_standard_collections),
|
|
610
548
|
use_generic_container=(bool, use_generic_container_types),
|
|
@@ -616,15 +554,11 @@ class DataTypeManager(ABC):
|
|
|
616
554
|
def get_data_type(self, types: Types, **kwargs: Any) -> DataType:
|
|
617
555
|
raise NotImplementedError
|
|
618
556
|
|
|
619
|
-
def get_data_type_from_full_path(
|
|
620
|
-
self
|
|
621
|
-
) -> DataType:
|
|
622
|
-
return self.data_type.from_import(
|
|
623
|
-
Import.from_full_path(full_path), is_custom_type=is_custom_type
|
|
624
|
-
)
|
|
557
|
+
def get_data_type_from_full_path(self, full_path: str, is_custom_type: bool) -> DataType: # noqa: FBT001
|
|
558
|
+
return self.data_type.from_import(Import.from_full_path(full_path), is_custom_type=is_custom_type)
|
|
625
559
|
|
|
626
560
|
def get_data_type_from_value(self, value: Any) -> DataType:
|
|
627
|
-
type_:
|
|
561
|
+
type_: Types | None = None
|
|
628
562
|
if isinstance(value, str):
|
|
629
563
|
type_ = Types.string
|
|
630
564
|
elif isinstance(value, bool):
|