Skip to content

Commit

Permalink
pythongh-103143: Polish pdb help messages and doc strings (pythonGH-1…
Browse files Browse the repository at this point in the history
…03144)

* Made all the command part of the docstring match the official documentation
* Always have a space between the command and the description in docstring
* Added a helper function to format the help message

Before:

```
(Pdb) h a
a(rgs)
        Print the argument list of the current function.
(Pdb) h commands
commands [bpnumber]
        (com) ...
        (com) end
        (Pdb)
        ...
(Pdb) h interact
interact

        Start an interactive interpreter whose global namespace
        contains all the (global and local) names found in the current scope.
```

After
```
(Pdb) h a
      Usage: a(rgs)
      
      Print the argument list of the current function.
(Pdb) h commands
      Usage: (Pdb) commands [bpnumber]
             (com) ...
             (com) end
             (Pdb)
             ...
(Pdb) h interact
      Usage: interact
      
      Start an interactive interpreter whose global namespace
      contains all the (global and local) names found in the current scope.
```

Automerge-Triggered-By: GH:brandtbucher
  • Loading branch information
gaogaotiantian authored and aisk committed Apr 18, 2023
1 parent 45f9d1b commit e327151
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 10 deletions.
4 changes: 2 additions & 2 deletions Doc/library/pdb.rst
Expand Up @@ -315,14 +315,14 @@ can be overridden by the local file.
With a space separated list of breakpoint numbers, clear those breakpoints.
Without argument, clear all breaks (but first ask confirmation).

.. pdbcommand:: disable [bpnumber ...]
.. pdbcommand:: disable bpnumber [bpnumber ...]

Disable the breakpoints given as a space separated list of breakpoint
numbers. Disabling a breakpoint means it cannot cause the program to stop
execution, but unlike clearing a breakpoint, it remains in the list of
breakpoints and can be (re-)enabled.

.. pdbcommand:: enable [bpnumber ...]
.. pdbcommand:: enable bpnumber [bpnumber ...]

Enable the breakpoints specified.

Expand Down
67 changes: 59 additions & 8 deletions Lib/pdb.py
Expand Up @@ -586,7 +586,7 @@ def _complete_expression(self, text, line, begidx, endidx):
# Return true to exit from the command loop

def do_commands(self, arg):
"""commands [bpnumber]
"""(Pdb) commands [bpnumber]
(com) ...
(com) end
(Pdb)
Expand Down Expand Up @@ -672,6 +672,7 @@ def do_commands(self, arg):

def do_break(self, arg, temporary = 0):
"""b(reak) [ ([filename:]lineno | function) [, condition] ]
Without argument, list all breaks.
With a line number argument, set a break at this line in the
Expand Down Expand Up @@ -780,6 +781,7 @@ def defaultFile(self):

def do_tbreak(self, arg):
"""tbreak [ ([filename:]lineno | function) [, condition] ]
Same arguments as break, but sets a temporary breakpoint: it
is automatically deleted when first hit.
"""
Expand Down Expand Up @@ -844,6 +846,7 @@ def checkline(self, filename, lineno):

def do_enable(self, arg):
"""enable bpnumber [bpnumber ...]
Enables the breakpoints given as a space separated list of
breakpoint numbers.
"""
Expand All @@ -861,6 +864,7 @@ def do_enable(self, arg):

def do_disable(self, arg):
"""disable bpnumber [bpnumber ...]
Disables the breakpoints given as a space separated list of
breakpoint numbers. Disabling a breakpoint means it cannot
cause the program to stop execution, but unlike clearing a
Expand All @@ -881,6 +885,7 @@ def do_disable(self, arg):

