mirror of
				https://github.com/python/cpython.git
				synced 2025-11-03 19:34:08 +00:00 
			
		
		
		
	gh-102980: Redirect output of pdb's interact command, add tests and improve docs (#111194)
				
					
				
			This commit is contained in:
		
							parent
							
								
									4b125dd31a
								
							
						
					
					
						commit
						3d712a9f4c
					
				
					 4 changed files with 86 additions and 4 deletions
				
			
		| 
						 | 
					@ -570,10 +570,27 @@ can be overridden by the local file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
   Start an interactive interpreter (using the :mod:`code` module) whose global
 | 
					   Start an interactive interpreter (using the :mod:`code` module) whose global
 | 
				
			||||||
   namespace contains all the (global and local) names found in the current
 | 
					   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.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:
 | 
					.. _debugger-aliases:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.. pdbcommand:: alias [name [command]]
 | 
					.. pdbcommand:: alias [name [command]]
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										17
									
								
								Lib/pdb.py
									
										
									
									
									
								
							
							
						
						
									
										17
									
								
								Lib/pdb.py
									
										
									
									
									
								
							| 
						 | 
					@ -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
 | 
					# Interaction prompt line will separate file and call info from code
 | 
				
			||||||
# text using value of line_prefix string.  A newline and arrow may
 | 
					# 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
 | 
					# 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
 | 
					    # interface abstraction functions
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def message(self, msg):
 | 
					    def message(self, msg, end='\n'):
 | 
				
			||||||
        print(msg, file=self.stdout)
 | 
					        print(msg, end=end, file=self.stdout)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def error(self, msg):
 | 
					    def error(self, msg):
 | 
				
			||||||
        print('***', msg, file=self.stdout)
 | 
					        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.
 | 
					        contains all the (global and local) names found in the current scope.
 | 
				
			||||||
        """
 | 
					        """
 | 
				
			||||||
        ns = {**self.curframe.f_globals, **self.curframe_locals}
 | 
					        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):
 | 
					    def do_alias(self, arg):
 | 
				
			||||||
        """alias [name [command]]
 | 
					        """alias [name [command]]
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -778,6 +778,59 @@ def test_pdb_where_command():
 | 
				
			||||||
    (Pdb) continue
 | 
					    (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():
 | 
					def test_convenience_variables():
 | 
				
			||||||
    """Test convenience variables
 | 
					    """Test convenience variables
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1 @@
 | 
				
			||||||
 | 
					Redirect the output of ``interact`` command of :mod:`pdb` to the same channel as the debugger. Add tests and improve docs.
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue