https://github.com/python/cpython/commit/af8403a58dbe45130400a133f756cbf53c5f1d7e
commit: af8403a58dbe45130400a133f756cbf53c5f1d7e
branch: main
author: Tian Gao <[email protected]>
committer: gaogaotiantian <[email protected]>
date: 2024-09-24T12:52:15-07:00
summary:

gh-120254: Add a `commands` argument to `pdb.set_trace` (#120255)

files:
A Misc/NEWS.d/next/Library/2024-06-08-03-29-01.gh-issue-120254.h682ke.rst
M Doc/library/pdb.rst
M Lib/doctest.py
M Lib/pdb.py
M Lib/test/test_pdb.py

diff --git a/Doc/library/pdb.rst b/Doc/library/pdb.rst
index d696161876e99d..ce7516a52b1d74 100644
--- a/Doc/library/pdb.rst
+++ b/Doc/library/pdb.rst
@@ -159,12 +159,15 @@ slightly different way:
    is entered.
 
 
-.. function:: set_trace(*, header=None)
+.. function:: set_trace(*, header=None, commands=None)
 
    Enter the debugger at the calling stack frame.  This is useful to hard-code
    a breakpoint at a given point in a program, even if the code is not
    otherwise being debugged (e.g. when an assertion fails).  If given,
    *header* is printed to the console just before debugging begins.
+   The *commands* argument, if given, is a list of commands to execute
+   when the debugger starts.
+
 
    .. versionchanged:: 3.7
       The keyword-only argument *header*.
@@ -173,6 +176,9 @@ slightly different way:
       :func:`set_trace` will enter the debugger immediately, rather than
       on the next line of code to be executed.
 
+   .. versionadded:: 3.14
+      The *commands* argument.
+
 .. function:: post_mortem(traceback=None)
 
    Enter post-mortem debugging of the given *traceback* object.  If no
diff --git a/Lib/doctest.py b/Lib/doctest.py
index ea7d275c91db04..bb281fc483c41c 100644
--- a/Lib/doctest.py
+++ b/Lib/doctest.py
@@ -389,11 +389,11 @@ def __init__(self, out):
         # still use input() to get user input
         self.use_rawinput = 1
 
-    def set_trace(self, frame=None):
+    def set_trace(self, frame=None, *, commands=None):
         self.__debugger_used = True
         if frame is None:
             frame = sys._getframe().f_back
-        pdb.Pdb.set_trace(self, frame)
+        pdb.Pdb.set_trace(self, frame, commands=commands)
 
     def set_continue(self):
         # Calling set_continue unconditionally would break unit test
diff --git a/Lib/pdb.py b/Lib/pdb.py
index 228de489a9cef1..dd21207a627bee 100644
--- a/Lib/pdb.py
+++ b/Lib/pdb.py
@@ -361,10 +361,14 @@ def __init__(self, completekey='tab', stdin=None, 
stdout=None, skip=None,
         self._chained_exceptions = tuple()
         self._chained_exception_index = 0
 
-    def set_trace(self, frame=None):
+    def set_trace(self, frame=None, *, commands=None):
         Pdb._last_pdb_instance = self
         if frame is None:
             frame = sys._getframe().f_back
+
+        if commands is not None:
+            self.rcLines.extend(commands)
+
         super().set_trace(frame)
 
     def sigint_handler(self, signum, frame):
@@ -2350,13 +2354,14 @@ def runcall(*args, **kwds):
     """
     return Pdb().runcall(*args, **kwds)
 
-def set_trace(*, header=None):
+def set_trace(*, header=None, commands=None):
     """Enter the debugger at the calling stack frame.
 
     This is useful to hard-code a breakpoint at a given point in a
     program, even if the code is not otherwise being debugged (e.g. when
     an assertion fails). If given, *header* is printed to the console
-    just before debugging begins.
+    just before debugging begins. *commands* is an optional list of
+    pdb commands to run when the debugger starts.
     """
     if Pdb._last_pdb_instance is not None:
         pdb = Pdb._last_pdb_instance
@@ -2364,7 +2369,7 @@ def set_trace(*, header=None):
         pdb = Pdb()
     if header is not None:
         pdb.message(header)
-    pdb.set_trace(sys._getframe().f_back)
+    pdb.set_trace(sys._getframe().f_back, commands=commands)
 
 # Post-Mortem interface
 
diff --git a/Lib/test/test_pdb.py b/Lib/test/test_pdb.py
index db7d1b1e9cd935..3173b0553c232f 100644
--- a/Lib/test/test_pdb.py
+++ b/Lib/test/test_pdb.py
@@ -901,6 +901,17 @@ def test_pdb_where_command():
     (Pdb) continue
     """
 
+def test_pdb_commands_with_set_trace():
+    """Test that commands can be passed to Pdb.set_trace()
+
+    >>> def test_function():
+    ...     x = 1
+    ...     import pdb; pdb.Pdb(nosigint=True, 
readrc=False).set_trace(commands=['p x', 'c'])
+
+    >>> test_function()
+    1
+    """
+
 
 # skip this test if sys.flags.no_site = True;
 # exit() isn't defined unless there's a site module.
diff --git 
a/Misc/NEWS.d/next/Library/2024-06-08-03-29-01.gh-issue-120254.h682ke.rst 
b/Misc/NEWS.d/next/Library/2024-06-08-03-29-01.gh-issue-120254.h682ke.rst
new file mode 100644
index 00000000000000..33ef1c91591c54
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2024-06-08-03-29-01.gh-issue-120254.h682ke.rst
@@ -0,0 +1 @@
+Added ``commands`` argument to :func:`pdb.set_trace` which allows users to 
send debugger commands from the source file.

_______________________________________________
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