Browse Source

️ Format and add types

pull/14168/head
Sebastián Ramírez 10 months ago
parent
commit
9e652f3644
  1. 20
      fastapi/_compat/main.py
  2. 6
      fastapi/_compat/shared.py
  3. 97
      fastapi/_compat/v1.py
  4. 29
      fastapi/_compat/v2.py
  5. 4
      fastapi/encoders.py
  6. 4
      fastapi/utils.py

20
fastapi/_compat/main.py

@ -31,24 +31,26 @@ if PYDANTIC_V2:
with_info_plain_validator_function as with_info_plain_validator_function, with_info_plain_validator_function as with_info_plain_validator_function,
) )
else: else:
from .v1 import BaseConfig as BaseConfig from .v1 import BaseConfig as BaseConfig # type: ignore[assignment]
from .v1 import FieldInfo as FieldInfo from .v1 import FieldInfo as FieldInfo
from .v1 import PydanticSchemaGenerationError as PydanticSchemaGenerationError from .v1 import ( # type: ignore[assignment]
PydanticSchemaGenerationError as PydanticSchemaGenerationError,
)
from .v1 import RequiredParam as RequiredParam from .v1 import RequiredParam as RequiredParam
from .v1 import Undefined as Undefined from .v1 import Undefined as Undefined
from .v1 import UndefinedType as UndefinedType from .v1 import UndefinedType as UndefinedType
from .v1 import Url as Url from .v1 import Url as Url # type: ignore[attr-defined, no-redef]
from .v1 import Validator as Validator from .v1 import Validator as Validator
from .v1 import evaluate_forwardref as evaluate_forwardref from .v1 import evaluate_forwardref as evaluate_forwardref
from .v1 import get_missing_field_error as get_missing_field_error from .v1 import get_missing_field_error as get_missing_field_error
from .v1 import ( from .v1 import ( # type: ignore[assignment]
with_info_plain_validator_function as with_info_plain_validator_function, with_info_plain_validator_function as with_info_plain_validator_function,
) )
@lru_cache @lru_cache
def get_cached_model_fields(model: Type[BaseModel]) -> List[ModelField]: def get_cached_model_fields(model: Type[BaseModel]) -> List[ModelField]:
if lenient_issubclass(model, v1.BaseModel): # type: ignore[attr-defined] if lenient_issubclass(model, v1.BaseModel):
return v1.get_model_fields(model) return v1.get_model_fields(model)
else: else:
from . import v2 from . import v2
@ -67,7 +69,7 @@ def _is_undefined(value: object) -> bool:
def _get_model_config(model: BaseModel) -> Any: def _get_model_config(model: BaseModel) -> Any:
if isinstance(model, v1.BaseModel): # type: ignore[attr-defined] if isinstance(model, v1.BaseModel):
return v1._get_model_config(model) return v1._get_model_config(model)
elif PYDANTIC_V2: elif PYDANTIC_V2:
from . import v2 from . import v2
@ -78,7 +80,7 @@ def _get_model_config(model: BaseModel) -> Any:
def _model_dump( def _model_dump(
model: BaseModel, mode: Literal["json", "python"] = "json", **kwargs: Any model: BaseModel, mode: Literal["json", "python"] = "json", **kwargs: Any
) -> Any: ) -> Any:
if isinstance(model, v1.BaseModel): # type: ignore[attr-defined] if isinstance(model, v1.BaseModel):
return v1._model_dump(model, mode=mode, **kwargs) return v1._model_dump(model, mode=mode, **kwargs)
elif PYDANTIC_V2: elif PYDANTIC_V2:
from . import v2 from . import v2
@ -195,7 +197,7 @@ def serialize_sequence_value(*, field: ModelField, value: Any) -> Sequence[Any]:
def _model_rebuild(model: Type[BaseModel]) -> None: def _model_rebuild(model: Type[BaseModel]) -> None:
if lenient_issubclass(model, v1.BaseModel): # type: ignore[attr-defined] if lenient_issubclass(model, v1.BaseModel):
v1._model_rebuild(model) v1._model_rebuild(model)
elif PYDANTIC_V2: elif PYDANTIC_V2:
from . import v2 from . import v2
@ -295,7 +297,7 @@ def _is_model_field(value: Any) -> bool:
def _is_model_class(value: Any) -> bool: def _is_model_class(value: Any) -> bool:
if lenient_issubclass(value, v1.BaseModel): # type: ignore[attr-defined] if lenient_issubclass(value, v1.BaseModel):
return True return True
elif PYDANTIC_V2: elif PYDANTIC_V2:
from . import v2 from . import v2

