https://github.com/python/cpython/commit/3cc57505e530c64b7d783e5ac15d3e66d233bbbb
commit: 3cc57505e530c64b7d783e5ac15d3e66d233bbbb
branch: main
author: Hai Zhu <[email protected]>
committer: gaogaotiantian <[email protected]>
date: 2025-12-20T09:27:34-08:00
summary:

gh-142834:  pdb commands command should use last available breakpoint (#142835)

files:
A Misc/NEWS.d/next/Library/2025-12-16-15-32-41.gh-issue-142834.g7mHw_.rst
M Doc/library/pdb.rst
M Lib/pdb.py
M Lib/test/test_pdb.py

diff --git a/Doc/library/pdb.rst b/Doc/library/pdb.rst
index 0bbdc42535290a..8ab3e7ec9ef9d2 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 c1a5db080dc7ef..4a6bc17e91cf0c 100644
--- a/Lib/pdb.py
+++ b/Lib/pdb.py
@@ -1315,7 +1315,14 @@ def do_commands(self, arg):
         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 5cba34ff8bad10..4352aa6abfeabb 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()
+    > <doctest 
test.test_pdb.test_pdb_commands_last_breakpoint[0]>(2)test_function()
+    -> import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
+    (Pdb) break 4
+    Breakpoint 1 at <doctest 
test.test_pdb.test_pdb_commands_last_breakpoint[0]>:4
+    (Pdb) break 3
+    Breakpoint 2 at <doctest 
test.test_pdb.test_pdb_commands_last_breakpoint[0]>:3
+    (Pdb) clear 2
+    Deleted breakpoint 2 at <doctest 
test.test_pdb.test_pdb_commands_last_breakpoint[0]>:3
+    (Pdb) commands
+    (com) p "success"
+    (com) end
+    (Pdb) continue
+    'success'
+    > <doctest 
test.test_pdb.test_pdb_commands_last_breakpoint[0]>(4)test_function()
+    -> bar = 2
+    (Pdb) clear 1
+    Deleted breakpoint 1 at <doctest 
test.test_pdb.test_pdb_commands_last_breakpoint[0]>: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 00000000000000..8cde592e7c937d
--- /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.

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to