[3.12] gh-119824: Revert the where solution and use meta commands (#120928)

This commit is contained in:
Tian Gao 2024-06-23 14:58:10 -07:00 committed by GitHub
parent 4e47f8ad6d
commit 69bd1a8da0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 63 additions and 80 deletions

View file

@ -395,7 +395,7 @@ def _cmdloop(self):
# Called before loop, handles display expressions
# Set up convenience variable containers
def preloop(self):
def _show_display(self):
displaying = self.displaying.get(self.curframe)
if displaying:
for expr, oldvalue in displaying.items():
@ -421,15 +421,13 @@ def interaction(self, frame, traceback):
self.setup(frame, traceback)
# We should print the stack entry if and only if the user input
# is expected, and we should print it right before the user input.
# If self.cmdqueue is not empty, we append a "w 0" command to the
# queue, which is equivalent to print_stack_entry
if self.cmdqueue:
self.cmdqueue.append('w 0')
else:
self.print_stack_entry(self.stack[self.curindex])
# We achieve this by appending _pdbcmd_print_frame_status to the
# command queue. If cmdqueue is not exausted, the user input is
# not expected and we will not print the stack entry.
self.cmdqueue.append('_pdbcmd_print_frame_status')
self._cmdloop()
# If "w 0" is not used, pop it out
if self.cmdqueue and self.cmdqueue[-1] == 'w 0':
# If _pdbcmd_print_frame_status is not used, pop it out
if self.cmdqueue and self.cmdqueue[-1] == '_pdbcmd_print_frame_status':
self.cmdqueue.pop()
self.forget()
@ -532,6 +530,10 @@ def onecmd(self, line):
a breakpoint command list definition.
"""
if not self.commands_defining:
if line.startswith('_pdbcmd'):
command, arg, line = self.parseline(line)
if hasattr(self, command):
return getattr(self, command)(arg)
return cmd.Cmd.onecmd(self, line)
else:
return self.handle_command_def(line)
@ -631,6 +633,12 @@ def _complete_expression(self, text, line, begidx, endidx):
# Complete a simple name.
return [n for n in ns.keys() if n.startswith(text)]
# Pdb meta commands, only intended to be used internally by pdb
def _pdbcmd_print_frame_status(self, arg):
self.print_stack_entry(self.stack[self.curindex])
self._show_display()
# Command definitions, called by cmdloop()
# The argument is the remaining string on the command line
# Return true to exit from the command loop
@ -1053,24 +1061,13 @@ def do_clear(self, arg):
complete_cl = _complete_location
def do_where(self, arg):
"""w(here) [count]
"""w(here)
Print a stack trace. If count is not specified, print the full stack.
If count is 0, print the current frame entry. If count is positive,
print count entries from the most recent frame. If count is negative,
print -count entries from the least recent frame.
Print a stack trace, with the most recent frame at the bottom.
An arrow indicates the "current frame", which determines the
context of most commands. 'bt' is an alias for this command.
"""
if not arg:
count = None
else:
try:
count = int(arg)
except ValueError:
self.error('Invalid count (%s)' % arg)
return
self.print_stack_trace(count)
self.print_stack_trace()
do_w = do_where
do_bt = do_where
@ -1642,22 +1639,10 @@ def complete_unalias(self, text, line, begidx, endidx):
# It is also consistent with the up/down commands (which are
# compatible with dbx and gdb: up moves towards 'main()'
# and down moves towards the most recent stack frame).
# * if count is None, prints the full stack
# * if count = 0, prints the current frame entry
# * if count < 0, prints -count least recent frame entries
# * if count > 0, prints count most recent frame entries
def print_stack_trace(self, count=None):
if count is None:
stack_to_print = self.stack
elif count == 0:
stack_to_print = [self.stack[self.curindex]]
elif count < 0:
stack_to_print = self.stack[:-count]
else:
stack_to_print = self.stack[-count:]
def print_stack_trace(self):
try:
for frame_lineno in stack_to_print:
for frame_lineno in self.stack:
self.print_stack_entry(frame_lineno)
except KeyboardInterrupt:
pass

View file

@ -446,6 +446,38 @@ def test_pdb_pp_repr_exc():
(Pdb) continue
"""
def test_pdb_empty_line():
"""Test that empty line repeats the last command.
>>> def test_function():
... x = 1
... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
... pass
... y = 2
>>> with PdbTestInput([ # doctest: +NORMALIZE_WHITESPACE
... 'p x',
... '', # Should repeat p x
... 'n ;; p 0 ;; p x', # Fill cmdqueue with multiple commands
... '', # Should still repeat p x
... 'continue',
... ]):
... test_function()
> <doctest test.test_pdb.test_pdb_empty_line[0]>(4)test_function()
-> pass
(Pdb) p x
1
(Pdb)
1
(Pdb) n ;; p 0 ;; p x
0
1
> <doctest test.test_pdb.test_pdb_empty_line[0]>(5)test_function()
-> y = 2
(Pdb)
1
(Pdb) continue
"""
def do_nothing():
pass
@ -703,7 +735,7 @@ def test_pdb_where_command():
... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
>>> def f():
... g()
... g();
>>> def test_function():
... f()
@ -711,13 +743,8 @@ def test_pdb_where_command():
>>> with PdbTestInput([ # doctest: +ELLIPSIS
... 'w',
... 'where',
... 'w 1',
... 'w invalid',
... 'u',
... 'w',
... 'w 0',
... 'w 100',
... 'w -100',
... 'continue',
... ]):
... test_function()
@ -726,63 +753,35 @@ def test_pdb_where_command():
-> import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
(Pdb) w
...
<doctest test.test_pdb.test_pdb_where_command[3]>(13)<module>()
<doctest test.test_pdb.test_pdb_where_command[3]>(8)<module>()
-> test_function()
<doctest test.test_pdb.test_pdb_where_command[2]>(2)test_function()
-> f()
<doctest test.test_pdb.test_pdb_where_command[1]>(2)f()
-> g()
-> g();
> <doctest test.test_pdb.test_pdb_where_command[0]>(2)g()->None
-> import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
(Pdb) where
...
<doctest test.test_pdb.test_pdb_where_command[3]>(13)<module>()
<doctest test.test_pdb.test_pdb_where_command[3]>(8)<module>()
-> test_function()
<doctest test.test_pdb.test_pdb_where_command[2]>(2)test_function()
-> f()
<doctest test.test_pdb.test_pdb_where_command[1]>(2)f()
-> g()
-> g();
> <doctest test.test_pdb.test_pdb_where_command[0]>(2)g()->None
-> import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
(Pdb) w 1
> <doctest test.test_pdb.test_pdb_where_command[0]>(2)g()->None
-> import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
(Pdb) w invalid
*** Invalid count (invalid)
(Pdb) u
> <doctest test.test_pdb.test_pdb_where_command[1]>(2)f()
-> g()
-> g();
(Pdb) w
...
<doctest test.test_pdb.test_pdb_where_command[3]>(13)<module>()
<doctest test.test_pdb.test_pdb_where_command[3]>(8)<module>()
-> test_function()
<doctest test.test_pdb.test_pdb_where_command[2]>(2)test_function()
-> f()
> <doctest test.test_pdb.test_pdb_where_command[1]>(2)f()
-> g()
<doctest test.test_pdb.test_pdb_where_command[0]>(2)g()->None
-> import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
(Pdb) w 0
> <doctest test.test_pdb.test_pdb_where_command[1]>(2)f()
-> g()
(Pdb) w 100
...
<doctest test.test_pdb.test_pdb_where_command[3]>(13)<module>()
-> test_function()
<doctest test.test_pdb.test_pdb_where_command[2]>(2)test_function()
-> f()
> <doctest test.test_pdb.test_pdb_where_command[1]>(2)f()
-> g()
<doctest test.test_pdb.test_pdb_where_command[0]>(2)g()->None
-> import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
(Pdb) w -100
...
<doctest test.test_pdb.test_pdb_where_command[3]>(13)<module>()
-> test_function()
<doctest test.test_pdb.test_pdb_where_command[2]>(2)test_function()
-> f()
> <doctest test.test_pdb.test_pdb_where_command[1]>(2)f()
-> g()
-> g();
<doctest test.test_pdb.test_pdb_where_command[0]>(2)g()->None
-> import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
(Pdb) continue
@ -2299,7 +2298,6 @@ def test_pdbrc_basic(self):
stdout, stderr = self.run_pdb_script(script, 'q\n', pdbrc=pdbrc, remove_home=True)
self.assertNotIn("SyntaxError", stdout)
self.assertIn("a+8=9", stdout)
self.assertIn("-> b = 2", stdout)
def test_pdbrc_empty_line(self):
"""Test that empty lines in .pdbrc are ignored."""

View file

@ -1 +0,0 @@
Print stack entry in :mod:`pdb` when and only when user input is needed.

View file

@ -0,0 +1 @@
Make empty line in :mod:`pdb` repeats the last command even when the command is from ``cmdqueue``.