mirror of https://github.com/python/cpython
gh-98442: fix locations of with statement's cleanup instructions (#120763)
gh-98442: fix location of with statement's cleanup instructions
This commit is contained in:
parent
8bc76ae45f
commit
55596ae044
|
@ -2055,6 +2055,39 @@ class TestSourcePositions(unittest.TestCase):
|
||||||
self.assertGreaterEqual(end_col, start_col)
|
self.assertGreaterEqual(end_col, start_col)
|
||||||
self.assertLessEqual(end_col, code_end)
|
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 TestExpectedAttributes(unittest.TestCase):
|
class TestExpectedAttributes(unittest.TestCase):
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
Fix too wide source locations of the cleanup instructions of a with
|
||||||
|
statement.
|
|
@ -119,6 +119,7 @@ enum fblocktype { WHILE_LOOP, FOR_LOOP, TRY_EXCEPT, FINALLY_TRY, FINALLY_END,
|
||||||
struct fblockinfo {
|
struct fblockinfo {
|
||||||
enum fblocktype fb_type;
|
enum fblocktype fb_type;
|
||||||
jump_target_label fb_block;
|
jump_target_label fb_block;
|
||||||
|
location fb_loc;
|
||||||
/* (optional) type-specific exit or cleanup block */
|
/* (optional) type-specific exit or cleanup block */
|
||||||
jump_target_label fb_exit;
|
jump_target_label fb_exit;
|
||||||
/* (optional) additional information required for unwinding */
|
/* (optional) additional information required for unwinding */
|
||||||
|
@ -1239,6 +1240,7 @@ compiler_push_fblock(struct compiler *c, location loc,
|
||||||
f = &c->u->u_fblock[c->u->u_nfblocks++];
|
f = &c->u->u_fblock[c->u->u_nfblocks++];
|
||||||
f->fb_type = t;
|
f->fb_type = t;
|
||||||
f->fb_block = block_label;
|
f->fb_block = block_label;
|
||||||
|
f->fb_loc = loc;
|
||||||
f->fb_exit = exit;
|
f->fb_exit = exit;
|
||||||
f->fb_datum = datum;
|
f->fb_datum = datum;
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
|
@ -1366,7 +1368,7 @@ compiler_unwind_fblock(struct compiler *c, location *ploc,
|
||||||
|
|
||||||
case WITH:
|
case WITH:
|
||||||
case ASYNC_WITH:
|
case ASYNC_WITH:
|
||||||
*ploc = LOC((stmt_ty)info->fb_datum);
|
*ploc = info->fb_loc;
|
||||||
ADDOP(c, *ploc, POP_BLOCK);
|
ADDOP(c, *ploc, POP_BLOCK);
|
||||||
if (preserve_tos) {
|
if (preserve_tos) {
|
||||||
ADDOP_I(c, *ploc, SWAP, 3);
|
ADDOP_I(c, *ploc, SWAP, 3);
|
||||||
|
|
Loading…
Reference in New Issue