Browse Source

♻️ Refactor and simplify function indirection through utils

pull/14862/head
Sebastián Ramírez 5 months ago
parent
commit
aeb2d20ade
  1. 12
      fastapi/_compat/__init__.py
  2. 16
      fastapi/_compat/v2.py
  3. 21
      fastapi/dependencies/utils.py

12
fastapi/_compat/__init__.py

@ -1,6 +1,14 @@
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 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 (
field_annotation_is_scalar_sequence as field_annotation_is_scalar_sequence,
)
from .shared import field_annotation_is_sequence as field_annotation_is_sequence
from .shared import (
is_bytes_or_nonable_bytes_annotation as is_bytes_or_nonable_bytes_annotation,
)
from .shared import is_bytes_sequence_annotation as is_bytes_sequence_annotation
from .shared import is_pydantic_v1_model_instance as is_pydantic_v1_model_instance from .shared import is_pydantic_v1_model_instance as is_pydantic_v1_model_instance
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,
@ -25,11 +33,7 @@ from .v2 import get_flat_models_from_fields as get_flat_models_from_fields
from .v2 import get_missing_field_error as get_missing_field_error from .v2 import get_missing_field_error as get_missing_field_error
from .v2 import get_model_name_map as get_model_name_map from .v2 import get_model_name_map as get_model_name_map
from .v2 import get_schema_from_model_field as get_schema_from_model_field from .v2 import get_schema_from_model_field as get_schema_from_model_field
from .v2 import is_bytes_field as is_bytes_field
from .v2 import is_bytes_sequence_field as is_bytes_sequence_field
from .v2 import is_scalar_field as is_scalar_field from .v2 import is_scalar_field as is_scalar_field
from .v2 import is_scalar_sequence_field as is_scalar_sequence_field
from .v2 import is_sequence_field as is_sequence_field
from .v2 import serialize_sequence_value as serialize_sequence_value from .v2 import serialize_sequence_value as serialize_sequence_value
from .v2 import ( from .v2 import (
with_info_plain_validator_function as with_info_plain_validator_function, with_info_plain_validator_function as with_info_plain_validator_function,

16
fastapi/_compat/v2.py

@ -296,22 +296,6 @@ def is_scalar_field(field: ModelField) -> bool:
) and not isinstance(field.field_info, params.Body) ) and not isinstance(field.field_info, params.Body)
def is_sequence_field(field: ModelField) -> bool:
return shared.field_annotation_is_sequence(field.field_info.annotation)
def is_scalar_sequence_field(field: ModelField) -> bool:
return shared.field_annotation_is_scalar_sequence(field.field_info.annotation)
def is_bytes_field(field: ModelField) -> bool:
return shared.is_bytes_or_nonable_bytes_annotation(field.field_info.annotation)
def is_bytes_sequence_field(field: ModelField) -> bool:
return shared.is_bytes_sequence_annotation(field.field_info.annotation)
def copy_field_info(*, field_info: FieldInfo, annotation: Any) -> FieldInfo: def copy_field_info(*, field_info: FieldInfo, annotation: Any) -> FieldInfo:
cls = type(field_info) cls = type(field_info)
merged_field_info = cls.from_annotation(annotation) merged_field_info = cls.from_annotation(annotation)

21
fastapi/dependencies/utils.py

@ -25,13 +25,13 @@ from fastapi._compat import (
create_body_model, create_body_model,
evaluate_forwardref, evaluate_forwardref,
field_annotation_is_scalar, field_annotation_is_scalar,
field_annotation_is_scalar_sequence,
field_annotation_is_sequence,
get_cached_model_fields, get_cached_model_fields,
get_missing_field_error, get_missing_field_error,
is_bytes_field, is_bytes_or_nonable_bytes_annotation,
is_bytes_sequence_field, is_bytes_sequence_annotation,
is_scalar_field, is_scalar_field,
is_scalar_sequence_field,
is_sequence_field,
is_uploadfile_or_nonable_uploadfile_annotation, is_uploadfile_or_nonable_uploadfile_annotation,
is_uploadfile_sequence_annotation, is_uploadfile_sequence_annotation,
lenient_issubclass, lenient_issubclass,
@ -523,7 +523,7 @@ def analyze_param(
elif isinstance(field_info, params.Query): elif isinstance(field_info, params.Query):
assert ( assert (
is_scalar_field(field) is_scalar_field(field)
or is_scalar_sequence_field(field) or field_annotation_is_scalar_sequence(field.field_info.annotation)
or lenient_issubclass(field.field_info.annotation, BaseModel) or lenient_issubclass(field.field_info.annotation, BaseModel)
), f"Query parameter {param_name!r} must be one of the supported types" ), f"Query parameter {param_name!r} must be one of the supported types"
@ -727,7 +727,7 @@ def _get_multidict_value(
alias = alias or get_validation_alias(field) alias = alias or get_validation_alias(field)
if ( if (
(not _is_json_field(field)) (not _is_json_field(field))
and is_sequence_field(field) and field_annotation_is_sequence(field.field_info.annotation)
and isinstance(values, (ImmutableMultiDict, Headers)) and isinstance(values, (ImmutableMultiDict, Headers))
): ):
value = values.getlist(alias) value = values.getlist(alias)
@ -740,7 +740,10 @@ def _get_multidict_value(
and isinstance(value, str) # For type checks and isinstance(value, str) # For type checks
and value == "" and value == ""
) )
or (is_sequence_field(field) and len(value) == 0) or (
field_annotation_is_sequence(field.field_info.annotation)
and len(value) == 0
)
): ):
if field.field_info.is_required(): if field.field_info.is_required():
return return
@ -888,12 +891,12 @@ async def _extract_form_body(
field_info = field.field_info field_info = field.field_info
if ( if (
isinstance(field_info, params.File) isinstance(field_info, params.File)
and is_bytes_field(field) and is_bytes_or_nonable_bytes_annotation(field.field_info.annotation)
and isinstance(value, UploadFile) and isinstance(value, UploadFile)
): ):
value = await value.read() value = await value.read()
elif ( elif (
is_bytes_sequence_field(field) is_bytes_sequence_annotation(field.field_info.annotation)
and isinstance(field_info, params.File) and isinstance(field_info, params.File)
and value_is_sequence(value) and value_is_sequence(value)
): ):

Loading…
Cancel
Save