mirror of https://github.com/python/cpython
gh-93691: fix too broad source locations of for statement iterators (#120330)
This commit is contained in:
parent
755dab719d
commit
97b69db167
|
@ -49,6 +49,7 @@ class IsolatedCodeGenTests(CodegenTestCase):
|
||||||
('GET_ITER', None, 1),
|
('GET_ITER', None, 1),
|
||||||
loop_lbl := self.Label(),
|
loop_lbl := self.Label(),
|
||||||
('FOR_ITER', exit_lbl := self.Label(), 1),
|
('FOR_ITER', exit_lbl := self.Label(), 1),
|
||||||
|
('NOP', None, 1, 1),
|
||||||
('STORE_NAME', 1, 1),
|
('STORE_NAME', 1, 1),
|
||||||
('LOAD_NAME', 2, 2),
|
('LOAD_NAME', 2, 2),
|
||||||
('PUSH_NULL', None, 2),
|
('PUSH_NULL', None, 2),
|
||||||
|
|
|
@ -10,6 +10,7 @@ import collections.abc
|
||||||
import functools
|
import functools
|
||||||
import contextlib
|
import contextlib
|
||||||
import builtins
|
import builtins
|
||||||
|
import traceback
|
||||||
|
|
||||||
# Test result of triple loop (too big to inline)
|
# Test result of triple loop (too big to inline)
|
||||||
TRIPLETS = [(0, 0, 0), (0, 0, 1), (0, 0, 2),
|
TRIPLETS = [(0, 0, 0), (0, 0, 1), (0, 0, 2),
|
||||||
|
@ -1143,6 +1144,51 @@ class TestCase(unittest.TestCase):
|
||||||
self.assertRaises(TypeError, iter, typ())
|
self.assertRaises(TypeError, iter, typ())
|
||||||
self.assertRaises(ZeroDivisionError, iter, BadIterableClass())
|
self.assertRaises(ZeroDivisionError, iter, BadIterableClass())
|
||||||
|
|
||||||
|
def test_exception_locations(self):
|
||||||
|
# The location of an exception raised from __init__ or
|
||||||
|
# __next__ should should be the iterator expression
|
||||||
|
|
||||||
|
class Iter:
|
||||||
|
def __init__(self, init_raises=False, next_raises=False):
|
||||||
|
if init_raises:
|
||||||
|
1/0
|
||||||
|
self.next_raises = next_raises
|
||||||
|
|
||||||
|
def __next__(self):
|
||||||
|
if self.next_raises:
|
||||||
|
1/0
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
return self
|
||||||
|
|
||||||
|
def init_raises():
|
||||||
|
try:
|
||||||
|
for x in Iter(init_raises=True):
|
||||||
|
pass
|
||||||
|
except Exception as e:
|
||||||
|
return e
|
||||||
|
|
||||||
|
def next_raises():
|
||||||
|
try:
|
||||||
|
for x in Iter(next_raises=True):
|
||||||
|
pass
|
||||||
|
except Exception as e:
|
||||||
|
return e
|
||||||
|
|
||||||
|
for func, expected in [(init_raises, "Iter(init_raises=True)"),
|
||||||
|
(next_raises, "Iter(next_raises=True)"),
|
||||||
|
]:
|
||||||
|
with self.subTest(func):
|
||||||
|
exc = func()
|
||||||
|
f = traceback.extract_tb(exc.__traceback__)[0]
|
||||||
|
indent = 16
|
||||||
|
co = func.__code__
|
||||||
|
self.assertEqual(f.lineno, co.co_firstlineno + 2)
|
||||||
|
self.assertEqual(f.end_lineno, co.co_firstlineno + 2)
|
||||||
|
self.assertEqual(f.line[f.colno - indent : f.end_colno - indent],
|
||||||
|
expected)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
@ -1650,15 +1650,15 @@ class TraceTestCase(unittest.TestCase):
|
||||||
EXPECTED_EVENTS = [
|
EXPECTED_EVENTS = [
|
||||||
(0, 'call'),
|
(0, 'call'),
|
||||||
(2, 'line'),
|
(2, 'line'),
|
||||||
(1, 'line'),
|
|
||||||
(-3, 'call'),
|
(-3, 'call'),
|
||||||
(-2, 'line'),
|
(-2, 'line'),
|
||||||
(-2, 'return'),
|
(-2, 'return'),
|
||||||
(4, 'line'),
|
|
||||||
(1, 'line'),
|
(1, 'line'),
|
||||||
|
(4, 'line'),
|
||||||
|
(2, 'line'),
|
||||||
(-2, 'call'),
|
(-2, 'call'),
|
||||||
(-2, 'return'),
|
(-2, 'return'),
|
||||||
(1, 'return'),
|
(2, 'return'),
|
||||||
]
|
]
|
||||||
|
|
||||||
# C level events should be the same as expected and the same as Python level.
|
# C level events should be the same as expected and the same as Python level.
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
Fix source locations of instructions generated for the iterator of a for
|
||||||
|
statement.
|
|
@ -27,12 +27,11 @@ unsigned char M_test_frozenmain[] = {
|
||||||
3,0,0,0,218,3,107,101,121,169,0,243,0,0,0,0,
|
3,0,0,0,218,3,107,101,121,169,0,243,0,0,0,0,
|
||||||
218,18,116,101,115,116,95,102,114,111,122,101,110,109,97,105,
|
218,18,116,101,115,116,95,102,114,111,122,101,110,109,97,105,
|
||||||
110,46,112,121,218,8,60,109,111,100,117,108,101,62,114,18,
|
110,46,112,121,218,8,60,109,111,100,117,108,101,62,114,18,
|
||||||
0,0,0,1,0,0,0,115,99,0,0,0,240,3,1,1,
|
0,0,0,1,0,0,0,115,94,0,0,0,240,3,1,1,
|
||||||
1,243,8,0,1,11,219,0,24,225,0,5,208,6,26,212,
|
1,243,8,0,1,11,219,0,24,225,0,5,208,6,26,212,
|
||||||
0,27,217,0,5,128,106,144,35,151,40,145,40,212,0,27,
|
0,27,217,0,5,128,106,144,35,151,40,145,40,212,0,27,
|
||||||
216,9,26,215,9,38,210,9,38,211,9,40,168,24,209,9,
|
216,9,26,215,9,38,210,9,38,211,9,40,168,24,209,9,
|
||||||
50,128,6,240,2,6,12,2,242,0,7,1,42,128,67,241,
|
50,128,6,243,2,6,12,2,128,67,241,14,0,5,10,136,
|
||||||
14,0,5,10,136,71,144,67,144,53,152,2,152,54,160,35,
|
71,144,67,144,53,152,2,152,54,160,35,153,59,152,45,208,
|
||||||
153,59,152,45,208,10,40,214,4,41,242,15,7,1,42,114,
|
10,40,214,4,41,242,15,6,12,2,114,16,0,0,0,
|
||||||
16,0,0,0,
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -3025,11 +3025,18 @@ compiler_for(struct compiler *c, stmt_ty s)
|
||||||
RETURN_IF_ERROR(compiler_push_fblock(c, loc, FOR_LOOP, start, end, NULL));
|
RETURN_IF_ERROR(compiler_push_fblock(c, loc, FOR_LOOP, start, end, NULL));
|
||||||
|
|
||||||
VISIT(c, expr, s->v.For.iter);
|
VISIT(c, expr, s->v.For.iter);
|
||||||
|
|
||||||
|
loc = LOC(s->v.For.iter);
|
||||||
ADDOP(c, loc, GET_ITER);
|
ADDOP(c, loc, GET_ITER);
|
||||||
|
|
||||||
USE_LABEL(c, start);
|
USE_LABEL(c, start);
|
||||||
ADDOP_JUMP(c, loc, FOR_ITER, cleanup);
|
ADDOP_JUMP(c, loc, FOR_ITER, cleanup);
|
||||||
|
|
||||||
|
/* Add NOP to ensure correct line tracing of multiline for statements.
|
||||||
|
* It will be removed later if redundant.
|
||||||
|
*/
|
||||||
|
ADDOP(c, LOC(s->v.For.target), NOP);
|
||||||
|
|
||||||
USE_LABEL(c, body);
|
USE_LABEL(c, body);
|
||||||
VISIT(c, expr, s->v.For.target);
|
VISIT(c, expr, s->v.For.target);
|
||||||
VISIT_SEQ(c, stmt, s->v.For.body);
|
VISIT_SEQ(c, stmt, s->v.For.body);
|
||||||
|
|
Loading…
Reference in New Issue