From 28efeefab7d577ea4fb6e3f6e82f903f2aee271d Mon Sep 17 00:00:00 2001 From: Tian Gao Date: Wed, 25 Sep 2024 11:18:01 -0700 Subject: gh-123756: Disable restart command if pdb is in inline mode (#123757) --- Doc/library/pdb.rst | 16 +++++++++++++++- Doc/whatsnew/3.14.rst | 3 +++ Lib/pdb.py | 12 +++++++++--- Lib/test/test_pdb.py | 21 +++++++++++++++++++++ .../2024-09-06-01-35-11.gh-issue-123756.Ozbhke.rst | 1 + 5 files changed, 49 insertions(+), 4 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2024-09-06-01-35-11.gh-issue-123756.Ozbhke.rst diff --git a/Doc/library/pdb.rst b/Doc/library/pdb.rst index ce7516a..1682eb0 100644 --- a/Doc/library/pdb.rst +++ b/Doc/library/pdb.rst @@ -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: .. 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. @@ -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 .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*:: import pdb; pdb.Pdb(skip=['django.*']).set_trace() @@ -233,6 +240,9 @@ access further features, you have to do this yourself: .. versionchanged:: 3.6 The *readrc* argument. + .. versionadded:: 3.14 + Added the *mode* argument. + .. method:: run(statement, globals=None, locals=None) runeval(expression, globals=None, locals=None) runcall(function, *args, **kwds) @@ -675,6 +685,10 @@ can be overridden by the local file. History, breakpoints, actions and debugger options are preserved. :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) Quit from the debugger. The program being executed is aborted. diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst index 5acb9bf..4d22f7a 100644 --- a/Doc/whatsnew/3.14.rst +++ b/Doc/whatsnew/3.14.rst @@ -318,6 +318,9 @@ pdb :pdbcmd:`commands` are preserved across hard-coded breakpoints. (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 ------ diff --git a/Lib/pdb.py b/Lib/pdb.py index dd21207..443160e 100644 --- a/Lib/pdb.py +++ b/Lib/pdb.py @@ -309,7 +309,7 @@ class Pdb(bdb.Bdb, cmd.Cmd): _last_pdb_instance = 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) cmd.Cmd.__init__(self, completekey, stdin, stdout) sys.audit("pdb.Pdb") @@ -321,6 +321,7 @@ class Pdb(bdb.Bdb, cmd.Cmd): self.mainpyfile = '' self._wait_for_mainpyfile = False self.tb_lineno = {} + self.mode = mode # Try to load readline if it exists try: import readline @@ -1611,6 +1612,11 @@ class Pdb(bdb.Bdb, cmd.Cmd): sys.argv. History, breakpoints, actions and debugger options 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: import shlex argv0 = sys.argv[0:1] @@ -2366,7 +2372,7 @@ def set_trace(*, header=None, commands=None): if Pdb._last_pdb_instance is not None: pdb = Pdb._last_pdb_instance else: - pdb = Pdb() + pdb = Pdb(mode='inline') if header is not None: pdb.message(header) 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 # changed by the user from the command line. There is a "restart" command # which allows explicit specification of command line arguments. - pdb = Pdb() + pdb = Pdb(mode='cli') pdb.rcLines.extend(opts.commands) while True: try: diff --git a/Lib/test/test_pdb.py b/Lib/test/test_pdb.py index 3173b05..84c0e10 100644 --- a/Lib/test/test_pdb.py +++ b/Lib/test/test_pdb.py @@ -901,6 +901,27 @@ def test_pdb_where_command(): (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() + > (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(): """Test that commands can be passed to Pdb.set_trace() diff --git a/Misc/NEWS.d/next/Library/2024-09-06-01-35-11.gh-issue-123756.Ozbhke.rst b/Misc/NEWS.d/next/Library/2024-09-06-01-35-11.gh-issue-123756.Ozbhke.rst new file mode 100644 index 0000000..258dd59 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-09-06-01-35-11.gh-issue-123756.Ozbhke.rst @@ -0,0 +1 @@ +Added a new argument ``mode`` to :class:`pdb.Pdb`. Only allow :mod:`pdb` from command line to use ``restart`` command. -- cgit v0.12