增加环绕侦察场景适配
This commit is contained in:
@@ -1,37 +1,31 @@
|
||||
import dataclasses
|
||||
import email.message
|
||||
import functools
|
||||
import inspect
|
||||
import json
|
||||
import sys
|
||||
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,
|
||||
)
|
||||
|
||||
from annotated_doc import Doc
|
||||
from fastapi import params, temp_pydantic_v1_params
|
||||
from fastapi import params
|
||||
from fastapi._compat import (
|
||||
ModelField,
|
||||
Undefined,
|
||||
_get_model_config,
|
||||
_model_dump,
|
||||
_normalize_errors,
|
||||
annotation_is_pydantic_v1,
|
||||
lenient_issubclass,
|
||||
)
|
||||
from fastapi.datastructures import Default, DefaultPlaceholder
|
||||
@@ -47,7 +41,9 @@ from fastapi.dependencies.utils import (
|
||||
)
|
||||
from fastapi.encoders import jsonable_encoder
|
||||
from fastapi.exceptions import (
|
||||
EndpointContext,
|
||||
FastAPIError,
|
||||
PydanticV1NotSupportedError,
|
||||
RequestValidationError,
|
||||
ResponseValidationError,
|
||||
WebSocketRequestValidationError,
|
||||
@@ -60,7 +56,6 @@ from fastapi.utils import (
|
||||
get_value_or_default,
|
||||
is_body_allowed_for_status_code,
|
||||
)
|
||||
from pydantic import BaseModel
|
||||
from starlette import routing
|
||||
from starlette._exception_handler import wrap_app_handling_exceptions
|
||||
from starlette._utils import is_async_callable
|
||||
@@ -77,12 +72,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
|
||||
|
||||
if sys.version_info >= (3, 13): # pragma: no cover
|
||||
from inspect import iscoroutinefunction
|
||||
else: # pragma: no cover
|
||||
from asyncio import iscoroutinefunction
|
||||
from typing_extensions import deprecated
|
||||
|
||||
|
||||
# Copy of starlette.routing.request_response modified to include the
|
||||
@@ -153,54 +143,6 @@ def websocket_session(
|
||||
return app
|
||||
|
||||
|
||||
def _prepare_response_content(
|
||||
res: Any,
|
||||
*,
|
||||
exclude_unset: bool,
|
||||
exclude_defaults: bool = False,
|
||||
exclude_none: bool = False,
|
||||
) -> Any:
|
||||
if isinstance(res, BaseModel):
|
||||
read_with_orm_mode = getattr(_get_model_config(res), "read_with_orm_mode", None)
|
||||
if read_with_orm_mode:
|
||||
# Let from_orm extract the data from this model instead of converting
|
||||
# it now to a dict.
|
||||
# Otherwise, there's no way to extract lazy data that requires attribute
|
||||
# access instead of dict iteration, e.g. lazy relationships.
|
||||
return res
|
||||
return _model_dump(
|
||||
res,
|
||||
by_alias=True,
|
||||
exclude_unset=exclude_unset,
|
||||
exclude_defaults=exclude_defaults,
|
||||
exclude_none=exclude_none,
|
||||
)
|
||||
elif isinstance(res, list):
|
||||
return [
|
||||
_prepare_response_content(
|
||||
item,
|
||||
exclude_unset=exclude_unset,
|
||||
exclude_defaults=exclude_defaults,
|
||||
exclude_none=exclude_none,
|
||||
)
|
||||
for item in res
|
||||
]
|
||||
elif isinstance(res, dict):
|
||||
return {
|
||||
k: _prepare_response_content(
|
||||
v,
|
||||
exclude_unset=exclude_unset,
|
||||
exclude_defaults=exclude_defaults,
|
||||
exclude_none=exclude_none,
|
||||
)
|
||||
for k, v in res.items()
|
||||
}
|
||||
elif dataclasses.is_dataclass(res):
|
||||
assert not isinstance(res, type)
|
||||
return dataclasses.asdict(res)
|
||||
return res
|
||||
|
||||
|
||||
def _merge_lifespan_context(
|
||||
original_context: Lifespan[Any], nested_context: Lifespan[Any]
|
||||
) -> Lifespan[Any]:
|
||||
@@ -218,6 +160,33 @@ def _merge_lifespan_context(
|
||||
return merged_lifespan # type: ignore[return-value]
|
||||
|
||||
|
||||
# Cache for endpoint context to avoid re-extracting on every request
|
||||
_endpoint_context_cache: dict[int, EndpointContext] = {}
|
||||
|
||||
|
||||
def _extract_endpoint_context(func: Any) -> EndpointContext:
|
||||
"""Extract endpoint context with caching to avoid repeated file I/O."""
|
||||
func_id = id(func)
|
||||
|
||||
if func_id in _endpoint_context_cache:
|
||||
return _endpoint_context_cache[func_id]
|
||||
|
||||
try:
|
||||
ctx: EndpointContext = {}
|
||||
|
||||
if (source_file := inspect.getsourcefile(func)) is not None:
|
||||
ctx["file"] = source_file
|
||||
if (line_number := inspect.getsourcelines(func)[1]) is not None:
|
||||
ctx["line"] = line_number
|
||||
if (func_name := getattr(func, "__name__", None)) is not None:
|
||||
ctx["function"] = func_name
|
||||
except Exception:
|
||||
ctx = EndpointContext()
|
||||
|
||||
_endpoint_context_cache[func_id] = ctx
|
||||
return ctx
|
||||
|
||||
|
||||
async def serialize_response(
|
||||
*,
|
||||
field: Optional[ModelField] = None,
|
||||
@@ -229,17 +198,10 @@ async def serialize_response(
|
||||
exclude_defaults: bool = False,
|
||||
exclude_none: bool = False,
|
||||
is_coroutine: bool = True,
|
||||
endpoint_ctx: Optional[EndpointContext] = None,
|
||||
) -> Any:
|
||||
if field:
|
||||
errors = []
|
||||
if not hasattr(field, "serialize"):
|
||||
# pydantic v1
|
||||
response_content = _prepare_response_content(
|
||||
response_content,
|
||||
exclude_unset=exclude_unset,
|
||||
exclude_defaults=exclude_defaults,
|
||||
exclude_none=exclude_none,
|
||||
)
|
||||
if is_coroutine:
|
||||
value, errors_ = field.validate(response_content, {}, loc=("response",))
|
||||
else:
|
||||
@@ -248,25 +210,15 @@ async def serialize_response(
|
||||
)
|
||||
if isinstance(errors_, list):
|
||||
errors.extend(errors_)
|
||||
elif errors_:
|
||||
errors.append(errors_)
|
||||
if errors:
|
||||
ctx = endpoint_ctx or EndpointContext()
|
||||
raise ResponseValidationError(
|
||||
errors=_normalize_errors(errors), body=response_content
|
||||
errors=errors,
|
||||
body=response_content,
|
||||
endpoint_ctx=ctx,
|
||||
)
|
||||
|
||||
if hasattr(field, "serialize"):
|
||||
return field.serialize(
|
||||
value,
|
||||
include=include,
|
||||
exclude=exclude,
|
||||
by_alias=by_alias,
|
||||
exclude_unset=exclude_unset,
|
||||
exclude_defaults=exclude_defaults,
|
||||
exclude_none=exclude_none,
|
||||
)
|
||||
|
||||
return jsonable_encoder(
|
||||
return field.serialize(
|
||||
value,
|
||||
include=include,
|
||||
exclude=exclude,
|
||||
@@ -275,12 +227,13 @@ async def serialize_response(
|
||||
exclude_defaults=exclude_defaults,
|
||||
exclude_none=exclude_none,
|
||||
)
|
||||
|
||||
else:
|
||||
return jsonable_encoder(response_content)
|
||||
|
||||
|
||||
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.
|
||||
@@ -296,7 +249,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,
|
||||
@@ -308,12 +261,10 @@ def get_request_handler(
|
||||
embed_body_fields: bool = False,
|
||||
) -> Callable[[Request], Coroutine[Any, Any, Response]]:
|
||||
assert dependant.call is not None, "dependant.call must be a function"
|
||||
is_coroutine = iscoroutinefunction(dependant.call)
|
||||
is_body_form = body_field and isinstance(
|
||||
body_field.field_info, (params.Form, temp_pydantic_v1_params.Form)
|
||||
)
|
||||
is_coroutine = dependant.is_coroutine_callable
|
||||
is_body_form = body_field and isinstance(body_field.field_info, 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
|
||||
|
||||
@@ -324,6 +275,18 @@ def get_request_handler(
|
||||
"fastapi_middleware_astack not found in request scope"
|
||||
)
|
||||
|
||||
# Extract endpoint context for error messages
|
||||
endpoint_ctx = (
|
||||
_extract_endpoint_context(dependant.call)
|
||||
if dependant.call
|
||||
else EndpointContext()
|
||||
)
|
||||
|
||||
if dependant.path:
|
||||
# For mounted sub-apps, include the mount path prefix
|
||||
mount_path = request.scope.get("root_path", "").rstrip("/")
|
||||
endpoint_ctx["path"] = f"{request.method} {mount_path}{dependant.path}"
|
||||
|
||||
# Read body and auto-close files
|
||||
try:
|
||||
body: Any = None
|
||||
@@ -361,6 +324,7 @@ def get_request_handler(
|
||||
}
|
||||
],
|
||||
body=e.doc,
|
||||
endpoint_ctx=endpoint_ctx,
|
||||
)
|
||||
raise validation_error from e
|
||||
except HTTPException:
|
||||
@@ -373,7 +337,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"
|
||||
@@ -398,7 +362,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
|
||||
@@ -420,6 +384,7 @@ def get_request_handler(
|
||||
exclude_defaults=response_model_exclude_defaults,
|
||||
exclude_none=response_model_exclude_none,
|
||||
is_coroutine=is_coroutine,
|
||||
endpoint_ctx=endpoint_ctx,
|
||||
)
|
||||
response = actual_response_class(content, **response_args)
|
||||
if not is_body_allowed_for_status_code(response.status_code):
|
||||
@@ -427,7 +392,7 @@ def get_request_handler(
|
||||
response.headers.raw.extend(solved_result.response.headers.raw)
|
||||
if errors:
|
||||
validation_error = RequestValidationError(
|
||||
_normalize_errors(errors), body=body
|
||||
errors, body=body, endpoint_ctx=endpoint_ctx
|
||||
)
|
||||
raise validation_error
|
||||
|
||||
@@ -444,6 +409,15 @@ def get_websocket_app(
|
||||
embed_body_fields: bool = False,
|
||||
) -> Callable[[WebSocket], Coroutine[Any, Any, Any]]:
|
||||
async def app(websocket: WebSocket) -> None:
|
||||
endpoint_ctx = (
|
||||
_extract_endpoint_context(dependant.call)
|
||||
if dependant.call
|
||||
else EndpointContext()
|
||||
)
|
||||
if dependant.path:
|
||||
# For mounted sub-apps, include the mount path prefix
|
||||
mount_path = websocket.scope.get("root_path", "").rstrip("/")
|
||||
endpoint_ctx["path"] = f"WS {mount_path}{dependant.path}"
|
||||
async_exit_stack = websocket.scope.get("fastapi_inner_astack")
|
||||
assert isinstance(async_exit_stack, AsyncExitStack), (
|
||||
"fastapi_inner_astack not found in request scope"
|
||||
@@ -457,7 +431,8 @@ def get_websocket_app(
|
||||
)
|
||||
if solved_result.errors:
|
||||
raise WebSocketRequestValidationError(
|
||||
_normalize_errors(solved_result.errors)
|
||||
solved_result.errors,
|
||||
endpoint_ctx=endpoint_ctx,
|
||||
)
|
||||
assert dependant.call is not None, "dependant.call must be a function"
|
||||
await dependant.call(**solved_result.values)
|
||||
@@ -500,7 +475,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
|
||||
@@ -515,15 +490,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,
|
||||
@@ -532,12 +507,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),
|
||||
@@ -573,7 +548,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
|
||||
@@ -590,6 +565,11 @@ class APIRoute(routing.Route):
|
||||
f"Status code {status_code} must not have a response body"
|
||||
)
|
||||
response_name = "Response_" + self.unique_id
|
||||
if annotation_is_pydantic_v1(self.response_model):
|
||||
raise PydanticV1NotSupportedError(
|
||||
"pydantic.v1 models are no longer supported by FastAPI."
|
||||
f" Please update the response model {self.response_model!r}."
|
||||
)
|
||||
self.response_field = create_model_field(
|
||||
name=response_name,
|
||||
type_=self.response_model,
|
||||
@@ -623,12 +603,17 @@ class APIRoute(routing.Route):
|
||||
f"Status code {additional_status_code} must not have a response body"
|
||||
)
|
||||
response_name = f"Response_{additional_status_code}_{self.unique_id}"
|
||||
if annotation_is_pydantic_v1(model):
|
||||
raise PydanticV1NotSupportedError(
|
||||
"pydantic.v1 models are no longer supported by FastAPI."
|
||||
f" In responses={{}}, please update {model}."
|
||||
)
|
||||
response_field = create_model_field(
|
||||
name=response_name, type_=model, mode="serialization"
|
||||
)
|
||||
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 = {}
|
||||
|
||||
@@ -669,7 +654,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
|
||||
@@ -708,7 +693,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
|
||||
@@ -734,7 +719,7 @@ class APIRouter(routing.Router):
|
||||
),
|
||||
] = None,
|
||||
default_response_class: Annotated[
|
||||
Type[Response],
|
||||
type[Response],
|
||||
Doc(
|
||||
"""
|
||||
The default response class to be used.
|
||||
@@ -745,7 +730,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.
|
||||
@@ -761,7 +746,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
|
||||
@@ -775,7 +760,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
|
||||
@@ -826,7 +811,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.
|
||||
@@ -932,7 +917,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
|
||||
@@ -969,14 +954,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,
|
||||
@@ -985,13 +970,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),
|
||||
@@ -1050,14 +1035,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,
|
||||
@@ -1066,10 +1051,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
|
||||
),
|
||||
@@ -1209,7 +1194,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
|
||||
@@ -1235,7 +1220,7 @@ class APIRouter(routing.Router):
|
||||
),
|
||||
] = None,
|
||||
default_response_class: Annotated[
|
||||
Type[Response],
|
||||
type[Response],
|
||||
Doc(
|
||||
"""
|
||||
The default response class to be used.
|
||||
@@ -1246,7 +1231,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.
|
||||
@@ -1262,7 +1247,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
|
||||
@@ -1367,7 +1352,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:
|
||||
@@ -1508,7 +1493,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*.
|
||||
@@ -1574,7 +1559,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*.
|
||||
@@ -1715,7 +1700,7 @@ class APIRouter(routing.Router):
|
||||
),
|
||||
] = True,
|
||||
response_class: Annotated[
|
||||
Type[Response],
|
||||
type[Response],
|
||||
Doc(
|
||||
"""
|
||||
Response class to be used for this *path operation*.
|
||||
@@ -1736,7 +1721,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.
|
||||
@@ -1752,7 +1737,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
|
||||
@@ -1885,7 +1870,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*.
|
||||
@@ -1951,7 +1936,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*.
|
||||
@@ -2092,7 +2077,7 @@ class APIRouter(routing.Router):
|
||||
),
|
||||
] = True,
|
||||
response_class: Annotated[
|
||||
Type[Response],
|
||||
type[Response],
|
||||
Doc(
|
||||
"""
|
||||
Response class to be used for this *path operation*.
|
||||
@@ -2113,7 +2098,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.
|
||||
@@ -2129,7 +2114,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
|
||||
@@ -2267,7 +2252,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*.
|
||||
@@ -2333,7 +2318,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*.
|
||||
@@ -2474,7 +2459,7 @@ class APIRouter(routing.Router):
|
||||
),
|
||||
] = True,
|
||||
response_class: Annotated[
|
||||
Type[Response],
|
||||
type[Response],
|
||||
Doc(
|
||||
"""
|
||||
Response class to be used for this *path operation*.
|
||||
@@ -2495,7 +2480,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.
|
||||
@@ -2511,7 +2496,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
|
||||
@@ -2649,7 +2634,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*.
|
||||
@@ -2715,7 +2700,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*.
|
||||
@@ -2856,7 +2841,7 @@ class APIRouter(routing.Router):
|
||||
),
|
||||
] = True,
|
||||
response_class: Annotated[
|
||||
Type[Response],
|
||||
type[Response],
|
||||
Doc(
|
||||
"""
|
||||
Response class to be used for this *path operation*.
|
||||
@@ -2877,7 +2862,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.
|
||||
@@ -2893,7 +2878,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
|
||||
@@ -3026,7 +3011,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*.
|
||||
@@ -3092,7 +3077,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*.
|
||||
@@ -3233,7 +3218,7 @@ class APIRouter(routing.Router):
|
||||
),
|
||||
] = True,
|
||||
response_class: Annotated[
|
||||
Type[Response],
|
||||
type[Response],
|
||||
Doc(
|
||||
"""
|
||||
Response class to be used for this *path operation*.
|
||||
@@ -3254,7 +3239,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.
|
||||
@@ -3270,7 +3255,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
|
||||
@@ -3403,7 +3388,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*.
|
||||
@@ -3469,7 +3454,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*.
|
||||
@@ -3610,7 +3595,7 @@ class APIRouter(routing.Router):
|
||||
),
|
||||
] = True,
|
||||
response_class: Annotated[
|
||||
Type[Response],
|
||||
type[Response],
|
||||
Doc(
|
||||
"""
|
||||
Response class to be used for this *path operation*.
|
||||
@@ -3631,7 +3616,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.
|
||||
@@ -3647,7 +3632,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
|
||||
@@ -3785,7 +3770,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*.
|
||||
@@ -3851,7 +3836,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*.
|
||||
@@ -3992,7 +3977,7 @@ class APIRouter(routing.Router):
|
||||
),
|
||||
] = True,
|
||||
response_class: Annotated[
|
||||
Type[Response],
|
||||
type[Response],
|
||||
Doc(
|
||||
"""
|
||||
Response class to be used for this *path operation*.
|
||||
@@ -4013,7 +3998,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.
|
||||
@@ -4029,7 +4014,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
|
||||
@@ -4167,7 +4152,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*.
|
||||
@@ -4233,7 +4218,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*.
|
||||
@@ -4374,7 +4359,7 @@ class APIRouter(routing.Router):
|
||||
),
|
||||
] = True,
|
||||
response_class: Annotated[
|
||||
Type[Response],
|
||||
type[Response],
|
||||
Doc(
|
||||
"""
|
||||
Response class to be used for this *path operation*.
|
||||
@@ -4395,7 +4380,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.
|
||||
@@ -4411,7 +4396,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
|
||||
|
||||
Reference in New Issue
Block a user