New submission from Yury Selivanov:

There is a small flaw in PEP 492 design -- __aiter__ should not return an 
awaitable object that resolves to an asynchronous iterator. It should return an 
asynchronous iterator directly.

Let me explain this by showing some examples.

I've discovered this while working on a new asynchronous generators PEP.  Let's 
pretend that we have them already: if we have a 'yield' expression in an 'async 
def' function, the function becomes an "asynchronous generator function":

   async def foo():
      await bar()
      yield 1
      await baz()
      yield 2

   # foo -- is an `asynchronous generator function`
   # foo() -- is an `asynchronous generator`

If we iterate through "foo()", it will await on "bar()", yield "1", await on 
"baz()", and yield "2":

   >>> async for el in foo():
   ...     print(el)
   1
   2

If we decide to have a class with an __aiter__ that is an async generator, we'd 
write something like this:

   class Foo:
      async def __aiter__(self):
          await bar()
          yield 1
          await baz()
          yield 2

However, with the current PEP 492 design, the above code would be invalid!  The 
interpreter expects __aiter__ to return a coroutine, not an async generator.

I'm still working on the PEP for async generators, targeting CPython 3.6.  And 
once it is ready, it might still be rejected or deferred.  But in any case, 
this PEP 492 flaw has to be fixed now, in 3.5.2 (since PEP 492 is provisional).

The attached patch fixes the __aiter__ in a backwards compatible way:

1. ceval/GET_AITER opcode calls the __aiter__ method.

2. If the returned object has an '__anext__' method, GET_AITER silently wraps 
it in an awaitable, which is equivalent to the following coroutine:

    async def wrapper(aiter_result):
        return aiter_result

3. If the returned object does not have an '__anext__' method, a 
DeprecationWarning is raised.

----------
assignee: yselivanov
components: Interpreter Core
files: fix_aiter.patch
keywords: patch
messages: 267544
nosy: brett.cannon, gvanrossum, haypo, lukasz.langa, ncoghlan, yselivanov
priority: release blocker
severity: normal
status: open
title: __aiter__ should return async iterator instead of awaitable
versions: Python 3.5, Python 3.6
Added file: http://bugs.python.org/file43264/fix_aiter.patch

_______________________________________
Python tracker <rep...@bugs.python.org>
<http://bugs.python.org/issue27243>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to