Repository: tiangolo/fastapi
File: fastapi/dependencies/models.py (Python)

Code before:
        if isinstance(self.call, partial):
            use_call = self.call.func
        if inspect.isgeneratorfunction(use_call):
            return True
        dunder_call = getattr(use_call, "__call__", None)  # noqa: B004
        return inspect.isgeneratorfunction(dunder_call)

    @cached_property
    def is_async_gen_callable(self) -> bool:
        use_call: Any = self.call
        if isinstance(self.call, partial):
            use_call = self.call.func
        if inspect.isasyncgenfunction(use_call):
            return True
        dunder_call = getattr(use_call, "__call__", None)  # noqa: B004
        return inspect.isasyncgenfunction(dunder_call)

    @cached_property
    def is_coroutine_callable(self) -> bool:
        use_call: Any = self.call
        if isinstance(self.call, partial):
            use_call = self.call.func
        if inspect.isroutine(use_call):
            return iscoroutinefunction(use_call)
        if inspect.isclass(use_call):
            return False
        dunder_call = getattr(use_call, "__call__", None)  # noqa: B004
        return iscoroutinefunction(dunder_call)

    @cached_property
    def computed_scope(self) -> Union[str, None]:
        if self.scope:
            return self.scope
        if self.is_gen_callable or self.is_async_gen_callable:
            return "request"
        return None


Review comment (refactor):
In the initial version of this PR it was suggested to change these lines to something like:
```diff
-        if inspect.isroutine(use_call):
-            return inspect.iscoroutinefunction(use_call)
+        if inspect.iscoroutinefunction(use_call):
+            return True
-        if inspect.isclass(use_call):
-            return False
```

See original commit: https://github.com/fastapi/fastapi/pull/9753/commits/f16dd38b478c0a88ae4ae79fd73094fdb3ffa425

I updated it to be closer to current implementation (don't simplify first condition and don't remove `if inspect.isclass(use_call):`)

Code after:
    def cache_key(self) -> DependencyCacheKey:
        scopes_for_cache = (
            tuple(sorted(set(self.oauth_scopes or []))) if self._uses_scopes else ()
        )
        return (
            self.call,
            scopes_for_cache,
            self.computed_scope or "",
        )

    @cached_property
    def _uses_scopes(self) -> bool:
        if self.own_oauth_scopes:
            return True
        if self.security_scopes_param_name is not None:
            return True
        for sub_dep in self.dependencies:
            if sub_dep._uses_scopes:
                return True
        return False

    @cached_property
    def _unwrapped_call(self) -> Any:
        if self.call is None:
            return self.call  # pragma: no cover
        unwrapped = inspect.unwrap(self.call)
        if isinstance(unwrapped, partial):
            unwrapped = unwrapped.func
        return unwrapped

    @cached_property
    def is_gen_callable(self) -> bool:
        if inspect.isgeneratorfunction(self._unwrapped_call):
            return True
        dunder_call = getattr(self._unwrapped_call, "__call__", None)  # noqa: B004
        return inspect.isgeneratorfunction(dunder_call)

    @cached_property
    def is_async_gen_callable(self) -> bool:
        if inspect.isasyncgenfunction(self._unwrapped_call):
            return True
        dunder_call = getattr(self._unwrapped_call, "__call__", None)  # noqa: B004
        return inspect.isasyncgenfunction(dunder_call)

    @cached_property
    def is_coroutine_callable(self) -> bool:
        if inspect.isroutine(self._unwrapped_call):
            return iscoroutinefunction(self._unwrapped_call)
        if inspect.isclass(self._unwrapped_call):
            return False
        dunder_call = getattr(self._unwrapped_call, "__call__", None)  # noqa: B004