def do_condition(self, arg):
"""condition bpnumber [condition]
Set a new condition for the breakpoint, an expression which
must evaluate to true before the breakpoint is honored. If
condition is absent, any existing condition is removed; i.e.,
Expand Down Expand Up @@ -911,6 +916,7 @@ def do_condition(self, arg):

def do_ignore(self, arg):
"""ignore bpnumber [count]
Set the ignore count for the given breakpoint number. If
count is omitted, the ignore count is set to 0. A breakpoint
becomes active when the ignore count is zero. When non-zero,
Expand Down Expand Up @@ -945,7 +951,8 @@ def do_ignore(self, arg):
complete_ignore = _complete_bpnumber

def do_clear(self, arg):
"""cl(ear) filename:lineno\ncl(ear) [bpnumber [bpnumber...]]
"""cl(ear) [filename:lineno | bpnumber ...]
With a space separated list of breakpoint numbers, clear
those breakpoints. Without argument, clear all breaks (but
first ask confirmation). With a filename:lineno argument,
Expand Down Expand Up @@ -997,6 +1004,7 @@ def do_clear(self, arg):

def do_where(self, arg):
"""w(here)
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.
Expand All @@ -1015,6 +1023,7 @@ def _select_frame(self, number):

def do_up(self, arg):
"""u(p) [count]
Move the current frame count (default one) levels up in the
stack trace (to an older frame).
"""
Expand All @@ -1035,6 +1044,7 @@ def do_up(self, arg):

def do_down(self, arg):
"""d(own) [count]
Move the current frame count (default one) levels down in the
stack trace (to a newer frame).
"""
Expand All @@ -1055,6 +1065,7 @@ def do_down(self, arg):

def do_until(self, arg):
"""unt(il) [lineno]
Without argument, continue execution until the line with a
number greater than the current one is reached. With a line
number, continue execution until a line with a number greater
Expand All @@ -1079,6 +1090,7 @@ def do_until(self, arg):

def do_step(self, arg):
"""s(tep)
Execute the current line, stop at the first possible occasion
(either in a function that is called or in the current
function).
Expand All @@ -1089,6 +1101,7 @@ def do_step(self, arg):

def do_next(self, arg):
"""n(ext)
Continue execution until the next line in the current function
is reached or it returns.
"""
Expand All @@ -1098,6 +1111,7 @@ def do_next(self, arg):

def do_run(self, arg):
"""run [args...]
Restart the debugged python program. If a string is supplied
it is split with "shlex", and the result is used as the new
sys.argv. History, breakpoints, actions and debugger options
Expand All @@ -1119,6 +1133,7 @@ def do_run(self, arg):

def do_return(self, arg):
"""r(eturn)
Continue execution until the current function returns.
"""
self.set_return(self.curframe)
Expand All @@ -1127,6 +1142,7 @@ def do_return(self, arg):

def do_continue(self, arg):
"""c(ont(inue))
Continue execution, only stop when a breakpoint is encountered.
"""
if not self.nosigint:
Expand All @@ -1145,6 +1161,7 @@ def do_continue(self, arg):

def do_jump(self, arg):
"""j(ump) lineno
Set the next line that will be executed. Only available in
the bottom-most frame. This lets you jump back and execute
code again, or jump forward to skip code that you don't want
Expand Down Expand Up @@ -1174,6 +1191,7 @@ def do_jump(self, arg):

def do_debug(self, arg):
"""debug code
Enter a recursive debugger that steps through the code
argument (which is an arbitrary expression or statement to be
executed in the current environment).
Expand All @@ -1195,7 +1213,8 @@ def do_debug(self, arg):
complete_debug = _complete_expression

