← pod_r2_v1e

fastapi_14458

resolved RESOLVED UNSUBMITTED PASS · 13 tool calls · 0 s · fastapi/fastapi

Task input

🐛 Fix using class (not instance) dependency that has `__call__` method

As reported in https://github.com/fastapi/fastapi/discussions/14452, FastAPI 0.123.6 introduced a regression - if we use class (not instance) as dependency and this class has `__call__` method that is coroutine or generator, it is mistakenly treated as coroutine\generator (actually class is not coroutine\generator, instance of this class is).


So, to fix this we need to check if the callable is class before inspecting its `dunder_call` in `is_coroutine_callable`, `is_async_gen_callable`, and `is_gen_callable`.

Tool calls (0)

#ToolArgumentsResult
No trace captured.

Patch

diff --git a/fastapi/dependencies/models.py b/fastapi/dependencies/models.py
index af168a17..cd0a5391 100644
--- a/fastapi/dependencies/models.py
+++ b/fastapi/dependencies/models.py
@@ -111,7 +111,7 @@ class Dependant:
         ) or inspect.isgeneratorfunction(_unwrapped_call(self.call)):
             return True
         dunder_call = getattr(_impartial(self.call), "__call__", None)  # noqa: B004
-        if dunder_call is None:
+        if dunder_call is None or inspect.isclass(self.call):
             return False  # pragma: no cover
         if inspect.isgeneratorfunction(
             _impartial(dunder_call)
@@ -135,7 +135,7 @@ class Dependant:
         ) or inspect.isasyncgenfunction(_unwrapped_call(self.call)):
             return True
         dunder_call = getattr(_impartial(self.call), "__call__", None)  # noqa: B004
-        if dunder_call is None:
+        if dunder_call is None or inspect.isclass(self.call):
             return False  # pragma: no cover
         if inspect.isasyncgenfunction(
             _impartial(dunder_call)
@@ -163,7 +163,7 @@ class Dependant:
         ):
             return True
         dunder_call = getattr(_impartial(self.call), "__call__", None)  # noqa: B004
-        if dunder_call is None:
+        if dunder_call is None or inspect.isclass(self.call):
             return False  # pragma: no cover
         if iscoroutinefunction(_impartial(dunder_call)) or iscoroutinefunction(
             _unwrapped_call(dunder_call)

Test output

show
............                                                             [100%]
=============================== warnings summary ===============================
../../../../../../../Users/jp/repos/kaggle-gemini-coding-agent-post-training/.envs/overlays/starlette-0.50.0-py3-none-any/starlette/testclient.py:45
  /Users/jp/repos/kaggle-gemini-coding-agent-post-training/.envs/overlays/starlette-0.50.0-py3-none-any/starlette/testclient.py:45: DeprecationWarning: The anyio.abc.BlockingPortal alias is deprecated, use anyio.from_thread.BlockingPortal instead.
    _PortalFactoryType = Callable[[], AbstractContextManager[anyio.abc.BlockingPortal]]

-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
12 passed, 1 warning in 0.46s