mirror of
https://github.com/python/cpython.git
synced 2025-11-27 13:45:25 +00:00
Patch #790710: Add breakpoint command lists in pdb.
This commit is contained in:
parent
297bf82920
commit
bd30f52881
3 changed files with 165 additions and 1 deletions
|
|
@ -240,6 +240,45 @@ Condition is an expression which must evaluate to true before
|
||||||
the breakpoint is honored. If condition is absent, any existing
|
the breakpoint is honored. If condition is absent, any existing
|
||||||
condition is removed; i.e., the breakpoint is made unconditional.
|
condition is removed; i.e., the breakpoint is made unconditional.
|
||||||
|
|
||||||
|
\item[commands \optional{\var{bpnumber}}]
|
||||||
|
|
||||||
|
Specify a list of commands for breakpoint number \var{bpnumber}. The
|
||||||
|
commands themselves appear on the following lines. Type a line
|
||||||
|
containing just 'end' to terminate the commands. An example:
|
||||||
|
|
||||||
|
\begin{verbatim}
|
||||||
|
(Pdb) commands 1
|
||||||
|
(com) print some_variable
|
||||||
|
(com) end
|
||||||
|
(Pdb)
|
||||||
|
\end{verbatim}
|
||||||
|
|
||||||
|
To remove all commands from a breakpoint, type commands and
|
||||||
|
follow it immediately with end; that is, give no commands.
|
||||||
|
|
||||||
|
With no \var{bpnumber} argument, commands refers to the last
|
||||||
|
breakpoint set.
|
||||||
|
|
||||||
|
You can use breakpoint commands to start your program up again.
|
||||||
|
Simply use the continue command, or step, or any other
|
||||||
|
command that resumes execution.
|
||||||
|
|
||||||
|
Specifying any command resuming execution (currently continue,
|
||||||
|
step, next, return, jump, quit and their abbreviations) terminates
|
||||||
|
the command list (as if that command was immediately followed by end).
|
||||||
|
This is because any time you resume execution
|
||||||
|
(even with a simple next or step), you may encounter·
|
||||||
|
another breakpoint--which could have its own command list, leading to
|
||||||
|
ambiguities about which list to execute.
|
||||||
|
|
||||||
|
If you use the 'silent' command in the command list, the
|
||||||
|
usual message about stopping at a breakpoint is not printed. This may
|
||||||
|
be desirable for breakpoints that are to print a specific message and
|
||||||
|
then continue. If none of the other commands print anything, you
|
||||||
|
see no sign that the breakpoint was reached.
|
||||||
|
|
||||||
|
\versionadded{2.5}
|
||||||
|
|
||||||
\item[s(tep)]
|
\item[s(tep)]
|
||||||
|
|
||||||
Execute the current line, stop at the first possible occasion
|
Execute the current line, stop at the first possible occasion
|
||||||
|
|
|
||||||
123
Lib/pdb.py
123
Lib/pdb.py
|
|
@ -86,6 +86,12 @@ class Pdb(bdb.Bdb, cmd.Cmd):
|
||||||
self.rcLines.append(line)
|
self.rcLines.append(line)
|
||||||
rcFile.close()
|
rcFile.close()
|
||||||
|
|
||||||
|
self.commands = {} # associates a command list to breakpoint numbers
|
||||||
|
self.commands_doprompt = {} # for each bp num, tells if the prompt must be disp. after execing the cmd list
|
||||||
|
self.commands_silent = {} # for each bp num, tells if the stack trace must be disp. after execing the cmd list
|
||||||
|
self.commands_defining = False # True while in the process of defining a command list
|
||||||
|
self.commands_bnum = None # The breakpoint number for which we are defining a list
|
||||||
|
|
||||||
def reset(self):
|
def reset(self):
|
||||||
bdb.Bdb.reset(self)
|
bdb.Bdb.reset(self)
|
||||||
self.forget()
|
self.forget()
|
||||||
|
|
@ -132,8 +138,29 @@ class Pdb(bdb.Bdb, cmd.Cmd):
|
||||||
or frame.f_lineno<= 0):
|
or frame.f_lineno<= 0):
|
||||||
return
|
return
|
||||||
self._wait_for_mainpyfile = 0
|
self._wait_for_mainpyfile = 0
|
||||||
|
if self.bp_commands(frame):
|
||||||
self.interaction(frame, None)
|
self.interaction(frame, None)
|
||||||
|
|
||||||
|
def bp_commands(self,frame):
|
||||||
|
""" Call every command that was set for the current active breakpoint (if there is one)
|
||||||
|
Returns True if the normal interaction function must be called, False otherwise """
|
||||||
|
#self.currentbp is set in bdb.py in bdb.break_here if a breakpoint was hit
|
||||||
|
if getattr(self,"currentbp",False) and self.currentbp in self.commands:
|
||||||
|
currentbp = self.currentbp
|
||||||
|
self.currentbp = 0
|
||||||
|
lastcmd_back = self.lastcmd
|
||||||
|
self.setup(frame, None)
|
||||||
|
for line in self.commands[currentbp]:
|
||||||
|
self.onecmd(line)
|
||||||
|
self.lastcmd = lastcmd_back
|
||||||
|
if not self.commands_silent[currentbp]:
|
||||||
|
self.print_stack_entry(self.stack[self.curindex])
|
||||||
|
if self.commands_doprompt[currentbp]:
|
||||||
|
self.cmdloop()
|
||||||
|
self.forget()
|
||||||
|
return
|
||||||
|
return 1
|
||||||
|
|
||||||
def user_return(self, frame, return_value):
|
def user_return(self, frame, return_value):
|
||||||
"""This function is called when a return trap is set here."""
|
"""This function is called when a return trap is set here."""
|
||||||
frame.f_locals['__return__'] = return_value
|
frame.f_locals['__return__'] = return_value
|
||||||
|
|
@ -197,12 +224,70 @@ class Pdb(bdb.Bdb, cmd.Cmd):
|
||||||
line = line[:marker].rstrip()
|
line = line[:marker].rstrip()
|
||||||
return line
|
return line
|
||||||
|
|
||||||
|
def onecmd(self, line):
|
||||||
|
"""Interpret the argument as though it had been typed in response
|
||||||
|
to the prompt.
|
||||||
|
|
||||||
|
Checks wether this line is typed in the normal prompt or in a breakpoint command list definition
|
||||||
|
"""
|
||||||
|
if not self.commands_defining:
|
||||||
|
return cmd.Cmd.onecmd(self, line)
|
||||||
|
else:
|
||||||
|
return self.handle_command_def(line)
|
||||||
|
|
||||||
|
def handle_command_def(self,line):
|
||||||
|
""" Handles one command line during command list definition. """
|
||||||
|
cmd, arg, line = self.parseline(line)
|
||||||
|
if cmd == 'silent':
|
||||||
|
self.commands_silent[self.commands_bnum] = True
|
||||||
|
return # continue to handle other cmd def in the cmd list
|
||||||
|
elif cmd == 'end':
|
||||||
|
self.cmdqueue = []
|
||||||
|
return 1 # end of cmd list
|
||||||
|
cmdlist = self.commands[self.commands_bnum]
|
||||||
|
if (arg):
|
||||||
|
cmdlist.append(cmd+' '+arg)
|
||||||
|
else:
|
||||||
|
cmdlist.append(cmd)
|
||||||
|
# Determine if we must stop
|
||||||
|
try:
|
||||||
|
func = getattr(self, 'do_' + cmd)
|
||||||
|
except AttributeError:
|
||||||
|
func = self.default
|
||||||
|
if func.func_name in self.commands_resuming : # one of the resuming commands.
|
||||||
|
self.commands_doprompt[self.commands_bnum] = False
|
||||||
|
self.cmdqueue = []
|
||||||
|
return 1
|
||||||
|
return
|
||||||
|
|
||||||
# Command definitions, called by cmdloop()
|
# Command definitions, called by cmdloop()
|
||||||
# The argument is the remaining string on the command line
|
# The argument is the remaining string on the command line
|
||||||
# Return true to exit from the command loop
|
# Return true to exit from the command loop
|
||||||
|
|
||||||
do_h = cmd.Cmd.do_help
|
do_h = cmd.Cmd.do_help
|
||||||
|
|
||||||
|
def do_commands(self, arg):
|
||||||
|
"""Defines a list of commands associated to a breakpoint
|
||||||
|
Those commands will be executed whenever the breakpoint causes the program to stop execution."""
|
||||||
|
if not arg:
|
||||||
|
bnum = len(bdb.Breakpoint.bpbynumber)-1
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
bnum = int(arg)
|
||||||
|
except:
|
||||||
|
print "Usage : commands [bnum]\n ...\n end"
|
||||||
|
return
|
||||||
|
self.commands_bnum = bnum
|
||||||
|
self.commands[bnum] = []
|
||||||
|
self.commands_doprompt[bnum] = True
|
||||||
|
self.commands_silent[bnum] = False
|
||||||
|
prompt_back = self.prompt
|
||||||
|
self.prompt = '(com) '
|
||||||
|
self.commands_defining = True
|
||||||
|
self.cmdloop()
|
||||||
|
self.commands_defining = False
|
||||||
|
self.prompt = prompt_back
|
||||||
|
|
||||||
def do_break(self, arg, temporary = 0):
|
def do_break(self, arg, temporary = 0):
|
||||||
# break [ ([filename:]lineno | function) [, "condition"] ]
|
# break [ ([filename:]lineno | function) [, "condition"] ]
|
||||||
if not arg:
|
if not arg:
|
||||||
|
|
@ -686,6 +771,9 @@ class Pdb(bdb.Bdb, cmd.Cmd):
|
||||||
if args[0] in self.aliases:
|
if args[0] in self.aliases:
|
||||||
del self.aliases[args[0]]
|
del self.aliases[args[0]]
|
||||||
|
|
||||||
|
#list of all the commands making the program resume execution.
|
||||||
|
commands_resuming = ['do_continue', 'do_step', 'do_next', 'do_return', 'do_quit', 'do_jump']
|
||||||
|
|
||||||
# Print a traceback starting at the top stack frame.
|
# Print a traceback starting at the top stack frame.
|
||||||
# The most recently entered frame is printed last;
|
# The most recently entered frame is printed last;
|
||||||
# this is different from dbx and gdb, but consistent with
|
# this is different from dbx and gdb, but consistent with
|
||||||
|
|
@ -939,6 +1027,41 @@ alias ps pi self
|
||||||
print """unalias name
|
print """unalias name
|
||||||
Deletes the specified alias."""
|
Deletes the specified alias."""
|
||||||
|
|
||||||
|
def help_commands(self):
|
||||||
|
print """commands [bpnumber]
|
||||||
|
(com) ...
|
||||||
|
(com) end
|
||||||
|
(Pdb)
|
||||||
|
|
||||||
|
Specify a list of commands for breakpoint number bpnumber. The
|
||||||
|
commands themselves appear on the following lines. Type a line
|
||||||
|
containing just 'end' to terminate the commands.
|
||||||
|
|
||||||
|
To remove all commands from a breakpoint, type commands and
|
||||||
|
follow it immediately with end; that is, give no commands.
|
||||||
|
|
||||||
|
With no bpnumber argument, commands refers to the last
|
||||||
|
breakpoint set.
|
||||||
|
|
||||||
|
You can use breakpoint commands to start your program up again.
|
||||||
|
Simply use the continue command, or step, or any other
|
||||||
|
command that resumes execution.
|
||||||
|
|
||||||
|
Specifying any command resuming execution (currently continue,
|
||||||
|
step, next, return, jump, quit and their abbreviations) terminates
|
||||||
|
the command list (as if that command was immediately followed by end).
|
||||||
|
This is because any time you resume execution
|
||||||
|
(even with a simple next or step), you may encounter·
|
||||||
|
another breakpoint--which could have its own command list, leading to
|
||||||
|
ambiguities about which list to execute.
|
||||||
|
|
||||||
|
If you use the 'silent' command in the command list, the
|
||||||
|
usual message about stopping at a breakpoint is not printed. This may
|
||||||
|
be desirable for breakpoints that are to print a specific message and
|
||||||
|
then continue. If none of the other commands print anything, you
|
||||||
|
see no sign that the breakpoint was reached.
|
||||||
|
"""
|
||||||
|
|
||||||
def help_pdb(self):
|
def help_pdb(self):
|
||||||
help()
|
help()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -72,6 +72,8 @@ Extension Modules
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- Patch #790710: Add breakpoint command lists in pdb.
|
||||||
|
|
||||||
- Patch #1063914: Add Tkinter.Misc.clipboard_get().
|
- Patch #1063914: Add Tkinter.Misc.clipboard_get().
|
||||||
|
|
||||||
- Patch #1191700: Adjust column alignment in bdb breakpoint lists.
|
- Patch #1191700: Adjust column alignment in bdb breakpoint lists.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue