Browse Source

🎨 Tweak types and ignores for linting

pull/14575/head
Sebastián Ramírez 7 months ago
parent
commit
ab7c1544e0
  1. 13
      fastapi/_compat/main.py
  2. 2
      fastapi/_compat/may_v1.py
  3. 47
      fastapi/_compat/v1.py
  4. 7
      fastapi/dependencies/utils.py
  5. 4
      fastapi/encoders.py
  6. 2
      fastapi/openapi/models.py
  7. 4
      fastapi/routing.py
  8. 16
      fastapi/temp_pydantic_v1_params.py
  9. 4
      fastapi/utils.py

13
fastapi/_compat/main.py

@ -33,7 +33,7 @@ def get_cached_model_fields(model: type[BaseModel]) -> list[ModelField]:
if lenient_issubclass(model, may_v1.BaseModel): if lenient_issubclass(model, may_v1.BaseModel):
from fastapi._compat import v1 from fastapi._compat import v1
return v1.get_model_fields(model) return v1.get_model_fields(model) # type: ignore[arg-type,return-value]
else: else:
from . import v2 from . import v2
@ -166,7 +166,8 @@ def get_compat_model_name_map(fields: list[ModelField]) -> ModelNameMap:
from fastapi._compat import v1 from fastapi._compat import v1
v1_flat_models = v1.get_flat_models_from_fields( v1_flat_models = v1.get_flat_models_from_fields(
v1_model_fields, known_models=set() v1_model_fields, # type: ignore[arg-type]
known_models=set(),
) )
all_flat_models = v1_flat_models all_flat_models = v1_flat_models
else: else:
@ -174,9 +175,9 @@ def get_compat_model_name_map(fields: list[ModelField]) -> ModelNameMap:
v2_model_fields = [field for field in fields if isinstance(field, v2.ModelField)] v2_model_fields = [field for field in fields if isinstance(field, v2.ModelField)]
v2_flat_models = v2.get_flat_models_from_fields(v2_model_fields, known_models=set()) v2_flat_models = v2.get_flat_models_from_fields(v2_model_fields, known_models=set())
all_flat_models = all_flat_models.union(v2_flat_models) all_flat_models = all_flat_models.union(v2_flat_models) # type: ignore[arg-type]
model_name_map = v2.get_model_name_map(all_flat_models) model_name_map = v2.get_model_name_map(all_flat_models) # type: ignore[arg-type]
return model_name_map return model_name_map
@ -195,7 +196,7 @@ def get_definitions(
if sys.version_info < (3, 14): if sys.version_info < (3, 14):
v1_fields = [field for field in fields if isinstance(field, may_v1.ModelField)] v1_fields = [field for field in fields if isinstance(field, may_v1.ModelField)]
v1_field_maps, v1_definitions = may_v1.get_definitions( v1_field_maps, v1_definitions = may_v1.get_definitions(
fields=v1_fields, fields=v1_fields, # type: ignore[arg-type]
model_name_map=model_name_map, model_name_map=model_name_map,
separate_input_output_schemas=separate_input_output_schemas, separate_input_output_schemas=separate_input_output_schemas,
) )
@ -207,7 +208,7 @@ def get_definitions(
separate_input_output_schemas=separate_input_output_schemas, separate_input_output_schemas=separate_input_output_schemas,
) )
all_definitions = {**v1_definitions, **v2_definitions} all_definitions = {**v1_definitions, **v2_definitions}
all_field_maps = {**v1_field_maps, **v2_field_maps} all_field_maps = {**v1_field_maps, **v2_field_maps} # type: ignore[misc]
return all_field_maps, all_definitions return all_field_maps, all_definitions
# Pydantic v1 is not supported since Python 3.14 # Pydantic v1 is not supported since Python 3.14

2
fastapi/_compat/may_v1.py

@ -102,7 +102,7 @@ def _normalize_errors(errors: Sequence[Any]) -> list[dict[str, Any]]:
use_errors: list[Any] = [] use_errors: list[Any] = []
for error in errors: for error in errors:
if isinstance(error, ErrorWrapper): if isinstance(error, ErrorWrapper):
new_errors = ValidationError( # type: ignore[call-arg] new_errors = ValidationError(
errors=[error], model=RequestErrorModel errors=[error], model=RequestErrorModel
).errors() ).errors()
use_errors.extend(new_errors) use_errors.extend(new_errors)

47
fastapi/_compat/v1.py

