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

Skip to content

Commit 24d3201

Browse files
bpo-33041: Fixed bytecode generation for "async for" with a complex target. (#6052)
A StopAsyncIteration raised on assigning or unpacking will be now propagated instead of stopping the iteration.
1 parent 5e80a71 commit 24d3201

3 files changed

Lines changed: 70 additions & 2 deletions

File tree

Lib/test/test_coroutines.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1949,6 +1949,71 @@ async def func(): pass
19491949
support.gc_collect()
19501950
self.assertIn("was never awaited", stderr.getvalue())
19511951

1952+
def test_for_assign_raising_stop_async_iteration(self):
1953+
class BadTarget:
1954+
def __setitem__(self, key, value):
1955+
raise StopAsyncIteration(42)
1956+
tgt = BadTarget()
1957+
async def source():
1958+
yield 10
1959+
1960+
async def run_for():
1961+
with self.assertRaises(StopAsyncIteration) as cm:
1962+
async for tgt[0] in source():
1963+
pass
1964+
self.assertEqual(cm.exception.args, (42,))
1965+
return 'end'
1966+
self.assertEqual(run_async(run_for()), ([], 'end'))
1967+
1968+
async def run_list():
1969+
with self.assertRaises(StopAsyncIteration) as cm:
1970+
return [0 async for tgt[0] in source()]
1971+
self.assertEqual(cm.exception.args, (42,))
1972+
return 'end'
1973+
self.assertEqual(run_async(run_list()), ([], 'end'))
1974+
1975+
async def run_gen():
1976+
gen = (0 async for tgt[0] in source())
1977+
a = gen.asend(None)
1978+
with self.assertRaises(RuntimeError) as cm:
1979+
await a
1980+
self.assertIsInstance(cm.exception.__cause__, StopAsyncIteration)
1981+
self.assertEqual(cm.exception.__cause__.args, (42,))
1982+
return 'end'
1983+
self.assertEqual(run_async(run_gen()), ([], 'end'))
1984+
1985+
def test_for_assign_raising_stop_async_iteration_2(self):
1986+
class BadIterable:
1987+
def __iter__(self):
1988+
raise StopAsyncIteration(42)
1989+
async def badpairs():
1990+
yield BadIterable()
1991+
1992+
async def run_for():
1993+
with self.assertRaises(StopAsyncIteration) as cm:
1994+
async for i, j in badpairs():
1995+
pass
1996+
self.assertEqual(cm.exception.args, (42,))
1997+
return 'end'
1998+
self.assertEqual(run_async(run_for()), ([], 'end'))
1999+
2000+
async def run_list():
2001+
with self.assertRaises(StopAsyncIteration) as cm:
2002+
return [0 async for i, j in badpairs()]
2003+
self.assertEqual(cm.exception.args, (42,))
2004+
return 'end'
2005+
self.assertEqual(run_async(run_list()), ([], 'end'))
2006+
2007+
async def run_gen():
2008+
gen = (0 async for i, j in badpairs())
2009+
a = gen.asend(None)
2010+
with self.assertRaises(RuntimeError) as cm:
2011+
await a
2012+
self.assertIsInstance(cm.exception.__cause__, StopAsyncIteration)
2013+
self.assertEqual(cm.exception.__cause__.args, (42,))
2014+
return 'end'
2015+
self.assertEqual(run_async(run_gen()), ([], 'end'))
2016+
19522017

19532018
class CoroAsyncIOCompatTest(unittest.TestCase):
19542019

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fixed bytecode generation for "async for" with a complex target. A
2+
StopAsyncIteration raised on assigning or unpacking will be now propagated
3+
instead of stopping the iteration.

Python/compile.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2473,8 +2473,8 @@ compiler_async_for(struct compiler *c, stmt_ty s)
24732473
ADDOP(c, GET_ANEXT);
24742474
ADDOP_O(c, LOAD_CONST, Py_None, consts);
24752475
ADDOP(c, YIELD_FROM);
2476-
VISIT(c, expr, s->v.AsyncFor.target);
24772476
ADDOP(c, POP_BLOCK); /* for SETUP_FINALLY */
2477+
VISIT(c, expr, s->v.AsyncFor.target);
24782478
compiler_pop_fblock(c, EXCEPT, try);
24792479
ADDOP_JREL(c, JUMP_FORWARD, after_try);
24802480

@@ -4060,8 +4060,8 @@ compiler_async_comprehension_generator(struct compiler *c,
40604060
ADDOP(c, GET_ANEXT);
40614061
ADDOP_O(c, LOAD_CONST, Py_None, consts);
40624062
ADDOP(c, YIELD_FROM);
4063-
VISIT(c, expr, gen->target);
40644063
ADDOP(c, POP_BLOCK);
4064+
VISIT(c, expr, gen->target);
40654065
compiler_pop_fblock(c, EXCEPT, try);
40664066
ADDOP_JREL(c, JUMP_FORWARD, after_try);
40674067

0 commit comments

Comments
 (0)