gh-102980: Redirect output of pdb's `interact` command, add tests and improve docs (#111194)

This commit is contained in:
Tian Gao 2023-12-07 02:19:33 -09:00 committed by GitHub
parent 4b125dd31a
commit 3d712a9f4c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 86 additions and 4 deletions

View File

@ -570,10 +570,27 @@ can be overridden by the local file.
Start an interactive interpreter (using the :mod:`code` module) whose global
namespace contains all the (global and local) names found in the current
scope.
scope. Use ``exit()`` or ``quit()`` to exit the interpreter and return to
the debugger.
.. note::
Because interact creates a new global namespace with the current global
and local namespace for execution, assignment to variables will not
affect the original namespaces.
However, modification to the mutable objects will be reflected in the
original namespaces.
.. versionadded:: 3.2
.. versionadded:: 3.13
``exit()`` and ``quit()`` can be used to exit :pdbcmd:`interact`
command.
.. versionchanged:: 3.13
:pdbcmd:`interact` directs its output to the debugger's
output channel rather than :data:`sys.stderr`.
.. _debugger-aliases:
.. pdbcommand:: alias [name [command]]

View File

@ -207,6 +207,15 @@ class _ModuleTarget(str):
)
class _PdbInteractiveConsole(code.InteractiveConsole):
def __init__(self, ns, message):
self._message = message
super().__init__(locals=ns, local_exit=True)
def write(self, data):
self._message(data, end='')
# Interaction prompt line will separate file and call info from code
# text using value of line_prefix string. A newline and arrow may
# be to your liking. You can set it once pdb is imported using the
@ -672,8 +681,8 @@ class Pdb(bdb.Bdb, cmd.Cmd):
# interface abstraction functions
def message(self, msg):
print(msg, file=self.stdout)
def message(self, msg, end='\n'):
print(msg, end=end, file=self.stdout)
def error(self, msg):
print('***', msg, file=self.stdout)
@ -1786,7 +1795,9 @@ class Pdb(bdb.Bdb, cmd.Cmd):
contains all the (global and local) names found in the current scope.
"""
ns = {**self.curframe.f_globals, **self.curframe_locals}
code.interact("*interactive*", local=ns, local_exit=True)
console = _PdbInteractiveConsole(ns, message=self.message)
console.interact(banner="*pdb interact start*",
exitmsg="*exit from pdb interact command*")
def do_alias(self, arg):
"""alias [name [command]]

View File

@ -778,6 +778,59 @@ def test_pdb_where_command():
(Pdb) continue
"""
def test_pdb_interact_command():
"""Test interact command
>>> g = 0
>>> dict_g = {}
>>> def test_function():
... x = 1
... lst_local = []
... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
>>> with PdbTestInput([ # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE
... 'interact',
... 'x',
... 'g',
... 'x = 2',
... 'g = 3',
... 'dict_g["a"] = True',
... 'lst_local.append(x)',
... 'exit()',
... 'p x',
... 'p g',
... 'p dict_g',
... 'p lst_local',
... 'continue',
... ]):
... test_function()
--Return--
> <doctest test.test_pdb.test_pdb_interact_command[2]>(4)test_function()->None
-> import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
(Pdb) interact
*pdb interact start*
... x
1
... g
0
... x = 2
... g = 3
... dict_g["a"] = True
... lst_local.append(x)
... exit()
*exit from pdb interact command*
(Pdb) p x
1
(Pdb) p g
0
(Pdb) p dict_g
{'a': True}
(Pdb) p lst_local
[2]
(Pdb) continue
"""
def test_convenience_variables():
"""Test convenience variables

View File

@ -0,0 +1 @@
Redirect the output of ``interact`` command of :mod:`pdb` to the same channel as the debugger. Add tests and improve docs.