8000 [3.13] gh-98442: fix locations of with statement's cleanup instructio… · python/cpython@80e0326 · GitHub
[go: up one dir, main page]

Skip to content

Commit 80e0326

Browse files
[3.13] gh-98442: fix locations of with statement's cleanup instructions (GH-120763) (#120786)
gh-98442: fix locations of with statement's cleanup instructions (GH-120763) (cherry picked from commit 55596ae) gh-98442: fix location of with statement's cleanup instructions Co-authored-by: Irit Katriel <1055913+iritkatriel@users.noreply.github.com>
1 parent 494181e commit 80e0326

File tree

3 files changed

+38
-1
lines changed

3 files changed

+38
-1
lines changed

Lib/test/test_compile.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
20552055
self.assertGreaterEqual(end_col, start_col)
20562056
self.assertLessEqual(end_col, code_end)
20572057

2058+
def test_return_in_with_positions(self):
2059+
# See gh-98442
2060+
def f():
2061+
with xyz:
2062+
1
2063+
2
2064+
3
2065+
4
2066+
return R
2067+
2068+
# All instructions should have locations on a single line
2069+
for instr in dis.get_instructions(f):
2070+
start_line, end_line, _, _ = instr.positions
2071+
self.assertEqual(start_line, end_line)
2072+
2073+
# Expect three load None instructions for the no-exception __exit__ call,
2074+
# and one RETURN_VALUE.
2075+
# They should all have the locations of the context manager ('xyz').
2076+
2077+
load_none = [instr for instr in dis.get_instructions(f) if
2078+
instr.opname == 'LOAD_CONST' and instr.argval is None]
2079+
return_value = [instr for instr in dis.get_instructions(f) if
2080+
instr.opname == 'RETURN_VALUE']
2081+
2082+
self.assertEqual(len(load_none), 3)
2083+
self.assertEqual(len(return_value), 1)
2084+
for instr in load_none + return_value:
2085+
start_line, end_line, start_col, end_col = instr.positions
2086+
self.assertEqual(start_line, f.__code__.co_firstlineno + 1)
2087+
self.assertEqual(end_line, f.__code__.co_firstlineno + 1)
2088+
self.assertEqual(start_col, 17)
2089+
self.assertEqual(end_col, 20)
2090+
20582091

20592092
class TestStaticAttributes(unittest.TestCase):
20602093

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix too wide source locations of the cleanup instructions of a with
2+
statement.

Python/compile.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ enum fblocktype { WHILE_LOOP, FOR_LOOP, TRY_EXCEPT, FINALLY_TRY, FINALLY_END,
119119
struct fblockinfo {
120120
enum fblocktype fb_type;
121121
jump_target_label fb_block;
122+
location fb_loc;
122123
/* (optional) type-specific exit or cleanup block */
123124
jump_target_label fb_exit;
124125
/* (optional) additional information required for unwinding */
@@ -1433,6 +1434,7 @@ compiler_push_fblock(struct compiler *c, location loc,
14331434
f = &c->u->u_fblock[c->u->u_nfblocks++];
14341435
f->fb_type = t;
14351436
f->fb_block = block_label;
1437+
f->fb_loc = loc;
14361438
f->fb_exit = exit;
14371439
f->fb_datum = datum;
14381440
return SUCCESS;
@@ -1560,7 +1562,7 @@ compiler_unwind_fblock(struct compiler *c, location *ploc,
15601562

15611563
case WITH:
15621564
case ASYNC_WITH:
1563-
*ploc = LOC((stmt_ty)info->fb_datum);
1565+
*ploc = info->fb_loc;
15641566
ADDOP(c, *ploc, POP_BLOCK);
15651567
if (preserve_tos) {
15661568
ADDOP_I(c, *ploc, SWAP, 2);

0 commit comments

Comments
 (0)
0