Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Sep 24, 2024
8 changes: 7 additions & 1 deletion Doc/library/pdb.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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*.
Expand All @@ -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
Expand Down
4 changes: 2 additions & 2 deletions Lib/doctest.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
13 changes: 9 additions & 4 deletions Lib/pdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -2350,21 +2354,22 @@ 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
else:
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

Expand Down
11 changes: 11 additions & 0 deletions Lib/test/test_pdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Added ``commands`` argument to :func:`pdb.set_trace` which allows users to send debugger commands from the source file.
Loading