Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit b8ab9d3

Browse files
authored
bpo-31708: Allow async generator expressions in synchronous functions (#3905)
1 parent faa135a commit b8ab9d3

5 files changed

Lines changed: 52 additions & 9 deletions

File tree

Doc/reference/expressions.rst

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -326,14 +326,16 @@ range(10) for y in bar(x))``.
326326
The parentheses can be omitted on calls with only one argument. See section
327327
:ref:`calls` for details.
328328

329-
Since Python 3.6, if the generator appears in an :keyword:`async def` function,
330-
then :keyword:`async for` clauses and :keyword:`await` expressions are permitted
331-
as with an asynchronous comprehension. If a generator expression
332-
contains either :keyword:`async for` clauses or :keyword:`await` expressions
333-
it is called an :dfn:`asynchronous generator expression`.
334-
An asynchronous generator expression yields a new asynchronous
335-
generator object, which is an asynchronous iterator
336-
(see :ref:`async-iterators`).
329+
If a generator expression contains either :keyword:`async for`
330+
clauses or :keyword:`await` expressions it is called an
331+
:dfn:`asynchronous generator expression`. An asynchronous generator
332+
expression returns a new asynchronous generator object,
333+
which is an asynchronous iterator (see :ref:`async-iterators`).
334+
335+
.. versionchanged:: 3.7
336+
Prior to Python 3.7, asynchronous generator expressions could
337+
only appear in :keyword:`async def` coroutines. Starting
338+
with 3.7, any function can use asynchronous generator expressions.
337339

338340
.. _yieldexpr:
339341

Lib/test/test_asyncgen.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1037,5 +1037,37 @@ async def wait():
10371037
t.cancel()
10381038
self.loop.run_until_complete(asyncio.sleep(0.1, loop=self.loop))
10391039

1040+
def test_async_gen_expression_01(self):
1041+
async def arange(n):
1042+
for i in range(n):
1043+
await asyncio.sleep(0.01, loop=self.loop)
1044+
yield i
1045+
1046+
def make_arange(n):
1047+
# This syntax is legal starting with Python 3.7
1048+
return (i * 2 async for i in arange(n))
1049+
1050+
async def run():
1051+
return [i async for i in make_arange(10)]
1052+
1053+
res = self.loop.run_until_complete(run())
1054+
self.assertEqual(res, [i * 2 for i in range(10)])
1055+
1056+
def test_async_gen_expression_02(self):
1057+
async def wrap(n):
1058+
await asyncio.sleep(0.01, loop=self.loop)
1059+
return n
1060+
1061+
def make_arange(n):
1062+
# This syntax is legal starting with Python 3.7
1063+
return (i * 2 for i in range(n) if await wrap(i))
1064+
1065+
async def run():
1066+
return [i async for i in make_arange(10)]
1067+
1068+
res = self.loop.run_until_complete(run())
1069+
self.assertEqual(res, [i * 2 for i in range(1, 10)])
1070+
1071+
10401072
if __name__ == "__main__":
10411073
unittest.main()

Lib/test/test_coroutines.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,14 @@ def bar():
149149
[i async for i in els]
150150
""",
151151

152+
"""def bar():
153+
{i: i async for i in els}
154+
""",
155+
156+
"""def bar():
157+
{i async for i in els}
158+
""",
159+
152160
"""def bar():
153161
[await i for i in els]
154162
""",
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Allow use of asynchronous generator expressions in synchronous functions.

Python/compile.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3974,7 +3974,7 @@ compiler_comprehension(struct compiler *c, expr_ty e, int type,
39743974

39753975
is_async_generator = c->u->u_ste->ste_coroutine;
39763976

3977-
if (is_async_generator && !is_async_function) {
3977+
if (is_async_generator && !is_async_function && type != COMP_GENEXP) {
39783978
if (e->lineno > c->u->u_lineno) {
39793979
c->u->u_lineno = e->lineno;
39803980
c->u->u_lineno_set = 0;

0 commit comments

Comments
 (0)