6
fastapi/_compat/shared.py

@ -98,7 +98,7 @@ def value_is_sequence(value: Any) -> bool:
def _annotation_is_complex(annotation: Union[Type[Any], None]) -> bool: def _annotation_is_complex(annotation: Union[Type[Any], None]) -> bool:
return ( return (
lenient_issubclass(annotation, (BaseModel, v1.BaseModel, Mapping, UploadFile)) # type: ignore[attr-defined] lenient_issubclass(annotation, (BaseModel, v1.BaseModel, Mapping, UploadFile))
or _annotation_is_sequence(annotation) or _annotation_is_sequence(annotation)
or is_dataclass(annotation) or is_dataclass(annotation)
) )
@ -195,12 +195,12 @@ def is_uploadfile_sequence_annotation(annotation: Any) -> bool:
def annotation_is_pydantic_v1(annotation: Any) -> bool: def annotation_is_pydantic_v1(annotation: Any) -> bool:
if lenient_issubclass(annotation, v1.BaseModel): # type: ignore[attr-defined] if lenient_issubclass(annotation, v1.BaseModel):
return True return True
origin = get_origin(annotation) origin = get_origin(annotation)
if origin is Union or origin is UnionType: if origin is Union or origin is UnionType:
for arg in get_args(annotation): for arg in get_args(annotation):
if lenient_issubclass(arg, v1.BaseModel): # type: ignore[attr-defined] if lenient_issubclass(arg, v1.BaseModel):
return True return True
if field_annotation_is_sequence(annotation): if field_annotation_is_sequence(annotation):
for sub_annotation in get_args(annotation): for sub_annotation in get_args(annotation):

97
fastapi/_compat/v1.py