def do_quit(self, arg):
"""q(uit)\nexit
"""q(uit) | exit
Quit from the debugger. The program being executed is aborted.
"""
self._user_requested_quit = True
Expand All @@ -1207,6 +1226,7 @@ def do_quit(self, arg):

def do_EOF(self, arg):
"""EOF
Handles the receipt of EOF as a command.
"""
self.message('')
Expand All @@ -1216,6 +1236,7 @@ def do_EOF(self, arg):

def do_args(self, arg):
"""a(rgs)
Print the argument list of the current function.
"""
co = self.curframe.f_code
Expand All @@ -1233,6 +1254,7 @@ def do_args(self, arg):

def do_retval(self, arg):
"""retval
Print the return value for the last return of a function.
"""
if '__return__' in self.curframe_locals:
Expand Down Expand Up @@ -1273,12 +1295,14 @@ def _msg_val_func(self, arg, func):

def do_p(self, arg):
"""p expression
Print the value of the expression.
"""
self._msg_val_func(arg, repr)

def do_pp(self, arg):
"""pp expression
Pretty-print the value of the expression.
"""
self._msg_val_func(arg, pprint.pformat)
Expand All @@ -1288,7 +1312,7 @@ def do_pp(self, arg):
complete_pp = _complete_expression

def do_list(self, arg):
"""l(ist) [first [,last] | .]
"""l(ist) [first[, last] | .]
List source code for the current file. Without arguments,
list 11 lines around the current line or continue the previous
Expand Down Expand Up @@ -1345,7 +1369,8 @@ def do_list(self, arg):
do_l = do_list

def do_longlist(self, arg):
"""longlist | ll
"""ll | longlist
List the whole source code for the current function or frame.
"""
filename = self.curframe.f_code.co_filename
Expand All @@ -1360,6 +1385,7 @@ def do_longlist(self, arg):

def do_source(self, arg):
"""source expression
Try to get source code for the given object and display it.
"""
try:
Expand Down Expand Up @@ -1397,7 +1423,8 @@ def _print_lines(self, lines, start, breaks=(), frame=None):
self.message(s + '\t' + line.rstrip())

def do_whatis(self, arg):
"""whatis arg
"""whatis expression
Print the type of the argument.
"""
try:
Expand Down Expand Up @@ -1485,7 +1512,8 @@ def do_interact(self, arg):
code.interact("*interactive*", local=ns)

def do_alias(self, arg):
"""alias [name [command [parameter parameter ...] ]]
"""alias [name [command]]
Create an alias called 'name' that executes 'command'. The
command must *not* be enclosed in quotes. Replaceable
parameters can be indicated by %1, %2, and so on, while %* is
Expand Down Expand Up @@ -1521,6 +1549,7 @@ def do_alias(self, arg):

def do_unalias(self, arg):
"""unalias name
Delete the specified alias.
"""
args = arg.split()
Expand Down Expand Up @@ -1563,6 +1592,7 @@ def print_stack_entry(self, frame_lineno, prompt_prefix=line_prefix):

def do_help(self, arg):
"""h(elp)
Without argument, print the list of available commands.
With a command name as argument, print help about that command.
"help pdb" shows the full pdb documentation.
Expand All @@ -1586,12 +1616,13 @@ def do_help(self, arg):
if command.__doc__ is None:
self.error('No help for %r; __doc__ string missing' % arg)
return
self.message(command.__doc__.rstrip())
self.message(self._help_message_from_doc(command.__doc__))

do_h = do_help

def help_exec(self):
"""(!) statement
Execute the (one-line) statement in the context of the current
stack frame. The exclamation point can be omitted unless the
first word of the statement resembles a debugger command. To
Expand Down Expand Up @@ -1672,6 +1703,26 @@ def _getsourcelines(self, obj):
lineno = max(1, lineno)
return lines, lineno

def _help_message_from_doc(self, doc):
lines = [line.strip() for line in doc.rstrip().splitlines()]
if not lines:
return "No help message found."
if "" in lines:
usage_end = lines.index("")
else:
usage_end = 1
formatted = []
indent = " " * len(self.prompt)
for i, line in enumerate(lines):
if i == 0:
prefix = "Usage: "
elif i < usage_end:
prefix = " "
else:
prefix = ""
formatted.append(indent + prefix + line)
return "\n".join(formatted)

# Collect all command help into docstring, if not run with -OO

if __doc__ is not None:
Expand Down
@@ -0,0 +1 @@
Polish the help messages and docstrings of :mod:`pdb`.

0 comments on commit e327151

Please sign in to comment.