@ -11,14 +11,12 @@ from typing import (
from fastapi._compat import shared from fastapi._compat import shared
from fastapi.openapi.constants import REF_PREFIX as REF_PREFIX from fastapi.openapi.constants import REF_PREFIX as REF_PREFIX
from fastapi.types import ModelNameMap from fastapi.types import ModelNameMap
from pydantic.v1 import BaseConfig as BaseConfig # type: ignore[assignment] from pydantic.v1 import BaseConfig as BaseConfig
from pydantic.v1 import BaseModel as BaseModel # type: ignore[assignment] from pydantic.v1 import BaseModel as BaseModel
from pydantic.v1 import ( # type: ignore[assignment] from pydantic.v1 import ValidationError as ValidationError
ValidationError as ValidationError, from pydantic.v1 import create_model as create_model
)
from pydantic.v1 import create_model as create_model # type: ignore[no-redef]
from pydantic.v1.class_validators import Validator as Validator from pydantic.v1.class_validators import Validator as Validator
from pydantic.v1.color import Color as Color # type: ignore[assignment] from pydantic.v1.color import Color as Color
from pydantic.v1.error_wrappers import ErrorWrapper as ErrorWrapper from pydantic.v1.error_wrappers import ErrorWrapper as ErrorWrapper
from pydantic.v1.fields import ( from pydantic.v1.fields import (
SHAPE_FROZENSET, SHAPE_FROZENSET,
@ -29,19 +27,14 @@ from pydantic.v1.fields import (
SHAPE_TUPLE, SHAPE_TUPLE,
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
from pydantic.v1.fields import ModelField as ModelField 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 from pydantic.v1.fields import UndefinedType as UndefinedType
from pydantic.v1.networks import AnyUrl as AnyUrl from pydantic.v1.networks import AnyUrl as AnyUrl
from pydantic.v1.networks import ( # type: ignore[assignment] from pydantic.v1.networks import NameEmail as NameEmail
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 field_schema, model_process_schema
field_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, get_annotation_from_field_info as get_annotation_from_field_info,
) )
@ -52,12 +45,8 @@ from pydantic.v1.schema import (
get_flat_models_from_fields as get_flat_models_from_fields, get_flat_models_from_fields as get_flat_models_from_fields,
) )
from pydantic.v1.schema import get_model_name_map as get_model_name_map from pydantic.v1.schema import get_model_name_map as get_model_name_map
from pydantic.v1.types import ( # type: ignore[assignment] from pydantic.v1.types import SecretBytes as SecretBytes
SecretBytes as SecretBytes, from pydantic.v1.types import SecretStr as SecretStr
)
from pydantic.v1.types import ( # type: ignore[assignment]
SecretStr as SecretStr,
)
from pydantic.v1.typing import evaluate_forwardref as evaluate_forwardref from pydantic.v1.typing import evaluate_forwardref as evaluate_forwardref
from pydantic.v1.utils import lenient_issubclass as lenient_issubclass from pydantic.v1.utils import lenient_issubclass as lenient_issubclass
from pydantic.version import VERSION as PYDANTIC_VERSION from pydantic.version import VERSION as PYDANTIC_VERSION
@ -163,7 +152,7 @@ def _model_dump(
def _get_model_config(model: BaseModel) -> Any: def _get_model_config(model: BaseModel) -> Any:
return model.__config__ # type: ignore[attr-defined] return model.__config__
def get_schema_from_model_field( def get_schema_from_model_field(
@ -175,8 +164,10 @@ def get_schema_from_model_field(
], ],
separate_input_output_schemas: bool = True, separate_input_output_schemas: bool = True,
) -> dict[str, Any]: ) -> dict[str, Any]:
return field_schema( # type: ignore[no-any-return] return field_schema(
field, model_name_map=model_name_map, ref_prefix=REF_PREFIX field,
model_name_map=model_name_map, # type: ignore[arg-type]
ref_prefix=REF_PREFIX,
)[0] )[0]
@ -195,7 +186,7 @@ def get_definitions(
dict[str, dict[str, Any]], dict[str, dict[str, Any]],
]: ]:
models = get_flat_models_from_fields(fields, known_models=set()) models = get_flat_models_from_fields(fields, known_models=set())
return {}, get_model_definitions(flat_models=models, model_name_map=model_name_map) return {}, get_model_definitions(flat_models=models, model_name_map=model_name_map) # type: ignore[arg-type]
def is_scalar_field(field: ModelField) -> bool: def is_scalar_field(field: ModelField) -> bool:
@ -207,7 +198,7 @@ def is_sequence_field(field: ModelField) -> bool:
def is_bytes_field(field: ModelField) -> bool: def is_bytes_field(field: ModelField) -> bool:
return lenient_issubclass(field.type_, bytes) # type: ignore[no-any-return] return lenient_issubclass(field.type_, bytes)
def is_bytes_sequence_field(field: ModelField) -> bool: def is_bytes_sequence_field(field: ModelField) -> bool:
@ -227,9 +218,9 @@ def create_body_model(
) -> type[BaseModel]: ) -> type[BaseModel]:
BodyModel = create_model(model_name) BodyModel = create_model(model_name)
for f in fields: for f in fields:
BodyModel.__fields__[f.name] = f # type: ignore[index] BodyModel.__fields__[f.name] = f
return BodyModel return BodyModel
def get_model_fields(model: type[BaseModel]) -> list[ModelField]: def get_model_fields(model: type[BaseModel]) -> list[ModelField]:
return list(model.__fields__.values()) # type: ignore[attr-defined] return list(model.__fields__.values())

