From: Hai Zhu <35182391+cocolato@users.noreply.github.com> Date: Sat, 20 Dec 2025 17:27:34 +0000 (+0800) Subject: gh-142834: pdb commands command should use last available breakpoint (#142835) X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3cc57505e530c64b7d783e5ac15d3e66d233bbbb;p=thirdparty%2FPython%2Fcpython.git gh-142834: pdb commands command should use last available breakpoint (#142835) --- diff --git a/Doc/library/pdb.rst b/Doc/library/pdb.rst index 0bbdc4253529..8ab3e7ec9ef9 100644 --- a/Doc/library/pdb.rst +++ b/Doc/library/pdb.rst @@ -520,7 +520,8 @@ can be overridden by the local file. To remove all commands from a breakpoint, type ``commands`` and follow it immediately with ``end``; that is, give no commands. - With no *bpnumber* argument, ``commands`` refers to the last breakpoint set. + With no *bpnumber* argument, ``commands`` refers to the most recently set + breakpoint that still exists. You can use breakpoint commands to start your program up again. Simply use the :pdbcmd:`continue` command, or :pdbcmd:`step`, diff --git a/Lib/pdb.py b/Lib/pdb.py index c1a5db080dc7..4a6bc17e91cf 100644 --- a/Lib/pdb.py +++ b/Lib/pdb.py @@ -1315,7 +1315,14 @@ class Pdb(bdb.Bdb, cmd.Cmd): reached. """ if not arg: - bnum = len(bdb.Breakpoint.bpbynumber) - 1 + for bp in reversed(bdb.Breakpoint.bpbynumber): + if bp is None: + continue + bnum = bp.number + break + else: + self.error('cannot set commands: no existing breakpoint') + return else: try: bnum = int(arg) diff --git a/Lib/test/test_pdb.py b/Lib/test/test_pdb.py index 5cba34ff8bad..4352aa6abfea 100644 --- a/Lib/test/test_pdb.py +++ b/Lib/test/test_pdb.py @@ -3478,6 +3478,49 @@ def test_pdb_issue_gh_65052(): (Pdb) continue """ +def test_pdb_commands_last_breakpoint(): + """See GH-142834 + + >>> def test_function(): + ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + ... foo = 1 + ... bar = 2 + + >>> with PdbTestInput([ # doctest: +NORMALIZE_WHITESPACE + ... 'break 4', + ... 'break 3', + ... 'clear 2', + ... 'commands', + ... 'p "success"', + ... 'end', + ... 'continue', + ... 'clear 1', + ... 'commands', + ... 'continue', + ... ]): + ... test_function() + > (2)test_function() + -> import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() + (Pdb) break 4 + Breakpoint 1 at :4 + (Pdb) break 3 + Breakpoint 2 at :3 + (Pdb) clear 2 + Deleted breakpoint 2 at :3 + (Pdb) commands + (com) p "success" + (com) end + (Pdb) continue + 'success' + > (4)test_function() + -> bar = 2 + (Pdb) clear 1 + Deleted breakpoint 1 at :4 + (Pdb) commands + *** cannot set commands: no existing breakpoint + (Pdb) continue + """ + @support.force_not_colorized_test_class @support.requires_subprocess() diff --git a/Misc/NEWS.d/next/Library/2025-12-16-15-32-41.gh-issue-142834.g7mHw_.rst b/Misc/NEWS.d/next/Library/2025-12-16-15-32-41.gh-issue-142834.g7mHw_.rst new file mode 100644 index 000000000000..8cde592e7c93 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-12-16-15-32-41.gh-issue-142834.g7mHw_.rst @@ -0,0 +1 @@ +Change the :mod:`pdb` ``commands`` command to use the last available breakpoint instead of failing when the most recently created breakpoint was deleted.