Skip to content

Commit de8e529

Browse files
committed
pythongh-93691: fix too broad source locations of for statement iterators
1 parent 6efe346 commit de8e529

File tree

2 files changed

+47
-0
lines changed

2 files changed

+47
-0
lines changed

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()

Python/compile.c

+1
Original file line numberDiff line numberDiff line change
@@ -2981,6 +2981,7 @@ compiler_for(struct compiler *c, stmt_ty s)
29812981
RETURN_IF_ERROR(compiler_push_fblock(c, loc, FOR_LOOP, start, end, NULL));
29822982

29832983
VISIT(c, expr, s->v.For.iter);
2984+
loc = LOC(s->v.For.iter);
29842985
ADDOP(c, loc, GET_ITER);
29852986

29862987
USE_LABEL(c, start);

0 commit comments

Comments
 (0)