Skip to content

Commit 3d712a9

Browse files
pythongh-102980: Redirect output of pdb's interact command, add tests and improve docs (python#111194)
1 parent 4b125dd commit 3d712a9

File tree

4 files changed

+86
-4
lines changed

4 files changed

+86
-4
lines changed

Doc/library/pdb.rst

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -570,10 +570,27 @@ can be overridden by the local file.
570570

571571
Start an interactive interpreter (using the :mod:`code` module) whose global
572572
namespace contains all the (global and local) names found in the current
573-
scope.
573+
scope. Use ``exit()`` or ``quit()`` to exit the interpreter and return to
574+
the debugger.
575+
576+
.. note::
577+
578+
Because interact creates a new global namespace with the current global
579+
and local namespace for execution, assignment to variables will not
580+
affect the original namespaces.
581+
However, modification to the mutable objects will be reflected in the
582+
original namespaces.
574583

575584
.. versionadded:: 3.2
576585

586+
.. versionadded:: 3.13
587+
``exit()`` and ``quit()`` can be used to exit :pdbcmd:`interact`
588+
command.
589+
590+
.. versionchanged:: 3.13
591+
:pdbcmd:`interact` directs its output to the debugger's
592+
output channel rather than :data:`sys.stderr`.
593+
577594
.. _debugger-aliases:
578595

579596
.. pdbcommand:: alias [name [command]]

Lib/pdb.py

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,15 @@ def namespace(self):
207207
)
208208

209209

210+
class _PdbInteractiveConsole(code.InteractiveConsole):
211+
def __init__(self, ns, message):
212+
self._message = message
213+
super().__init__(locals=ns, local_exit=True)
214+
215+
def write(self, data):
216+
self._message(data, end='')
217+
218+
210219
# Interaction prompt line will separate file and call info from code
211220
# text using value of line_prefix string. A newline and arrow may
212221
# be to your liking. You can set it once pdb is imported using the
@@ -672,8 +681,8 @@ def handle_command_def(self, line):
672681

673682
# interface abstraction functions
674683

675-
def message(self, msg):
676-
print(msg, file=self.stdout)
684+
def message(self, msg, end='\n'):
685+
print(msg, end=end, file=self.stdout)
677686

678687
def error(self, msg):
679688
print('***', msg, file=self.stdout)
@@ -1786,7 +1795,9 @@ def do_interact(self, arg):
17861795
contains all the (global and local) names found in the current scope.
17871796
"""
17881797
ns = {**self.curframe.f_globals, **self.curframe_locals}
1789-
code.interact("*interactive*", local=ns, local_exit=True)
1798+
console = _PdbInteractiveConsole(ns, message=self.message)
1799+
console.interact(banner="*pdb interact start*",
1800+
exitmsg="*exit from pdb interact command*")
17901801

17911802
def do_alias(self, arg):
17921803
"""alias [name [command]]

Lib/test/test_pdb.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -778,6 +778,59 @@ def test_pdb_where_command():
778778
(Pdb) continue
779779
"""
780780

781+
def test_pdb_interact_command():
782+
"""Test interact command
783+
784+
>>> g = 0
785+
>>> dict_g = {}
786+
787+
>>> def test_function():
788+
... x = 1
789+
... lst_local = []
790+
... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
791+
792+
>>> with PdbTestInput([ # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE
793+
... 'interact',
794+
... 'x',
795+
... 'g',
796+
... 'x = 2',
797+
... 'g = 3',
798+
... 'dict_g["a"] = True',
799+
... 'lst_local.append(x)',
800+
... 'exit()',
801+
... 'p x',
802+
... 'p g',
803+
... 'p dict_g',
804+
... 'p lst_local',
805+
... 'continue',
806+
... ]):
807+
... test_function()
808+
--Return--
809+
> <doctest test.test_pdb.test_pdb_interact_command[2]>(4)test_function()->None
810+
-> import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
811+
(Pdb) interact
812+
*pdb interact start*
813+
... x
814+
1
815+
... g
816+
0
817+
... x = 2
818+
... g = 3
819+
... dict_g["a"] = True
820+
... lst_local.append(x)
821+
... exit()
822+
*exit from pdb interact command*
823+
(Pdb) p x
824+
1
825+
(Pdb) p g
826+
0
827+
(Pdb) p dict_g
828+
{'a': True}
829+
(Pdb) p lst_local
830+
[2]
831+
(Pdb) continue
832+
"""
833+
781834
def test_convenience_variables():
782835
"""Test convenience variables
783836
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Redirect the output of ``interact`` command of :mod:`pdb` to the same channel as the debugger. Add tests and improve docs.

0 commit comments

Comments
 (0)