gh-123756: Disable restart command if pdb is in inline mode (#123757)

This commit is contained in:
Tian Gao 2024-09-25 11:18:01 -07:00 committed by GitHub
parent da5855e99a
commit 28efeefab7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 49 additions and 4 deletions

View file

@ -198,7 +198,7 @@ The ``run*`` functions and :func:`set_trace` are aliases for instantiating the
access further features, you have to do this yourself: access further features, you have to do this yourself:
.. class:: Pdb(completekey='tab', stdin=None, stdout=None, skip=None, \ .. class:: Pdb(completekey='tab', stdin=None, stdout=None, skip=None, \
nosigint=False, readrc=True) nosigint=False, readrc=True, mode=None)
:class:`Pdb` is the debugger class. :class:`Pdb` is the debugger class.
@ -217,6 +217,13 @@ access further features, you have to do this yourself:
The *readrc* argument defaults to true and controls whether Pdb will load The *readrc* argument defaults to true and controls whether Pdb will load
.pdbrc files from the filesystem. .pdbrc files from the filesystem.
The *mode* argument specifies how the debugger was invoked.
It impacts the workings of some debugger commands.
Valid values are ``'inline'`` (used by the breakpoint() builtin),
``'cli'`` (used by the command line invocation)
or ``None`` (for backwards compatible behaviour, as before the *mode*
argument was added).
Example call to enable tracing with *skip*:: Example call to enable tracing with *skip*::
import pdb; pdb.Pdb(skip=['django.*']).set_trace() import pdb; pdb.Pdb(skip=['django.*']).set_trace()
@ -233,6 +240,9 @@ access further features, you have to do this yourself:
.. versionchanged:: 3.6 .. versionchanged:: 3.6
The *readrc* argument. The *readrc* argument.
.. versionadded:: 3.14
Added the *mode* argument.
.. method:: run(statement, globals=None, locals=None) .. method:: run(statement, globals=None, locals=None)
runeval(expression, globals=None, locals=None) runeval(expression, globals=None, locals=None)
runcall(function, *args, **kwds) runcall(function, *args, **kwds)
@ -675,6 +685,10 @@ can be overridden by the local file.
History, breakpoints, actions and debugger options are preserved. History, breakpoints, actions and debugger options are preserved.
:pdbcmd:`restart` is an alias for :pdbcmd:`run`. :pdbcmd:`restart` is an alias for :pdbcmd:`run`.
.. versionchanged:: 3.14
:pdbcmd:`run` and :pdbcmd:`restart` commands are disabled when the
debugger is invoked in ``'inline'`` mode.
.. pdbcommand:: q(uit) .. pdbcommand:: q(uit)
Quit from the debugger. The program being executed is aborted. Quit from the debugger. The program being executed is aborted.

View file

@ -318,6 +318,9 @@ pdb
:pdbcmd:`commands` are preserved across hard-coded breakpoints. :pdbcmd:`commands` are preserved across hard-coded breakpoints.
(Contributed by Tian Gao in :gh:`121450`.) (Contributed by Tian Gao in :gh:`121450`.)
* Added a new argument ``mode`` to :class:`pdb.Pdb`. Disabled ``restart``
command when :mod:`pdb` is in ``inline`` mode.
(Contributed by Tian Gao in :gh:`123757`.)
pickle pickle
------ ------

View file

@ -309,7 +309,7 @@ class Pdb(bdb.Bdb, cmd.Cmd):
_last_pdb_instance = None _last_pdb_instance = None
def __init__(self, completekey='tab', stdin=None, stdout=None, skip=None, def __init__(self, completekey='tab', stdin=None, stdout=None, skip=None,
nosigint=False, readrc=True): nosigint=False, readrc=True, mode=None):
bdb.Bdb.__init__(self, skip=skip) bdb.Bdb.__init__(self, skip=skip)
cmd.Cmd.__init__(self, completekey, stdin, stdout) cmd.Cmd.__init__(self, completekey, stdin, stdout)
sys.audit("pdb.Pdb") sys.audit("pdb.Pdb")
@ -321,6 +321,7 @@ class Pdb(bdb.Bdb, cmd.Cmd):
self.mainpyfile = '' self.mainpyfile = ''
self._wait_for_mainpyfile = False self._wait_for_mainpyfile = False
self.tb_lineno = {} self.tb_lineno = {}
self.mode = mode
# Try to load readline if it exists # Try to load readline if it exists
try: try:
import readline import readline
@ -1611,6 +1612,11 @@ class Pdb(bdb.Bdb, cmd.Cmd):
sys.argv. History, breakpoints, actions and debugger options sys.argv. History, breakpoints, actions and debugger options
are preserved. "restart" is an alias for "run". are preserved. "restart" is an alias for "run".
""" """
if self.mode == 'inline':
self.error('run/restart command is disabled when pdb is running in inline mode.\n'
'Use the command line interface to enable restarting your program\n'
'e.g. "python -m pdb myscript.py"')
return
if arg: if arg:
import shlex import shlex
argv0 = sys.argv[0:1] argv0 = sys.argv[0:1]
@ -2366,7 +2372,7 @@ def set_trace(*, header=None, commands=None):
if Pdb._last_pdb_instance is not None: if Pdb._last_pdb_instance is not None:
pdb = Pdb._last_pdb_instance pdb = Pdb._last_pdb_instance
else: else:
pdb = Pdb() pdb = Pdb(mode='inline')
if header is not None: if header is not None:
pdb.message(header) pdb.message(header)
pdb.set_trace(sys._getframe().f_back, commands=commands) pdb.set_trace(sys._getframe().f_back, commands=commands)
@ -2481,7 +2487,7 @@ def main():
# modified by the script being debugged. It's a bad idea when it was # modified by the script being debugged. It's a bad idea when it was
# changed by the user from the command line. There is a "restart" command # changed by the user from the command line. There is a "restart" command
# which allows explicit specification of command line arguments. # which allows explicit specification of command line arguments.
pdb = Pdb() pdb = Pdb(mode='cli')
pdb.rcLines.extend(opts.commands) pdb.rcLines.extend(opts.commands)
while True: while True:
try: try:

View file

@ -901,6 +901,27 @@ def test_pdb_where_command():
(Pdb) continue (Pdb) continue
""" """
def test_pdb_restart_command():
"""Test restart command
>>> def test_function():
... import pdb; pdb.Pdb(nosigint=True, readrc=False, mode='inline').set_trace()
... x = 1
>>> with PdbTestInput([ # doctest: +ELLIPSIS
... 'restart',
... 'continue',
... ]):
... test_function()
> <doctest test.test_pdb.test_pdb_restart_command[0]>(2)test_function()
-> import pdb; pdb.Pdb(nosigint=True, readrc=False, mode='inline').set_trace()
(Pdb) restart
*** run/restart command is disabled when pdb is running in inline mode.
Use the command line interface to enable restarting your program
e.g. "python -m pdb myscript.py"
(Pdb) continue
"""
def test_pdb_commands_with_set_trace(): def test_pdb_commands_with_set_trace():
"""Test that commands can be passed to Pdb.set_trace() """Test that commands can be passed to Pdb.set_trace()

View file

@ -0,0 +1 @@
Added a new argument ``mode`` to :class:`pdb.Pdb`. Only allow :mod:`pdb` from command line to use ``restart`` command.