From eb5b08b83d3bc8dd34f42d695e86f936b35800dd Mon Sep 17 00:00:00 2001 From: Evgeny Bokshitsky Date: Sun, 28 Dec 2025 01:21:44 +0400 Subject: [PATCH 1/2] add typing for dependency_overrides_provider --- fastapi/dependencies/utils.py | 8 +++----- fastapi/routing.py | 12 ++++++------ fastapi/types.py | 5 ++++- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/fastapi/dependencies/utils.py b/fastapi/dependencies/utils.py index 45e1ff3ed1..cee9a5ffa4 100644 --- a/fastapi/dependencies/utils.py +++ b/fastapi/dependencies/utils.py @@ -49,7 +49,7 @@ from fastapi.dependencies.models import Dependant from fastapi.exceptions import DependencyScopeError from fastapi.logger import logger from fastapi.security.oauth2 import SecurityScopes -from fastapi.types import DependencyCacheKey +from fastapi.types import DependencyCacheKey, DependencyOverridesProvider from fastapi.utils import create_model_field, get_path_param_names from pydantic import BaseModel from pydantic.fields import FieldInfo @@ -567,7 +567,7 @@ async def solve_dependencies( body: Optional[Union[dict[str, Any], FormData]] = None, background_tasks: Optional[StarletteBackgroundTasks] = None, response: Optional[Response] = None, - dependency_overrides_provider: Optional[Any] = None, + dependency_overrides_provider: Optional[DependencyOverridesProvider] = 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) @@ -599,9 +599,7 @@ async def solve_dependencies( and dependency_overrides_provider.dependency_overrides ): original_call = sub_dependant.call - call = getattr( - dependency_overrides_provider, "dependency_overrides", {} - ).get(original_call, original_call) + call = dependency_overrides_provider.dependency_overrides.get(original_call, original_call) use_path: str = sub_dependant.path # type: ignore use_sub_dependant = get_dependant( path=use_path, diff --git a/fastapi/routing.py b/fastapi/routing.py index 9ca2f46732..d70e804ccb 100644 --- a/fastapi/routing.py +++ b/fastapi/routing.py @@ -48,7 +48,7 @@ from fastapi.exceptions import ( ResponseValidationError, WebSocketRequestValidationError, ) -from fastapi.types import DecoratedCallable, IncEx +from fastapi.types import DecoratedCallable, IncEx, DependencyOverridesProvider from fastapi.utils import ( create_cloned_field, create_model_field, @@ -257,7 +257,7 @@ def get_request_handler( response_model_exclude_unset: bool = False, response_model_exclude_defaults: bool = False, response_model_exclude_none: bool = False, - dependency_overrides_provider: Optional[Any] = None, + dependency_overrides_provider: Optional[DependencyOverridesProvider] = None, embed_body_fields: bool = False, ) -> Callable[[Request], Coroutine[Any, Any, Response]]: assert dependant.call is not None, "dependant.call must be a function" @@ -405,7 +405,7 @@ def get_request_handler( def get_websocket_app( dependant: Dependant, - dependency_overrides_provider: Optional[Any] = None, + dependency_overrides_provider: Optional[DependencyOverridesProvider] = None, embed_body_fields: bool = False, ) -> Callable[[WebSocket], Coroutine[Any, Any, Any]]: async def app(websocket: WebSocket) -> None: @@ -448,7 +448,7 @@ class APIWebSocketRoute(routing.WebSocketRoute): *, name: Optional[str] = None, dependencies: Optional[Sequence[params.Depends]] = None, - dependency_overrides_provider: Optional[Any] = None, + dependency_overrides_provider: Optional[DependencyOverridesProvider] = None, ) -> None: self.path = path self.endpoint = endpoint @@ -510,7 +510,7 @@ class APIRoute(routing.Route): response_class: Union[type[Response], DefaultPlaceholder] = Default( JSONResponse ), - dependency_overrides_provider: Optional[Any] = None, + dependency_overrides_provider: Optional[DependencyOverridesProvider] = None, callbacks: Optional[list[BaseRoute]] = None, openapi_extra: Optional[dict[str, Any]] = None, generate_unique_id_function: Union[ @@ -800,7 +800,7 @@ class APIRouter(routing.Router): ), ] = None, dependency_overrides_provider: Annotated[ - Optional[Any], + Optional[DependencyOverridesProvider], Doc( """ Only used internally by FastAPI to handle dependency overrides. diff --git a/fastapi/types.py b/fastapi/types.py index d3e980cb43..62667c7823 100644 --- a/fastapi/types.py +++ b/fastapi/types.py @@ -1,6 +1,6 @@ import types from enum import Enum -from typing import Any, Callable, Optional, TypeVar, Union +from typing import Any, Callable, Optional, TypeVar, Union, Protocol from pydantic import BaseModel @@ -9,3 +9,6 @@ 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] + +class DependencyOverridesProvider(Protocol): + dependency_overrides: dict[Callable[..., Any], Any] From e6f75eb9cd50ac278f111fecee27d65490f91046 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci-lite[bot]" <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Date: Sat, 27 Dec 2025 21:26:25 +0000 Subject: [PATCH 2/2] =?UTF-8?q?=F0=9F=8E=A8=20Auto=20format?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fastapi/dependencies/utils.py | 4 +++- fastapi/routing.py | 2 +- fastapi/types.py | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/fastapi/dependencies/utils.py b/fastapi/dependencies/utils.py index cee9a5ffa4..2d84fd3bb4 100644 --- a/fastapi/dependencies/utils.py +++ b/fastapi/dependencies/utils.py @@ -599,7 +599,9 @@ async def solve_dependencies( and dependency_overrides_provider.dependency_overrides ): original_call = sub_dependant.call - call = dependency_overrides_provider.dependency_overrides.get(original_call, original_call) + call = dependency_overrides_provider.dependency_overrides.get( + original_call, original_call + ) use_path: str = sub_dependant.path # type: ignore use_sub_dependant = get_dependant( path=use_path, diff --git a/fastapi/routing.py b/fastapi/routing.py index d70e804ccb..c39f95154d 100644 --- a/fastapi/routing.py +++ b/fastapi/routing.py @@ -48,7 +48,7 @@ from fastapi.exceptions import ( ResponseValidationError, WebSocketRequestValidationError, ) -from fastapi.types import DecoratedCallable, IncEx, DependencyOverridesProvider +from fastapi.types import DecoratedCallable, DependencyOverridesProvider, IncEx from fastapi.utils import ( create_cloned_field, create_model_field, diff --git a/fastapi/types.py b/fastapi/types.py index 62667c7823..465861616e 100644 --- a/fastapi/types.py +++ b/fastapi/types.py @@ -1,6 +1,6 @@ import types from enum import Enum -from typing import Any, Callable, Optional, TypeVar, Union, Protocol +from typing import Any, Callable, Optional, Protocol, TypeVar, Union from pydantic import BaseModel @@ -10,5 +10,6 @@ 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] + class DependencyOverridesProvider(Protocol): dependency_overrides: dict[Callable[..., Any], Any]