Description
I'm trying something new here, pouring my thoughts into the issue tracker to get some clarity.
I hope that we'll soon have syntactic support for PEP 492, in particular async def
and await
(#1808). (Yes, it also supports async for
and async with
, but these aren't very interesting so I won't mention them.)
I've also made some improvements to the asyncio stubs (python/typeshed#373, merged already) and created a fully annotated example, crawl.py (#1878). But these do not use async def
or await
; they use generators annotated with @asyncio.coroutine
and yield from
to wait for coroutines and Futures.
The next step is supporting asyncio code that uses async def
and await
, and here I am a little stuck. On the one hand, PEP 492 draws a clear distinction between generators and native coroutines (the latter being the ones defined using async def
). You can't use a generator with await
, and you can't use a native coroutine with yield from
. On the other hand, PEP 492 also allows an escape clause: by using the decorator @types.coroutine
you can mark a generator as a coroutine, and then await
accepts it. The @asyncio.coroutine
decorator calls this decorator, in addition to doing other asyncio-specific things (some of which are only apparent in debug mode).
I would like mypy to model all this as well as possible, so that mypy will give a useful error message when you try to use a generator with await
or a coroutine with yield from
. But it should also understand that a generator decorated with @types.coroutine
or @asyncio.coroutine
is acceptable for await
as well as for yield from
(in the latter case it would be even better if it could also keep track of whether the generator containing the yield from
is decorated with @asyncio.coroutine
).
The final piece of the puzzle (or rather, contribution to the problem) is that it's not easy to specify the type for a decorator that modifies the signature of the function it wraps. What I wish I could do is to declare that the @asyncio.coroutine
decorator takes a function with arguments AA
and return type Generator[Any, Any, R]
and returns a function with arguments AA
and return type Awaitable[R]
(which is what await
requires -- the return value of await
is then of type R
). And I'd like the decorator to be overloaded so that it also handles a few other cases.
But neither PEP 484 nor mypy supports this "signature algebra", so the best I can think of is to special-case the two decorators (@types.coroutine
and @asyncio.coroutine
) in mypy, in a similar fashion as how it deals with some other built-in decorators (@property
, @classmethod
and probably a few more).
[To be continued]