-from .shared import PYDANTIC_V2 as PYDANTIC_V2
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
) # pyright: ignore[reportAttributeAccessIssue]
PYDANTIC_VERSION_MINOR_TUPLE = tuple(int(x) for x in PYDANTIC_VERSION.split(".")[:2])
-PYDANTIC_V2 = PYDANTIC_VERSION_MINOR_TUPLE[0] == 2
sequence_annotation_to_type = {
def get_compat_model_name_map(fields: list[ModelField]) -> ModelNameMap:
- all_flat_models: TypeModelSet = set()
-
- v2_model_fields = [field for field in fields if isinstance(field, ModelField)]
- v2_flat_models = get_flat_models_from_fields(v2_model_fields, known_models=set())
- all_flat_models = all_flat_models.union(v2_flat_models)
-
- model_name_map = get_model_name_map(all_flat_models)
- return model_name_map
+ flat_models = get_flat_models_from_fields(fields, known_models=set())
+ return get_model_name_map(flat_models)
def get_flat_models_from_model(
)
from fastapi.types import DecoratedCallable, IncEx
from fastapi.utils import (
- create_cloned_field,
create_model_field,
generate_unique_id,
get_value_or_default,
type_=self.response_model,
mode="serialization",
)
- # Create a clone of the field, so that a Pydantic submodel is not returned
- # as is just because it's an instance of a subclass of a more limited class
- # e.g. UserInDB (containing hashed_password) could be a subclass of User
- # that doesn't have the hashed_password. But because it's a subclass, it
- # would pass the validation and be returned as is.
- # By being a new field, no inheritance will be passed as is. A new model
- # will always be created.
- # TODO: remove when deprecating Pydantic v1
- self.secure_cloned_response_field: Optional[ModelField] = (
- create_cloned_field(self.response_field)
- )
else:
self.response_field = None # type: ignore
- self.secure_cloned_response_field = None
self.dependencies = list(dependencies or [])
self.description = description or inspect.cleandoc(self.endpoint.__doc__ or "")
# if a "form feed" character (page break) is found in the description text,
body_field=self.body_field,
status_code=self.status_code,
response_class=self.response_class,
- response_field=self.secure_cloned_response_field,
+ response_field=self.response_field,
response_model_include=self.response_model_include,
response_model_exclude=self.response_model_exclude,
response_model_by_alias=self.response_model_by_alias,
import re
import warnings
-from collections.abc import MutableMapping
from typing import (
TYPE_CHECKING,
Any,
Optional,
Union,
)
-from weakref import WeakKeyDictionary
import fastapi
from fastapi._compat import (
)
from fastapi.datastructures import DefaultPlaceholder, DefaultType
from fastapi.exceptions import FastAPIDeprecationWarning, PydanticV1NotSupportedError
-from pydantic import BaseModel
from pydantic.fields import FieldInfo
from typing_extensions import Literal
if TYPE_CHECKING: # pragma: nocover
from .routing import APIRoute
-# Cache for `create_cloned_field`
-_CLONED_TYPES_CACHE: MutableMapping[type[BaseModel], type[BaseModel]] = (
- WeakKeyDictionary()
-)
-
def is_body_allowed_for_status_code(status_code: Union[int, str, None]) -> bool:
if status_code is None:
) from None
-def create_cloned_field(
- field: ModelField,
- *,
- cloned_types: Optional[MutableMapping[type[BaseModel], type[BaseModel]]] = None,
-) -> ModelField:
- return field
-
-
def generate_operation_id_for_path(
*, name: str, path: str, method: str
) -> str: # pragma: nocover