55from typing import TYPE_CHECKING , Any , Type , Tuple , Union , Generic , TypeVar , Callable , Optional , cast
66from datetime import date , datetime
77from typing_extensions import (
8+ List ,
89 Unpack ,
910 Literal ,
1011 ClassVar ,
@@ -391,7 +392,7 @@ def _construct_field(value: object, field: FieldInfo, key: str) -> object:
391392 if type_ is None :
392393 raise RuntimeError (f"Unexpected field type is None for { key } " )
393394
394- return construct_type (value = value , type_ = type_ )
395+ return construct_type (value = value , type_ = type_ , metadata = getattr ( field , "metadata" , None ) )
395396
396397
397398def is_basemodel (type_ : type ) -> bool :
@@ -445,7 +446,7 @@ def construct_type_unchecked(*, value: object, type_: type[_T]) -> _T:
445446 return cast (_T , construct_type (value = value , type_ = type_ ))
446447
447448
448- def construct_type (* , value : object , type_ : object ) -> object :
449+ def construct_type (* , value : object , type_ : object , metadata : Optional [ List [ Any ]] = None ) -> object :
449450 """Loose coercion to the expected type with construction of nested values.
450451
451452 If the given value does not match the expected type then it is returned as-is.
@@ -463,8 +464,10 @@ def construct_type(*, value: object, type_: object) -> object:
463464 type_ = type_ .__value__ # type: ignore[unreachable]
464465
465466 # unwrap `Annotated[T, ...]` -> `T`
466- if is_annotated_type (type_ ):
467- meta : tuple [Any , ...] = get_args (type_ )[1 :]
467+ if metadata is not None :
468+ meta : tuple [Any , ...] = tuple (metadata )
469+ elif is_annotated_type (type_ ):
470+ meta = get_args (type_ )[1 :]
468471 type_ = extract_type_arg (type_ , 0 )
469472 else :
470473 meta = tuple ()
0 commit comments