@@ -233,14 +233,18 @@ def construct( # pyright: ignore[reportIncompatibleMethodOverride]
233
233
else :
234
234
fields_values [name ] = field_get_default (field )
235
235
236
+ extra_field_type = _get_extra_fields_type (__cls )
237
+
236
238
_extra = {}
237
239
for key , value in values .items ():
238
240
if key not in model_fields :
241
+ parsed = construct_type (value = value , type_ = extra_field_type ) if extra_field_type is not None else value
242
+
239
243
if PYDANTIC_V2 :
240
- _extra [key ] = value
244
+ _extra [key ] = parsed
241
245
else :
242
246
_fields_set .add (key )
243
- fields_values [key ] = value
247
+ fields_values [key ] = parsed
244
248
245
249
object .__setattr__ (m , "__dict__" , fields_values )
246
250
@@ -395,6 +399,23 @@ def _construct_field(value: object, field: FieldInfo, key: str) -> object:
395
399
return construct_type (value = value , type_ = type_ , metadata = getattr (field , "metadata" , None ))
396
400
397
401
402
+ def _get_extra_fields_type (cls : type [pydantic .BaseModel ]) -> type | None :
403
+ if not PYDANTIC_V2 :
404
+ # TODO
405
+ return None
406
+
407
+ schema = cls .__pydantic_core_schema__
408
+ if schema ["type" ] == "model" :
409
+ fields = schema ["schema" ]
410
+ if fields ["type" ] == "model-fields" :
411
+ extras = fields .get ("extras_schema" )
412
+ if extras and "cls" in extras :
413
+ # mypy can't narrow the type
414
+ return extras ["cls" ] # type: ignore[no-any-return]
415
+
416
+ return None
417
+
418
+
398
419
def is_basemodel (type_ : type ) -> bool :
399
420
"""Returns whether or not the given type is either a `BaseModel` or a union of `BaseModel`"""
400
421
if is_union (type_ ):
0 commit comments