@@ -185,6 +185,57 @@ def __init__(
185
185
self .unmarshallers_factory = unmarshallers_factory
186
186
self .context = context
187
187
188
+ def _get_one_of_schema_unmarshaller (
189
+ self , value : Any
190
+ ) -> Optional [BaseSchemaUnmarshaller ]:
191
+ if "oneOf" not in self .schema :
192
+ return None
193
+
194
+ one_of_schemas = self .schema / "oneOf"
195
+ for subschema in one_of_schemas :
196
+ unmarshaller = self .unmarshallers_factory .create (subschema )
197
+ try :
198
+ unmarshaller .validate (value )
199
+ except ValidateError :
200
+ continue
201
+ else :
202
+ return unmarshaller
203
+ return None
204
+
205
+ def _iter_any_of_schema_unmarshallers (
206
+ self , value : Any
207
+ ) -> Iterator [BaseSchemaUnmarshaller ]:
208
+ if "anyOf" not in self .schema :
209
+ return
210
+
211
+ any_of_schemas = self .schema / "anyOf"
212
+ for subschema in any_of_schemas :
213
+ unmarshaller = self .unmarshallers_factory .create (subschema )
214
+ try :
215
+ unmarshaller .validate (value )
216
+ except ValidateError :
217
+ continue
218
+ else :
219
+ yield unmarshaller
220
+
221
+ def _iter_all_of_schema_unmarshallers (
222
+ self , value : Any
223
+ ) -> Iterator [BaseSchemaUnmarshaller ]:
224
+ if "allOf" not in self .schema :
225
+ return
226
+
227
+ all_of_schemas = self .schema / "allOf"
228
+ for subschema in all_of_schemas :
229
+ if "type" not in subschema :
230
+ continue
231
+ unmarshaller = self .unmarshallers_factory .create (subschema )
232
+ try :
233
+ unmarshaller .validate (value )
234
+ except ValidateError :
235
+ continue
236
+ else :
237
+ yield unmarshaller
238
+
188
239
189
240
class ArrayUnmarshaller (ComplexUnmarshaller ):
190
241
@@ -221,52 +272,41 @@ def unmarshal(self, value: Any) -> Any:
221
272
222
273
return object_class (** properties )
223
274
224
- def format (self , value : Any ) -> Any :
275
+ def format (self , value : Any , schema_only : bool = False ) -> Any :
225
276
formatted = super ().format (value )
226
- return self ._unmarshal_properties (formatted )
277
+ return self ._unmarshal_properties (formatted , schema_only = schema_only )
227
278
228
279
def _clone (self , schema : Spec ) -> "ObjectUnmarshaller" :
229
280
return cast (
230
281
"ObjectUnmarshaller" ,
231
282
self .unmarshallers_factory .create (schema , "object" ),
232
283
)
233
284
234
- def _unmarshal_properties (self , value : Any ) -> Any :
285
+ def _unmarshal_properties (
286
+ self , value : Any , schema_only : bool = False
287
+ ) -> Any :
235
288
properties = {}
236
289
237
- if "oneOf" in self .schema :
238
- one_of_properties = None
239
- for one_of_schema in self .schema / "oneOf" :
240
- try :
241
- unmarshalled = self ._clone (one_of_schema ).format (value )
242
- except (UnmarshalError , ValueError ):
243
- pass
244
- else :
245
- if one_of_properties is not None :
246
- log .warning ("multiple valid oneOf schemas found" )
247
- continue
248
- one_of_properties = unmarshalled
249
-
250
- if one_of_properties is None :
251
- log .warning ("valid oneOf schema not found" )
252
- else :
253
- properties .update (one_of_properties )
254
-
255
- elif "anyOf" in self .schema :
256
- any_of_properties = None
257
- for any_of_schema in self .schema / "anyOf" :
258
- try :
259
- unmarshalled = self ._clone (any_of_schema ).format (value )
260
- except (UnmarshalError , ValueError ):
261
- pass
262
- else :
263
- any_of_properties = unmarshalled
264
- break
265
-
266
- if any_of_properties is None :
267
- log .warning ("valid anyOf schema not found" )
268
- else :
269
- properties .update (any_of_properties )
290
+ one_of_unmarshaller = self ._get_one_of_schema_unmarshaller (value )
291
+ if one_of_unmarshaller is not None :
292
+ one_of_properties = one_of_unmarshaller .format (
293
+ value , schema_only = True
294
+ )
295
+ properties .update (one_of_properties )
296
+
297
+ any_of_unmarshallers = self ._iter_any_of_schema_unmarshallers (value )
298
+ for any_of_unmarshaller in any_of_unmarshallers :
299
+ any_of_properties = any_of_unmarshaller .format (
300
+ value , schema_only = True
301
+ )
302
+ properties .update (any_of_properties )
303
+
304
+ all_of_unmarshallers = self ._iter_all_of_schema_unmarshallers (value )
305
+ for all_of_unmarshaller in all_of_unmarshallers :
306
+ all_of_properties = all_of_unmarshaller .format (
307
+ value , schema_only = True
308
+ )
309
+ properties .update (all_of_properties )
270
310
271
311
for prop_name , prop in get_all_properties (self .schema ).items ():
272
312
read_only = prop .getkey ("readOnly" , False )
@@ -286,6 +326,9 @@ def _unmarshal_properties(self, value: Any) -> Any:
286
326
prop_value
287
327
)
288
328
329
+ if schema_only :
330
+ return properties
331
+
289
332
additional_properties = self .schema .getkey (
290
333
"additionalProperties" , True
291
334
)
@@ -359,63 +402,30 @@ def type(self) -> List[str]:
359
402
return self .SCHEMA_TYPES_ORDER
360
403
361
404
def unmarshal (self , value : Any ) -> Any :
362
- one_of_schema = self ._get_one_of_schema (value )
363
- if one_of_schema :
364
- return self .unmarshallers_factory .create (one_of_schema )(value )
405
+ one_of_schema_unmarshaller = self ._get_one_of_schema_unmarshaller (
406
+ value
407
+ )
408
+ if one_of_schema_unmarshaller :
409
+ return one_of_schema_unmarshaller (value )
365
410
366
- any_of_schema = self ._get_any_of_schema (value )
367
- if any_of_schema :
368
- return self .unmarshallers_factory .create (any_of_schema )(value )
411
+ any_of_schema_unmarshallers = self ._iter_any_of_schema_unmarshallers (
412
+ value
413
+ )
414
+ try :
415
+ any_of_schema_unmarshaller = next (any_of_schema_unmarshallers )
416
+ except StopIteration :
417
+ pass
418
+ else :
419
+ return any_of_schema_unmarshaller (value )
369
420
370
- all_of_schema = self ._get_all_of_schema (value )
371
- if all_of_schema :
372
- return self .unmarshallers_factory .create (all_of_schema )(value )
421
+ all_of_schema_unmarshallers = self ._iter_all_of_schema_unmarshallers (
422
+ value
423
+ )
424
+ try :
425
+ all_of_schema_unmarshaller = next (all_of_schema_unmarshallers )
426
+ except StopIteration :
427
+ pass
428
+ else :
429
+ return all_of_schema_unmarshaller (value )
373
430
374
431
return super ().unmarshal (value )
375
-
376
- def _get_one_of_schema (self , value : Any ) -> Optional [Spec ]:
377
- if "oneOf" not in self .schema :
378
- return None
379
-
380
- one_of_schemas = self .schema / "oneOf"
381
- for subschema in one_of_schemas :
382
- unmarshaller = self .unmarshallers_factory .create (subschema )
383
- try :
384
- unmarshaller .validate (value )
385
- except ValidateError :
386
- continue
387
- else :
388
- return subschema
389
- return None
390
-
391
- def _get_any_of_schema (self , value : Any ) -> Optional [Spec ]:
392
- if "anyOf" not in self .schema :
393
- return None
394
-
395
- any_of_schemas = self .schema / "anyOf"
396
- for subschema in any_of_schemas :
397
- unmarshaller = self .unmarshallers_factory .create (subschema )
398
- try :
399
- unmarshaller .validate (value )
400
- except ValidateError :
401
- continue
402
- else :
403
- return subschema
404
- return None
405
-
406
- def _get_all_of_schema (self , value : Any ) -> Optional [Spec ]:
407
- if "allOf" not in self .schema :
408
- return None
409
-
410
- all_of_schemas = self .schema / "allOf"
411
- for subschema in all_of_schemas :
412
- if "type" not in subschema :
413
- continue
414
- unmarshaller = self .unmarshallers_factory .create (subschema )
415
- try :
416
- unmarshaller .validate (value )
417
- except ValidateError :
418
- continue
419
- else :
420
- return subschema
421
- return None
0 commit comments