py/compile: Don't await __aiter__ special method in async-for.
MicroPython's original implementation of __aiter__ was correct for an earlier (provisional) version of PEP492 (CPython 3.5), where __aiter__ was an async-def function. But that changed in the final version of PEP492 (in CPython 3.5.2) where the function was changed to a normal one. See https://www.python.org/dev/peps/pep-0492/#why-aiter-does-not-return-an-awaitable See also the note at the end of this subsection in the docs: https://docs.python.org/3.5/reference/datamodel.html#asynchronous-iterators And for completeness the BPO: https://bugs.python.org/issue27243 To be consistent with the Python spec as it stands today (and now that PEP492 is final) this commit changes MicroPython's behaviour to match CPython: __aiter__ should return an async-iterable object, but is not itself awaitable. The relevant tests are updated to match. See #6267.
This commit is contained in:
parent
a6e048686f
commit
901f3dce6e
|
@ -1741,7 +1741,8 @@ STATIC void compile_async_for_stmt(compiler_t *comp, mp_parse_node_struct_t *pns
|
||||||
uint try_finally_label = comp_next_label(comp);
|
uint try_finally_label = comp_next_label(comp);
|
||||||
|
|
||||||
compile_node(comp, pns->nodes[1]); // iterator
|
compile_node(comp, pns->nodes[1]); // iterator
|
||||||
compile_await_object_method(comp, MP_QSTR___aiter__);
|
EMIT_ARG(load_method, MP_QSTR___aiter__, false);
|
||||||
|
EMIT_ARG(call_method, 0, 0, 0);
|
||||||
compile_store_id(comp, context);
|
compile_store_id(comp, context);
|
||||||
|
|
||||||
START_BREAK_CONTINUE_BLOCK
|
START_BREAK_CONTINUE_BLOCK
|
||||||
|
|
|
@ -6,7 +6,7 @@ class AsyncIteratorWrapper:
|
||||||
print('init')
|
print('init')
|
||||||
self._it = iter(obj)
|
self._it = iter(obj)
|
||||||
|
|
||||||
async def __aiter__(self):
|
def __aiter__(self):
|
||||||
print('aiter')
|
print('aiter')
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# test waiting within "async for" aiter/anext functions
|
# test waiting within "async for" __anext__ function
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
if sys.implementation.name in ('micropython', 'circuitpython'):
|
if sys.implementation.name in ('micropython', 'circuitpython'):
|
||||||
|
@ -21,9 +21,8 @@ class ARange:
|
||||||
self.cur = 0
|
self.cur = 0
|
||||||
self.high = high
|
self.high = high
|
||||||
|
|
||||||
async def __aiter__(self):
|
def __aiter__(self):
|
||||||
print('aiter')
|
print('aiter')
|
||||||
print('f returned:', await f(10))
|
|
||||||
return self
|
return self
|
||||||
|
|
||||||
async def __anext__(self):
|
async def __anext__(self):
|
||||||
|
|
|
@ -1,9 +1,5 @@
|
||||||
init
|
init
|
||||||
aiter
|
aiter
|
||||||
f start: 10
|
|
||||||
coro yielded: 11
|
|
||||||
coro yielded: 12
|
|
||||||
f returned: 13
|
|
||||||
anext
|
anext
|
||||||
f start: 20
|
f start: 20
|
||||||
coro yielded: 21
|
coro yielded: 21
|
||||||
|
|
Loading…
Reference in New Issue