🐛 Fix support for tagged union with discriminator

This commit is contained in:
Sebastián Ramírez 2025-12-12 15:00:04 +01:00
parent 10c551636e
commit 1643b0b6f5
1 changed files with 43 additions and 4 deletions

View File

@ -18,7 +18,7 @@ from typing import (
from fastapi._compat import may_v1, shared from fastapi._compat import may_v1, shared
from fastapi.openapi.constants import REF_TEMPLATE from fastapi.openapi.constants import REF_TEMPLATE
from fastapi.types import IncEx, ModelNameMap, UnionType from fastapi.types import IncEx, ModelNameMap, UnionType
from pydantic import BaseModel, ConfigDict, TypeAdapter, create_model from pydantic import BaseModel, ConfigDict, Field, TypeAdapter, create_model
from pydantic import PydanticSchemaGenerationError as PydanticSchemaGenerationError from pydantic import PydanticSchemaGenerationError as PydanticSchemaGenerationError
from pydantic import PydanticUndefinedAnnotation as PydanticUndefinedAnnotation from pydantic import PydanticUndefinedAnnotation as PydanticUndefinedAnnotation
from pydantic import ValidationError as ValidationError from pydantic import ValidationError as ValidationError
@ -50,6 +50,40 @@ UndefinedType = PydanticUndefinedType
evaluate_forwardref = eval_type_lenient evaluate_forwardref = eval_type_lenient
Validator = Any Validator = Any
# TODO: remove when dropping support for Pydantic < v2.12.3
_Attrs = {
"default": ...,
"default_factory": None,
"alias": None,
"alias_priority": None,
"validation_alias": None,
"serialization_alias": None,
"title": None,
"field_title_generator": None,
"description": None,
"examples": None,
"exclude": None,
"exclude_if": None,
"discriminator": None,
"deprecated": None,
"json_schema_extra": None,
"frozen": None,
"validate_default": None,
"repr": True,
"init": None,
"init_var": None,
"kw_only": None,
}
# TODO: remove when dropping support for Pydantic < v2.12.3
def asdict(field_info: FieldInfo) -> Dict[str, Any]:
return {
"annotation": field_info.annotation,
"metadata": field_info.metadata,
"attributes": {attr: getattr(field_info, attr) for attr in _Attrs},
}
class BaseConfig: class BaseConfig:
pass pass
@ -95,10 +129,15 @@ class ModelField:
warnings.simplefilter( warnings.simplefilter(
"ignore", category=UnsupportedFieldAttributeWarning "ignore", category=UnsupportedFieldAttributeWarning
) )
# TODO: remove after dropping support for Python 3.8 and
# setting the min Pydantic to v2.12.3 that adds asdict()
field_dict = asdict(self.field_info)
annotated_args = ( annotated_args = (
self.field_info.annotation, field_dict["annotation"],
*self.field_info.metadata, *field_dict["metadata"],
self.field_info, # this FieldInfo needs to be created again so that it doesn't include
# the old field info metadata and only the rest of the attributes
Field(**field_dict["attributes"]),
) )
self._type_adapter: TypeAdapter[Any] = TypeAdapter( self._type_adapter: TypeAdapter[Any] = TypeAdapter(
Annotated[annotated_args], Annotated[annotated_args],