5
5
from typing import TYPE_CHECKING , Any , Type , Tuple , Union , Generic , TypeVar , Callable , Optional , cast
6
6
from datetime import date , datetime
7
7
from typing_extensions import (
8
+ List ,
8
9
Unpack ,
9
10
Literal ,
10
11
ClassVar ,
@@ -391,7 +392,7 @@ def _construct_field(value: object, field: FieldInfo, key: str) -> object:
391
392
if type_ is None :
392
393
raise RuntimeError (f"Unexpected field type is None for { key } " )
393
394
394
- return construct_type (value = value , type_ = type_ )
395
+ return construct_type (value = value , type_ = type_ , metadata = getattr ( field , "metadata" , None ) )
395
396
396
397
397
398
def is_basemodel (type_ : type ) -> bool :
@@ -445,7 +446,7 @@ def construct_type_unchecked(*, value: object, type_: type[_T]) -> _T:
445
446
return cast (_T , construct_type (value = value , type_ = type_ ))
446
447
447
448
448
- def construct_type (* , value : object , type_ : object ) -> object :
449
+ def construct_type (* , value : object , type_ : object , metadata : Optional [ List [ Any ]] = None ) -> object :
449
450
"""Loose coercion to the expected type with construction of nested values.
450
451
451
452
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:
463
464
type_ = type_ .__value__ # type: ignore[unreachable]
464
465
465
466
# 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 :]
468
471
type_ = extract_type_arg (type_ , 0 )
469
472
else :
470
473
meta = tuple ()
0 commit comments