datamodel-code-generator 0.27.2__py3-none-any.whl → 0.27.3__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 +159 -190
- datamodel_code_generator/__main__.py +151 -173
- datamodel_code_generator/arguments.py +227 -230
- datamodel_code_generator/format.py +77 -99
- datamodel_code_generator/http.py +9 -10
- datamodel_code_generator/imports.py +57 -64
- datamodel_code_generator/model/__init__.py +26 -31
- datamodel_code_generator/model/base.py +94 -127
- datamodel_code_generator/model/dataclass.py +58 -59
- datamodel_code_generator/model/enum.py +34 -30
- datamodel_code_generator/model/imports.py +13 -11
- datamodel_code_generator/model/msgspec.py +112 -126
- datamodel_code_generator/model/pydantic/__init__.py +14 -27
- datamodel_code_generator/model/pydantic/base_model.py +120 -139
- 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 +86 -117
- datamodel_code_generator/model/pydantic_v2/__init__.py +17 -17
- datamodel_code_generator/model/pydantic_v2/base_model.py +118 -119
- 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 +8 -7
- datamodel_code_generator/model/rootmodel.py +1 -1
- datamodel_code_generator/model/scalar.py +33 -32
- datamodel_code_generator/model/typed_dict.py +42 -41
- datamodel_code_generator/model/types.py +19 -17
- datamodel_code_generator/model/union.py +21 -17
- datamodel_code_generator/parser/__init__.py +12 -11
- datamodel_code_generator/parser/base.py +320 -492
- datamodel_code_generator/parser/graphql.py +80 -111
- datamodel_code_generator/parser/jsonschema.py +422 -580
- datamodel_code_generator/parser/openapi.py +175 -204
- datamodel_code_generator/pydantic_patch.py +8 -9
- datamodel_code_generator/reference.py +192 -274
- datamodel_code_generator/types.py +147 -182
- datamodel_code_generator/util.py +22 -26
- {datamodel_code_generator-0.27.2.dist-info → datamodel_code_generator-0.27.3.dist-info}/METADATA +7 -1
- datamodel_code_generator-0.27.3.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.27.3.dist-info}/WHEEL +0 -0
- {datamodel_code_generator-0.27.2.dist-info → datamodel_code_generator-0.27.3.dist-info}/entry_points.txt +0 -0
- {datamodel_code_generator-0.27.2.dist-info → datamodel_code_generator-0.27.3.dist-info}/licenses/LICENSE +0 -0
|
@@ -3,12 +3,11 @@ from __future__ import annotations
|
|
|
3
3
|
import re
|
|
4
4
|
from collections import defaultdict
|
|
5
5
|
from enum import Enum
|
|
6
|
-
from pathlib import Path
|
|
7
6
|
from typing import (
|
|
7
|
+
TYPE_CHECKING,
|
|
8
8
|
Any,
|
|
9
9
|
Callable,
|
|
10
10
|
ClassVar,
|
|
11
|
-
DefaultDict,
|
|
12
11
|
Dict,
|
|
13
12
|
Iterable,
|
|
14
13
|
List,
|
|
@@ -16,13 +15,9 @@ from typing import (
|
|
|
16
15
|
Optional,
|
|
17
16
|
Pattern,
|
|
18
17
|
Sequence,
|
|
19
|
-
Set,
|
|
20
|
-
Tuple,
|
|
21
|
-
Type,
|
|
22
18
|
TypeVar,
|
|
23
19
|
Union,
|
|
24
20
|
)
|
|
25
|
-
from urllib.parse import ParseResult
|
|
26
21
|
from warnings import warn
|
|
27
22
|
|
|
28
23
|
from pydantic import Field
|
|
@@ -54,182 +49,184 @@ from datamodel_code_generator.types import (
|
|
|
54
49
|
)
|
|
55
50
|
from datamodel_code_generator.util import BaseModel
|
|
56
51
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
52
|
+
if TYPE_CHECKING:
|
|
53
|
+
from pathlib import Path
|
|
54
|
+
from urllib.parse import ParseResult
|
|
55
|
+
|
|
56
|
+
RE_APPLICATION_JSON_PATTERN: Pattern[str] = re.compile(r"^application/.*json$")
|
|
57
|
+
|
|
58
|
+
OPERATION_NAMES: list[str] = [
|
|
59
|
+
"get",
|
|
60
|
+
"put",
|
|
61
|
+
"post",
|
|
62
|
+
"delete",
|
|
63
|
+
"patch",
|
|
64
|
+
"head",
|
|
65
|
+
"options",
|
|
66
|
+
"trace",
|
|
68
67
|
]
|
|
69
68
|
|
|
70
69
|
|
|
71
70
|
class ParameterLocation(Enum):
|
|
72
|
-
query =
|
|
73
|
-
header =
|
|
74
|
-
path =
|
|
75
|
-
cookie =
|
|
71
|
+
query = "query"
|
|
72
|
+
header = "header"
|
|
73
|
+
path = "path"
|
|
74
|
+
cookie = "cookie"
|
|
76
75
|
|
|
77
76
|
|
|
78
|
-
BaseModelT = TypeVar(
|
|
77
|
+
BaseModelT = TypeVar("BaseModelT", bound=BaseModel)
|
|
79
78
|
|
|
80
79
|
|
|
81
80
|
class ReferenceObject(BaseModel):
|
|
82
|
-
ref: str = Field(..., alias=
|
|
81
|
+
ref: str = Field(..., alias="$ref")
|
|
83
82
|
|
|
84
83
|
|
|
85
84
|
class ExampleObject(BaseModel):
|
|
86
|
-
summary: Optional[str] = None
|
|
87
|
-
description: Optional[str] = None
|
|
85
|
+
summary: Optional[str] = None # noqa: UP045
|
|
86
|
+
description: Optional[str] = None # noqa: UP045
|
|
88
87
|
value: Any = None
|
|
89
|
-
externalValue: Optional[str] = None
|
|
88
|
+
externalValue: Optional[str] = None # noqa: N815, UP045
|
|
90
89
|
|
|
91
90
|
|
|
92
91
|
class MediaObject(BaseModel):
|
|
93
|
-
schema_: Union[ReferenceObject, JsonSchemaObject
|
|
94
|
-
None, alias='schema'
|
|
95
|
-
)
|
|
92
|
+
schema_: Optional[Union[ReferenceObject, JsonSchemaObject]] = Field(None, alias="schema") # noqa: UP007, UP045
|
|
96
93
|
example: Any = None
|
|
97
|
-
examples: Union[str, ReferenceObject, ExampleObject
|
|
94
|
+
examples: Optional[Union[str, ReferenceObject, ExampleObject]] = None # noqa: UP007, UP045
|
|
98
95
|
|
|
99
96
|
|
|
100
97
|
class ParameterObject(BaseModel):
|
|
101
|
-
name: Optional[str] = None
|
|
102
|
-
in_: Optional[ParameterLocation] = Field(None, alias=
|
|
103
|
-
description: Optional[str] = None
|
|
98
|
+
name: Optional[str] = None # noqa: UP045
|
|
99
|
+
in_: Optional[ParameterLocation] = Field(None, alias="in") # noqa: UP045
|
|
100
|
+
description: Optional[str] = None # noqa: UP045
|
|
104
101
|
required: bool = False
|
|
105
102
|
deprecated: bool = False
|
|
106
|
-
schema_: Optional[JsonSchemaObject] = Field(None, alias=
|
|
103
|
+
schema_: Optional[JsonSchemaObject] = Field(None, alias="schema") # noqa: UP045
|
|
107
104
|
example: Any = None
|
|
108
|
-
examples: Union[str, ReferenceObject, ExampleObject
|
|
109
|
-
content: Dict[str, MediaObject] = {}
|
|
105
|
+
examples: Optional[Union[str, ReferenceObject, ExampleObject]] = None # noqa: UP007, UP045
|
|
106
|
+
content: Dict[str, MediaObject] = {} # noqa: RUF012, UP006
|
|
110
107
|
|
|
111
108
|
|
|
112
109
|
class HeaderObject(BaseModel):
|
|
113
|
-
description: Optional[str] = None
|
|
110
|
+
description: Optional[str] = None # noqa: UP045
|
|
114
111
|
required: bool = False
|
|
115
112
|
deprecated: bool = False
|
|
116
|
-
schema_: Optional[JsonSchemaObject] = Field(None, alias=
|
|
113
|
+
schema_: Optional[JsonSchemaObject] = Field(None, alias="schema") # noqa: UP045
|
|
117
114
|
example: Any = None
|
|
118
|
-
examples: Union[str, ReferenceObject, ExampleObject
|
|
119
|
-
content: Dict[str, MediaObject] = {}
|
|
115
|
+
examples: Optional[Union[str, ReferenceObject, ExampleObject]] = None # noqa: UP007, UP045
|
|
116
|
+
content: Dict[str, MediaObject] = {} # noqa: RUF012, UP006
|
|
120
117
|
|
|
121
118
|
|
|
122
119
|
class RequestBodyObject(BaseModel):
|
|
123
|
-
description: Optional[str] = None
|
|
124
|
-
content: Dict[str, MediaObject] = {}
|
|
120
|
+
description: Optional[str] = None # noqa: UP045
|
|
121
|
+
content: Dict[str, MediaObject] = {} # noqa: RUF012, UP006
|
|
125
122
|
required: bool = False
|
|
126
123
|
|
|
127
124
|
|
|
128
125
|
class ResponseObject(BaseModel):
|
|
129
|
-
description: Optional[str] = None
|
|
130
|
-
headers: Dict[str, ParameterObject] = {}
|
|
131
|
-
content: Dict[Union[str, int], MediaObject] = {}
|
|
126
|
+
description: Optional[str] = None # noqa: UP045
|
|
127
|
+
headers: Dict[str, ParameterObject] = {} # noqa: RUF012, UP006
|
|
128
|
+
content: Dict[Union[str, int], MediaObject] = {} # noqa: RUF012, UP006, UP007
|
|
132
129
|
|
|
133
130
|
|
|
134
131
|
class Operation(BaseModel):
|
|
135
|
-
tags: List[str] = []
|
|
136
|
-
summary: Optional[str] = None
|
|
137
|
-
description: Optional[str] = None
|
|
138
|
-
operationId: Optional[str] = None
|
|
139
|
-
parameters: List[Union[ReferenceObject, ParameterObject]] = []
|
|
140
|
-
requestBody: Union[ReferenceObject, RequestBodyObject
|
|
141
|
-
responses: Dict[Union[str, int], Union[ReferenceObject, ResponseObject]] = {}
|
|
132
|
+
tags: List[str] = [] # noqa: RUF012, UP006
|
|
133
|
+
summary: Optional[str] = None # noqa: UP045
|
|
134
|
+
description: Optional[str] = None # noqa: UP045
|
|
135
|
+
operationId: Optional[str] = None # noqa: N815, UP045
|
|
136
|
+
parameters: List[Union[ReferenceObject, ParameterObject]] = [] # noqa: RUF012, UP006, UP007
|
|
137
|
+
requestBody: Optional[Union[ReferenceObject, RequestBodyObject]] = None # noqa: N815, UP007, UP045
|
|
138
|
+
responses: Dict[Union[str, int], Union[ReferenceObject, ResponseObject]] = {} # noqa: RUF012, UP006, UP007
|
|
142
139
|
deprecated: bool = False
|
|
143
140
|
|
|
144
141
|
|
|
145
142
|
class ComponentsObject(BaseModel):
|
|
146
|
-
schemas: Dict[str, Union[ReferenceObject, JsonSchemaObject]] = {}
|
|
147
|
-
responses: Dict[str, Union[ReferenceObject, ResponseObject]] = {}
|
|
148
|
-
examples: Dict[str, Union[ReferenceObject, ExampleObject]] = {}
|
|
149
|
-
requestBodies: Dict[str, Union[ReferenceObject, RequestBodyObject]] = {}
|
|
150
|
-
headers: Dict[str, Union[ReferenceObject, HeaderObject]] = {}
|
|
143
|
+
schemas: Dict[str, Union[ReferenceObject, JsonSchemaObject]] = {} # noqa: RUF012, UP006, UP007
|
|
144
|
+
responses: Dict[str, Union[ReferenceObject, ResponseObject]] = {} # noqa: RUF012, UP006, UP007
|
|
145
|
+
examples: Dict[str, Union[ReferenceObject, ExampleObject]] = {} # noqa: RUF012, UP006, UP007
|
|
146
|
+
requestBodies: Dict[str, Union[ReferenceObject, RequestBodyObject]] = {} # noqa: N815, RUF012, UP006, UP007
|
|
147
|
+
headers: Dict[str, Union[ReferenceObject, HeaderObject]] = {} # noqa: RUF012, UP006, UP007
|
|
151
148
|
|
|
152
149
|
|
|
153
|
-
@snooper_to_methods(
|
|
150
|
+
@snooper_to_methods()
|
|
154
151
|
class OpenAPIParser(JsonSchemaParser):
|
|
155
|
-
SCHEMA_PATHS: ClassVar[List[str]] = [
|
|
152
|
+
SCHEMA_PATHS: ClassVar[List[str]] = ["#/components/schemas"] # noqa: UP006
|
|
156
153
|
|
|
157
|
-
def __init__(
|
|
154
|
+
def __init__( # noqa: PLR0913
|
|
158
155
|
self,
|
|
159
|
-
source:
|
|
156
|
+
source: str | Path | list[Path] | ParseResult,
|
|
160
157
|
*,
|
|
161
|
-
data_model_type:
|
|
162
|
-
data_model_root_type:
|
|
163
|
-
data_type_manager_type:
|
|
164
|
-
data_model_field_type:
|
|
165
|
-
base_class:
|
|
166
|
-
additional_imports:
|
|
167
|
-
custom_template_dir:
|
|
168
|
-
extra_template_data:
|
|
158
|
+
data_model_type: type[DataModel] = pydantic_model.BaseModel,
|
|
159
|
+
data_model_root_type: type[DataModel] = pydantic_model.CustomRootType,
|
|
160
|
+
data_type_manager_type: type[DataTypeManager] = pydantic_model.DataTypeManager,
|
|
161
|
+
data_model_field_type: type[DataModelFieldBase] = pydantic_model.DataModelField,
|
|
162
|
+
base_class: str | None = None,
|
|
163
|
+
additional_imports: list[str] | None = None,
|
|
164
|
+
custom_template_dir: Path | None = None,
|
|
165
|
+
extra_template_data: defaultdict[str, dict[str, Any]] | None = None,
|
|
169
166
|
target_python_version: PythonVersion = PythonVersion.PY_38,
|
|
170
|
-
dump_resolve_reference_action:
|
|
167
|
+
dump_resolve_reference_action: Callable[[Iterable[str]], str] | None = None,
|
|
171
168
|
validation: bool = False,
|
|
172
169
|
field_constraints: bool = False,
|
|
173
170
|
snake_case_field: bool = False,
|
|
174
171
|
strip_default_none: bool = False,
|
|
175
|
-
aliases:
|
|
172
|
+
aliases: Mapping[str, str] | None = None,
|
|
176
173
|
allow_population_by_field_name: bool = False,
|
|
177
174
|
allow_extra_fields: bool = False,
|
|
178
175
|
apply_default_values_for_required_fields: bool = False,
|
|
179
176
|
force_optional_for_required_fields: bool = False,
|
|
180
|
-
class_name:
|
|
177
|
+
class_name: str | None = None,
|
|
181
178
|
use_standard_collections: bool = False,
|
|
182
|
-
base_path:
|
|
179
|
+
base_path: Path | None = None,
|
|
183
180
|
use_schema_description: bool = False,
|
|
184
181
|
use_field_description: bool = False,
|
|
185
182
|
use_default_kwarg: bool = False,
|
|
186
183
|
reuse_model: bool = False,
|
|
187
|
-
encoding: str =
|
|
188
|
-
enum_field_as_literal:
|
|
184
|
+
encoding: str = "utf-8",
|
|
185
|
+
enum_field_as_literal: LiteralType | None = None,
|
|
189
186
|
use_one_literal_as_default: bool = False,
|
|
190
187
|
set_default_enum_member: bool = False,
|
|
191
188
|
use_subclass_enum: bool = False,
|
|
192
189
|
strict_nullable: bool = False,
|
|
193
190
|
use_generic_container_types: bool = False,
|
|
194
191
|
enable_faux_immutability: bool = False,
|
|
195
|
-
remote_text_cache:
|
|
192
|
+
remote_text_cache: DefaultPutDict[str, str] | None = None,
|
|
196
193
|
disable_appending_item_suffix: bool = False,
|
|
197
|
-
strict_types:
|
|
198
|
-
empty_enum_field_name:
|
|
199
|
-
custom_class_name_generator:
|
|
200
|
-
field_extra_keys:
|
|
194
|
+
strict_types: Sequence[StrictTypes] | None = None,
|
|
195
|
+
empty_enum_field_name: str | None = None,
|
|
196
|
+
custom_class_name_generator: Callable[[str], str] | None = None,
|
|
197
|
+
field_extra_keys: set[str] | None = None,
|
|
201
198
|
field_include_all_keys: bool = False,
|
|
202
|
-
field_extra_keys_without_x_prefix:
|
|
203
|
-
openapi_scopes:
|
|
204
|
-
wrap_string_literal:
|
|
199
|
+
field_extra_keys_without_x_prefix: set[str] | None = None,
|
|
200
|
+
openapi_scopes: list[OpenAPIScope] | None = None,
|
|
201
|
+
wrap_string_literal: bool | None = False,
|
|
205
202
|
use_title_as_name: bool = False,
|
|
206
203
|
use_operation_id_as_name: bool = False,
|
|
207
204
|
use_unique_items_as_set: bool = False,
|
|
208
|
-
http_headers:
|
|
205
|
+
http_headers: Sequence[tuple[str, str]] | None = None,
|
|
209
206
|
http_ignore_tls: bool = False,
|
|
210
207
|
use_annotated: bool = False,
|
|
211
208
|
use_non_positive_negative_number_constrained_types: bool = False,
|
|
212
|
-
original_field_name_delimiter:
|
|
209
|
+
original_field_name_delimiter: str | None = None,
|
|
213
210
|
use_double_quotes: bool = False,
|
|
214
211
|
use_union_operator: bool = False,
|
|
215
212
|
allow_responses_without_content: bool = False,
|
|
216
213
|
collapse_root_models: bool = False,
|
|
217
|
-
special_field_name_prefix:
|
|
214
|
+
special_field_name_prefix: str | None = None,
|
|
218
215
|
remove_special_field_name_prefix: bool = False,
|
|
219
216
|
capitalise_enum_members: bool = False,
|
|
220
217
|
keep_model_order: bool = False,
|
|
221
|
-
known_third_party:
|
|
222
|
-
custom_formatters:
|
|
223
|
-
custom_formatters_kwargs:
|
|
218
|
+
known_third_party: list[str] | None = None,
|
|
219
|
+
custom_formatters: list[str] | None = None,
|
|
220
|
+
custom_formatters_kwargs: dict[str, Any] | None = None,
|
|
224
221
|
use_pendulum: bool = False,
|
|
225
|
-
http_query_parameters:
|
|
222
|
+
http_query_parameters: Sequence[tuple[str, str]] | None = None,
|
|
226
223
|
treat_dots_as_module: bool = False,
|
|
227
224
|
use_exact_imports: bool = False,
|
|
228
|
-
default_field_extras:
|
|
225
|
+
default_field_extras: dict[str, Any] | None = None,
|
|
229
226
|
target_datetime_class: DatetimeClassType = DatetimeClassType.Datetime,
|
|
230
227
|
keyword_only: bool = False,
|
|
231
228
|
no_alias: bool = False,
|
|
232
|
-
):
|
|
229
|
+
) -> None:
|
|
233
230
|
super().__init__(
|
|
234
231
|
source=source,
|
|
235
232
|
data_model_type=data_model_type,
|
|
@@ -303,17 +300,12 @@ class OpenAPIParser(JsonSchemaParser):
|
|
|
303
300
|
keyword_only=keyword_only,
|
|
304
301
|
no_alias=no_alias,
|
|
305
302
|
)
|
|
306
|
-
self.open_api_scopes:
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
if ref_file:
|
|
313
|
-
ref_body = self._get_ref_body(ref_file)
|
|
314
|
-
else: # pragma: no cover
|
|
315
|
-
ref_body = self.raw_obj
|
|
316
|
-
return get_model_by_path(ref_body, ref_path.split('/')[1:])
|
|
303
|
+
self.open_api_scopes: list[OpenAPIScope] = openapi_scopes or [OpenAPIScope.Schemas]
|
|
304
|
+
|
|
305
|
+
def get_ref_model(self, ref: str) -> dict[str, Any]:
|
|
306
|
+
ref_file, ref_path = self.model_resolver.resolve_ref(ref).split("#", 1)
|
|
307
|
+
ref_body = self._get_ref_body(ref_file) if ref_file else self.raw_obj
|
|
308
|
+
return get_model_by_path(ref_body, ref_path.split("/")[1:])
|
|
317
309
|
|
|
318
310
|
def get_data_type(self, obj: JsonSchemaObject) -> DataType:
|
|
319
311
|
# OpenAPI 3.0 doesn't allow `null` in the `type` field and list of types
|
|
@@ -321,13 +313,11 @@ class OpenAPIParser(JsonSchemaParser):
|
|
|
321
313
|
# OpenAPI 3.1 does allow `null` in the `type` field and is equivalent to
|
|
322
314
|
# a `nullable` flag on the property itself
|
|
323
315
|
if obj.nullable and self.strict_nullable and isinstance(obj.type, str):
|
|
324
|
-
obj.type = [obj.type,
|
|
316
|
+
obj.type = [obj.type, "null"]
|
|
325
317
|
|
|
326
318
|
return super().get_data_type(obj)
|
|
327
319
|
|
|
328
|
-
def resolve_object(
|
|
329
|
-
self, obj: Union[ReferenceObject, BaseModelT], object_type: Type[BaseModelT]
|
|
330
|
-
) -> BaseModelT:
|
|
320
|
+
def resolve_object(self, obj: ReferenceObject | BaseModelT, object_type: type[BaseModelT]) -> BaseModelT:
|
|
331
321
|
if isinstance(obj, ReferenceObject):
|
|
332
322
|
ref_obj = self.get_ref_model(obj.ref)
|
|
333
323
|
return object_type.parse_obj(ref_obj)
|
|
@@ -337,7 +327,7 @@ class OpenAPIParser(JsonSchemaParser):
|
|
|
337
327
|
self,
|
|
338
328
|
name: str,
|
|
339
329
|
obj: JsonSchemaObject,
|
|
340
|
-
path:
|
|
330
|
+
path: list[str],
|
|
341
331
|
) -> DataType:
|
|
342
332
|
if obj.is_array:
|
|
343
333
|
data_type = self.parse_array(name, obj, [*path, name])
|
|
@@ -362,7 +352,7 @@ class OpenAPIParser(JsonSchemaParser):
|
|
|
362
352
|
self,
|
|
363
353
|
name: str,
|
|
364
354
|
request_body: RequestBodyObject,
|
|
365
|
-
path:
|
|
355
|
+
path: list[str],
|
|
366
356
|
) -> None:
|
|
367
357
|
for (
|
|
368
358
|
media_type,
|
|
@@ -374,39 +364,34 @@ class OpenAPIParser(JsonSchemaParser):
|
|
|
374
364
|
def parse_responses(
|
|
375
365
|
self,
|
|
376
366
|
name: str,
|
|
377
|
-
responses:
|
|
378
|
-
path:
|
|
379
|
-
) ->
|
|
380
|
-
data_types:
|
|
381
|
-
dict
|
|
382
|
-
)
|
|
367
|
+
responses: dict[str | int, ReferenceObject | ResponseObject],
|
|
368
|
+
path: list[str],
|
|
369
|
+
) -> dict[str | int, dict[str, DataType]]:
|
|
370
|
+
data_types: defaultdict[str | int, dict[str, DataType]] = defaultdict(dict)
|
|
383
371
|
for status_code, detail in responses.items():
|
|
384
372
|
if isinstance(detail, ReferenceObject):
|
|
385
373
|
if not detail.ref: # pragma: no cover
|
|
386
374
|
continue
|
|
387
375
|
ref_model = self.get_ref_model(detail.ref)
|
|
388
|
-
content = {
|
|
389
|
-
k: MediaObject.parse_obj(v)
|
|
390
|
-
for k, v in ref_model.get('content', {}).items()
|
|
391
|
-
}
|
|
376
|
+
content = {k: MediaObject.parse_obj(v) for k, v in ref_model.get("content", {}).items()}
|
|
392
377
|
else:
|
|
393
378
|
content = detail.content
|
|
394
379
|
|
|
395
380
|
if self.allow_responses_without_content and not content:
|
|
396
|
-
data_types[status_code][
|
|
381
|
+
data_types[status_code]["application/json"] = DataType(type="None")
|
|
397
382
|
|
|
398
383
|
for content_type, obj in content.items():
|
|
399
384
|
object_schema = obj.schema_
|
|
400
385
|
if not object_schema: # pragma: no cover
|
|
401
386
|
continue
|
|
402
387
|
if isinstance(object_schema, JsonSchemaObject):
|
|
403
|
-
data_types[status_code][content_type] = self.parse_schema( # pyright: ignore
|
|
388
|
+
data_types[status_code][content_type] = self.parse_schema( # pyright: ignore[reportArgumentType]
|
|
404
389
|
name,
|
|
405
390
|
object_schema,
|
|
406
|
-
[*path, str(status_code), content_type], # pyright: ignore
|
|
391
|
+
[*path, str(status_code), content_type], # pyright: ignore[reportArgumentType]
|
|
407
392
|
)
|
|
408
393
|
else:
|
|
409
|
-
data_types[status_code][content_type] = self.get_ref_data_type( # pyright: ignore
|
|
394
|
+
data_types[status_code][content_type] = self.get_ref_data_type( # pyright: ignore[reportArgumentType]
|
|
410
395
|
object_schema.ref
|
|
411
396
|
)
|
|
412
397
|
|
|
@@ -415,28 +400,28 @@ class OpenAPIParser(JsonSchemaParser):
|
|
|
415
400
|
@classmethod
|
|
416
401
|
def parse_tags(
|
|
417
402
|
cls,
|
|
418
|
-
name: str,
|
|
419
|
-
tags:
|
|
420
|
-
path:
|
|
421
|
-
) ->
|
|
403
|
+
name: str, # noqa: ARG003
|
|
404
|
+
tags: list[str],
|
|
405
|
+
path: list[str], # noqa: ARG003
|
|
406
|
+
) -> list[str]:
|
|
422
407
|
return tags
|
|
423
408
|
|
|
424
409
|
@classmethod
|
|
425
410
|
def _get_model_name(cls, path_name: str, method: str, suffix: str) -> str:
|
|
426
|
-
camel_path_name = snake_to_upper_camel(path_name.replace(
|
|
427
|
-
return f
|
|
411
|
+
camel_path_name = snake_to_upper_camel(path_name.replace("/", "_"))
|
|
412
|
+
return f"{camel_path_name}{method.capitalize()}{suffix}"
|
|
428
413
|
|
|
429
414
|
def parse_all_parameters(
|
|
430
415
|
self,
|
|
431
416
|
name: str,
|
|
432
|
-
parameters:
|
|
433
|
-
path:
|
|
417
|
+
parameters: list[ReferenceObject | ParameterObject],
|
|
418
|
+
path: list[str],
|
|
434
419
|
) -> None:
|
|
435
|
-
fields:
|
|
436
|
-
exclude_field_names:
|
|
420
|
+
fields: list[DataModelFieldBase] = []
|
|
421
|
+
exclude_field_names: set[str] = set()
|
|
437
422
|
reference = self.model_resolver.add(path, name, class_name=True, unique=True)
|
|
438
|
-
for
|
|
439
|
-
parameter = self.resolve_object(
|
|
423
|
+
for parameter_ in parameters:
|
|
424
|
+
parameter = self.resolve_object(parameter_, ParameterObject)
|
|
440
425
|
parameter_name = parameter.name
|
|
441
426
|
if not parameter_name or parameter.in_ != ParameterLocation.query:
|
|
442
427
|
continue
|
|
@@ -448,26 +433,22 @@ class OpenAPIParser(JsonSchemaParser):
|
|
|
448
433
|
self.get_object_field(
|
|
449
434
|
field_name=field_name,
|
|
450
435
|
field=parameter.schema_,
|
|
451
|
-
field_type=self.parse_item(
|
|
452
|
-
field_name, parameter.schema_, [*path, name, parameter_name]
|
|
453
|
-
),
|
|
436
|
+
field_type=self.parse_item(field_name, parameter.schema_, [*path, name, parameter_name]),
|
|
454
437
|
original_field_name=parameter_name,
|
|
455
438
|
required=parameter.required,
|
|
456
439
|
alias=alias,
|
|
457
440
|
)
|
|
458
441
|
)
|
|
459
442
|
else:
|
|
460
|
-
data_types:
|
|
461
|
-
object_schema:
|
|
443
|
+
data_types: list[DataType] = []
|
|
444
|
+
object_schema: JsonSchemaObject | None = None
|
|
462
445
|
for (
|
|
463
446
|
media_type,
|
|
464
447
|
media_obj,
|
|
465
448
|
) in parameter.content.items():
|
|
466
449
|
if not media_obj.schema_:
|
|
467
450
|
continue
|
|
468
|
-
object_schema = self.resolve_object(
|
|
469
|
-
media_obj.schema_, JsonSchemaObject
|
|
470
|
-
)
|
|
451
|
+
object_schema = self.resolve_object(media_obj.schema_, JsonSchemaObject)
|
|
471
452
|
data_types.append(
|
|
472
453
|
self.parse_item(
|
|
473
454
|
field_name,
|
|
@@ -495,24 +476,16 @@ class OpenAPIParser(JsonSchemaParser):
|
|
|
495
476
|
if object_schema and self.is_constraints_field(object_schema)
|
|
496
477
|
else None,
|
|
497
478
|
nullable=object_schema.nullable
|
|
498
|
-
if object_schema
|
|
499
|
-
and self.strict_nullable
|
|
500
|
-
and (object_schema.has_default or parameter.required)
|
|
479
|
+
if object_schema and self.strict_nullable and (object_schema.has_default or parameter.required)
|
|
501
480
|
else None,
|
|
502
481
|
strip_default_none=self.strip_default_none,
|
|
503
|
-
extras=self.get_field_extras(object_schema)
|
|
504
|
-
if object_schema
|
|
505
|
-
else {},
|
|
482
|
+
extras=self.get_field_extras(object_schema) if object_schema else {},
|
|
506
483
|
use_annotated=self.use_annotated,
|
|
507
484
|
use_field_description=self.use_field_description,
|
|
508
485
|
use_default_kwarg=self.use_default_kwarg,
|
|
509
486
|
original_name=parameter_name,
|
|
510
|
-
has_default=object_schema.has_default
|
|
511
|
-
if object_schema
|
|
512
|
-
else False,
|
|
513
|
-
type_has_null=object_schema.type_has_null
|
|
514
|
-
if object_schema
|
|
515
|
-
else None,
|
|
487
|
+
has_default=object_schema.has_default if object_schema else False,
|
|
488
|
+
type_has_null=object_schema.type_has_null if object_schema else None,
|
|
516
489
|
)
|
|
517
490
|
)
|
|
518
491
|
|
|
@@ -529,23 +502,24 @@ class OpenAPIParser(JsonSchemaParser):
|
|
|
529
502
|
|
|
530
503
|
def parse_operation(
|
|
531
504
|
self,
|
|
532
|
-
raw_operation:
|
|
533
|
-
path:
|
|
505
|
+
raw_operation: dict[str, Any],
|
|
506
|
+
path: list[str],
|
|
534
507
|
) -> None:
|
|
535
508
|
operation = Operation.parse_obj(raw_operation)
|
|
536
509
|
path_name, method = path[-2:]
|
|
537
510
|
if self.use_operation_id_as_name:
|
|
538
511
|
if not operation.operationId:
|
|
539
|
-
|
|
540
|
-
f
|
|
541
|
-
f
|
|
512
|
+
msg = (
|
|
513
|
+
f"All operations must have an operationId when --use_operation_id_as_name is set."
|
|
514
|
+
f"The following path was missing an operationId: {path_name}"
|
|
542
515
|
)
|
|
516
|
+
raise Error(msg)
|
|
543
517
|
path_name = operation.operationId
|
|
544
|
-
method =
|
|
518
|
+
method = ""
|
|
545
519
|
self.parse_all_parameters(
|
|
546
|
-
self._get_model_name(path_name, method, suffix=
|
|
520
|
+
self._get_model_name(path_name, method, suffix="ParametersQuery"),
|
|
547
521
|
operation.parameters,
|
|
548
|
-
[*path,
|
|
522
|
+
[*path, "parameters"],
|
|
549
523
|
)
|
|
550
524
|
if operation.requestBody:
|
|
551
525
|
if isinstance(operation.requestBody, ReferenceObject):
|
|
@@ -554,54 +528,52 @@ class OpenAPIParser(JsonSchemaParser):
|
|
|
554
528
|
else:
|
|
555
529
|
request_body = operation.requestBody
|
|
556
530
|
self.parse_request_body(
|
|
557
|
-
name=self._get_model_name(path_name, method, suffix=
|
|
531
|
+
name=self._get_model_name(path_name, method, suffix="Request"),
|
|
558
532
|
request_body=request_body,
|
|
559
|
-
path=[*path,
|
|
533
|
+
path=[*path, "requestBody"],
|
|
560
534
|
)
|
|
561
535
|
self.parse_responses(
|
|
562
|
-
name=self._get_model_name(path_name, method, suffix=
|
|
536
|
+
name=self._get_model_name(path_name, method, suffix="Response"),
|
|
563
537
|
responses=operation.responses,
|
|
564
|
-
path=[*path,
|
|
538
|
+
path=[*path, "responses"],
|
|
565
539
|
)
|
|
566
540
|
if OpenAPIScope.Tags in self.open_api_scopes:
|
|
567
541
|
self.parse_tags(
|
|
568
|
-
name=self._get_model_name(path_name, method, suffix=
|
|
542
|
+
name=self._get_model_name(path_name, method, suffix="Tags"),
|
|
569
543
|
tags=operation.tags,
|
|
570
|
-
path=[*path,
|
|
544
|
+
path=[*path, "tags"],
|
|
571
545
|
)
|
|
572
546
|
|
|
573
|
-
def parse_raw(self) -> None:
|
|
574
|
-
for source, path_parts in self._get_context_source_path_parts():
|
|
547
|
+
def parse_raw(self) -> None: # noqa: PLR0912
|
|
548
|
+
for source, path_parts in self._get_context_source_path_parts(): # noqa: PLR1702
|
|
575
549
|
if self.validation:
|
|
576
550
|
warn(
|
|
577
|
-
|
|
578
|
-
|
|
551
|
+
"Deprecated: `--validation` option is deprecated. the option will be removed in a future "
|
|
552
|
+
"release. please use another tool to validate OpenAPI.\n",
|
|
553
|
+
stacklevel=2,
|
|
579
554
|
)
|
|
580
555
|
|
|
581
556
|
try:
|
|
582
|
-
from prance import BaseParser
|
|
557
|
+
from prance import BaseParser # noqa: PLC0415
|
|
583
558
|
|
|
584
559
|
BaseParser(
|
|
585
560
|
spec_string=source.text,
|
|
586
|
-
backend=
|
|
561
|
+
backend="openapi-spec-validator",
|
|
587
562
|
encoding=self.encoding,
|
|
588
563
|
)
|
|
589
564
|
except ImportError: # pragma: no cover
|
|
590
565
|
warn(
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
"'datamodel-code-generator[validation]'`.\n"
|
|
566
|
+
"Warning: Validation was skipped for OpenAPI. `prance` or `openapi-spec-validator` are not "
|
|
567
|
+
"installed.\n"
|
|
568
|
+
"To use --validation option after datamodel-code-generator 0.24.0, Please run `$pip install "
|
|
569
|
+
"'datamodel-code-generator[validation]'`.\n",
|
|
570
|
+
stacklevel=2,
|
|
595
571
|
)
|
|
596
572
|
|
|
597
|
-
specification:
|
|
573
|
+
specification: dict[str, Any] = load_yaml(source.text)
|
|
598
574
|
self.raw_obj = specification
|
|
599
|
-
schemas:
|
|
600
|
-
|
|
601
|
-
)
|
|
602
|
-
security: Optional[List[Dict[str, List[str]]]] = specification.get(
|
|
603
|
-
'security'
|
|
604
|
-
)
|
|
575
|
+
schemas: dict[Any, Any] = specification.get("components", {}).get("schemas", {})
|
|
576
|
+
security: list[dict[str, list[str]]] | None = specification.get("security")
|
|
605
577
|
if OpenAPIScope.Schemas in self.open_api_scopes:
|
|
606
578
|
for (
|
|
607
579
|
obj_name,
|
|
@@ -610,38 +582,37 @@ class OpenAPIParser(JsonSchemaParser):
|
|
|
610
582
|
self.parse_raw_obj(
|
|
611
583
|
obj_name,
|
|
612
584
|
raw_obj,
|
|
613
|
-
[*path_parts,
|
|
585
|
+
[*path_parts, "#/components", "schemas", obj_name],
|
|
614
586
|
)
|
|
615
587
|
if OpenAPIScope.Paths in self.open_api_scopes:
|
|
616
|
-
paths:
|
|
617
|
-
parameters:
|
|
618
|
-
self._get_ref_body(p[
|
|
619
|
-
for p in paths.get(
|
|
588
|
+
paths: dict[str, dict[str, Any]] = specification.get("paths", {})
|
|
589
|
+
parameters: list[dict[str, Any]] = [
|
|
590
|
+
self._get_ref_body(p["$ref"]) if "$ref" in p else p
|
|
591
|
+
for p in paths.get("parameters", [])
|
|
620
592
|
if isinstance(p, dict)
|
|
621
593
|
]
|
|
622
|
-
paths_path = [*path_parts,
|
|
623
|
-
for path_name,
|
|
594
|
+
paths_path = [*path_parts, "#/paths"]
|
|
595
|
+
for path_name, methods_ in paths.items():
|
|
624
596
|
# Resolve path items if applicable
|
|
625
|
-
if
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
paths_parameters.extend(methods['parameters'])
|
|
597
|
+
methods = self.get_ref_model(methods_["$ref"]) if "$ref" in methods_ else methods_
|
|
598
|
+
paths_parameters = parameters.copy()
|
|
599
|
+
if "parameters" in methods:
|
|
600
|
+
paths_parameters.extend(methods["parameters"])
|
|
630
601
|
relative_path_name = path_name[1:]
|
|
631
602
|
if relative_path_name:
|
|
632
603
|
path = [*paths_path, relative_path_name]
|
|
633
604
|
else: # pragma: no cover
|
|
634
|
-
path = get_special_path(
|
|
605
|
+
path = get_special_path("root", paths_path)
|
|
635
606
|
for operation_name, raw_operation in methods.items():
|
|
636
607
|
if operation_name not in OPERATION_NAMES:
|
|
637
608
|
continue
|
|
638
609
|
if paths_parameters:
|
|
639
|
-
if
|
|
640
|
-
raw_operation[
|
|
610
|
+
if "parameters" in raw_operation: # pragma: no cover
|
|
611
|
+
raw_operation["parameters"].extend(paths_parameters)
|
|
641
612
|
else:
|
|
642
|
-
raw_operation[
|
|
643
|
-
if security is not None and
|
|
644
|
-
raw_operation[
|
|
613
|
+
raw_operation["parameters"] = paths_parameters
|
|
614
|
+
if security is not None and "security" not in raw_operation:
|
|
615
|
+
raw_operation["security"] = security
|
|
645
616
|
self.parse_operation(
|
|
646
617
|
raw_operation,
|
|
647
618
|
[*path, operation_name],
|