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_asyncio/test_unix_events.py b/Lib/test/test_asyncio/test_unix_events.py index 96999470a7c69a..cdf3eaac68af15 100644 --- a/Lib/test/test_asyncio/test_unix_events.py +++ b/Lib/test/test_asyncio/test_unix_events.py @@ -1712,11 +1712,11 @@ class PolicyTests(unittest.TestCase): def create_policy(self): return asyncio.DefaultEventLoopPolicy() - def test_get_default_child_watcher(self): + @mock.patch('asyncio.unix_events.can_use_pidfd') + def test_get_default_child_watcher(self, m_can_use_pidfd): + m_can_use_pidfd.return_value = False policy = self.create_policy() self.assertIsNone(policy._watcher) - unix_events.can_use_pidfd = mock.Mock() - unix_events.can_use_pidfd.return_value = False with self.assertWarns(DeprecationWarning): watcher = policy.get_child_watcher() self.assertIsInstance(watcher, asyncio.ThreadedChildWatcher) @@ -1725,10 +1725,9 @@ def test_get_default_child_watcher(self): with self.assertWarns(DeprecationWarning): self.assertIs(watcher, policy.get_child_watcher()) + m_can_use_pidfd.return_value = True policy = self.create_policy() self.assertIsNone(policy._watcher) - unix_events.can_use_pidfd = mock.Mock() - unix_events.can_use_pidfd.return_value = True with self.assertWarns(DeprecationWarning): watcher = policy.get_child_watcher() self.assertIsInstance(watcher, asyncio.PidfdChildWatcher) 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 4d91144b1cebb7..2f7072827241da 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -3067,11 +3067,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] @@ -3079,8 +3077,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) @@ -3136,7 +3140,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 */ /* @@ -3154,13 +3159,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); @@ -3219,9 +3220,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) */