While manipulating coroutines, I came across AwaitableGenerator. Everything was going well until I noticed it had four type parameters. So, I checked the code.
Apparently, they have an additional type variable _S, which, to me, makes no sense since it's not used in the protocol.
So, I want to know if this feature is intentional and if it has any use.
If not, I think it's appropriate to follow the Generator[YieldT, SendT, ReturnT] structure because it is a generator but it supports await.
AwaitableGenerator should probably not exist in typeshed. It's a holdover from when mypy and typeshed were tightly coupled. Cf. python/mypy#8699 and python/mypy#8240.
Reacted by Brian Schubert, Jelle Zijlstra and Alan Bogarin
I have a proposal for typing generator-based coroutines.
When using yield from with a types.CoroutineType, replace AwaitableGenerator with Generator.
This is consistent with its runtime type types.GeneratorType, prevents using await if it is not decorated with @types.coroutine, and Generator has existed since v3.5.
Some drawbacks:
Extending linters’ functionality to determine the types involved in a coroutine for yield from.
from __future__ importannotationsimporttypesimportasynciofromcollections.abcimportGeneratorfromtypingimportAny@types.coroutinedefgenerator_a(): # () -> Generator[None, Any, None]yieldNone# @types.coroutinedefgenerator_b() ->Generator[Any, Any, None]:
yieldfromasyncio.sleep(1) # type: ignore[misc]# () -> AwaitableGenerator[Any, Any, None, Any]defgenerator_c():
yieldfromasyncio.sleep(1)
asyncdeftest_awaitable() ->None:
awaitgenerator_a() # okawaitgenerator_b() # TypeError! without @coroutineawaitgenerator_c() # bad: no @coroutine mark
Taking advantage of the topic: inspect can detect these objects marked with @types.coroutine via inspect.isawaitable, but it lacks an introspection function specifically for them.
Activity
brianschubert commented on Apr 7, 2025
I don't know the background, but mypy makes use of this, e.g. here https://github.com/python/mypy/blob/749f2584da9425173d68eb220db7e92aa13ad8ea/mypy/checkexpr.py#L6361-L6382
So I would say it's intentional :)
srittau commented on Apr 7, 2025
AwaitableGenerator should probably not exist in typeshed. It's a holdover from when mypy and typeshed were tightly coupled. Cf. python/mypy#8699 and python/mypy#8240.
AlanBogarin commented on Apr 9, 2025
I have a proposal for typing generator-based coroutines.
When using yield from with a types.CoroutineType, replace AwaitableGenerator with Generator.
This is consistent with its runtime type types.GeneratorType, prevents using await if it is not decorated with @types.coroutine, and Generator has existed since v3.5.
Some drawbacks:
Extending linters’ functionality to determine the types involved in a coroutine for yield from.
Taking advantage of the topic: inspect can detect these objects marked with @types.coroutine via inspect.isawaitable, but it lacks an introspection function specifically for them.