@ -26,19 +26,13 @@ PYDANTIC_V2 = PYDANTIC_VERSION_MINOR_TUPLE[0] == 2
RequiredParam: Any = Ellipsis RequiredParam: Any = Ellipsis
if not PYDANTIC_V2: if not PYDANTIC_V2:
from pydantic import AnyUrl as Url # noqa: F401 from pydantic import BaseConfig as BaseConfig
from pydantic import ( from pydantic import BaseModel as BaseModel
BaseConfig as BaseConfig, # noqa: F401 from pydantic import ValidationError as ValidationError
) from pydantic import create_model as create_model
from pydantic import BaseModel, create_model from pydantic.class_validators import Validator as Validator
from pydantic import ValidationError as ValidationError # noqa: F401 from pydantic.color import Color as Color
from pydantic.class_validators import ( from pydantic.error_wrappers import ErrorWrapper as ErrorWrapper
Validator as Validator, # noqa: F401
)
from pydantic.color import Color as Color # noqa: F401
from pydantic.error_wrappers import (
ErrorWrapper as ErrorWrapper, # noqa: F401
)
from pydantic.errors import MissingError from pydantic.errors import MissingError
from pydantic.fields import ( # type: ignore[attr-defined] from pydantic.fields import ( # type: ignore[attr-defined]
SHAPE_FROZENSET, SHAPE_FROZENSET,
@ -52,11 +46,11 @@ if not PYDANTIC_V2:
from pydantic.fields import FieldInfo as FieldInfo from pydantic.fields import FieldInfo as FieldInfo
from pydantic.fields import ModelField as ModelField # type: ignore[attr-defined] from pydantic.fields import ModelField as ModelField # type: ignore[attr-defined]
from pydantic.fields import Undefined as Undefined # type: ignore[attr-defined] from pydantic.fields import Undefined as Undefined # type: ignore[attr-defined]
from pydantic.fields import ( from pydantic.fields import ( # type: ignore[attr-defined]
UndefinedType as UndefinedType, # type: ignore[attr-defined] # noqa: F401 UndefinedType as UndefinedType,
) )
from pydantic.networks import AnyUrl as AnyUrl # noqa: F401 from pydantic.networks import AnyUrl as AnyUrl
from pydantic.networks import NameEmail as NameEmail # noqa: F401 from pydantic.networks import NameEmail as NameEmail
from pydantic.schema import TypeModelSet as TypeModelSet from pydantic.schema import TypeModelSet as TypeModelSet
from pydantic.schema import ( from pydantic.schema import (
field_schema, field_schema,
@ -64,33 +58,26 @@ if not PYDANTIC_V2:
model_process_schema, model_process_schema,
) )
from pydantic.schema import ( from pydantic.schema import (
get_annotation_from_field_info as get_annotation_from_field_info, # noqa: F401 get_annotation_from_field_info as get_annotation_from_field_info,
) )
from pydantic.schema import get_flat_models_from_field as get_flat_models_from_field from pydantic.schema import get_flat_models_from_field as get_flat_models_from_field
from pydantic.schema import get_model_name_map as get_model_name_map # noqa: F401 from pydantic.schema import get_model_name_map as get_model_name_map
from pydantic.types import SecretBytes as SecretBytes # noqa: F401 from pydantic.types import SecretBytes as SecretBytes
from pydantic.types import SecretStr as SecretStr # noqa: F401 from pydantic.types import SecretStr as SecretStr
from pydantic.typing import evaluate_forwardref as evaluate_forwardref # noqa: F401 from pydantic.typing import evaluate_forwardref as evaluate_forwardref
from pydantic.utils import lenient_issubclass as lenient_issubclass # noqa: F401 from pydantic.utils import lenient_issubclass as lenient_issubclass
else: else:
from pydantic.v1 import AnyUrl as Url # noqa: F401 from pydantic.v1 import BaseConfig as BaseConfig # type: ignore[assignment]
from pydantic.v1 import ( from pydantic.v1 import BaseModel as BaseModel # type: ignore[assignment]
BaseConfig as BaseConfig, # type: ignore[assignment] # noqa: F401 from pydantic.v1 import ( # type: ignore[assignment]
) ValidationError as ValidationError,
from pydantic.v1 import (
BaseModel as BaseModel, # type: ignore[assignment] # noqa: F401
)
from pydantic.v1 import (
ValidationError as ValidationError, # type: ignore[assignment] # noqa: F401
) )
from pydantic.v1 import create_model as create_model # noqa: F401 from pydantic.v1 import create_model as create_model # type: ignore[no-redef]
from pydantic.v1.class_validators import Validator as Validator # noqa: F401 from pydantic.v1.class_validators import Validator as Validator
from pydantic.v1.color import ( from pydantic.v1.color import Color as Color # type: ignore[assignment]
Color as Color, # type: ignore[assignment] # noqa: F401 from pydantic.v1.error_wrappers import ErrorWrapper as ErrorWrapper
)
from pydantic.v1.error_wrappers import ErrorWrapper as ErrorWrapper # noqa: F401
from pydantic.v1.errors import MissingError from pydantic.v1.errors import MissingError
from pydantic.v1.fields import ( from pydantic.v1.fields import (
SHAPE_FROZENSET, SHAPE_FROZENSET,
@ -102,12 +89,12 @@ else:
SHAPE_TUPLE_ELLIPSIS, SHAPE_TUPLE_ELLIPSIS,
) )
from pydantic.v1.fields import FieldInfo as FieldInfo # type: ignore[assignment] from pydantic.v1.fields import FieldInfo as FieldInfo # type: ignore[assignment]
from pydantic.v1.fields import ModelField as ModelField # noqa: F401 from pydantic.v1.fields import ModelField as ModelField
from pydantic.v1.fields import Undefined as Undefined from pydantic.v1.fields import Undefined as Undefined
from pydantic.v1.fields import UndefinedType as UndefinedType # noqa: F401 from pydantic.v1.fields import UndefinedType as UndefinedType
from pydantic.v1.networks import AnyUrl as AnyUrl # noqa: F401 from pydantic.v1.networks import AnyUrl as AnyUrl
from pydantic.v1.networks import ( from pydantic.v1.networks import ( # type: ignore[assignment]
NameEmail as NameEmail, # type: ignore[assignment] # noqa: F401 NameEmail as NameEmail,
) )
from pydantic.v1.schema import TypeModelSet as TypeModelSet from pydantic.v1.schema import TypeModelSet as TypeModelSet
from pydantic.v1.schema import ( from pydantic.v1.schema import (
@ -116,30 +103,26 @@ else:
model_process_schema, model_process_schema,
) )
from pydantic.v1.schema import ( from pydantic.v1.schema import (
get_annotation_from_field_info as get_annotation_from_field_info, # noqa: F401 get_annotation_from_field_info as get_annotation_from_field_info,
)
from pydantic.v1.schema import (
get_flat_models_from_field as get_flat_models_from_field, # noqa: F401
) )
from pydantic.v1.schema import ( from pydantic.v1.schema import (
get_model_name_map as get_model_name_map, # noqa: F401 get_flat_models_from_field as get_flat_models_from_field,
) )
from pydantic.v1.types import ( from pydantic.v1.schema import get_model_name_map as get_model_name_map
SecretBytes as SecretBytes, # type: ignore[assignment] # noqa: F401 from pydantic.v1.types import ( # type: ignore[assignment]
SecretBytes as SecretBytes,
) )
from pydantic.v1.types import ( from pydantic.v1.types import ( # type: ignore[assignment]
SecretStr as SecretStr, # type: ignore[assignment] # noqa: F401 SecretStr as SecretStr,
) )
from pydantic.v1.typing import ( from pydantic.v1.typing import evaluate_forwardref as evaluate_forwardref
evaluate_forwardref as evaluate_forwardref, # noqa: F401 from pydantic.v1.utils import lenient_issubclass as lenient_issubclass
)
from pydantic.v1.utils import lenient_issubclass as lenient_issubclass # noqa: F401
GetJsonSchemaHandler = Any GetJsonSchemaHandler = Any
JsonSchemaValue = Dict[str, Any] JsonSchemaValue = Dict[str, Any]
CoreSchema = Any CoreSchema = Any
Url = AnyUrl
sequence_shapes = { sequence_shapes = {
SHAPE_LIST, SHAPE_LIST,

29
fastapi/_compat/v2.py

@ -27,7 +27,7 @@ from pydantic._internal._schema_generation_shared import ( # type: ignore[attr-
) )
from pydantic._internal._typing_extra import eval_type_lenient from pydantic._internal._typing_extra import eval_type_lenient
from pydantic._internal._utils import lenient_issubclass as lenient_issubclass from pydantic._internal._utils import lenient_issubclass as lenient_issubclass
from pydantic.fields import FieldInfo from pydantic.fields import FieldInfo as FieldInfo
from pydantic.json_schema import GenerateJsonSchema as GenerateJsonSchema from pydantic.json_schema import GenerateJsonSchema as GenerateJsonSchema
from pydantic.json_schema import JsonSchemaValue as JsonSchemaValue from pydantic.json_schema import JsonSchemaValue as JsonSchemaValue
from pydantic_core import CoreSchema as CoreSchema from pydantic_core import CoreSchema as CoreSchema
@ -196,7 +196,7 @@ def get_schema_from_model_field(
def get_definitions( def get_definitions(
*, *,
fields: List[ModelField], fields: Sequence[ModelField],
model_name_map: ModelNameMap, model_name_map: ModelNameMap,
separate_input_output_schemas: bool = True, separate_input_output_schemas: bool = True,
) -> Tuple[ ) -> Tuple[
@ -219,7 +219,7 @@ def get_definitions(
inputs = [ inputs = [
(field, override_mode or field.mode, field._type_adapter.core_schema) (field, override_mode or field.mode, field._type_adapter.core_schema)
for field in fields + list(unique_flat_model_fields) for field in list(fields) + list(unique_flat_model_fields)
] ]
field_mapping, definitions = schema_generator.generate_definitions(inputs=inputs) field_mapping, definitions = schema_generator.generate_definitions(inputs=inputs)
for item_def in cast(Dict[str, Dict[str, Any]], definitions).values(): for item_def in cast(Dict[str, Dict[str, Any]], definitions).values():
@ -277,25 +277,30 @@ def _remap_definitions_and_field_mappings(
field_mapping: Dict[ field_mapping: Dict[
Tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue Tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue
], ],
): ) -> Tuple[
Dict[Tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue],
Dict[str, Any],
]:
old_name_to_new_name_map = {} old_name_to_new_name_map = {}
for key, value in field_mapping.items(): for field_key, schema in field_mapping.items():
model = key[0].type_ model = field_key[0].type_
if model not in model_name_map: if model not in model_name_map:
continue continue
new_name = model_name_map[model] new_name = model_name_map[model]
old_name = value["$ref"].split("/")[-1] old_name = schema["$ref"].split("/")[-1]
if old_name in {f"{new_name}-Input", f"{new_name}-Output"}: if old_name in {f"{new_name}-Input", f"{new_name}-Output"}:
continue continue
old_name_to_new_name_map[old_name] = new_name old_name_to_new_name_map[old_name] = new_name
new_field_mapping = {} new_field_mapping: Dict[
for key, value in field_mapping.items(): Tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue
new_value = _replace_refs( ] = {}
schema=value, for field_key, schema in field_mapping.items():
new_schema = _replace_refs(
schema=schema,
old_name_to_new_name_map=old_name_to_new_name_map, old_name_to_new_name_map=old_name_to_new_name_map,
) )
new_field_mapping[key] = new_value new_field_mapping[field_key] = new_schema
new_definitions = {} new_definitions = {}
for key, value in definitions.items(): for key, value in definitions.items():

4
fastapi/encoders.py

@ -220,10 +220,10 @@ def jsonable_encoder(
include = set(include) include = set(include)
if exclude is not None and not isinstance(exclude, (set, dict)): if exclude is not None and not isinstance(exclude, (set, dict)):
exclude = set(exclude) exclude = set(exclude)
if isinstance(obj, (BaseModel, v1.BaseModel)): # type: ignore[attr-defined] if isinstance(obj, (BaseModel, v1.BaseModel)):
# TODO: remove when deprecating Pydantic v1 # TODO: remove when deprecating Pydantic v1
encoders: Dict[Any, Any] = {} encoders: Dict[Any, Any] = {}
if isinstance(obj, v1.BaseModel): # type: ignore[attr-defined] if isinstance(obj, v1.BaseModel):
encoders = getattr(obj.__config__, "json_encoders", {}) # type: ignore[attr-defined] encoders = getattr(obj.__config__, "json_encoders", {}) # type: ignore[attr-defined]
if custom_encoder: if custom_encoder:
encoders = {**encoders, **custom_encoder} encoders = {**encoders, **custom_encoder}

4
fastapi/utils.py

@ -144,10 +144,10 @@ def create_cloned_field(
original_type = original_type.__pydantic_model__ original_type = original_type.__pydantic_model__
use_type = original_type use_type = original_type
if lenient_issubclass(original_type, v1.BaseModel): if lenient_issubclass(original_type, v1.BaseModel):
original_type = cast(Type[v1.BaseModel], original_type) # type: ignore[name-defined] original_type = cast(Type[v1.BaseModel], original_type)
use_type = cloned_types.get(original_type) use_type = cloned_types.get(original_type)
if use_type is None: if use_type is None:
use_type = v1.create_model(original_type.__name__, __base__=original_type) # type: ignore[attr-defined] use_type = v1.create_model(original_type.__name__, __base__=original_type)
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(

Loading…
Cancel
Save