mirror of https://github.com/python/cpython
[3.13] gh-119824: Print stack entry when user input is needed (GH-119882) (#120533)
Co-authored-by: Irit Katriel <1055913+iritkatriel@users.noreply.github.com>
This commit is contained in:
parent
6ee68fbf9b
commit
1c41aa78d8
48
Lib/pdb.py
48
Lib/pdb.py
|
@ -605,10 +605,18 @@ class Pdb(bdb.Bdb, cmd.Cmd):
|
||||||
assert tb is not None, "main exception must have a traceback"
|
assert tb is not None, "main exception must have a traceback"
|
||||||
with self._hold_exceptions(_chained_exceptions):
|
with self._hold_exceptions(_chained_exceptions):
|
||||||
self.setup(frame, tb)
|
self.setup(frame, tb)
|
||||||
# if we have more commands to process, do not show the stack entry
|
# We should print the stack entry if and only if the user input
|
||||||
if not self.cmdqueue:
|
# 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])
|
self.print_stack_entry(self.stack[self.curindex])
|
||||||
self._cmdloop()
|
self._cmdloop()
|
||||||
|
# If "w 0" is not used, pop it out
|
||||||
|
if self.cmdqueue and self.cmdqueue[-1] == 'w 0':
|
||||||
|
self.cmdqueue.pop()
|
||||||
self.forget()
|
self.forget()
|
||||||
|
|
||||||
def displayhook(self, obj):
|
def displayhook(self, obj):
|
||||||
|
@ -1403,16 +1411,24 @@ class Pdb(bdb.Bdb, cmd.Cmd):
|
||||||
complete_cl = _complete_location
|
complete_cl = _complete_location
|
||||||
|
|
||||||
def do_where(self, arg):
|
def do_where(self, arg):
|
||||||
"""w(here)
|
"""w(here) [count]
|
||||||
|
|
||||||
Print a stack trace, with the most recent frame at the bottom.
|
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.
|
||||||
An arrow indicates the "current frame", which determines the
|
An arrow indicates the "current frame", which determines the
|
||||||
context of most commands. 'bt' is an alias for this command.
|
context of most commands. 'bt' is an alias for this command.
|
||||||
"""
|
"""
|
||||||
if arg:
|
if not arg:
|
||||||
self._print_invalid_arg(arg)
|
count = None
|
||||||
return
|
else:
|
||||||
self.print_stack_trace()
|
try:
|
||||||
|
count = int(arg)
|
||||||
|
except ValueError:
|
||||||
|
self.error('Invalid count (%s)' % arg)
|
||||||
|
return
|
||||||
|
self.print_stack_trace(count)
|
||||||
do_w = do_where
|
do_w = do_where
|
||||||
do_bt = do_where
|
do_bt = do_where
|
||||||
|
|
||||||
|
@ -2067,10 +2083,22 @@ class Pdb(bdb.Bdb, cmd.Cmd):
|
||||||
# It is also consistent with the up/down commands (which are
|
# It is also consistent with the up/down commands (which are
|
||||||
# compatible with dbx and gdb: up moves towards 'main()'
|
# compatible with dbx and gdb: up moves towards 'main()'
|
||||||
# and down moves towards the most recent stack frame).
|
# 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):
|
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:]
|
||||||
try:
|
try:
|
||||||
for frame_lineno in self.stack:
|
for frame_lineno in stack_to_print:
|
||||||
self.print_stack_entry(frame_lineno)
|
self.print_stack_entry(frame_lineno)
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
pass
|
pass
|
||||||
|
|
|
@ -781,7 +781,7 @@ def test_pdb_where_command():
|
||||||
... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
|
... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
|
||||||
|
|
||||||
>>> def f():
|
>>> def f():
|
||||||
... g();
|
... g()
|
||||||
|
|
||||||
>>> def test_function():
|
>>> def test_function():
|
||||||
... f()
|
... f()
|
||||||
|
@ -789,8 +789,13 @@ def test_pdb_where_command():
|
||||||
>>> with PdbTestInput([ # doctest: +ELLIPSIS
|
>>> with PdbTestInput([ # doctest: +ELLIPSIS
|
||||||
... 'w',
|
... 'w',
|
||||||
... 'where',
|
... 'where',
|
||||||
|
... 'w 1',
|
||||||
|
... 'w invalid',
|
||||||
... 'u',
|
... 'u',
|
||||||
... 'w',
|
... 'w',
|
||||||
|
... 'w 0',
|
||||||
|
... 'w 100',
|
||||||
|
... 'w -100',
|
||||||
... 'continue',
|
... 'continue',
|
||||||
... ]):
|
... ]):
|
||||||
... test_function()
|
... test_function()
|
||||||
|
@ -798,35 +803,63 @@ def test_pdb_where_command():
|
||||||
-> import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
|
-> import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
|
||||||
(Pdb) w
|
(Pdb) w
|
||||||
...
|
...
|
||||||
<doctest test.test_pdb.test_pdb_where_command[3]>(8)<module>()
|
<doctest test.test_pdb.test_pdb_where_command[3]>(13)<module>()
|
||||||
-> test_function()
|
-> test_function()
|
||||||
<doctest test.test_pdb.test_pdb_where_command[2]>(2)test_function()
|
<doctest test.test_pdb.test_pdb_where_command[2]>(2)test_function()
|
||||||
-> f()
|
-> f()
|
||||||
<doctest test.test_pdb.test_pdb_where_command[1]>(2)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()
|
> <doctest test.test_pdb.test_pdb_where_command[0]>(2)g()
|
||||||
-> import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
|
-> import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
|
||||||
(Pdb) where
|
(Pdb) where
|
||||||
...
|
...
|
||||||
<doctest test.test_pdb.test_pdb_where_command[3]>(8)<module>()
|
<doctest test.test_pdb.test_pdb_where_command[3]>(13)<module>()
|
||||||
-> test_function()
|
-> test_function()
|
||||||
<doctest test.test_pdb.test_pdb_where_command[2]>(2)test_function()
|
<doctest test.test_pdb.test_pdb_where_command[2]>(2)test_function()
|
||||||
-> f()
|
-> f()
|
||||||
<doctest test.test_pdb.test_pdb_where_command[1]>(2)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()
|
> <doctest test.test_pdb.test_pdb_where_command[0]>(2)g()
|
||||||
-> import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
|
-> import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
|
||||||
|
(Pdb) w 1
|
||||||
|
> <doctest test.test_pdb.test_pdb_where_command[0]>(2)g()
|
||||||
|
-> import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
|
||||||
|
(Pdb) w invalid
|
||||||
|
*** Invalid count (invalid)
|
||||||
(Pdb) u
|
(Pdb) u
|
||||||
> <doctest test.test_pdb.test_pdb_where_command[1]>(2)f()
|
> <doctest test.test_pdb.test_pdb_where_command[1]>(2)f()
|
||||||
-> g();
|
-> g()
|
||||||
(Pdb) w
|
(Pdb) w
|
||||||
...
|
...
|
||||||
<doctest test.test_pdb.test_pdb_where_command[3]>(8)<module>()
|
<doctest test.test_pdb.test_pdb_where_command[3]>(13)<module>()
|
||||||
-> test_function()
|
-> test_function()
|
||||||
<doctest test.test_pdb.test_pdb_where_command[2]>(2)test_function()
|
<doctest test.test_pdb.test_pdb_where_command[2]>(2)test_function()
|
||||||
-> f()
|
-> f()
|
||||||
> <doctest test.test_pdb.test_pdb_where_command[1]>(2)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()
|
||||||
|
-> 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()
|
||||||
|
-> 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()
|
||||||
<doctest test.test_pdb.test_pdb_where_command[0]>(2)g()
|
<doctest test.test_pdb.test_pdb_where_command[0]>(2)g()
|
||||||
-> import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
|
-> import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
|
||||||
(Pdb) continue
|
(Pdb) continue
|
||||||
|
@ -3165,6 +3198,7 @@ def bœr():
|
||||||
stdout, stderr = self.run_pdb_script(script, 'q\n', pdbrc=pdbrc, remove_home=True)
|
stdout, stderr = self.run_pdb_script(script, 'q\n', pdbrc=pdbrc, remove_home=True)
|
||||||
self.assertNotIn("SyntaxError", stdout)
|
self.assertNotIn("SyntaxError", stdout)
|
||||||
self.assertIn("a+8=9", stdout)
|
self.assertIn("a+8=9", stdout)
|
||||||
|
self.assertIn("-> b = 2", stdout)
|
||||||
|
|
||||||
def test_pdbrc_empty_line(self):
|
def test_pdbrc_empty_line(self):
|
||||||
"""Test that empty lines in .pdbrc are ignored."""
|
"""Test that empty lines in .pdbrc are ignored."""
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Print stack entry in :mod:`pdb` when and only when user input is needed.
|
Loading…
Reference in New Issue