[Python-checkins] gh-103143: Polish pdb help messages and doc strings (GH-103144)

miss-islington webhook-mailer at python.org
Tue Apr 11 18:40:37 EDT 2023


https://github.com/python/cpython/commit/2f41a009b7311a4b44bae5b3583cde3d6d10d8d1
commit: 2f41a009b7311a4b44bae5b3583cde3d6d10d8d1
branch: main
author: Tian Gao <gaogaotiantian at hotmail.com>
committer: miss-islington <31488909+miss-islington at users.noreply.github.com>
date: 2023-04-11T15:40:30-07:00
summary:

gh-103143: Polish pdb help messages and doc strings  (GH-103144)



* 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

files:
A Misc/NEWS.d/next/Library/2023-03-31-01-13-00.gh-issue-103143.6eMluy.rst
M Doc/library/pdb.rst
M Lib/pdb.py

diff --git a/Doc/library/pdb.rst b/Doc/library/pdb.rst
index d80c5eebbf27..4170882efef1 100644
--- a/Doc/library/pdb.rst
+++ b/Doc/library/pdb.rst
@@ -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.
 
diff --git a/Lib/pdb.py b/Lib/pdb.py
index e03142e9b5d8..a3553b345a8d 100755
--- a/Lib/pdb.py
+++ b/Lib/pdb.py
@@ -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)
@@ -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
@@ -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.
         """
@@ -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.
         """
@@ -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
@@ -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.,
@@ -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,
@@ -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,
@@ -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.
@@ -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).
         """
@@ -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).
         """
@@ -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
@@ -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).
@@ -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.
         """
@@ -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
@@ -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)
@@ -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:
@@ -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
@@ -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).
@@ -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
@@ -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('')
@@ -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
@@ -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:
@@ -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)
@@ -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
@@ -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
@@ -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:
@@ -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:
@@ -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
@@ -1521,6 +1549,7 @@ def do_alias(self, arg):
 
     def do_unalias(self, arg):
         """unalias name
+
         Delete the specified alias.
         """
         args = arg.split()
@@ -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.
@@ -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
@@ -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:
diff --git a/Misc/NEWS.d/next/Library/2023-03-31-01-13-00.gh-issue-103143.6eMluy.rst b/Misc/NEWS.d/next/Library/2023-03-31-01-13-00.gh-issue-103143.6eMluy.rst
new file mode 100644
index 000000000000..32bd62d27c7c
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-03-31-01-13-00.gh-issue-103143.6eMluy.rst
@@ -0,0 +1 @@
+Polish the help messages and docstrings of :mod:`pdb`.



More information about the Python-checkins mailing list