Browse Source

formatting

pull/14186/head
svlandeg 9 months ago
parent
commit
90bd5683a7
  1. 8
      fastapi/_compat/__init__.py
  2. 32
      fastapi/_compat/main.py
  3. 74
      fastapi/_compat/may_v1.py
  4. 4
      fastapi/_compat/shared.py
  5. 2
      fastapi/_compat/v2.py
  6. 11
      fastapi/dependencies/utils.py
  7. 2
      fastapi/temp_pydantic_v1_params.py
  8. 5
      fastapi/utils.py
  9. 2
      tests/test_compat.py
  10. 1
      tests/test_get_model_definitions_formfeed_escape.py
  11. 1
      tests/test_response_model_as_return_annotation.py

8
fastapi/_compat/__init__.py

@ -30,6 +30,10 @@ from .main import serialize_sequence_value as serialize_sequence_value
from .main import (
with_info_plain_validator_function as with_info_plain_validator_function,
)
from .may_v1 import CoreSchema as CoreSchema
from .may_v1 import GetJsonSchemaHandler as GetJsonSchemaHandler
from .may_v1 import JsonSchemaValue as JsonSchemaValue
from .may_v1 import _normalize_errors as _normalize_errors
from .model_field import ModelField as ModelField
from .shared import PYDANTIC_V2 as PYDANTIC_V2
from .shared import PYDANTIC_VERSION_MINOR_TUPLE as PYDANTIC_VERSION_MINOR_TUPLE
@ -44,7 +48,3 @@ from .shared import (
from .shared import lenient_issubclass as lenient_issubclass
from .shared import sequence_types as sequence_types
from .shared import value_is_sequence as value_is_sequence
from .may_v1 import CoreSchema as CoreSchema
from .may_v1 import GetJsonSchemaHandler as GetJsonSchemaHandler
from .may_v1 import JsonSchemaValue as JsonSchemaValue
from .may_v1 import _normalize_errors as _normalize_errors

32
fastapi/_compat/main.py

@ -52,6 +52,7 @@ else:
def get_cached_model_fields(model: Type[BaseModel]) -> List[ModelField]:
if lenient_issubclass(model, may_v1.BaseModel):
from fastapi._compat import v1
return v1.get_model_fields(model)
else:
from . import v2
@ -61,7 +62,6 @@ def get_cached_model_fields(model: Type[BaseModel]) -> List[ModelField]:
def _is_undefined(value: object) -> bool:
if isinstance(value, may_v1.UndefinedType):
from fastapi._compat import v1
return True
elif PYDANTIC_V2:
from . import v2
@ -73,6 +73,7 @@ def _is_undefined(value: object) -> bool:
def _get_model_config(model: BaseModel) -> Any:
if isinstance(model, may_v1.BaseModel):
from fastapi._compat import v1
return v1._get_model_config(model)
elif PYDANTIC_V2:
from . import v2
@ -85,6 +86,7 @@ def _model_dump(
) -> Any:
if isinstance(model, may_v1.BaseModel):
from fastapi._compat import v1
return v1._model_dump(model, mode=mode, **kwargs)
elif PYDANTIC_V2:
from . import v2
@ -105,6 +107,7 @@ def _is_error_wrapper(exc: Exception) -> bool:
def copy_field_info(*, field_info: FieldInfo, annotation: Any) -> FieldInfo:
if isinstance(field_info, may_v1.FieldInfo):
from fastapi._compat import v1
return v1.copy_field_info(field_info=field_info, annotation=annotation)
else:
assert PYDANTIC_V2
@ -118,6 +121,7 @@ def create_body_model(
) -> Type[BaseModel]:
if fields and isinstance(fields[0], may_v1.ModelField):
from fastapi._compat import v1
return v1.create_body_model(fields=fields, model_name=model_name)
else:
assert PYDANTIC_V2
@ -131,6 +135,7 @@ def get_annotation_from_field_info(
) -> Any:
if isinstance(field_info, may_v1.FieldInfo):
from fastapi._compat import v1
return v1.get_annotation_from_field_info(
annotation=annotation, field_info=field_info, field_name=field_name
)
@ -146,6 +151,7 @@ def get_annotation_from_field_info(
def is_bytes_field(field: ModelField) -> bool:
if isinstance(field, may_v1.ModelField):
from fastapi._compat import v1
return v1.is_bytes_field(field)
else:
assert PYDANTIC_V2
@ -157,6 +163,7 @@ def is_bytes_field(field: ModelField) -> bool:
def is_bytes_sequence_field(field: ModelField) -> bool:
if isinstance(field, may_v1.ModelField):
from fastapi._compat import v1
return v1.is_bytes_sequence_field(field)
else:
assert PYDANTIC_V2
@ -168,6 +175,7 @@ def is_bytes_sequence_field(field: ModelField) -> bool:
def is_scalar_field(field: ModelField) -> bool:
if isinstance(field, may_v1.ModelField):
from fastapi._compat import v1
return v1.is_scalar_field(field)
else:
assert PYDANTIC_V2
@ -179,6 +187,7 @@ def is_scalar_field(field: ModelField) -> bool:
def is_scalar_sequence_field(field: ModelField) -> bool:
if isinstance(field, may_v1.ModelField):
from fastapi._compat import v1
return v1.is_scalar_sequence_field(field)
else:
assert PYDANTIC_V2
@ -190,6 +199,7 @@ def is_scalar_sequence_field(field: ModelField) -> bool:
def is_sequence_field(field: ModelField) -> bool:
if isinstance(field, may_v1.ModelField):
from fastapi._compat import v1
return v1.is_sequence_field(field)
else:
assert PYDANTIC_V2
@ -201,6 +211,7 @@ def is_sequence_field(field: ModelField) -> bool:
def serialize_sequence_value(*, field: ModelField, value: Any) -> Sequence[Any]:
if isinstance(field, may_v1.ModelField):
from fastapi._compat import v1
return v1.serialize_sequence_value(field=field, value=value)
else:
assert PYDANTIC_V2
@ -212,6 +223,7 @@ def serialize_sequence_value(*, field: ModelField, value: Any) -> Sequence[Any]:
def _model_rebuild(model: Type[BaseModel]) -> None:
if lenient_issubclass(model, may_v1.BaseModel):
from fastapi._compat import v1
v1._model_rebuild(model)
elif PYDANTIC_V2:
from . import v2
@ -220,10 +232,15 @@ def _model_rebuild(model: Type[BaseModel]) -> None:
def get_compat_model_name_map(fields: List[ModelField]) -> ModelNameMap:
v1_model_fields = [field for field in fields if isinstance(field, may_v1.ModelField)]
v1_model_fields = [
field for field in fields if isinstance(field, may_v1.ModelField)
]
if len(v1_model_fields) > 0:
from fastapi._compat import v1
v1_flat_models = v1.get_flat_models_from_fields(v1_model_fields, known_models=set()) # type: ignore[attr-defined]
v1_flat_models = v1.get_flat_models_from_fields(
v1_model_fields, known_models=set()
) # type: ignore[attr-defined]
all_flat_models = v1_flat_models
else:
all_flat_models = set()
@ -241,6 +258,7 @@ def get_compat_model_name_map(fields: List[ModelField]) -> ModelNameMap:
model_name_map = v2.get_model_name_map(all_flat_models)
return model_name_map
from fastapi._compat import v1
model_name_map = v1.get_model_name_map(all_flat_models)
return model_name_map
@ -251,7 +269,10 @@ def get_definitions(
model_name_map: ModelNameMap,
separate_input_output_schemas: bool = True,
) -> Tuple[
Dict[Tuple[ModelField, Literal["validation", "serialization"]], may_v1.JsonSchemaValue],
Dict[
Tuple[ModelField, Literal["validation", "serialization"]],
may_v1.JsonSchemaValue,
],
Dict[str, Dict[str, Any]],
]:
v1_fields = [field for field in fields if isinstance(field, may_v1.ModelField)]
@ -281,7 +302,8 @@ def get_schema_from_model_field(
field: ModelField,
model_name_map: ModelNameMap,
field_mapping: Dict[
Tuple[ModelField, Literal["validation", "serialization"]], v1.JsonSchemaValue
Tuple[ModelField, Literal["validation", "serialization"]],
may_v1.JsonSchemaValue,
],
separate_input_output_schemas: bool = True,
) -> Dict[str, Any]:

74
fastapi/_compat/may_v1.py

@ -1,104 +1,88 @@
import sys
from typing import Any, Dict, List, Literal, Sequence, Tuple, Union
from fastapi.types import ModelNameMap
from fastapi.types import ModelNameMap
if sys.version_info >= (3, 14):
class BaseConfig():
pass
class FieldInfo():
class BaseConfig:
pass
class BaseModel():
class FieldInfo:
pass
class UndefinedType():
class BaseModel:
pass
class ErrorWrapper():
class UndefinedType:
pass
class ModelField():
class ErrorWrapper:
pass
class JsonSchemaValue():
class ModelField:
pass
class Color():
class JsonSchemaValue:
pass
class NameEmail():
class Color:
pass
class SecretBytes():
class NameEmail:
pass
class SecretStr():
class SecretBytes:
pass
class AnyUrl():
class SecretStr:
pass
class Url():
class AnyUrl:
pass
class CoreSchema():
class Url:
pass
class GetJsonSchemaHandler():
class CoreSchema:
pass
class JsonSchemaValue():
class GetJsonSchemaHandler:
pass
class Undefined():
class Undefined:
pass
class RequiredParam():
class RequiredParam:
pass
def get_definitions(
*,
fields: List[ModelField],
model_name_map: ModelNameMap,
separate_input_output_schemas: bool = True,
*,
fields: List[ModelField],
model_name_map: ModelNameMap,
separate_input_output_schemas: bool = True,
) -> Tuple[
Dict[Tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue],
Dict[
Tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue
],
Dict[str, Dict[str, Any]],
]:
return {}, {}
def _regenerate_error_with_loc(
*, errors: Sequence[Any], loc_prefix: Tuple[Union[str, int], ...]
*, errors: Sequence[Any], loc_prefix: Tuple[Union[str, int], ...]
) -> List[Dict[str, Any]]:
return []
def _normalize_errors(errors: Sequence[Any]) -> List[Dict[str, Any]]:
return []
else:
from fastapi._compat import v1
from .v1 import BaseConfig as BaseConfig # type: ignore[assignment]
from .v1 import FieldInfo as FieldInfo
from .v1 import BaseModel
from .v1 import UndefinedType as UndefinedType
from .v1 import ErrorWrapper
from .v1 import ModelField
from .v1 import JsonSchemaValue
from .v1 import Color
from .v1 import NameEmail
from .v1 import SecretBytes
from .v1 import SecretStr
from .v1 import AnyUrl
from .v1 import Url
from .v1 import get_definitions
from .v1 import _regenerate_error_with_loc
from .v1 import CoreSchema as CoreSchema
from .v1 import FieldInfo as FieldInfo
from .v1 import GetJsonSchemaHandler as GetJsonSchemaHandler
from .v1 import JsonSchemaValue as JsonSchemaValue
from .v1 import ModelField
from .v1 import UndefinedType as UndefinedType
from .v1 import _normalize_errors as _normalize_errors
from .v1 import Undefined
from .v1 import RequiredParam

4
fastapi/_compat/shared.py

@ -98,7 +98,9 @@ def value_is_sequence(value: Any) -> bool:
def _annotation_is_complex(annotation: Union[Type[Any], None]) -> bool:
return (
lenient_issubclass(annotation, (BaseModel, may_v1.BaseModel, Mapping, UploadFile))
lenient_issubclass(
annotation, (BaseModel, may_v1.BaseModel, Mapping, UploadFile)
)
or _annotation_is_sequence(annotation)
or is_dataclass(annotation)
)

2
fastapi/_compat/v2.py

@ -15,7 +15,7 @@ from typing import (
cast,
)
from fastapi._compat import shared, may_v1
from fastapi._compat import may_v1, shared
from fastapi.openapi.constants import REF_TEMPLATE
from fastapi.types import IncEx, ModelNameMap
from pydantic import BaseModel, TypeAdapter, create_model

11
fastapi/dependencies/utils.py

@ -43,9 +43,9 @@ from fastapi._compat import (
is_uploadfile_or_nonable_uploadfile_annotation,
is_uploadfile_sequence_annotation,
lenient_issubclass,
may_v1,
sequence_types,
serialize_sequence_value,
may_v1,
value_is_sequence,
)
from fastapi._compat.shared import annotation_is_pydantic_v1
@ -397,9 +397,9 @@ def analyze_param(
)
]
if fastapi_specific_annotations:
fastapi_annotation: Union[FieldInfo, may_v1.FieldInfo, params.Depends, None] = (
fastapi_specific_annotations[-1]
)
fastapi_annotation: Union[
FieldInfo, may_v1.FieldInfo, params.Depends, None
] = fastapi_specific_annotations[-1]
else:
fastapi_annotation = None
# Set default for Annotated FieldInfo
@ -524,7 +524,8 @@ def analyze_param(
type_=use_annotation_from_field_info,
default=field_info.default,
alias=alias,
required=field_info.default in (RequiredParam, may_v1.RequiredParam, Undefined),
required=field_info.default
in (RequiredParam, may_v1.RequiredParam, Undefined),
field_info=field_info,
)
if is_path_param:

2
fastapi/temp_pydantic_v1_params.py

@ -5,8 +5,8 @@ from fastapi.openapi.models import Example
from fastapi.params import ParamTypes
from typing_extensions import Annotated, deprecated
from ._compat.shared import PYDANTIC_VERSION_MINOR_TUPLE
from ._compat.may_v1 import FieldInfo, Undefined
from ._compat.shared import PYDANTIC_VERSION_MINOR_TUPLE
_Unset: Any = Undefined

5
fastapi/utils.py

@ -25,7 +25,7 @@ from fastapi._compat import (
Validator,
annotation_is_pydantic_v1,
lenient_issubclass,
may_v1
may_v1,
)
from fastapi.datastructures import DefaultPlaceholder, DefaultType
from pydantic import BaseModel
@ -106,6 +106,7 @@ def create_model_field(
or version == "1"
):
from fastapi._compat import v1
try:
return v1.ModelField(**v1_kwargs) # type: ignore[no-any-return]
except RuntimeError:
@ -124,6 +125,7 @@ def create_model_field(
# Pydantic v2 is not installed, but it's not a Pydantic v1 ModelField, it could be
# a Pydantic v1 type, like a constrained int
from fastapi._compat import v1
try:
return v1.ModelField(**v1_kwargs) # type: ignore[no-any-return]
except RuntimeError:
@ -142,6 +144,7 @@ def create_cloned_field(
return field
from fastapi._compat import v1
# cloned_types caches already cloned types to support recursive models and improve
# performance by avoiding unnecessary cloning
if cloned_types is None:

2
tests/test_compat.py

@ -139,6 +139,7 @@ def test_is_uploadfile_sequence_annotation():
@needs_py_lt_314
def test_is_pv1_scalar_field():
from fastapi._compat import v1
# For coverage
class Model(v1.BaseModel):
foo: Union[str, Dict[str, Any]]
@ -150,6 +151,7 @@ def test_is_pv1_scalar_field():
@needs_py_lt_314
def test_get_model_fields_cached():
from fastapi._compat import v1
class Model(may_v1.BaseModel):
foo: str

1
tests/test_get_model_definitions_formfeed_escape.py

@ -165,6 +165,7 @@ def test_model_description_escaped_with_formfeed(sort_reversed: bool):
Test `get_model_definitions` with models passed in different order.
"""
from fastapi._compat import v1
all_fields = fastapi.openapi.utils.get_fields_from_routes(app.routes)
flat_models = v1.get_flat_models_from_fields(all_fields, known_models=set())

1
tests/test_response_model_as_return_annotation.py

@ -515,6 +515,7 @@ def test_invalid_response_model_field():
@needs_pydanticv1
def test_invalid_response_model_field_pv1():
from fastapi._compat import v1
app = FastAPI()
class Model(v1.BaseModel):

Loading…
Cancel
Save