Browse Source

♻️ Tweak _compat to account for lists of models

pull/14168/head
Sebastián Ramírez 10 months ago
parent
commit
0d4d7d21ad
  1. 1
      fastapi/_compat/__init__.py
  2. 5
      fastapi/_compat/main.py
  3. 9
      fastapi/utils.py

1
fastapi/_compat/__init__.py

@ -33,6 +33,7 @@ from .main import (
from .model_field import ModelField as ModelField from .model_field import ModelField as ModelField
from .shared import PYDANTIC_V2 as PYDANTIC_V2 from .shared import PYDANTIC_V2 as PYDANTIC_V2
from .shared import PYDANTIC_VERSION_MINOR_TUPLE as PYDANTIC_VERSION_MINOR_TUPLE from .shared import PYDANTIC_VERSION_MINOR_TUPLE as PYDANTIC_VERSION_MINOR_TUPLE
from .shared import annotation_is_pydantic_v1 as annotation_is_pydantic_v1
from .shared import field_annotation_is_scalar as field_annotation_is_scalar from .shared import field_annotation_is_scalar as field_annotation_is_scalar
from .shared import ( from .shared import (
is_uploadfile_or_nonable_uploadfile_annotation as is_uploadfile_or_nonable_uploadfile_annotation, is_uploadfile_or_nonable_uploadfile_annotation as is_uploadfile_or_nonable_uploadfile_annotation,

5
fastapi/_compat/main.py

@ -205,8 +205,9 @@ def _model_rebuild(model: Type[BaseModel]) -> None:
def get_compat_model_name_map(fields: List[ModelField]) -> ModelNameMap: def get_compat_model_name_map(fields: List[ModelField]) -> ModelNameMap:
if fields and isinstance(fields[0], v1.ModelField): v1_models = [field for field in fields if isinstance(field, v1.ModelField)]
models = v1.get_flat_models_from_fields(fields, known_models=set()) if v1_models:
models = v1.get_flat_models_from_fields(v1_models, known_models=set())
return v1.get_model_name_map(models) # type: ignore[no-any-return] return v1.get_model_name_map(models) # type: ignore[no-any-return]
return {} return {}

9
fastapi/utils.py

@ -23,11 +23,12 @@ from fastapi._compat import (
Undefined, Undefined,
UndefinedType, UndefinedType,
Validator, Validator,
annotation_is_pydantic_v1,
lenient_issubclass, lenient_issubclass,
v1, v1,
) )
from fastapi.datastructures import DefaultPlaceholder, DefaultType from fastapi.datastructures import DefaultPlaceholder, DefaultType
from pydantic import BaseModel, create_model from pydantic import BaseModel
from pydantic.fields import FieldInfo from pydantic.fields import FieldInfo
from typing_extensions import Literal from typing_extensions import Literal
@ -86,7 +87,7 @@ def create_model_field(
) -> ModelField: ) -> ModelField:
class_validators = class_validators or {} class_validators = class_validators or {}
if lenient_issubclass(type_, v1.BaseModel) or version == "1": if annotation_is_pydantic_v1(type_) or version == "1":
model_config = v1.BaseConfig model_config = v1.BaseConfig
field_info = field_info or v1.FieldInfo() field_info = field_info or v1.FieldInfo()
kwargs = { kwargs = {
@ -124,6 +125,7 @@ def create_cloned_field(
) -> ModelField: ) -> ModelField:
if PYDANTIC_V2: if PYDANTIC_V2:
from ._compat import v2 from ._compat import v2
if isinstance(field, v2.ModelField): # type: ignore[name-defined] if isinstance(field, v2.ModelField): # type: ignore[name-defined]
return field return field
# cloned_types caches already cloned types to support recursive models and improve # cloned_types caches already cloned types to support recursive models and improve
@ -143,7 +145,8 @@ def create_cloned_field(
cloned_types[original_type] = use_type cloned_types[original_type] = use_type
for f in original_type.__fields__.values(): for f in original_type.__fields__.values():
use_type.__fields__[f.name] = create_cloned_field( use_type.__fields__[f.name] = create_cloned_field(
f, cloned_types=cloned_types, f,
cloned_types=cloned_types,
) )
new_field = create_model_field(name=field.name, type_=use_type, version="1") new_field = create_model_field(name=field.name, type_=use_type, version="1")
new_field.has_alias = field.has_alias # type: ignore[attr-defined] new_field.has_alias = field.has_alias # type: ignore[attr-defined]

Loading…
Cancel
Save