]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-120254: Add a `commands` argument to `pdb.set_trace` (#120255)
authorTian Gao <gaogaotiantian@hotmail.com>
Tue, 24 Sep 2024 19:52:15 +0000 (12:52 -0700)
committerGitHub <noreply@github.com>
Tue, 24 Sep 2024 19:52:15 +0000 (12:52 -0700)
Doc/library/pdb.rst
Lib/doctest.py
Lib/pdb.py
Lib/test/test_pdb.py
Misc/NEWS.d/next/Library/2024-06-08-03-29-01.gh-issue-120254.h682ke.rst [new file with mode: 0644]

index d696161876e99dba08df93c935bec46a16050ad1..ce7516a52b1d74541808e3f775232d3b963adec7 100644 (file)
@@ -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
index ea7d275c91db0494fe6a39c7d1c734aac09cd24b..bb281fc483c41c684d11d427fda0a3d1cfe350b4 100644 (file)
@@ -389,11 +389,11 @@ class _OutputRedirectingPdb(pdb.Pdb):
         # 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
index 228de489a9cef100010163b3df6f460d95fd5def..dd21207a627bee2dde4e75f721750cd08335eadc 100644 (file)
@@ -361,10 +361,14 @@ class Pdb(bdb.Bdb, cmd.Cmd):
         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
 
index db7d1b1e9cd935c7e4f118454c3938bfcd9332fe..3173b0553c232f72da0aa5971166250282a6c07b 100644 (file)
@@ -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 (file)
index 0000000..33ef1c9
--- /dev/null
@@ -0,0 +1 @@
+Added ``commands`` argument to :func:`pdb.set_trace` which allows users to send debugger commands from the source file.