mirror of https://github.com/tiangolo/fastapi.git
♻️ Upgrade internal syntax to Python 3.9+ 🎉 (#14564)
This commit is contained in:
parent
7f9709d75e
commit
1c4fc96c91
|
|
@ -1,4 +1,4 @@
|
|||
from typing import Annotated, List, Union
|
||||
from typing import Annotated, Union
|
||||
|
||||
from fastapi import FastAPI, Header
|
||||
|
||||
|
|
@ -6,5 +6,5 @@ app = FastAPI()
|
|||
|
||||
|
||||
@app.get("/items/")
|
||||
async def read_items(x_token: Annotated[Union[List[str], None], Header()] = None):
|
||||
async def read_items(x_token: Annotated[Union[list[str], None], Header()] = None):
|
||||
return {"X-Token values": x_token}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,8 @@
|
|||
import sys
|
||||
from collections.abc import Sequence
|
||||
from functools import lru_cache
|
||||
from typing import (
|
||||
Any,
|
||||
Dict,
|
||||
List,
|
||||
Sequence,
|
||||
Tuple,
|
||||
Type,
|
||||
)
|
||||
|
||||
from fastapi._compat import may_v1
|
||||
|
|
@ -50,7 +46,7 @@ else:
|
|||
|
||||
|
||||
@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, may_v1.BaseModel):
|
||||
from fastapi._compat import v1
|
||||
|
||||
|
|
@ -119,7 +115,7 @@ def copy_field_info(*, field_info: FieldInfo, annotation: Any) -> FieldInfo:
|
|||
|
||||
def create_body_model(
|
||||
*, fields: Sequence[ModelField], model_name: str
|
||||
) -> Type[BaseModel]:
|
||||
) -> type[BaseModel]:
|
||||
if fields and isinstance(fields[0], may_v1.ModelField):
|
||||
from fastapi._compat import v1
|
||||
|
||||
|
|
@ -221,7 +217,7 @@ def serialize_sequence_value(*, field: ModelField, value: Any) -> Sequence[Any]:
|
|||
return v2.serialize_sequence_value(field=field, value=value) # type: ignore[arg-type]
|
||||
|
||||
|
||||
def _model_rebuild(model: Type[BaseModel]) -> None:
|
||||
def _model_rebuild(model: type[BaseModel]) -> None:
|
||||
if lenient_issubclass(model, may_v1.BaseModel):
|
||||
from fastapi._compat import v1
|
||||
|
||||
|
|
@ -232,7 +228,7 @@ def _model_rebuild(model: Type[BaseModel]) -> None:
|
|||
v2._model_rebuild(model)
|
||||
|
||||
|
||||
def get_compat_model_name_map(fields: List[ModelField]) -> ModelNameMap:
|
||||
def get_compat_model_name_map(fields: list[ModelField]) -> ModelNameMap:
|
||||
v1_model_fields = [
|
||||
field for field in fields if isinstance(field, may_v1.ModelField)
|
||||
]
|
||||
|
|
@ -266,15 +262,15 @@ def get_compat_model_name_map(fields: List[ModelField]) -> ModelNameMap:
|
|||
|
||||
def get_definitions(
|
||||
*,
|
||||
fields: List[ModelField],
|
||||
fields: list[ModelField],
|
||||
model_name_map: ModelNameMap,
|
||||
separate_input_output_schemas: bool = True,
|
||||
) -> Tuple[
|
||||
Dict[
|
||||
Tuple[ModelField, Literal["validation", "serialization"]],
|
||||
) -> tuple[
|
||||
dict[
|
||||
tuple[ModelField, Literal["validation", "serialization"]],
|
||||
may_v1.JsonSchemaValue,
|
||||
],
|
||||
Dict[str, Dict[str, Any]],
|
||||
dict[str, dict[str, Any]],
|
||||
]:
|
||||
if sys.version_info < (3, 14):
|
||||
v1_fields = [field for field in fields if isinstance(field, may_v1.ModelField)]
|
||||
|
|
@ -315,12 +311,12 @@ def get_schema_from_model_field(
|
|||
*,
|
||||
field: ModelField,
|
||||
model_name_map: ModelNameMap,
|
||||
field_mapping: Dict[
|
||||
Tuple[ModelField, Literal["validation", "serialization"]],
|
||||
field_mapping: dict[
|
||||
tuple[ModelField, Literal["validation", "serialization"]],
|
||||
may_v1.JsonSchemaValue,
|
||||
],
|
||||
separate_input_output_schemas: bool = True,
|
||||
) -> Dict[str, Any]:
|
||||
) -> dict[str, Any]:
|
||||
if isinstance(field, may_v1.ModelField):
|
||||
from fastapi._compat import v1
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import sys
|
||||
from typing import Any, Dict, List, Literal, Sequence, Tuple, Type, Union
|
||||
from collections.abc import Sequence
|
||||
from typing import Any, Literal, Union
|
||||
|
||||
from fastapi.types import ModelNameMap
|
||||
|
||||
|
|
@ -60,14 +61,14 @@ if sys.version_info >= (3, 14):
|
|||
|
||||
def get_definitions(
|
||||
*,
|
||||
fields: List[ModelField],
|
||||
fields: list[ModelField],
|
||||
model_name_map: ModelNameMap,
|
||||
separate_input_output_schemas: bool = True,
|
||||
) -> Tuple[
|
||||
Dict[
|
||||
Tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue
|
||||
) -> tuple[
|
||||
dict[
|
||||
tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue
|
||||
],
|
||||
Dict[str, Dict[str, Any]],
|
||||
dict[str, dict[str, Any]],
|
||||
]:
|
||||
return {}, {} # pragma: no cover
|
||||
|
||||
|
|
@ -94,11 +95,11 @@ else:
|
|||
from .v1 import get_definitions as get_definitions
|
||||
|
||||
|
||||
RequestErrorModel: Type[BaseModel] = create_model("Request")
|
||||
RequestErrorModel: type[BaseModel] = create_model("Request")
|
||||
|
||||
|
||||
def _normalize_errors(errors: Sequence[Any]) -> List[Dict[str, Any]]:
|
||||
use_errors: List[Any] = []
|
||||
def _normalize_errors(errors: Sequence[Any]) -> list[dict[str, Any]]:
|
||||
use_errors: list[Any] = []
|
||||
for error in errors:
|
||||
if isinstance(error, ErrorWrapper):
|
||||
new_errors = ValidationError( # type: ignore[call-arg]
|
||||
|
|
@ -113,9 +114,9 @@ def _normalize_errors(errors: Sequence[Any]) -> List[Dict[str, Any]]:
|
|||
|
||||
|
||||
def _regenerate_error_with_loc(
|
||||
*, errors: Sequence[Any], loc_prefix: Tuple[Union[str, int], ...]
|
||||
) -> List[Dict[str, Any]]:
|
||||
updated_loc_errors: List[Any] = [
|
||||
*, errors: Sequence[Any], loc_prefix: tuple[Union[str, int], ...]
|
||||
) -> list[dict[str, Any]]:
|
||||
updated_loc_errors: list[Any] = [
|
||||
{**err, "loc": loc_prefix + err.get("loc", ())}
|
||||
for err in _normalize_errors(errors)
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,8 +1,5 @@
|
|||
from typing import (
|
||||
Any,
|
||||
Dict,
|
||||
List,
|
||||
Tuple,
|
||||
Union,
|
||||
)
|
||||
|
||||
|
|
@ -34,10 +31,10 @@ class ModelField(Protocol):
|
|||
def validate(
|
||||
self,
|
||||
value: Any,
|
||||
values: Dict[str, Any] = {}, # noqa: B006
|
||||
values: dict[str, Any] = {}, # noqa: B006
|
||||
*,
|
||||
loc: Tuple[Union[int, str], ...] = (),
|
||||
) -> Tuple[Any, Union[List[Dict[str, Any]], None]]: ...
|
||||
loc: tuple[Union[int, str], ...] = (),
|
||||
) -> tuple[Any, Union[list[dict[str, Any]], None]]: ...
|
||||
|
||||
def serialize(
|
||||
self,
|
||||
|
|
|
|||
|
|
@ -2,17 +2,11 @@ import sys
|
|||
import types
|
||||
import typing
|
||||
from collections import deque
|
||||
from collections.abc import Mapping, Sequence
|
||||
from dataclasses import is_dataclass
|
||||
from typing import (
|
||||
Annotated,
|
||||
Any,
|
||||
Deque,
|
||||
FrozenSet,
|
||||
List,
|
||||
Mapping,
|
||||
Sequence,
|
||||
Set,
|
||||
Tuple,
|
||||
Type,
|
||||
Union,
|
||||
)
|
||||
|
||||
|
|
@ -21,7 +15,7 @@ from fastapi.types import UnionType
|
|||
from pydantic import BaseModel
|
||||
from pydantic.version import VERSION as PYDANTIC_VERSION
|
||||
from starlette.datastructures import UploadFile
|
||||
from typing_extensions import Annotated, get_args, get_origin
|
||||
from typing_extensions import get_args, get_origin
|
||||
|
||||
# Copy from Pydantic v2, compatible with v1
|
||||
if sys.version_info < (3, 10):
|
||||
|
|
@ -39,26 +33,21 @@ PYDANTIC_V2 = PYDANTIC_VERSION_MINOR_TUPLE[0] == 2
|
|||
|
||||
sequence_annotation_to_type = {
|
||||
Sequence: list,
|
||||
List: list,
|
||||
list: list,
|
||||
Tuple: tuple,
|
||||
tuple: tuple,
|
||||
Set: set,
|
||||
set: set,
|
||||
FrozenSet: frozenset,
|
||||
frozenset: frozenset,
|
||||
Deque: deque,
|
||||
deque: deque,
|
||||
}
|
||||
|
||||
sequence_types = tuple(sequence_annotation_to_type.keys())
|
||||
|
||||
Url: Type[Any]
|
||||
Url: type[Any]
|
||||
|
||||
|
||||
# Copy of Pydantic v2, compatible with v1
|
||||
def lenient_issubclass(
|
||||
cls: Any, class_or_tuple: Union[Type[Any], Tuple[Type[Any], ...], None]
|
||||
cls: Any, class_or_tuple: Union[type[Any], tuple[type[Any], ...], None]
|
||||
) -> bool:
|
||||
try:
|
||||
return isinstance(cls, type) and issubclass(cls, class_or_tuple) # type: ignore[arg-type]
|
||||
|
|
@ -68,13 +57,13 @@ def lenient_issubclass(
|
|||
raise # pragma: no cover
|
||||
|
||||
|
||||
def _annotation_is_sequence(annotation: Union[Type[Any], None]) -> bool:
|
||||
def _annotation_is_sequence(annotation: Union[type[Any], None]) -> bool:
|
||||
if lenient_issubclass(annotation, (str, bytes)):
|
||||
return False
|
||||
return lenient_issubclass(annotation, sequence_types) # type: ignore[arg-type]
|
||||
return lenient_issubclass(annotation, sequence_types)
|
||||
|
||||
|
||||
def field_annotation_is_sequence(annotation: Union[Type[Any], None]) -> bool:
|
||||
def field_annotation_is_sequence(annotation: Union[type[Any], None]) -> bool:
|
||||
origin = get_origin(annotation)
|
||||
if origin is Union or origin is UnionType:
|
||||
for arg in get_args(annotation):
|
||||
|
|
@ -87,10 +76,10 @@ def field_annotation_is_sequence(annotation: Union[Type[Any], None]) -> bool:
|
|||
|
||||
|
||||
def value_is_sequence(value: Any) -> bool:
|
||||
return isinstance(value, sequence_types) and not isinstance(value, (str, bytes)) # type: ignore[arg-type]
|
||||
return isinstance(value, sequence_types) and not isinstance(value, (str, bytes))
|
||||
|
||||
|
||||
def _annotation_is_complex(annotation: Union[Type[Any], None]) -> bool:
|
||||
def _annotation_is_complex(annotation: Union[type[Any], None]) -> bool:
|
||||
return (
|
||||
lenient_issubclass(
|
||||
annotation, (BaseModel, may_v1.BaseModel, Mapping, UploadFile)
|
||||
|
|
@ -100,7 +89,7 @@ def _annotation_is_complex(annotation: Union[Type[Any], None]) -> bool:
|
|||
)
|
||||
|
||||
|
||||
def field_annotation_is_complex(annotation: Union[Type[Any], None]) -> bool:
|
||||
def field_annotation_is_complex(annotation: Union[type[Any], None]) -> bool:
|
||||
origin = get_origin(annotation)
|
||||
if origin is Union or origin is UnionType:
|
||||
return any(field_annotation_is_complex(arg) for arg in get_args(annotation))
|
||||
|
|
@ -121,7 +110,7 @@ def field_annotation_is_scalar(annotation: Any) -> bool:
|
|||
return annotation is Ellipsis or not field_annotation_is_complex(annotation)
|
||||
|
||||
|
||||
def field_annotation_is_scalar_sequence(annotation: Union[Type[Any], None]) -> bool:
|
||||
def field_annotation_is_scalar_sequence(annotation: Union[type[Any], None]) -> bool:
|
||||
origin = get_origin(annotation)
|
||||
if origin is Union or origin is UnionType:
|
||||
at_least_one_scalar_sequence = False
|
||||
|
|
|
|||
|
|
@ -1,15 +1,10 @@
|
|||
from collections.abc import Sequence
|
||||
from copy import copy
|
||||
from dataclasses import dataclass, is_dataclass
|
||||
from enum import Enum
|
||||
from typing import (
|
||||
Any,
|
||||
Callable,
|
||||
Dict,
|
||||
List,
|
||||
Sequence,
|
||||
Set,
|
||||
Tuple,
|
||||
Type,
|
||||
Union,
|
||||
)
|
||||
|
||||
|
|
@ -124,7 +119,7 @@ else:
|
|||
|
||||
|
||||
GetJsonSchemaHandler = Any
|
||||
JsonSchemaValue = Dict[str, Any]
|
||||
JsonSchemaValue = dict[str, Any]
|
||||
CoreSchema = Any
|
||||
Url = AnyUrl
|
||||
|
||||
|
|
@ -154,7 +149,7 @@ class PydanticSchemaGenerationError(Exception):
|
|||
pass
|
||||
|
||||
|
||||
RequestErrorModel: Type[BaseModel] = create_model("Request")
|
||||
RequestErrorModel: type[BaseModel] = create_model("Request")
|
||||
|
||||
|
||||
def with_info_plain_validator_function(
|
||||
|
|
@ -169,10 +164,10 @@ def with_info_plain_validator_function(
|
|||
|
||||
def get_model_definitions(
|
||||
*,
|
||||
flat_models: Set[Union[Type[BaseModel], Type[Enum]]],
|
||||
model_name_map: Dict[Union[Type[BaseModel], Type[Enum]], str],
|
||||
) -> Dict[str, Any]:
|
||||
definitions: Dict[str, Dict[str, Any]] = {}
|
||||
flat_models: set[Union[type[BaseModel], type[Enum]]],
|
||||
model_name_map: dict[Union[type[BaseModel], type[Enum]], str],
|
||||
) -> dict[str, Any]:
|
||||
definitions: dict[str, dict[str, Any]] = {}
|
||||
for model in flat_models:
|
||||
m_schema, m_definitions, m_nested_models = model_process_schema(
|
||||
model, model_name_map=model_name_map, ref_prefix=REF_PREFIX
|
||||
|
|
@ -219,7 +214,7 @@ def is_pv1_scalar_sequence_field(field: ModelField) -> bool:
|
|||
return False
|
||||
|
||||
|
||||
def _model_rebuild(model: Type[BaseModel]) -> None:
|
||||
def _model_rebuild(model: type[BaseModel]) -> None:
|
||||
model.update_forward_refs()
|
||||
|
||||
|
||||
|
|
@ -237,11 +232,11 @@ def get_schema_from_model_field(
|
|||
*,
|
||||
field: ModelField,
|
||||
model_name_map: ModelNameMap,
|
||||
field_mapping: Dict[
|
||||
Tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue
|
||||
field_mapping: dict[
|
||||
tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue
|
||||
],
|
||||
separate_input_output_schemas: bool = True,
|
||||
) -> Dict[str, Any]:
|
||||
) -> dict[str, Any]:
|
||||
return field_schema( # type: ignore[no-any-return]
|
||||
field, model_name_map=model_name_map, ref_prefix=REF_PREFIX
|
||||
)[0]
|
||||
|
|
@ -254,12 +249,12 @@ def get_schema_from_model_field(
|
|||
|
||||
def get_definitions(
|
||||
*,
|
||||
fields: List[ModelField],
|
||||
fields: list[ModelField],
|
||||
model_name_map: ModelNameMap,
|
||||
separate_input_output_schemas: bool = True,
|
||||
) -> Tuple[
|
||||
Dict[Tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue],
|
||||
Dict[str, Dict[str, Any]],
|
||||
) -> tuple[
|
||||
dict[tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue],
|
||||
dict[str, dict[str, Any]],
|
||||
]:
|
||||
models = get_flat_models_from_fields(fields, known_models=set())
|
||||
return {}, get_model_definitions(flat_models=models, model_name_map=model_name_map)
|
||||
|
|
@ -293,7 +288,7 @@ def serialize_sequence_value(*, field: ModelField, value: Any) -> Sequence[Any]:
|
|||
return sequence_shape_to_type[field.shape](value) # type: ignore[no-any-return]
|
||||
|
||||
|
||||
def get_missing_field_error(loc: Tuple[str, ...]) -> Dict[str, Any]:
|
||||
def get_missing_field_error(loc: tuple[str, ...]) -> dict[str, Any]:
|
||||
missing_field_error = ErrorWrapper(MissingError(), loc=loc)
|
||||
new_error = ValidationError([missing_field_error], RequestErrorModel)
|
||||
return new_error.errors()[0] # type: ignore[return-value]
|
||||
|
|
@ -301,12 +296,12 @@ def get_missing_field_error(loc: Tuple[str, ...]) -> Dict[str, Any]:
|
|||
|
||||
def create_body_model(
|
||||
*, fields: Sequence[ModelField], model_name: str
|
||||
) -> Type[BaseModel]:
|
||||
) -> type[BaseModel]:
|
||||
BodyModel = create_model(model_name)
|
||||
for f in fields:
|
||||
BodyModel.__fields__[f.name] = f # type: ignore[index]
|
||||
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]
|
||||
|
|
|
|||
|
|
@ -1,16 +1,12 @@
|
|||
import re
|
||||
import warnings
|
||||
from collections.abc import Sequence
|
||||
from copy import copy, deepcopy
|
||||
from dataclasses import dataclass, is_dataclass
|
||||
from enum import Enum
|
||||
from typing import (
|
||||
Annotated,
|
||||
Any,
|
||||
Dict,
|
||||
List,
|
||||
Sequence,
|
||||
Set,
|
||||
Tuple,
|
||||
Type,
|
||||
Union,
|
||||
cast,
|
||||
)
|
||||
|
|
@ -33,7 +29,7 @@ from pydantic.json_schema import JsonSchemaValue as JsonSchemaValue
|
|||
from pydantic_core import CoreSchema as CoreSchema
|
||||
from pydantic_core import PydanticUndefined, PydanticUndefinedType
|
||||
from pydantic_core import Url as Url
|
||||
from typing_extensions import Annotated, Literal, get_args, get_origin
|
||||
from typing_extensions import Literal, get_args, get_origin
|
||||
|
||||
try:
|
||||
from pydantic_core.core_schema import (
|
||||
|
|
@ -77,7 +73,7 @@ _Attrs = {
|
|||
|
||||
|
||||
# TODO: remove when dropping support for Pydantic < v2.12.3
|
||||
def asdict(field_info: FieldInfo) -> Dict[str, Any]:
|
||||
def asdict(field_info: FieldInfo) -> dict[str, Any]:
|
||||
attributes = {}
|
||||
for attr in _Attrs:
|
||||
value = getattr(field_info, attr, Undefined)
|
||||
|
|
@ -169,10 +165,10 @@ class ModelField:
|
|||
def validate(
|
||||
self,
|
||||
value: Any,
|
||||
values: Dict[str, Any] = {}, # noqa: B006
|
||||
values: dict[str, Any] = {}, # noqa: B006
|
||||
*,
|
||||
loc: Tuple[Union[int, str], ...] = (),
|
||||
) -> Tuple[Any, Union[List[Dict[str, Any]], None]]:
|
||||
loc: tuple[Union[int, str], ...] = (),
|
||||
) -> tuple[Any, Union[list[dict[str, Any]], None]]:
|
||||
try:
|
||||
return (
|
||||
self._type_adapter.validate_python(value, from_attributes=True),
|
||||
|
|
@ -220,7 +216,7 @@ def get_annotation_from_field_info(
|
|||
return annotation
|
||||
|
||||
|
||||
def _model_rebuild(model: Type[BaseModel]) -> None:
|
||||
def _model_rebuild(model: type[BaseModel]) -> None:
|
||||
model.model_rebuild()
|
||||
|
||||
|
||||
|
|
@ -245,11 +241,11 @@ def get_schema_from_model_field(
|
|||
*,
|
||||
field: ModelField,
|
||||
model_name_map: ModelNameMap,
|
||||
field_mapping: Dict[
|
||||
Tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue
|
||||
field_mapping: dict[
|
||||
tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue
|
||||
],
|
||||
separate_input_output_schemas: bool = True,
|
||||
) -> Dict[str, Any]:
|
||||
) -> dict[str, Any]:
|
||||
override_mode: Union[Literal["validation"], None] = (
|
||||
None
|
||||
if (separate_input_output_schemas or _has_computed_fields(field))
|
||||
|
|
@ -277,9 +273,9 @@ def get_definitions(
|
|||
fields: Sequence[ModelField],
|
||||
model_name_map: ModelNameMap,
|
||||
separate_input_output_schemas: bool = True,
|
||||
) -> Tuple[
|
||||
Dict[Tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue],
|
||||
Dict[str, Dict[str, Any]],
|
||||
) -> tuple[
|
||||
dict[tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue],
|
||||
dict[str, dict[str, Any]],
|
||||
]:
|
||||
schema_generator = GenerateJsonSchema(ref_template=REF_TEMPLATE)
|
||||
validation_fields = [field for field in fields if field.mode == "validation"]
|
||||
|
|
@ -324,7 +320,7 @@ def get_definitions(
|
|||
for field in list(fields) + list(unique_flat_model_fields)
|
||||
]
|
||||
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():
|
||||
if "description" in item_def:
|
||||
item_description = cast(str, item_def["description"]).split("\f")[0]
|
||||
item_def["description"] = item_description
|
||||
|
|
@ -338,9 +334,9 @@ def get_definitions(
|
|||
|
||||
def _replace_refs(
|
||||
*,
|
||||
schema: Dict[str, Any],
|
||||
old_name_to_new_name_map: Dict[str, str],
|
||||
) -> Dict[str, Any]:
|
||||
schema: dict[str, Any],
|
||||
old_name_to_new_name_map: dict[str, str],
|
||||
) -> dict[str, Any]:
|
||||
new_schema = deepcopy(schema)
|
||||
for key, value in new_schema.items():
|
||||
if key == "$ref":
|
||||
|
|
@ -375,13 +371,13 @@ def _replace_refs(
|
|||
def _remap_definitions_and_field_mappings(
|
||||
*,
|
||||
model_name_map: ModelNameMap,
|
||||
definitions: Dict[str, Any],
|
||||
field_mapping: Dict[
|
||||
Tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue
|
||||
definitions: dict[str, Any],
|
||||
field_mapping: dict[
|
||||
tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue
|
||||
],
|
||||
) -> Tuple[
|
||||
Dict[Tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue],
|
||||
Dict[str, Any],
|
||||
) -> tuple[
|
||||
dict[tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue],
|
||||
dict[str, Any],
|
||||
]:
|
||||
old_name_to_new_name_map = {}
|
||||
for field_key, schema in field_mapping.items():
|
||||
|
|
@ -394,8 +390,8 @@ def _remap_definitions_and_field_mappings(
|
|||
continue
|
||||
old_name_to_new_name_map[old_name] = new_name
|
||||
|
||||
new_field_mapping: Dict[
|
||||
Tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue
|
||||
new_field_mapping: dict[
|
||||
tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue
|
||||
] = {}
|
||||
for field_key, schema in field_mapping.items():
|
||||
new_schema = _replace_refs(
|
||||
|
|
@ -461,10 +457,10 @@ def serialize_sequence_value(*, field: ModelField, value: Any) -> Sequence[Any]:
|
|||
origin_type = get_origin(union_arg) or union_arg
|
||||
break
|
||||
assert issubclass(origin_type, shared.sequence_types) # type: ignore[arg-type]
|
||||
return shared.sequence_annotation_to_type[origin_type](value) # type: ignore[no-any-return]
|
||||
return shared.sequence_annotation_to_type[origin_type](value) # type: ignore[no-any-return,index]
|
||||
|
||||
|
||||
def get_missing_field_error(loc: Tuple[str, ...]) -> Dict[str, Any]:
|
||||
def get_missing_field_error(loc: tuple[str, ...]) -> dict[str, Any]:
|
||||
error = ValidationError.from_exception_data(
|
||||
"Field required", [{"type": "missing", "loc": loc, "input": {}}]
|
||||
).errors(include_url=False)[0]
|
||||
|
|
@ -474,14 +470,14 @@ def get_missing_field_error(loc: Tuple[str, ...]) -> Dict[str, Any]:
|
|||
|
||||
def create_body_model(
|
||||
*, fields: Sequence[ModelField], model_name: str
|
||||
) -> Type[BaseModel]:
|
||||
) -> type[BaseModel]:
|
||||
field_params = {f.name: (f.field_info.annotation, f.field_info) for f in fields}
|
||||
BodyModel: Type[BaseModel] = create_model(model_name, **field_params) # type: ignore[call-overload]
|
||||
BodyModel: type[BaseModel] = create_model(model_name, **field_params) # type: ignore[call-overload]
|
||||
return BodyModel
|
||||
|
||||
|
||||
def get_model_fields(model: Type[BaseModel]) -> List[ModelField]:
|
||||
model_fields: List[ModelField] = []
|
||||
def get_model_fields(model: type[BaseModel]) -> list[ModelField]:
|
||||
model_fields: list[ModelField] = []
|
||||
for name, field_info in model.model_fields.items():
|
||||
type_ = field_info.annotation
|
||||
if lenient_issubclass(type_, (BaseModel, dict)) or is_dataclass(type_):
|
||||
|
|
@ -501,17 +497,17 @@ def get_model_fields(model: Type[BaseModel]) -> List[ModelField]:
|
|||
# Duplicate of several schema functions from Pydantic v1 to make them compatible with
|
||||
# Pydantic v2 and allow mixing the models
|
||||
|
||||
TypeModelOrEnum = Union[Type["BaseModel"], Type[Enum]]
|
||||
TypeModelSet = Set[TypeModelOrEnum]
|
||||
TypeModelOrEnum = Union[type["BaseModel"], type[Enum]]
|
||||
TypeModelSet = set[TypeModelOrEnum]
|
||||
|
||||
|
||||
def normalize_name(name: str) -> str:
|
||||
return re.sub(r"[^a-zA-Z0-9.\-_]", "_", name)
|
||||
|
||||
|
||||
def get_model_name_map(unique_models: TypeModelSet) -> Dict[TypeModelOrEnum, str]:
|
||||
def get_model_name_map(unique_models: TypeModelSet) -> dict[TypeModelOrEnum, str]:
|
||||
name_model_map = {}
|
||||
conflicting_names: Set[str] = set()
|
||||
conflicting_names: set[str] = set()
|
||||
for model in unique_models:
|
||||
model_name = normalize_name(model.__name__)
|
||||
if model_name in conflicting_names:
|
||||
|
|
@ -528,7 +524,7 @@ def get_model_name_map(unique_models: TypeModelSet) -> Dict[TypeModelOrEnum, str
|
|||
|
||||
|
||||
def get_flat_models_from_model(
|
||||
model: Type["BaseModel"], known_models: Union[TypeModelSet, None] = None
|
||||
model: type["BaseModel"], known_models: Union[TypeModelSet, None] = None
|
||||
) -> TypeModelSet:
|
||||
known_models = known_models or set()
|
||||
fields = get_model_fields(model)
|
||||
|
|
|
|||
|
|
@ -1,14 +1,10 @@
|
|||
from collections.abc import Awaitable, Coroutine, Sequence
|
||||
from enum import Enum
|
||||
from typing import (
|
||||
Annotated,
|
||||
Any,
|
||||
Awaitable,
|
||||
Callable,
|
||||
Coroutine,
|
||||
Dict,
|
||||
List,
|
||||
Optional,
|
||||
Sequence,
|
||||
Type,
|
||||
TypeVar,
|
||||
Union,
|
||||
)
|
||||
|
|
@ -44,7 +40,7 @@ from starlette.requests import Request
|
|||
from starlette.responses import HTMLResponse, JSONResponse, Response
|
||||
from starlette.routing import BaseRoute
|
||||
from starlette.types import ASGIApp, ExceptionHandler, Lifespan, Receive, Scope, Send
|
||||
from typing_extensions import Annotated, deprecated
|
||||
from typing_extensions import deprecated
|
||||
|
||||
AppType = TypeVar("AppType", bound="FastAPI")
|
||||
|
||||
|
|
@ -81,7 +77,7 @@ class FastAPI(Starlette):
|
|||
),
|
||||
] = False,
|
||||
routes: Annotated[
|
||||
Optional[List[BaseRoute]],
|
||||
Optional[list[BaseRoute]],
|
||||
Doc(
|
||||
"""
|
||||
**Note**: you probably shouldn't use this parameter, it is inherited
|
||||
|
|
@ -230,7 +226,7 @@ class FastAPI(Starlette):
|
|||
),
|
||||
] = "/openapi.json",
|
||||
openapi_tags: Annotated[
|
||||
Optional[List[Dict[str, Any]]],
|
||||
Optional[list[dict[str, Any]]],
|
||||
Doc(
|
||||
"""
|
||||
A list of tags used by OpenAPI, these are the same `tags` you can set
|
||||
|
|
@ -290,7 +286,7 @@ class FastAPI(Starlette):
|
|||
),
|
||||
] = None,
|
||||
servers: Annotated[
|
||||
Optional[List[Dict[str, Union[str, Any]]]],
|
||||
Optional[list[dict[str, Union[str, Any]]]],
|
||||
Doc(
|
||||
"""
|
||||
A `list` of `dict`s with connectivity information to a target server.
|
||||
|
|
@ -361,7 +357,7 @@ class FastAPI(Starlette):
|
|||
),
|
||||
] = None,
|
||||
default_response_class: Annotated[
|
||||
Type[Response],
|
||||
type[Response],
|
||||
Doc(
|
||||
"""
|
||||
The default response class to be used.
|
||||
|
|
@ -467,7 +463,7 @@ class FastAPI(Starlette):
|
|||
),
|
||||
] = "/docs/oauth2-redirect",
|
||||
swagger_ui_init_oauth: Annotated[
|
||||
Optional[Dict[str, Any]],
|
||||
Optional[dict[str, Any]],
|
||||
Doc(
|
||||
"""
|
||||
OAuth2 configuration for the Swagger UI, by default shown at `/docs`.
|
||||
|
|
@ -493,8 +489,8 @@ class FastAPI(Starlette):
|
|||
] = None,
|
||||
exception_handlers: Annotated[
|
||||
Optional[
|
||||
Dict[
|
||||
Union[int, Type[Exception]],
|
||||
dict[
|
||||
Union[int, type[Exception]],
|
||||
Callable[[Request, Any], Coroutine[Any, Any, Response]],
|
||||
]
|
||||
],
|
||||
|
|
@ -567,7 +563,7 @@ class FastAPI(Starlette):
|
|||
),
|
||||
] = None,
|
||||
contact: Annotated[
|
||||
Optional[Dict[str, Union[str, Any]]],
|
||||
Optional[dict[str, Union[str, Any]]],
|
||||
Doc(
|
||||
"""
|
||||
A dictionary with the contact information for the exposed API.
|
||||
|
|
@ -600,7 +596,7 @@ class FastAPI(Starlette):
|
|||
),
|
||||
] = None,
|
||||
license_info: Annotated[
|
||||
Optional[Dict[str, Union[str, Any]]],
|
||||
Optional[dict[str, Union[str, Any]]],
|
||||
Doc(
|
||||
"""
|
||||
A dictionary with the license information for the exposed API.
|
||||
|
|
@ -689,7 +685,7 @@ class FastAPI(Starlette):
|
|||
),
|
||||
] = True,
|
||||
responses: Annotated[
|
||||
Optional[Dict[Union[int, str], Dict[str, Any]]],
|
||||
Optional[dict[Union[int, str], dict[str, Any]]],
|
||||
Doc(
|
||||
"""
|
||||
Additional responses to be shown in OpenAPI.
|
||||
|
|
@ -705,7 +701,7 @@ class FastAPI(Starlette):
|
|||
),
|
||||
] = None,
|
||||
callbacks: Annotated[
|
||||
Optional[List[BaseRoute]],
|
||||
Optional[list[BaseRoute]],
|
||||
Doc(
|
||||
"""
|
||||
OpenAPI callbacks that should apply to all *path operations*.
|
||||
|
|
@ -762,7 +758,7 @@ class FastAPI(Starlette):
|
|||
),
|
||||
] = True,
|
||||
swagger_ui_parameters: Annotated[
|
||||
Optional[Dict[str, Any]],
|
||||
Optional[dict[str, Any]],
|
||||
Doc(
|
||||
"""
|
||||
Parameters to configure Swagger UI, the autogenerated interactive API
|
||||
|
|
@ -820,7 +816,7 @@ class FastAPI(Starlette):
|
|||
),
|
||||
] = True,
|
||||
openapi_external_docs: Annotated[
|
||||
Optional[Dict[str, Any]],
|
||||
Optional[dict[str, Any]],
|
||||
Doc(
|
||||
"""
|
||||
This field allows you to provide additional external documentation links.
|
||||
|
|
@ -906,7 +902,7 @@ class FastAPI(Starlette):
|
|||
"""
|
||||
),
|
||||
] = "3.1.0"
|
||||
self.openapi_schema: Optional[Dict[str, Any]] = None
|
||||
self.openapi_schema: Optional[dict[str, Any]] = None
|
||||
if self.openapi_url:
|
||||
assert self.title, "A title must be provided for OpenAPI, e.g.: 'My API'"
|
||||
assert self.version, "A version must be provided for OpenAPI, e.g.: '2.1.0'"
|
||||
|
|
@ -949,7 +945,7 @@ class FastAPI(Starlette):
|
|||
),
|
||||
] = State()
|
||||
self.dependency_overrides: Annotated[
|
||||
Dict[Callable[..., Any], Callable[..., Any]],
|
||||
dict[Callable[..., Any], Callable[..., Any]],
|
||||
Doc(
|
||||
"""
|
||||
A dictionary with overrides for the dependencies.
|
||||
|
|
@ -980,7 +976,7 @@ class FastAPI(Starlette):
|
|||
responses=responses,
|
||||
generate_unique_id_function=generate_unique_id_function,
|
||||
)
|
||||
self.exception_handlers: Dict[
|
||||
self.exception_handlers: dict[
|
||||
Any, Callable[[Request, Any], Union[Response, Awaitable[Response]]]
|
||||
] = {} if exception_handlers is None else dict(exception_handlers)
|
||||
self.exception_handlers.setdefault(HTTPException, http_exception_handler)
|
||||
|
|
@ -993,7 +989,7 @@ class FastAPI(Starlette):
|
|||
websocket_request_validation_exception_handler, # type: ignore
|
||||
)
|
||||
|
||||
self.user_middleware: List[Middleware] = (
|
||||
self.user_middleware: list[Middleware] = (
|
||||
[] if middleware is None else list(middleware)
|
||||
)
|
||||
self.middleware_stack: Union[ASGIApp, None] = None
|
||||
|
|
@ -1047,7 +1043,7 @@ class FastAPI(Starlette):
|
|||
app = cls(app, *args, **kwargs)
|
||||
return app
|
||||
|
||||
def openapi(self) -> Dict[str, Any]:
|
||||
def openapi(self) -> dict[str, Any]:
|
||||
"""
|
||||
Generate the OpenAPI schema of the application. This is called by FastAPI
|
||||
internally.
|
||||
|
|
@ -1145,14 +1141,14 @@ class FastAPI(Starlette):
|
|||
*,
|
||||
response_model: Any = Default(None),
|
||||
status_code: Optional[int] = None,
|
||||
tags: Optional[List[Union[str, Enum]]] = None,
|
||||
tags: Optional[list[Union[str, Enum]]] = None,
|
||||
dependencies: Optional[Sequence[Depends]] = None,
|
||||
summary: Optional[str] = None,
|
||||
description: Optional[str] = None,
|
||||
response_description: str = "Successful Response",
|
||||
responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None,
|
||||
responses: Optional[dict[Union[int, str], dict[str, Any]]] = None,
|
||||
deprecated: Optional[bool] = None,
|
||||
methods: Optional[List[str]] = None,
|
||||
methods: Optional[list[str]] = None,
|
||||
operation_id: Optional[str] = None,
|
||||
response_model_include: Optional[IncEx] = None,
|
||||
response_model_exclude: Optional[IncEx] = None,
|
||||
|
|
@ -1161,11 +1157,11 @@ class FastAPI(Starlette):
|
|||
response_model_exclude_defaults: bool = False,
|
||||
response_model_exclude_none: bool = False,
|
||||
include_in_schema: bool = True,
|
||||
response_class: Union[Type[Response], DefaultPlaceholder] = Default(
|
||||
response_class: Union[type[Response], DefaultPlaceholder] = Default(
|
||||
JSONResponse
|
||||
),
|
||||
name: Optional[str] = None,
|
||||
openapi_extra: Optional[Dict[str, Any]] = None,
|
||||
openapi_extra: Optional[dict[str, Any]] = None,
|
||||
generate_unique_id_function: Callable[[routing.APIRoute], str] = Default(
|
||||
generate_unique_id
|
||||
),
|
||||
|
|
@ -1203,14 +1199,14 @@ class FastAPI(Starlette):
|
|||
*,
|
||||
response_model: Any = Default(None),
|
||||
status_code: Optional[int] = None,
|
||||
tags: Optional[List[Union[str, Enum]]] = None,
|
||||
tags: Optional[list[Union[str, Enum]]] = None,
|
||||
dependencies: Optional[Sequence[Depends]] = None,
|
||||
summary: Optional[str] = None,
|
||||
description: Optional[str] = None,
|
||||
response_description: str = "Successful Response",
|
||||
responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None,
|
||||
responses: Optional[dict[Union[int, str], dict[str, Any]]] = None,
|
||||
deprecated: Optional[bool] = None,
|
||||
methods: Optional[List[str]] = None,
|
||||
methods: Optional[list[str]] = None,
|
||||
operation_id: Optional[str] = None,
|
||||
response_model_include: Optional[IncEx] = None,
|
||||
response_model_exclude: Optional[IncEx] = None,
|
||||
|
|
@ -1219,9 +1215,9 @@ class FastAPI(Starlette):
|
|||
response_model_exclude_defaults: bool = False,
|
||||
response_model_exclude_none: bool = False,
|
||||
include_in_schema: bool = True,
|
||||
response_class: Type[Response] = Default(JSONResponse),
|
||||
response_class: type[Response] = Default(JSONResponse),
|
||||
name: Optional[str] = None,
|
||||
openapi_extra: Optional[Dict[str, Any]] = None,
|
||||
openapi_extra: Optional[dict[str, Any]] = None,
|
||||
generate_unique_id_function: Callable[[routing.APIRoute], str] = Default(
|
||||
generate_unique_id
|
||||
),
|
||||
|
|
@ -1343,7 +1339,7 @@ class FastAPI(Starlette):
|
|||
*,
|
||||
prefix: Annotated[str, Doc("An optional path prefix for the router.")] = "",
|
||||
tags: Annotated[
|
||||
Optional[List[Union[str, Enum]]],
|
||||
Optional[list[Union[str, Enum]]],
|
||||
Doc(
|
||||
"""
|
||||
A list of tags to be applied to all the *path operations* in this
|
||||
|
|
@ -1385,7 +1381,7 @@ class FastAPI(Starlette):
|
|||
),
|
||||
] = None,
|
||||
responses: Annotated[
|
||||
Optional[Dict[Union[int, str], Dict[str, Any]]],
|
||||
Optional[dict[Union[int, str], dict[str, Any]]],
|
||||
Doc(
|
||||
"""
|
||||
Additional responses to be shown in OpenAPI.
|
||||
|
|
@ -1452,7 +1448,7 @@ class FastAPI(Starlette):
|
|||
),
|
||||
] = True,
|
||||
default_response_class: Annotated[
|
||||
Type[Response],
|
||||
type[Response],
|
||||
Doc(
|
||||
"""
|
||||
Default response class to be used for the *path operations* in this
|
||||
|
|
@ -1480,7 +1476,7 @@ class FastAPI(Starlette):
|
|||
),
|
||||
] = Default(JSONResponse),
|
||||
callbacks: Annotated[
|
||||
Optional[List[BaseRoute]],
|
||||
Optional[list[BaseRoute]],
|
||||
Doc(
|
||||
"""
|
||||
List of *path operations* that will be used as OpenAPI callbacks.
|
||||
|
|
@ -1603,7 +1599,7 @@ class FastAPI(Starlette):
|
|||
),
|
||||
] = None,
|
||||
tags: Annotated[
|
||||
Optional[List[Union[str, Enum]]],
|
||||
Optional[list[Union[str, Enum]]],
|
||||
Doc(
|
||||
"""
|
||||
A list of tags to be applied to the *path operation*.
|
||||
|
|
@ -1669,7 +1665,7 @@ class FastAPI(Starlette):
|
|||
),
|
||||
] = "Successful Response",
|
||||
responses: Annotated[
|
||||
Optional[Dict[Union[int, str], Dict[str, Any]]],
|
||||
Optional[dict[Union[int, str], dict[str, Any]]],
|
||||
Doc(
|
||||
"""
|
||||
Additional responses that could be returned by this *path operation*.
|
||||
|
|
@ -1810,7 +1806,7 @@ class FastAPI(Starlette):
|
|||
),
|
||||
] = True,
|
||||
response_class: Annotated[
|
||||
Type[Response],
|
||||
type[Response],
|
||||
Doc(
|
||||
"""
|
||||
Response class to be used for this *path operation*.
|
||||
|
|
@ -1831,7 +1827,7 @@ class FastAPI(Starlette):
|
|||
),
|
||||
] = None,
|
||||
callbacks: Annotated[
|
||||
Optional[List[BaseRoute]],
|
||||
Optional[list[BaseRoute]],
|
||||
Doc(
|
||||
"""
|
||||
List of *path operations* that will be used as OpenAPI callbacks.
|
||||
|
|
@ -1847,7 +1843,7 @@ class FastAPI(Starlette):
|
|||
),
|
||||
] = None,
|
||||
openapi_extra: Annotated[
|
||||
Optional[Dict[str, Any]],
|
||||
Optional[dict[str, Any]],
|
||||
Doc(
|
||||
"""
|
||||
Extra metadata to be included in the OpenAPI schema for this *path
|
||||
|
|
@ -1976,7 +1972,7 @@ class FastAPI(Starlette):
|
|||
),
|
||||
] = None,
|
||||
tags: Annotated[
|
||||
Optional[List[Union[str, Enum]]],
|
||||
Optional[list[Union[str, Enum]]],
|
||||
Doc(
|
||||
"""
|
||||
A list of tags to be applied to the *path operation*.
|
||||
|
|
@ -2042,7 +2038,7 @@ class FastAPI(Starlette):
|
|||
),
|
||||
] = "Successful Response",
|
||||
responses: Annotated[
|
||||
Optional[Dict[Union[int, str], Dict[str, Any]]],
|
||||
Optional[dict[Union[int, str], dict[str, Any]]],
|
||||
Doc(
|
||||
"""
|
||||
Additional responses that could be returned by this *path operation*.
|
||||
|
|
@ -2183,7 +2179,7 @@ class FastAPI(Starlette):
|
|||
),
|
||||
] = True,
|
||||
response_class: Annotated[
|
||||
Type[Response],
|
||||
type[Response],
|
||||
Doc(
|
||||
"""
|
||||
Response class to be used for this *path operation*.
|
||||
|
|
@ -2204,7 +2200,7 @@ class FastAPI(Starlette):
|
|||
),
|
||||
] = None,
|
||||
callbacks: Annotated[
|
||||
Optional[List[BaseRoute]],
|
||||
Optional[list[BaseRoute]],
|
||||
Doc(
|
||||
"""
|
||||
List of *path operations* that will be used as OpenAPI callbacks.
|
||||
|
|
@ -2220,7 +2216,7 @@ class FastAPI(Starlette):
|
|||
),
|
||||
] = None,
|
||||
openapi_extra: Annotated[
|
||||
Optional[Dict[str, Any]],
|
||||
Optional[dict[str, Any]],
|
||||
Doc(
|
||||
"""
|
||||
Extra metadata to be included in the OpenAPI schema for this *path
|
||||
|
|
@ -2354,7 +2350,7 @@ class FastAPI(Starlette):
|
|||
),
|
||||
] = None,
|
||||
tags: Annotated[
|
||||
Optional[List[Union[str, Enum]]],
|
||||
Optional[list[Union[str, Enum]]],
|
||||
Doc(
|
||||
"""
|
||||
A list of tags to be applied to the *path operation*.
|
||||
|
|
@ -2420,7 +2416,7 @@ class FastAPI(Starlette):
|
|||
),
|
||||
] = "Successful Response",
|
||||
responses: Annotated[
|
||||
Optional[Dict[Union[int, str], Dict[str, Any]]],
|
||||
Optional[dict[Union[int, str], dict[str, Any]]],
|
||||
Doc(
|
||||
"""
|
||||
Additional responses that could be returned by this *path operation*.
|
||||
|
|
@ -2561,7 +2557,7 @@ class FastAPI(Starlette):
|
|||
),
|
||||
] = True,
|
||||
response_class: Annotated[
|
||||
Type[Response],
|
||||
type[Response],
|
||||
Doc(
|
||||
"""
|
||||
Response class to be used for this *path operation*.
|
||||
|
|
@ -2582,7 +2578,7 @@ class FastAPI(Starlette):
|
|||
),
|
||||
] = None,
|
||||
callbacks: Annotated[
|
||||
Optional[List[BaseRoute]],
|
||||
Optional[list[BaseRoute]],
|
||||
Doc(
|
||||
"""
|
||||
List of *path operations* that will be used as OpenAPI callbacks.
|
||||
|
|
@ -2598,7 +2594,7 @@ class FastAPI(Starlette):
|
|||
),
|
||||
] = None,
|
||||
openapi_extra: Annotated[
|
||||
Optional[Dict[str, Any]],
|
||||
Optional[dict[str, Any]],
|
||||
Doc(
|
||||
"""
|
||||
Extra metadata to be included in the OpenAPI schema for this *path
|
||||
|
|
@ -2732,7 +2728,7 @@ class FastAPI(Starlette):
|
|||
),
|
||||
] = None,
|
||||
tags: Annotated[
|
||||
Optional[List[Union[str, Enum]]],
|
||||
Optional[list[Union[str, Enum]]],
|
||||
Doc(
|
||||
"""
|
||||
A list of tags to be applied to the *path operation*.
|
||||
|
|
@ -2798,7 +2794,7 @@ class FastAPI(Starlette):
|
|||
),
|
||||
] = "Successful Response",
|
||||
responses: Annotated[
|
||||
Optional[Dict[Union[int, str], Dict[str, Any]]],
|
||||
Optional[dict[Union[int, str], dict[str, Any]]],
|
||||
Doc(
|
||||
"""
|
||||
Additional responses that could be returned by this *path operation*.
|
||||
|
|
@ -2939,7 +2935,7 @@ class FastAPI(Starlette):
|
|||
),
|
||||
] = True,
|
||||
response_class: Annotated[
|
||||
Type[Response],
|
||||
type[Response],
|
||||
Doc(
|
||||
"""
|
||||
Response class to be used for this *path operation*.
|
||||
|
|
@ -2960,7 +2956,7 @@ class FastAPI(Starlette):
|
|||
),
|
||||
] = None,
|
||||
callbacks: Annotated[
|
||||
Optional[List[BaseRoute]],
|
||||
Optional[list[BaseRoute]],
|
||||
Doc(
|
||||
"""
|
||||
List of *path operations* that will be used as OpenAPI callbacks.
|
||||
|
|
@ -2976,7 +2972,7 @@ class FastAPI(Starlette):
|
|||
),
|
||||
] = None,
|
||||
openapi_extra: Annotated[
|
||||
Optional[Dict[str, Any]],
|
||||
Optional[dict[str, Any]],
|
||||
Doc(
|
||||
"""
|
||||
Extra metadata to be included in the OpenAPI schema for this *path
|
||||
|
|
@ -3105,7 +3101,7 @@ class FastAPI(Starlette):
|
|||
),
|
||||
] = None,
|
||||
tags: Annotated[
|
||||
Optional[List[Union[str, Enum]]],
|
||||
Optional[list[Union[str, Enum]]],
|
||||
Doc(
|
||||
"""
|
||||
A list of tags to be applied to the *path operation*.
|
||||
|
|
@ -3171,7 +3167,7 @@ class FastAPI(Starlette):
|
|||
),
|
||||
] = "Successful Response",
|
||||
responses: Annotated[
|
||||
Optional[Dict[Union[int, str], Dict[str, Any]]],
|
||||
Optional[dict[Union[int, str], dict[str, Any]]],
|
||||
Doc(
|
||||
"""
|
||||
Additional responses that could be returned by this *path operation*.
|
||||
|
|
@ -3312,7 +3308,7 @@ class FastAPI(Starlette):
|
|||
),
|
||||
] = True,
|
||||
response_class: Annotated[
|
||||
Type[Response],
|
||||
type[Response],
|
||||
Doc(
|
||||
"""
|
||||
Response class to be used for this *path operation*.
|
||||
|
|
@ -3333,7 +3329,7 @@ class FastAPI(Starlette):
|
|||
),
|
||||
] = None,
|
||||
callbacks: Annotated[
|
||||
Optional[List[BaseRoute]],
|
||||
Optional[list[BaseRoute]],
|
||||
Doc(
|
||||
"""
|
||||
List of *path operations* that will be used as OpenAPI callbacks.
|
||||
|
|
@ -3349,7 +3345,7 @@ class FastAPI(Starlette):
|
|||
),
|
||||
] = None,
|
||||
openapi_extra: Annotated[
|
||||
Optional[Dict[str, Any]],
|
||||
Optional[dict[str, Any]],
|
||||
Doc(
|
||||
"""
|
||||
Extra metadata to be included in the OpenAPI schema for this *path
|
||||
|
|
@ -3478,7 +3474,7 @@ class FastAPI(Starlette):
|
|||
),
|
||||
] = None,
|
||||
tags: Annotated[
|
||||
Optional[List[Union[str, Enum]]],
|
||||
Optional[list[Union[str, Enum]]],
|
||||
Doc(
|
||||
"""
|
||||
A list of tags to be applied to the *path operation*.
|
||||
|
|
@ -3544,7 +3540,7 @@ class FastAPI(Starlette):
|
|||
),
|
||||
] = "Successful Response",
|
||||
responses: Annotated[
|
||||
Optional[Dict[Union[int, str], Dict[str, Any]]],
|
||||
Optional[dict[Union[int, str], dict[str, Any]]],
|
||||
Doc(
|
||||
"""
|
||||
Additional responses that could be returned by this *path operation*.
|
||||
|
|
@ -3685,7 +3681,7 @@ class FastAPI(Starlette):
|
|||
),
|
||||
] = True,
|
||||
response_class: Annotated[
|
||||
Type[Response],
|
||||
type[Response],
|
||||
Doc(
|
||||
"""
|
||||
Response class to be used for this *path operation*.
|
||||
|
|
@ -3706,7 +3702,7 @@ class FastAPI(Starlette):
|
|||
),
|
||||
] = None,
|
||||
callbacks: Annotated[
|
||||
Optional[List[BaseRoute]],
|
||||
Optional[list[BaseRoute]],
|
||||
Doc(
|
||||
"""
|
||||
List of *path operations* that will be used as OpenAPI callbacks.
|
||||
|
|
@ -3722,7 +3718,7 @@ class FastAPI(Starlette):
|
|||
),
|
||||
] = None,
|
||||
openapi_extra: Annotated[
|
||||
Optional[Dict[str, Any]],
|
||||
Optional[dict[str, Any]],
|
||||
Doc(
|
||||
"""
|
||||
Extra metadata to be included in the OpenAPI schema for this *path
|
||||
|
|
@ -3851,7 +3847,7 @@ class FastAPI(Starlette):
|
|||
),
|
||||
] = None,
|
||||
tags: Annotated[
|
||||
Optional[List[Union[str, Enum]]],
|
||||
Optional[list[Union[str, Enum]]],
|
||||
Doc(
|
||||
"""
|
||||
A list of tags to be applied to the *path operation*.
|
||||
|
|
@ -3917,7 +3913,7 @@ class FastAPI(Starlette):
|
|||
),
|
||||
] = "Successful Response",
|
||||
responses: Annotated[
|
||||
Optional[Dict[Union[int, str], Dict[str, Any]]],
|
||||
Optional[dict[Union[int, str], dict[str, Any]]],
|
||||
Doc(
|
||||
"""
|
||||
Additional responses that could be returned by this *path operation*.
|
||||
|
|
@ -4058,7 +4054,7 @@ class FastAPI(Starlette):
|
|||
),
|
||||
] = True,
|
||||
response_class: Annotated[
|
||||
Type[Response],
|
||||
type[Response],
|
||||
Doc(
|
||||
"""
|
||||
Response class to be used for this *path operation*.
|
||||
|
|
@ -4079,7 +4075,7 @@ class FastAPI(Starlette):
|
|||
),
|
||||
] = None,
|
||||
callbacks: Annotated[
|
||||
Optional[List[BaseRoute]],
|
||||
Optional[list[BaseRoute]],
|
||||
Doc(
|
||||
"""
|
||||
List of *path operations* that will be used as OpenAPI callbacks.
|
||||
|
|
@ -4095,7 +4091,7 @@ class FastAPI(Starlette):
|
|||
),
|
||||
] = None,
|
||||
openapi_extra: Annotated[
|
||||
Optional[Dict[str, Any]],
|
||||
Optional[dict[str, Any]],
|
||||
Doc(
|
||||
"""
|
||||
Extra metadata to be included in the OpenAPI schema for this *path
|
||||
|
|
@ -4229,7 +4225,7 @@ class FastAPI(Starlette):
|
|||
),
|
||||
] = None,
|
||||
tags: Annotated[
|
||||
Optional[List[Union[str, Enum]]],
|
||||
Optional[list[Union[str, Enum]]],
|
||||
Doc(
|
||||
"""
|
||||
A list of tags to be applied to the *path operation*.
|
||||
|
|
@ -4295,7 +4291,7 @@ class FastAPI(Starlette):
|
|||
),
|
||||
] = "Successful Response",
|
||||
responses: Annotated[
|
||||
Optional[Dict[Union[int, str], Dict[str, Any]]],
|
||||
Optional[dict[Union[int, str], dict[str, Any]]],
|
||||
Doc(
|
||||
"""
|
||||
Additional responses that could be returned by this *path operation*.
|
||||
|
|
@ -4436,7 +4432,7 @@ class FastAPI(Starlette):
|
|||
),
|
||||
] = True,
|
||||
response_class: Annotated[
|
||||
Type[Response],
|
||||
type[Response],
|
||||
Doc(
|
||||
"""
|
||||
Response class to be used for this *path operation*.
|
||||
|
|
@ -4457,7 +4453,7 @@ class FastAPI(Starlette):
|
|||
),
|
||||
] = None,
|
||||
callbacks: Annotated[
|
||||
Optional[List[BaseRoute]],
|
||||
Optional[list[BaseRoute]],
|
||||
Doc(
|
||||
"""
|
||||
List of *path operations* that will be used as OpenAPI callbacks.
|
||||
|
|
@ -4473,7 +4469,7 @@ class FastAPI(Starlette):
|
|||
),
|
||||
] = None,
|
||||
openapi_extra: Annotated[
|
||||
Optional[Dict[str, Any]],
|
||||
Optional[dict[str, Any]],
|
||||
Doc(
|
||||
"""
|
||||
Extra metadata to be included in the OpenAPI schema for this *path
|
||||
|
|
@ -4628,7 +4624,7 @@ class FastAPI(Starlette):
|
|||
def exception_handler(
|
||||
self,
|
||||
exc_class_or_status_code: Annotated[
|
||||
Union[int, Type[Exception]],
|
||||
Union[int, type[Exception]],
|
||||
Doc(
|
||||
"""
|
||||
The Exception class this would handle, or a status code.
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
from typing import Any, Callable
|
||||
from typing import Annotated, Any, Callable
|
||||
|
||||
from annotated_doc import Doc
|
||||
from starlette.background import BackgroundTasks as StarletteBackgroundTasks
|
||||
from typing_extensions import Annotated, ParamSpec
|
||||
from typing_extensions import ParamSpec
|
||||
|
||||
P = ParamSpec("P")
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
from collections.abc import AsyncGenerator
|
||||
from contextlib import AbstractContextManager
|
||||
from contextlib import asynccontextmanager as asynccontextmanager
|
||||
from typing import AsyncGenerator, ContextManager, TypeVar
|
||||
from typing import TypeVar
|
||||
|
||||
import anyio.to_thread
|
||||
from anyio import CapacityLimiter
|
||||
|
|
@ -14,7 +16,7 @@ _T = TypeVar("_T")
|
|||
|
||||
@asynccontextmanager
|
||||
async def contextmanager_in_threadpool(
|
||||
cm: ContextManager[_T],
|
||||
cm: AbstractContextManager[_T],
|
||||
) -> AsyncGenerator[_T, None]:
|
||||
# blocking __exit__ from running waiting on a free thread
|
||||
# can create race conditions/deadlocks if the context manager itself
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
from collections.abc import Iterable
|
||||
from typing import (
|
||||
Annotated,
|
||||
Any,
|
||||
BinaryIO,
|
||||
Callable,
|
||||
Dict,
|
||||
Iterable,
|
||||
Optional,
|
||||
Type,
|
||||
TypeVar,
|
||||
cast,
|
||||
)
|
||||
|
|
@ -23,7 +22,6 @@ from starlette.datastructures import Headers as Headers # noqa: F401
|
|||
from starlette.datastructures import QueryParams as QueryParams # noqa: F401
|
||||
from starlette.datastructures import State as State # noqa: F401
|
||||
from starlette.datastructures import UploadFile as StarletteUploadFile
|
||||
from typing_extensions import Annotated
|
||||
|
||||
|
||||
class UploadFile(StarletteUploadFile):
|
||||
|
|
@ -138,11 +136,11 @@ class UploadFile(StarletteUploadFile):
|
|||
return await super().close()
|
||||
|
||||
@classmethod
|
||||
def __get_validators__(cls: Type["UploadFile"]) -> Iterable[Callable[..., Any]]:
|
||||
def __get_validators__(cls: type["UploadFile"]) -> Iterable[Callable[..., Any]]:
|
||||
yield cls.validate
|
||||
|
||||
@classmethod
|
||||
def validate(cls: Type["UploadFile"], v: Any) -> Any:
|
||||
def validate(cls: type["UploadFile"], v: Any) -> Any:
|
||||
if not isinstance(v, StarletteUploadFile):
|
||||
raise ValueError(f"Expected UploadFile, received: {type(v)}")
|
||||
return v
|
||||
|
|
@ -155,7 +153,7 @@ class UploadFile(StarletteUploadFile):
|
|||
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
@classmethod
|
||||
def __modify_schema__(cls, field_schema: Dict[str, Any]) -> None:
|
||||
def __modify_schema__(cls, field_schema: dict[str, Any]) -> None:
|
||||
field_schema.update({"type": "string", "format": "binary"})
|
||||
|
||||
@classmethod
|
||||
|
|
@ -166,7 +164,7 @@ class UploadFile(StarletteUploadFile):
|
|||
|
||||
@classmethod
|
||||
def __get_pydantic_core_schema__(
|
||||
cls, source: Type[Any], handler: Callable[[Any], CoreSchema]
|
||||
cls, source: type[Any], handler: Callable[[Any], CoreSchema]
|
||||
) -> CoreSchema:
|
||||
from ._compat.v2 import with_info_plain_validator_function
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import inspect
|
|||
import sys
|
||||
from dataclasses import dataclass, field
|
||||
from functools import cached_property, partial
|
||||
from typing import Any, Callable, List, Optional, Union
|
||||
from typing import Any, Callable, Optional, Union
|
||||
|
||||
from fastapi._compat import ModelField
|
||||
from fastapi.security.base import SecurityBase
|
||||
|
|
@ -30,12 +30,12 @@ def _impartial(func: Callable[..., Any]) -> Callable[..., Any]:
|
|||
|
||||
@dataclass
|
||||
class Dependant:
|
||||
path_params: List[ModelField] = field(default_factory=list)
|
||||
query_params: List[ModelField] = field(default_factory=list)
|
||||
header_params: List[ModelField] = field(default_factory=list)
|
||||
cookie_params: List[ModelField] = field(default_factory=list)
|
||||
body_params: List[ModelField] = field(default_factory=list)
|
||||
dependencies: List["Dependant"] = field(default_factory=list)
|
||||
path_params: list[ModelField] = field(default_factory=list)
|
||||
query_params: list[ModelField] = field(default_factory=list)
|
||||
header_params: list[ModelField] = field(default_factory=list)
|
||||
cookie_params: list[ModelField] = field(default_factory=list)
|
||||
body_params: list[ModelField] = field(default_factory=list)
|
||||
dependencies: list["Dependant"] = field(default_factory=list)
|
||||
name: Optional[str] = None
|
||||
call: Optional[Callable[..., Any]] = None
|
||||
request_param_name: Optional[str] = None
|
||||
|
|
@ -44,14 +44,14 @@ class Dependant:
|
|||
response_param_name: Optional[str] = None
|
||||
background_tasks_param_name: Optional[str] = None
|
||||
security_scopes_param_name: Optional[str] = None
|
||||
own_oauth_scopes: Optional[List[str]] = None
|
||||
parent_oauth_scopes: Optional[List[str]] = None
|
||||
own_oauth_scopes: Optional[list[str]] = None
|
||||
parent_oauth_scopes: Optional[list[str]] = None
|
||||
use_cache: bool = True
|
||||
path: Optional[str] = None
|
||||
scope: Union[Literal["function", "request"], None] = None
|
||||
|
||||
@cached_property
|
||||
def oauth_scopes(self) -> List[str]:
|
||||
def oauth_scopes(self) -> list[str]:
|
||||
scopes = self.parent_oauth_scopes.copy() if self.parent_oauth_scopes else []
|
||||
# This doesn't use a set to preserve order, just in case
|
||||
for scope in self.own_oauth_scopes or []:
|
||||
|
|
@ -98,7 +98,7 @@ class Dependant:
|
|||
return unwrapped
|
||||
|
||||
@cached_property
|
||||
def _security_dependencies(self) -> List["Dependant"]:
|
||||
def _security_dependencies(self) -> list["Dependant"]:
|
||||
security_deps = [dep for dep in self.dependencies if dep._is_security_scheme]
|
||||
return security_deps
|
||||
|
||||
|
|
|
|||
|
|
@ -1,21 +1,16 @@
|
|||
import dataclasses
|
||||
import inspect
|
||||
import sys
|
||||
from collections.abc import Coroutine, Mapping, Sequence
|
||||
from contextlib import AsyncExitStack, contextmanager
|
||||
from copy import copy, deepcopy
|
||||
from dataclasses import dataclass
|
||||
from typing import (
|
||||
Annotated,
|
||||
Any,
|
||||
Callable,
|
||||
Coroutine,
|
||||
Dict,
|
||||
ForwardRef,
|
||||
List,
|
||||
Mapping,
|
||||
Optional,
|
||||
Sequence,
|
||||
Tuple,
|
||||
Type,
|
||||
Union,
|
||||
cast,
|
||||
)
|
||||
|
|
@ -75,7 +70,7 @@ from starlette.datastructures import (
|
|||
from starlette.requests import HTTPConnection, Request
|
||||
from starlette.responses import Response
|
||||
from starlette.websockets import WebSocket
|
||||
from typing_extensions import Annotated, Literal, get_args, get_origin
|
||||
from typing_extensions import Literal, get_args, get_origin
|
||||
|
||||
from .. import temp_pydantic_v1_params
|
||||
|
||||
|
|
@ -125,7 +120,7 @@ def get_parameterless_sub_dependant(*, depends: params.Depends, path: str) -> De
|
|||
assert callable(depends.dependency), (
|
||||
"A parameter-less dependency must have a callable dependency"
|
||||
)
|
||||
own_oauth_scopes: List[str] = []
|
||||
own_oauth_scopes: list[str] = []
|
||||
if isinstance(depends, params.Security) and depends.scopes:
|
||||
own_oauth_scopes.extend(depends.scopes)
|
||||
return get_dependant(
|
||||
|
|
@ -140,8 +135,8 @@ def get_flat_dependant(
|
|||
dependant: Dependant,
|
||||
*,
|
||||
skip_repeats: bool = False,
|
||||
visited: Optional[List[DependencyCacheKey]] = None,
|
||||
parent_oauth_scopes: Optional[List[str]] = None,
|
||||
visited: Optional[list[DependencyCacheKey]] = None,
|
||||
parent_oauth_scopes: Optional[list[str]] = None,
|
||||
) -> Dependant:
|
||||
if visited is None:
|
||||
visited = []
|
||||
|
|
@ -190,7 +185,7 @@ def get_flat_dependant(
|
|||
return flat_dependant
|
||||
|
||||
|
||||
def _get_flat_fields_from_params(fields: List[ModelField]) -> List[ModelField]:
|
||||
def _get_flat_fields_from_params(fields: list[ModelField]) -> list[ModelField]:
|
||||
if not fields:
|
||||
return fields
|
||||
first_field = fields[0]
|
||||
|
|
@ -200,7 +195,7 @@ def _get_flat_fields_from_params(fields: List[ModelField]) -> List[ModelField]:
|
|||
return fields
|
||||
|
||||
|
||||
def get_flat_params(dependant: Dependant) -> List[ModelField]:
|
||||
def get_flat_params(dependant: Dependant) -> list[ModelField]:
|
||||
flat_dependant = get_flat_dependant(dependant, skip_repeats=True)
|
||||
path_params = _get_flat_fields_from_params(flat_dependant.path_params)
|
||||
query_params = _get_flat_fields_from_params(flat_dependant.query_params)
|
||||
|
|
@ -239,7 +234,7 @@ def get_typed_signature(call: Callable[..., Any]) -> inspect.Signature:
|
|||
return typed_signature
|
||||
|
||||
|
||||
def get_typed_annotation(annotation: Any, globalns: Dict[str, Any]) -> Any:
|
||||
def get_typed_annotation(annotation: Any, globalns: dict[str, Any]) -> Any:
|
||||
if isinstance(annotation, str):
|
||||
annotation = ForwardRef(annotation)
|
||||
annotation = evaluate_forwardref(annotation, globalns, globalns)
|
||||
|
|
@ -265,8 +260,8 @@ def get_dependant(
|
|||
path: str,
|
||||
call: Callable[..., Any],
|
||||
name: Optional[str] = None,
|
||||
own_oauth_scopes: Optional[List[str]] = None,
|
||||
parent_oauth_scopes: Optional[List[str]] = None,
|
||||
own_oauth_scopes: Optional[list[str]] = None,
|
||||
parent_oauth_scopes: Optional[list[str]] = None,
|
||||
use_cache: bool = True,
|
||||
scope: Union[Literal["function", "request"], None] = None,
|
||||
) -> Dependant:
|
||||
|
|
@ -303,7 +298,7 @@ def get_dependant(
|
|||
f'The dependency "{dependant.call.__name__}" has a scope of '
|
||||
'"request", it cannot depend on dependencies with scope "function".'
|
||||
)
|
||||
sub_own_oauth_scopes: List[str] = []
|
||||
sub_own_oauth_scopes: list[str] = []
|
||||
if isinstance(param_details.depends, params.Security):
|
||||
if param_details.depends.scopes:
|
||||
sub_own_oauth_scopes = list(param_details.depends.scopes)
|
||||
|
|
@ -572,7 +567,7 @@ def add_param_to_fields(*, field: ModelField, dependant: Dependant) -> None:
|
|||
|
||||
|
||||
async def _solve_generator(
|
||||
*, dependant: Dependant, stack: AsyncExitStack, sub_values: Dict[str, Any]
|
||||
*, dependant: Dependant, stack: AsyncExitStack, sub_values: dict[str, Any]
|
||||
) -> Any:
|
||||
assert dependant.call
|
||||
if dependant.is_async_gen_callable:
|
||||
|
|
@ -584,22 +579,22 @@ async def _solve_generator(
|
|||
|
||||
@dataclass
|
||||
class SolvedDependency:
|
||||
values: Dict[str, Any]
|
||||
errors: List[Any]
|
||||
values: dict[str, Any]
|
||||
errors: list[Any]
|
||||
background_tasks: Optional[StarletteBackgroundTasks]
|
||||
response: Response
|
||||
dependency_cache: Dict[DependencyCacheKey, Any]
|
||||
dependency_cache: dict[DependencyCacheKey, Any]
|
||||
|
||||
|
||||
async def solve_dependencies(
|
||||
*,
|
||||
request: Union[Request, WebSocket],
|
||||
dependant: Dependant,
|
||||
body: Optional[Union[Dict[str, Any], FormData]] = None,
|
||||
body: Optional[Union[dict[str, Any], FormData]] = None,
|
||||
background_tasks: Optional[StarletteBackgroundTasks] = None,
|
||||
response: Optional[Response] = None,
|
||||
dependency_overrides_provider: Optional[Any] = None,
|
||||
dependency_cache: Optional[Dict[DependencyCacheKey, Any]] = None,
|
||||
dependency_cache: Optional[dict[DependencyCacheKey, Any]] = None,
|
||||
# TODO: remove this parameter later, no longer used, not removing it yet as some
|
||||
# people might be monkey patching this function (although that's not supported)
|
||||
async_exit_stack: AsyncExitStack,
|
||||
|
|
@ -613,8 +608,8 @@ async def solve_dependencies(
|
|||
assert isinstance(function_astack, AsyncExitStack), (
|
||||
"fastapi_function_astack not found in request scope"
|
||||
)
|
||||
values: Dict[str, Any] = {}
|
||||
errors: List[Any] = []
|
||||
values: dict[str, Any] = {}
|
||||
errors: list[Any] = []
|
||||
if response is None:
|
||||
response = Response()
|
||||
del response.headers["content-length"]
|
||||
|
|
@ -732,8 +727,8 @@ async def solve_dependencies(
|
|||
|
||||
|
||||
def _validate_value_with_model_field(
|
||||
*, field: ModelField, value: Any, values: Dict[str, Any], loc: Tuple[str, ...]
|
||||
) -> Tuple[Any, List[Any]]:
|
||||
*, field: ModelField, value: Any, values: dict[str, Any], loc: tuple[str, ...]
|
||||
) -> tuple[Any, list[Any]]:
|
||||
if value is None:
|
||||
if field.required:
|
||||
return None, [get_missing_field_error(loc=loc)]
|
||||
|
|
@ -776,9 +771,9 @@ def _get_multidict_value(
|
|||
def request_params_to_args(
|
||||
fields: Sequence[ModelField],
|
||||
received_params: Union[Mapping[str, Any], QueryParams, Headers],
|
||||
) -> Tuple[Dict[str, Any], List[Any]]:
|
||||
values: Dict[str, Any] = {}
|
||||
errors: List[Dict[str, Any]] = []
|
||||
) -> tuple[dict[str, Any], list[Any]]:
|
||||
values: dict[str, Any] = {}
|
||||
errors: list[dict[str, Any]] = []
|
||||
|
||||
if not fields:
|
||||
return values, errors
|
||||
|
|
@ -796,7 +791,7 @@ def request_params_to_args(
|
|||
first_field.field_info, "convert_underscores", True
|
||||
)
|
||||
|
||||
params_to_process: Dict[str, Any] = {}
|
||||
params_to_process: dict[str, Any] = {}
|
||||
|
||||
processed_keys = set()
|
||||
|
||||
|
|
@ -833,7 +828,7 @@ def request_params_to_args(
|
|||
assert isinstance(field_info, (params.Param, temp_pydantic_v1_params.Param)), (
|
||||
"Params must be subclasses of Param"
|
||||
)
|
||||
loc: Tuple[str, ...] = (field_info.in_.value,)
|
||||
loc: tuple[str, ...] = (field_info.in_.value,)
|
||||
v_, errors_ = _validate_value_with_model_field(
|
||||
field=first_field, value=params_to_process, values=values, loc=loc
|
||||
)
|
||||
|
|
@ -875,7 +870,7 @@ def is_union_of_base_models(field_type: Any) -> bool:
|
|||
return True
|
||||
|
||||
|
||||
def _should_embed_body_fields(fields: List[ModelField]) -> bool:
|
||||
def _should_embed_body_fields(fields: list[ModelField]) -> bool:
|
||||
if not fields:
|
||||
return False
|
||||
# More than one dependency could have the same field, it would show up as multiple
|
||||
|
|
@ -900,9 +895,9 @@ def _should_embed_body_fields(fields: List[ModelField]) -> bool:
|
|||
|
||||
|
||||
async def _extract_form_body(
|
||||
body_fields: List[ModelField],
|
||||
body_fields: list[ModelField],
|
||||
received_body: FormData,
|
||||
) -> Dict[str, Any]:
|
||||
) -> dict[str, Any]:
|
||||
values = {}
|
||||
|
||||
for field in body_fields:
|
||||
|
|
@ -920,8 +915,8 @@ async def _extract_form_body(
|
|||
and value_is_sequence(value)
|
||||
):
|
||||
# For types
|
||||
assert isinstance(value, sequence_types) # type: ignore[arg-type]
|
||||
results: List[Union[bytes, str]] = []
|
||||
assert isinstance(value, sequence_types)
|
||||
results: list[Union[bytes, str]] = []
|
||||
|
||||
async def process_fn(
|
||||
fn: Callable[[], Coroutine[Any, Any, Any]],
|
||||
|
|
@ -947,18 +942,18 @@ async def _extract_form_body(
|
|||
|
||||
|
||||
async def request_body_to_args(
|
||||
body_fields: List[ModelField],
|
||||
received_body: Optional[Union[Dict[str, Any], FormData]],
|
||||
body_fields: list[ModelField],
|
||||
received_body: Optional[Union[dict[str, Any], FormData]],
|
||||
embed_body_fields: bool,
|
||||
) -> Tuple[Dict[str, Any], List[Dict[str, Any]]]:
|
||||
values: Dict[str, Any] = {}
|
||||
errors: List[Dict[str, Any]] = []
|
||||
) -> tuple[dict[str, Any], list[dict[str, Any]]]:
|
||||
values: dict[str, Any] = {}
|
||||
errors: list[dict[str, Any]] = []
|
||||
assert body_fields, "request_body_to_args() should be called with fields"
|
||||
single_not_embedded_field = len(body_fields) == 1 and not embed_body_fields
|
||||
first_field = body_fields[0]
|
||||
body_to_process = received_body
|
||||
|
||||
fields_to_extract: List[ModelField] = body_fields
|
||||
fields_to_extract: list[ModelField] = body_fields
|
||||
|
||||
if (
|
||||
single_not_embedded_field
|
||||
|
|
@ -971,7 +966,7 @@ async def request_body_to_args(
|
|||
body_to_process = await _extract_form_body(fields_to_extract, received_body)
|
||||
|
||||
if single_not_embedded_field:
|
||||
loc: Tuple[str, ...] = ("body",)
|
||||
loc: tuple[str, ...] = ("body",)
|
||||
v_, errors_ = _validate_value_with_model_field(
|
||||
field=first_field, value=body_to_process, values=values, loc=loc
|
||||
)
|
||||
|
|
@ -1019,19 +1014,19 @@ def get_body_field(
|
|||
fields=flat_dependant.body_params, model_name=model_name
|
||||
)
|
||||
required = any(True for f in flat_dependant.body_params if f.required)
|
||||
BodyFieldInfo_kwargs: Dict[str, Any] = {
|
||||
BodyFieldInfo_kwargs: dict[str, Any] = {
|
||||
"annotation": BodyModel,
|
||||
"alias": "body",
|
||||
}
|
||||
if not required:
|
||||
BodyFieldInfo_kwargs["default"] = None
|
||||
if any(isinstance(f.field_info, params.File) for f in flat_dependant.body_params):
|
||||
BodyFieldInfo: Type[params.Body] = params.File
|
||||
BodyFieldInfo: type[params.Body] = params.File
|
||||
elif any(
|
||||
isinstance(f.field_info, temp_pydantic_v1_params.File)
|
||||
for f in flat_dependant.body_params
|
||||
):
|
||||
BodyFieldInfo: Type[temp_pydantic_v1_params.Body] = temp_pydantic_v1_params.File # type: ignore[no-redef]
|
||||
BodyFieldInfo: type[temp_pydantic_v1_params.Body] = temp_pydantic_v1_params.File # type: ignore[no-redef]
|
||||
elif any(isinstance(f.field_info, params.Form) for f in flat_dependant.body_params):
|
||||
BodyFieldInfo = params.Form
|
||||
elif any(
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ from ipaddress import (
|
|||
from pathlib import Path, PurePath
|
||||
from re import Pattern
|
||||
from types import GeneratorType
|
||||
from typing import Any, Callable, Dict, List, Optional, Tuple, Type, Union
|
||||
from typing import Annotated, Any, Callable, Optional, Union
|
||||
from uuid import UUID
|
||||
|
||||
from annotated_doc import Doc
|
||||
|
|
@ -24,7 +24,6 @@ from pydantic import BaseModel
|
|||
from pydantic.color import Color
|
||||
from pydantic.networks import AnyUrl, NameEmail
|
||||
from pydantic.types import SecretBytes, SecretStr
|
||||
from typing_extensions import Annotated
|
||||
|
||||
from ._compat import Url, _is_undefined, _model_dump
|
||||
|
||||
|
|
@ -61,7 +60,7 @@ def decimal_encoder(dec_value: Decimal) -> Union[int, float]:
|
|||
return float(dec_value)
|
||||
|
||||
|
||||
ENCODERS_BY_TYPE: Dict[Type[Any], Callable[[Any], Any]] = {
|
||||
ENCODERS_BY_TYPE: dict[type[Any], Callable[[Any], Any]] = {
|
||||
bytes: lambda o: o.decode(),
|
||||
Color: str,
|
||||
may_v1.Color: str,
|
||||
|
|
@ -98,9 +97,9 @@ ENCODERS_BY_TYPE: Dict[Type[Any], Callable[[Any], Any]] = {
|
|||
|
||||
|
||||
def generate_encoders_by_class_tuples(
|
||||
type_encoder_map: Dict[Any, Callable[[Any], Any]],
|
||||
) -> Dict[Callable[[Any], Any], Tuple[Any, ...]]:
|
||||
encoders_by_class_tuples: Dict[Callable[[Any], Any], Tuple[Any, ...]] = defaultdict(
|
||||
type_encoder_map: dict[Any, Callable[[Any], Any]],
|
||||
) -> dict[Callable[[Any], Any], tuple[Any, ...]]:
|
||||
encoders_by_class_tuples: dict[Callable[[Any], Any], tuple[Any, ...]] = defaultdict(
|
||||
tuple
|
||||
)
|
||||
for type_, encoder in type_encoder_map.items():
|
||||
|
|
@ -180,7 +179,7 @@ def jsonable_encoder(
|
|||
),
|
||||
] = False,
|
||||
custom_encoder: Annotated[
|
||||
Optional[Dict[Any, Callable[[Any], Any]]],
|
||||
Optional[dict[Any, Callable[[Any], Any]]],
|
||||
Doc(
|
||||
"""
|
||||
Pydantic's `custom_encoder` parameter, passed to Pydantic models to define
|
||||
|
|
@ -227,7 +226,7 @@ def jsonable_encoder(
|
|||
exclude = set(exclude)
|
||||
if isinstance(obj, (BaseModel, may_v1.BaseModel)):
|
||||
# TODO: remove when deprecating Pydantic v1
|
||||
encoders: Dict[Any, Any] = {}
|
||||
encoders: dict[Any, Any] = {}
|
||||
if isinstance(obj, may_v1.BaseModel):
|
||||
encoders = getattr(obj.__config__, "json_encoders", {}) # type: ignore[attr-defined]
|
||||
if custom_encoder:
|
||||
|
|
@ -336,7 +335,7 @@ def jsonable_encoder(
|
|||
try:
|
||||
data = dict(obj)
|
||||
except Exception as e:
|
||||
errors: List[Exception] = []
|
||||
errors: list[Exception] = []
|
||||
errors.append(e)
|
||||
try:
|
||||
data = vars(obj)
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
from typing import Any, Dict, Optional, Sequence, Type, TypedDict, Union
|
||||
from collections.abc import Sequence
|
||||
from typing import Annotated, Any, Optional, TypedDict, Union
|
||||
|
||||
from annotated_doc import Doc
|
||||
from pydantic import BaseModel, create_model
|
||||
from starlette.exceptions import HTTPException as StarletteHTTPException
|
||||
from starlette.exceptions import WebSocketException as StarletteWebSocketException
|
||||
from typing_extensions import Annotated
|
||||
|
||||
|
||||
class EndpointContext(TypedDict, total=False):
|
||||
|
|
@ -62,7 +62,7 @@ class HTTPException(StarletteHTTPException):
|
|||
),
|
||||
] = None,
|
||||
headers: Annotated[
|
||||
Optional[Dict[str, str]],
|
||||
Optional[dict[str, str]],
|
||||
Doc(
|
||||
"""
|
||||
Any headers to send to the client in the response.
|
||||
|
|
@ -144,8 +144,8 @@ class WebSocketException(StarletteWebSocketException):
|
|||
super().__init__(code=code, reason=reason)
|
||||
|
||||
|
||||
RequestErrorModel: Type[BaseModel] = create_model("Request")
|
||||
WebSocketErrorModel: Type[BaseModel] = create_model("WebSocket")
|
||||
RequestErrorModel: type[BaseModel] = create_model("Request")
|
||||
WebSocketErrorModel: type[BaseModel] = create_model("WebSocket")
|
||||
|
||||
|
||||
class FastAPIError(RuntimeError):
|
||||
|
|
|
|||
|
|
@ -1,13 +1,12 @@
|
|||
import json
|
||||
from typing import Any, Dict, Optional
|
||||
from typing import Annotated, Any, Optional
|
||||
|
||||
from annotated_doc import Doc
|
||||
from fastapi.encoders import jsonable_encoder
|
||||
from starlette.responses import HTMLResponse
|
||||
from typing_extensions import Annotated
|
||||
|
||||
swagger_ui_default_parameters: Annotated[
|
||||
Dict[str, Any],
|
||||
dict[str, Any],
|
||||
Doc(
|
||||
"""
|
||||
Default configurations for Swagger UI.
|
||||
|
|
@ -82,7 +81,7 @@ def get_swagger_ui_html(
|
|||
),
|
||||
] = None,
|
||||
init_oauth: Annotated[
|
||||
Optional[Dict[str, Any]],
|
||||
Optional[dict[str, Any]],
|
||||
Doc(
|
||||
"""
|
||||
A dictionary with Swagger UI OAuth2 initialization configurations.
|
||||
|
|
@ -90,7 +89,7 @@ def get_swagger_ui_html(
|
|||
),
|
||||
] = None,
|
||||
swagger_ui_parameters: Annotated[
|
||||
Optional[Dict[str, Any]],
|
||||
Optional[dict[str, Any]],
|
||||
Doc(
|
||||
"""
|
||||
Configuration parameters for Swagger UI.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
from collections.abc import Iterable
|
||||
from enum import Enum
|
||||
from typing import Any, Callable, Dict, Iterable, List, Optional, Set, Type, Union
|
||||
from typing import Annotated, Any, Callable, Optional, Union
|
||||
|
||||
from fastapi._compat import (
|
||||
PYDANTIC_V2,
|
||||
|
|
@ -11,7 +12,7 @@ from fastapi._compat import (
|
|||
)
|
||||
from fastapi.logger import logger
|
||||
from pydantic import AnyUrl, BaseModel, Field
|
||||
from typing_extensions import Annotated, Literal, TypedDict
|
||||
from typing_extensions import Literal, TypedDict
|
||||
from typing_extensions import deprecated as typing_deprecated
|
||||
|
||||
try:
|
||||
|
|
@ -50,7 +51,7 @@ except ImportError: # pragma: no cover
|
|||
|
||||
@classmethod
|
||||
def __get_pydantic_core_schema__(
|
||||
cls, source: Type[Any], handler: Callable[[Any], CoreSchema]
|
||||
cls, source: type[Any], handler: Callable[[Any], CoreSchema]
|
||||
) -> CoreSchema:
|
||||
return with_info_plain_validator_function(cls._validate)
|
||||
|
||||
|
|
@ -88,7 +89,7 @@ class Info(BaseModelWithConfig):
|
|||
|
||||
|
||||
class ServerVariable(BaseModelWithConfig):
|
||||
enum: Annotated[Optional[List[str]], Field(min_length=1)] = None
|
||||
enum: Annotated[Optional[list[str]], Field(min_length=1)] = None
|
||||
default: str
|
||||
description: Optional[str] = None
|
||||
|
||||
|
|
@ -96,7 +97,7 @@ class ServerVariable(BaseModelWithConfig):
|
|||
class Server(BaseModelWithConfig):
|
||||
url: Union[AnyUrl, str]
|
||||
description: Optional[str] = None
|
||||
variables: Optional[Dict[str, ServerVariable]] = None
|
||||
variables: Optional[dict[str, ServerVariable]] = None
|
||||
|
||||
|
||||
class Reference(BaseModel):
|
||||
|
|
@ -105,7 +106,7 @@ class Reference(BaseModel):
|
|||
|
||||
class Discriminator(BaseModel):
|
||||
propertyName: str
|
||||
mapping: Optional[Dict[str, str]] = None
|
||||
mapping: Optional[dict[str, str]] = None
|
||||
|
||||
|
||||
class XML(BaseModelWithConfig):
|
||||
|
|
@ -137,34 +138,34 @@ class Schema(BaseModelWithConfig):
|
|||
dynamicAnchor: Optional[str] = Field(default=None, alias="$dynamicAnchor")
|
||||
ref: Optional[str] = Field(default=None, alias="$ref")
|
||||
dynamicRef: Optional[str] = Field(default=None, alias="$dynamicRef")
|
||||
defs: Optional[Dict[str, "SchemaOrBool"]] = Field(default=None, alias="$defs")
|
||||
defs: Optional[dict[str, "SchemaOrBool"]] = Field(default=None, alias="$defs")
|
||||
comment: Optional[str] = Field(default=None, alias="$comment")
|
||||
# Ref: JSON Schema 2020-12: https://json-schema.org/draft/2020-12/json-schema-core.html#name-a-vocabulary-for-applying-s
|
||||
# A Vocabulary for Applying Subschemas
|
||||
allOf: Optional[List["SchemaOrBool"]] = None
|
||||
anyOf: Optional[List["SchemaOrBool"]] = None
|
||||
oneOf: Optional[List["SchemaOrBool"]] = None
|
||||
allOf: Optional[list["SchemaOrBool"]] = None
|
||||
anyOf: Optional[list["SchemaOrBool"]] = None
|
||||
oneOf: Optional[list["SchemaOrBool"]] = None
|
||||
not_: Optional["SchemaOrBool"] = Field(default=None, alias="not")
|
||||
if_: Optional["SchemaOrBool"] = Field(default=None, alias="if")
|
||||
then: Optional["SchemaOrBool"] = None
|
||||
else_: Optional["SchemaOrBool"] = Field(default=None, alias="else")
|
||||
dependentSchemas: Optional[Dict[str, "SchemaOrBool"]] = None
|
||||
prefixItems: Optional[List["SchemaOrBool"]] = None
|
||||
dependentSchemas: Optional[dict[str, "SchemaOrBool"]] = None
|
||||
prefixItems: Optional[list["SchemaOrBool"]] = None
|
||||
# TODO: uncomment and remove below when deprecating Pydantic v1
|
||||
# It generates a list of schemas for tuples, before prefixItems was available
|
||||
# items: Optional["SchemaOrBool"] = None
|
||||
items: Optional[Union["SchemaOrBool", List["SchemaOrBool"]]] = None
|
||||
items: Optional[Union["SchemaOrBool", list["SchemaOrBool"]]] = None
|
||||
contains: Optional["SchemaOrBool"] = None
|
||||
properties: Optional[Dict[str, "SchemaOrBool"]] = None
|
||||
patternProperties: Optional[Dict[str, "SchemaOrBool"]] = None
|
||||
properties: Optional[dict[str, "SchemaOrBool"]] = None
|
||||
patternProperties: Optional[dict[str, "SchemaOrBool"]] = None
|
||||
additionalProperties: Optional["SchemaOrBool"] = None
|
||||
propertyNames: Optional["SchemaOrBool"] = None
|
||||
unevaluatedItems: Optional["SchemaOrBool"] = None
|
||||
unevaluatedProperties: Optional["SchemaOrBool"] = None
|
||||
# Ref: JSON Schema Validation 2020-12: https://json-schema.org/draft/2020-12/json-schema-validation.html#name-a-vocabulary-for-structural
|
||||
# A Vocabulary for Structural Validation
|
||||
type: Optional[Union[SchemaType, List[SchemaType]]] = None
|
||||
enum: Optional[List[Any]] = None
|
||||
type: Optional[Union[SchemaType, list[SchemaType]]] = None
|
||||
enum: Optional[list[Any]] = None
|
||||
const: Optional[Any] = None
|
||||
multipleOf: Optional[float] = Field(default=None, gt=0)
|
||||
maximum: Optional[float] = None
|
||||
|
|
@ -181,8 +182,8 @@ class Schema(BaseModelWithConfig):
|
|||
minContains: Optional[int] = Field(default=None, ge=0)
|
||||
maxProperties: Optional[int] = Field(default=None, ge=0)
|
||||
minProperties: Optional[int] = Field(default=None, ge=0)
|
||||
required: Optional[List[str]] = None
|
||||
dependentRequired: Optional[Dict[str, Set[str]]] = None
|
||||
required: Optional[list[str]] = None
|
||||
dependentRequired: Optional[dict[str, set[str]]] = None
|
||||
# Ref: JSON Schema Validation 2020-12: https://json-schema.org/draft/2020-12/json-schema-validation.html#name-vocabularies-for-semantic-c
|
||||
# Vocabularies for Semantic Content With "format"
|
||||
format: Optional[str] = None
|
||||
|
|
@ -199,7 +200,7 @@ class Schema(BaseModelWithConfig):
|
|||
deprecated: Optional[bool] = None
|
||||
readOnly: Optional[bool] = None
|
||||
writeOnly: Optional[bool] = None
|
||||
examples: Optional[List[Any]] = None
|
||||
examples: Optional[list[Any]] = None
|
||||
# Ref: OpenAPI 3.1.0: https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#schema-object
|
||||
# Schema Object
|
||||
discriminator: Optional[Discriminator] = None
|
||||
|
|
@ -243,7 +244,7 @@ class ParameterInType(Enum):
|
|||
|
||||
class Encoding(BaseModelWithConfig):
|
||||
contentType: Optional[str] = None
|
||||
headers: Optional[Dict[str, Union["Header", Reference]]] = None
|
||||
headers: Optional[dict[str, Union["Header", Reference]]] = None
|
||||
style: Optional[str] = None
|
||||
explode: Optional[bool] = None
|
||||
allowReserved: Optional[bool] = None
|
||||
|
|
@ -252,8 +253,8 @@ class Encoding(BaseModelWithConfig):
|
|||
class MediaType(BaseModelWithConfig):
|
||||
schema_: Optional[Union[Schema, Reference]] = Field(default=None, alias="schema")
|
||||
example: Optional[Any] = None
|
||||
examples: Optional[Dict[str, Union[Example, Reference]]] = None
|
||||
encoding: Optional[Dict[str, Encoding]] = None
|
||||
examples: Optional[dict[str, Union[Example, Reference]]] = None
|
||||
encoding: Optional[dict[str, Encoding]] = None
|
||||
|
||||
|
||||
class ParameterBase(BaseModelWithConfig):
|
||||
|
|
@ -266,9 +267,9 @@ class ParameterBase(BaseModelWithConfig):
|
|||
allowReserved: Optional[bool] = None
|
||||
schema_: Optional[Union[Schema, Reference]] = Field(default=None, alias="schema")
|
||||
example: Optional[Any] = None
|
||||
examples: Optional[Dict[str, Union[Example, Reference]]] = None
|
||||
examples: Optional[dict[str, Union[Example, Reference]]] = None
|
||||
# Serialization rules for more complex scenarios
|
||||
content: Optional[Dict[str, MediaType]] = None
|
||||
content: Optional[dict[str, MediaType]] = None
|
||||
|
||||
|
||||
class Parameter(ParameterBase):
|
||||
|
|
@ -282,14 +283,14 @@ class Header(ParameterBase):
|
|||
|
||||
class RequestBody(BaseModelWithConfig):
|
||||
description: Optional[str] = None
|
||||
content: Dict[str, MediaType]
|
||||
content: dict[str, MediaType]
|
||||
required: Optional[bool] = None
|
||||
|
||||
|
||||
class Link(BaseModelWithConfig):
|
||||
operationRef: Optional[str] = None
|
||||
operationId: Optional[str] = None
|
||||
parameters: Optional[Dict[str, Union[Any, str]]] = None
|
||||
parameters: Optional[dict[str, Union[Any, str]]] = None
|
||||
requestBody: Optional[Union[Any, str]] = None
|
||||
description: Optional[str] = None
|
||||
server: Optional[Server] = None
|
||||
|
|
@ -297,25 +298,25 @@ class Link(BaseModelWithConfig):
|
|||
|
||||
class Response(BaseModelWithConfig):
|
||||
description: str
|
||||
headers: Optional[Dict[str, Union[Header, Reference]]] = None
|
||||
content: Optional[Dict[str, MediaType]] = None
|
||||
links: Optional[Dict[str, Union[Link, Reference]]] = None
|
||||
headers: Optional[dict[str, Union[Header, Reference]]] = None
|
||||
content: Optional[dict[str, MediaType]] = None
|
||||
links: Optional[dict[str, Union[Link, Reference]]] = None
|
||||
|
||||
|
||||
class Operation(BaseModelWithConfig):
|
||||
tags: Optional[List[str]] = None
|
||||
tags: Optional[list[str]] = None
|
||||
summary: Optional[str] = None
|
||||
description: Optional[str] = None
|
||||
externalDocs: Optional[ExternalDocumentation] = None
|
||||
operationId: Optional[str] = None
|
||||
parameters: Optional[List[Union[Parameter, Reference]]] = None
|
||||
parameters: Optional[list[Union[Parameter, Reference]]] = None
|
||||
requestBody: Optional[Union[RequestBody, Reference]] = None
|
||||
# Using Any for Specification Extensions
|
||||
responses: Optional[Dict[str, Union[Response, Any]]] = None
|
||||
callbacks: Optional[Dict[str, Union[Dict[str, "PathItem"], Reference]]] = None
|
||||
responses: Optional[dict[str, Union[Response, Any]]] = None
|
||||
callbacks: Optional[dict[str, Union[dict[str, "PathItem"], Reference]]] = None
|
||||
deprecated: Optional[bool] = None
|
||||
security: Optional[List[Dict[str, List[str]]]] = None
|
||||
servers: Optional[List[Server]] = None
|
||||
security: Optional[list[dict[str, list[str]]]] = None
|
||||
servers: Optional[list[Server]] = None
|
||||
|
||||
|
||||
class PathItem(BaseModelWithConfig):
|
||||
|
|
@ -330,8 +331,8 @@ class PathItem(BaseModelWithConfig):
|
|||
head: Optional[Operation] = None
|
||||
patch: Optional[Operation] = None
|
||||
trace: Optional[Operation] = None
|
||||
servers: Optional[List[Server]] = None
|
||||
parameters: Optional[List[Union[Parameter, Reference]]] = None
|
||||
servers: Optional[list[Server]] = None
|
||||
parameters: Optional[list[Union[Parameter, Reference]]] = None
|
||||
|
||||
|
||||
class SecuritySchemeType(Enum):
|
||||
|
|
@ -370,7 +371,7 @@ class HTTPBearer(HTTPBase):
|
|||
|
||||
class OAuthFlow(BaseModelWithConfig):
|
||||
refreshUrl: Optional[str] = None
|
||||
scopes: Dict[str, str] = {}
|
||||
scopes: dict[str, str] = {}
|
||||
|
||||
|
||||
class OAuthFlowImplicit(OAuthFlow):
|
||||
|
|
@ -413,17 +414,17 @@ SecurityScheme = Union[APIKey, HTTPBase, OAuth2, OpenIdConnect, HTTPBearer]
|
|||
|
||||
|
||||
class Components(BaseModelWithConfig):
|
||||
schemas: Optional[Dict[str, Union[Schema, Reference]]] = None
|
||||
responses: Optional[Dict[str, Union[Response, Reference]]] = None
|
||||
parameters: Optional[Dict[str, Union[Parameter, Reference]]] = None
|
||||
examples: Optional[Dict[str, Union[Example, Reference]]] = None
|
||||
requestBodies: Optional[Dict[str, Union[RequestBody, Reference]]] = None
|
||||
headers: Optional[Dict[str, Union[Header, Reference]]] = None
|
||||
securitySchemes: Optional[Dict[str, Union[SecurityScheme, Reference]]] = None
|
||||
links: Optional[Dict[str, Union[Link, Reference]]] = None
|
||||
schemas: Optional[dict[str, Union[Schema, Reference]]] = None
|
||||
responses: Optional[dict[str, Union[Response, Reference]]] = None
|
||||
parameters: Optional[dict[str, Union[Parameter, Reference]]] = None
|
||||
examples: Optional[dict[str, Union[Example, Reference]]] = None
|
||||
requestBodies: Optional[dict[str, Union[RequestBody, Reference]]] = None
|
||||
headers: Optional[dict[str, Union[Header, Reference]]] = None
|
||||
securitySchemes: Optional[dict[str, Union[SecurityScheme, Reference]]] = None
|
||||
links: Optional[dict[str, Union[Link, Reference]]] = None
|
||||
# Using Any for Specification Extensions
|
||||
callbacks: Optional[Dict[str, Union[Dict[str, PathItem], Reference, Any]]] = None
|
||||
pathItems: Optional[Dict[str, Union[PathItem, Reference]]] = None
|
||||
callbacks: Optional[dict[str, Union[dict[str, PathItem], Reference, Any]]] = None
|
||||
pathItems: Optional[dict[str, Union[PathItem, Reference]]] = None
|
||||
|
||||
|
||||
class Tag(BaseModelWithConfig):
|
||||
|
|
@ -436,13 +437,13 @@ class OpenAPI(BaseModelWithConfig):
|
|||
openapi: str
|
||||
info: Info
|
||||
jsonSchemaDialect: Optional[str] = None
|
||||
servers: Optional[List[Server]] = None
|
||||
servers: Optional[list[Server]] = None
|
||||
# Using Any for Specification Extensions
|
||||
paths: Optional[Dict[str, Union[PathItem, Any]]] = None
|
||||
webhooks: Optional[Dict[str, Union[PathItem, Reference]]] = None
|
||||
paths: Optional[dict[str, Union[PathItem, Any]]] = None
|
||||
webhooks: Optional[dict[str, Union[PathItem, Reference]]] = None
|
||||
components: Optional[Components] = None
|
||||
security: Optional[List[Dict[str, List[str]]]] = None
|
||||
tags: Optional[List[Tag]] = None
|
||||
security: Optional[list[dict[str, list[str]]]] = None
|
||||
tags: Optional[list[Tag]] = None
|
||||
externalDocs: Optional[ExternalDocumentation] = None
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
import http.client
|
||||
import inspect
|
||||
import warnings
|
||||
from typing import Any, Dict, List, Optional, Sequence, Set, Tuple, Type, Union, cast
|
||||
from collections.abc import Sequence
|
||||
from typing import Any, Optional, Union, cast
|
||||
|
||||
from fastapi import routing
|
||||
from fastapi._compat import (
|
||||
|
|
@ -66,7 +67,7 @@ validation_error_response_definition = {
|
|||
},
|
||||
}
|
||||
|
||||
status_code_ranges: Dict[str, str] = {
|
||||
status_code_ranges: dict[str, str] = {
|
||||
"1XX": "Information",
|
||||
"2XX": "Success",
|
||||
"3XX": "Redirection",
|
||||
|
|
@ -78,10 +79,10 @@ status_code_ranges: Dict[str, str] = {
|
|||
|
||||
def get_openapi_security_definitions(
|
||||
flat_dependant: Dependant,
|
||||
) -> Tuple[Dict[str, Any], List[Dict[str, Any]]]:
|
||||
) -> tuple[dict[str, Any], list[dict[str, Any]]]:
|
||||
security_definitions = {}
|
||||
# Use a dict to merge scopes for same security scheme
|
||||
operation_security_dict: Dict[str, List[str]] = {}
|
||||
operation_security_dict: dict[str, list[str]] = {}
|
||||
for security_dependency in flat_dependant._security_dependencies:
|
||||
security_definition = jsonable_encoder(
|
||||
security_dependency._security_scheme.model,
|
||||
|
|
@ -106,11 +107,11 @@ def _get_openapi_operation_parameters(
|
|||
*,
|
||||
dependant: Dependant,
|
||||
model_name_map: ModelNameMap,
|
||||
field_mapping: Dict[
|
||||
Tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue
|
||||
field_mapping: dict[
|
||||
tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue
|
||||
],
|
||||
separate_input_output_schemas: bool = True,
|
||||
) -> List[Dict[str, Any]]:
|
||||
) -> list[dict[str, Any]]:
|
||||
parameters = []
|
||||
flat_dependant = get_flat_dependant(dependant, skip_repeats=True)
|
||||
path_params = _get_flat_fields_from_params(flat_dependant.path_params)
|
||||
|
|
@ -179,11 +180,11 @@ def get_openapi_operation_request_body(
|
|||
*,
|
||||
body_field: Optional[ModelField],
|
||||
model_name_map: ModelNameMap,
|
||||
field_mapping: Dict[
|
||||
Tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue
|
||||
field_mapping: dict[
|
||||
tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue
|
||||
],
|
||||
separate_input_output_schemas: bool = True,
|
||||
) -> Optional[Dict[str, Any]]:
|
||||
) -> Optional[dict[str, Any]]:
|
||||
if not body_field:
|
||||
return None
|
||||
assert _is_model_field(body_field)
|
||||
|
|
@ -196,10 +197,10 @@ def get_openapi_operation_request_body(
|
|||
field_info = cast(Body, body_field.field_info)
|
||||
request_media_type = field_info.media_type
|
||||
required = body_field.required
|
||||
request_body_oai: Dict[str, Any] = {}
|
||||
request_body_oai: dict[str, Any] = {}
|
||||
if required:
|
||||
request_body_oai["required"] = required
|
||||
request_media_content: Dict[str, Any] = {"schema": body_schema}
|
||||
request_media_content: dict[str, Any] = {"schema": body_schema}
|
||||
if field_info.openapi_examples:
|
||||
request_media_content["examples"] = jsonable_encoder(
|
||||
field_info.openapi_examples
|
||||
|
|
@ -232,9 +233,9 @@ def generate_operation_summary(*, route: routing.APIRoute, method: str) -> str:
|
|||
|
||||
|
||||
def get_openapi_operation_metadata(
|
||||
*, route: routing.APIRoute, method: str, operation_ids: Set[str]
|
||||
) -> Dict[str, Any]:
|
||||
operation: Dict[str, Any] = {}
|
||||
*, route: routing.APIRoute, method: str, operation_ids: set[str]
|
||||
) -> dict[str, Any]:
|
||||
operation: dict[str, Any] = {}
|
||||
if route.tags:
|
||||
operation["tags"] = route.tags
|
||||
operation["summary"] = generate_operation_summary(route=route, method=method)
|
||||
|
|
@ -260,19 +261,19 @@ def get_openapi_operation_metadata(
|
|||
def get_openapi_path(
|
||||
*,
|
||||
route: routing.APIRoute,
|
||||
operation_ids: Set[str],
|
||||
operation_ids: set[str],
|
||||
model_name_map: ModelNameMap,
|
||||
field_mapping: Dict[
|
||||
Tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue
|
||||
field_mapping: dict[
|
||||
tuple[ModelField, Literal["validation", "serialization"]], JsonSchemaValue
|
||||
],
|
||||
separate_input_output_schemas: bool = True,
|
||||
) -> Tuple[Dict[str, Any], Dict[str, Any], Dict[str, Any]]:
|
||||
) -> tuple[dict[str, Any], dict[str, Any], dict[str, Any]]:
|
||||
path = {}
|
||||
security_schemes: Dict[str, Any] = {}
|
||||
definitions: Dict[str, Any] = {}
|
||||
security_schemes: dict[str, Any] = {}
|
||||
definitions: dict[str, Any] = {}
|
||||
assert route.methods is not None, "Methods must be a list"
|
||||
if isinstance(route.response_class, DefaultPlaceholder):
|
||||
current_response_class: Type[Response] = route.response_class.value
|
||||
current_response_class: type[Response] = route.response_class.value
|
||||
else:
|
||||
current_response_class = route.response_class
|
||||
assert current_response_class, "A response class is needed to generate OpenAPI"
|
||||
|
|
@ -282,7 +283,7 @@ def get_openapi_path(
|
|||
operation = get_openapi_operation_metadata(
|
||||
route=route, method=method, operation_ids=operation_ids
|
||||
)
|
||||
parameters: List[Dict[str, Any]] = []
|
||||
parameters: list[dict[str, Any]] = []
|
||||
flat_dependant = get_flat_dependant(route.dependant, skip_repeats=True)
|
||||
security_definitions, operation_security = get_openapi_security_definitions(
|
||||
flat_dependant=flat_dependant
|
||||
|
|
@ -390,7 +391,7 @@ def get_openapi_path(
|
|||
"An additional response must be a dict"
|
||||
)
|
||||
field = route.response_fields.get(additional_status_code)
|
||||
additional_field_schema: Optional[Dict[str, Any]] = None
|
||||
additional_field_schema: Optional[dict[str, Any]] = None
|
||||
if field:
|
||||
additional_field_schema = get_schema_from_model_field(
|
||||
field=field,
|
||||
|
|
@ -445,11 +446,11 @@ def get_openapi_path(
|
|||
|
||||
def get_fields_from_routes(
|
||||
routes: Sequence[BaseRoute],
|
||||
) -> List[ModelField]:
|
||||
body_fields_from_routes: List[ModelField] = []
|
||||
responses_from_routes: List[ModelField] = []
|
||||
request_fields_from_routes: List[ModelField] = []
|
||||
callback_flat_models: List[ModelField] = []
|
||||
) -> list[ModelField]:
|
||||
body_fields_from_routes: list[ModelField] = []
|
||||
responses_from_routes: list[ModelField] = []
|
||||
request_fields_from_routes: list[ModelField] = []
|
||||
callback_flat_models: list[ModelField] = []
|
||||
for route in routes:
|
||||
if getattr(route, "include_in_schema", None) and isinstance(
|
||||
route, routing.APIRoute
|
||||
|
|
@ -483,15 +484,15 @@ def get_openapi(
|
|||
description: Optional[str] = None,
|
||||
routes: Sequence[BaseRoute],
|
||||
webhooks: Optional[Sequence[BaseRoute]] = None,
|
||||
tags: Optional[List[Dict[str, Any]]] = None,
|
||||
servers: Optional[List[Dict[str, Union[str, Any]]]] = None,
|
||||
tags: Optional[list[dict[str, Any]]] = None,
|
||||
servers: Optional[list[dict[str, Union[str, Any]]]] = None,
|
||||
terms_of_service: Optional[str] = None,
|
||||
contact: Optional[Dict[str, Union[str, Any]]] = None,
|
||||
license_info: Optional[Dict[str, Union[str, Any]]] = None,
|
||||
contact: Optional[dict[str, Union[str, Any]]] = None,
|
||||
license_info: Optional[dict[str, Union[str, Any]]] = None,
|
||||
separate_input_output_schemas: bool = True,
|
||||
external_docs: Optional[Dict[str, Any]] = None,
|
||||
) -> Dict[str, Any]:
|
||||
info: Dict[str, Any] = {"title": title, "version": version}
|
||||
external_docs: Optional[dict[str, Any]] = None,
|
||||
) -> dict[str, Any]:
|
||||
info: dict[str, Any] = {"title": title, "version": version}
|
||||
if summary:
|
||||
info["summary"] = summary
|
||||
if description:
|
||||
|
|
@ -502,13 +503,13 @@ def get_openapi(
|
|||
info["contact"] = contact
|
||||
if license_info:
|
||||
info["license"] = license_info
|
||||
output: Dict[str, Any] = {"openapi": openapi_version, "info": info}
|
||||
output: dict[str, Any] = {"openapi": openapi_version, "info": info}
|
||||
if servers:
|
||||
output["servers"] = servers
|
||||
components: Dict[str, Dict[str, Any]] = {}
|
||||
paths: Dict[str, Dict[str, Any]] = {}
|
||||
webhook_paths: Dict[str, Dict[str, Any]] = {}
|
||||
operation_ids: Set[str] = set()
|
||||
components: dict[str, dict[str, Any]] = {}
|
||||
paths: dict[str, dict[str, Any]] = {}
|
||||
webhook_paths: dict[str, dict[str, Any]] = {}
|
||||
operation_ids: set[str] = set()
|
||||
all_fields = get_fields_from_routes(list(routes or []) + list(webhooks or []))
|
||||
model_name_map = get_compat_model_name_map(all_fields)
|
||||
field_mapping, definitions = get_definitions(
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
from typing import Any, Callable, Dict, List, Optional, Sequence, Union
|
||||
from collections.abc import Sequence
|
||||
from typing import Annotated, Any, Callable, Optional, Union
|
||||
|
||||
from annotated_doc import Doc
|
||||
from fastapi import params
|
||||
from fastapi._compat import Undefined
|
||||
from fastapi.openapi.models import Example
|
||||
from typing_extensions import Annotated, Literal, deprecated
|
||||
from typing_extensions import Literal, deprecated
|
||||
|
||||
_Unset: Any = Undefined
|
||||
|
||||
|
|
@ -209,7 +210,7 @@ def Path( # noqa: N802
|
|||
),
|
||||
] = _Unset,
|
||||
examples: Annotated[
|
||||
Optional[List[Any]],
|
||||
Optional[list[Any]],
|
||||
Doc(
|
||||
"""
|
||||
Example values for this field.
|
||||
|
|
@ -224,7 +225,7 @@ def Path( # noqa: N802
|
|||
),
|
||||
] = _Unset,
|
||||
openapi_examples: Annotated[
|
||||
Optional[Dict[str, Example]],
|
||||
Optional[dict[str, Example]],
|
||||
Doc(
|
||||
"""
|
||||
OpenAPI-specific examples.
|
||||
|
|
@ -262,7 +263,7 @@ def Path( # noqa: N802
|
|||
),
|
||||
] = True,
|
||||
json_schema_extra: Annotated[
|
||||
Union[Dict[str, Any], None],
|
||||
Union[dict[str, Any], None],
|
||||
Doc(
|
||||
"""
|
||||
Any additional JSON schema data.
|
||||
|
|
@ -534,7 +535,7 @@ def Query( # noqa: N802
|
|||
),
|
||||
] = _Unset,
|
||||
examples: Annotated[
|
||||
Optional[List[Any]],
|
||||
Optional[list[Any]],
|
||||
Doc(
|
||||
"""
|
||||
Example values for this field.
|
||||
|
|
@ -549,7 +550,7 @@ def Query( # noqa: N802
|
|||
),
|
||||
] = _Unset,
|
||||
openapi_examples: Annotated[
|
||||
Optional[Dict[str, Example]],
|
||||
Optional[dict[str, Example]],
|
||||
Doc(
|
||||
"""
|
||||
OpenAPI-specific examples.
|
||||
|
|
@ -587,7 +588,7 @@ def Query( # noqa: N802
|
|||
),
|
||||
] = True,
|
||||
json_schema_extra: Annotated[
|
||||
Union[Dict[str, Any], None],
|
||||
Union[dict[str, Any], None],
|
||||
Doc(
|
||||
"""
|
||||
Any additional JSON schema data.
|
||||
|
|
@ -849,7 +850,7 @@ def Header( # noqa: N802
|
|||
),
|
||||
] = _Unset,
|
||||
examples: Annotated[
|
||||
Optional[List[Any]],
|
||||
Optional[list[Any]],
|
||||
Doc(
|
||||
"""
|
||||
Example values for this field.
|
||||
|
|
@ -864,7 +865,7 @@ def Header( # noqa: N802
|
|||
),
|
||||
] = _Unset,
|
||||
openapi_examples: Annotated[
|
||||
Optional[Dict[str, Example]],
|
||||
Optional[dict[str, Example]],
|
||||
Doc(
|
||||
"""
|
||||
OpenAPI-specific examples.
|
||||
|
|
@ -902,7 +903,7 @@ def Header( # noqa: N802
|
|||
),
|
||||
] = True,
|
||||
json_schema_extra: Annotated[
|
||||
Union[Dict[str, Any], None],
|
||||
Union[dict[str, Any], None],
|
||||
Doc(
|
||||
"""
|
||||
Any additional JSON schema data.
|
||||
|
|
@ -1154,7 +1155,7 @@ def Cookie( # noqa: N802
|
|||
),
|
||||
] = _Unset,
|
||||
examples: Annotated[
|
||||
Optional[List[Any]],
|
||||
Optional[list[Any]],
|
||||
Doc(
|
||||
"""
|
||||
Example values for this field.
|
||||
|
|
@ -1169,7 +1170,7 @@ def Cookie( # noqa: N802
|
|||
),
|
||||
] = _Unset,
|
||||
openapi_examples: Annotated[
|
||||
Optional[Dict[str, Example]],
|
||||
Optional[dict[str, Example]],
|
||||
Doc(
|
||||
"""
|
||||
OpenAPI-specific examples.
|
||||
|
|
@ -1207,7 +1208,7 @@ def Cookie( # noqa: N802
|
|||
),
|
||||
] = True,
|
||||
json_schema_extra: Annotated[
|
||||
Union[Dict[str, Any], None],
|
||||
Union[dict[str, Any], None],
|
||||
Doc(
|
||||
"""
|
||||
Any additional JSON schema data.
|
||||
|
|
@ -1481,7 +1482,7 @@ def Body( # noqa: N802
|
|||
),
|
||||
] = _Unset,
|
||||
examples: Annotated[
|
||||
Optional[List[Any]],
|
||||
Optional[list[Any]],
|
||||
Doc(
|
||||
"""
|
||||
Example values for this field.
|
||||
|
|
@ -1496,7 +1497,7 @@ def Body( # noqa: N802
|
|||
),
|
||||
] = _Unset,
|
||||
openapi_examples: Annotated[
|
||||
Optional[Dict[str, Example]],
|
||||
Optional[dict[str, Example]],
|
||||
Doc(
|
||||
"""
|
||||
OpenAPI-specific examples.
|
||||
|
|
@ -1534,7 +1535,7 @@ def Body( # noqa: N802
|
|||
),
|
||||
] = True,
|
||||
json_schema_extra: Annotated[
|
||||
Union[Dict[str, Any], None],
|
||||
Union[dict[str, Any], None],
|
||||
Doc(
|
||||
"""
|
||||
Any additional JSON schema data.
|
||||
|
|
@ -1796,7 +1797,7 @@ def Form( # noqa: N802
|
|||
),
|
||||
] = _Unset,
|
||||
examples: Annotated[
|
||||
Optional[List[Any]],
|
||||
Optional[list[Any]],
|
||||
Doc(
|
||||
"""
|
||||
Example values for this field.
|
||||
|
|
@ -1811,7 +1812,7 @@ def Form( # noqa: N802
|
|||
),
|
||||
] = _Unset,
|
||||
openapi_examples: Annotated[
|
||||
Optional[Dict[str, Example]],
|
||||
Optional[dict[str, Example]],
|
||||
Doc(
|
||||
"""
|
||||
OpenAPI-specific examples.
|
||||
|
|
@ -1849,7 +1850,7 @@ def Form( # noqa: N802
|
|||
),
|
||||
] = True,
|
||||
json_schema_extra: Annotated[
|
||||
Union[Dict[str, Any], None],
|
||||
Union[dict[str, Any], None],
|
||||
Doc(
|
||||
"""
|
||||
Any additional JSON schema data.
|
||||
|
|
@ -2110,7 +2111,7 @@ def File( # noqa: N802
|
|||
),
|
||||
] = _Unset,
|
||||
examples: Annotated[
|
||||
Optional[List[Any]],
|
||||
Optional[list[Any]],
|
||||
Doc(
|
||||
"""
|
||||
Example values for this field.
|
||||
|
|
@ -2125,7 +2126,7 @@ def File( # noqa: N802
|
|||
),
|
||||
] = _Unset,
|
||||
openapi_examples: Annotated[
|
||||
Optional[Dict[str, Example]],
|
||||
Optional[dict[str, Example]],
|
||||
Doc(
|
||||
"""
|
||||
OpenAPI-specific examples.
|
||||
|
|
@ -2163,7 +2164,7 @@ def File( # noqa: N802
|
|||
),
|
||||
] = True,
|
||||
json_schema_extra: Annotated[
|
||||
Union[Dict[str, Any], None],
|
||||
Union[dict[str, Any], None],
|
||||
Doc(
|
||||
"""
|
||||
Any additional JSON schema data.
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
import warnings
|
||||
from collections.abc import Sequence
|
||||
from dataclasses import dataclass
|
||||
from enum import Enum
|
||||
from typing import Any, Callable, Dict, List, Optional, Sequence, Union
|
||||
from typing import Annotated, Any, Callable, Optional, Union
|
||||
|
||||
from fastapi.openapi.models import Example
|
||||
from pydantic.fields import FieldInfo
|
||||
from typing_extensions import Annotated, Literal, deprecated
|
||||
from typing_extensions import Literal, deprecated
|
||||
|
||||
from ._compat import (
|
||||
PYDANTIC_V2,
|
||||
|
|
@ -59,7 +60,7 @@ class Param(FieldInfo): # type: ignore[misc]
|
|||
allow_inf_nan: Union[bool, None] = _Unset,
|
||||
max_digits: Union[int, None] = _Unset,
|
||||
decimal_places: Union[int, None] = _Unset,
|
||||
examples: Optional[List[Any]] = None,
|
||||
examples: Optional[list[Any]] = None,
|
||||
example: Annotated[
|
||||
Optional[Any],
|
||||
deprecated(
|
||||
|
|
@ -67,10 +68,10 @@ class Param(FieldInfo): # type: ignore[misc]
|
|||
"although still supported. Use examples instead."
|
||||
),
|
||||
] = _Unset,
|
||||
openapi_examples: Optional[Dict[str, Example]] = None,
|
||||
openapi_examples: Optional[dict[str, Example]] = None,
|
||||
deprecated: Union[deprecated, str, bool, None] = None,
|
||||
include_in_schema: bool = True,
|
||||
json_schema_extra: Union[Dict[str, Any], None] = None,
|
||||
json_schema_extra: Union[dict[str, Any], None] = None,
|
||||
**extra: Any,
|
||||
):
|
||||
if example is not _Unset:
|
||||
|
|
@ -177,7 +178,7 @@ class Path(Param): # type: ignore[misc]
|
|||
allow_inf_nan: Union[bool, None] = _Unset,
|
||||
max_digits: Union[int, None] = _Unset,
|
||||
decimal_places: Union[int, None] = _Unset,
|
||||
examples: Optional[List[Any]] = None,
|
||||
examples: Optional[list[Any]] = None,
|
||||
example: Annotated[
|
||||
Optional[Any],
|
||||
deprecated(
|
||||
|
|
@ -185,10 +186,10 @@ class Path(Param): # type: ignore[misc]
|
|||
"although still supported. Use examples instead."
|
||||
),
|
||||
] = _Unset,
|
||||
openapi_examples: Optional[Dict[str, Example]] = None,
|
||||
openapi_examples: Optional[dict[str, Example]] = None,
|
||||
deprecated: Union[deprecated, str, bool, None] = None,
|
||||
include_in_schema: bool = True,
|
||||
json_schema_extra: Union[Dict[str, Any], None] = None,
|
||||
json_schema_extra: Union[dict[str, Any], None] = None,
|
||||
**extra: Any,
|
||||
):
|
||||
assert default is ..., "Path parameters cannot have a default value"
|
||||
|
|
@ -263,7 +264,7 @@ class Query(Param): # type: ignore[misc]
|
|||
allow_inf_nan: Union[bool, None] = _Unset,
|
||||
max_digits: Union[int, None] = _Unset,
|
||||
decimal_places: Union[int, None] = _Unset,
|
||||
examples: Optional[List[Any]] = None,
|
||||
examples: Optional[list[Any]] = None,
|
||||
example: Annotated[
|
||||
Optional[Any],
|
||||
deprecated(
|
||||
|
|
@ -271,10 +272,10 @@ class Query(Param): # type: ignore[misc]
|
|||
"although still supported. Use examples instead."
|
||||
),
|
||||
] = _Unset,
|
||||
openapi_examples: Optional[Dict[str, Example]] = None,
|
||||
openapi_examples: Optional[dict[str, Example]] = None,
|
||||
deprecated: Union[deprecated, str, bool, None] = None,
|
||||
include_in_schema: bool = True,
|
||||
json_schema_extra: Union[Dict[str, Any], None] = None,
|
||||
json_schema_extra: Union[dict[str, Any], None] = None,
|
||||
**extra: Any,
|
||||
):
|
||||
super().__init__(
|
||||
|
|
@ -348,7 +349,7 @@ class Header(Param): # type: ignore[misc]
|
|||
allow_inf_nan: Union[bool, None] = _Unset,
|
||||
max_digits: Union[int, None] = _Unset,
|
||||
decimal_places: Union[int, None] = _Unset,
|
||||
examples: Optional[List[Any]] = None,
|
||||
examples: Optional[list[Any]] = None,
|
||||
example: Annotated[
|
||||
Optional[Any],
|
||||
deprecated(
|
||||
|
|
@ -356,10 +357,10 @@ class Header(Param): # type: ignore[misc]
|
|||
"although still supported. Use examples instead."
|
||||
),
|
||||
] = _Unset,
|
||||
openapi_examples: Optional[Dict[str, Example]] = None,
|
||||
openapi_examples: Optional[dict[str, Example]] = None,
|
||||
deprecated: Union[deprecated, str, bool, None] = None,
|
||||
include_in_schema: bool = True,
|
||||
json_schema_extra: Union[Dict[str, Any], None] = None,
|
||||
json_schema_extra: Union[dict[str, Any], None] = None,
|
||||
**extra: Any,
|
||||
):
|
||||
self.convert_underscores = convert_underscores
|
||||
|
|
@ -433,7 +434,7 @@ class Cookie(Param): # type: ignore[misc]
|
|||
allow_inf_nan: Union[bool, None] = _Unset,
|
||||
max_digits: Union[int, None] = _Unset,
|
||||
decimal_places: Union[int, None] = _Unset,
|
||||
examples: Optional[List[Any]] = None,
|
||||
examples: Optional[list[Any]] = None,
|
||||
example: Annotated[
|
||||
Optional[Any],
|
||||
deprecated(
|
||||
|
|
@ -441,10 +442,10 @@ class Cookie(Param): # type: ignore[misc]
|
|||
"although still supported. Use examples instead."
|
||||
),
|
||||
] = _Unset,
|
||||
openapi_examples: Optional[Dict[str, Example]] = None,
|
||||
openapi_examples: Optional[dict[str, Example]] = None,
|
||||
deprecated: Union[deprecated, str, bool, None] = None,
|
||||
include_in_schema: bool = True,
|
||||
json_schema_extra: Union[Dict[str, Any], None] = None,
|
||||
json_schema_extra: Union[dict[str, Any], None] = None,
|
||||
**extra: Any,
|
||||
):
|
||||
super().__init__(
|
||||
|
|
@ -517,7 +518,7 @@ class Body(FieldInfo): # type: ignore[misc]
|
|||
allow_inf_nan: Union[bool, None] = _Unset,
|
||||
max_digits: Union[int, None] = _Unset,
|
||||
decimal_places: Union[int, None] = _Unset,
|
||||
examples: Optional[List[Any]] = None,
|
||||
examples: Optional[list[Any]] = None,
|
||||
example: Annotated[
|
||||
Optional[Any],
|
||||
deprecated(
|
||||
|
|
@ -525,10 +526,10 @@ class Body(FieldInfo): # type: ignore[misc]
|
|||
"although still supported. Use examples instead."
|
||||
),
|
||||
] = _Unset,
|
||||
openapi_examples: Optional[Dict[str, Example]] = None,
|
||||
openapi_examples: Optional[dict[str, Example]] = None,
|
||||
deprecated: Union[deprecated, str, bool, None] = None,
|
||||
include_in_schema: bool = True,
|
||||
json_schema_extra: Union[Dict[str, Any], None] = None,
|
||||
json_schema_extra: Union[dict[str, Any], None] = None,
|
||||
**extra: Any,
|
||||
):
|
||||
self.embed = embed
|
||||
|
|
@ -637,7 +638,7 @@ class Form(Body): # type: ignore[misc]
|
|||
allow_inf_nan: Union[bool, None] = _Unset,
|
||||
max_digits: Union[int, None] = _Unset,
|
||||
decimal_places: Union[int, None] = _Unset,
|
||||
examples: Optional[List[Any]] = None,
|
||||
examples: Optional[list[Any]] = None,
|
||||
example: Annotated[
|
||||
Optional[Any],
|
||||
deprecated(
|
||||
|
|
@ -645,10 +646,10 @@ class Form(Body): # type: ignore[misc]
|
|||
"although still supported. Use examples instead."
|
||||
),
|
||||
] = _Unset,
|
||||
openapi_examples: Optional[Dict[str, Example]] = None,
|
||||
openapi_examples: Optional[dict[str, Example]] = None,
|
||||
deprecated: Union[deprecated, str, bool, None] = None,
|
||||
include_in_schema: bool = True,
|
||||
json_schema_extra: Union[Dict[str, Any], None] = None,
|
||||
json_schema_extra: Union[dict[str, Any], None] = None,
|
||||
**extra: Any,
|
||||
):
|
||||
super().__init__(
|
||||
|
|
@ -721,7 +722,7 @@ class File(Form): # type: ignore[misc]
|
|||
allow_inf_nan: Union[bool, None] = _Unset,
|
||||
max_digits: Union[int, None] = _Unset,
|
||||
decimal_places: Union[int, None] = _Unset,
|
||||
examples: Optional[List[Any]] = None,
|
||||
examples: Optional[list[Any]] = None,
|
||||
example: Annotated[
|
||||
Optional[Any],
|
||||
deprecated(
|
||||
|
|
@ -729,10 +730,10 @@ class File(Form): # type: ignore[misc]
|
|||
"although still supported. Use examples instead."
|
||||
),
|
||||
] = _Unset,
|
||||
openapi_examples: Optional[Dict[str, Example]] = None,
|
||||
openapi_examples: Optional[dict[str, Example]] = None,
|
||||
deprecated: Union[deprecated, str, bool, None] = None,
|
||||
include_in_schema: bool = True,
|
||||
json_schema_extra: Union[Dict[str, Any], None] = None,
|
||||
json_schema_extra: Union[dict[str, Any], None] = None,
|
||||
**extra: Any,
|
||||
):
|
||||
super().__init__(
|
||||
|
|
|
|||
|
|
@ -3,23 +3,21 @@ import email.message
|
|||
import functools
|
||||
import inspect
|
||||
import json
|
||||
from collections.abc import (
|
||||
AsyncIterator,
|
||||
Awaitable,
|
||||
Collection,
|
||||
Coroutine,
|
||||
Mapping,
|
||||
Sequence,
|
||||
)
|
||||
from contextlib import AsyncExitStack, asynccontextmanager
|
||||
from enum import Enum, IntEnum
|
||||
from typing import (
|
||||
Annotated,
|
||||
Any,
|
||||
AsyncIterator,
|
||||
Awaitable,
|
||||
Callable,
|
||||
Collection,
|
||||
Coroutine,
|
||||
Dict,
|
||||
List,
|
||||
Mapping,
|
||||
Optional,
|
||||
Sequence,
|
||||
Set,
|
||||
Tuple,
|
||||
Type,
|
||||
Union,
|
||||
)
|
||||
|
||||
|
|
@ -77,7 +75,7 @@ from starlette.routing import (
|
|||
from starlette.routing import Mount as Mount # noqa
|
||||
from starlette.types import AppType, ASGIApp, Lifespan, Receive, Scope, Send
|
||||
from starlette.websockets import WebSocket
|
||||
from typing_extensions import Annotated, deprecated
|
||||
from typing_extensions import deprecated
|
||||
|
||||
|
||||
# Copy of starlette.routing.request_response modified to include the
|
||||
|
|
@ -214,7 +212,7 @@ def _merge_lifespan_context(
|
|||
|
||||
|
||||
# Cache for endpoint context to avoid re-extracting on every request
|
||||
_endpoint_context_cache: Dict[int, EndpointContext] = {}
|
||||
_endpoint_context_cache: dict[int, EndpointContext] = {}
|
||||
|
||||
|
||||
def _extract_endpoint_context(func: Any) -> EndpointContext:
|
||||
|
|
@ -306,7 +304,7 @@ async def serialize_response(
|
|||
|
||||
|
||||
async def run_endpoint_function(
|
||||
*, dependant: Dependant, values: Dict[str, Any], is_coroutine: bool
|
||||
*, dependant: Dependant, values: dict[str, Any], is_coroutine: bool
|
||||
) -> Any:
|
||||
# Only called by get_request_handler. Has been split into its own function to
|
||||
# facilitate profiling endpoints, since inner functions are harder to profile.
|
||||
|
|
@ -322,7 +320,7 @@ def get_request_handler(
|
|||
dependant: Dependant,
|
||||
body_field: Optional[ModelField] = None,
|
||||
status_code: Optional[int] = None,
|
||||
response_class: Union[Type[Response], DefaultPlaceholder] = Default(JSONResponse),
|
||||
response_class: Union[type[Response], DefaultPlaceholder] = Default(JSONResponse),
|
||||
response_field: Optional[ModelField] = None,
|
||||
response_model_include: Optional[IncEx] = None,
|
||||
response_model_exclude: Optional[IncEx] = None,
|
||||
|
|
@ -339,7 +337,7 @@ def get_request_handler(
|
|||
body_field.field_info, (params.Form, temp_pydantic_v1_params.Form)
|
||||
)
|
||||
if isinstance(response_class, DefaultPlaceholder):
|
||||
actual_response_class: Type[Response] = response_class.value
|
||||
actual_response_class: type[Response] = response_class.value
|
||||
else:
|
||||
actual_response_class = response_class
|
||||
|
||||
|
|
@ -412,7 +410,7 @@ def get_request_handler(
|
|||
raise http_error from e
|
||||
|
||||
# Solve dependencies and run path operation function, auto-closing dependencies
|
||||
errors: List[Any] = []
|
||||
errors: list[Any] = []
|
||||
async_exit_stack = request.scope.get("fastapi_inner_astack")
|
||||
assert isinstance(async_exit_stack, AsyncExitStack), (
|
||||
"fastapi_inner_astack not found in request scope"
|
||||
|
|
@ -437,7 +435,7 @@ def get_request_handler(
|
|||
raw_response.background = solved_result.background_tasks
|
||||
response = raw_response
|
||||
else:
|
||||
response_args: Dict[str, Any] = {
|
||||
response_args: dict[str, Any] = {
|
||||
"background": solved_result.background_tasks
|
||||
}
|
||||
# If status_code was set, use it, otherwise use the default from the
|
||||
|
|
@ -550,7 +548,7 @@ class APIWebSocketRoute(routing.WebSocketRoute):
|
|||
)
|
||||
)
|
||||
|
||||
def matches(self, scope: Scope) -> Tuple[Match, Scope]:
|
||||
def matches(self, scope: Scope) -> tuple[Match, Scope]:
|
||||
match, child_scope = super().matches(scope)
|
||||
if match != Match.NONE:
|
||||
child_scope["route"] = self
|
||||
|
|
@ -565,15 +563,15 @@ class APIRoute(routing.Route):
|
|||
*,
|
||||
response_model: Any = Default(None),
|
||||
status_code: Optional[int] = None,
|
||||
tags: Optional[List[Union[str, Enum]]] = None,
|
||||
tags: Optional[list[Union[str, Enum]]] = None,
|
||||
dependencies: Optional[Sequence[params.Depends]] = None,
|
||||
summary: Optional[str] = None,
|
||||
description: Optional[str] = None,
|
||||
response_description: str = "Successful Response",
|
||||
responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None,
|
||||
responses: Optional[dict[Union[int, str], dict[str, Any]]] = None,
|
||||
deprecated: Optional[bool] = None,
|
||||
name: Optional[str] = None,
|
||||
methods: Optional[Union[Set[str], List[str]]] = None,
|
||||
methods: Optional[Union[set[str], list[str]]] = None,
|
||||
operation_id: Optional[str] = None,
|
||||
response_model_include: Optional[IncEx] = None,
|
||||
response_model_exclude: Optional[IncEx] = None,
|
||||
|
|
@ -582,12 +580,12 @@ class APIRoute(routing.Route):
|
|||
response_model_exclude_defaults: bool = False,
|
||||
response_model_exclude_none: bool = False,
|
||||
include_in_schema: bool = True,
|
||||
response_class: Union[Type[Response], DefaultPlaceholder] = Default(
|
||||
response_class: Union[type[Response], DefaultPlaceholder] = Default(
|
||||
JSONResponse
|
||||
),
|
||||
dependency_overrides_provider: Optional[Any] = None,
|
||||
callbacks: Optional[List[BaseRoute]] = None,
|
||||
openapi_extra: Optional[Dict[str, Any]] = None,
|
||||
callbacks: Optional[list[BaseRoute]] = None,
|
||||
openapi_extra: Optional[dict[str, Any]] = None,
|
||||
generate_unique_id_function: Union[
|
||||
Callable[["APIRoute"], str], DefaultPlaceholder
|
||||
] = Default(generate_unique_id),
|
||||
|
|
@ -623,7 +621,7 @@ class APIRoute(routing.Route):
|
|||
self.path_regex, self.path_format, self.param_convertors = compile_path(path)
|
||||
if methods is None:
|
||||
methods = ["GET"]
|
||||
self.methods: Set[str] = {method.upper() for method in methods}
|
||||
self.methods: set[str] = {method.upper() for method in methods}
|
||||
if isinstance(generate_unique_id_function, DefaultPlaceholder):
|
||||
current_generate_unique_id: Callable[[APIRoute], str] = (
|
||||
generate_unique_id_function.value
|
||||
|
|
@ -678,7 +676,7 @@ class APIRoute(routing.Route):
|
|||
)
|
||||
response_fields[additional_status_code] = response_field
|
||||
if response_fields:
|
||||
self.response_fields: Dict[Union[int, str], ModelField] = response_fields
|
||||
self.response_fields: dict[Union[int, str], ModelField] = response_fields
|
||||
else:
|
||||
self.response_fields = {}
|
||||
|
||||
|
|
@ -719,7 +717,7 @@ class APIRoute(routing.Route):
|
|||
embed_body_fields=self._embed_body_fields,
|
||||
)
|
||||
|
||||
def matches(self, scope: Scope) -> Tuple[Match, Scope]:
|
||||
def matches(self, scope: Scope) -> tuple[Match, Scope]:
|
||||
match, child_scope = super().matches(scope)
|
||||
if match != Match.NONE:
|
||||
child_scope["route"] = self
|
||||
|
|
@ -758,7 +756,7 @@ class APIRouter(routing.Router):
|
|||
*,
|
||||
prefix: Annotated[str, Doc("An optional path prefix for the router.")] = "",
|
||||
tags: Annotated[
|
||||
Optional[List[Union[str, Enum]]],
|
||||
Optional[list[Union[str, Enum]]],
|
||||
Doc(
|
||||
"""
|
||||
A list of tags to be applied to all the *path operations* in this
|
||||
|
|
@ -784,7 +782,7 @@ class APIRouter(routing.Router):
|
|||
),
|
||||
] = None,
|
||||
default_response_class: Annotated[
|
||||
Type[Response],
|
||||
type[Response],
|
||||
Doc(
|
||||
"""
|
||||
The default response class to be used.
|
||||
|
|
@ -795,7 +793,7 @@ class APIRouter(routing.Router):
|
|||
),
|
||||
] = Default(JSONResponse),
|
||||
responses: Annotated[
|
||||
Optional[Dict[Union[int, str], Dict[str, Any]]],
|
||||
Optional[dict[Union[int, str], dict[str, Any]]],
|
||||
Doc(
|
||||
"""
|
||||
Additional responses to be shown in OpenAPI.
|
||||
|
|
@ -811,7 +809,7 @@ class APIRouter(routing.Router):
|
|||
),
|
||||
] = None,
|
||||
callbacks: Annotated[
|
||||
Optional[List[BaseRoute]],
|
||||
Optional[list[BaseRoute]],
|
||||
Doc(
|
||||
"""
|
||||
OpenAPI callbacks that should apply to all *path operations* in this
|
||||
|
|
@ -825,7 +823,7 @@ class APIRouter(routing.Router):
|
|||
),
|
||||
] = None,
|
||||
routes: Annotated[
|
||||
Optional[List[BaseRoute]],
|
||||
Optional[list[BaseRoute]],
|
||||
Doc(
|
||||
"""
|
||||
**Note**: you probably shouldn't use this parameter, it is inherited
|
||||
|
|
@ -876,7 +874,7 @@ class APIRouter(routing.Router):
|
|||
),
|
||||
] = None,
|
||||
route_class: Annotated[
|
||||
Type[APIRoute],
|
||||
type[APIRoute],
|
||||
Doc(
|
||||
"""
|
||||
Custom route (*path operation*) class to be used by this router.
|
||||
|
|
@ -982,7 +980,7 @@ class APIRouter(routing.Router):
|
|||
"A path prefix must not end with '/', as the routes will start with '/'"
|
||||
)
|
||||
self.prefix = prefix
|
||||
self.tags: List[Union[str, Enum]] = tags or []
|
||||
self.tags: list[Union[str, Enum]] = tags or []
|
||||
self.dependencies = list(dependencies or [])
|
||||
self.deprecated = deprecated
|
||||
self.include_in_schema = include_in_schema
|
||||
|
|
@ -1019,14 +1017,14 @@ class APIRouter(routing.Router):
|
|||
*,
|
||||
response_model: Any = Default(None),
|
||||
status_code: Optional[int] = None,
|
||||
tags: Optional[List[Union[str, Enum]]] = None,
|
||||
tags: Optional[list[Union[str, Enum]]] = None,
|
||||
dependencies: Optional[Sequence[params.Depends]] = None,
|
||||
summary: Optional[str] = None,
|
||||
description: Optional[str] = None,
|
||||
response_description: str = "Successful Response",
|
||||
responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None,
|
||||
responses: Optional[dict[Union[int, str], dict[str, Any]]] = None,
|
||||
deprecated: Optional[bool] = None,
|
||||
methods: Optional[Union[Set[str], List[str]]] = None,
|
||||
methods: Optional[Union[set[str], list[str]]] = None,
|
||||
operation_id: Optional[str] = None,
|
||||
response_model_include: Optional[IncEx] = None,
|
||||
response_model_exclude: Optional[IncEx] = None,
|
||||
|
|
@ -1035,13 +1033,13 @@ class APIRouter(routing.Router):
|
|||
response_model_exclude_defaults: bool = False,
|
||||
response_model_exclude_none: bool = False,
|
||||
include_in_schema: bool = True,
|
||||
response_class: Union[Type[Response], DefaultPlaceholder] = Default(
|
||||
response_class: Union[type[Response], DefaultPlaceholder] = Default(
|
||||
JSONResponse
|
||||
),
|
||||
name: Optional[str] = None,
|
||||
route_class_override: Optional[Type[APIRoute]] = None,
|
||||
callbacks: Optional[List[BaseRoute]] = None,
|
||||
openapi_extra: Optional[Dict[str, Any]] = None,
|
||||
route_class_override: Optional[type[APIRoute]] = None,
|
||||
callbacks: Optional[list[BaseRoute]] = None,
|
||||
openapi_extra: Optional[dict[str, Any]] = None,
|
||||
generate_unique_id_function: Union[
|
||||
Callable[[APIRoute], str], DefaultPlaceholder
|
||||
] = Default(generate_unique_id),
|
||||
|
|
@ -1100,14 +1098,14 @@ class APIRouter(routing.Router):
|
|||
*,
|
||||
response_model: Any = Default(None),
|
||||
status_code: Optional[int] = None,
|
||||
tags: Optional[List[Union[str, Enum]]] = None,
|
||||
tags: Optional[list[Union[str, Enum]]] = None,
|
||||
dependencies: Optional[Sequence[params.Depends]] = None,
|
||||
summary: Optional[str] = None,
|
||||
description: Optional[str] = None,
|
||||
response_description: str = "Successful Response",
|
||||
responses: Optional[Dict[Union[int, str], Dict[str, Any]]] = None,
|
||||
responses: Optional[dict[Union[int, str], dict[str, Any]]] = None,
|
||||
deprecated: Optional[bool] = None,
|
||||
methods: Optional[List[str]] = None,
|
||||
methods: Optional[list[str]] = None,
|
||||
operation_id: Optional[str] = None,
|
||||
response_model_include: Optional[IncEx] = None,
|
||||
response_model_exclude: Optional[IncEx] = None,
|
||||
|
|
@ -1116,10 +1114,10 @@ class APIRouter(routing.Router):
|
|||
response_model_exclude_defaults: bool = False,
|
||||
response_model_exclude_none: bool = False,
|
||||
include_in_schema: bool = True,
|
||||
response_class: Type[Response] = Default(JSONResponse),
|
||||
response_class: type[Response] = Default(JSONResponse),
|
||||
name: Optional[str] = None,
|
||||
callbacks: Optional[List[BaseRoute]] = None,
|
||||
openapi_extra: Optional[Dict[str, Any]] = None,
|
||||
callbacks: Optional[list[BaseRoute]] = None,
|
||||
openapi_extra: Optional[dict[str, Any]] = None,
|
||||
generate_unique_id_function: Callable[[APIRoute], str] = Default(
|
||||
generate_unique_id
|
||||
),
|
||||
|
|
@ -1259,7 +1257,7 @@ class APIRouter(routing.Router):
|
|||
*,
|
||||
prefix: Annotated[str, Doc("An optional path prefix for the router.")] = "",
|
||||
tags: Annotated[
|
||||
Optional[List[Union[str, Enum]]],
|
||||
Optional[list[Union[str, Enum]]],
|
||||
Doc(
|
||||
"""
|
||||
A list of tags to be applied to all the *path operations* in this
|
||||
|
|
@ -1285,7 +1283,7 @@ class APIRouter(routing.Router):
|
|||
),
|
||||
] = None,
|
||||
default_response_class: Annotated[
|
||||
Type[Response],
|
||||
type[Response],
|
||||
Doc(
|
||||
"""
|
||||
The default response class to be used.
|
||||
|
|
@ -1296,7 +1294,7 @@ class APIRouter(routing.Router):
|
|||
),
|
||||
] = Default(JSONResponse),
|
||||
responses: Annotated[
|
||||
Optional[Dict[Union[int, str], Dict[str, Any]]],
|
||||
Optional[dict[Union[int, str], dict[str, Any]]],
|
||||
Doc(
|
||||
"""
|
||||
Additional responses to be shown in OpenAPI.
|
||||
|
|
@ -1312,7 +1310,7 @@ class APIRouter(routing.Router):
|
|||
),
|
||||
] = None,
|
||||
callbacks: Annotated[
|
||||
Optional[List[BaseRoute]],
|
||||
Optional[list[BaseRoute]],
|
||||
Doc(
|
||||
"""
|
||||
OpenAPI callbacks that should apply to all *path operations* in this
|
||||
|
|
@ -1417,7 +1415,7 @@ class APIRouter(routing.Router):
|
|||
current_tags.extend(tags)
|
||||
if route.tags:
|
||||
current_tags.extend(route.tags)
|
||||
current_dependencies: List[params.Depends] = []
|
||||
current_dependencies: list[params.Depends] = []
|
||||
if dependencies:
|
||||
current_dependencies.extend(dependencies)
|
||||
if route.dependencies:
|
||||
|
|
@ -1558,7 +1556,7 @@ class APIRouter(routing.Router):
|
|||
),
|
||||
] = None,
|
||||
tags: Annotated[
|
||||
Optional[List[Union[str, Enum]]],
|
||||
Optional[list[Union[str, Enum]]],
|
||||
Doc(
|
||||
"""
|
||||
A list of tags to be applied to the *path operation*.
|
||||
|
|
@ -1624,7 +1622,7 @@ class APIRouter(routing.Router):
|
|||
),
|
||||
] = "Successful Response",
|
||||
responses: Annotated[
|
||||
Optional[Dict[Union[int, str], Dict[str, Any]]],
|
||||
Optional[dict[Union[int, str], dict[str, Any]]],
|
||||
Doc(
|
||||
"""
|
||||
Additional responses that could be returned by this *path operation*.
|
||||
|
|
@ -1765,7 +1763,7 @@ class APIRouter(routing.Router):
|
|||
),
|
||||
] = True,
|
||||
response_class: Annotated[
|
||||
Type[Response],
|
||||
type[Response],
|
||||
Doc(
|
||||
"""
|
||||
Response class to be used for this *path operation*.
|
||||
|
|
@ -1786,7 +1784,7 @@ class APIRouter(routing.Router):
|
|||
),
|
||||
] = None,
|
||||
callbacks: Annotated[
|
||||
Optional[List[BaseRoute]],
|
||||
Optional[list[BaseRoute]],
|
||||
Doc(
|
||||
"""
|
||||
List of *path operations* that will be used as OpenAPI callbacks.
|
||||
|
|
@ -1802,7 +1800,7 @@ class APIRouter(routing.Router):
|
|||
),
|
||||
] = None,
|
||||
openapi_extra: Annotated[
|
||||
Optional[Dict[str, Any]],
|
||||
Optional[dict[str, Any]],
|
||||
Doc(
|
||||
"""
|
||||
Extra metadata to be included in the OpenAPI schema for this *path
|
||||
|
|
@ -1935,7 +1933,7 @@ class APIRouter(routing.Router):
|
|||
),
|
||||
] = None,
|
||||
tags: Annotated[
|
||||
Optional[List[Union[str, Enum]]],
|
||||
Optional[list[Union[str, Enum]]],
|
||||
Doc(
|
||||
"""
|
||||
A list of tags to be applied to the *path operation*.
|
||||
|
|
@ -2001,7 +1999,7 @@ class APIRouter(routing.Router):
|
|||
),
|
||||
] = "Successful Response",
|
||||
responses: Annotated[
|
||||
Optional[Dict[Union[int, str], Dict[str, Any]]],
|
||||
Optional[dict[Union[int, str], dict[str, Any]]],
|
||||
Doc(
|
||||
"""
|
||||
Additional responses that could be returned by this *path operation*.
|
||||
|
|
@ -2142,7 +2140,7 @@ class APIRouter(routing.Router):
|
|||
),
|
||||
] = True,
|
||||
response_class: Annotated[
|
||||
Type[Response],
|
||||
type[Response],
|
||||
Doc(
|
||||
"""
|
||||
Response class to be used for this *path operation*.
|
||||
|
|
@ -2163,7 +2161,7 @@ class APIRouter(routing.Router):
|
|||
),
|
||||
] = None,
|
||||
callbacks: Annotated[
|
||||
Optional[List[BaseRoute]],
|
||||
Optional[list[BaseRoute]],
|
||||
Doc(
|
||||
"""
|
||||
List of *path operations* that will be used as OpenAPI callbacks.
|
||||
|
|
@ -2179,7 +2177,7 @@ class APIRouter(routing.Router):
|
|||
),
|
||||
] = None,
|
||||
openapi_extra: Annotated[
|
||||
Optional[Dict[str, Any]],
|
||||
Optional[dict[str, Any]],
|
||||
Doc(
|
||||
"""
|
||||
Extra metadata to be included in the OpenAPI schema for this *path
|
||||
|
|
@ -2317,7 +2315,7 @@ class APIRouter(routing.Router):
|
|||
),
|
||||
] = None,
|
||||
tags: Annotated[
|
||||
Optional[List[Union[str, Enum]]],
|
||||
Optional[list[Union[str, Enum]]],
|
||||
Doc(
|
||||
"""
|
||||
A list of tags to be applied to the *path operation*.
|
||||
|
|
@ -2383,7 +2381,7 @@ class APIRouter(routing.Router):
|
|||
),
|
||||
] = "Successful Response",
|
||||
responses: Annotated[
|
||||
Optional[Dict[Union[int, str], Dict[str, Any]]],
|
||||
Optional[dict[Union[int, str], dict[str, Any]]],
|
||||
Doc(
|
||||
"""
|
||||
Additional responses that could be returned by this *path operation*.
|
||||
|
|
@ -2524,7 +2522,7 @@ class APIRouter(routing.Router):
|
|||
),
|
||||
] = True,
|
||||
response_class: Annotated[
|
||||
Type[Response],
|
||||
type[Response],
|
||||
Doc(
|
||||
"""
|
||||
Response class to be used for this *path operation*.
|
||||
|
|
@ -2545,7 +2543,7 @@ class APIRouter(routing.Router):
|
|||
),
|
||||
] = None,
|
||||
callbacks: Annotated[
|
||||
Optional[List[BaseRoute]],
|
||||
Optional[list[BaseRoute]],
|
||||
Doc(
|
||||
"""
|
||||
List of *path operations* that will be used as OpenAPI callbacks.
|
||||
|
|
@ -2561,7 +2559,7 @@ class APIRouter(routing.Router):
|
|||
),
|
||||
] = None,
|
||||
openapi_extra: Annotated[
|
||||
Optional[Dict[str, Any]],
|
||||
Optional[dict[str, Any]],
|
||||
Doc(
|
||||
"""
|
||||
Extra metadata to be included in the OpenAPI schema for this *path
|
||||
|
|
@ -2699,7 +2697,7 @@ class APIRouter(routing.Router):
|
|||
),
|
||||
] = None,
|
||||
tags: Annotated[
|
||||
Optional[List[Union[str, Enum]]],
|
||||
Optional[list[Union[str, Enum]]],
|
||||
Doc(
|
||||
"""
|
||||
A list of tags to be applied to the *path operation*.
|
||||
|
|
@ -2765,7 +2763,7 @@ class APIRouter(routing.Router):
|
|||
),
|
||||
] = "Successful Response",
|
||||
responses: Annotated[
|
||||
Optional[Dict[Union[int, str], Dict[str, Any]]],
|
||||
Optional[dict[Union[int, str], dict[str, Any]]],
|
||||
Doc(
|
||||
"""
|
||||
Additional responses that could be returned by this *path operation*.
|
||||
|
|
@ -2906,7 +2904,7 @@ class APIRouter(routing.Router):
|
|||
),
|
||||
] = True,
|
||||
response_class: Annotated[
|
||||
Type[Response],
|
||||
type[Response],
|
||||
Doc(
|
||||
"""
|
||||
Response class to be used for this *path operation*.
|
||||
|
|
@ -2927,7 +2925,7 @@ class APIRouter(routing.Router):
|
|||
),
|
||||
] = None,
|
||||
callbacks: Annotated[
|
||||
Optional[List[BaseRoute]],
|
||||
Optional[list[BaseRoute]],
|
||||
Doc(
|
||||
"""
|
||||
List of *path operations* that will be used as OpenAPI callbacks.
|
||||
|
|
@ -2943,7 +2941,7 @@ class APIRouter(routing.Router):
|
|||
),
|
||||
] = None,
|
||||
openapi_extra: Annotated[
|
||||
Optional[Dict[str, Any]],
|
||||
Optional[dict[str, Any]],
|
||||
Doc(
|
||||
"""
|
||||
Extra metadata to be included in the OpenAPI schema for this *path
|
||||
|
|
@ -3076,7 +3074,7 @@ class APIRouter(routing.Router):
|
|||
),
|
||||
] = None,
|
||||
tags: Annotated[
|
||||
Optional[List[Union[str, Enum]]],
|
||||
Optional[list[Union[str, Enum]]],
|
||||
Doc(
|
||||
"""
|
||||
A list of tags to be applied to the *path operation*.
|
||||
|
|
@ -3142,7 +3140,7 @@ class APIRouter(routing.Router):
|
|||
),
|
||||
] = "Successful Response",
|
||||
responses: Annotated[
|
||||
Optional[Dict[Union[int, str], Dict[str, Any]]],
|
||||
Optional[dict[Union[int, str], dict[str, Any]]],
|
||||
Doc(
|
||||
"""
|
||||
Additional responses that could be returned by this *path operation*.
|
||||
|
|
@ -3283,7 +3281,7 @@ class APIRouter(routing.Router):
|
|||
),
|
||||
] = True,
|
||||
response_class: Annotated[
|
||||
Type[Response],
|
||||
type[Response],
|
||||
Doc(
|
||||
"""
|
||||
Response class to be used for this *path operation*.
|
||||
|
|
@ -3304,7 +3302,7 @@ class APIRouter(routing.Router):
|
|||
),
|
||||
] = None,
|
||||
callbacks: Annotated[
|
||||
Optional[List[BaseRoute]],
|
||||
Optional[list[BaseRoute]],
|
||||
Doc(
|
||||
"""
|
||||
List of *path operations* that will be used as OpenAPI callbacks.
|
||||
|
|
@ -3320,7 +3318,7 @@ class APIRouter(routing.Router):
|
|||
),
|
||||
] = None,
|
||||
openapi_extra: Annotated[
|
||||
Optional[Dict[str, Any]],
|
||||
Optional[dict[str, Any]],
|
||||
Doc(
|
||||
"""
|
||||
Extra metadata to be included in the OpenAPI schema for this *path
|
||||
|
|
@ -3453,7 +3451,7 @@ class APIRouter(routing.Router):
|
|||
),
|
||||
] = None,
|
||||
tags: Annotated[
|
||||
Optional[List[Union[str, Enum]]],
|
||||
Optional[list[Union[str, Enum]]],
|
||||
Doc(
|
||||
"""
|
||||
A list of tags to be applied to the *path operation*.
|
||||
|
|
@ -3519,7 +3517,7 @@ class APIRouter(routing.Router):
|
|||
),
|
||||
] = "Successful Response",
|
||||
responses: Annotated[
|
||||
Optional[Dict[Union[int, str], Dict[str, Any]]],
|
||||
Optional[dict[Union[int, str], dict[str, Any]]],
|
||||
Doc(
|
||||
"""
|
||||
Additional responses that could be returned by this *path operation*.
|
||||
|
|
@ -3660,7 +3658,7 @@ class APIRouter(routing.Router):
|
|||
),
|
||||
] = True,
|
||||
response_class: Annotated[
|
||||
Type[Response],
|
||||
type[Response],
|
||||
Doc(
|
||||
"""
|
||||
Response class to be used for this *path operation*.
|
||||
|
|
@ -3681,7 +3679,7 @@ class APIRouter(routing.Router):
|
|||
),
|
||||
] = None,
|
||||
callbacks: Annotated[
|
||||
Optional[List[BaseRoute]],
|
||||
Optional[list[BaseRoute]],
|
||||
Doc(
|
||||
"""
|
||||
List of *path operations* that will be used as OpenAPI callbacks.
|
||||
|
|
@ -3697,7 +3695,7 @@ class APIRouter(routing.Router):
|
|||
),
|
||||
] = None,
|
||||
openapi_extra: Annotated[
|
||||
Optional[Dict[str, Any]],
|
||||
Optional[dict[str, Any]],
|
||||
Doc(
|
||||
"""
|
||||
Extra metadata to be included in the OpenAPI schema for this *path
|
||||
|
|
@ -3835,7 +3833,7 @@ class APIRouter(routing.Router):
|
|||
),
|
||||
] = None,
|
||||
tags: Annotated[
|
||||
Optional[List[Union[str, Enum]]],
|
||||
Optional[list[Union[str, Enum]]],
|
||||
Doc(
|
||||
"""
|
||||
A list of tags to be applied to the *path operation*.
|
||||
|
|
@ -3901,7 +3899,7 @@ class APIRouter(routing.Router):
|
|||
),
|
||||
] = "Successful Response",
|
||||
responses: Annotated[
|
||||
Optional[Dict[Union[int, str], Dict[str, Any]]],
|
||||
Optional[dict[Union[int, str], dict[str, Any]]],
|
||||
Doc(
|
||||
"""
|
||||
Additional responses that could be returned by this *path operation*.
|
||||
|
|
@ -4042,7 +4040,7 @@ class APIRouter(routing.Router):
|
|||
),
|
||||
] = True,
|
||||
response_class: Annotated[
|
||||
Type[Response],
|
||||
type[Response],
|
||||
Doc(
|
||||
"""
|
||||
Response class to be used for this *path operation*.
|
||||
|
|
@ -4063,7 +4061,7 @@ class APIRouter(routing.Router):
|
|||
),
|
||||
] = None,
|
||||
callbacks: Annotated[
|
||||
Optional[List[BaseRoute]],
|
||||
Optional[list[BaseRoute]],
|
||||
Doc(
|
||||
"""
|
||||
List of *path operations* that will be used as OpenAPI callbacks.
|
||||
|
|
@ -4079,7 +4077,7 @@ class APIRouter(routing.Router):
|
|||
),
|
||||
] = None,
|
||||
openapi_extra: Annotated[
|
||||
Optional[Dict[str, Any]],
|
||||
Optional[dict[str, Any]],
|
||||
Doc(
|
||||
"""
|
||||
Extra metadata to be included in the OpenAPI schema for this *path
|
||||
|
|
@ -4217,7 +4215,7 @@ class APIRouter(routing.Router):
|
|||
),
|
||||
] = None,
|
||||
tags: Annotated[
|
||||
Optional[List[Union[str, Enum]]],
|
||||
Optional[list[Union[str, Enum]]],
|
||||
Doc(
|
||||
"""
|
||||
A list of tags to be applied to the *path operation*.
|
||||
|
|
@ -4283,7 +4281,7 @@ class APIRouter(routing.Router):
|
|||
),
|
||||
] = "Successful Response",
|
||||
responses: Annotated[
|
||||
Optional[Dict[Union[int, str], Dict[str, Any]]],
|
||||
Optional[dict[Union[int, str], dict[str, Any]]],
|
||||
Doc(
|
||||
"""
|
||||
Additional responses that could be returned by this *path operation*.
|
||||
|
|
@ -4424,7 +4422,7 @@ class APIRouter(routing.Router):
|
|||
),
|
||||
] = True,
|
||||
response_class: Annotated[
|
||||
Type[Response],
|
||||
type[Response],
|
||||
Doc(
|
||||
"""
|
||||
Response class to be used for this *path operation*.
|
||||
|
|
@ -4445,7 +4443,7 @@ class APIRouter(routing.Router):
|
|||
),
|
||||
] = None,
|
||||
callbacks: Annotated[
|
||||
Optional[List[BaseRoute]],
|
||||
Optional[list[BaseRoute]],
|
||||
Doc(
|
||||
"""
|
||||
List of *path operations* that will be used as OpenAPI callbacks.
|
||||
|
|
@ -4461,7 +4459,7 @@ class APIRouter(routing.Router):
|
|||
),
|
||||
] = None,
|
||||
openapi_extra: Annotated[
|
||||
Optional[Dict[str, Any]],
|
||||
Optional[dict[str, Any]],
|
||||
Doc(
|
||||
"""
|
||||
Extra metadata to be included in the OpenAPI schema for this *path
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from typing import Optional, Union
|
||||
from typing import Annotated, Optional, Union
|
||||
|
||||
from annotated_doc import Doc
|
||||
from fastapi.openapi.models import APIKey, APIKeyIn
|
||||
|
|
@ -6,7 +6,6 @@ from fastapi.security.base import SecurityBase
|
|||
from starlette.exceptions import HTTPException
|
||||
from starlette.requests import Request
|
||||
from starlette.status import HTTP_401_UNAUTHORIZED
|
||||
from typing_extensions import Annotated
|
||||
|
||||
|
||||
class APIKeyBase(SecurityBase):
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import binascii
|
||||
from base64 import b64decode
|
||||
from typing import Dict, Optional
|
||||
from typing import Annotated, Optional
|
||||
|
||||
from annotated_doc import Doc
|
||||
from fastapi.exceptions import HTTPException
|
||||
|
|
@ -11,7 +11,6 @@ from fastapi.security.utils import get_authorization_scheme_param
|
|||
from pydantic import BaseModel
|
||||
from starlette.requests import Request
|
||||
from starlette.status import HTTP_401_UNAUTHORIZED
|
||||
from typing_extensions import Annotated
|
||||
|
||||
|
||||
class HTTPBasicCredentials(BaseModel):
|
||||
|
|
@ -82,7 +81,7 @@ class HTTPBase(SecurityBase):
|
|||
self.scheme_name = scheme_name or self.__class__.__name__
|
||||
self.auto_error = auto_error
|
||||
|
||||
def make_authenticate_headers(self) -> Dict[str, str]:
|
||||
def make_authenticate_headers(self) -> dict[str, str]:
|
||||
return {"WWW-Authenticate": f"{self.model.scheme.title()}"}
|
||||
|
||||
def make_not_authenticated_error(self) -> HTTPException:
|
||||
|
|
@ -197,7 +196,7 @@ class HTTPBasic(HTTPBase):
|
|||
self.realm = realm
|
||||
self.auto_error = auto_error
|
||||
|
||||
def make_authenticate_headers(self) -> Dict[str, str]:
|
||||
def make_authenticate_headers(self) -> dict[str, str]:
|
||||
if self.realm:
|
||||
return {"WWW-Authenticate": f'Basic realm="{self.realm}"'}
|
||||
return {"WWW-Authenticate": "Basic"}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from typing import Any, Dict, List, Optional, Union, cast
|
||||
from typing import Annotated, Any, Optional, Union, cast
|
||||
|
||||
from annotated_doc import Doc
|
||||
from fastapi.exceptions import HTTPException
|
||||
|
|
@ -10,9 +10,6 @@ from fastapi.security.utils import get_authorization_scheme_param
|
|||
from starlette.requests import Request
|
||||
from starlette.status import HTTP_401_UNAUTHORIZED
|
||||
|
||||
# TODO: import from typing when deprecating Python 3.9
|
||||
from typing_extensions import Annotated
|
||||
|
||||
|
||||
class OAuth2PasswordRequestForm:
|
||||
"""
|
||||
|
|
@ -323,7 +320,7 @@ class OAuth2(SecurityBase):
|
|||
self,
|
||||
*,
|
||||
flows: Annotated[
|
||||
Union[OAuthFlowsModel, Dict[str, Dict[str, Any]]],
|
||||
Union[OAuthFlowsModel, dict[str, dict[str, Any]]],
|
||||
Doc(
|
||||
"""
|
||||
The dictionary of OAuth2 flows.
|
||||
|
|
@ -440,7 +437,7 @@ class OAuth2PasswordBearer(OAuth2):
|
|||
),
|
||||
] = None,
|
||||
scopes: Annotated[
|
||||
Optional[Dict[str, str]],
|
||||
Optional[dict[str, str]],
|
||||
Doc(
|
||||
"""
|
||||
The OAuth2 scopes that would be required by the *path operations* that
|
||||
|
|
@ -553,7 +550,7 @@ class OAuth2AuthorizationCodeBearer(OAuth2):
|
|||
),
|
||||
] = None,
|
||||
scopes: Annotated[
|
||||
Optional[Dict[str, str]],
|
||||
Optional[dict[str, str]],
|
||||
Doc(
|
||||
"""
|
||||
The OAuth2 scopes that would be required by the *path operations* that
|
||||
|
|
@ -639,7 +636,7 @@ class SecurityScopes:
|
|||
def __init__(
|
||||
self,
|
||||
scopes: Annotated[
|
||||
Optional[List[str]],
|
||||
Optional[list[str]],
|
||||
Doc(
|
||||
"""
|
||||
This will be filled by FastAPI.
|
||||
|
|
@ -648,7 +645,7 @@ class SecurityScopes:
|
|||
] = None,
|
||||
):
|
||||
self.scopes: Annotated[
|
||||
List[str],
|
||||
list[str],
|
||||
Doc(
|
||||
"""
|
||||
The list of all the scopes required by dependencies.
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from typing import Optional
|
||||
from typing import Annotated, Optional
|
||||
|
||||
from annotated_doc import Doc
|
||||
from fastapi.openapi.models import OpenIdConnect as OpenIdConnectModel
|
||||
|
|
@ -6,7 +6,6 @@ from fastapi.security.base import SecurityBase
|
|||
from starlette.exceptions import HTTPException
|
||||
from starlette.requests import Request
|
||||
from starlette.status import HTTP_401_UNAUTHORIZED
|
||||
from typing_extensions import Annotated
|
||||
|
||||
|
||||
class OpenIdConnect(SecurityBase):
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
from typing import Optional, Tuple
|
||||
from typing import Optional
|
||||
|
||||
|
||||
def get_authorization_scheme_param(
|
||||
authorization_header_value: Optional[str],
|
||||
) -> Tuple[str, str]:
|
||||
) -> tuple[str, str]:
|
||||
if not authorization_header_value:
|
||||
return "", ""
|
||||
scheme, _, param = authorization_header_value.partition(" ")
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import warnings
|
||||
from typing import Any, Callable, Dict, List, Optional, Union
|
||||
from typing import Annotated, Any, Callable, Optional, Union
|
||||
|
||||
from fastapi.openapi.models import Example
|
||||
from fastapi.params import ParamTypes
|
||||
from typing_extensions import Annotated, deprecated
|
||||
from typing_extensions import deprecated
|
||||
|
||||
from ._compat.may_v1 import FieldInfo, Undefined
|
||||
from ._compat.shared import PYDANTIC_VERSION_MINOR_TUPLE
|
||||
|
|
@ -47,7 +47,7 @@ class Param(FieldInfo): # type: ignore[misc]
|
|||
allow_inf_nan: Union[bool, None] = _Unset,
|
||||
max_digits: Union[int, None] = _Unset,
|
||||
decimal_places: Union[int, None] = _Unset,
|
||||
examples: Optional[List[Any]] = None,
|
||||
examples: Optional[list[Any]] = None,
|
||||
example: Annotated[
|
||||
Optional[Any],
|
||||
deprecated(
|
||||
|
|
@ -55,10 +55,10 @@ class Param(FieldInfo): # type: ignore[misc]
|
|||
"although still supported. Use examples instead."
|
||||
),
|
||||
] = _Unset,
|
||||
openapi_examples: Optional[Dict[str, Example]] = None,
|
||||
openapi_examples: Optional[dict[str, Example]] = None,
|
||||
deprecated: Union[deprecated, str, bool, None] = None,
|
||||
include_in_schema: bool = True,
|
||||
json_schema_extra: Union[Dict[str, Any], None] = None,
|
||||
json_schema_extra: Union[dict[str, Any], None] = None,
|
||||
**extra: Any,
|
||||
):
|
||||
if example is not _Unset:
|
||||
|
|
@ -148,7 +148,7 @@ class Path(Param): # type: ignore[misc]
|
|||
allow_inf_nan: Union[bool, None] = _Unset,
|
||||
max_digits: Union[int, None] = _Unset,
|
||||
decimal_places: Union[int, None] = _Unset,
|
||||
examples: Optional[List[Any]] = None,
|
||||
examples: Optional[list[Any]] = None,
|
||||
example: Annotated[
|
||||
Optional[Any],
|
||||
deprecated(
|
||||
|
|
@ -156,10 +156,10 @@ class Path(Param): # type: ignore[misc]
|
|||
"although still supported. Use examples instead."
|
||||
),
|
||||
] = _Unset,
|
||||
openapi_examples: Optional[Dict[str, Example]] = None,
|
||||
openapi_examples: Optional[dict[str, Example]] = None,
|
||||
deprecated: Union[deprecated, str, bool, None] = None,
|
||||
include_in_schema: bool = True,
|
||||
json_schema_extra: Union[Dict[str, Any], None] = None,
|
||||
json_schema_extra: Union[dict[str, Any], None] = None,
|
||||
**extra: Any,
|
||||
):
|
||||
assert default is ..., "Path parameters cannot have a default value"
|
||||
|
|
@ -234,7 +234,7 @@ class Query(Param): # type: ignore[misc]
|
|||
allow_inf_nan: Union[bool, None] = _Unset,
|
||||
max_digits: Union[int, None] = _Unset,
|
||||
decimal_places: Union[int, None] = _Unset,
|
||||
examples: Optional[List[Any]] = None,
|
||||
examples: Optional[list[Any]] = None,
|
||||
example: Annotated[
|
||||
Optional[Any],
|
||||
deprecated(
|
||||
|
|
@ -242,10 +242,10 @@ class Query(Param): # type: ignore[misc]
|
|||
"although still supported. Use examples instead."
|
||||
),
|
||||
] = _Unset,
|
||||
openapi_examples: Optional[Dict[str, Example]] = None,
|
||||
openapi_examples: Optional[dict[str, Example]] = None,
|
||||
deprecated: Union[deprecated, str, bool, None] = None,
|
||||
include_in_schema: bool = True,
|
||||
json_schema_extra: Union[Dict[str, Any], None] = None,
|
||||
json_schema_extra: Union[dict[str, Any], None] = None,
|
||||
**extra: Any,
|
||||
):
|
||||
super().__init__(
|
||||
|
|
@ -319,7 +319,7 @@ class Header(Param): # type: ignore[misc]
|
|||
allow_inf_nan: Union[bool, None] = _Unset,
|
||||
max_digits: Union[int, None] = _Unset,
|
||||
decimal_places: Union[int, None] = _Unset,
|
||||
examples: Optional[List[Any]] = None,
|
||||
examples: Optional[list[Any]] = None,
|
||||
example: Annotated[
|
||||
Optional[Any],
|
||||
deprecated(
|
||||
|
|
@ -327,10 +327,10 @@ class Header(Param): # type: ignore[misc]
|
|||
"although still supported. Use examples instead."
|
||||
),
|
||||
] = _Unset,
|
||||
openapi_examples: Optional[Dict[str, Example]] = None,
|
||||
openapi_examples: Optional[dict[str, Example]] = None,
|
||||
deprecated: Union[deprecated, str, bool, None] = None,
|
||||
include_in_schema: bool = True,
|
||||
json_schema_extra: Union[Dict[str, Any], None] = None,
|
||||
json_schema_extra: Union[dict[str, Any], None] = None,
|
||||
**extra: Any,
|
||||
):
|
||||
self.convert_underscores = convert_underscores
|
||||
|
|
@ -404,7 +404,7 @@ class Cookie(Param): # type: ignore[misc]
|
|||
allow_inf_nan: Union[bool, None] = _Unset,
|
||||
max_digits: Union[int, None] = _Unset,
|
||||
decimal_places: Union[int, None] = _Unset,
|
||||
examples: Optional[List[Any]] = None,
|
||||
examples: Optional[list[Any]] = None,
|
||||
example: Annotated[
|
||||
Optional[Any],
|
||||
deprecated(
|
||||
|
|
@ -412,10 +412,10 @@ class Cookie(Param): # type: ignore[misc]
|
|||
"although still supported. Use examples instead."
|
||||
),
|
||||
] = _Unset,
|
||||
openapi_examples: Optional[Dict[str, Example]] = None,
|
||||
openapi_examples: Optional[dict[str, Example]] = None,
|
||||
deprecated: Union[deprecated, str, bool, None] = None,
|
||||
include_in_schema: bool = True,
|
||||
json_schema_extra: Union[Dict[str, Any], None] = None,
|
||||
json_schema_extra: Union[dict[str, Any], None] = None,
|
||||
**extra: Any,
|
||||
):
|
||||
super().__init__(
|
||||
|
|
@ -488,7 +488,7 @@ class Body(FieldInfo): # type: ignore[misc]
|
|||
allow_inf_nan: Union[bool, None] = _Unset,
|
||||
max_digits: Union[int, None] = _Unset,
|
||||
decimal_places: Union[int, None] = _Unset,
|
||||
examples: Optional[List[Any]] = None,
|
||||
examples: Optional[list[Any]] = None,
|
||||
example: Annotated[
|
||||
Optional[Any],
|
||||
deprecated(
|
||||
|
|
@ -496,10 +496,10 @@ class Body(FieldInfo): # type: ignore[misc]
|
|||
"although still supported. Use examples instead."
|
||||
),
|
||||
] = _Unset,
|
||||
openapi_examples: Optional[Dict[str, Example]] = None,
|
||||
openapi_examples: Optional[dict[str, Example]] = None,
|
||||
deprecated: Union[deprecated, str, bool, None] = None,
|
||||
include_in_schema: bool = True,
|
||||
json_schema_extra: Union[Dict[str, Any], None] = None,
|
||||
json_schema_extra: Union[dict[str, Any], None] = None,
|
||||
**extra: Any,
|
||||
):
|
||||
self.embed = embed
|
||||
|
|
@ -591,7 +591,7 @@ class Form(Body): # type: ignore[misc]
|
|||
allow_inf_nan: Union[bool, None] = _Unset,
|
||||
max_digits: Union[int, None] = _Unset,
|
||||
decimal_places: Union[int, None] = _Unset,
|
||||
examples: Optional[List[Any]] = None,
|
||||
examples: Optional[list[Any]] = None,
|
||||
example: Annotated[
|
||||
Optional[Any],
|
||||
deprecated(
|
||||
|
|
@ -599,10 +599,10 @@ class Form(Body): # type: ignore[misc]
|
|||
"although still supported. Use examples instead."
|
||||
),
|
||||
] = _Unset,
|
||||
openapi_examples: Optional[Dict[str, Example]] = None,
|
||||
openapi_examples: Optional[dict[str, Example]] = None,
|
||||
deprecated: Union[deprecated, str, bool, None] = None,
|
||||
include_in_schema: bool = True,
|
||||
json_schema_extra: Union[Dict[str, Any], None] = None,
|
||||
json_schema_extra: Union[dict[str, Any], None] = None,
|
||||
**extra: Any,
|
||||
):
|
||||
super().__init__(
|
||||
|
|
@ -675,7 +675,7 @@ class File(Form): # type: ignore[misc]
|
|||
allow_inf_nan: Union[bool, None] = _Unset,
|
||||
max_digits: Union[int, None] = _Unset,
|
||||
decimal_places: Union[int, None] = _Unset,
|
||||
examples: Optional[List[Any]] = None,
|
||||
examples: Optional[list[Any]] = None,
|
||||
example: Annotated[
|
||||
Optional[Any],
|
||||
deprecated(
|
||||
|
|
@ -683,10 +683,10 @@ class File(Form): # type: ignore[misc]
|
|||
"although still supported. Use examples instead."
|
||||
),
|
||||
] = _Unset,
|
||||
openapi_examples: Optional[Dict[str, Example]] = None,
|
||||
openapi_examples: Optional[dict[str, Example]] = None,
|
||||
deprecated: Union[deprecated, str, bool, None] = None,
|
||||
include_in_schema: bool = True,
|
||||
json_schema_extra: Union[Dict[str, Any], None] = None,
|
||||
json_schema_extra: Union[dict[str, Any], None] = None,
|
||||
**extra: Any,
|
||||
):
|
||||
super().__init__(
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import types
|
||||
from enum import Enum
|
||||
from typing import Any, Callable, Dict, Optional, Set, Tuple, Type, TypeVar, Union
|
||||
from typing import Any, Callable, Optional, TypeVar, Union
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
DecoratedCallable = TypeVar("DecoratedCallable", bound=Callable[..., Any])
|
||||
UnionType = getattr(types, "UnionType", Union)
|
||||
ModelNameMap = Dict[Union[Type[BaseModel], Type[Enum]], str]
|
||||
IncEx = Union[Set[int], Set[str], Dict[int, Any], Dict[str, Any]]
|
||||
DependencyCacheKey = Tuple[Optional[Callable[..., Any]], Tuple[str, ...], str]
|
||||
ModelNameMap = dict[Union[type[BaseModel], type[Enum]], str]
|
||||
IncEx = Union[set[int], set[str], dict[int, Any], dict[str, Any]]
|
||||
DependencyCacheKey = tuple[Optional[Callable[..., Any]], tuple[str, ...], str]
|
||||
|
|
|
|||
|
|
@ -1,14 +1,11 @@
|
|||
import re
|
||||
import warnings
|
||||
from collections.abc import MutableMapping
|
||||
from dataclasses import is_dataclass
|
||||
from typing import (
|
||||
TYPE_CHECKING,
|
||||
Any,
|
||||
Dict,
|
||||
MutableMapping,
|
||||
Optional,
|
||||
Set,
|
||||
Type,
|
||||
Union,
|
||||
cast,
|
||||
)
|
||||
|
|
@ -36,7 +33,7 @@ if TYPE_CHECKING: # pragma: nocover
|
|||
from .routing import APIRoute
|
||||
|
||||
# Cache for `create_cloned_field`
|
||||
_CLONED_TYPES_CACHE: MutableMapping[Type[BaseModel], Type[BaseModel]] = (
|
||||
_CLONED_TYPES_CACHE: MutableMapping[type[BaseModel], type[BaseModel]] = (
|
||||
WeakKeyDictionary()
|
||||
)
|
||||
|
||||
|
|
@ -58,7 +55,7 @@ def is_body_allowed_for_status_code(status_code: Union[int, str, None]) -> bool:
|
|||
return not (current_status_code < 200 or current_status_code in {204, 205, 304})
|
||||
|
||||
|
||||
def get_path_param_names(path: str) -> Set[str]:
|
||||
def get_path_param_names(path: str) -> set[str]:
|
||||
return set(re.findall("{(.*?)}", path))
|
||||
|
||||
|
||||
|
|
@ -76,10 +73,10 @@ _invalid_args_message = (
|
|||
def create_model_field(
|
||||
name: str,
|
||||
type_: Any,
|
||||
class_validators: Optional[Dict[str, Validator]] = None,
|
||||
class_validators: Optional[dict[str, Validator]] = None,
|
||||
default: Optional[Any] = Undefined,
|
||||
required: Union[bool, UndefinedType] = Undefined,
|
||||
model_config: Union[Type[BaseConfig], None] = None,
|
||||
model_config: Union[type[BaseConfig], None] = None,
|
||||
field_info: Optional[FieldInfo] = None,
|
||||
alias: Optional[str] = None,
|
||||
mode: Literal["validation", "serialization"] = "validation",
|
||||
|
|
@ -141,7 +138,7 @@ def create_model_field(
|
|||
def create_cloned_field(
|
||||
field: ModelField,
|
||||
*,
|
||||
cloned_types: Optional[MutableMapping[Type[BaseModel], Type[BaseModel]]] = None,
|
||||
cloned_types: Optional[MutableMapping[type[BaseModel], type[BaseModel]]] = None,
|
||||
) -> ModelField:
|
||||
if PYDANTIC_V2:
|
||||
from ._compat import v2
|
||||
|
|
@ -161,7 +158,7 @@ def create_cloned_field(
|
|||
original_type = original_type.__pydantic_model__
|
||||
use_type = original_type
|
||||
if lenient_issubclass(original_type, v1.BaseModel):
|
||||
original_type = cast(Type[v1.BaseModel], original_type)
|
||||
original_type = cast(type[v1.BaseModel], original_type)
|
||||
use_type = cloned_types.get(original_type)
|
||||
if use_type is None:
|
||||
use_type = v1.create_model(original_type.__name__, __base__=original_type)
|
||||
|
|
@ -224,7 +221,7 @@ def generate_unique_id(route: "APIRoute") -> str:
|
|||
return operation_id
|
||||
|
||||
|
||||
def deep_dict_update(main_dict: Dict[Any, Any], update_dict: Dict[Any, Any]) -> None:
|
||||
def deep_dict_update(main_dict: dict[Any, Any], update_dict: dict[Any, Any]) -> None:
|
||||
for key, value in update_dict.items():
|
||||
if (
|
||||
key in main_dict
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import os
|
||||
from typing import Any, Dict
|
||||
from typing import Any
|
||||
|
||||
from pdm.backend.hooks import Context
|
||||
|
||||
|
|
@ -9,12 +9,12 @@ TIANGOLO_BUILD_PACKAGE = os.getenv("TIANGOLO_BUILD_PACKAGE", "fastapi")
|
|||
def pdm_build_initialize(context: Context) -> None:
|
||||
metadata = context.config.metadata
|
||||
# Get custom config for the current package, from the env var
|
||||
config: Dict[str, Any] = context.config.data["tool"]["tiangolo"][
|
||||
config: dict[str, Any] = context.config.data["tool"]["tiangolo"][
|
||||
"_internal-slim-build"
|
||||
]["packages"].get(TIANGOLO_BUILD_PACKAGE)
|
||||
if not config:
|
||||
return
|
||||
project_config: Dict[str, Any] = config["project"]
|
||||
project_config: dict[str, Any] = config["project"]
|
||||
# Override main [project] configs with custom configs for this package
|
||||
for key, value in project_config.items():
|
||||
metadata[key] = value
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ from html.parser import HTMLParser
|
|||
from http.server import HTTPServer, SimpleHTTPRequestHandler
|
||||
from multiprocessing import Pool
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict, List, Optional, Union
|
||||
from typing import Any, Optional, Union
|
||||
|
||||
import mkdocs.utils
|
||||
import typer
|
||||
|
|
@ -82,11 +82,11 @@ def slugify(text: str) -> str:
|
|||
)
|
||||
|
||||
|
||||
def get_en_config() -> Dict[str, Any]:
|
||||
def get_en_config() -> dict[str, Any]:
|
||||
return mkdocs.utils.yaml_load(en_config_path.read_text(encoding="utf-8"))
|
||||
|
||||
|
||||
def get_lang_paths() -> List[Path]:
|
||||
def get_lang_paths() -> list[Path]:
|
||||
return sorted(docs_path.iterdir())
|
||||
|
||||
|
||||
|
|
@ -334,14 +334,14 @@ def live(
|
|||
)
|
||||
|
||||
|
||||
def get_updated_config_content() -> Dict[str, Any]:
|
||||
def get_updated_config_content() -> dict[str, Any]:
|
||||
config = get_en_config()
|
||||
languages = [{"en": "/"}]
|
||||
new_alternate: List[Dict[str, str]] = []
|
||||
new_alternate: list[dict[str, str]] = []
|
||||
# Language names sourced from https://quickref.me/iso-639-1
|
||||
# Contributors may wish to update or change these, e.g. to fix capitalization.
|
||||
language_names_path = Path(__file__).parent / "../docs/language_names.yml"
|
||||
local_language_names: Dict[str, str] = mkdocs.utils.yaml_load(
|
||||
local_language_names: dict[str, str] = mkdocs.utils.yaml_load(
|
||||
language_names_path.read_text(encoding="utf-8")
|
||||
)
|
||||
for lang_path in get_lang_paths():
|
||||
|
|
@ -530,7 +530,7 @@ def add_permalinks_page(path: Path, update_existing: bool = False):
|
|||
|
||||
|
||||
@app.command()
|
||||
def add_permalinks_pages(pages: List[Path], update_existing: bool = False) -> None:
|
||||
def add_permalinks_pages(pages: list[Path], update_existing: bool = False) -> None:
|
||||
"""
|
||||
Add or update header permalinks in specific pages of En docs.
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
from functools import lru_cache
|
||||
from pathlib import Path
|
||||
from typing import Any, List, Union
|
||||
from typing import Any, Union
|
||||
|
||||
import material
|
||||
from mkdocs.config.defaults import MkDocsConfig
|
||||
|
|
@ -27,7 +27,7 @@ def get_missing_translation_content(docs_dir: str) -> str:
|
|||
|
||||
|
||||
@lru_cache
|
||||
def get_mkdocs_material_langs() -> List[str]:
|
||||
def get_mkdocs_material_langs() -> list[str]:
|
||||
material_path = Path(material.__file__).parent
|
||||
material_langs_path = material_path / "templates" / "partials" / "languages"
|
||||
langs = [file.stem for file in material_langs_path.glob("*.html")]
|
||||
|
|
@ -65,7 +65,7 @@ def resolve_file(*, item: str, files: Files, config: MkDocsConfig) -> None:
|
|||
)
|
||||
|
||||
|
||||
def resolve_files(*, items: List[Any], files: Files, config: MkDocsConfig) -> None:
|
||||
def resolve_files(*, items: list[Any], files: Files, config: MkDocsConfig) -> None:
|
||||
for item in items:
|
||||
if isinstance(item, str):
|
||||
resolve_file(item=item, files=files, config=config)
|
||||
|
|
@ -94,9 +94,9 @@ def on_files(files: Files, *, config: MkDocsConfig) -> Files:
|
|||
|
||||
|
||||
def generate_renamed_section_items(
|
||||
items: List[Union[Page, Section, Link]], *, config: MkDocsConfig
|
||||
) -> List[Union[Page, Section, Link]]:
|
||||
new_items: List[Union[Page, Section, Link]] = []
|
||||
items: list[Union[Page, Section, Link]], *, config: MkDocsConfig
|
||||
) -> list[Union[Page, Section, Link]]:
|
||||
new_items: list[Union[Page, Section, Link]] = []
|
||||
for item in items:
|
||||
if isinstance(item, Section):
|
||||
new_title = item.title
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import random
|
|||
import sys
|
||||
import time
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict, List, Union, cast
|
||||
from typing import Any, Union, cast
|
||||
|
||||
import httpx
|
||||
from github import Github
|
||||
|
|
@ -120,7 +120,7 @@ class CommentsEdge(BaseModel):
|
|||
|
||||
|
||||
class Comments(BaseModel):
|
||||
edges: List[CommentsEdge]
|
||||
edges: list[CommentsEdge]
|
||||
|
||||
|
||||
class CommentsDiscussion(BaseModel):
|
||||
|
|
@ -149,7 +149,7 @@ class AllDiscussionsLabelsEdge(BaseModel):
|
|||
|
||||
|
||||
class AllDiscussionsDiscussionLabels(BaseModel):
|
||||
edges: List[AllDiscussionsLabelsEdge]
|
||||
edges: list[AllDiscussionsLabelsEdge]
|
||||
|
||||
|
||||
class AllDiscussionsDiscussionNode(BaseModel):
|
||||
|
|
@ -160,7 +160,7 @@ class AllDiscussionsDiscussionNode(BaseModel):
|
|||
|
||||
|
||||
class AllDiscussionsDiscussions(BaseModel):
|
||||
nodes: List[AllDiscussionsDiscussionNode]
|
||||
nodes: list[AllDiscussionsDiscussionNode]
|
||||
|
||||
|
||||
class AllDiscussionsRepository(BaseModel):
|
||||
|
|
@ -205,7 +205,7 @@ def get_graphql_response(
|
|||
discussion_id: Union[str, None] = None,
|
||||
comment_id: Union[str, None] = None,
|
||||
body: Union[str, None] = None,
|
||||
) -> Dict[str, Any]:
|
||||
) -> dict[str, Any]:
|
||||
headers = {"Authorization": f"token {settings.github_token.get_secret_value()}"}
|
||||
variables = {
|
||||
"after": after,
|
||||
|
|
@ -233,12 +233,12 @@ def get_graphql_response(
|
|||
logging.error(data["errors"])
|
||||
logging.error(response.text)
|
||||
raise RuntimeError(response.text)
|
||||
return cast(Dict[str, Any], data)
|
||||
return cast(dict[str, Any], data)
|
||||
|
||||
|
||||
def get_graphql_translation_discussions(
|
||||
*, settings: Settings
|
||||
) -> List[AllDiscussionsDiscussionNode]:
|
||||
) -> list[AllDiscussionsDiscussionNode]:
|
||||
data = get_graphql_response(
|
||||
settings=settings,
|
||||
query=all_discussions_query,
|
||||
|
|
@ -250,7 +250,7 @@ def get_graphql_translation_discussions(
|
|||
|
||||
def get_graphql_translation_discussion_comments_edges(
|
||||
*, settings: Settings, discussion_number: int, after: Union[str, None] = None
|
||||
) -> List[CommentsEdge]:
|
||||
) -> list[CommentsEdge]:
|
||||
data = get_graphql_response(
|
||||
settings=settings,
|
||||
query=translation_discussion_query,
|
||||
|
|
@ -264,7 +264,7 @@ def get_graphql_translation_discussion_comments_edges(
|
|||
def get_graphql_translation_discussion_comments(
|
||||
*, settings: Settings, discussion_number: int
|
||||
) -> list[Comment]:
|
||||
comment_nodes: List[Comment] = []
|
||||
comment_nodes: list[Comment] = []
|
||||
discussion_edges = get_graphql_translation_discussion_comments_edges(
|
||||
settings=settings, discussion_number=discussion_number
|
||||
)
|
||||
|
|
@ -348,7 +348,7 @@ def main() -> None:
|
|||
|
||||
# Generate translation map, lang ID to discussion
|
||||
discussions = get_graphql_translation_discussions(settings=settings)
|
||||
lang_to_discussion_map: Dict[str, AllDiscussionsDiscussionNode] = {}
|
||||
lang_to_discussion_map: dict[str, AllDiscussionsDiscussionNode] = {}
|
||||
for discussion in discussions:
|
||||
for edge in discussion.labels.edges:
|
||||
label = edge.node.name
|
||||
|
|
|
|||
|
|
@ -3,9 +3,10 @@ import secrets
|
|||
import subprocess
|
||||
import time
|
||||
from collections import Counter
|
||||
from collections.abc import Container
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from pathlib import Path
|
||||
from typing import Any, Container, Union
|
||||
from typing import Any, Union
|
||||
|
||||
import httpx
|
||||
import yaml
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import http
|
||||
from typing import FrozenSet, List, Optional
|
||||
from typing import Optional
|
||||
|
||||
from fastapi import FastAPI, Path, Query
|
||||
|
||||
|
|
@ -195,15 +195,15 @@ def get_enum_status_code():
|
|||
|
||||
|
||||
@app.get("/query/frozenset")
|
||||
def get_query_type_frozenset(query: FrozenSet[int] = Query(...)):
|
||||
def get_query_type_frozenset(query: frozenset[int] = Query(...)):
|
||||
return ",".join(map(str, sorted(query)))
|
||||
|
||||
|
||||
@app.get("/query/list")
|
||||
def get_query_list(device_ids: List[int] = Query()) -> List[int]:
|
||||
def get_query_list(device_ids: list[int] = Query()) -> list[int]:
|
||||
return device_ids
|
||||
|
||||
|
||||
@app.get("/query/list-default")
|
||||
def get_query_list_default(device_ids: List[int] = Query(default=[])) -> List[int]:
|
||||
def get_query_list_default(device_ids: list[int] = Query(default=[])) -> list[int]:
|
||||
return device_ids
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
from typing import Dict
|
||||
|
||||
from fastapi import FastAPI
|
||||
from fastapi.testclient import TestClient
|
||||
from pydantic import BaseModel
|
||||
|
|
@ -8,7 +6,7 @@ app = FastAPI()
|
|||
|
||||
|
||||
class Items(BaseModel):
|
||||
items: Dict[str, int]
|
||||
items: dict[str, int]
|
||||
|
||||
|
||||
@app.post("/foo")
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
import typing
|
||||
|
||||
from fastapi import FastAPI
|
||||
from fastapi.responses import JSONResponse
|
||||
from fastapi.testclient import TestClient
|
||||
|
|
@ -18,7 +16,7 @@ class Error(BaseModel):
|
|||
|
||||
|
||||
class JsonApiError(BaseModel):
|
||||
errors: typing.List[Error]
|
||||
errors: list[Error]
|
||||
|
||||
|
||||
@app.get(
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
import typing
|
||||
|
||||
from fastapi import FastAPI
|
||||
from fastapi.responses import JSONResponse
|
||||
from fastapi.testclient import TestClient
|
||||
|
|
@ -18,7 +16,7 @@ class Error(BaseModel):
|
|||
|
||||
|
||||
class JsonApiError(BaseModel):
|
||||
errors: typing.List[Error]
|
||||
errors: list[Error]
|
||||
|
||||
|
||||
@app.get(
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
from typing import Annotated
|
||||
|
||||
import pytest
|
||||
from fastapi import Body, FastAPI, Query
|
||||
from fastapi.testclient import TestClient
|
||||
from typing_extensions import Annotated
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
from typing import Annotated
|
||||
|
||||
import pytest
|
||||
from fastapi import Depends, FastAPI, Path
|
||||
from fastapi.param_functions import Query
|
||||
from fastapi.testclient import TestClient
|
||||
from fastapi.utils import PYDANTIC_V2
|
||||
from typing_extensions import Annotated
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
from typing import Annotated
|
||||
|
||||
import pytest
|
||||
from dirty_equals import IsDict
|
||||
from fastapi import APIRouter, FastAPI, Query
|
||||
from fastapi.testclient import TestClient
|
||||
from typing_extensions import Annotated
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
from typing import List
|
||||
from typing import Annotated
|
||||
|
||||
import pytest
|
||||
from fastapi import FastAPI
|
||||
from fastapi.testclient import TestClient
|
||||
from inline_snapshot import snapshot
|
||||
from typing_extensions import Annotated
|
||||
|
||||
from .utils import needs_pydanticv2
|
||||
|
||||
|
|
@ -25,7 +24,7 @@ def get_client():
|
|||
|
||||
FakeNumpyArrayPydantic = Annotated[
|
||||
FakeNumpyArray,
|
||||
WithJsonSchema(TypeAdapter(List[float]).json_schema()),
|
||||
WithJsonSchema(TypeAdapter(list[float]).json_schema()),
|
||||
PlainSerializer(lambda v: v.data),
|
||||
]
|
||||
|
||||
|
|
@ -66,7 +65,7 @@ def test_typeadapter():
|
|||
|
||||
FakeNumpyArrayPydantic = Annotated[
|
||||
FakeNumpyArray,
|
||||
WithJsonSchema(TypeAdapter(List[float]).json_schema()),
|
||||
WithJsonSchema(TypeAdapter(list[float]).json_schema()),
|
||||
PlainSerializer(lambda v: v.data),
|
||||
]
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from typing import Any, Dict, List, Union
|
||||
from typing import Any, Union
|
||||
|
||||
from fastapi import FastAPI, UploadFile
|
||||
from fastapi._compat import (
|
||||
|
|
@ -61,7 +61,7 @@ def test_complex():
|
|||
app = FastAPI()
|
||||
|
||||
@app.post("/")
|
||||
def foo(foo: Union[str, List[int]]):
|
||||
def foo(foo: Union[str, list[int]]):
|
||||
return foo
|
||||
|
||||
client = TestClient(app)
|
||||
|
|
@ -95,7 +95,7 @@ def test_propagates_pydantic2_model_config():
|
|||
embedded_model: EmbeddedModel = EmbeddedModel()
|
||||
|
||||
@app.post("/")
|
||||
def foo(req: Model) -> Dict[str, Union[str, None]]:
|
||||
def foo(req: Model) -> dict[str, Union[str, None]]:
|
||||
return {
|
||||
"value": req.value or None,
|
||||
"embedded_value": req.embedded_model.value or None,
|
||||
|
|
@ -125,7 +125,7 @@ def test_is_bytes_sequence_annotation_union():
|
|||
# TODO: in theory this would allow declaring types that could be lists of bytes
|
||||
# to be read from files and other types, but I'm not even sure it's a good idea
|
||||
# to support it as a first class "feature"
|
||||
assert is_bytes_sequence_annotation(Union[List[str], List[bytes]])
|
||||
assert is_bytes_sequence_annotation(Union[list[str], list[bytes]])
|
||||
|
||||
|
||||
def test_is_uploadfile_sequence_annotation():
|
||||
|
|
@ -133,7 +133,7 @@ def test_is_uploadfile_sequence_annotation():
|
|||
# TODO: in theory this would allow declaring types that could be lists of UploadFile
|
||||
# and other types, but I'm not even sure it's a good idea to support it as a first
|
||||
# class "feature"
|
||||
assert is_uploadfile_sequence_annotation(Union[List[str], List[UploadFile]])
|
||||
assert is_uploadfile_sequence_annotation(Union[list[str], list[UploadFile]])
|
||||
|
||||
|
||||
@needs_pydanticv2
|
||||
|
|
@ -141,7 +141,7 @@ def test_serialize_sequence_value_with_optional_list():
|
|||
"""Test that serialize_sequence_value handles optional lists correctly."""
|
||||
from fastapi._compat import v2
|
||||
|
||||
field_info = FieldInfo(annotation=Union[List[str], None])
|
||||
field_info = FieldInfo(annotation=Union[list[str], None])
|
||||
field = v2.ModelField(name="items", field_info=field_info)
|
||||
result = v2.serialize_sequence_value(field=field, value=["a", "b", "c"])
|
||||
assert result == ["a", "b", "c"]
|
||||
|
|
@ -166,7 +166,7 @@ def test_serialize_sequence_value_with_none_first_in_union():
|
|||
"""Test that serialize_sequence_value handles Union[None, List[...]] correctly."""
|
||||
from fastapi._compat import v2
|
||||
|
||||
field_info = FieldInfo(annotation=Union[None, List[str]])
|
||||
field_info = FieldInfo(annotation=Union[None, list[str]])
|
||||
field = v2.ModelField(name="items", field_info=field_info)
|
||||
result = v2.serialize_sequence_value(field=field, value=["x", "y"])
|
||||
assert result == ["x", "y"]
|
||||
|
|
@ -179,7 +179,7 @@ def test_is_pv1_scalar_field():
|
|||
|
||||
# For coverage
|
||||
class Model(v1.BaseModel):
|
||||
foo: Union[str, Dict[str, Any]]
|
||||
foo: Union[str, dict[str, Any]]
|
||||
|
||||
fields = v1.get_model_fields(Model)
|
||||
assert not is_scalar_field(fields[0])
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import sys
|
||||
from typing import List, Optional
|
||||
from typing import Optional
|
||||
|
||||
import pytest
|
||||
|
||||
|
|
@ -8,6 +8,8 @@ from tests.utils import pydantic_snapshot, skip_module_if_py_gte_314
|
|||
if sys.version_info >= (3, 14):
|
||||
skip_module_if_py_gte_314()
|
||||
|
||||
from typing import Annotated
|
||||
|
||||
from fastapi import FastAPI
|
||||
from fastapi._compat.v1 import BaseModel
|
||||
from fastapi.temp_pydantic_v1_params import (
|
||||
|
|
@ -21,7 +23,6 @@ from fastapi.temp_pydantic_v1_params import (
|
|||
)
|
||||
from fastapi.testclient import TestClient
|
||||
from inline_snapshot import snapshot
|
||||
from typing_extensions import Annotated
|
||||
|
||||
|
||||
class Item(BaseModel):
|
||||
|
|
@ -112,7 +113,7 @@ def upload_file(
|
|||
|
||||
@app.post("/upload-multiple/")
|
||||
def upload_multiple_files(
|
||||
files: Annotated[List[bytes], File()],
|
||||
files: Annotated[list[bytes], File()],
|
||||
note: Annotated[str, Form()] = "",
|
||||
):
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
from typing import Optional
|
||||
from typing import Annotated, Optional
|
||||
|
||||
from fastapi import FastAPI
|
||||
from fastapi._compat import PYDANTIC_V2
|
||||
from fastapi.testclient import TestClient
|
||||
from pydantic import BaseModel
|
||||
from typing_extensions import Annotated
|
||||
|
||||
if PYDANTIC_V2:
|
||||
from pydantic import WithJsonSchema
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import io
|
||||
from pathlib import Path
|
||||
from typing import List
|
||||
|
||||
import pytest
|
||||
from fastapi import FastAPI, UploadFile
|
||||
|
|
@ -38,7 +37,7 @@ def test_upload_file_is_closed(tmp_path: Path):
|
|||
path.write_bytes(b"<file content>")
|
||||
app = FastAPI()
|
||||
|
||||
testing_file_store: List[UploadFile] = []
|
||||
testing_file_store: list[UploadFile] = []
|
||||
|
||||
@app.post("/uploadfile/")
|
||||
def create_upload_file(file: UploadFile):
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
from typing import Any
|
||||
from typing import Annotated, Any
|
||||
|
||||
import pytest
|
||||
from fastapi import Depends, FastAPI, HTTPException
|
||||
from fastapi.testclient import TestClient
|
||||
from typing_extensions import Annotated
|
||||
|
||||
|
||||
class CustomError(Exception):
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
from collections.abc import Generator
|
||||
from contextlib import contextmanager
|
||||
from typing import Any, Generator
|
||||
from typing import Annotated, Any
|
||||
|
||||
import pytest
|
||||
from fastapi import Depends, FastAPI
|
||||
from fastapi.responses import StreamingResponse
|
||||
from fastapi.testclient import TestClient
|
||||
from typing_extensions import Annotated
|
||||
|
||||
|
||||
class Session:
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
from collections.abc import Generator
|
||||
from contextlib import contextmanager
|
||||
from typing import Any, Generator
|
||||
from typing import Annotated, Any
|
||||
|
||||
import pytest
|
||||
from fastapi import Depends, FastAPI, WebSocket
|
||||
from fastapi.testclient import TestClient
|
||||
from typing_extensions import Annotated
|
||||
|
||||
|
||||
class Session:
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from typing import AsyncGenerator, Generator
|
||||
from collections.abc import AsyncGenerator, Generator
|
||||
|
||||
import pytest
|
||||
from fastapi import Depends, FastAPI
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import json
|
||||
from typing import Dict
|
||||
|
||||
import pytest
|
||||
from fastapi import BackgroundTasks, Depends, FastAPI
|
||||
|
|
@ -37,19 +36,19 @@ class OtherDependencyError(Exception):
|
|||
pass
|
||||
|
||||
|
||||
async def asyncgen_state(state: Dict[str, str] = Depends(get_state)):
|
||||
async def asyncgen_state(state: dict[str, str] = Depends(get_state)):
|
||||
state["/async"] = "asyncgen started"
|
||||
yield state["/async"]
|
||||
state["/async"] = "asyncgen completed"
|
||||
|
||||
|
||||
def generator_state(state: Dict[str, str] = Depends(get_state)):
|
||||
def generator_state(state: dict[str, str] = Depends(get_state)):
|
||||
state["/sync"] = "generator started"
|
||||
yield state["/sync"]
|
||||
state["/sync"] = "generator completed"
|
||||
|
||||
|
||||
async def asyncgen_state_try(state: Dict[str, str] = Depends(get_state)):
|
||||
async def asyncgen_state_try(state: dict[str, str] = Depends(get_state)):
|
||||
state["/async_raise"] = "asyncgen raise started"
|
||||
try:
|
||||
yield state["/async_raise"]
|
||||
|
|
@ -60,7 +59,7 @@ async def asyncgen_state_try(state: Dict[str, str] = Depends(get_state)):
|
|||
state["/async_raise"] = "asyncgen raise finalized"
|
||||
|
||||
|
||||
def generator_state_try(state: Dict[str, str] = Depends(get_state)):
|
||||
def generator_state_try(state: dict[str, str] = Depends(get_state)):
|
||||
state["/sync_raise"] = "generator raise started"
|
||||
try:
|
||||
yield state["/sync_raise"]
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
from collections.abc import Awaitable
|
||||
from contextvars import ContextVar
|
||||
from typing import Any, Awaitable, Callable, Dict, Optional
|
||||
from typing import Any, Callable, Optional
|
||||
|
||||
from fastapi import Depends, FastAPI, Request, Response
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
legacy_request_state_context_var: ContextVar[Optional[Dict[str, Any]]] = ContextVar(
|
||||
legacy_request_state_context_var: ContextVar[Optional[dict[str, Any]]] = ContextVar(
|
||||
"legacy_request_state_context_var", default=None
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
from typing import List
|
||||
|
||||
from dirty_equals import IsDict
|
||||
from fastapi import Depends, FastAPI
|
||||
from fastapi.testclient import TestClient
|
||||
|
|
@ -40,7 +38,7 @@ async def no_duplicates(item: Item, item2: Item = Depends(dependency)):
|
|||
|
||||
@app.post("/with-duplicates-sub")
|
||||
async def no_duplicates_sub(
|
||||
item: Item, sub_items: List[Item] = Depends(sub_duplicate_dependency)
|
||||
item: Item, sub_items: list[Item] = Depends(sub_duplicate_dependency)
|
||||
):
|
||||
return [item, sub_items]
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from typing import Union
|
||||
from typing import Annotated, Union
|
||||
|
||||
from fastapi import FastAPI, HTTPException, Security
|
||||
from fastapi.security import (
|
||||
|
|
@ -6,7 +6,6 @@ from fastapi.security import (
|
|||
SecurityScopes,
|
||||
)
|
||||
from fastapi.testclient import TestClient
|
||||
from typing_extensions import Annotated
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
from collections.abc import AsyncGenerator, Generator
|
||||
from functools import partial
|
||||
from typing import AsyncGenerator, Generator
|
||||
from typing import Annotated
|
||||
|
||||
import pytest
|
||||
from fastapi import Depends, FastAPI
|
||||
from fastapi.testclient import TestClient
|
||||
from typing_extensions import Annotated
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
from typing import List, Tuple
|
||||
|
||||
from fastapi import Depends, FastAPI, Security
|
||||
from fastapi.security import SecurityScopes
|
||||
from fastapi.testclient import TestClient
|
||||
|
|
@ -25,8 +23,8 @@ def get_data_override():
|
|||
|
||||
@app.get("/user")
|
||||
def read_user(
|
||||
user_data: Tuple[str, List[str]] = Security(get_user, scopes=["foo", "bar"]),
|
||||
data: List[int] = Depends(get_data),
|
||||
user_data: tuple[str, list[str]] = Security(get_user, scopes=["foo", "bar"]),
|
||||
data: list[int] = Depends(get_data),
|
||||
):
|
||||
return {"user": user_data[0], "scopes": user_data[1], "data": data}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import inspect
|
||||
import sys
|
||||
from collections.abc import AsyncGenerator, Generator
|
||||
from functools import wraps
|
||||
from typing import AsyncGenerator, Generator
|
||||
|
||||
import pytest
|
||||
from fastapi import Depends, FastAPI
|
||||
|
|
|
|||
|
|
@ -1,12 +1,11 @@
|
|||
import json
|
||||
from typing import Any, Tuple
|
||||
from typing import Annotated, Any
|
||||
|
||||
import pytest
|
||||
from fastapi import APIRouter, Depends, FastAPI, HTTPException
|
||||
from fastapi.exceptions import FastAPIError
|
||||
from fastapi.responses import StreamingResponse
|
||||
from fastapi.testclient import TestClient
|
||||
from typing_extensions import Annotated
|
||||
|
||||
|
||||
class Session:
|
||||
|
|
@ -43,7 +42,7 @@ def get_named_session(session: SessionRequestDep, session_b: SessionDefaultDep)
|
|||
named_session.open = False
|
||||
|
||||
|
||||
NamedSessionsDep = Annotated[Tuple[NamedSession, Session], Depends(get_named_session)]
|
||||
NamedSessionsDep = Annotated[tuple[NamedSession, Session], Depends(get_named_session)]
|
||||
|
||||
|
||||
def get_named_func_session(session: SessionFuncDep) -> Any:
|
||||
|
|
@ -58,14 +57,14 @@ def get_named_regular_func_session(session: SessionFuncDep) -> Any:
|
|||
|
||||
|
||||
BrokenSessionsDep = Annotated[
|
||||
Tuple[NamedSession, Session], Depends(get_named_func_session)
|
||||
tuple[NamedSession, Session], Depends(get_named_func_session)
|
||||
]
|
||||
NamedSessionsFuncDep = Annotated[
|
||||
Tuple[NamedSession, Session], Depends(get_named_func_session, scope="function")
|
||||
tuple[NamedSession, Session], Depends(get_named_func_session, scope="function")
|
||||
]
|
||||
|
||||
RegularSessionsDep = Annotated[
|
||||
Tuple[NamedSession, Session], Depends(get_named_regular_func_session)
|
||||
tuple[NamedSession, Session], Depends(get_named_regular_func_session)
|
||||
]
|
||||
|
||||
app = FastAPI()
|
||||
|
|
|
|||
|
|
@ -1,13 +1,12 @@
|
|||
from contextvars import ContextVar
|
||||
from typing import Any, Dict, Tuple
|
||||
from typing import Annotated, Any
|
||||
|
||||
import pytest
|
||||
from fastapi import Depends, FastAPI, WebSocket
|
||||
from fastapi.exceptions import FastAPIError
|
||||
from fastapi.testclient import TestClient
|
||||
from typing_extensions import Annotated
|
||||
|
||||
global_context: ContextVar[Dict[str, Any]] = ContextVar("global_context", default={}) # noqa: B039
|
||||
global_context: ContextVar[dict[str, Any]] = ContextVar("global_context", default={}) # noqa: B039
|
||||
|
||||
|
||||
class Session:
|
||||
|
|
@ -43,7 +42,7 @@ def get_named_session(session: SessionRequestDep, session_b: SessionDefaultDep)
|
|||
global_state["named_session_closed"] = True
|
||||
|
||||
|
||||
NamedSessionsDep = Annotated[Tuple[NamedSession, Session], Depends(get_named_session)]
|
||||
NamedSessionsDep = Annotated[tuple[NamedSession, Session], Depends(get_named_session)]
|
||||
|
||||
|
||||
def get_named_func_session(session: SessionFuncDep) -> Any:
|
||||
|
|
@ -60,14 +59,14 @@ def get_named_regular_func_session(session: SessionFuncDep) -> Any:
|
|||
|
||||
|
||||
BrokenSessionsDep = Annotated[
|
||||
Tuple[NamedSession, Session], Depends(get_named_func_session)
|
||||
tuple[NamedSession, Session], Depends(get_named_func_session)
|
||||
]
|
||||
NamedSessionsFuncDep = Annotated[
|
||||
Tuple[NamedSession, Session], Depends(get_named_func_session, scope="function")
|
||||
tuple[NamedSession, Session], Depends(get_named_func_session, scope="function")
|
||||
]
|
||||
|
||||
RegularSessionsDep = Annotated[
|
||||
Tuple[NamedSession, Session], Depends(get_named_regular_func_session)
|
||||
tuple[NamedSession, Session], Depends(get_named_regular_func_session)
|
||||
]
|
||||
|
||||
app = FastAPI()
|
||||
|
|
|
|||
|
|
@ -4,12 +4,11 @@ See https://github.com/tiangolo/fastapi/discussions/9116
|
|||
"""
|
||||
|
||||
from pathlib import Path
|
||||
from typing import List
|
||||
from typing import Annotated
|
||||
|
||||
import pytest
|
||||
from fastapi import FastAPI, File, Form
|
||||
from fastapi.testclient import TestClient
|
||||
from typing_extensions import Annotated
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
|
@ -32,7 +31,7 @@ def file_after_form(
|
|||
|
||||
@app.post("/file_list_before_form")
|
||||
def file_list_before_form(
|
||||
files: Annotated[List[bytes], File()],
|
||||
files: Annotated[list[bytes], File()],
|
||||
city: Annotated[str, Form()],
|
||||
):
|
||||
return {"file_contents": files, "city": city}
|
||||
|
|
@ -41,7 +40,7 @@ def file_list_before_form(
|
|||
@app.post("/file_list_after_form")
|
||||
def file_list_after_form(
|
||||
city: Annotated[str, Form()],
|
||||
files: Annotated[List[bytes], File()],
|
||||
files: Annotated[list[bytes], File()],
|
||||
):
|
||||
return {"file_contents": files, "city": city}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
from typing import Optional
|
||||
from typing import Annotated, Optional
|
||||
|
||||
from fastapi import FastAPI, File, Form
|
||||
from starlette.testclient import TestClient
|
||||
from typing_extensions import Annotated
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
from typing import List, Optional
|
||||
from typing import Annotated, Optional
|
||||
|
||||
from dirty_equals import IsDict
|
||||
from fastapi import FastAPI, Form
|
||||
from fastapi._compat import PYDANTIC_V2
|
||||
from fastapi.testclient import TestClient
|
||||
from pydantic import BaseModel, Field
|
||||
from typing_extensions import Annotated
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
|
@ -14,7 +13,7 @@ class FormModel(BaseModel):
|
|||
username: str
|
||||
lastname: str
|
||||
age: Optional[int] = None
|
||||
tags: List[str] = ["foo", "bar"]
|
||||
tags: list[str] = ["foo", "bar"]
|
||||
alias_with: str = Field(alias="with", default="nothing")
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
from typing import Annotated
|
||||
|
||||
from fastapi import FastAPI, Form
|
||||
from fastapi.testclient import TestClient
|
||||
from typing_extensions import Annotated
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import warnings
|
||||
from typing import List
|
||||
|
||||
from fastapi import APIRouter, FastAPI
|
||||
from fastapi.routing import APIRoute
|
||||
|
|
@ -33,12 +32,12 @@ def test_top_level_generate_unique_id():
|
|||
app = FastAPI(generate_unique_id_function=custom_generate_unique_id)
|
||||
router = APIRouter()
|
||||
|
||||
@app.post("/", response_model=List[Item], responses={404: {"model": List[Message]}})
|
||||
@app.post("/", response_model=list[Item], responses={404: {"model": list[Message]}})
|
||||
def post_root(item1: Item, item2: Item):
|
||||
return item1, item2 # pragma: nocover
|
||||
|
||||
@router.post(
|
||||
"/router", response_model=List[Item], responses={404: {"model": List[Message]}}
|
||||
"/router", response_model=list[Item], responses={404: {"model": list[Message]}}
|
||||
)
|
||||
def post_router(item1: Item, item2: Item):
|
||||
return item1, item2 # pragma: nocover
|
||||
|
|
@ -234,12 +233,12 @@ def test_router_overrides_generate_unique_id():
|
|||
app = FastAPI(generate_unique_id_function=custom_generate_unique_id)
|
||||
router = APIRouter(generate_unique_id_function=custom_generate_unique_id2)
|
||||
|
||||
@app.post("/", response_model=List[Item], responses={404: {"model": List[Message]}})
|
||||
@app.post("/", response_model=list[Item], responses={404: {"model": list[Message]}})
|
||||
def post_root(item1: Item, item2: Item):
|
||||
return item1, item2 # pragma: nocover
|
||||
|
||||
@router.post(
|
||||
"/router", response_model=List[Item], responses={404: {"model": List[Message]}}
|
||||
"/router", response_model=list[Item], responses={404: {"model": list[Message]}}
|
||||
)
|
||||
def post_router(item1: Item, item2: Item):
|
||||
return item1, item2 # pragma: nocover
|
||||
|
|
@ -435,12 +434,12 @@ def test_router_include_overrides_generate_unique_id():
|
|||
app = FastAPI(generate_unique_id_function=custom_generate_unique_id)
|
||||
router = APIRouter(generate_unique_id_function=custom_generate_unique_id2)
|
||||
|
||||
@app.post("/", response_model=List[Item], responses={404: {"model": List[Message]}})
|
||||
@app.post("/", response_model=list[Item], responses={404: {"model": list[Message]}})
|
||||
def post_root(item1: Item, item2: Item):
|
||||
return item1, item2 # pragma: nocover
|
||||
|
||||
@router.post(
|
||||
"/router", response_model=List[Item], responses={404: {"model": List[Message]}}
|
||||
"/router", response_model=list[Item], responses={404: {"model": list[Message]}}
|
||||
)
|
||||
def post_router(item1: Item, item2: Item):
|
||||
return item1, item2 # pragma: nocover
|
||||
|
|
@ -637,20 +636,20 @@ def test_subrouter_top_level_include_overrides_generate_unique_id():
|
|||
router = APIRouter()
|
||||
sub_router = APIRouter(generate_unique_id_function=custom_generate_unique_id2)
|
||||
|
||||
@app.post("/", response_model=List[Item], responses={404: {"model": List[Message]}})
|
||||
@app.post("/", response_model=list[Item], responses={404: {"model": list[Message]}})
|
||||
def post_root(item1: Item, item2: Item):
|
||||
return item1, item2 # pragma: nocover
|
||||
|
||||
@router.post(
|
||||
"/router", response_model=List[Item], responses={404: {"model": List[Message]}}
|
||||
"/router", response_model=list[Item], responses={404: {"model": list[Message]}}
|
||||
)
|
||||
def post_router(item1: Item, item2: Item):
|
||||
return item1, item2 # pragma: nocover
|
||||
|
||||
@sub_router.post(
|
||||
"/subrouter",
|
||||
response_model=List[Item],
|
||||
responses={404: {"model": List[Message]}},
|
||||
response_model=list[Item],
|
||||
responses={404: {"model": list[Message]}},
|
||||
)
|
||||
def post_subrouter(item1: Item, item2: Item):
|
||||
return item1, item2 # pragma: nocover
|
||||
|
|
@ -910,14 +909,14 @@ def test_router_path_operation_overrides_generate_unique_id():
|
|||
app = FastAPI(generate_unique_id_function=custom_generate_unique_id)
|
||||
router = APIRouter(generate_unique_id_function=custom_generate_unique_id2)
|
||||
|
||||
@app.post("/", response_model=List[Item], responses={404: {"model": List[Message]}})
|
||||
@app.post("/", response_model=list[Item], responses={404: {"model": list[Message]}})
|
||||
def post_root(item1: Item, item2: Item):
|
||||
return item1, item2 # pragma: nocover
|
||||
|
||||
@router.post(
|
||||
"/router",
|
||||
response_model=List[Item],
|
||||
responses={404: {"model": List[Message]}},
|
||||
response_model=list[Item],
|
||||
responses={404: {"model": list[Message]}},
|
||||
generate_unique_id_function=custom_generate_unique_id3,
|
||||
)
|
||||
def post_router(item1: Item, item2: Item):
|
||||
|
|
@ -1116,8 +1115,8 @@ def test_app_path_operation_overrides_generate_unique_id():
|
|||
|
||||
@app.post(
|
||||
"/",
|
||||
response_model=List[Item],
|
||||
responses={404: {"model": List[Message]}},
|
||||
response_model=list[Item],
|
||||
responses={404: {"model": list[Message]}},
|
||||
generate_unique_id_function=custom_generate_unique_id3,
|
||||
)
|
||||
def post_root(item1: Item, item2: Item):
|
||||
|
|
@ -1125,8 +1124,8 @@ def test_app_path_operation_overrides_generate_unique_id():
|
|||
|
||||
@router.post(
|
||||
"/router",
|
||||
response_model=List[Item],
|
||||
responses={404: {"model": List[Message]}},
|
||||
response_model=list[Item],
|
||||
responses={404: {"model": list[Message]}},
|
||||
)
|
||||
def post_router(item1: Item, item2: Item):
|
||||
return item1, item2 # pragma: nocover
|
||||
|
|
@ -1324,8 +1323,8 @@ def test_callback_override_generate_unique_id():
|
|||
|
||||
@callback_router.post(
|
||||
"/post-callback",
|
||||
response_model=List[Item],
|
||||
responses={404: {"model": List[Message]}},
|
||||
response_model=list[Item],
|
||||
responses={404: {"model": list[Message]}},
|
||||
generate_unique_id_function=custom_generate_unique_id3,
|
||||
)
|
||||
def post_callback(item1: Item, item2: Item):
|
||||
|
|
@ -1333,8 +1332,8 @@ def test_callback_override_generate_unique_id():
|
|||
|
||||
@app.post(
|
||||
"/",
|
||||
response_model=List[Item],
|
||||
responses={404: {"model": List[Message]}},
|
||||
response_model=list[Item],
|
||||
responses={404: {"model": list[Message]}},
|
||||
generate_unique_id_function=custom_generate_unique_id3,
|
||||
callbacks=callback_router.routes,
|
||||
)
|
||||
|
|
@ -1343,8 +1342,8 @@ def test_callback_override_generate_unique_id():
|
|||
|
||||
@app.post(
|
||||
"/tocallback",
|
||||
response_model=List[Item],
|
||||
responses={404: {"model": List[Message]}},
|
||||
response_model=list[Item],
|
||||
responses={404: {"model": list[Message]}},
|
||||
)
|
||||
def post_with_callback(item1: Item, item2: Item):
|
||||
return item1, item2 # pragma: nocover
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
from typing import TypeVar
|
||||
from typing import Annotated, TypeVar
|
||||
|
||||
from fastapi import Depends, FastAPI
|
||||
from fastapi.testclient import TestClient
|
||||
from typing_extensions import Annotated
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
from typing import Any, Iterator, Set, Type
|
||||
from collections.abc import Iterator
|
||||
from typing import Any
|
||||
|
||||
import fastapi._compat
|
||||
import fastapi.openapi.utils
|
||||
|
|
@ -143,11 +144,11 @@ class SortedTypeSet(set):
|
|||
Set of Types whose `__iter__()` method yields results sorted by the type names
|
||||
"""
|
||||
|
||||
def __init__(self, seq: Set[Type[Any]], *, sort_reversed: bool):
|
||||
def __init__(self, seq: set[type[Any]], *, sort_reversed: bool):
|
||||
super().__init__(seq)
|
||||
self.sort_reversed = sort_reversed
|
||||
|
||||
def __iter__(self) -> Iterator[Type[Any]]:
|
||||
def __iter__(self) -> Iterator[type[Any]]:
|
||||
members_sorted = sorted(
|
||||
super().__iter__(),
|
||||
key=lambda type_: type_.__name__,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
from typing import Dict, List, Tuple
|
||||
|
||||
import pytest
|
||||
from fastapi import FastAPI
|
||||
from pydantic import BaseModel
|
||||
|
|
@ -13,7 +11,7 @@ def test_invalid_sequence():
|
|||
title: str
|
||||
|
||||
@app.get("/items/{id}")
|
||||
def read_items(id: List[Item]):
|
||||
def read_items(id: list[Item]):
|
||||
pass # pragma: no cover
|
||||
|
||||
|
||||
|
|
@ -25,7 +23,7 @@ def test_invalid_tuple():
|
|||
title: str
|
||||
|
||||
@app.get("/items/{id}")
|
||||
def read_items(id: Tuple[Item, Item]):
|
||||
def read_items(id: tuple[Item, Item]):
|
||||
pass # pragma: no cover
|
||||
|
||||
|
||||
|
|
@ -37,7 +35,7 @@ def test_invalid_dict():
|
|||
title: str
|
||||
|
||||
@app.get("/items/{id}")
|
||||
def read_items(id: Dict[str, Item]):
|
||||
def read_items(id: dict[str, Item]):
|
||||
pass # pragma: no cover
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from typing import Dict, List, Optional, Tuple
|
||||
from typing import Optional
|
||||
|
||||
import pytest
|
||||
from fastapi import FastAPI, Query
|
||||
|
|
@ -13,7 +13,7 @@ def test_invalid_sequence():
|
|||
title: str
|
||||
|
||||
@app.get("/items/")
|
||||
def read_items(q: List[Item] = Query(default=None)):
|
||||
def read_items(q: list[Item] = Query(default=None)):
|
||||
pass # pragma: no cover
|
||||
|
||||
|
||||
|
|
@ -25,7 +25,7 @@ def test_invalid_tuple():
|
|||
title: str
|
||||
|
||||
@app.get("/items/")
|
||||
def read_items(q: Tuple[Item, Item] = Query(default=None)):
|
||||
def read_items(q: tuple[Item, Item] = Query(default=None)):
|
||||
pass # pragma: no cover
|
||||
|
||||
|
||||
|
|
@ -37,7 +37,7 @@ def test_invalid_dict():
|
|||
title: str
|
||||
|
||||
@app.get("/items/")
|
||||
def read_items(q: Dict[str, Item] = Query(default=None)):
|
||||
def read_items(q: dict[str, Item] = Query(default=None)):
|
||||
pass # pragma: no cover
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
from decimal import Decimal
|
||||
from typing import List
|
||||
|
||||
from dirty_equals import IsDict, IsOneOf
|
||||
from fastapi import FastAPI
|
||||
|
|
@ -15,7 +14,7 @@ class Item(BaseModel):
|
|||
|
||||
|
||||
@app.post("/items/")
|
||||
def save_item_no_body(item: List[Item]):
|
||||
def save_item_no_body(item: list[Item]):
|
||||
return {"item": item}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
from typing import List
|
||||
|
||||
from dirty_equals import IsDict
|
||||
from fastapi import FastAPI, Query
|
||||
from fastapi.testclient import TestClient
|
||||
|
|
@ -8,7 +6,7 @@ app = FastAPI()
|
|||
|
||||
|
||||
@app.get("/items/")
|
||||
def read_items(q: List[int] = Query(default=None)):
|
||||
def read_items(q: list[int] = Query(default=None)):
|
||||
return {"q": q}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
# Made an issue in:
|
||||
# https://github.com/fastapi/fastapi/issues/14247
|
||||
from enum import Enum
|
||||
from typing import List
|
||||
|
||||
from fastapi import FastAPI
|
||||
from fastapi.testclient import TestClient
|
||||
|
|
@ -25,7 +24,7 @@ class MessageEvent(BaseModel):
|
|||
|
||||
class MessageOutput(BaseModel):
|
||||
body: str = ""
|
||||
events: List[MessageEvent] = []
|
||||
events: list[MessageEvent] = []
|
||||
|
||||
|
||||
class Message(BaseModel):
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from typing import List, Optional, Union
|
||||
from typing import Optional, Union
|
||||
|
||||
import pytest
|
||||
from fastapi.openapi.models import Schema, SchemaType
|
||||
|
|
@ -13,7 +13,7 @@ from fastapi.openapi.models import Schema, SchemaType
|
|||
],
|
||||
)
|
||||
def test_allowed_schema_type(
|
||||
type_value: Optional[Union[SchemaType, List[SchemaType]]],
|
||||
type_value: Optional[Union[SchemaType, list[SchemaType]]],
|
||||
) -> None:
|
||||
"""Test that Schema accepts SchemaType, List[SchemaType] and None for type field."""
|
||||
schema = Schema(type=type_value)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from typing import List, Optional
|
||||
from typing import Optional
|
||||
|
||||
from fastapi import FastAPI
|
||||
from fastapi.testclient import TestClient
|
||||
|
|
@ -11,7 +11,7 @@ from .utils import PYDANTIC_V2, needs_pydanticv2
|
|||
class SubItem(BaseModel):
|
||||
subname: str
|
||||
sub_description: Optional[str] = None
|
||||
tags: List[str] = []
|
||||
tags: list[str] = []
|
||||
if PYDANTIC_V2:
|
||||
model_config = {"json_schema_serialization_defaults_required": True}
|
||||
|
||||
|
|
@ -44,11 +44,11 @@ def get_app_client(separate_input_output_schemas: bool = True) -> TestClient:
|
|||
return item
|
||||
|
||||
@app.post("/items-list/")
|
||||
def create_item_list(item: List[Item]):
|
||||
def create_item_list(item: list[Item]):
|
||||
return item
|
||||
|
||||
@app.get("/items/")
|
||||
def read_items() -> List[Item]:
|
||||
def read_items() -> list[Item]:
|
||||
return [
|
||||
Item(
|
||||
name="Portal Gun",
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from typing import List, Optional
|
||||
from typing import Optional
|
||||
|
||||
from fastapi import FastAPI, File
|
||||
from fastapi.testclient import TestClient
|
||||
|
|
@ -7,7 +7,7 @@ app = FastAPI()
|
|||
|
||||
|
||||
@app.post("/files")
|
||||
async def upload_files(files: Optional[List[bytes]] = File(None)):
|
||||
async def upload_files(files: Optional[list[bytes]] = File(None)):
|
||||
if files is None:
|
||||
return {"files_count": 0}
|
||||
return {"files_count": len(files), "sizes": [len(f) for f in files]}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
from typing import Any, List
|
||||
from typing import Any
|
||||
|
||||
from dirty_equals import IsOneOf
|
||||
from fastapi.params import Body, Cookie, Header, Param, Path, Query
|
||||
|
||||
test_data: List[Any] = ["teststr", None, ..., 1, []]
|
||||
test_data: list[Any] = ["teststr", None, ..., 1, []]
|
||||
|
||||
|
||||
def get_user():
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import sys
|
||||
from typing import Any, List, Union
|
||||
from typing import Any, Union
|
||||
|
||||
from tests.utils import pydantic_snapshot, skip_module_if_py_gte_314
|
||||
|
||||
|
|
@ -21,7 +21,7 @@ class Item(BaseModel):
|
|||
size: int
|
||||
description: Union[str, None] = None
|
||||
sub: SubItem
|
||||
multi: List[SubItem] = []
|
||||
multi: list[SubItem] = []
|
||||
|
||||
|
||||
app = FastAPI()
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import sys
|
||||
from typing import Any, List, Union
|
||||
from typing import Any, Union
|
||||
|
||||
from tests.utils import pydantic_snapshot, skip_module_if_py_gte_314
|
||||
|
||||
|
|
@ -21,18 +21,18 @@ class Item(BaseModel):
|
|||
size: int
|
||||
description: Union[str, None] = None
|
||||
sub: SubItem
|
||||
multi: List[SubItem] = []
|
||||
multi: list[SubItem] = []
|
||||
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
@app.post("/item")
|
||||
def handle_item(data: Item) -> List[Item]:
|
||||
def handle_item(data: Item) -> list[Item]:
|
||||
return [data, data]
|
||||
|
||||
|
||||
@app.post("/item-filter", response_model=List[Item])
|
||||
@app.post("/item-filter", response_model=list[Item])
|
||||
def handle_item_filter(data: Item) -> Any:
|
||||
extended_data = data.dict()
|
||||
extended_data.update({"secret_data": "classified", "internal_id": 12345})
|
||||
|
|
@ -41,14 +41,14 @@ def handle_item_filter(data: Item) -> Any:
|
|||
|
||||
|
||||
@app.post("/item-list")
|
||||
def handle_item_list(data: List[Item]) -> Item:
|
||||
def handle_item_list(data: list[Item]) -> Item:
|
||||
if data:
|
||||
return data[0]
|
||||
return Item(title="", size=0, sub=SubItem(name=""))
|
||||
|
||||
|
||||
@app.post("/item-list-filter", response_model=Item)
|
||||
def handle_item_list_filter(data: List[Item]) -> Any:
|
||||
def handle_item_list_filter(data: list[Item]) -> Any:
|
||||
if data:
|
||||
extended_data = data[0].dict()
|
||||
extended_data.update({"secret_data": "classified", "internal_id": 12345})
|
||||
|
|
@ -58,12 +58,12 @@ def handle_item_list_filter(data: List[Item]) -> Any:
|
|||
|
||||
|
||||
@app.post("/item-list-to-list")
|
||||
def handle_item_list_to_list(data: List[Item]) -> List[Item]:
|
||||
def handle_item_list_to_list(data: list[Item]) -> list[Item]:
|
||||
return data
|
||||
|
||||
|
||||
@app.post("/item-list-to-list-filter", response_model=List[Item])
|
||||
def handle_item_list_to_list_filter(data: List[Item]) -> Any:
|
||||
@app.post("/item-list-to-list-filter", response_model=list[Item])
|
||||
def handle_item_list_to_list_filter(data: list[Item]) -> Any:
|
||||
if data:
|
||||
extended_data = data[0].dict()
|
||||
extended_data.update({"secret_data": "classified", "internal_id": 12345})
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import sys
|
||||
from typing import Any, List, Union
|
||||
from typing import Any, Union
|
||||
|
||||
from tests.utils import pydantic_snapshot, skip_module_if_py_gte_314
|
||||
|
||||
|
|
@ -22,7 +22,7 @@ class Item(BaseModel):
|
|||
size: int
|
||||
description: Union[str, None] = None
|
||||
sub: SubItem
|
||||
multi: List[SubItem] = []
|
||||
multi: list[SubItem] = []
|
||||
|
||||
|
||||
class NewSubItem(NewBaseModel):
|
||||
|
|
@ -34,7 +34,7 @@ class NewItem(NewBaseModel):
|
|||
new_size: int
|
||||
new_description: Union[str, None] = None
|
||||
new_sub: NewSubItem
|
||||
new_multi: List[NewSubItem] = []
|
||||
new_multi: list[NewSubItem] = []
|
||||
|
||||
|
||||
app = FastAPI()
|
||||
|
|
@ -93,7 +93,7 @@ def handle_v2_item_to_v1_filter(data: NewItem) -> Any:
|
|||
|
||||
|
||||
@app.post("/v1-to-v2/item-to-list")
|
||||
def handle_v1_item_to_v2_list(data: Item) -> List[NewItem]:
|
||||
def handle_v1_item_to_v2_list(data: Item) -> list[NewItem]:
|
||||
converted = NewItem(
|
||||
new_title=data.title,
|
||||
new_size=data.size,
|
||||
|
|
@ -105,7 +105,7 @@ def handle_v1_item_to_v2_list(data: Item) -> List[NewItem]:
|
|||
|
||||
|
||||
@app.post("/v1-to-v2/list-to-list")
|
||||
def handle_v1_list_to_v2_list(data: List[Item]) -> List[NewItem]:
|
||||
def handle_v1_list_to_v2_list(data: list[Item]) -> list[NewItem]:
|
||||
result = []
|
||||
for item in data:
|
||||
result.append(
|
||||
|
|
@ -120,8 +120,8 @@ def handle_v1_list_to_v2_list(data: List[Item]) -> List[NewItem]:
|
|||
return result
|
||||
|
||||
|
||||
@app.post("/v1-to-v2/list-to-list-filter", response_model=List[NewItem])
|
||||
def handle_v1_list_to_v2_list_filter(data: List[Item]) -> Any:
|
||||
@app.post("/v1-to-v2/list-to-list-filter", response_model=list[NewItem])
|
||||
def handle_v1_list_to_v2_list_filter(data: list[Item]) -> Any:
|
||||
result = []
|
||||
for item in data:
|
||||
converted = {
|
||||
|
|
@ -140,7 +140,7 @@ def handle_v1_list_to_v2_list_filter(data: List[Item]) -> Any:
|
|||
|
||||
|
||||
@app.post("/v1-to-v2/list-to-item")
|
||||
def handle_v1_list_to_v2_item(data: List[Item]) -> NewItem:
|
||||
def handle_v1_list_to_v2_item(data: list[Item]) -> NewItem:
|
||||
if data:
|
||||
item = data[0]
|
||||
return NewItem(
|
||||
|
|
@ -154,7 +154,7 @@ def handle_v1_list_to_v2_item(data: List[Item]) -> NewItem:
|
|||
|
||||
|
||||
@app.post("/v2-to-v1/item-to-list")
|
||||
def handle_v2_item_to_v1_list(data: NewItem) -> List[Item]:
|
||||
def handle_v2_item_to_v1_list(data: NewItem) -> list[Item]:
|
||||
converted = Item(
|
||||
title=data.new_title,
|
||||
size=data.new_size,
|
||||
|
|
@ -166,7 +166,7 @@ def handle_v2_item_to_v1_list(data: NewItem) -> List[Item]:
|
|||
|
||||
|
||||
@app.post("/v2-to-v1/list-to-list")
|
||||
def handle_v2_list_to_v1_list(data: List[NewItem]) -> List[Item]:
|
||||
def handle_v2_list_to_v1_list(data: list[NewItem]) -> list[Item]:
|
||||
result = []
|
||||
for item in data:
|
||||
result.append(
|
||||
|
|
@ -181,8 +181,8 @@ def handle_v2_list_to_v1_list(data: List[NewItem]) -> List[Item]:
|
|||
return result
|
||||
|
||||
|
||||
@app.post("/v2-to-v1/list-to-list-filter", response_model=List[Item])
|
||||
def handle_v2_list_to_v1_list_filter(data: List[NewItem]) -> Any:
|
||||
@app.post("/v2-to-v1/list-to-list-filter", response_model=list[Item])
|
||||
def handle_v2_list_to_v1_list_filter(data: list[NewItem]) -> Any:
|
||||
result = []
|
||||
for item in data:
|
||||
converted = {
|
||||
|
|
@ -201,7 +201,7 @@ def handle_v2_list_to_v1_list_filter(data: List[NewItem]) -> Any:
|
|||
|
||||
|
||||
@app.post("/v2-to-v1/list-to-item")
|
||||
def handle_v2_list_to_v1_item(data: List[NewItem]) -> Item:
|
||||
def handle_v2_list_to_v1_item(data: list[NewItem]) -> Item:
|
||||
if data:
|
||||
item = data[0]
|
||||
return Item(
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
from typing import List
|
||||
|
||||
from fastapi import FastAPI
|
||||
|
||||
from . import modelsv1, modelsv2, modelsv2b
|
||||
|
|
@ -30,7 +28,7 @@ def handle_v2_item_to_v1(data: modelsv2.Item) -> modelsv1.Item:
|
|||
|
||||
|
||||
@app.post("/v1-to-v2/item-to-list")
|
||||
def handle_v1_item_to_v2_list(data: modelsv1.Item) -> List[modelsv2.Item]:
|
||||
def handle_v1_item_to_v2_list(data: modelsv1.Item) -> list[modelsv2.Item]:
|
||||
converted = modelsv2.Item(
|
||||
new_title=data.title,
|
||||
new_size=data.size,
|
||||
|
|
@ -42,7 +40,7 @@ def handle_v1_item_to_v2_list(data: modelsv1.Item) -> List[modelsv2.Item]:
|
|||
|
||||
|
||||
@app.post("/v1-to-v2/list-to-list")
|
||||
def handle_v1_list_to_v2_list(data: List[modelsv1.Item]) -> List[modelsv2.Item]:
|
||||
def handle_v1_list_to_v2_list(data: list[modelsv1.Item]) -> list[modelsv2.Item]:
|
||||
result = []
|
||||
for item in data:
|
||||
result.append(
|
||||
|
|
@ -58,7 +56,7 @@ def handle_v1_list_to_v2_list(data: List[modelsv1.Item]) -> List[modelsv2.Item]:
|
|||
|
||||
|
||||
@app.post("/v1-to-v2/list-to-item")
|
||||
def handle_v1_list_to_v2_item(data: List[modelsv1.Item]) -> modelsv2.Item:
|
||||
def handle_v1_list_to_v2_item(data: list[modelsv1.Item]) -> modelsv2.Item:
|
||||
if data:
|
||||
item = data[0]
|
||||
return modelsv2.Item(
|
||||
|
|
@ -74,7 +72,7 @@ def handle_v1_list_to_v2_item(data: List[modelsv1.Item]) -> modelsv2.Item:
|
|||
|
||||
|
||||
@app.post("/v2-to-v1/item-to-list")
|
||||
def handle_v2_item_to_v1_list(data: modelsv2.Item) -> List[modelsv1.Item]:
|
||||
def handle_v2_item_to_v1_list(data: modelsv2.Item) -> list[modelsv1.Item]:
|
||||
converted = modelsv1.Item(
|
||||
title=data.new_title,
|
||||
size=data.new_size,
|
||||
|
|
@ -86,7 +84,7 @@ def handle_v2_item_to_v1_list(data: modelsv2.Item) -> List[modelsv1.Item]:
|
|||
|
||||
|
||||
@app.post("/v2-to-v1/list-to-list")
|
||||
def handle_v2_list_to_v1_list(data: List[modelsv2.Item]) -> List[modelsv1.Item]:
|
||||
def handle_v2_list_to_v1_list(data: list[modelsv2.Item]) -> list[modelsv1.Item]:
|
||||
result = []
|
||||
for item in data:
|
||||
result.append(
|
||||
|
|
@ -102,7 +100,7 @@ def handle_v2_list_to_v1_list(data: List[modelsv2.Item]) -> List[modelsv1.Item]:
|
|||
|
||||
|
||||
@app.post("/v2-to-v1/list-to-item")
|
||||
def handle_v2_list_to_v1_item(data: List[modelsv2.Item]) -> modelsv1.Item:
|
||||
def handle_v2_list_to_v1_item(data: list[modelsv2.Item]) -> modelsv1.Item:
|
||||
if data:
|
||||
item = data[0]
|
||||
return modelsv1.Item(
|
||||
|
|
@ -130,8 +128,8 @@ def handle_v2_same_name_to_v1(
|
|||
|
||||
@app.post("/v2-to-v1/list-of-items-to-list-of-items")
|
||||
def handle_v2_items_in_list_to_v1_item_in_list(
|
||||
data1: List[modelsv2.ItemInList], data2: List[modelsv2b.ItemInList]
|
||||
) -> List[modelsv1.ItemInList]:
|
||||
data1: list[modelsv2.ItemInList], data2: list[modelsv2b.ItemInList]
|
||||
) -> list[modelsv1.ItemInList]:
|
||||
result = []
|
||||
item1 = data1[0]
|
||||
item2 = data2[0]
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from typing import List, Union
|
||||
from typing import Union
|
||||
|
||||
from fastapi._compat.v1 import BaseModel
|
||||
|
||||
|
|
@ -12,7 +12,7 @@ class Item(BaseModel):
|
|||
size: int
|
||||
description: Union[str, None] = None
|
||||
sub: SubItem
|
||||
multi: List[SubItem] = []
|
||||
multi: list[SubItem] = []
|
||||
|
||||
|
||||
class ItemInList(BaseModel):
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from typing import List, Union
|
||||
from typing import Union
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
|
@ -12,7 +12,7 @@ class Item(BaseModel):
|
|||
new_size: int
|
||||
new_description: Union[str, None] = None
|
||||
new_sub: SubItem
|
||||
new_multi: List[SubItem] = []
|
||||
new_multi: list[SubItem] = []
|
||||
|
||||
|
||||
class ItemInList(BaseModel):
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from typing import List, Union
|
||||
from typing import Union
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
|
@ -12,7 +12,7 @@ class Item(BaseModel):
|
|||
dup_size: int
|
||||
dup_description: Union[str, None] = None
|
||||
dup_sub: SubItem
|
||||
dup_multi: List[SubItem] = []
|
||||
dup_multi: list[SubItem] = []
|
||||
|
||||
|
||||
class ItemInList(BaseModel):
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import sys
|
||||
from typing import Any, List, Union
|
||||
from typing import Any, Union
|
||||
|
||||
from tests.utils import pydantic_snapshot, skip_module_if_py_gte_314
|
||||
|
||||
|
|
@ -22,7 +22,7 @@ class Item(BaseModel):
|
|||
size: int
|
||||
description: Union[str, None] = None
|
||||
sub: SubItem
|
||||
multi: List[SubItem] = []
|
||||
multi: list[SubItem] = []
|
||||
|
||||
|
||||
class NewSubItem(NewBaseModel):
|
||||
|
|
@ -34,7 +34,7 @@ class NewItem(NewBaseModel):
|
|||
new_size: int
|
||||
new_description: Union[str, None] = None
|
||||
new_sub: NewSubItem
|
||||
new_multi: List[NewSubItem] = []
|
||||
new_multi: list[NewSubItem] = []
|
||||
|
||||
|
||||
app = FastAPI()
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ from __future__ import annotations
|
|||
|
||||
import uuid
|
||||
from dataclasses import dataclass, field
|
||||
from typing import List, Union
|
||||
from typing import Union
|
||||
|
||||
from dirty_equals import IsUUID
|
||||
from fastapi import FastAPI
|
||||
|
|
@ -15,7 +15,7 @@ class Item:
|
|||
id: uuid.UUID
|
||||
name: str
|
||||
price: float
|
||||
tags: List[str] = field(default_factory=list)
|
||||
tags: list[str] = field(default_factory=list)
|
||||
description: Union[str, None] = None
|
||||
tax: Union[float, None] = None
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
from typing import Annotated
|
||||
|
||||
import pytest
|
||||
from dirty_equals import IsDict
|
||||
from fastapi import FastAPI, Form
|
||||
from fastapi.testclient import TestClient
|
||||
from typing_extensions import Annotated
|
||||
|
||||
from .utils import needs_py310
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
from typing import Annotated
|
||||
|
||||
import pytest
|
||||
from dirty_equals import IsDict
|
||||
from fastapi import FastAPI, Query
|
||||
from fastapi.testclient import TestClient
|
||||
from typing_extensions import Annotated
|
||||
|
||||
from .utils import needs_py310
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
import typing
|
||||
|
||||
from fastapi import Body, FastAPI
|
||||
from fastapi.testclient import TestClient
|
||||
from pydantic import BaseModel
|
||||
|
|
@ -28,7 +26,7 @@ async def create_product(data: Product = Body(media_type=media_type, embed=True)
|
|||
@app.post("/shops")
|
||||
async def create_shop(
|
||||
data: Shop = Body(media_type=media_type),
|
||||
included: typing.List[Product] = Body(default=[], media_type=media_type),
|
||||
included: list[Product] = Body(default=[], media_type=media_type),
|
||||
):
|
||||
pass # pragma: no cover
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
from typing import List, Union
|
||||
from typing import Annotated, Union
|
||||
|
||||
import pytest
|
||||
from dirty_equals import IsDict, IsOneOf, IsPartialDict
|
||||
from fastapi import Body, FastAPI
|
||||
from fastapi.testclient import TestClient
|
||||
from pydantic import BaseModel, Field
|
||||
from typing_extensions import Annotated
|
||||
|
||||
from tests.utils import needs_pydanticv2
|
||||
|
||||
|
|
@ -18,12 +17,12 @@ app = FastAPI()
|
|||
|
||||
|
||||
@app.post("/required-list-str", operation_id="required_list_str")
|
||||
async def read_required_list_str(p: Annotated[List[str], Body(embed=True)]):
|
||||
async def read_required_list_str(p: Annotated[list[str], Body(embed=True)]):
|
||||
return {"p": p}
|
||||
|
||||
|
||||
class BodyModelRequiredListStr(BaseModel):
|
||||
p: List[str]
|
||||
p: list[str]
|
||||
|
||||
|
||||
@app.post("/model-required-list-str", operation_id="model_required_list_str")
|
||||
|
|
@ -103,13 +102,13 @@ def test_required_list_str(path: str):
|
|||
|
||||
@app.post("/required-list-alias", operation_id="required_list_alias")
|
||||
async def read_required_list_alias(
|
||||
p: Annotated[List[str], Body(embed=True, alias="p_alias")],
|
||||
p: Annotated[list[str], Body(embed=True, alias="p_alias")],
|
||||
):
|
||||
return {"p": p}
|
||||
|
||||
|
||||
class BodyModelRequiredListAlias(BaseModel):
|
||||
p: List[str] = Field(alias="p_alias")
|
||||
p: list[str] = Field(alias="p_alias")
|
||||
|
||||
|
||||
@app.post("/model-required-list-alias", operation_id="model_required_list_alias")
|
||||
|
|
@ -228,13 +227,13 @@ def test_required_list_alias_by_alias(path: str):
|
|||
"/required-list-validation-alias", operation_id="required_list_validation_alias"
|
||||
)
|
||||
def read_required_list_validation_alias(
|
||||
p: Annotated[List[str], Body(embed=True, validation_alias="p_val_alias")],
|
||||
p: Annotated[list[str], Body(embed=True, validation_alias="p_val_alias")],
|
||||
):
|
||||
return {"p": p}
|
||||
|
||||
|
||||
class BodyModelRequiredListValidationAlias(BaseModel):
|
||||
p: List[str] = Field(validation_alias="p_val_alias")
|
||||
p: list[str] = Field(validation_alias="p_val_alias")
|
||||
|
||||
|
||||
@app.post(
|
||||
|
|
@ -345,14 +344,14 @@ def test_required_list_validation_alias_by_validation_alias(path: str):
|
|||
)
|
||||
def read_required_list_alias_and_validation_alias(
|
||||
p: Annotated[
|
||||
List[str], Body(embed=True, alias="p_alias", validation_alias="p_val_alias")
|
||||
list[str], Body(embed=True, alias="p_alias", validation_alias="p_val_alias")
|
||||
],
|
||||
):
|
||||
return {"p": p}
|
||||
|
||||
|
||||
class BodyModelRequiredListAliasAndValidationAlias(BaseModel):
|
||||
p: List[str] = Field(alias="p_alias", validation_alias="p_val_alias")
|
||||
p: list[str] = Field(alias="p_alias", validation_alias="p_val_alias")
|
||||
|
||||
|
||||
@app.post(
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
from typing import List, Optional
|
||||
from typing import Annotated, Optional
|
||||
|
||||
import pytest
|
||||
from dirty_equals import IsDict
|
||||
from fastapi import Body, FastAPI
|
||||
from fastapi.testclient import TestClient
|
||||
from pydantic import BaseModel, Field
|
||||
from typing_extensions import Annotated
|
||||
|
||||
from tests.utils import needs_pydanticv2
|
||||
|
||||
|
|
@ -19,13 +18,13 @@ app = FastAPI()
|
|||
|
||||
@app.post("/optional-list-str", operation_id="optional_list_str")
|
||||
async def read_optional_list_str(
|
||||
p: Annotated[Optional[List[str]], Body(embed=True)] = None,
|
||||
p: Annotated[Optional[list[str]], Body(embed=True)] = None,
|
||||
):
|
||||
return {"p": p}
|
||||
|
||||
|
||||
class BodyModelOptionalListStr(BaseModel):
|
||||
p: Optional[List[str]] = None
|
||||
p: Optional[list[str]] = None
|
||||
|
||||
|
||||
@app.post("/model-optional-list-str", operation_id="model_optional_list_str")
|
||||
|
|
@ -131,13 +130,13 @@ def test_optional_list_str(path: str):
|
|||
|
||||
@app.post("/optional-list-alias", operation_id="optional_list_alias")
|
||||
async def read_optional_list_alias(
|
||||
p: Annotated[Optional[List[str]], Body(embed=True, alias="p_alias")] = None,
|
||||
p: Annotated[Optional[list[str]], Body(embed=True, alias="p_alias")] = None,
|
||||
):
|
||||
return {"p": p}
|
||||
|
||||
|
||||
class BodyModelOptionalListAlias(BaseModel):
|
||||
p: Optional[List[str]] = Field(None, alias="p_alias")
|
||||
p: Optional[list[str]] = Field(None, alias="p_alias")
|
||||
|
||||
|
||||
@app.post("/model-optional-list-alias", operation_id="model_optional_list_alias")
|
||||
|
|
@ -264,14 +263,14 @@ def test_optional_list_alias_by_alias(path: str):
|
|||
)
|
||||
def read_optional_list_validation_alias(
|
||||
p: Annotated[
|
||||
Optional[List[str]], Body(embed=True, validation_alias="p_val_alias")
|
||||
Optional[list[str]], Body(embed=True, validation_alias="p_val_alias")
|
||||
] = None,
|
||||
):
|
||||
return {"p": p}
|
||||
|
||||
|
||||
class BodyModelOptionalListValidationAlias(BaseModel):
|
||||
p: Optional[List[str]] = Field(None, validation_alias="p_val_alias")
|
||||
p: Optional[list[str]] = Field(None, validation_alias="p_val_alias")
|
||||
|
||||
|
||||
@app.post(
|
||||
|
|
@ -410,7 +409,7 @@ def test_optional_list_validation_alias_by_validation_alias(path: str):
|
|||
)
|
||||
def read_optional_list_alias_and_validation_alias(
|
||||
p: Annotated[
|
||||
Optional[List[str]],
|
||||
Optional[list[str]],
|
||||
Body(embed=True, alias="p_alias", validation_alias="p_val_alias"),
|
||||
] = None,
|
||||
):
|
||||
|
|
@ -418,7 +417,7 @@ def read_optional_list_alias_and_validation_alias(
|
|||
|
||||
|
||||
class BodyModelOptionalListAliasAndValidationAlias(BaseModel):
|
||||
p: Optional[List[str]] = Field(
|
||||
p: Optional[list[str]] = Field(
|
||||
None, alias="p_alias", validation_alias="p_val_alias"
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
from typing import Optional
|
||||
from typing import Annotated, Optional
|
||||
|
||||
import pytest
|
||||
from dirty_equals import IsDict
|
||||
from fastapi import Body, FastAPI
|
||||
from fastapi.testclient import TestClient
|
||||
from pydantic import BaseModel, Field
|
||||
from typing_extensions import Annotated
|
||||
|
||||
from tests.utils import needs_pydanticv2
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
from typing import Any, Dict, Union
|
||||
from typing import Annotated, Any, Union
|
||||
|
||||
import pytest
|
||||
from dirty_equals import IsDict, IsOneOf
|
||||
from fastapi import Body, FastAPI
|
||||
from fastapi.testclient import TestClient
|
||||
from pydantic import BaseModel, Field
|
||||
from typing_extensions import Annotated
|
||||
|
||||
from tests.utils import needs_pydanticv2
|
||||
|
||||
|
|
@ -54,7 +53,7 @@ def test_required_str_schema(path: str):
|
|||
"path",
|
||||
["/required-str", "/model-required-str"],
|
||||
)
|
||||
def test_required_str_missing(path: str, json: Union[Dict[str, Any], None]):
|
||||
def test_required_str_missing(path: str, json: Union[dict[str, Any], None]):
|
||||
client = TestClient(app)
|
||||
response = client.post(path, json=json)
|
||||
assert response.status_code == 422
|
||||
|
|
@ -140,7 +139,7 @@ def test_required_str_alias_schema(path: str):
|
|||
"path",
|
||||
["/required-alias", "/model-required-alias"],
|
||||
)
|
||||
def test_required_alias_missing(path: str, json: Union[Dict[str, Any], None]):
|
||||
def test_required_alias_missing(path: str, json: Union[dict[str, Any], None]):
|
||||
client = TestClient(app)
|
||||
response = client.post(path, json=json)
|
||||
assert response.status_code == 422
|
||||
|
|
@ -266,7 +265,7 @@ def test_required_validation_alias_schema(path: str):
|
|||
],
|
||||
)
|
||||
def test_required_validation_alias_missing(
|
||||
path: str, json: Union[Dict[str, Any], None]
|
||||
path: str, json: Union[dict[str, Any], None]
|
||||
):
|
||||
client = TestClient(app)
|
||||
response = client.post(path, json=json)
|
||||
|
|
@ -386,7 +385,7 @@ def test_required_alias_and_validation_alias_schema(path: str):
|
|||
],
|
||||
)
|
||||
def test_required_alias_and_validation_alias_missing(
|
||||
path: str, json: Union[Dict[str, Any], None]
|
||||
path: str, json: Union[dict[str, Any], None]
|
||||
):
|
||||
client = TestClient(app)
|
||||
response = client.post(path, json=json)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
from typing import Any, Dict
|
||||
from typing import Any
|
||||
|
||||
|
||||
def get_body_model_name(openapi: Dict[str, Any], path: str) -> str:
|
||||
def get_body_model_name(openapi: dict[str, Any], path: str) -> str:
|
||||
body = openapi["paths"][path]["post"]["requestBody"]
|
||||
body_schema = body["content"]["application/json"]["schema"]
|
||||
return body_schema.get("$ref", "").split("/")[-1]
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
from typing import Optional
|
||||
from typing import Annotated, Optional
|
||||
|
||||
import pytest
|
||||
from dirty_equals import IsDict
|
||||
from fastapi import Cookie, FastAPI
|
||||
from fastapi.testclient import TestClient
|
||||
from pydantic import BaseModel, Field
|
||||
from typing_extensions import Annotated
|
||||
|
||||
from tests.utils import needs_pydanticv2
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
from typing import Annotated
|
||||
|
||||
import pytest
|
||||
from dirty_equals import IsDict, IsOneOf
|
||||
from fastapi import Cookie, FastAPI
|
||||
from fastapi.testclient import TestClient
|
||||
from pydantic import BaseModel, Field
|
||||
from typing_extensions import Annotated
|
||||
|
||||
from tests.utils import needs_pydanticv2
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
from typing import List
|
||||
from typing import Annotated
|
||||
|
||||
import pytest
|
||||
from dirty_equals import IsDict
|
||||
from fastapi import FastAPI, File, UploadFile
|
||||
from fastapi.testclient import TestClient
|
||||
from typing_extensions import Annotated
|
||||
|
||||
from tests.utils import needs_pydanticv2
|
||||
|
||||
|
|
@ -17,12 +16,12 @@ app = FastAPI()
|
|||
|
||||
|
||||
@app.post("/list-bytes", operation_id="list_bytes")
|
||||
async def read_list_bytes(p: Annotated[List[bytes], File()]):
|
||||
async def read_list_bytes(p: Annotated[list[bytes], File()]):
|
||||
return {"file_size": [len(file) for file in p]}
|
||||
|
||||
|
||||
@app.post("/list-uploadfile", operation_id="list_uploadfile")
|
||||
async def read_list_uploadfile(p: Annotated[List[UploadFile], File()]):
|
||||
async def read_list_uploadfile(p: Annotated[list[UploadFile], File()]):
|
||||
return {"file_size": [file.size for file in p]}
|
||||
|
||||
|
||||
|
|
@ -122,13 +121,13 @@ def test_list(path: str):
|
|||
|
||||
|
||||
@app.post("/list-bytes-alias", operation_id="list_bytes_alias")
|
||||
async def read_list_bytes_alias(p: Annotated[List[bytes], File(alias="p_alias")]):
|
||||
async def read_list_bytes_alias(p: Annotated[list[bytes], File(alias="p_alias")]):
|
||||
return {"file_size": [len(file) for file in p]}
|
||||
|
||||
|
||||
@app.post("/list-uploadfile-alias", operation_id="list_uploadfile_alias")
|
||||
async def read_list_uploadfile_alias(
|
||||
p: Annotated[List[UploadFile], File(alias="p_alias")],
|
||||
p: Annotated[list[UploadFile], File(alias="p_alias")],
|
||||
):
|
||||
return {"file_size": [file.size for file in p]}
|
||||
|
||||
|
|
@ -266,7 +265,7 @@ def test_list_alias_by_alias(path: str):
|
|||
|
||||
@app.post("/list-bytes-validation-alias", operation_id="list_bytes_validation_alias")
|
||||
def read_list_bytes_validation_alias(
|
||||
p: Annotated[List[bytes], File(validation_alias="p_val_alias")],
|
||||
p: Annotated[list[bytes], File(validation_alias="p_val_alias")],
|
||||
):
|
||||
return {"file_size": [len(file) for file in p]}
|
||||
|
||||
|
|
@ -276,7 +275,7 @@ def read_list_bytes_validation_alias(
|
|||
operation_id="list_uploadfile_validation_alias",
|
||||
)
|
||||
def read_list_uploadfile_validation_alias(
|
||||
p: Annotated[List[UploadFile], File(validation_alias="p_val_alias")],
|
||||
p: Annotated[list[UploadFile], File(validation_alias="p_val_alias")],
|
||||
):
|
||||
return {"file_size": [file.size for file in p]}
|
||||
|
||||
|
|
@ -401,7 +400,7 @@ def test_list_validation_alias_by_validation_alias(path: str):
|
|||
operation_id="list_bytes_alias_and_validation_alias",
|
||||
)
|
||||
def read_list_bytes_alias_and_validation_alias(
|
||||
p: Annotated[List[bytes], File(alias="p_alias", validation_alias="p_val_alias")],
|
||||
p: Annotated[list[bytes], File(alias="p_alias", validation_alias="p_val_alias")],
|
||||
):
|
||||
return {"file_size": [len(file) for file in p]}
|
||||
|
||||
|
|
@ -412,7 +411,7 @@ def read_list_bytes_alias_and_validation_alias(
|
|||
)
|
||||
def read_list_uploadfile_alias_and_validation_alias(
|
||||
p: Annotated[
|
||||
List[UploadFile], File(alias="p_alias", validation_alias="p_val_alias")
|
||||
list[UploadFile], File(alias="p_alias", validation_alias="p_val_alias")
|
||||
],
|
||||
):
|
||||
return {"file_size": [file.size for file in p]}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
from typing import Optional
|
||||
from typing import Annotated, Optional
|
||||
|
||||
import pytest
|
||||
from dirty_equals import IsDict
|
||||
from fastapi import FastAPI, File, UploadFile
|
||||
from fastapi.testclient import TestClient
|
||||
from typing_extensions import Annotated
|
||||
|
||||
from tests.utils import needs_pydanticv2
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
from typing import List, Optional
|
||||
from typing import Annotated, Optional
|
||||
|
||||
import pytest
|
||||
from dirty_equals import IsDict
|
||||
from fastapi import FastAPI, File, UploadFile
|
||||
from fastapi.testclient import TestClient
|
||||
from typing_extensions import Annotated
|
||||
|
||||
from tests.utils import needs_pydanticv2
|
||||
|
||||
|
|
@ -17,13 +16,13 @@ app = FastAPI()
|
|||
|
||||
|
||||
@app.post("/optional-list-bytes")
|
||||
async def read_optional_list_bytes(p: Annotated[Optional[List[bytes]], File()] = None):
|
||||
async def read_optional_list_bytes(p: Annotated[Optional[list[bytes]], File()] = None):
|
||||
return {"file_size": [len(file) for file in p] if p else None}
|
||||
|
||||
|
||||
@app.post("/optional-list-uploadfile")
|
||||
async def read_optional_list_uploadfile(
|
||||
p: Annotated[Optional[List[UploadFile]], File()] = None,
|
||||
p: Annotated[Optional[list[UploadFile]], File()] = None,
|
||||
):
|
||||
return {"file_size": [file.size for file in p] if p else None}
|
||||
|
||||
|
|
@ -103,14 +102,14 @@ def test_optional_list(path: str):
|
|||
|
||||
@app.post("/optional-list-bytes-alias")
|
||||
async def read_optional_list_bytes_alias(
|
||||
p: Annotated[Optional[List[bytes]], File(alias="p_alias")] = None,
|
||||
p: Annotated[Optional[list[bytes]], File(alias="p_alias")] = None,
|
||||
):
|
||||
return {"file_size": [len(file) for file in p] if p else None}
|
||||
|
||||
|
||||
@app.post("/optional-list-uploadfile-alias")
|
||||
async def read_optional_list_uploadfile_alias(
|
||||
p: Annotated[Optional[List[UploadFile]], File(alias="p_alias")] = None,
|
||||
p: Annotated[Optional[list[UploadFile]], File(alias="p_alias")] = None,
|
||||
):
|
||||
return {"file_size": [file.size for file in p] if p else None}
|
||||
|
||||
|
|
@ -204,7 +203,7 @@ def test_optional_list_alias_by_alias(path: str):
|
|||
|
||||
@app.post("/optional-list-bytes-validation-alias")
|
||||
def read_optional_list_bytes_validation_alias(
|
||||
p: Annotated[Optional[List[bytes]], File(validation_alias="p_val_alias")] = None,
|
||||
p: Annotated[Optional[list[bytes]], File(validation_alias="p_val_alias")] = None,
|
||||
):
|
||||
return {"file_size": [len(file) for file in p] if p else None}
|
||||
|
||||
|
|
@ -212,7 +211,7 @@ def read_optional_list_bytes_validation_alias(
|
|||
@app.post("/optional-list-uploadfile-validation-alias")
|
||||
def read_optional_list_uploadfile_validation_alias(
|
||||
p: Annotated[
|
||||
Optional[List[UploadFile]], File(validation_alias="p_val_alias")
|
||||
Optional[list[UploadFile]], File(validation_alias="p_val_alias")
|
||||
] = None,
|
||||
):
|
||||
return {"file_size": [file.size for file in p] if p else None}
|
||||
|
|
@ -314,7 +313,7 @@ def test_optional_validation_alias_by_validation_alias(path: str):
|
|||
@app.post("/optional-list-bytes-alias-and-validation-alias")
|
||||
def read_optional_list_bytes_alias_and_validation_alias(
|
||||
p: Annotated[
|
||||
Optional[List[bytes]], File(alias="p_alias", validation_alias="p_val_alias")
|
||||
Optional[list[bytes]], File(alias="p_alias", validation_alias="p_val_alias")
|
||||
] = None,
|
||||
):
|
||||
return {"file_size": [len(file) for file in p] if p else None}
|
||||
|
|
@ -323,7 +322,7 @@ def read_optional_list_bytes_alias_and_validation_alias(
|
|||
@app.post("/optional-list-uploadfile-alias-and-validation-alias")
|
||||
def read_optional_list_uploadfile_alias_and_validation_alias(
|
||||
p: Annotated[
|
||||
Optional[List[UploadFile]],
|
||||
Optional[list[UploadFile]],
|
||||
File(alias="p_alias", validation_alias="p_val_alias"),
|
||||
] = None,
|
||||
):
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
from typing import Annotated
|
||||
|
||||
import pytest
|
||||
from dirty_equals import IsDict
|
||||
from fastapi import FastAPI, File, UploadFile
|
||||
from fastapi.testclient import TestClient
|
||||
from typing_extensions import Annotated
|
||||
|
||||
from tests.utils import needs_pydanticv2
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
from typing import Any, Dict
|
||||
from typing import Any
|
||||
|
||||
|
||||
def get_body_model_name(openapi: Dict[str, Any], path: str) -> str:
|
||||
def get_body_model_name(openapi: dict[str, Any], path: str) -> str:
|
||||
body = openapi["paths"][path]["post"]["requestBody"]
|
||||
body_schema = body["content"]["multipart/form-data"]["schema"]
|
||||
return body_schema.get("$ref", "").split("/")[-1]
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
from typing import List
|
||||
from typing import Annotated
|
||||
|
||||
import pytest
|
||||
from dirty_equals import IsDict, IsOneOf, IsPartialDict
|
||||
from fastapi import FastAPI, Form
|
||||
from fastapi.testclient import TestClient
|
||||
from pydantic import BaseModel, Field
|
||||
from typing_extensions import Annotated
|
||||
|
||||
from tests.utils import needs_pydanticv2
|
||||
|
||||
|
|
@ -18,12 +17,12 @@ app = FastAPI()
|
|||
|
||||
|
||||
@app.post("/required-list-str", operation_id="required_list_str")
|
||||
async def read_required_list_str(p: Annotated[List[str], Form()]):
|
||||
async def read_required_list_str(p: Annotated[list[str], Form()]):
|
||||
return {"p": p}
|
||||
|
||||
|
||||
class FormModelRequiredListStr(BaseModel):
|
||||
p: List[str]
|
||||
p: list[str]
|
||||
|
||||
|
||||
@app.post("/model-required-list-str", operation_id="model_required_list_str")
|
||||
|
|
@ -101,12 +100,12 @@ def test_required_list_str(path: str):
|
|||
|
||||
|
||||
@app.post("/required-list-alias", operation_id="required_list_alias")
|
||||
async def read_required_list_alias(p: Annotated[List[str], Form(alias="p_alias")]):
|
||||
async def read_required_list_alias(p: Annotated[list[str], Form(alias="p_alias")]):
|
||||
return {"p": p}
|
||||
|
||||
|
||||
class FormModelRequiredListAlias(BaseModel):
|
||||
p: List[str] = Field(alias="p_alias")
|
||||
p: list[str] = Field(alias="p_alias")
|
||||
|
||||
|
||||
@app.post("/model-required-list-alias", operation_id="model_required_list_alias")
|
||||
|
|
@ -229,13 +228,13 @@ def test_required_list_alias_by_alias(path: str):
|
|||
"/required-list-validation-alias", operation_id="required_list_validation_alias"
|
||||
)
|
||||
def read_required_list_validation_alias(
|
||||
p: Annotated[List[str], Form(validation_alias="p_val_alias")],
|
||||
p: Annotated[list[str], Form(validation_alias="p_val_alias")],
|
||||
):
|
||||
return {"p": p}
|
||||
|
||||
|
||||
class FormModelRequiredListValidationAlias(BaseModel):
|
||||
p: List[str] = Field(validation_alias="p_val_alias")
|
||||
p: list[str] = Field(validation_alias="p_val_alias")
|
||||
|
||||
|
||||
@app.post(
|
||||
|
|
@ -345,13 +344,13 @@ def test_required_list_validation_alias_by_validation_alias(path: str):
|
|||
operation_id="required_list_alias_and_validation_alias",
|
||||
)
|
||||
def read_required_list_alias_and_validation_alias(
|
||||
p: Annotated[List[str], Form(alias="p_alias", validation_alias="p_val_alias")],
|
||||
p: Annotated[list[str], Form(alias="p_alias", validation_alias="p_val_alias")],
|
||||
):
|
||||
return {"p": p}
|
||||
|
||||
|
||||
class FormModelRequiredListAliasAndValidationAlias(BaseModel):
|
||||
p: List[str] = Field(alias="p_alias", validation_alias="p_val_alias")
|
||||
p: list[str] = Field(alias="p_alias", validation_alias="p_val_alias")
|
||||
|
||||
|
||||
@app.post(
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue