datamodel-code-generator 0.27.1__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.1.dist-info → datamodel_code_generator-0.27.3.dist-info}/METADATA +12 -11
- datamodel_code_generator-0.27.3.dist-info/RECORD +59 -0
- datamodel_code_generator-0.27.1.dist-info/RECORD +0 -59
- {datamodel_code_generator-0.27.1.dist-info → datamodel_code_generator-0.27.3.dist-info}/WHEEL +0 -0
- {datamodel_code_generator-0.27.1.dist-info → datamodel_code_generator-0.27.3.dist-info}/entry_points.txt +0 -0
- {datamodel_code_generator-0.27.1.dist-info → datamodel_code_generator-0.27.3.dist-info}/licenses/LICENSE +0 -0
|
@@ -10,7 +10,6 @@ from typing import (
|
|
|
10
10
|
Any,
|
|
11
11
|
Callable,
|
|
12
12
|
ClassVar,
|
|
13
|
-
DefaultDict,
|
|
14
13
|
Dict,
|
|
15
14
|
Generator,
|
|
16
15
|
Iterable,
|
|
@@ -20,7 +19,6 @@ from typing import (
|
|
|
20
19
|
Optional,
|
|
21
20
|
Sequence,
|
|
22
21
|
Set,
|
|
23
|
-
Tuple,
|
|
24
22
|
Type,
|
|
25
23
|
Union,
|
|
26
24
|
)
|
|
@@ -74,88 +72,84 @@ if PYDANTIC_V2:
|
|
|
74
72
|
from datamodel_code_generator.format import DatetimeClassType
|
|
75
73
|
|
|
76
74
|
|
|
77
|
-
def get_model_by_path(
|
|
78
|
-
|
|
79
|
-
) -> Dict[Any, Any]:
|
|
80
|
-
model: Union[Dict[Any, Any], List[Any]]
|
|
75
|
+
def get_model_by_path(schema: dict[str, Any] | list[Any], keys: list[str] | list[int]) -> dict[Any, Any]:
|
|
76
|
+
model: dict[Any, Any] | list[Any]
|
|
81
77
|
if not keys:
|
|
82
78
|
model = schema
|
|
83
79
|
elif len(keys) == 1:
|
|
84
|
-
if isinstance(schema, dict)
|
|
85
|
-
model = schema.get(keys[0], {}) # type: ignore
|
|
86
|
-
else: # pragma: no cover
|
|
87
|
-
model = schema[int(keys[0])]
|
|
80
|
+
model = schema.get(str(keys[0]), {}) if isinstance(schema, dict) else schema[int(keys[0])]
|
|
88
81
|
elif isinstance(schema, dict):
|
|
89
|
-
model = get_model_by_path(schema[keys[0]], keys[1:])
|
|
82
|
+
model = get_model_by_path(schema[str(keys[0])], keys[1:])
|
|
90
83
|
else:
|
|
91
84
|
model = get_model_by_path(schema[int(keys[0])], keys[1:])
|
|
92
85
|
if isinstance(model, dict):
|
|
93
86
|
return model
|
|
87
|
+
msg = f"Does not support json pointer to array. schema={schema}, key={keys}"
|
|
94
88
|
raise NotImplementedError( # pragma: no cover
|
|
95
|
-
|
|
89
|
+
msg
|
|
96
90
|
)
|
|
97
91
|
|
|
98
92
|
|
|
99
|
-
json_schema_data_formats:
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
93
|
+
json_schema_data_formats: dict[str, dict[str, Types]] = {
|
|
94
|
+
"integer": {
|
|
95
|
+
"int32": Types.int32,
|
|
96
|
+
"int64": Types.int64,
|
|
97
|
+
"default": Types.integer,
|
|
98
|
+
"date-time": Types.date_time,
|
|
99
|
+
"unix-time": Types.int64,
|
|
106
100
|
},
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
101
|
+
"number": {
|
|
102
|
+
"float": Types.float,
|
|
103
|
+
"double": Types.double,
|
|
104
|
+
"decimal": Types.decimal,
|
|
105
|
+
"date-time": Types.date_time,
|
|
106
|
+
"time": Types.time,
|
|
107
|
+
"default": Types.number,
|
|
114
108
|
},
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
109
|
+
"string": {
|
|
110
|
+
"default": Types.string,
|
|
111
|
+
"byte": Types.byte, # base64 encoded string
|
|
112
|
+
"binary": Types.binary,
|
|
113
|
+
"date": Types.date,
|
|
114
|
+
"date-time": Types.date_time,
|
|
115
|
+
"duration": Types.timedelta,
|
|
116
|
+
"time": Types.time,
|
|
117
|
+
"password": Types.password,
|
|
118
|
+
"path": Types.path,
|
|
119
|
+
"email": Types.email,
|
|
120
|
+
"idn-email": Types.email,
|
|
121
|
+
"uuid": Types.uuid,
|
|
122
|
+
"uuid1": Types.uuid1,
|
|
123
|
+
"uuid2": Types.uuid2,
|
|
124
|
+
"uuid3": Types.uuid3,
|
|
125
|
+
"uuid4": Types.uuid4,
|
|
126
|
+
"uuid5": Types.uuid5,
|
|
127
|
+
"uri": Types.uri,
|
|
128
|
+
"uri-reference": Types.string,
|
|
129
|
+
"hostname": Types.hostname,
|
|
130
|
+
"ipv4": Types.ipv4,
|
|
131
|
+
"ipv4-network": Types.ipv4_network,
|
|
132
|
+
"ipv6": Types.ipv6,
|
|
133
|
+
"ipv6-network": Types.ipv6_network,
|
|
134
|
+
"decimal": Types.decimal,
|
|
135
|
+
"integer": Types.integer,
|
|
142
136
|
},
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
137
|
+
"boolean": {"default": Types.boolean},
|
|
138
|
+
"object": {"default": Types.object},
|
|
139
|
+
"null": {"default": Types.null},
|
|
140
|
+
"array": {"default": Types.array},
|
|
147
141
|
}
|
|
148
142
|
|
|
149
143
|
|
|
150
144
|
class JSONReference(_enum.Enum):
|
|
151
|
-
LOCAL =
|
|
152
|
-
REMOTE =
|
|
153
|
-
URL =
|
|
145
|
+
LOCAL = "LOCAL"
|
|
146
|
+
REMOTE = "REMOTE"
|
|
147
|
+
URL = "URL"
|
|
154
148
|
|
|
155
149
|
|
|
156
150
|
class Discriminator(BaseModel):
|
|
157
|
-
propertyName: str
|
|
158
|
-
mapping: Optional[Dict[str, str]] = None
|
|
151
|
+
propertyName: str # noqa: N815
|
|
152
|
+
mapping: Optional[Dict[str, str]] = None # noqa: UP006, UP045
|
|
159
153
|
|
|
160
154
|
|
|
161
155
|
class JsonSchemaObject(BaseModel):
|
|
@@ -163,102 +157,102 @@ class JsonSchemaObject(BaseModel):
|
|
|
163
157
|
if PYDANTIC_V2:
|
|
164
158
|
|
|
165
159
|
@classmethod
|
|
166
|
-
def get_fields(cls) ->
|
|
160
|
+
def get_fields(cls) -> dict[str, Any]:
|
|
167
161
|
return cls.model_fields
|
|
168
162
|
|
|
169
163
|
else:
|
|
170
164
|
|
|
171
165
|
@classmethod
|
|
172
|
-
def get_fields(cls) ->
|
|
166
|
+
def get_fields(cls) -> dict[str, Any]:
|
|
173
167
|
return cls.__fields__
|
|
174
168
|
|
|
175
169
|
@classmethod
|
|
176
170
|
def model_rebuild(cls) -> None:
|
|
177
171
|
cls.update_forward_refs()
|
|
178
172
|
|
|
179
|
-
__constraint_fields__: Set[str] = {
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
173
|
+
__constraint_fields__: Set[str] = { # noqa: RUF012, UP006
|
|
174
|
+
"exclusiveMinimum",
|
|
175
|
+
"minimum",
|
|
176
|
+
"exclusiveMaximum",
|
|
177
|
+
"maximum",
|
|
178
|
+
"multipleOf",
|
|
179
|
+
"minItems",
|
|
180
|
+
"maxItems",
|
|
181
|
+
"minLength",
|
|
182
|
+
"maxLength",
|
|
183
|
+
"pattern",
|
|
184
|
+
"uniqueItems",
|
|
191
185
|
}
|
|
192
|
-
__extra_key__: str = SPECIAL_PATH_FORMAT.format(
|
|
186
|
+
__extra_key__: str = SPECIAL_PATH_FORMAT.format("extras")
|
|
193
187
|
|
|
194
|
-
@model_validator(mode=
|
|
195
|
-
def validate_exclusive_maximum_and_exclusive_minimum(cls, values: Any) -> Any:
|
|
188
|
+
@model_validator(mode="before")
|
|
189
|
+
def validate_exclusive_maximum_and_exclusive_minimum(cls, values: Any) -> Any: # noqa: N805
|
|
196
190
|
if not isinstance(values, dict):
|
|
197
191
|
return values
|
|
198
|
-
exclusive_maximum:
|
|
199
|
-
exclusive_minimum:
|
|
192
|
+
exclusive_maximum: float | bool | None = values.get("exclusiveMaximum")
|
|
193
|
+
exclusive_minimum: float | bool | None = values.get("exclusiveMinimum")
|
|
200
194
|
|
|
201
195
|
if exclusive_maximum is True:
|
|
202
|
-
values[
|
|
203
|
-
del values[
|
|
196
|
+
values["exclusiveMaximum"] = values["maximum"]
|
|
197
|
+
del values["maximum"]
|
|
204
198
|
elif exclusive_maximum is False:
|
|
205
|
-
del values[
|
|
199
|
+
del values["exclusiveMaximum"]
|
|
206
200
|
if exclusive_minimum is True:
|
|
207
|
-
values[
|
|
208
|
-
del values[
|
|
201
|
+
values["exclusiveMinimum"] = values["minimum"]
|
|
202
|
+
del values["minimum"]
|
|
209
203
|
elif exclusive_minimum is False:
|
|
210
|
-
del values[
|
|
204
|
+
del values["exclusiveMinimum"]
|
|
211
205
|
return values
|
|
212
206
|
|
|
213
|
-
@field_validator(
|
|
214
|
-
def validate_ref(cls, value: Any) -> Any:
|
|
215
|
-
if isinstance(value, str) and
|
|
216
|
-
if value.endswith(
|
|
207
|
+
@field_validator("ref")
|
|
208
|
+
def validate_ref(cls, value: Any) -> Any: # noqa: N805
|
|
209
|
+
if isinstance(value, str) and "#" in value:
|
|
210
|
+
if value.endswith("#/"):
|
|
217
211
|
return value[:-1]
|
|
218
|
-
|
|
212
|
+
if "#/" in value or value[0] == "#" or value[-1] == "#":
|
|
219
213
|
return value
|
|
220
|
-
return value.replace(
|
|
214
|
+
return value.replace("#", "#/")
|
|
221
215
|
return value
|
|
222
216
|
|
|
223
|
-
items: Union[List[JsonSchemaObject], JsonSchemaObject, bool
|
|
224
|
-
uniqueItems: Optional[bool] = None
|
|
225
|
-
type: Union[str, List[str]
|
|
226
|
-
format: Optional[str] = None
|
|
227
|
-
pattern: Optional[str] = None
|
|
228
|
-
minLength: Optional[int] = None
|
|
229
|
-
maxLength: Optional[int] = None
|
|
230
|
-
minimum: Optional[UnionIntFloat] = None
|
|
231
|
-
maximum: Optional[UnionIntFloat] = None
|
|
232
|
-
minItems: Optional[int] = None
|
|
233
|
-
maxItems: Optional[int] = None
|
|
234
|
-
multipleOf: Optional[float] = None
|
|
235
|
-
exclusiveMaximum: Union[float, bool
|
|
236
|
-
exclusiveMinimum: Union[float, bool
|
|
237
|
-
additionalProperties: Union[JsonSchemaObject, bool
|
|
238
|
-
patternProperties: Optional[Dict[str, JsonSchemaObject]] = None
|
|
239
|
-
oneOf: List[JsonSchemaObject] = []
|
|
240
|
-
anyOf: List[JsonSchemaObject] = []
|
|
241
|
-
allOf: List[JsonSchemaObject] = []
|
|
242
|
-
enum: List[Any] = []
|
|
243
|
-
writeOnly: Optional[bool] = None
|
|
244
|
-
readOnly: Optional[bool] = None
|
|
245
|
-
properties: Optional[Dict[str, Union[JsonSchemaObject, bool]]] = None
|
|
246
|
-
required: List[str] = []
|
|
247
|
-
ref: Optional[str] = Field(default=None, alias=
|
|
248
|
-
nullable: Optional[bool] = False
|
|
249
|
-
x_enum_varnames: List[str] = Field(default=[], alias=
|
|
250
|
-
description: Optional[str] = None
|
|
251
|
-
title: Optional[str] = None
|
|
217
|
+
items: Optional[Union[List[JsonSchemaObject], JsonSchemaObject, bool]] = None # noqa: UP006, UP007, UP045
|
|
218
|
+
uniqueItems: Optional[bool] = None # noqa: N815, UP045
|
|
219
|
+
type: Optional[Union[str, List[str]]] = None # noqa: UP006, UP007, UP045
|
|
220
|
+
format: Optional[str] = None # noqa: UP045
|
|
221
|
+
pattern: Optional[str] = None # noqa: UP045
|
|
222
|
+
minLength: Optional[int] = None # noqa: N815,UP045
|
|
223
|
+
maxLength: Optional[int] = None # noqa: N815,UP045
|
|
224
|
+
minimum: Optional[UnionIntFloat] = None # noqa: UP045
|
|
225
|
+
maximum: Optional[UnionIntFloat] = None # noqa: UP045
|
|
226
|
+
minItems: Optional[int] = None # noqa: N815,UP045
|
|
227
|
+
maxItems: Optional[int] = None # noqa: N815,UP045
|
|
228
|
+
multipleOf: Optional[float] = None # noqa: N815, UP045
|
|
229
|
+
exclusiveMaximum: Optional[Union[float, bool]] = None # noqa: N815, UP007, UP045
|
|
230
|
+
exclusiveMinimum: Optional[Union[float, bool]] = None # noqa: N815, UP007, UP045
|
|
231
|
+
additionalProperties: Optional[Union[JsonSchemaObject, bool]] = None # noqa: N815, UP007, UP045
|
|
232
|
+
patternProperties: Optional[Dict[str, JsonSchemaObject]] = None # noqa: N815, UP006, UP045
|
|
233
|
+
oneOf: List[JsonSchemaObject] = [] # noqa: N815, RUF012, UP006
|
|
234
|
+
anyOf: List[JsonSchemaObject] = [] # noqa: N815, RUF012, UP006
|
|
235
|
+
allOf: List[JsonSchemaObject] = [] # noqa: N815, RUF012, UP006
|
|
236
|
+
enum: List[Any] = [] # noqa: RUF012, UP006
|
|
237
|
+
writeOnly: Optional[bool] = None # noqa: N815, UP045
|
|
238
|
+
readOnly: Optional[bool] = None # noqa: N815, UP045
|
|
239
|
+
properties: Optional[Dict[str, Union[JsonSchemaObject, bool]]] = None # noqa: UP006, UP007, UP045
|
|
240
|
+
required: List[str] = [] # noqa: RUF012, UP006
|
|
241
|
+
ref: Optional[str] = Field(default=None, alias="$ref") # noqa: UP045
|
|
242
|
+
nullable: Optional[bool] = False # noqa: UP045
|
|
243
|
+
x_enum_varnames: List[str] = Field(default=[], alias="x-enum-varnames") # noqa: UP006
|
|
244
|
+
description: Optional[str] = None # noqa: UP045
|
|
245
|
+
title: Optional[str] = None # noqa: UP045
|
|
252
246
|
example: Any = None
|
|
253
247
|
examples: Any = None
|
|
254
248
|
default: Any = None
|
|
255
|
-
id: Optional[str] = Field(default=None, alias=
|
|
256
|
-
custom_type_path: Optional[str] = Field(default=None, alias=
|
|
257
|
-
custom_base_path: Optional[str] = Field(default=None, alias=
|
|
258
|
-
extras: Dict[str, Any] = Field(alias=__extra_key__, default_factory=dict)
|
|
259
|
-
discriminator: Union[Discriminator, str
|
|
249
|
+
id: Optional[str] = Field(default=None, alias="$id") # noqa: UP045
|
|
250
|
+
custom_type_path: Optional[str] = Field(default=None, alias="customTypePath") # noqa: UP045
|
|
251
|
+
custom_base_path: Optional[str] = Field(default=None, alias="customBasePath") # noqa: UP045
|
|
252
|
+
extras: Dict[str, Any] = Field(alias=__extra_key__, default_factory=dict) # noqa: UP006
|
|
253
|
+
discriminator: Optional[Union[Discriminator, str]] = None # noqa: UP007, UP045
|
|
260
254
|
if PYDANTIC_V2:
|
|
261
|
-
model_config = ConfigDict( # pyright: ignore
|
|
255
|
+
model_config = ConfigDict( # pyright: ignore[reportPossiblyUnboundVariable]
|
|
262
256
|
arbitrary_types_allowed=True,
|
|
263
257
|
ignored_types=(cached_property,),
|
|
264
258
|
)
|
|
@@ -274,178 +268,171 @@ class JsonSchemaObject(BaseModel):
|
|
|
274
268
|
def __init__(self, **data: Any) -> None:
|
|
275
269
|
super().__init__(**data)
|
|
276
270
|
self.extras = {k: v for k, v in data.items() if k not in EXCLUDE_FIELD_KEYS}
|
|
277
|
-
if
|
|
278
|
-
self.extras[
|
|
271
|
+
if "const" in data.get(self.__extra_key__, {}):
|
|
272
|
+
self.extras["const"] = data[self.__extra_key__]["const"]
|
|
279
273
|
|
|
280
274
|
@cached_property
|
|
281
275
|
def is_object(self) -> bool:
|
|
282
|
-
return (
|
|
283
|
-
self.
|
|
284
|
-
or self.type == 'object'
|
|
285
|
-
and not self.allOf
|
|
286
|
-
and not self.oneOf
|
|
287
|
-
and not self.anyOf
|
|
288
|
-
and not self.ref
|
|
276
|
+
return self.properties is not None or (
|
|
277
|
+
self.type == "object" and not self.allOf and not self.oneOf and not self.anyOf and not self.ref
|
|
289
278
|
)
|
|
290
279
|
|
|
291
280
|
@cached_property
|
|
292
281
|
def is_array(self) -> bool:
|
|
293
|
-
return self.items is not None or self.type ==
|
|
282
|
+
return self.items is not None or self.type == "array"
|
|
294
283
|
|
|
295
284
|
@cached_property
|
|
296
285
|
def ref_object_name(self) -> str: # pragma: no cover
|
|
297
|
-
return self.ref.rsplit(
|
|
286
|
+
return (self.ref or "").rsplit("/", 1)[-1]
|
|
298
287
|
|
|
299
|
-
@field_validator(
|
|
300
|
-
def validate_items(cls, values: Any) -> Any:
|
|
288
|
+
@field_validator("items", mode="before")
|
|
289
|
+
def validate_items(cls, values: Any) -> Any: # noqa: N805
|
|
301
290
|
# this condition expects empty dict
|
|
302
291
|
return values or None
|
|
303
292
|
|
|
304
293
|
@cached_property
|
|
305
294
|
def has_default(self) -> bool:
|
|
306
|
-
return
|
|
295
|
+
return "default" in self.__fields_set__ or "default_factory" in self.extras
|
|
307
296
|
|
|
308
297
|
@cached_property
|
|
309
298
|
def has_constraint(self) -> bool:
|
|
310
299
|
return bool(self.__constraint_fields__ & self.__fields_set__)
|
|
311
300
|
|
|
312
301
|
@cached_property
|
|
313
|
-
def ref_type(self) ->
|
|
302
|
+
def ref_type(self) -> JSONReference | None:
|
|
314
303
|
if self.ref:
|
|
315
304
|
return get_ref_type(self.ref)
|
|
316
305
|
return None # pragma: no cover
|
|
317
306
|
|
|
318
307
|
@cached_property
|
|
319
308
|
def type_has_null(self) -> bool:
|
|
320
|
-
return isinstance(self.type, list) and
|
|
309
|
+
return isinstance(self.type, list) and "null" in self.type
|
|
321
310
|
|
|
322
311
|
|
|
323
312
|
@lru_cache
|
|
324
313
|
def get_ref_type(ref: str) -> JSONReference:
|
|
325
|
-
if ref[0] ==
|
|
314
|
+
if ref[0] == "#":
|
|
326
315
|
return JSONReference.LOCAL
|
|
327
|
-
|
|
316
|
+
if is_url(ref):
|
|
328
317
|
return JSONReference.URL
|
|
329
318
|
return JSONReference.REMOTE
|
|
330
319
|
|
|
331
320
|
|
|
332
|
-
def _get_type(type_: str, format__:
|
|
321
|
+
def _get_type(type_: str, format__: str | None = None) -> Types:
|
|
333
322
|
if type_ not in json_schema_data_formats:
|
|
334
323
|
return Types.any
|
|
335
|
-
data_formats:
|
|
336
|
-
'default' if format__ is None else format__
|
|
337
|
-
)
|
|
324
|
+
data_formats: Types | None = json_schema_data_formats[type_].get("default" if format__ is None else format__)
|
|
338
325
|
if data_formats is not None:
|
|
339
326
|
return data_formats
|
|
340
327
|
|
|
341
|
-
warn(f
|
|
342
|
-
return json_schema_data_formats[type_][
|
|
328
|
+
warn(f"format of {format__!r} not understood for {type_!r} - using default", stacklevel=2)
|
|
329
|
+
return json_schema_data_formats[type_]["default"]
|
|
343
330
|
|
|
344
331
|
|
|
345
332
|
JsonSchemaObject.model_rebuild()
|
|
346
333
|
|
|
347
|
-
DEFAULT_FIELD_KEYS:
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
334
|
+
DEFAULT_FIELD_KEYS: set[str] = {
|
|
335
|
+
"example",
|
|
336
|
+
"examples",
|
|
337
|
+
"description",
|
|
338
|
+
"discriminator",
|
|
339
|
+
"title",
|
|
340
|
+
"const",
|
|
341
|
+
"default_factory",
|
|
355
342
|
}
|
|
356
343
|
|
|
357
|
-
EXCLUDE_FIELD_KEYS_IN_JSON_SCHEMA:
|
|
358
|
-
|
|
359
|
-
|
|
344
|
+
EXCLUDE_FIELD_KEYS_IN_JSON_SCHEMA: set[str] = {
|
|
345
|
+
"readOnly",
|
|
346
|
+
"writeOnly",
|
|
360
347
|
}
|
|
361
348
|
|
|
362
349
|
EXCLUDE_FIELD_KEYS = (
|
|
363
|
-
set(JsonSchemaObject.get_fields()) # pyright: ignore
|
|
350
|
+
set(JsonSchemaObject.get_fields()) # pyright: ignore[reportAttributeAccessIssue]
|
|
364
351
|
- DEFAULT_FIELD_KEYS
|
|
365
352
|
- EXCLUDE_FIELD_KEYS_IN_JSON_SCHEMA
|
|
366
353
|
) | {
|
|
367
|
-
|
|
368
|
-
|
|
354
|
+
"$id",
|
|
355
|
+
"$ref",
|
|
369
356
|
JsonSchemaObject.__extra_key__,
|
|
370
357
|
}
|
|
371
358
|
|
|
372
359
|
|
|
373
|
-
@snooper_to_methods(
|
|
360
|
+
@snooper_to_methods() # noqa: PLR0904
|
|
374
361
|
class JsonSchemaParser(Parser):
|
|
375
|
-
SCHEMA_PATHS: ClassVar[List[str]] = [
|
|
376
|
-
SCHEMA_OBJECT_TYPE: ClassVar[Type[JsonSchemaObject]] = JsonSchemaObject
|
|
362
|
+
SCHEMA_PATHS: ClassVar[List[str]] = ["#/definitions", "#/$defs"] # noqa: UP006
|
|
363
|
+
SCHEMA_OBJECT_TYPE: ClassVar[Type[JsonSchemaObject]] = JsonSchemaObject # noqa: UP006
|
|
377
364
|
|
|
378
|
-
def __init__(
|
|
365
|
+
def __init__( # noqa: PLR0913
|
|
379
366
|
self,
|
|
380
|
-
source:
|
|
367
|
+
source: str | Path | list[Path] | ParseResult,
|
|
381
368
|
*,
|
|
382
|
-
data_model_type:
|
|
383
|
-
data_model_root_type:
|
|
384
|
-
data_type_manager_type:
|
|
385
|
-
data_model_field_type:
|
|
386
|
-
base_class:
|
|
387
|
-
additional_imports:
|
|
388
|
-
custom_template_dir:
|
|
389
|
-
extra_template_data:
|
|
369
|
+
data_model_type: type[DataModel] = pydantic_model.BaseModel,
|
|
370
|
+
data_model_root_type: type[DataModel] = pydantic_model.CustomRootType,
|
|
371
|
+
data_type_manager_type: type[DataTypeManager] = pydantic_model.DataTypeManager,
|
|
372
|
+
data_model_field_type: type[DataModelFieldBase] = pydantic_model.DataModelField,
|
|
373
|
+
base_class: str | None = None,
|
|
374
|
+
additional_imports: list[str] | None = None,
|
|
375
|
+
custom_template_dir: Path | None = None,
|
|
376
|
+
extra_template_data: defaultdict[str, dict[str, Any]] | None = None,
|
|
390
377
|
target_python_version: PythonVersion = PythonVersion.PY_38,
|
|
391
|
-
dump_resolve_reference_action:
|
|
378
|
+
dump_resolve_reference_action: Callable[[Iterable[str]], str] | None = None,
|
|
392
379
|
validation: bool = False,
|
|
393
380
|
field_constraints: bool = False,
|
|
394
381
|
snake_case_field: bool = False,
|
|
395
382
|
strip_default_none: bool = False,
|
|
396
|
-
aliases:
|
|
383
|
+
aliases: Mapping[str, str] | None = None,
|
|
397
384
|
allow_population_by_field_name: bool = False,
|
|
398
385
|
apply_default_values_for_required_fields: bool = False,
|
|
399
386
|
allow_extra_fields: bool = False,
|
|
400
387
|
force_optional_for_required_fields: bool = False,
|
|
401
|
-
class_name:
|
|
388
|
+
class_name: str | None = None,
|
|
402
389
|
use_standard_collections: bool = False,
|
|
403
|
-
base_path:
|
|
390
|
+
base_path: Path | None = None,
|
|
404
391
|
use_schema_description: bool = False,
|
|
405
392
|
use_field_description: bool = False,
|
|
406
393
|
use_default_kwarg: bool = False,
|
|
407
394
|
reuse_model: bool = False,
|
|
408
|
-
encoding: str =
|
|
409
|
-
enum_field_as_literal:
|
|
395
|
+
encoding: str = "utf-8",
|
|
396
|
+
enum_field_as_literal: LiteralType | None = None,
|
|
410
397
|
use_one_literal_as_default: bool = False,
|
|
411
398
|
set_default_enum_member: bool = False,
|
|
412
399
|
use_subclass_enum: bool = False,
|
|
413
400
|
strict_nullable: bool = False,
|
|
414
401
|
use_generic_container_types: bool = False,
|
|
415
402
|
enable_faux_immutability: bool = False,
|
|
416
|
-
remote_text_cache:
|
|
403
|
+
remote_text_cache: DefaultPutDict[str, str] | None = None,
|
|
417
404
|
disable_appending_item_suffix: bool = False,
|
|
418
|
-
strict_types:
|
|
419
|
-
empty_enum_field_name:
|
|
420
|
-
custom_class_name_generator:
|
|
421
|
-
field_extra_keys:
|
|
405
|
+
strict_types: Sequence[StrictTypes] | None = None,
|
|
406
|
+
empty_enum_field_name: str | None = None,
|
|
407
|
+
custom_class_name_generator: Callable[[str], str] | None = None,
|
|
408
|
+
field_extra_keys: set[str] | None = None,
|
|
422
409
|
field_include_all_keys: bool = False,
|
|
423
|
-
field_extra_keys_without_x_prefix:
|
|
424
|
-
wrap_string_literal:
|
|
410
|
+
field_extra_keys_without_x_prefix: set[str] | None = None,
|
|
411
|
+
wrap_string_literal: bool | None = None,
|
|
425
412
|
use_title_as_name: bool = False,
|
|
426
413
|
use_operation_id_as_name: bool = False,
|
|
427
414
|
use_unique_items_as_set: bool = False,
|
|
428
|
-
http_headers:
|
|
415
|
+
http_headers: Sequence[tuple[str, str]] | None = None,
|
|
429
416
|
http_ignore_tls: bool = False,
|
|
430
417
|
use_annotated: bool = False,
|
|
431
418
|
use_non_positive_negative_number_constrained_types: bool = False,
|
|
432
|
-
original_field_name_delimiter:
|
|
419
|
+
original_field_name_delimiter: str | None = None,
|
|
433
420
|
use_double_quotes: bool = False,
|
|
434
421
|
use_union_operator: bool = False,
|
|
435
422
|
allow_responses_without_content: bool = False,
|
|
436
423
|
collapse_root_models: bool = False,
|
|
437
|
-
special_field_name_prefix:
|
|
424
|
+
special_field_name_prefix: str | None = None,
|
|
438
425
|
remove_special_field_name_prefix: bool = False,
|
|
439
426
|
capitalise_enum_members: bool = False,
|
|
440
427
|
keep_model_order: bool = False,
|
|
441
|
-
known_third_party:
|
|
442
|
-
custom_formatters:
|
|
443
|
-
custom_formatters_kwargs:
|
|
428
|
+
known_third_party: list[str] | None = None,
|
|
429
|
+
custom_formatters: list[str] | None = None,
|
|
430
|
+
custom_formatters_kwargs: dict[str, Any] | None = None,
|
|
444
431
|
use_pendulum: bool = False,
|
|
445
|
-
http_query_parameters:
|
|
432
|
+
http_query_parameters: Sequence[tuple[str, str]] | None = None,
|
|
446
433
|
treat_dots_as_module: bool = False,
|
|
447
434
|
use_exact_imports: bool = False,
|
|
448
|
-
default_field_extras:
|
|
435
|
+
default_field_extras: dict[str, Any] | None = None,
|
|
449
436
|
target_datetime_class: DatetimeClassType = DatetimeClassType.Datetime,
|
|
450
437
|
keyword_only: bool = False,
|
|
451
438
|
no_alias: bool = False,
|
|
@@ -524,12 +511,12 @@ class JsonSchemaParser(Parser):
|
|
|
524
511
|
no_alias=no_alias,
|
|
525
512
|
)
|
|
526
513
|
|
|
527
|
-
self.remote_object_cache: DefaultPutDict[str,
|
|
528
|
-
self.raw_obj:
|
|
529
|
-
self._root_id: Optional[str] = None
|
|
530
|
-
self._root_id_base_path: Optional[str] = None
|
|
531
|
-
self.reserved_refs:
|
|
532
|
-
self.field_keys:
|
|
514
|
+
self.remote_object_cache: DefaultPutDict[str, dict[str, Any]] = DefaultPutDict()
|
|
515
|
+
self.raw_obj: dict[Any, Any] = {}
|
|
516
|
+
self._root_id: Optional[str] = None # noqa: UP045
|
|
517
|
+
self._root_id_base_path: Optional[str] = None # noqa: UP045
|
|
518
|
+
self.reserved_refs: defaultdict[tuple[str, ...], set[str]] = defaultdict(set)
|
|
519
|
+
self.field_keys: set[str] = {
|
|
533
520
|
*DEFAULT_FIELD_KEYS,
|
|
534
521
|
*self.field_extra_keys,
|
|
535
522
|
*self.field_extra_keys_without_x_prefix,
|
|
@@ -543,19 +530,15 @@ class JsonSchemaParser(Parser):
|
|
|
543
530
|
else:
|
|
544
531
|
self.get_field_extra_key = lambda key: key
|
|
545
532
|
|
|
546
|
-
def get_field_extras(self, obj: JsonSchemaObject) ->
|
|
533
|
+
def get_field_extras(self, obj: JsonSchemaObject) -> dict[str, Any]:
|
|
547
534
|
if self.field_include_all_keys:
|
|
548
535
|
extras = {
|
|
549
|
-
self.get_field_extra_key(
|
|
550
|
-
k.lstrip('x-') if k in self.field_extra_keys_without_x_prefix else k
|
|
551
|
-
): v
|
|
536
|
+
self.get_field_extra_key(k.lstrip("x-") if k in self.field_extra_keys_without_x_prefix else k): v
|
|
552
537
|
for k, v in obj.extras.items()
|
|
553
538
|
}
|
|
554
539
|
else:
|
|
555
540
|
extras = {
|
|
556
|
-
self.get_field_extra_key(
|
|
557
|
-
k.lstrip('x-') if k in self.field_extra_keys_without_x_prefix else k
|
|
558
|
-
): v
|
|
541
|
+
self.get_field_extra_key(k.lstrip("x-") if k in self.field_extra_keys_without_x_prefix else k): v
|
|
559
542
|
for k, v in obj.extras.items()
|
|
560
543
|
if k in self.field_keys
|
|
561
544
|
}
|
|
@@ -564,15 +547,15 @@ class JsonSchemaParser(Parser):
|
|
|
564
547
|
return extras
|
|
565
548
|
|
|
566
549
|
@cached_property
|
|
567
|
-
def schema_paths(self) ->
|
|
568
|
-
return [(s, s.lstrip(
|
|
550
|
+
def schema_paths(self) -> list[tuple[str, list[str]]]:
|
|
551
|
+
return [(s, s.lstrip("#/").split("/")) for s in self.SCHEMA_PATHS]
|
|
569
552
|
|
|
570
553
|
@property
|
|
571
|
-
def root_id(self) ->
|
|
554
|
+
def root_id(self) -> str | None:
|
|
572
555
|
return self.model_resolver.root_id
|
|
573
556
|
|
|
574
557
|
@root_id.setter
|
|
575
|
-
def root_id(self, value:
|
|
558
|
+
def root_id(self, value: str | None) -> None:
|
|
576
559
|
self.model_resolver.set_root_id(value)
|
|
577
560
|
|
|
578
561
|
def should_parse_enum_as_literal(self, obj: JsonSchemaObject) -> bool:
|
|
@@ -582,26 +565,18 @@ class JsonSchemaParser(Parser):
|
|
|
582
565
|
|
|
583
566
|
def is_constraints_field(self, obj: JsonSchemaObject) -> bool:
|
|
584
567
|
return obj.is_array or (
|
|
585
|
-
self.field_constraints
|
|
586
|
-
and not (
|
|
587
|
-
obj.ref
|
|
588
|
-
or obj.anyOf
|
|
589
|
-
or obj.oneOf
|
|
590
|
-
or obj.allOf
|
|
591
|
-
or obj.is_object
|
|
592
|
-
or obj.enum
|
|
593
|
-
)
|
|
568
|
+
self.field_constraints and not (obj.ref or obj.anyOf or obj.oneOf or obj.allOf or obj.is_object or obj.enum)
|
|
594
569
|
)
|
|
595
570
|
|
|
596
|
-
def get_object_field(
|
|
571
|
+
def get_object_field( # noqa: PLR0913
|
|
597
572
|
self,
|
|
598
573
|
*,
|
|
599
|
-
field_name:
|
|
574
|
+
field_name: str | None,
|
|
600
575
|
field: JsonSchemaObject,
|
|
601
576
|
required: bool,
|
|
602
577
|
field_type: DataType,
|
|
603
|
-
alias:
|
|
604
|
-
original_field_name:
|
|
578
|
+
alias: str | None,
|
|
579
|
+
original_field_name: str | None,
|
|
605
580
|
) -> DataModelFieldBase:
|
|
606
581
|
return self.data_model_field_type(
|
|
607
582
|
name=field_name,
|
|
@@ -610,9 +585,7 @@ class JsonSchemaParser(Parser):
|
|
|
610
585
|
required=required,
|
|
611
586
|
alias=alias,
|
|
612
587
|
constraints=field.dict() if self.is_constraints_field(field) else None,
|
|
613
|
-
nullable=field.nullable
|
|
614
|
-
if self.strict_nullable and (field.has_default or required)
|
|
615
|
-
else None,
|
|
588
|
+
nullable=field.nullable if self.strict_nullable and (field.has_default or required) else None,
|
|
616
589
|
strip_default_none=self.strip_default_none,
|
|
617
590
|
extras=self.get_field_extras(field),
|
|
618
591
|
use_annotated=self.use_annotated,
|
|
@@ -625,10 +598,8 @@ class JsonSchemaParser(Parser):
|
|
|
625
598
|
|
|
626
599
|
def get_data_type(self, obj: JsonSchemaObject) -> DataType:
|
|
627
600
|
if obj.type is None:
|
|
628
|
-
if
|
|
629
|
-
return self.data_type_manager.get_data_type_from_value(
|
|
630
|
-
obj.extras['const']
|
|
631
|
-
)
|
|
601
|
+
if "const" in obj.extras:
|
|
602
|
+
return self.data_type_manager.get_data_type_from_value(obj.extras["const"])
|
|
632
603
|
return self.data_type_manager.get_data_type(
|
|
633
604
|
Types.any,
|
|
634
605
|
)
|
|
@@ -641,14 +612,10 @@ class JsonSchemaParser(Parser):
|
|
|
641
612
|
|
|
642
613
|
if isinstance(obj.type, list):
|
|
643
614
|
return self.data_type(
|
|
644
|
-
data_types=[
|
|
645
|
-
|
|
646
|
-
for t in obj.type
|
|
647
|
-
if t != 'null'
|
|
648
|
-
],
|
|
649
|
-
is_optional='null' in obj.type,
|
|
615
|
+
data_types=[_get_data_type(t, obj.format or "default") for t in obj.type if t != "null"],
|
|
616
|
+
is_optional="null" in obj.type,
|
|
650
617
|
)
|
|
651
|
-
return _get_data_type(obj.type, obj.format or
|
|
618
|
+
return _get_data_type(obj.type, obj.format or "default")
|
|
652
619
|
|
|
653
620
|
def get_ref_data_type(self, ref: str) -> DataType:
|
|
654
621
|
reference = self.model_resolver.add_ref(ref)
|
|
@@ -656,25 +623,21 @@ class JsonSchemaParser(Parser):
|
|
|
656
623
|
|
|
657
624
|
def set_additional_properties(self, name: str, obj: JsonSchemaObject) -> None:
|
|
658
625
|
if isinstance(obj.additionalProperties, bool):
|
|
659
|
-
self.extra_template_data[name][
|
|
660
|
-
obj.additionalProperties
|
|
661
|
-
)
|
|
626
|
+
self.extra_template_data[name]["additionalProperties"] = obj.additionalProperties
|
|
662
627
|
|
|
663
628
|
def set_title(self, name: str, obj: JsonSchemaObject) -> None:
|
|
664
629
|
if obj.title:
|
|
665
|
-
self.extra_template_data[name][
|
|
630
|
+
self.extra_template_data[name]["title"] = obj.title
|
|
666
631
|
|
|
667
|
-
def _deep_merge(
|
|
668
|
-
self, dict1: Dict[Any, Any], dict2: Dict[Any, Any]
|
|
669
|
-
) -> Dict[Any, Any]:
|
|
632
|
+
def _deep_merge(self, dict1: dict[Any, Any], dict2: dict[Any, Any]) -> dict[Any, Any]:
|
|
670
633
|
result = dict1.copy()
|
|
671
634
|
for key, value in dict2.items():
|
|
672
635
|
if key in result:
|
|
673
636
|
if isinstance(result[key], dict) and isinstance(value, dict):
|
|
674
637
|
result[key] = self._deep_merge(result[key], value)
|
|
675
638
|
continue
|
|
676
|
-
|
|
677
|
-
result[key]
|
|
639
|
+
if isinstance(result[key], list) and isinstance(value, list):
|
|
640
|
+
result[key] += value
|
|
678
641
|
continue
|
|
679
642
|
result[key] = value
|
|
680
643
|
return result
|
|
@@ -683,34 +646,17 @@ class JsonSchemaParser(Parser):
|
|
|
683
646
|
self,
|
|
684
647
|
name: str,
|
|
685
648
|
obj: JsonSchemaObject,
|
|
686
|
-
path:
|
|
649
|
+
path: list[str],
|
|
687
650
|
target_attribute_name: str,
|
|
688
|
-
) ->
|
|
689
|
-
base_object = obj.dict(
|
|
690
|
-
|
|
691
|
-
)
|
|
692
|
-
combined_schemas: List[JsonSchemaObject] = []
|
|
651
|
+
) -> list[DataType]:
|
|
652
|
+
base_object = obj.dict(exclude={target_attribute_name}, exclude_unset=True, by_alias=True)
|
|
653
|
+
combined_schemas: list[JsonSchemaObject] = []
|
|
693
654
|
refs = []
|
|
694
|
-
for index, target_attribute in enumerate(
|
|
695
|
-
getattr(obj, target_attribute_name, [])
|
|
696
|
-
):
|
|
655
|
+
for index, target_attribute in enumerate(getattr(obj, target_attribute_name, [])):
|
|
697
656
|
if target_attribute.ref:
|
|
698
657
|
combined_schemas.append(target_attribute)
|
|
699
658
|
refs.append(index)
|
|
700
659
|
# TODO: support partial ref
|
|
701
|
-
# {
|
|
702
|
-
# "type": "integer",
|
|
703
|
-
# "oneOf": [
|
|
704
|
-
# { "minimum": 5 },
|
|
705
|
-
# { "$ref": "#/definitions/positive" }
|
|
706
|
-
# ],
|
|
707
|
-
# "definitions": {
|
|
708
|
-
# "positive": {
|
|
709
|
-
# "minimum": 0,
|
|
710
|
-
# "exclusiveMinimum": true
|
|
711
|
-
# }
|
|
712
|
-
# }
|
|
713
|
-
# }
|
|
714
660
|
else:
|
|
715
661
|
combined_schemas.append(
|
|
716
662
|
self.SCHEMA_OBJECT_TYPE.parse_obj(
|
|
@@ -728,7 +674,7 @@ class JsonSchemaParser(Parser):
|
|
|
728
674
|
obj,
|
|
729
675
|
singular_name=False,
|
|
730
676
|
)
|
|
731
|
-
common_path_keyword = f
|
|
677
|
+
common_path_keyword = f"{target_attribute_name}Common"
|
|
732
678
|
return [
|
|
733
679
|
self._parse_object_common_part(
|
|
734
680
|
name,
|
|
@@ -744,35 +690,27 @@ class JsonSchemaParser(Parser):
|
|
|
744
690
|
for i, d in enumerate(parsed_schemas)
|
|
745
691
|
]
|
|
746
692
|
|
|
747
|
-
def parse_any_of(
|
|
748
|
-
self
|
|
749
|
-
) -> List[DataType]:
|
|
750
|
-
return self.parse_combined_schema(name, obj, path, 'anyOf')
|
|
693
|
+
def parse_any_of(self, name: str, obj: JsonSchemaObject, path: list[str]) -> list[DataType]:
|
|
694
|
+
return self.parse_combined_schema(name, obj, path, "anyOf")
|
|
751
695
|
|
|
752
|
-
def parse_one_of(
|
|
753
|
-
self
|
|
754
|
-
) -> List[DataType]:
|
|
755
|
-
return self.parse_combined_schema(name, obj, path, 'oneOf')
|
|
696
|
+
def parse_one_of(self, name: str, obj: JsonSchemaObject, path: list[str]) -> list[DataType]:
|
|
697
|
+
return self.parse_combined_schema(name, obj, path, "oneOf")
|
|
756
698
|
|
|
757
|
-
def _parse_object_common_part(
|
|
699
|
+
def _parse_object_common_part( # noqa: PLR0913, PLR0917
|
|
758
700
|
self,
|
|
759
701
|
name: str,
|
|
760
702
|
obj: JsonSchemaObject,
|
|
761
|
-
path:
|
|
762
|
-
ignore_duplicate_model: bool,
|
|
763
|
-
fields:
|
|
764
|
-
base_classes:
|
|
765
|
-
required:
|
|
703
|
+
path: list[str],
|
|
704
|
+
ignore_duplicate_model: bool, # noqa: FBT001
|
|
705
|
+
fields: list[DataModelFieldBase],
|
|
706
|
+
base_classes: list[Reference],
|
|
707
|
+
required: list[str],
|
|
766
708
|
) -> DataType:
|
|
767
709
|
if obj.properties:
|
|
768
|
-
fields.extend(
|
|
769
|
-
self.parse_object_fields(obj, path, get_module_name(name, None))
|
|
770
|
-
)
|
|
710
|
+
fields.extend(self.parse_object_fields(obj, path, get_module_name(name, None)))
|
|
771
711
|
# ignore an undetected object
|
|
772
712
|
if ignore_duplicate_model and not fields and len(base_classes) == 1:
|
|
773
|
-
with self.model_resolver.current_base_path_context(
|
|
774
|
-
self.model_resolver._base_path
|
|
775
|
-
):
|
|
713
|
+
with self.model_resolver.current_base_path_context(self.model_resolver._base_path): # noqa: SLF001
|
|
776
714
|
self.model_resolver.delete(path)
|
|
777
715
|
return self.data_type(reference=base_classes[0])
|
|
778
716
|
if required:
|
|
@@ -789,16 +727,13 @@ class JsonSchemaParser(Parser):
|
|
|
789
727
|
if required_ in field_name_to_field:
|
|
790
728
|
field = field_name_to_field[required_]
|
|
791
729
|
if self.force_optional_for_required_fields or (
|
|
792
|
-
self.apply_default_values_for_required_fields
|
|
793
|
-
and field.has_default
|
|
730
|
+
self.apply_default_values_for_required_fields and field.has_default
|
|
794
731
|
):
|
|
795
732
|
continue
|
|
796
733
|
field.required = True
|
|
797
734
|
else:
|
|
798
735
|
fields.append(
|
|
799
|
-
self.data_model_field_type(
|
|
800
|
-
required=True, original_name=required_, data_type=DataType()
|
|
801
|
-
)
|
|
736
|
+
self.data_model_field_type(required=True, original_name=required_, data_type=DataType())
|
|
802
737
|
)
|
|
803
738
|
if self.use_title_as_name and obj.title: # pragma: no cover
|
|
804
739
|
name = obj.title
|
|
@@ -819,15 +754,15 @@ class JsonSchemaParser(Parser):
|
|
|
819
754
|
|
|
820
755
|
return self.data_type(reference=reference)
|
|
821
756
|
|
|
822
|
-
def _parse_all_of_item(
|
|
757
|
+
def _parse_all_of_item( # noqa: PLR0913, PLR0917
|
|
823
758
|
self,
|
|
824
759
|
name: str,
|
|
825
760
|
obj: JsonSchemaObject,
|
|
826
|
-
path:
|
|
827
|
-
fields:
|
|
828
|
-
base_classes:
|
|
829
|
-
required:
|
|
830
|
-
union_models:
|
|
761
|
+
path: list[str],
|
|
762
|
+
fields: list[DataModelFieldBase],
|
|
763
|
+
base_classes: list[Reference],
|
|
764
|
+
required: list[str],
|
|
765
|
+
union_models: list[Reference],
|
|
831
766
|
) -> None:
|
|
832
767
|
for all_of_item in obj.allOf:
|
|
833
768
|
if all_of_item.ref: # $ref
|
|
@@ -842,9 +777,8 @@ class JsonSchemaParser(Parser):
|
|
|
842
777
|
|
|
843
778
|
if object_fields:
|
|
844
779
|
fields.extend(object_fields)
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
required.extend(all_of_item.required)
|
|
780
|
+
elif all_of_item.required:
|
|
781
|
+
required.extend(all_of_item.required)
|
|
848
782
|
self._parse_all_of_item(
|
|
849
783
|
name,
|
|
850
784
|
all_of_item,
|
|
@@ -856,40 +790,31 @@ class JsonSchemaParser(Parser):
|
|
|
856
790
|
)
|
|
857
791
|
if all_of_item.anyOf:
|
|
858
792
|
self.model_resolver.add(path, name, class_name=True, loaded=True)
|
|
859
|
-
union_models.extend(
|
|
860
|
-
d.reference
|
|
861
|
-
for d in self.parse_any_of(name, all_of_item, path)
|
|
862
|
-
if d.reference
|
|
863
|
-
)
|
|
793
|
+
union_models.extend(d.reference for d in self.parse_any_of(name, all_of_item, path) if d.reference)
|
|
864
794
|
if all_of_item.oneOf:
|
|
865
795
|
self.model_resolver.add(path, name, class_name=True, loaded=True)
|
|
866
|
-
union_models.extend(
|
|
867
|
-
d.reference
|
|
868
|
-
for d in self.parse_one_of(name, all_of_item, path)
|
|
869
|
-
if d.reference
|
|
870
|
-
)
|
|
796
|
+
union_models.extend(d.reference for d in self.parse_one_of(name, all_of_item, path) if d.reference)
|
|
871
797
|
|
|
872
798
|
def parse_all_of(
|
|
873
799
|
self,
|
|
874
800
|
name: str,
|
|
875
801
|
obj: JsonSchemaObject,
|
|
876
|
-
path:
|
|
877
|
-
ignore_duplicate_model: bool = False,
|
|
802
|
+
path: list[str],
|
|
803
|
+
ignore_duplicate_model: bool = False, # noqa: FBT001, FBT002
|
|
878
804
|
) -> DataType:
|
|
879
805
|
if len(obj.allOf) == 1 and not obj.properties:
|
|
880
806
|
single_obj = obj.allOf[0]
|
|
881
|
-
if
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
)
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
)
|
|
807
|
+
if (
|
|
808
|
+
single_obj.ref
|
|
809
|
+
and single_obj.ref_type == JSONReference.LOCAL
|
|
810
|
+
and get_model_by_path(self.raw_obj, single_obj.ref[2:].split("/")).get("enum")
|
|
811
|
+
):
|
|
812
|
+
return self.get_ref_data_type(single_obj.ref)
|
|
813
|
+
fields: list[DataModelFieldBase] = []
|
|
814
|
+
base_classes: list[Reference] = []
|
|
815
|
+
required: list[str] = []
|
|
816
|
+
union_models: list[Reference] = []
|
|
817
|
+
self._parse_all_of_item(name, obj, path, fields, base_classes, required, union_models)
|
|
893
818
|
if not union_models:
|
|
894
819
|
return self._parse_object_common_part(
|
|
895
820
|
name, obj, path, ignore_duplicate_model, fields, base_classes, required
|
|
@@ -898,21 +823,22 @@ class JsonSchemaParser(Parser):
|
|
|
898
823
|
all_of_data_type = self._parse_object_common_part(
|
|
899
824
|
name,
|
|
900
825
|
obj,
|
|
901
|
-
get_special_path(
|
|
826
|
+
get_special_path("allOf", path),
|
|
902
827
|
ignore_duplicate_model,
|
|
903
828
|
fields,
|
|
904
829
|
base_classes,
|
|
905
830
|
required,
|
|
906
831
|
)
|
|
832
|
+
assert all_of_data_type.reference is not None
|
|
907
833
|
data_type = self.data_type(
|
|
908
834
|
data_types=[
|
|
909
835
|
self._parse_object_common_part(
|
|
910
836
|
name,
|
|
911
837
|
obj,
|
|
912
|
-
get_special_path(f
|
|
838
|
+
get_special_path(f"union_model-{index}", path),
|
|
913
839
|
ignore_duplicate_model,
|
|
914
840
|
[],
|
|
915
|
-
[union_model, all_of_data_type.reference],
|
|
841
|
+
[union_model, all_of_data_type.reference],
|
|
916
842
|
[],
|
|
917
843
|
)
|
|
918
844
|
for index, union_model in enumerate(union_models)
|
|
@@ -940,20 +866,21 @@ class JsonSchemaParser(Parser):
|
|
|
940
866
|
return self.data_type(reference=reference)
|
|
941
867
|
|
|
942
868
|
def parse_object_fields(
|
|
943
|
-
self,
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
869
|
+
self,
|
|
870
|
+
obj: JsonSchemaObject,
|
|
871
|
+
path: list[str],
|
|
872
|
+
module_name: Optional[str] = None, # noqa: UP045
|
|
873
|
+
) -> list[DataModelFieldBase]:
|
|
874
|
+
properties: dict[str, JsonSchemaObject | bool] = {} if obj.properties is None else obj.properties
|
|
875
|
+
requires: set[str] = {*()} if obj.required is None else {*obj.required}
|
|
876
|
+
fields: list[DataModelFieldBase] = []
|
|
877
|
+
|
|
878
|
+
exclude_field_names: set[str] = set()
|
|
952
879
|
for original_field_name, field in properties.items():
|
|
953
880
|
field_name, alias = self.model_resolver.get_valid_field_name_and_alias(
|
|
954
881
|
original_field_name, exclude_field_names
|
|
955
882
|
)
|
|
956
|
-
modular_name = f
|
|
883
|
+
modular_name = f"{module_name}.{field_name}" if module_name else field_name
|
|
957
884
|
|
|
958
885
|
exclude_field_names.add(field_name)
|
|
959
886
|
|
|
@@ -964,9 +891,7 @@ class JsonSchemaParser(Parser):
|
|
|
964
891
|
data_type=self.data_type_manager.get_data_type(
|
|
965
892
|
Types.any,
|
|
966
893
|
),
|
|
967
|
-
required=False
|
|
968
|
-
if self.force_optional_for_required_fields
|
|
969
|
-
else original_field_name in requires,
|
|
894
|
+
required=False if self.force_optional_for_required_fields else original_field_name in requires,
|
|
970
895
|
alias=alias,
|
|
971
896
|
strip_default_none=self.strip_default_none,
|
|
972
897
|
use_annotated=self.use_annotated,
|
|
@@ -1000,15 +925,16 @@ class JsonSchemaParser(Parser):
|
|
|
1000
925
|
self,
|
|
1001
926
|
name: str,
|
|
1002
927
|
obj: JsonSchemaObject,
|
|
1003
|
-
path:
|
|
1004
|
-
singular_name: bool = False,
|
|
1005
|
-
unique: bool = True,
|
|
928
|
+
path: list[str],
|
|
929
|
+
singular_name: bool = False, # noqa: FBT001, FBT002
|
|
930
|
+
unique: bool = True, # noqa: FBT001, FBT002
|
|
1006
931
|
) -> DataType:
|
|
1007
932
|
if not unique: # pragma: no cover
|
|
1008
933
|
warn(
|
|
1009
|
-
f
|
|
1010
|
-
f
|
|
1011
|
-
f
|
|
934
|
+
f"{self.__class__.__name__}.parse_object() ignore `unique` argument."
|
|
935
|
+
f"An object name must be unique."
|
|
936
|
+
f"This argument will be removed in a future version",
|
|
937
|
+
stacklevel=2,
|
|
1012
938
|
)
|
|
1013
939
|
if self.use_title_as_name and obj.title:
|
|
1014
940
|
name = obj.title
|
|
@@ -1037,7 +963,7 @@ class JsonSchemaParser(Parser):
|
|
|
1037
963
|
# TODO: Improve naming for nested ClassName
|
|
1038
964
|
name,
|
|
1039
965
|
obj.additionalProperties,
|
|
1040
|
-
[*path,
|
|
966
|
+
[*path, "additionalProperties"],
|
|
1041
967
|
)
|
|
1042
968
|
],
|
|
1043
969
|
is_dict=True,
|
|
@@ -1065,8 +991,8 @@ class JsonSchemaParser(Parser):
|
|
|
1065
991
|
def parse_pattern_properties(
|
|
1066
992
|
self,
|
|
1067
993
|
name: str,
|
|
1068
|
-
pattern_properties:
|
|
1069
|
-
path:
|
|
994
|
+
pattern_properties: dict[str, JsonSchemaObject],
|
|
995
|
+
path: list[str],
|
|
1070
996
|
) -> DataType:
|
|
1071
997
|
return self.data_type(
|
|
1072
998
|
data_types=[
|
|
@@ -1075,7 +1001,7 @@ class JsonSchemaParser(Parser):
|
|
|
1075
1001
|
self.parse_item(
|
|
1076
1002
|
name,
|
|
1077
1003
|
kv[1],
|
|
1078
|
-
get_special_path(f
|
|
1004
|
+
get_special_path(f"patternProperties/{i}", path),
|
|
1079
1005
|
)
|
|
1080
1006
|
],
|
|
1081
1007
|
is_dict=True,
|
|
@@ -1088,24 +1014,19 @@ class JsonSchemaParser(Parser):
|
|
|
1088
1014
|
],
|
|
1089
1015
|
)
|
|
1090
1016
|
|
|
1091
|
-
def parse_item(
|
|
1017
|
+
def parse_item( # noqa: PLR0911, PLR0912
|
|
1092
1018
|
self,
|
|
1093
1019
|
name: str,
|
|
1094
1020
|
item: JsonSchemaObject,
|
|
1095
|
-
path:
|
|
1096
|
-
singular_name: bool = False,
|
|
1097
|
-
parent:
|
|
1021
|
+
path: list[str],
|
|
1022
|
+
singular_name: bool = False, # noqa: FBT001, FBT002
|
|
1023
|
+
parent: JsonSchemaObject | None = None,
|
|
1098
1024
|
) -> DataType:
|
|
1099
1025
|
if self.use_title_as_name and item.title:
|
|
1100
1026
|
name = item.title
|
|
1101
1027
|
singular_name = False
|
|
1102
|
-
if (
|
|
1103
|
-
|
|
1104
|
-
and not item.enum
|
|
1105
|
-
and item.has_constraint
|
|
1106
|
-
and (parent.has_constraint or self.field_constraints)
|
|
1107
|
-
):
|
|
1108
|
-
root_type_path = get_special_path('array', path)
|
|
1028
|
+
if parent and not item.enum and item.has_constraint and (parent.has_constraint or self.field_constraints):
|
|
1029
|
+
root_type_path = get_special_path("array", path)
|
|
1109
1030
|
return self.parse_root_type(
|
|
1110
1031
|
self.model_resolver.add(
|
|
1111
1032
|
root_type_path,
|
|
@@ -1116,83 +1037,56 @@ class JsonSchemaParser(Parser):
|
|
|
1116
1037
|
item,
|
|
1117
1038
|
root_type_path,
|
|
1118
1039
|
)
|
|
1119
|
-
|
|
1040
|
+
if item.ref:
|
|
1120
1041
|
return self.get_ref_data_type(item.ref)
|
|
1121
|
-
|
|
1122
|
-
return self.data_type_manager.get_data_type_from_full_path(
|
|
1123
|
-
|
|
1124
|
-
)
|
|
1125
|
-
|
|
1126
|
-
return self.parse_array_fields(
|
|
1127
|
-
name, item, get_special_path('array', path)
|
|
1128
|
-
).data_type
|
|
1129
|
-
elif (
|
|
1130
|
-
item.discriminator
|
|
1131
|
-
and parent
|
|
1132
|
-
and parent.is_array
|
|
1133
|
-
and (item.oneOf or item.anyOf)
|
|
1134
|
-
):
|
|
1042
|
+
if item.custom_type_path:
|
|
1043
|
+
return self.data_type_manager.get_data_type_from_full_path(item.custom_type_path, is_custom_type=True)
|
|
1044
|
+
if item.is_array:
|
|
1045
|
+
return self.parse_array_fields(name, item, get_special_path("array", path)).data_type
|
|
1046
|
+
if item.discriminator and parent and parent.is_array and (item.oneOf or item.anyOf):
|
|
1135
1047
|
return self.parse_root_type(name, item, path)
|
|
1136
|
-
|
|
1137
|
-
return self.data_type(
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
)
|
|
1142
|
-
elif item.oneOf:
|
|
1143
|
-
return self.data_type(
|
|
1144
|
-
data_types=self.parse_one_of(
|
|
1145
|
-
name, item, get_special_path('oneOf', path)
|
|
1146
|
-
)
|
|
1147
|
-
)
|
|
1148
|
-
elif item.allOf:
|
|
1149
|
-
all_of_path = get_special_path('allOf', path)
|
|
1048
|
+
if item.anyOf:
|
|
1049
|
+
return self.data_type(data_types=self.parse_any_of(name, item, get_special_path("anyOf", path)))
|
|
1050
|
+
if item.oneOf:
|
|
1051
|
+
return self.data_type(data_types=self.parse_one_of(name, item, get_special_path("oneOf", path)))
|
|
1052
|
+
if item.allOf:
|
|
1053
|
+
all_of_path = get_special_path("allOf", path)
|
|
1150
1054
|
all_of_path = [self.model_resolver.resolve_ref(all_of_path)]
|
|
1151
1055
|
return self.parse_all_of(
|
|
1152
|
-
self.model_resolver.add(
|
|
1153
|
-
all_of_path, name, singular_name=singular_name, class_name=True
|
|
1154
|
-
).name,
|
|
1056
|
+
self.model_resolver.add(all_of_path, name, singular_name=singular_name, class_name=True).name,
|
|
1155
1057
|
item,
|
|
1156
1058
|
all_of_path,
|
|
1157
1059
|
ignore_duplicate_model=True,
|
|
1158
1060
|
)
|
|
1159
|
-
|
|
1160
|
-
object_path = get_special_path(
|
|
1061
|
+
if item.is_object or item.patternProperties:
|
|
1062
|
+
object_path = get_special_path("object", path)
|
|
1161
1063
|
if item.properties:
|
|
1162
|
-
return self.parse_object(
|
|
1163
|
-
|
|
1164
|
-
)
|
|
1165
|
-
elif item.patternProperties:
|
|
1064
|
+
return self.parse_object(name, item, object_path, singular_name=singular_name)
|
|
1065
|
+
if item.patternProperties:
|
|
1166
1066
|
# support only single key dict.
|
|
1167
|
-
return self.parse_pattern_properties(
|
|
1168
|
-
|
|
1169
|
-
)
|
|
1170
|
-
elif isinstance(item.additionalProperties, JsonSchemaObject):
|
|
1067
|
+
return self.parse_pattern_properties(name, item.patternProperties, object_path)
|
|
1068
|
+
if isinstance(item.additionalProperties, JsonSchemaObject):
|
|
1171
1069
|
return self.data_type(
|
|
1172
|
-
data_types=[
|
|
1173
|
-
self.parse_item(name, item.additionalProperties, object_path)
|
|
1174
|
-
],
|
|
1070
|
+
data_types=[self.parse_item(name, item.additionalProperties, object_path)],
|
|
1175
1071
|
is_dict=True,
|
|
1176
1072
|
)
|
|
1177
1073
|
return self.data_type_manager.get_data_type(
|
|
1178
1074
|
Types.object,
|
|
1179
1075
|
)
|
|
1180
|
-
|
|
1076
|
+
if item.enum:
|
|
1181
1077
|
if self.should_parse_enum_as_literal(item):
|
|
1182
1078
|
return self.parse_enum_as_literal(item)
|
|
1183
|
-
return self.parse_enum(
|
|
1184
|
-
name, item, get_special_path('enum', path), singular_name=singular_name
|
|
1185
|
-
)
|
|
1079
|
+
return self.parse_enum(name, item, get_special_path("enum", path), singular_name=singular_name)
|
|
1186
1080
|
return self.get_data_type(item)
|
|
1187
1081
|
|
|
1188
1082
|
def parse_list_item(
|
|
1189
1083
|
self,
|
|
1190
1084
|
name: str,
|
|
1191
|
-
target_items:
|
|
1192
|
-
path:
|
|
1085
|
+
target_items: list[JsonSchemaObject],
|
|
1086
|
+
path: list[str],
|
|
1193
1087
|
parent: JsonSchemaObject,
|
|
1194
|
-
singular_name: bool = True,
|
|
1195
|
-
) ->
|
|
1088
|
+
singular_name: bool = True, # noqa: FBT001, FBT002
|
|
1089
|
+
) -> list[DataType]:
|
|
1196
1090
|
return [
|
|
1197
1091
|
self.parse_item(
|
|
1198
1092
|
name,
|
|
@@ -1208,29 +1102,27 @@ class JsonSchemaParser(Parser):
|
|
|
1208
1102
|
self,
|
|
1209
1103
|
name: str,
|
|
1210
1104
|
obj: JsonSchemaObject,
|
|
1211
|
-
path:
|
|
1212
|
-
singular_name: bool = True,
|
|
1105
|
+
path: list[str],
|
|
1106
|
+
singular_name: bool = True, # noqa: FBT001, FBT002
|
|
1213
1107
|
) -> DataModelFieldBase:
|
|
1214
1108
|
if self.force_optional_for_required_fields:
|
|
1215
1109
|
required: bool = False
|
|
1216
|
-
nullable: Optional[bool] = None
|
|
1110
|
+
nullable: Optional[bool] = None # noqa: UP045
|
|
1217
1111
|
else:
|
|
1218
|
-
required = not (
|
|
1219
|
-
obj.has_default and self.apply_default_values_for_required_fields
|
|
1220
|
-
)
|
|
1112
|
+
required = not (obj.has_default and self.apply_default_values_for_required_fields)
|
|
1221
1113
|
if self.strict_nullable:
|
|
1222
1114
|
nullable = obj.nullable if obj.has_default or required else True
|
|
1223
1115
|
else:
|
|
1224
1116
|
required = not obj.nullable and required
|
|
1225
1117
|
nullable = None
|
|
1226
1118
|
if isinstance(obj.items, JsonSchemaObject):
|
|
1227
|
-
items:
|
|
1119
|
+
items: list[JsonSchemaObject] = [obj.items]
|
|
1228
1120
|
elif isinstance(obj.items, list):
|
|
1229
1121
|
items = obj.items
|
|
1230
1122
|
else:
|
|
1231
1123
|
items = []
|
|
1232
1124
|
|
|
1233
|
-
data_types:
|
|
1125
|
+
data_types: list[DataType] = [
|
|
1234
1126
|
self.data_type(
|
|
1235
1127
|
data_types=self.parse_list_item(
|
|
1236
1128
|
name,
|
|
@@ -1244,17 +1136,11 @@ class JsonSchemaParser(Parser):
|
|
|
1244
1136
|
]
|
|
1245
1137
|
# TODO: decide special path word for a combined data model.
|
|
1246
1138
|
if obj.allOf:
|
|
1247
|
-
data_types.append(
|
|
1248
|
-
self.parse_all_of(name, obj, get_special_path('allOf', path))
|
|
1249
|
-
)
|
|
1139
|
+
data_types.append(self.parse_all_of(name, obj, get_special_path("allOf", path)))
|
|
1250
1140
|
elif obj.is_object:
|
|
1251
|
-
data_types.append(
|
|
1252
|
-
self.parse_object(name, obj, get_special_path('object', path))
|
|
1253
|
-
)
|
|
1141
|
+
data_types.append(self.parse_object(name, obj, get_special_path("object", path)))
|
|
1254
1142
|
if obj.enum:
|
|
1255
|
-
data_types.append(
|
|
1256
|
-
self.parse_enum(name, obj, get_special_path('enum', path))
|
|
1257
|
-
)
|
|
1143
|
+
data_types.append(self.parse_enum(name, obj, get_special_path("enum", path)))
|
|
1258
1144
|
return self.data_model_field_type(
|
|
1259
1145
|
data_type=self.data_type(data_types=data_types),
|
|
1260
1146
|
default=obj.default,
|
|
@@ -1273,24 +1159,20 @@ class JsonSchemaParser(Parser):
|
|
|
1273
1159
|
self,
|
|
1274
1160
|
name: str,
|
|
1275
1161
|
obj: JsonSchemaObject,
|
|
1276
|
-
path:
|
|
1277
|
-
original_name:
|
|
1162
|
+
path: list[str],
|
|
1163
|
+
original_name: str | None = None,
|
|
1278
1164
|
) -> DataType:
|
|
1279
1165
|
if self.use_title_as_name and obj.title:
|
|
1280
1166
|
name = obj.title
|
|
1281
1167
|
reference = self.model_resolver.add(path, name, loaded=True, class_name=True)
|
|
1282
1168
|
field = self.parse_array_fields(original_name or name, obj, [*path, name])
|
|
1283
1169
|
|
|
1284
|
-
if reference in [
|
|
1285
|
-
d.reference for d in field.data_type.all_data_types if d.reference
|
|
1286
|
-
]:
|
|
1170
|
+
if reference in [d.reference for d in field.data_type.all_data_types if d.reference]:
|
|
1287
1171
|
# self-reference
|
|
1288
1172
|
field = self.data_model_field_type(
|
|
1289
1173
|
data_type=self.data_type(
|
|
1290
1174
|
data_types=[
|
|
1291
|
-
self.data_type(
|
|
1292
|
-
data_types=field.data_type.data_types[1:], is_list=True
|
|
1293
|
-
),
|
|
1175
|
+
self.data_type(data_types=field.data_type.data_types[1:], is_list=True),
|
|
1294
1176
|
*field.data_type.data_types[1:],
|
|
1295
1177
|
]
|
|
1296
1178
|
),
|
|
@@ -1319,13 +1201,13 @@ class JsonSchemaParser(Parser):
|
|
|
1319
1201
|
self.results.append(data_model_root)
|
|
1320
1202
|
return self.data_type(reference=reference)
|
|
1321
1203
|
|
|
1322
|
-
def parse_root_type(
|
|
1204
|
+
def parse_root_type( # noqa: PLR0912
|
|
1323
1205
|
self,
|
|
1324
1206
|
name: str,
|
|
1325
1207
|
obj: JsonSchemaObject,
|
|
1326
|
-
path:
|
|
1208
|
+
path: list[str],
|
|
1327
1209
|
) -> DataType:
|
|
1328
|
-
reference:
|
|
1210
|
+
reference: Reference | None = None
|
|
1329
1211
|
if obj.ref:
|
|
1330
1212
|
data_type: DataType = self.get_ref_data_type(obj.ref)
|
|
1331
1213
|
elif obj.custom_type_path:
|
|
@@ -1334,20 +1216,14 @@ class JsonSchemaParser(Parser):
|
|
|
1334
1216
|
) # pragma: no cover
|
|
1335
1217
|
elif obj.is_array:
|
|
1336
1218
|
data_type = self.parse_array_fields(
|
|
1337
|
-
name, obj, get_special_path(
|
|
1219
|
+
name, obj, get_special_path("array", path)
|
|
1338
1220
|
).data_type # pragma: no cover
|
|
1339
1221
|
elif obj.anyOf or obj.oneOf:
|
|
1340
|
-
reference = self.model_resolver.add(
|
|
1341
|
-
path, name, loaded=True, class_name=True
|
|
1342
|
-
)
|
|
1222
|
+
reference = self.model_resolver.add(path, name, loaded=True, class_name=True)
|
|
1343
1223
|
if obj.anyOf:
|
|
1344
|
-
data_types:
|
|
1345
|
-
name, obj, get_special_path('anyOf', path)
|
|
1346
|
-
)
|
|
1224
|
+
data_types: list[DataType] = self.parse_any_of(name, obj, get_special_path("anyOf", path))
|
|
1347
1225
|
else:
|
|
1348
|
-
data_types = self.parse_one_of(
|
|
1349
|
-
name, obj, get_special_path('oneOf', path)
|
|
1350
|
-
)
|
|
1226
|
+
data_types = self.parse_one_of(name, obj, get_special_path("oneOf", path))
|
|
1351
1227
|
|
|
1352
1228
|
if len(data_types) > 1: # pragma: no cover
|
|
1353
1229
|
data_type = self.data_type(data_types=data_types)
|
|
@@ -1371,15 +1247,11 @@ class JsonSchemaParser(Parser):
|
|
|
1371
1247
|
if self.force_optional_for_required_fields:
|
|
1372
1248
|
required: bool = False
|
|
1373
1249
|
else:
|
|
1374
|
-
required = not obj.nullable and not (
|
|
1375
|
-
obj.has_default and self.apply_default_values_for_required_fields
|
|
1376
|
-
)
|
|
1250
|
+
required = not obj.nullable and not (obj.has_default and self.apply_default_values_for_required_fields)
|
|
1377
1251
|
if self.use_title_as_name and obj.title:
|
|
1378
1252
|
name = obj.title
|
|
1379
1253
|
if not reference:
|
|
1380
|
-
reference = self.model_resolver.add(
|
|
1381
|
-
path, name, loaded=True, class_name=True
|
|
1382
|
-
)
|
|
1254
|
+
reference = self.model_resolver.add(path, name, loaded=True, class_name=True)
|
|
1383
1255
|
self.set_title(name, obj)
|
|
1384
1256
|
self.set_additional_properties(name, obj)
|
|
1385
1257
|
data_model_root_type = self.data_model_root_type(
|
|
@@ -1415,19 +1287,20 @@ class JsonSchemaParser(Parser):
|
|
|
1415
1287
|
self,
|
|
1416
1288
|
name: str,
|
|
1417
1289
|
obj: JsonSchemaObject,
|
|
1418
|
-
path:
|
|
1419
|
-
singular_name: bool = False,
|
|
1420
|
-
unique: bool = True,
|
|
1290
|
+
path: list[str],
|
|
1291
|
+
singular_name: bool = False, # noqa: FBT001, FBT002
|
|
1292
|
+
unique: bool = True, # noqa: FBT001, FBT002
|
|
1421
1293
|
) -> DataType:
|
|
1422
1294
|
if not unique: # pragma: no cover
|
|
1423
1295
|
warn(
|
|
1424
|
-
f
|
|
1425
|
-
f
|
|
1426
|
-
f
|
|
1296
|
+
f"{self.__class__.__name__}.parse_enum() ignore `unique` argument."
|
|
1297
|
+
f"An object name must be unique."
|
|
1298
|
+
f"This argument will be removed in a future version",
|
|
1299
|
+
stacklevel=2,
|
|
1427
1300
|
)
|
|
1428
|
-
enum_fields:
|
|
1301
|
+
enum_fields: list[DataModelFieldBase] = []
|
|
1429
1302
|
|
|
1430
|
-
if None in obj.enum and obj.type ==
|
|
1303
|
+
if None in obj.enum and obj.type == "string":
|
|
1431
1304
|
# Nullable is valid in only OpenAPI
|
|
1432
1305
|
nullable: bool = True
|
|
1433
1306
|
enum_times = [e for e in obj.enum if e is not None]
|
|
@@ -1435,30 +1308,19 @@ class JsonSchemaParser(Parser):
|
|
|
1435
1308
|
enum_times = obj.enum
|
|
1436
1309
|
nullable = False
|
|
1437
1310
|
|
|
1438
|
-
exclude_field_names:
|
|
1311
|
+
exclude_field_names: set[str] = set()
|
|
1439
1312
|
|
|
1440
1313
|
for i, enum_part in enumerate(enum_times):
|
|
1441
|
-
if obj.type ==
|
|
1442
|
-
default = (
|
|
1443
|
-
|
|
1444
|
-
if isinstance(enum_part, str)
|
|
1445
|
-
else enum_part
|
|
1446
|
-
)
|
|
1447
|
-
if obj.x_enum_varnames:
|
|
1448
|
-
field_name = obj.x_enum_varnames[i]
|
|
1449
|
-
else:
|
|
1450
|
-
field_name = str(enum_part)
|
|
1314
|
+
if obj.type == "string" or isinstance(enum_part, str):
|
|
1315
|
+
default = f"'{enum_part.translate(escape_characters)}'" if isinstance(enum_part, str) else enum_part
|
|
1316
|
+
field_name = obj.x_enum_varnames[i] if obj.x_enum_varnames else str(enum_part)
|
|
1451
1317
|
else:
|
|
1452
1318
|
default = enum_part
|
|
1453
1319
|
if obj.x_enum_varnames:
|
|
1454
1320
|
field_name = obj.x_enum_varnames[i]
|
|
1455
1321
|
else:
|
|
1456
|
-
prefix = (
|
|
1457
|
-
|
|
1458
|
-
if isinstance(obj.type, str)
|
|
1459
|
-
else type(enum_part).__name__
|
|
1460
|
-
)
|
|
1461
|
-
field_name = f'{prefix}_{enum_part}'
|
|
1322
|
+
prefix = obj.type if isinstance(obj.type, str) else type(enum_part).__name__
|
|
1323
|
+
field_name = f"{prefix}_{enum_part}"
|
|
1462
1324
|
field_name = self.model_resolver.get_valid_field_name(
|
|
1463
1325
|
field_name, excludes=exclude_field_names, model_type=ModelType.ENUM
|
|
1464
1326
|
)
|
|
@@ -1485,9 +1347,7 @@ class JsonSchemaParser(Parser):
|
|
|
1485
1347
|
path=self.current_source_path,
|
|
1486
1348
|
description=obj.description if self.use_schema_description else None,
|
|
1487
1349
|
custom_template_dir=self.custom_template_dir,
|
|
1488
|
-
type_=_get_type(obj.type, obj.format)
|
|
1489
|
-
if self.use_subclass_enum and isinstance(obj.type, str)
|
|
1490
|
-
else None,
|
|
1350
|
+
type_=_get_type(obj.type, obj.format) if self.use_subclass_enum and isinstance(obj.type, str) else None,
|
|
1491
1351
|
default=obj.default if obj.has_default else UNDEFINED,
|
|
1492
1352
|
)
|
|
1493
1353
|
self.results.append(enum)
|
|
@@ -1500,7 +1360,7 @@ class JsonSchemaParser(Parser):
|
|
|
1500
1360
|
name,
|
|
1501
1361
|
class_name=True,
|
|
1502
1362
|
singular_name=singular_name,
|
|
1503
|
-
singular_name_suffix=
|
|
1363
|
+
singular_name_suffix="Enum",
|
|
1504
1364
|
loaded=True,
|
|
1505
1365
|
)
|
|
1506
1366
|
|
|
@@ -1508,11 +1368,11 @@ class JsonSchemaParser(Parser):
|
|
|
1508
1368
|
return create_enum(reference)
|
|
1509
1369
|
|
|
1510
1370
|
enum_reference = self.model_resolver.add(
|
|
1511
|
-
[*path,
|
|
1512
|
-
f
|
|
1371
|
+
[*path, "Enum"],
|
|
1372
|
+
f"{reference.name}Enum",
|
|
1513
1373
|
class_name=True,
|
|
1514
1374
|
singular_name=singular_name,
|
|
1515
|
-
singular_name_suffix=
|
|
1375
|
+
singular_name_suffix="Enum",
|
|
1516
1376
|
loaded=True,
|
|
1517
1377
|
)
|
|
1518
1378
|
|
|
@@ -1542,19 +1402,19 @@ class JsonSchemaParser(Parser):
|
|
|
1542
1402
|
self.results.append(data_model_root_type)
|
|
1543
1403
|
return self.data_type(reference=reference)
|
|
1544
1404
|
|
|
1545
|
-
def _get_ref_body(self, resolved_ref: str) ->
|
|
1405
|
+
def _get_ref_body(self, resolved_ref: str) -> dict[Any, Any]:
|
|
1546
1406
|
if is_url(resolved_ref):
|
|
1547
1407
|
return self._get_ref_body_from_url(resolved_ref)
|
|
1548
1408
|
return self._get_ref_body_from_remote(resolved_ref)
|
|
1549
1409
|
|
|
1550
|
-
def _get_ref_body_from_url(self, ref: str) ->
|
|
1551
|
-
# URL Reference
|
|
1410
|
+
def _get_ref_body_from_url(self, ref: str) -> dict[Any, Any]:
|
|
1411
|
+
# URL Reference: $ref: 'http://path/to/your/resource' Uses the whole document located on the different server.
|
|
1552
1412
|
return self.remote_object_cache.get_or_put(
|
|
1553
1413
|
ref, default_factory=lambda key: load_yaml(self._get_text_from_url(key))
|
|
1554
1414
|
)
|
|
1555
1415
|
|
|
1556
|
-
def _get_ref_body_from_remote(self, resolved_ref: str) ->
|
|
1557
|
-
# Remote Reference
|
|
1416
|
+
def _get_ref_body_from_remote(self, resolved_ref: str) -> dict[Any, Any]:
|
|
1417
|
+
# Remote Reference: $ref: 'document.json' Uses the whole document located on the same server and in
|
|
1558
1418
|
# the same location. TODO treat edge case
|
|
1559
1419
|
full_path = self.base_path / resolved_ref
|
|
1560
1420
|
|
|
@@ -1571,46 +1431,45 @@ class JsonSchemaParser(Parser):
|
|
|
1571
1431
|
# https://swagger.io/docs/specification/using-ref/
|
|
1572
1432
|
ref = self.model_resolver.resolve_ref(object_ref)
|
|
1573
1433
|
if get_ref_type(object_ref) == JSONReference.LOCAL:
|
|
1574
|
-
# Local Reference
|
|
1575
|
-
self.reserved_refs[tuple(self.model_resolver.current_root)].add(ref)
|
|
1434
|
+
# Local Reference: $ref: '#/definitions/myElement'
|
|
1435
|
+
self.reserved_refs[tuple(self.model_resolver.current_root)].add(ref)
|
|
1576
1436
|
return reference
|
|
1577
|
-
|
|
1578
|
-
self.reserved_refs[tuple(ref.split(
|
|
1437
|
+
if self.model_resolver.is_after_load(ref):
|
|
1438
|
+
self.reserved_refs[tuple(ref.split("#")[0].split("/"))].add(ref)
|
|
1579
1439
|
return reference
|
|
1580
1440
|
|
|
1581
1441
|
if is_url(ref):
|
|
1582
|
-
relative_path, object_path = ref.split(
|
|
1442
|
+
relative_path, object_path = ref.split("#")
|
|
1583
1443
|
relative_paths = [relative_path]
|
|
1584
1444
|
base_path = None
|
|
1585
1445
|
else:
|
|
1586
1446
|
if self.model_resolver.is_external_root_ref(ref):
|
|
1587
|
-
relative_path, object_path = ref[:-1],
|
|
1447
|
+
relative_path, object_path = ref[:-1], ""
|
|
1588
1448
|
else:
|
|
1589
|
-
relative_path, object_path = ref.split(
|
|
1590
|
-
relative_paths = relative_path.split(
|
|
1449
|
+
relative_path, object_path = ref.split("#")
|
|
1450
|
+
relative_paths = relative_path.split("/")
|
|
1591
1451
|
base_path = Path(*relative_paths).parent
|
|
1592
|
-
with self.model_resolver.current_base_path_context(
|
|
1593
|
-
|
|
1594
|
-
)
|
|
1452
|
+
with self.model_resolver.current_base_path_context(base_path), self.model_resolver.base_url_context(
|
|
1453
|
+
relative_path
|
|
1454
|
+
):
|
|
1595
1455
|
self._parse_file(
|
|
1596
1456
|
self._get_ref_body(relative_path),
|
|
1597
1457
|
self.model_resolver.add_ref(ref, resolved=True).name,
|
|
1598
1458
|
relative_paths,
|
|
1599
|
-
object_path.split(
|
|
1459
|
+
object_path.split("/") if object_path else None,
|
|
1600
1460
|
)
|
|
1601
1461
|
reference.loaded = True
|
|
1602
1462
|
return reference
|
|
1603
1463
|
|
|
1604
|
-
def parse_ref(self, obj: JsonSchemaObject, path:
|
|
1464
|
+
def parse_ref(self, obj: JsonSchemaObject, path: list[str]) -> None: # noqa: PLR0912
|
|
1605
1465
|
if obj.ref:
|
|
1606
1466
|
self.resolve_ref(obj.ref)
|
|
1607
1467
|
if obj.items:
|
|
1608
1468
|
if isinstance(obj.items, JsonSchemaObject):
|
|
1609
1469
|
self.parse_ref(obj.items, path)
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
self.parse_ref(item, path)
|
|
1470
|
+
elif isinstance(obj.items, list):
|
|
1471
|
+
for item in obj.items:
|
|
1472
|
+
self.parse_ref(item, path)
|
|
1614
1473
|
if isinstance(obj.additionalProperties, JsonSchemaObject):
|
|
1615
1474
|
self.parse_ref(obj.additionalProperties, path)
|
|
1616
1475
|
if obj.patternProperties:
|
|
@@ -1627,16 +1486,15 @@ class JsonSchemaParser(Parser):
|
|
|
1627
1486
|
if isinstance(property_value, JsonSchemaObject):
|
|
1628
1487
|
self.parse_ref(property_value, path)
|
|
1629
1488
|
|
|
1630
|
-
def parse_id(self, obj: JsonSchemaObject, path:
|
|
1489
|
+
def parse_id(self, obj: JsonSchemaObject, path: list[str]) -> None: # noqa: PLR0912
|
|
1631
1490
|
if obj.id:
|
|
1632
1491
|
self.model_resolver.add_id(obj.id, path)
|
|
1633
1492
|
if obj.items:
|
|
1634
1493
|
if isinstance(obj.items, JsonSchemaObject):
|
|
1635
1494
|
self.parse_id(obj.items, path)
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
self.parse_id(item, path)
|
|
1495
|
+
elif isinstance(obj.items, list):
|
|
1496
|
+
for item in obj.items:
|
|
1497
|
+
self.parse_id(item, path)
|
|
1640
1498
|
if isinstance(obj.additionalProperties, JsonSchemaObject):
|
|
1641
1499
|
self.parse_id(obj.additionalProperties, path)
|
|
1642
1500
|
if obj.patternProperties:
|
|
@@ -1652,18 +1510,18 @@ class JsonSchemaParser(Parser):
|
|
|
1652
1510
|
self.parse_id(property_value, path)
|
|
1653
1511
|
|
|
1654
1512
|
@contextmanager
|
|
1655
|
-
def root_id_context(self, root_raw:
|
|
1656
|
-
root_id:
|
|
1657
|
-
previous_root_id:
|
|
1658
|
-
self.root_id = root_id
|
|
1513
|
+
def root_id_context(self, root_raw: dict[str, Any]) -> Generator[None, None, None]:
|
|
1514
|
+
root_id: str | None = root_raw.get("$id")
|
|
1515
|
+
previous_root_id: str | None = self.root_id
|
|
1516
|
+
self.root_id = root_id or None
|
|
1659
1517
|
yield
|
|
1660
1518
|
self.root_id = previous_root_id
|
|
1661
1519
|
|
|
1662
1520
|
def parse_raw_obj(
|
|
1663
1521
|
self,
|
|
1664
1522
|
name: str,
|
|
1665
|
-
raw:
|
|
1666
|
-
path:
|
|
1523
|
+
raw: dict[str, Any],
|
|
1524
|
+
path: list[str],
|
|
1667
1525
|
) -> None:
|
|
1668
1526
|
self.parse_obj(name, self.SCHEMA_OBJECT_TYPE.parse_obj(raw), path)
|
|
1669
1527
|
|
|
@@ -1671,7 +1529,7 @@ class JsonSchemaParser(Parser):
|
|
|
1671
1529
|
self,
|
|
1672
1530
|
name: str,
|
|
1673
1531
|
obj: JsonSchemaObject,
|
|
1674
|
-
path:
|
|
1532
|
+
path: list[str],
|
|
1675
1533
|
) -> None:
|
|
1676
1534
|
if obj.is_array:
|
|
1677
1535
|
self.parse_array(name, obj, path)
|
|
@@ -1685,7 +1543,7 @@ class JsonSchemaParser(Parser):
|
|
|
1685
1543
|
self.parse_object(name, obj, path)
|
|
1686
1544
|
elif obj.patternProperties:
|
|
1687
1545
|
self.parse_root_type(name, obj, path)
|
|
1688
|
-
elif obj.type ==
|
|
1546
|
+
elif obj.type == "object":
|
|
1689
1547
|
self.parse_object(name, obj, path)
|
|
1690
1548
|
elif obj.enum and not self.should_parse_enum_as_literal(obj):
|
|
1691
1549
|
self.parse_enum(name, obj, path)
|
|
@@ -1693,14 +1551,11 @@ class JsonSchemaParser(Parser):
|
|
|
1693
1551
|
self.parse_root_type(name, obj, path)
|
|
1694
1552
|
self.parse_ref(obj, path)
|
|
1695
1553
|
|
|
1696
|
-
def _get_context_source_path_parts(self) -> Iterator[
|
|
1697
|
-
if isinstance(self.source, list) or (
|
|
1698
|
-
isinstance(self.source, Path) and self.source.is_dir()
|
|
1699
|
-
):
|
|
1554
|
+
def _get_context_source_path_parts(self) -> Iterator[tuple[Source, list[str]]]:
|
|
1555
|
+
if isinstance(self.source, list) or (isinstance(self.source, Path) and self.source.is_dir()):
|
|
1700
1556
|
self.current_source_path = Path()
|
|
1701
1557
|
self.model_resolver.after_load_files = {
|
|
1702
|
-
self.base_path.joinpath(s.path).resolve().as_posix()
|
|
1703
|
-
for s in self.iter_source
|
|
1558
|
+
self.base_path.joinpath(s.path).resolve().as_posix() for s in self.iter_source
|
|
1704
1559
|
}
|
|
1705
1560
|
|
|
1706
1561
|
for source in self.iter_source:
|
|
@@ -1719,16 +1574,16 @@ class JsonSchemaParser(Parser):
|
|
|
1719
1574
|
for source, path_parts in self._get_context_source_path_parts():
|
|
1720
1575
|
self.raw_obj = load_yaml(source.text)
|
|
1721
1576
|
if self.raw_obj is None: # pragma: no cover
|
|
1722
|
-
warn(f
|
|
1577
|
+
warn(f"{source.path} is empty. Skipping this file", stacklevel=2)
|
|
1723
1578
|
continue
|
|
1724
1579
|
if self.custom_class_name_generator:
|
|
1725
|
-
obj_name = self.raw_obj.get(
|
|
1580
|
+
obj_name = self.raw_obj.get("title", "Model")
|
|
1726
1581
|
else:
|
|
1727
1582
|
if self.class_name:
|
|
1728
1583
|
obj_name = self.class_name
|
|
1729
1584
|
else:
|
|
1730
1585
|
# backward compatible
|
|
1731
|
-
obj_name = self.raw_obj.get(
|
|
1586
|
+
obj_name = self.raw_obj.get("title", "Model")
|
|
1732
1587
|
if not self.model_resolver.validate_name(obj_name):
|
|
1733
1588
|
obj_name = title_to_class_name(obj_name)
|
|
1734
1589
|
if not self.model_resolver.validate_name(obj_name):
|
|
@@ -1741,7 +1596,7 @@ class JsonSchemaParser(Parser):
|
|
|
1741
1596
|
model_count: int = len(self.results)
|
|
1742
1597
|
for source in self.iter_source:
|
|
1743
1598
|
path_parts = list(source.path.parts)
|
|
1744
|
-
reserved_refs = self.reserved_refs.get(tuple(path_parts))
|
|
1599
|
+
reserved_refs = self.reserved_refs.get(tuple(path_parts))
|
|
1745
1600
|
if not reserved_refs:
|
|
1746
1601
|
continue
|
|
1747
1602
|
if self.current_source_path is not None:
|
|
@@ -1761,45 +1616,36 @@ class JsonSchemaParser(Parser):
|
|
|
1761
1616
|
# New model have been generated. It try to resolve json pointer again.
|
|
1762
1617
|
self._resolve_unparsed_json_pointer()
|
|
1763
1618
|
|
|
1764
|
-
def parse_json_pointer(
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
path = ref.split('#', 1)[-1]
|
|
1768
|
-
if path[0] == '/': # pragma: no cover
|
|
1619
|
+
def parse_json_pointer(self, raw: dict[str, Any], ref: str, path_parts: list[str]) -> None:
|
|
1620
|
+
path = ref.split("#", 1)[-1]
|
|
1621
|
+
if path[0] == "/": # pragma: no cover
|
|
1769
1622
|
path = path[1:]
|
|
1770
|
-
object_paths = path.split(
|
|
1623
|
+
object_paths = path.split("/")
|
|
1771
1624
|
models = get_model_by_path(raw, object_paths)
|
|
1772
1625
|
model_name = object_paths[-1]
|
|
1773
1626
|
|
|
1774
|
-
self.parse_raw_obj(
|
|
1775
|
-
model_name, models, [*path_parts, f'#/{object_paths[0]}', *object_paths[1:]]
|
|
1776
|
-
)
|
|
1627
|
+
self.parse_raw_obj(model_name, models, [*path_parts, f"#/{object_paths[0]}", *object_paths[1:]])
|
|
1777
1628
|
|
|
1778
|
-
def _parse_file(
|
|
1629
|
+
def _parse_file( # noqa: PLR0912
|
|
1779
1630
|
self,
|
|
1780
|
-
raw:
|
|
1631
|
+
raw: dict[str, Any],
|
|
1781
1632
|
obj_name: str,
|
|
1782
|
-
path_parts:
|
|
1783
|
-
object_paths:
|
|
1633
|
+
path_parts: list[str],
|
|
1634
|
+
object_paths: list[str] | None = None,
|
|
1784
1635
|
) -> None:
|
|
1785
1636
|
object_paths = [o for o in object_paths or [] if o]
|
|
1786
|
-
if object_paths
|
|
1787
|
-
path = [*path_parts, f'#/{object_paths[0]}', *object_paths[1:]]
|
|
1788
|
-
else:
|
|
1789
|
-
path = path_parts
|
|
1637
|
+
path = [*path_parts, f"#/{object_paths[0]}", *object_paths[1:]] if object_paths else path_parts
|
|
1790
1638
|
with self.model_resolver.current_root_context(path_parts):
|
|
1791
|
-
obj_name = self.model_resolver.add(
|
|
1792
|
-
path, obj_name, unique=False, class_name=True
|
|
1793
|
-
).name
|
|
1639
|
+
obj_name = self.model_resolver.add(path, obj_name, unique=False, class_name=True).name
|
|
1794
1640
|
with self.root_id_context(raw):
|
|
1795
1641
|
# Some jsonschema docs include attribute self to have include version details
|
|
1796
|
-
raw.pop(
|
|
1642
|
+
raw.pop("self", None)
|
|
1797
1643
|
# parse $id before parsing $ref
|
|
1798
1644
|
root_obj = self.SCHEMA_OBJECT_TYPE.parse_obj(raw)
|
|
1799
1645
|
self.parse_id(root_obj, path_parts)
|
|
1800
|
-
definitions:
|
|
1801
|
-
|
|
1802
|
-
for
|
|
1646
|
+
definitions: dict[Any, Any] | None = None
|
|
1647
|
+
_schema_path = ""
|
|
1648
|
+
for _schema_path, split_schema_path in self.schema_paths:
|
|
1803
1649
|
try:
|
|
1804
1650
|
definitions = get_model_by_path(raw, split_schema_path)
|
|
1805
1651
|
if definitions:
|
|
@@ -1811,18 +1657,16 @@ class JsonSchemaParser(Parser):
|
|
|
1811
1657
|
|
|
1812
1658
|
for key, model in definitions.items():
|
|
1813
1659
|
obj = self.SCHEMA_OBJECT_TYPE.parse_obj(model)
|
|
1814
|
-
self.parse_id(obj, [*path_parts,
|
|
1660
|
+
self.parse_id(obj, [*path_parts, _schema_path, key])
|
|
1815
1661
|
|
|
1816
1662
|
if object_paths:
|
|
1817
1663
|
models = get_model_by_path(raw, object_paths)
|
|
1818
1664
|
model_name = object_paths[-1]
|
|
1819
|
-
self.parse_obj(
|
|
1820
|
-
model_name, self.SCHEMA_OBJECT_TYPE.parse_obj(models), path
|
|
1821
|
-
)
|
|
1665
|
+
self.parse_obj(model_name, self.SCHEMA_OBJECT_TYPE.parse_obj(models), path)
|
|
1822
1666
|
else:
|
|
1823
|
-
self.parse_obj(obj_name, root_obj, path_parts or [
|
|
1667
|
+
self.parse_obj(obj_name, root_obj, path_parts or ["#"])
|
|
1824
1668
|
for key, model in definitions.items():
|
|
1825
|
-
path = [*path_parts,
|
|
1669
|
+
path = [*path_parts, _schema_path, key]
|
|
1826
1670
|
reference = self.model_resolver.get(path)
|
|
1827
1671
|
if not reference or not reference.loaded:
|
|
1828
1672
|
self.parse_raw_obj(key, model, path)
|
|
@@ -1834,13 +1678,11 @@ class JsonSchemaParser(Parser):
|
|
|
1834
1678
|
reference = self.model_resolver.get(reserved_path)
|
|
1835
1679
|
if not reference or reference.loaded:
|
|
1836
1680
|
continue
|
|
1837
|
-
object_paths = reserved_path.split(
|
|
1838
|
-
path = reserved_path.split(
|
|
1681
|
+
object_paths = reserved_path.split("#/", 1)[-1].split("/")
|
|
1682
|
+
path = reserved_path.split("/")
|
|
1839
1683
|
models = get_model_by_path(raw, object_paths)
|
|
1840
1684
|
model_name = object_paths[-1]
|
|
1841
|
-
self.parse_obj(
|
|
1842
|
-
model_name, self.SCHEMA_OBJECT_TYPE.parse_obj(models), path
|
|
1843
|
-
)
|
|
1685
|
+
self.parse_obj(model_name, self.SCHEMA_OBJECT_TYPE.parse_obj(models), path)
|
|
1844
1686
|
previous_reserved_refs = reserved_refs
|
|
1845
1687
|
reserved_refs = set(self.reserved_refs.get(key) or [])
|
|
1846
1688
|
if previous_reserved_refs == reserved_refs:
|