Skip to content

Commit

Permalink
[3.12] gh-98442: fix locations of with statement's cleanup instructio…
Browse files Browse the repository at this point in the history
…ns (GH-120763) (#120787)

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>
  • Loading branch information
miss-islington and iritkatriel authored Sep 15, 2024
1 parent b2a7d71 commit ffde4cd
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 1 deletion.
33 changes: 33 additions & 0 deletions Lib/test/test_compile.py
Original file line number Diff line number Diff line change
Expand Up @@ -1856,6 +1856,39 @@ def test_lambda_return_position(self):
self.assertGreaterEqual(end_col, start_col)
self.assertLessEqual(end_col, code_end)

def test_return_in_with_positions(self):
# See gh-98442
def f():
with xyz:
1
2
3
4
return R

# All instructions should have locations on a single line
for instr in dis.get_instructions(f):
start_line, end_line, _, _ = instr.positions
self.assertEqual(start_line, end_line)

# Expect three load None instructions for the no-exception __exit__ call,
# and one RETURN_VALUE.
# They should all have the locations of the context manager ('xyz').

load_none = [instr for instr in dis.get_instructions(f) if
instr.opname == 'LOAD_CONST' and instr.argval is None]
return_value = [instr for instr in dis.get_instructions(f) if
instr.opname == 'RETURN_VALUE']

self.assertEqual(len(load_none), 3)
self.assertEqual(len(return_value), 1)
for instr in load_none + return_value:
start_line, end_line, start_col, end_col = instr.positions
self.assertEqual(start_line, f.__code__.co_firstlineno + 1)
self.assertEqual(end_line, f.__code__.co_firstlineno + 1)
self.assertEqual(start_col, 17)
self.assertEqual(end_col, 20)


class TestExpressionStackSize(unittest.TestCase):
# These tests check that the computed stack size for a code object
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fix too wide source locations of the cleanup instructions of a with
statement.
4 changes: 3 additions & 1 deletion Python/compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ enum fblocktype { WHILE_LOOP, FOR_LOOP, TRY_EXCEPT, FINALLY_TRY, FINALLY_END,
struct fblockinfo {
enum fblocktype fb_type;
jump_target_label fb_block;
location fb_loc;
/* (optional) type-specific exit or cleanup block */
jump_target_label fb_exit;
/* (optional) additional information required for unwinding */
Expand Down Expand Up @@ -1467,6 +1468,7 @@ compiler_push_fblock(struct compiler *c, location loc,
f = &c->u->u_fblock[c->u->u_nfblocks++];
f->fb_type = t;
f->fb_block = block_label;
f->fb_loc = loc;
f->fb_exit = exit;
f->fb_datum = datum;
return SUCCESS;
Expand Down Expand Up @@ -1594,7 +1596,7 @@ compiler_unwind_fblock(struct compiler *c, location *ploc,

case WITH:
case ASYNC_WITH:
*ploc = LOC((stmt_ty)info->fb_datum);
*ploc = info->fb_loc;
ADDOP(c, *ploc, POP_BLOCK);
if (preserve_tos) {
ADDOP_I(c, *ploc, SWAP, 2);
Expand Down

0 comments on commit ffde4cd

Please sign in to comment.