Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 4994eaf

Browse files
iritkatrielmiss-islington
authored andcommittedJun 12, 2024·
pythongh-93691: fix too broad source locations of for statement iterators (pythonGH-120330)
(cherry picked from commit 97b69db) Co-authored-by: Irit Katriel <1055913+iritkatriel@users.noreply.github.com>
1 parent 10821cc commit 4994eaf

File tree

6 files changed

+63
-8
lines changed

6 files changed

+63
-8
lines changed
 

‎Lib/test/test_compiler_codegen.py

+1
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ def test_for_loop(self):
4949
('GET_ITER', None, 1),
5050
loop_lbl := self.Label(),
5151
('FOR_ITER', exit_lbl := self.Label(), 1),
52+
('NOP', None, 1, 1),
5253
('STORE_NAME', 1, 1),
5354
('LOAD_NAME', 2, 2),
5455
('PUSH_NULL', None, 2),

‎Lib/test/test_iter.py

+46
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import functools
1111
import contextlib
1212
import builtins
13+
import traceback
1314

1415
# Test result of triple loop (too big to inline)
1516
TRIPLETS = [(0, 0, 0), (0, 0, 1), (0, 0, 2),
@@ -1143,6 +1144,51 @@ def test_error_iter(self):
11431144
self.assertRaises(TypeError, iter, typ())
11441145
self.assertRaises(ZeroDivisionError, iter, BadIterableClass())
11451146

1147+
def test_exception_locations(self):
1148+
# The location of an exception raised from __init__ or
1149+
# __next__ should should be the iterator expression
1150+
1151+
class Iter:
1152+
def __init__(self, init_raises=False, next_raises=False):
1153+
if init_raises:
1154+
1/0
1155+
self.next_raises = next_raises
1156+
1157+
def __next__(self):
1158+
if self.next_raises:
1159+
1/0
1160+
1161+
def __iter__(self):
1162+
return self
1163+
1164+
def init_raises():
1165+
try:
1166+
for x in Iter(init_raises=True):
1167+
pass
1168+
except Exception as e:
1169+
return e
1170+
1171+
def next_raises():
1172+
try:
1173+
for x in Iter(next_raises=True):
1174+
pass
1175+
except Exception as e:
1176+
return e
1177+
1178+
for func, expected in [(init_raises, "Iter(init_raises=True)"),
1179+
(next_raises, "Iter(next_raises=True)"),
1180+
]:
1181+
with self.subTest(func):
1182+
exc = func()
1183+
f = traceback.extract_tb(exc.__traceback__)[0]
1184+
indent = 16
1185+
co = func.__code__
1186+
self.assertEqual(f.lineno, co.co_firstlineno + 2)
1187+
self.assertEqual(f.end_lineno, co.co_firstlineno + 2)
1188+
self.assertEqual(f.line[f.colno - indent : f.end_colno - indent],
1189+
expected)
1190+
1191+
11461192

11471193
if __name__ == "__main__":
11481194
unittest.main()

‎Lib/test/test_sys_settrace.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -1650,15 +1650,15 @@ def func():
16501650
EXPECTED_EVENTS = [
16511651
(0, 'call'),
16521652
(2, 'line'),
1653-
(1, 'line'),
16541653
(-3, 'call'),
16551654
(-2, 'line'),
16561655
(-2, 'return'),
1657-
(4, 'line'),
16581656
(1, 'line'),
1657+
(4, 'line'),
1658+
(2, 'line'),
16591659
(-2, 'call'),
16601660
(-2, 'return'),
1661-
(1, 'return'),
1661+
(2, 'return'),
16621662
]
16631663

16641664
# C level events should be the same as expected and the same as Python level.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix source locations of instructions generated for the iterator of a for
2+
statement.

‎Programs/test_frozenmain.h

+4-5
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎Python/compile.c

+7
Original file line numberDiff line numberDiff line change
@@ -3101,11 +3101,18 @@ compiler_for(struct compiler *c, stmt_ty s)
31013101
RETURN_IF_ERROR(compiler_push_fblock(c, loc, FOR_LOOP, start, end, NULL));
31023102

31033103
VISIT(c, expr, s->v.For.iter);
3104+
3105+
loc = LOC(s->v.For.iter);
31043106
ADDOP(c, loc, GET_ITER);
31053107

31063108
USE_LABEL(c, start);
31073109
ADDOP_JUMP(c, loc, FOR_ITER, cleanup);
31083110

3111+
/* Add NOP to ensure correct line tracing of multiline for statements.
3112+
* It will be removed later if redundant.
3113+
*/
3114+
ADDOP(c, LOC(s->v.For.target), NOP);
3115+
31093116
USE_LABEL(c, body);
31103117
VISIT(c, expr, s->v.For.target);
31113118
VISIT_SEQ(c, stmt, s->v.For.body);

0 commit comments

Comments
 (0)
Please sign in to comment.