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