Overuse may indicate design issues; consider polymorphism
while isinstance(func, partial):
1import inspect2import sys3from collections.abc import Callable4from dataclasses import dataclass, field5from functools import cached_property, partial6from typing import Any, Literal78from fastapi._compat import ModelField9from fastapi.security.base import SecurityBase10from fastapi.types import DependencyCacheKey1112if sys.version_info >= (3, 13): # pragma: no cover13 from inspect import iscoroutinefunction14else: # pragma: no cover15 from asyncio import iscoroutinefunction161718def _unwrapped_call(call: Callable[..., Any] | None) -> Any:19 if call is None:20 return call # pragma: no cover21 unwrapped = inspect.unwrap(_impartial(call))22 return unwrapped232425def _impartial(func: Callable[..., Any]) -> Callable[..., Any]:26 while isinstance(func, partial):27 func = func.func28 return func293031@dataclass32class Dependant:33 path_params: list[ModelField] = field(default_factory=list)34 query_params: list[ModelField] = field(default_factory=list)35 header_params: list[ModelField] = field(default_factory=list)36 cookie_params: list[ModelField] = field(default_factory=list)37 body_params: list[ModelField] = field(default_factory=list)38 dependencies: list["Dependant"] = field(default_factory=list)39 name: str | None = None40 call: Callable[..., Any] | None = None41 request_param_name: str | None = None42 websocket_param_name: str | None = None43 http_connection_param_name: str | None = None44 response_param_name: str | None = None45 background_tasks_param_name: str | None = None46 security_scopes_param_name: str | None = None47 own_oauth_scopes: list[str] | None = None48 parent_oauth_scopes: list[str] | None = None49 use_cache: bool = True50 path: str | None = None51 scope: Literal["function", "request"] | None = None5253 @cached_property54 def oauth_scopes(self) -> list[str]:55 scopes = self.parent_oauth_scopes.copy() if self.parent_oauth_scopes else []56 # This doesn't use a set to preserve order, just in case57 for scope in self.own_oauth_scopes or []:58 if scope not in scopes:59 scopes.append(scope)60 return scopes6162 @cached_property63 def cache_key(self) -> DependencyCacheKey:64 scopes_for_cache = (65 tuple(sorted(set(self.oauth_scopes or []))) if self._uses_scopes else ()66 )67 return (68 self.call,69 scopes_for_cache,70 self.computed_scope or "",71 )7273 @cached_property74 def _uses_scopes(self) -> bool:75 if self.own_oauth_scopes:76 return True77 if self.security_scopes_param_name is not None:78 return True79 if self._is_security_scheme:80 return True81 for sub_dep in self.dependencies:82 if sub_dep._uses_scopes:83 return True84 return False8586 @cached_property87 def _is_security_scheme(self) -> bool:88 if self.call is None:89 return False # pragma: no cover90 unwrapped = _unwrapped_call(self.call)91 return isinstance(unwrapped, SecurityBase)9293 # Mainly to get the type of SecurityBase, but it's the same self.call94 @cached_property95 def _security_scheme(self) -> SecurityBase:96 unwrapped = _unwrapped_call(self.call)97 assert isinstance(unwrapped, SecurityBase)98 return unwrapped99100 @cached_property101 def _security_dependencies(self) -> list["Dependant"]:102 security_deps = [dep for dep in self.dependencies if dep._is_security_scheme]103 return security_deps104105 @cached_property106 def is_gen_callable(self) -> bool:107 if self.call is None:108 return False # pragma: no cover109 if inspect.isgeneratorfunction(110 _impartial(self.call)111 ) or inspect.isgeneratorfunction(_unwrapped_call(self.call)):112 return True113 if inspect.isclass(_unwrapped_call(self.call)):114 return False115 dunder_call = getattr(_impartial(self.call), "__call__", None) # noqa: B004116 if dunder_call is None:117 return False # pragma: no cover118 if inspect.isgeneratorfunction(119 _impartial(dunder_call)120 ) or inspect.isgeneratorfunction(_unwrapped_call(dunder_call)):121 return True122 dunder_unwrapped_call = getattr(_unwrapped_call(self.call), "__call__", None) # noqa: B004123 if dunder_unwrapped_call is None:124 return False # pragma: no cover125 if inspect.isgeneratorfunction(126 _impartial(dunder_unwrapped_call)127 ) or inspect.isgeneratorfunction(_unwrapped_call(dunder_unwrapped_call)):128 return True129 return False130131 @cached_property132 def is_async_gen_callable(self) -> bool:133 if self.call is None:134 return False # pragma: no cover135 if inspect.isasyncgenfunction(136 _impartial(self.call)137 ) or inspect.isasyncgenfunction(_unwrapped_call(self.call)):138 return True139 if inspect.isclass(_unwrapped_call(self.call)):140 return False141 dunder_call = getattr(_impartial(self.call), "__call__", None) # noqa: B004142 if dunder_call is None:143 return False # pragma: no cover144 if inspect.isasyncgenfunction(145 _impartial(dunder_call)146 ) or inspect.isasyncgenfunction(_unwrapped_call(dunder_call)):147 return True148 dunder_unwrapped_call = getattr(_unwrapped_call(self.call), "__call__", None) # noqa: B004149 if dunder_unwrapped_call is None:150 return False # pragma: no cover151 if inspect.isasyncgenfunction(152 _impartial(dunder_unwrapped_call)153 ) or inspect.isasyncgenfunction(_unwrapped_call(dunder_unwrapped_call)):154 return True155 return False156157 @cached_property158 def is_coroutine_callable(self) -> bool:159 if self.call is None:160 return False # pragma: no cover161 if inspect.isroutine(_impartial(self.call)) and iscoroutinefunction(162 _impartial(self.call)163 ):164 return True165 if inspect.isroutine(_unwrapped_call(self.call)) and iscoroutinefunction(166 _unwrapped_call(self.call)167 ):168 return True169 if inspect.isclass(_unwrapped_call(self.call)):170 return False171 dunder_call = getattr(_impartial(self.call), "__call__", None) # noqa: B004172 if dunder_call is None:173 return False # pragma: no cover174 if iscoroutinefunction(_impartial(dunder_call)) or iscoroutinefunction(175 _unwrapped_call(dunder_call)176 ):177 return True178 dunder_unwrapped_call = getattr(_unwrapped_call(self.call), "__call__", None) # noqa: B004179 if dunder_unwrapped_call is None:180 return False # pragma: no cover181 if iscoroutinefunction(182 _impartial(dunder_unwrapped_call)183 ) or iscoroutinefunction(_unwrapped_call(dunder_unwrapped_call)):184 return True185 return False186187 @cached_property188 def computed_scope(self) -> str | None:189 if self.scope:190 return self.scope191 if self.is_gen_callable or self.is_async_gen_callable:192 return "request"193 return None
Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.