@@ -124,7 +124,9 @@ def __parse_primitive(self, name: str, path: str, schema: Dict[str, Any]) -> Pri
124
124
}
125
125
)
126
126
127
- def __parse_object (self , name : str , path : str , schema : Dict [str , Any ]) -> Object :
127
+ def __parse_object (
128
+ self , name : str , path : str , schema : Dict [str , Any ], root : Optional [AllTypes ] = None
129
+ ) -> Object :
128
130
_ , is_nullable = self .__is_field_nullable (schema )
129
131
model = Object .from_dict (
130
132
{
@@ -136,21 +138,25 @@ def __parse_object(self, name: str, path: str, schema: Dict[str, Any]) -> Object
136
138
** schema ,
137
139
}
138
140
)
139
- self . root = model if not self . root else self . root
141
+ root = model if root is None else root
140
142
props = []
141
143
for _name , definition in schema .get ("properties" , {}).items ():
142
- props .append (self .__parse_definition (_name , path = f"{ path } /{ _name } " , schema = definition ))
144
+ props .append (
145
+ self .__parse_definition (_name , path = f"{ path } /{ _name } " , schema = definition , root = root )
146
+ )
143
147
model .properties = props
144
148
pattern_props = []
145
149
for _name , definition in schema .get ("patternProperties" , {}).items ():
146
150
pattern_props .append (
147
- self .__parse_definition (_name , path = f"{ path } /{ _name } " , schema = definition )
151
+ self .__parse_definition (_name , path = f"{ path } /{ _name } " , schema = definition , root = root )
148
152
)
149
153
model .patternProperties = pattern_props
150
154
151
155
return model
152
156
153
- def __parse_array (self , name : str , path : str , schema : Dict [str , Any ]) -> Array :
157
+ def __parse_array (
158
+ self , name : str , path : str , schema : Dict [str , Any ], root : Optional [AllTypes ] = None
159
+ ) -> Array :
154
160
_ , is_nullable = self .__is_field_nullable (schema )
155
161
arr = Array .from_dict (
156
162
{
@@ -162,11 +168,13 @@ def __parse_array(self, name: str, path: str, schema: Dict[str, Any]) -> Array:
162
168
** schema ,
163
169
}
164
170
)
165
- self . root = arr if not self . root else self . root
166
- arr .items = self .__parse_definition (name , f"{ path } /items" , schema ["items" ])
171
+ root = arr if root is None else root
172
+ arr .items = self .__parse_definition (name , f"{ path } /items" , schema ["items" ], root = root )
167
173
return arr
168
174
169
- def __parse_tuple (self , name : str , path : str , schema : Dict [str , Any ]) -> JSFTuple :
175
+ def __parse_tuple (
176
+ self , name : str , path : str , schema : Dict [str , Any ], root : Optional [AllTypes ] = None
177
+ ) -> JSFTuple :
170
178
_ , is_nullable = self .__is_field_nullable (schema )
171
179
arr = JSFTuple .from_dict (
172
180
{
@@ -178,10 +186,12 @@ def __parse_tuple(self, name: str, path: str, schema: Dict[str, Any]) -> JSFTupl
178
186
** schema ,
179
187
}
180
188
)
181
- self . root = arr if not self . root else self . root
189
+ root = arr if root is None else root
182
190
arr .items = []
183
191
for i , item in enumerate (schema ["items" ]):
184
- arr .items .append (self .__parse_definition (name , path = f"{ path } /{ name } [{ i } ]" , schema = item ))
192
+ arr .items .append (
193
+ self .__parse_definition (name , path = f"{ path } /{ name } [{ i } ]" , schema = item , root = root )
194
+ )
185
195
return arr
186
196
187
197
def __is_field_nullable (self , schema : Dict [str , Any ]) -> Tuple [str , bool ]:
@@ -196,46 +206,55 @@ def __is_field_nullable(self, schema: Dict[str, Any]) -> Tuple[str, bool]:
196
206
return random .choice (item_type_deep_copy ), False
197
207
return item_type , False
198
208
199
- def __parse_anyOf (self , name : str , path : str , schema : Dict [str , Any ]) -> AnyOf :
209
+ def __parse_anyOf (
210
+ self , name : str , path : str , schema : Dict [str , Any ], root : Optional [AllTypes ] = None
211
+ ) -> AnyOf :
200
212
model = AnyOf (name = name , path = path , max_recursive_depth = self .max_recursive_depth , ** schema )
201
- self . root = model if not self . root else self . root
213
+ root = model if root is None else root
202
214
schemas = []
203
215
for d in schema ["anyOf" ]:
204
- schemas .append (self .__parse_definition (name , path , d ))
216
+ schemas .append (self .__parse_definition (name , path , d , root = root ))
205
217
model .schemas = schemas
206
218
return model
207
219
208
- def __parse_allOf (self , name : str , path : str , schema : Dict [str , Any ]) -> AllOf :
220
+ def __parse_allOf (
221
+ self , name : str , path : str , schema : Dict [str , Any ], root : Optional [AllTypes ] = None
222
+ ) -> AllOf :
209
223
combined_schema = dict (ChainMap (* schema ["allOf" ]))
210
224
model = AllOf (name = name , path = path , max_recursive_depth = self .max_recursive_depth , ** schema )
211
- self . root = model if not self . root else self . root
212
- model .combined_schema = self .__parse_definition (name , path , combined_schema )
225
+ root = model if root is None else root
226
+ model .combined_schema = self .__parse_definition (name , path , combined_schema , root = root )
213
227
return model
214
228
215
- def __parse_oneOf (self , name : str , path : str , schema : Dict [str , Any ]) -> OneOf :
229
+ def __parse_oneOf (
230
+ self , name : str , path : str , schema : Dict [str , Any ], root : Optional [AllTypes ] = None
231
+ ) -> OneOf :
216
232
model = OneOf (name = name , path = path , max_recursive_depth = self .max_recursive_depth , ** schema )
217
- self . root = model if not self . root else self . root
233
+ root = model if root is None else root
218
234
schemas = []
219
235
for d in schema ["oneOf" ]:
220
- schemas .append (self .__parse_definition (name , path , d ))
236
+ schemas .append (self .__parse_definition (name , path , d , root = root ))
221
237
model .schemas = schemas
222
238
return model
223
239
224
- def __parse_named_definition (self , path : str , def_name : str ) -> AllTypes :
240
+ def __parse_named_definition (self , path : str , def_name : str , root ) -> AllTypes :
225
241
schema = self .root_schema
226
242
parsed_definition = None
227
243
for def_tag in ("definitions" , "$defs" ):
228
244
if path .startswith (f"#/{ def_tag } /{ def_name } " ):
229
- self .root .is_recursive = True
230
- return self .root
231
- elif definition := schema .get (def_tag , {}).get (def_name ):
245
+ root .is_recursive = True
246
+ return root
247
+ definition = schema .get (def_tag , {}).get (def_name )
248
+ if definition is not None :
232
249
parsed_definition = self .__parse_definition (
233
- def_name , path = f"{ path } /#/{ def_tag } /{ def_name } " , schema = definition
250
+ def_name , path = f"{ path } /#/{ def_tag } /{ def_name } " , schema = definition , root = root
234
251
)
235
252
self .definitions [f"#/{ def_tag } /{ def_name } " ] = parsed_definition
236
253
return parsed_definition
237
254
238
- def __parse_definition (self , name : str , path : str , schema : Dict [str , Any ]) -> AllTypes :
255
+ def __parse_definition (
256
+ self , name : str , path : str , schema : Dict [str , Any ], root : Optional [AllTypes ] = None
257
+ ) -> AllTypes :
239
258
self .base_state ["__all_json_paths__" ].append (path )
240
259
item_type , is_nullable = self .__is_field_nullable (schema )
241
260
if "const" in schema :
@@ -259,20 +278,20 @@ def __parse_definition(self, name: str, path: str, schema: Dict[str, Any]) -> Al
259
278
)
260
279
elif "type" in schema :
261
280
if item_type == "object" and "properties" in schema :
262
- return self .__parse_object (name , path , schema )
281
+ return self .__parse_object (name , path , schema , root )
263
282
elif item_type == "object" and "anyOf" in schema :
264
- return self .__parse_anyOf (name , path , schema )
283
+ return self .__parse_anyOf (name , path , schema , root )
265
284
elif item_type == "object" and "allOf" in schema :
266
- return self .__parse_allOf (name , path , schema )
285
+ return self .__parse_allOf (name , path , schema , root )
267
286
elif item_type == "object" and "oneOf" in schema :
268
- return self .__parse_oneOf (name , path , schema )
287
+ return self .__parse_oneOf (name , path , schema , root )
269
288
elif item_type == "array" :
270
289
if (schema .get ("contains" ) is not None ) or isinstance (schema .get ("items" ), dict ):
271
- return self .__parse_array (name , path , schema )
290
+ return self .__parse_array (name , path , schema , root )
272
291
if isinstance (schema .get ("items" ), list ) and all (
273
292
isinstance (x , dict ) for x in schema .get ("items" , [])
274
293
):
275
- return self .__parse_tuple (name , path , schema )
294
+ return self .__parse_tuple (name , path , schema , root )
276
295
else :
277
296
return self .__parse_primitive (name , path , schema )
278
297
elif "$ref" in schema :
@@ -283,20 +302,23 @@ def __parse_definition(self, name: str, path: str, schema: Dict[str, Any]) -> Al
283
302
else :
284
303
# parse referenced definition
285
304
ref_name = frag .split ("/" )[- 1 ]
286
- cls = self .__parse_named_definition (path , ref_name )
305
+ cls = self .__parse_named_definition (path , ref_name , root )
287
306
else :
288
307
with s_open (ext , "r" ) as f :
289
308
external_jsf = JSF (json .load (f ))
290
309
cls = deepcopy (external_jsf .definitions .get (f"#{ frag } " ))
291
- cls .name = name
292
- cls .path = path
310
+ if path != "#" and cls == root :
311
+ cls .name = name
312
+ elif path != "#" :
313
+ cls .name = name
314
+ cls .path = path
293
315
return cls
294
316
elif "anyOf" in schema :
295
- return self .__parse_anyOf (name , path , schema )
317
+ return self .__parse_anyOf (name , path , schema , root )
296
318
elif "allOf" in schema :
297
- return self .__parse_allOf (name , path , schema )
319
+ return self .__parse_allOf (name , path , schema , root )
298
320
elif "oneOf" in schema :
299
- return self .__parse_oneOf (name , path , schema )
321
+ return self .__parse_oneOf (name , path , schema , root )
300
322
else :
301
323
raise ValueError (f"Cannot parse schema { repr (schema )} " ) # pragma: no cover
302
324
0 commit comments