7
fastapi/dependencies/utils.py

@ -409,7 +409,8 @@ def analyze_param(
if isinstance(fastapi_annotation, (FieldInfo, may_v1.FieldInfo)): if isinstance(fastapi_annotation, (FieldInfo, may_v1.FieldInfo)):
# Copy `field_info` because we mutate `field_info.default` below. # Copy `field_info` because we mutate `field_info.default` below.
field_info = copy_field_info( field_info = copy_field_info(
field_info=fastapi_annotation, annotation=use_annotation field_info=fastapi_annotation, # type: ignore[arg-type]
annotation=use_annotation,
) )
assert field_info.default in { assert field_info.default in {
Undefined, Undefined,
@ -443,7 +444,7 @@ def analyze_param(
"Cannot specify FastAPI annotations in `Annotated` and default value" "Cannot specify FastAPI annotations in `Annotated` and default value"
f" together for {param_name!r}" f" together for {param_name!r}"
) )
field_info = value field_info = value # type: ignore[assignment]
if isinstance(field_info, FieldInfo): if isinstance(field_info, FieldInfo):
field_info.annotation = type_annotation field_info.annotation = type_annotation
@ -483,7 +484,7 @@ def analyze_param(
field_info = params.File(annotation=use_annotation, default=default_value) field_info = params.File(annotation=use_annotation, default=default_value)
elif not field_annotation_is_scalar(annotation=type_annotation): elif not field_annotation_is_scalar(annotation=type_annotation):
if annotation_is_pydantic_v1(use_annotation): if annotation_is_pydantic_v1(use_annotation):
field_info = temp_pydantic_v1_params.Body( field_info = temp_pydantic_v1_params.Body( # type: ignore[assignment]
annotation=use_annotation, default=default_value annotation=use_annotation, default=default_value
) )
else: else:

4
fastapi/encoders.py

@ -228,11 +228,11 @@ def jsonable_encoder(
# TODO: remove when deprecating Pydantic v1 # TODO: remove when deprecating Pydantic v1
encoders: dict[Any, Any] = {} encoders: dict[Any, Any] = {}
if isinstance(obj, may_v1.BaseModel): if isinstance(obj, may_v1.BaseModel):
encoders = getattr(obj.__config__, "json_encoders", {}) # type: ignore[attr-defined] encoders = getattr(obj.__config__, "json_encoders", {})
if custom_encoder: if custom_encoder:
encoders = {**encoders, **custom_encoder} encoders = {**encoders, **custom_encoder}
obj_dict = _model_dump( obj_dict = _model_dump(
obj, obj, # type: ignore[arg-type]
mode="json", mode="json",
include=include, include=include,
exclude=exclude, exclude=exclude,

2
fastapi/openapi/models.py

@ -218,7 +218,7 @@ class Example(TypedDict, total=False):
value: Optional[Any] value: Optional[Any]
externalValue: Optional[AnyUrl] externalValue: Optional[AnyUrl]
__pydantic_config__ = {"extra": "allow"} __pydantic_config__ = {"extra": "allow"} # type: ignore[misc]
class ParameterInType(Enum): class ParameterInType(Enum):

4
fastapi/routing.py

@ -153,7 +153,7 @@ def _prepare_response_content(
exclude_none: bool = False, exclude_none: bool = False,
) -> Any: ) -> Any:
if isinstance(res, may_v1.BaseModel): if isinstance(res, may_v1.BaseModel):
read_with_orm_mode = getattr(_get_model_config(res), "read_with_orm_mode", None) read_with_orm_mode = getattr(_get_model_config(res), "read_with_orm_mode", None) # type: ignore[arg-type]
if read_with_orm_mode: if read_with_orm_mode:
# Let from_orm extract the data from this model instead of converting # Let from_orm extract the data from this model instead of converting
# it now to a dict. # it now to a dict.
@ -161,7 +161,7 @@ def _prepare_response_content(
# access instead of dict iteration, e.g. lazy relationships. # access instead of dict iteration, e.g. lazy relationships.
return res return res
return _model_dump( return _model_dump(
res, res, # type: ignore[arg-type]
by_alias=True, by_alias=True,
exclude_unset=exclude_unset, exclude_unset=exclude_unset,
exclude_defaults=exclude_defaults, exclude_defaults=exclude_defaults,

16
fastapi/temp_pydantic_v1_params.py

@ -10,7 +10,7 @@ from ._compat.may_v1 import FieldInfo, Undefined
_Unset: Any = Undefined _Unset: Any = Undefined
class Param(FieldInfo): # type: ignore[misc] class Param(FieldInfo):
in_: ParamTypes in_: ParamTypes
def __init__( def __init__(
@ -108,7 +108,7 @@ class Param(FieldInfo): # type: ignore[misc]
return f"{self.__class__.__name__}({self.default})" return f"{self.__class__.__name__}({self.default})"
class Path(Param): # type: ignore[misc] class Path(Param):
in_ = ParamTypes.path in_ = ParamTypes.path
def __init__( def __init__(
@ -194,7 +194,7 @@ class Path(Param): # type: ignore[misc]
) )
class Query(Param): # type: ignore[misc] class Query(Param):
in_ = ParamTypes.query in_ = ParamTypes.query
def __init__( def __init__(
@ -278,7 +278,7 @@ class Query(Param): # type: ignore[misc]
) )
class Header(Param): # type: ignore[misc] class Header(Param):
in_ = ParamTypes.header in_ = ParamTypes.header
def __init__( def __init__(
@ -364,7 +364,7 @@ class Header(Param): # type: ignore[misc]
) )
class Cookie(Param): # type: ignore[misc] class Cookie(Param):
in_ = ParamTypes.cookie in_ = ParamTypes.cookie
def __init__( def __init__(
@ -448,7 +448,7 @@ class Cookie(Param): # type: ignore[misc]
) )
class Body(FieldInfo): # type: ignore[misc] class Body(FieldInfo):
def __init__( def __init__(
self, self,
default: Any = Undefined, default: Any = Undefined,
@ -549,7 +549,7 @@ class Body(FieldInfo): # type: ignore[misc]
return f"{self.__class__.__name__}({self.default})" return f"{self.__class__.__name__}({self.default})"
class Form(Body): # type: ignore[misc] class Form(Body):
def __init__( def __init__(
self, self,
default: Any = Undefined, default: Any = Undefined,
@ -633,7 +633,7 @@ class Form(Body): # type: ignore[misc]
) )
class File(Form): # type: ignore[misc] class File(Form):
def __init__( def __init__(
self, self,
default: Any = Undefined, default: Any = Undefined,

4
fastapi/utils.py

@ -105,7 +105,7 @@ def create_model_field(
from fastapi._compat import v1 from fastapi._compat import v1
try: try:
return v1.ModelField(**v1_kwargs) # type: ignore[no-any-return] return v1.ModelField(**v1_kwargs) # type: ignore[return-value]
except RuntimeError: except RuntimeError:
raise fastapi.exceptions.FastAPIError( raise fastapi.exceptions.FastAPIError(
_invalid_args_message.format(type_=type_) _invalid_args_message.format(type_=type_)
@ -126,7 +126,7 @@ def create_model_field(
from fastapi._compat import v1 from fastapi._compat import v1
try: try:
return v1.ModelField(**v1_kwargs) # type: ignore[no-any-return] return v1.ModelField(**v1_kwargs)
except RuntimeError: except RuntimeError:
raise fastapi.exceptions.FastAPIError( raise fastapi.exceptions.FastAPIError(
_invalid_args_message.format(type_=type_) _invalid_args_message.format(type_=type_)

Loading…
Cancel
Save