I have the following use-case of a class that takes a regular function or a coroutine as an attribute, and then provides access to it through two properties. Basically the code looks like this:
"""example.py"""
from asyncio import iscoroutinefunction
from typing import TypeVar, Generic, Callable, Awaitable, Any
T = TypeVar('T')
class Response(Generic[T]):
...
class Request(Generic[T]):
...
class Foo:
def __init__(self, callback: Callable[[Request[T]], Response[T] | Awaitable[Response[T]]]):
self._callback = callback
@property
def func(self) -> Callable[[Request[T]], Response[T]]:
if iscoroutinefunction(self._callback):
raise AttributeError()
return self._callback
@property
def coro(self) -> Callable[[Request[T]], Awaitable[Response[T]]:
if not iscoroutinefunction(self._callback):
raise AttributeError()
return self._callback
async def bar(req: Request[T]) -> Response[T]:
...
foo = Foo(bar)
Now, I expected mypy to give no errors due to type narrowing from `iscoroutinefunction, but instead I get
example.py:21: error: Incompatible return value type (got "Callable[[Request[T]], Union[Response[T], Awaitable[Response[T]]]]", expected "Callable[[Request[T]], Response[T]]")
example.py:28: error: Incompatible return value type (got "Callable[[Request[T]], Union[Response[T], Awaitable[Response[T]]]]", expected "Callable[[Request[T]], Awaitable[Response[T]]]")
After finding this, I started searching through the issues in both mypy and typeshed but couldn't find anything related to iscoroutinefunction. I then looked into typeshed and saw that the return type of iscoroutinefunction is just bool, and not a TypeGuard, despite the similar iscoroutine having one. This makes me think that iscoroutinefunction is annotated like that on purpose.
So my question is, should the return type of asyncio.iscoroutinefunction be a TypeGuard of some kind?
I'm new to the more advanced features of Python typing, and my naive implementation would be something like
from typing import TypeVar, TypeGuard
T = TypeVar('T')
def iscoroutinefunction(func: T) -> TypeGuard[T]: ...
If you feel like this should be changed, I'd be happy to submit a PR once I know what the type should be.
I have the following use-case of a class that takes a regular function or a coroutine as an attribute, and then provides access to it through two properties. Basically the code looks like this:
Now, I expected mypy to give no errors due to type narrowing from `iscoroutinefunction, but instead I get
After finding this, I started searching through the issues in both mypy and typeshed but couldn't find anything related to
iscoroutinefunction. I then looked into typeshed and saw that the return type ofiscoroutinefunctionis justbool, and not aTypeGuard, despite the similariscoroutinehaving one. This makes me think thatiscoroutinefunctionis annotated like that on purpose.So my question is, should the return type of
asyncio.iscoroutinefunctionbe aTypeGuardof some kind?I'm new to the more advanced features of Python typing, and my naive implementation would be something like
If you feel like this should be changed, I'd be happy to submit a PR once I know what the type should be.