bpo-31708: Allow async generator expressions in synchronous functions (#3905)
This commit is contained in:
parent
faa135acbf
commit
b8ab9d3fc8
@ -326,14 +326,16 @@ range(10) for y in bar(x))``.
|
|||||||
The parentheses can be omitted on calls with only one argument. See section
|
The parentheses can be omitted on calls with only one argument. See section
|
||||||
:ref:`calls` for details.
|
:ref:`calls` for details.
|
||||||
|
|
||||||
Since Python 3.6, if the generator appears in an :keyword:`async def` function,
|
If a generator expression contains either :keyword:`async for`
|
||||||
then :keyword:`async for` clauses and :keyword:`await` expressions are permitted
|
clauses or :keyword:`await` expressions it is called an
|
||||||
as with an asynchronous comprehension. If a generator expression
|
:dfn:`asynchronous generator expression`. An asynchronous generator
|
||||||
contains either :keyword:`async for` clauses or :keyword:`await` expressions
|
expression returns a new asynchronous generator object,
|
||||||
it is called an :dfn:`asynchronous generator expression`.
|
which is an asynchronous iterator (see :ref:`async-iterators`).
|
||||||
An asynchronous generator expression yields a new asynchronous
|
|
||||||
generator object, which is an asynchronous iterator
|
.. versionchanged:: 3.7
|
||||||
(see :ref:`async-iterators`).
|
Prior to Python 3.7, asynchronous generator expressions could
|
||||||
|
only appear in :keyword:`async def` coroutines. Starting
|
||||||
|
with 3.7, any function can use asynchronous generator expressions.
|
||||||
|
|
||||||
.. _yieldexpr:
|
.. _yieldexpr:
|
||||||
|
|
||||||
|
@ -1037,5 +1037,37 @@ class AsyncGenAsyncioTest(unittest.TestCase):
|
|||||||
t.cancel()
|
t.cancel()
|
||||||
self.loop.run_until_complete(asyncio.sleep(0.1, loop=self.loop))
|
self.loop.run_until_complete(asyncio.sleep(0.1, loop=self.loop))
|
||||||
|
|
||||||
|
def test_async_gen_expression_01(self):
|
||||||
|
async def arange(n):
|
||||||
|
for i in range(n):
|
||||||
|
await asyncio.sleep(0.01, loop=self.loop)
|
||||||
|
yield i
|
||||||
|
|
||||||
|
def make_arange(n):
|
||||||
|
# This syntax is legal starting with Python 3.7
|
||||||
|
return (i * 2 async for i in arange(n))
|
||||||
|
|
||||||
|
async def run():
|
||||||
|
return [i async for i in make_arange(10)]
|
||||||
|
|
||||||
|
res = self.loop.run_until_complete(run())
|
||||||
|
self.assertEqual(res, [i * 2 for i in range(10)])
|
||||||
|
|
||||||
|
def test_async_gen_expression_02(self):
|
||||||
|
async def wrap(n):
|
||||||
|
await asyncio.sleep(0.01, loop=self.loop)
|
||||||
|
return n
|
||||||
|
|
||||||
|
def make_arange(n):
|
||||||
|
# This syntax is legal starting with Python 3.7
|
||||||
|
return (i * 2 for i in range(n) if await wrap(i))
|
||||||
|
|
||||||
|
async def run():
|
||||||
|
return [i async for i in make_arange(10)]
|
||||||
|
|
||||||
|
res = self.loop.run_until_complete(run())
|
||||||
|
self.assertEqual(res, [i * 2 for i in range(1, 10)])
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
@ -149,6 +149,14 @@ class AsyncBadSyntaxTest(unittest.TestCase):
|
|||||||
[i async for i in els]
|
[i async for i in els]
|
||||||
""",
|
""",
|
||||||
|
|
||||||
|
"""def bar():
|
||||||
|
{i: i async for i in els}
|
||||||
|
""",
|
||||||
|
|
||||||
|
"""def bar():
|
||||||
|
{i async for i in els}
|
||||||
|
""",
|
||||||
|
|
||||||
"""def bar():
|
"""def bar():
|
||||||
[await i for i in els]
|
[await i for i in els]
|
||||||
""",
|
""",
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
Allow use of asynchronous generator expressions in synchronous functions.
|
@ -3974,7 +3974,7 @@ compiler_comprehension(struct compiler *c, expr_ty e, int type,
|
|||||||
|
|
||||||
is_async_generator = c->u->u_ste->ste_coroutine;
|
is_async_generator = c->u->u_ste->ste_coroutine;
|
||||||
|
|
||||||
if (is_async_generator && !is_async_function) {
|
if (is_async_generator && !is_async_function && type != COMP_GENEXP) {
|
||||||
if (e->lineno > c->u->u_lineno) {
|
if (e->lineno > c->u->u_lineno) {
|
||||||
c->u->u_lineno = e->lineno;
|
c->u->u_lineno = e->lineno;
|
||||||
c->u->u_lineno_set = 0;
|
c->u->u_lineno_set = 0;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user