From 1c01f8d79760ca74f6d35b839d23ac408b3bb44e Mon Sep 17 00:00:00 2001 From: Irit Katriel <1055913+iritkatriel@users.noreply.github.com> Date: Mon, 24 Apr 2023 14:58:51 -0600 Subject: [PATCH] gh-101517: fix line number propagation in code generated for except* (#103550) --- Lib/bdb.py | 2 ++ Lib/test/test_bdb.py | 3 +- Lib/test/test_pdb.py | 4 +-- ...-04-14-22-35-23.gh-issue-101517.5EqM-S.rst | 1 + Python/compile.c | 32 ++++++++++++------- 5 files changed, 27 insertions(+), 15 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2023-04-14-22-35-23.gh-issue-101517.5EqM-S.rst diff --git a/Lib/bdb.py b/Lib/bdb.py index 7f9b09514ffd00..0f3eec653baaad 100644 --- a/Lib/bdb.py +++ b/Lib/bdb.py @@ -574,6 +574,8 @@ def format_stack_entry(self, frame_lineno, lprefix=': '): line = linecache.getline(filename, lineno, frame.f_globals) if line: s += lprefix + line.strip() + else: + s += f'{lprefix}Warning: lineno is None' return s # The following methods can be called by clients to use diff --git a/Lib/test/test_bdb.py b/Lib/test/test_bdb.py index fc4b8094316332..568c88e326c087 100644 --- a/Lib/test/test_bdb.py +++ b/Lib/test/test_bdb.py @@ -1207,7 +1207,8 @@ def main(): class TestRegressions(unittest.TestCase): def test_format_stack_entry_no_lineno(self): # See gh-101517 - Bdb().format_stack_entry((sys._getframe(), None)) + self.assertIn('Warning: lineno is None', + Bdb().format_stack_entry((sys._getframe(), None))) if __name__ == "__main__": diff --git a/Lib/test/test_pdb.py b/Lib/test/test_pdb.py index 94b441720f258c..b5c413af344c93 100644 --- a/Lib/test/test_pdb.py +++ b/Lib/test/test_pdb.py @@ -1715,8 +1715,8 @@ def test_pdb_issue_gh_101517(): ... 'continue' ... ]): ... test_function() - --Return-- - > (None)test_function()->None + > (5)test_function() + -> import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() (Pdb) continue """ diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-04-14-22-35-23.gh-issue-101517.5EqM-S.rst b/Misc/NEWS.d/next/Core and Builtins/2023-04-14-22-35-23.gh-issue-101517.5EqM-S.rst new file mode 100644 index 00000000000000..730c6cd40d7235 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2023-04-14-22-35-23.gh-issue-101517.5EqM-S.rst @@ -0,0 +1 @@ +Fix bug in line numbers of instructions emitted for :keyword:`except* `. diff --git a/Python/compile.c b/Python/compile.c index 9c5f3aabf37510..9603269d2b2a9d 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -3045,11 +3045,9 @@ compiler_try_except(struct compiler *c, stmt_ty s) [orig, res, exc] [orig, res, exc, E1] CHECK_EG_MATCH [orig, res, rest/exc, match?] COPY 1 - [orig, res, rest/exc, match?, match?] POP_JUMP_IF_NOT_NONE H1 - [orig, res, exc, None] POP_TOP - [orig, res, exc] JUMP L2 + [orig, res, rest/exc, match?, match?] POP_JUMP_IF_NONE C1 - [orig, res, rest, match] H1: (or POP if no V1) + [orig, res, rest, match] (or POP if no V1) [orig, res, rest] SETUP_FINALLY R1 [orig, res, rest] @@ -3057,8 +3055,14 @@ compiler_try_except(struct compiler *c, stmt_ty s) [orig, res, rest, i, v] R1: LIST_APPEND 3 ) exc raised in except* body - add to res [orig, res, rest, i] POP + [orig, res, rest] JUMP LE2 - [orig, res, rest] L2: + [orig, res, rest] L2: NOP ) for lineno + [orig, res, rest] JUMP LE2 + + [orig, res, rest/exc, None] C1: POP + + [orig, res, rest] LE2: .............................etc....................... [orig, res, rest] Ln+1: LIST_APPEND 1 ) add unhandled exc to res (could be None) @@ -3114,7 +3118,8 @@ compiler_try_star_except(struct compiler *c, stmt_ty s) location loc = LOC(handler); NEW_JUMP_TARGET_LABEL(c, next_except); except = next_except; - NEW_JUMP_TARGET_LABEL(c, handle_match); + NEW_JUMP_TARGET_LABEL(c, except_with_error); + NEW_JUMP_TARGET_LABEL(c, no_match); if (i == 0) { /* create empty list for exceptions raised/reraise in the except* blocks */ /* @@ -3132,13 +3137,9 @@ compiler_try_star_except(struct compiler *c, stmt_ty s) VISIT(c, expr, handler->v.ExceptHandler.type); ADDOP(c, loc, CHECK_EG_MATCH); ADDOP_I(c, loc, COPY, 1); - ADDOP_JUMP(c, loc, POP_JUMP_IF_NOT_NONE, handle_match); - ADDOP(c, loc, POP_TOP); // match - ADDOP_JUMP(c, loc, JUMP, except); + ADDOP_JUMP(c, loc, POP_JUMP_IF_NONE, no_match); } - USE_LABEL(c, handle_match); - NEW_JUMP_TARGET_LABEL(c, cleanup_end); NEW_JUMP_TARGET_LABEL(c, cleanup_body); @@ -3197,9 +3198,16 @@ compiler_try_star_except(struct compiler *c, stmt_ty s) /* add exception raised to the res list */ ADDOP_I(c, NO_LOCATION, LIST_APPEND, 3); // exc ADDOP(c, NO_LOCATION, POP_TOP); // lasti - ADDOP_JUMP(c, NO_LOCATION, JUMP, except); + ADDOP_JUMP(c, NO_LOCATION, JUMP, except_with_error); USE_LABEL(c, except); + ADDOP(c, NO_LOCATION, NOP); // to hold a propagated location info + ADDOP_JUMP(c, NO_LOCATION, JUMP, except_with_error); + + USE_LABEL(c, no_match); + ADDOP(c, loc, POP_TOP); // match (None) + + USE_LABEL(c, except_with_error); if (i == n - 1) { /* Add exc to the list (if not None it's the unhandled part of the EG) */