Thanks for the thorough rundown, Nathaniel. I started to get an idea of the required shape only by looking at CPython code like you suggest. I wanted to create an awaitable compatible with asyncio and trio that could be awaited more than once unlike a coroutine, and not runner-specific like a Future or Deferred. Are coroutines the only common awaitable the various async libraries are going to have for now?
I'll take Python documentation suggestions up with other channels. - Justin On Wed, Nov 7, 2018 at 11:27 PM Nathaniel Smith <n...@pobox.com> wrote: > "Awaitable" is a language-level concept. To actually use awaitables, > you also need a coroutine runner library, and each library defines > additional restrictions on the awaitables it works with. So e.g. when > using asyncio as your coroutine runner, asyncio expects your > awaitables to follow particular rules about what values they yield, > what kinds of values they can handle being sent/thrown back in, etc. > Different async libraries use different rules here. > > Asyncio's rules aren't documented, I guess because it's such a > low-level thing that anyone who really needs to know is expected to > read the source :-). (In particular asyncio/futures.py and > asyncio/tasks.py.) But it's basically: the object returned by > __await__ has to implement the generator interface (which is a > superset of the iterator interface), the objects yielded by your > iterator have to implement the Future interface, and then you're > resumed either by sending back None when the Future completes, or else > by having an exception thrown in. > > -n > > On Wed, Nov 7, 2018 at 8:24 PM, Justin Turner Arthur > <justinart...@gmail.com> wrote: > > I'm trying to figure out if our documentation on the new awaitable > concept > > in Python 3.6+ is correct. It seems to imply that if an object's > __await__ > > method returns an iterator, the object is awaitable. However, just > returning > > an iterator doesn't seem to work with await in a coroutine or with the > > asyncio selector loop's run_until_complete method. > > > > If the awaitable is not a coroutine or future, it looks like we wrap it > in a > > coroutine using sub-generator delegation, and therefore have to have an > > iterator that fits a very specific shape for the coroutine step process > that > > isn't documented anywhere I could find. Am I missing something? > > > > If the definition of an awaitable is more than just an __await__ > iterator, > > we may need to expand the documentation as well as the abstract base > class. > > > > Here's what I tried in making a synchronous awaitable that resolves to > the > > int 42: > > class MyAwaitable(Awaitable): > > def __await__(self): > > return iter((42,)) > > # RuntimeError: Task got bad yield: 42 > > > > class MyAwaitable(Awaitable): > > def __await__(self): > > yield 42 > > # RuntimeError: Task got bad yield: 42 > > > > class MyAwaitable(Awaitable): > > def __await__(self): > > return (i for i in (42,)) > > # RuntimeError: Task got bad yield: 42 > > > > class MyAwaitable(Awaitable): > > def __await__(self): > > return self > > def __next__(self): > > return 42 > > # RuntimeError: Task got bad yield: 42''' > > > > class MyAwaitable(Awaitable): > > def __await__(self): > > return iter(asyncio.coroutine(lambda: 42)()) > > # TypeError: __await__() returned a coroutine > > > > class MyAwaitable(Awaitable): > > def __await__(self): > > yield from asyncio.coroutine(lambda: 42)() > > # None > > > > class MyAwaitable(Awaitable): > > def __await__(self): > > return (yield from asyncio.coroutine(lambda: 42)()) > > # 42 > > > > async def await_things(): > > print(await MyAwaitable()) > > > > asyncio.get_event_loop().run_until_complete(await_things()) > > > > > > _______________________________________________ > > Python-Dev mailing list > > Python-Dev@python.org > > https://mail.python.org/mailman/listinfo/python-dev > > Unsubscribe: > > https://mail.python.org/mailman/options/python-dev/njs%40pobox.com > > > > > > -- > Nathaniel J. Smith -- https://vorpus.org >
_______________________________________________ Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com