Skip to content

gh-120769: Add pdb meta command to print frame status. #120770

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jun 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 17 additions & 9 deletions Lib/pdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -517,7 +517,7 @@ def _validate_file_mtime(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():
Expand Down Expand Up @@ -605,15 +605,13 @@ def interaction(self, frame, tb_or_exc):
self.setup(frame, tb)
# 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()

Expand Down Expand Up @@ -846,6 +844,10 @@ def onecmd(self, line):
"""
if not self.commands_defining:
self._validate_file_mtime()
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)
Expand Down Expand Up @@ -982,6 +984,12 @@ def completedefault(self, text, line, begidx, endidx):
state += 1
return matches

# Pdb meta commands, only intended to be used internally by pdb

def _pdbcmd_print_frame_status(self, arg):
self.print_stack_trace(0)
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
Expand Down
31 changes: 31 additions & 0 deletions Lib/test/test_pdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,37 @@ 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()
... 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]>(3)test_function()
-> import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
(Pdb) p x
1
(Pdb)
1
(Pdb) n ;; p 0 ;; p x
0
1
> <doctest test.test_pdb.test_pdb_empty_line[0]>(4)test_function()
-> y = 2
(Pdb)
1
(Pdb) continue
"""

def do_nothing():
pass
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Make empty line in :mod:`pdb` repeats the last command even when the command is from ``cmdqueue``.
Loading