mirror of https://github.com/python/cpython
#1437051: allow "continue"/"next"/etc. in .pdbrc, also add pdb -c option to give these commands. This allows to run a script until an exception occurs.
This commit is contained in:
parent
1e30bd3753
commit
e023091815
|
@ -49,6 +49,10 @@ after normal exit of the program), pdb will restart the program. Automatic
|
||||||
restarting preserves pdb's state (such as breakpoints) and in most cases is more
|
restarting preserves pdb's state (such as breakpoints) and in most cases is more
|
||||||
useful than quitting the debugger upon program's exit.
|
useful than quitting the debugger upon program's exit.
|
||||||
|
|
||||||
|
.. versionadded:: 3.2
|
||||||
|
:file:`pdb.py` now accepts a ``-c`` option that executes commands as if given
|
||||||
|
in a :file:`.pdbrc` file, see :ref:`debugger-commands`.
|
||||||
|
|
||||||
The typical usage to break into the debugger from a running program is to
|
The typical usage to break into the debugger from a running program is to
|
||||||
insert ::
|
insert ::
|
||||||
|
|
||||||
|
@ -202,6 +206,11 @@ prompt. This is particularly useful for aliases. If both files exist, the one
|
||||||
in the home directory is read first and aliases defined there can be overridden
|
in the home directory is read first and aliases defined there can be overridden
|
||||||
by the local file.
|
by the local file.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.2
|
||||||
|
:file:`.pdbrc` can now contain commands that continue debugging, such as
|
||||||
|
:pdbcmd:`continue` or :pdbcmd:`next`. Previously, these commands had no
|
||||||
|
effect.
|
||||||
|
|
||||||
|
|
||||||
.. pdbcommand:: h(elp) [command]
|
.. pdbcommand:: h(elp) [command]
|
||||||
|
|
||||||
|
|
65
Lib/pdb.py
65
Lib/pdb.py
|
@ -332,19 +332,26 @@ class Pdb(bdb.Bdb, cmd.Cmd):
|
||||||
# locals whenever the .f_locals accessor is called, so we
|
# locals whenever the .f_locals accessor is called, so we
|
||||||
# cache it here to ensure that modifications are not overwritten.
|
# cache it here to ensure that modifications are not overwritten.
|
||||||
self.curframe_locals = self.curframe.f_locals
|
self.curframe_locals = self.curframe.f_locals
|
||||||
self.execRcLines()
|
return self.execRcLines()
|
||||||
|
|
||||||
# Can be executed earlier than 'setup' if desired
|
# Can be executed earlier than 'setup' if desired
|
||||||
def execRcLines(self):
|
def execRcLines(self):
|
||||||
if self.rcLines:
|
if not self.rcLines:
|
||||||
# Make local copy because of recursion
|
return
|
||||||
|
# local copy because of recursion
|
||||||
rcLines = self.rcLines
|
rcLines = self.rcLines
|
||||||
# executed only once
|
rcLines.reverse()
|
||||||
|
# execute every line only once
|
||||||
self.rcLines = []
|
self.rcLines = []
|
||||||
for line in rcLines:
|
while rcLines:
|
||||||
line = line[:-1]
|
line = rcLines.pop().strip()
|
||||||
if len(line) > 0 and line[0] != '#':
|
if line and line[0] != '#':
|
||||||
self.onecmd(line)
|
if self.onecmd(line):
|
||||||
|
# if onecmd returns True, the command wants to exit
|
||||||
|
# from the interaction, save leftover rc lines
|
||||||
|
# to execute before next interaction
|
||||||
|
self.rcLines += reversed(rcLines)
|
||||||
|
return True
|
||||||
|
|
||||||
# Override Bdb methods
|
# Override Bdb methods
|
||||||
|
|
||||||
|
@ -409,7 +416,11 @@ class Pdb(bdb.Bdb, cmd.Cmd):
|
||||||
# General interaction function
|
# General interaction function
|
||||||
|
|
||||||
def interaction(self, frame, traceback):
|
def interaction(self, frame, traceback):
|
||||||
self.setup(frame, traceback)
|
if self.setup(frame, traceback):
|
||||||
|
# no interaction desired at this time (happens if .pdbrc contains
|
||||||
|
# a command like "continue")
|
||||||
|
self.forget()
|
||||||
|
return
|
||||||
self.print_stack_entry(self.stack[self.curindex])
|
self.print_stack_entry(self.stack[self.curindex])
|
||||||
self.cmdloop()
|
self.cmdloop()
|
||||||
self.forget()
|
self.forget()
|
||||||
|
@ -1497,17 +1508,42 @@ def help():
|
||||||
import pydoc
|
import pydoc
|
||||||
pydoc.pager(__doc__)
|
pydoc.pager(__doc__)
|
||||||
|
|
||||||
|
_usage = """\
|
||||||
|
usage: pdb.py [-c command] ... pyfile [arg] ...
|
||||||
|
|
||||||
|
Debug the Python program given by pyfile.
|
||||||
|
|
||||||
|
Initial commands are read from .pdbrc files in your home directory
|
||||||
|
and in the current directory, if they exist. Commands supplied with
|
||||||
|
-c are executed after commands from .pdbrc files.
|
||||||
|
|
||||||
|
To let the script run until an exception occurs, use "-c continue".
|
||||||
|
To let the script run until a given line X in the debugged file, use
|
||||||
|
"-c 'break X' -c continue"."""
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
if not sys.argv[1:] or sys.argv[1] in ("--help", "-h"):
|
import getopt
|
||||||
print("usage: pdb.py scriptfile [arg] ...")
|
|
||||||
|
opts, args = getopt.getopt(sys.argv[1:], 'hc:', ['--help', '--command='])
|
||||||
|
|
||||||
|
if not args:
|
||||||
|
print(_usage)
|
||||||
sys.exit(2)
|
sys.exit(2)
|
||||||
|
|
||||||
mainpyfile = sys.argv[1] # Get script filename
|
commands = []
|
||||||
|
for opt, optarg in opts:
|
||||||
|
if opt in ['-h', '--help']:
|
||||||
|
print(_usage)
|
||||||
|
sys.exit()
|
||||||
|
elif opt in ['-c', '--command']:
|
||||||
|
commands.append(optarg)
|
||||||
|
|
||||||
|
mainpyfile = args[0] # Get script filename
|
||||||
if not os.path.exists(mainpyfile):
|
if not os.path.exists(mainpyfile):
|
||||||
print('Error:', mainpyfile, 'does not exist')
|
print('Error:', mainpyfile, 'does not exist')
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
del sys.argv[0] # Hide "pdb.py" from argument list
|
sys.argv[:] = args # Hide "pdb.py" and pdb options from argument list
|
||||||
|
|
||||||
# Replace pdb's dir with script's dir in front of module search path.
|
# Replace pdb's dir with script's dir in front of module search path.
|
||||||
sys.path[0] = os.path.dirname(mainpyfile)
|
sys.path[0] = os.path.dirname(mainpyfile)
|
||||||
|
@ -1517,6 +1553,7 @@ def main():
|
||||||
# changed by the user from the command line. There is a "restart" command
|
# changed by the user from the command line. There is a "restart" command
|
||||||
# which allows explicit specification of command line arguments.
|
# which allows explicit specification of command line arguments.
|
||||||
pdb = Pdb()
|
pdb = Pdb()
|
||||||
|
pdb.rcLines.extend(commands)
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
pdb._runscript(mainpyfile)
|
pdb._runscript(mainpyfile)
|
||||||
|
@ -1525,7 +1562,7 @@ def main():
|
||||||
print("The program finished and will be restarted")
|
print("The program finished and will be restarted")
|
||||||
except Restart:
|
except Restart:
|
||||||
print("Restarting", mainpyfile, "with arguments:")
|
print("Restarting", mainpyfile, "with arguments:")
|
||||||
print("\t" + " ".join(sys.argv[1:]))
|
print("\t" + " ".join(args))
|
||||||
except SystemExit:
|
except SystemExit:
|
||||||
# In most cases SystemExit does not warrant a post-mortem session.
|
# In most cases SystemExit does not warrant a post-mortem session.
|
||||||
print("The program exited via sys.exit(). Exit status:", end=' ')
|
print("The program exited via sys.exit(). Exit status:", end=' ')
|
||||||
|
|
|
@ -475,6 +475,10 @@ C-API
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- Issue #1437051: For pdb, allow "continue" and related commands in
|
||||||
|
.pdbrc files. Also, add a command-line option "-c" that runs a
|
||||||
|
command as if given in .pdbrc.
|
||||||
|
|
||||||
- Issue #4179: In pdb, allow "list ." as a command to return to the
|
- Issue #4179: In pdb, allow "list ." as a command to return to the
|
||||||
currently debugged line.
|
currently debugged line.
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue