From 09c871dac863c2c38db30ff509d220b1da4da5f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 4 Dec 2025 01:30:43 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20Fix=20Dependant=20logic=20to=20a?= =?UTF-8?q?ccount=20for=20callable=20class=20instances=20wrapped?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fastapi/dependencies/models.py | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/fastapi/dependencies/models.py b/fastapi/dependencies/models.py index 1a65766ef..9b545e4e5 100644 --- a/fastapi/dependencies/models.py +++ b/fastapi/dependencies/models.py @@ -99,9 +99,18 @@ class Dependant: dunder_call = getattr(_impartial(self.call), "__call__", None) # noqa: B004 if dunder_call is None: return False # pragma: no cover - return inspect.isgeneratorfunction( + if inspect.isgeneratorfunction( _impartial(dunder_call) - ) or inspect.isgeneratorfunction(_unwrapped_call(dunder_call)) + ) or inspect.isgeneratorfunction(_unwrapped_call(dunder_call)): + return True + dunder_unwrapped_call = getattr(_unwrapped_call(self.call), "__call__", None) # noqa: B004 + if dunder_unwrapped_call is None: + return False # pragma: no cover + if inspect.isgeneratorfunction( + _impartial(dunder_unwrapped_call) + ) or inspect.isgeneratorfunction(_unwrapped_call(dunder_unwrapped_call)): + return True + return False @cached_property def is_async_gen_callable(self) -> bool: @@ -114,9 +123,18 @@ class Dependant: dunder_call = getattr(_impartial(self.call), "__call__", None) # noqa: B004 if dunder_call is None: return False # pragma: no cover - return inspect.isasyncgenfunction( + if inspect.isasyncgenfunction( _impartial(dunder_call) - ) or inspect.isasyncgenfunction(_unwrapped_call(dunder_call)) + ) or inspect.isasyncgenfunction(_unwrapped_call(dunder_call)): + return True + dunder_unwrapped_call = getattr(_unwrapped_call(self.call), "__call__", None) # noqa: B004 + if dunder_unwrapped_call is None: + return False # pragma: no cover + if inspect.isasyncgenfunction( + _impartial(dunder_unwrapped_call) + ) or inspect.isasyncgenfunction(_unwrapped_call(dunder_unwrapped_call)): + return True + return False @cached_property def is_coroutine_callable(self) -> bool: @@ -137,6 +155,13 @@ class Dependant: _unwrapped_call(dunder_call) ): return True + dunder_unwrapped_call = getattr(_unwrapped_call(self.call), "__call__", None) # noqa: B004 + if dunder_unwrapped_call is None: + return False # pragma: no cover + if iscoroutinefunction( + _impartial(dunder_unwrapped_call) + ) or iscoroutinefunction(_unwrapped_call(dunder_unwrapped_call)): + return True # if inspect.isclass(self.call): False, covered by default return return False