]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-102980: Redirect output of pdb's `interact` command, add tests and improve docs...
authorTian Gao <gaogaotiantian@hotmail.com>
Thu, 7 Dec 2023 11:19:33 +0000 (02:19 -0900)
committerGitHub <noreply@github.com>
Thu, 7 Dec 2023 11:19:33 +0000 (11:19 +0000)
Doc/library/pdb.rst
Lib/pdb.py
Lib/test/test_pdb.py
Misc/NEWS.d/next/Library/2023-10-23-03-49-34.gh-issue-102980.aXBd54.rst [new file with mode: 0644]

index bbc6aacc62aafa7b67b0ffcd2be4e02b75756ea9..2495dcf50bb17f5be42f71ab7ab1e9d9b0e9eabf 100644 (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]]
index 9d124189df11cfc98fc789b742383531c0911136..83b7fefec63636da6ebebcd03f3e67d3f0fb5a1b 100755 (executable)
@@ -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]]
index 50d8c8f52a909de500214a3da5d5a1a2950dd8f6..d53fe3c611bc35e11e06df68b1bbd4a8d339b1fc 100644 (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
 
diff --git a/Misc/NEWS.d/next/Library/2023-10-23-03-49-34.gh-issue-102980.aXBd54.rst b/Misc/NEWS.d/next/Library/2023-10-23-03-49-34.gh-issue-102980.aXBd54.rst
new file mode 100644 (file)
index 0000000..d4bae47
--- /dev/null
@@ -0,0 +1 @@
+Redirect the output of ``interact`` command of :mod:`pdb` to the same channel as the debugger. Add tests and improve docs.