1 # pdb.py -- finally, a Python debugger!
3 # (See pdb.doc for documentation.)
13 class Pdb(bdb
.Bdb
, cmd
.Cmd
):
16 bdb
.Bdb
.__init
__(self
)
17 cmd
.Cmd
.__init
__(self
)
18 self
.prompt
= '(Pdb) '
30 def setup(self
, f
, t
):
32 self
.stack
, self
.curindex
= self
.get_stack(f
, t
)
33 self
.curframe
= self
.stack
[self
.curindex
][0]
35 # Override Bdb methods (except user_call, for now)
37 def user_line(self
, frame
):
38 # This function is called when we stop or break at this line
39 self
.interaction(frame
, None)
41 def user_return(self
, frame
, return_value
):
42 # This function is called when a return trap is set here
43 frame
.f_locals
['__return__'] = return_value
45 self
.interaction(frame
, None)
47 def user_exception(self
, frame
, (exc_type
, exc_value
, exc_traceback
)):
48 # This function is called if an exception occurs,
49 # but only if we are to stop at or just below this level
50 frame
.f_locals
['__exception__'] = exc_type
, exc_value
51 print exc_type
+ ':', repr.repr(exc_value
)
52 self
.interaction(frame
, exc_traceback
)
54 # General interaction function
56 def interaction(self
, frame
, traceback
):
57 self
.setup(frame
, traceback
)
58 self
.print_stack_entry(self
.stack
[self
.curindex
])
62 def default(self
, line
):
63 if line
[:1] == '!': line
= line
[1:]
64 locals = self
.curframe
.f_locals
65 globals = self
.curframe
.f_globals
66 globals['__privileged__'] = 1
68 exec(line
+ '\n', globals, locals)
70 print '***', sys
.exc_type
+ ':', sys
.exc_value
72 # Command definitions, called by cmdloop()
73 # The argument is the remaining string on the command line
74 # Return true to exit from the command loop
76 do_h
= cmd
.Cmd
.do_help
78 def do_break(self
, arg
):
80 print self
.get_all_breaks() # XXX
82 # Try line number as argument
84 lineno
= int(eval(arg
))
85 filename
= self
.curframe
.f_code
.co_filename
87 # Try function name as the argument
90 func
= eval(arg
, self
.curframe
.f_globals
,
91 self
.curframe
.f_locals
)
92 if hasattr(func
, 'im_func'):
96 print '*** Could not eval argument:', arg
98 lineno
= codehack
.getlineno(code
)
99 filename
= code
.co_filename
101 # now set the break point
102 err
= self
.set_break(filename
, lineno
)
103 if err
: print '***', err
106 def do_clear(self
, arg
):
109 reply
= raw_input('Clear all breaks? ')
112 reply
= string
.lower(string
.strip(reply
))
113 if reply
in ('y', 'yes'):
114 self
.clear_all_breaks()
117 lineno
= int(eval(arg
))
119 print '*** Error in argument:', `arg`
121 filename
= self
.curframe
.f_code
.co_filename
122 err
= self
.clear_break(filename
, lineno
)
123 if err
: print '***', err
124 do_cl
= do_clear
# 'c' is already an abbreviation for 'continue'
126 def do_where(self
, arg
):
127 self
.print_stack_trace()
130 def do_up(self
, arg
):
131 if self
.curindex
== 0:
132 print '*** Oldest frame'
134 self
.curindex
= self
.curindex
- 1
135 self
.curframe
= self
.stack
[self
.curindex
][0]
136 self
.print_stack_entry(self
.stack
[self
.curindex
])
140 def do_down(self
, arg
):
141 if self
.curindex
+ 1 == len(self
.stack
):
142 print '*** Newest frame'
144 self
.curindex
= self
.curindex
+ 1
145 self
.curframe
= self
.stack
[self
.curindex
][0]
146 self
.print_stack_entry(self
.stack
[self
.curindex
])
150 def do_step(self
, arg
):
155 def do_next(self
, arg
):
156 self
.set_next(self
.curframe
)
160 def do_return(self
, arg
):
161 self
.set_return(self
.curframe
)
165 def do_continue(self
, arg
):
168 do_c
= do_cont
= do_continue
170 def do_quit(self
, arg
):
175 def do_args(self
, arg
):
176 if self
.curframe
.f_locals
.has_key('__args__'):
177 print `self
.curframe
.f_locals
['__args__']`
179 print '*** No arguments?!'
182 def do_retval(self
, arg
):
183 if self
.curframe
.f_locals
.has_key('__return__'):
184 print self
.curframe
.f_locals
['__return__']
186 print '*** Not yet returned!'
190 self
.curframe
.f_globals
['__privileged__'] = 1
192 value
= eval(arg
, self
.curframe
.f_globals
, \
193 self
.curframe
.f_locals
)
195 print '***', sys
.exc_type
+ ':', `sys
.exc_value`
200 def do_list(self
, arg
):
201 self
.lastcmd
= 'list'
205 x
= eval(arg
, {}, {})
206 if type(x
) == type(()):
211 # Assume it's a count
214 first
= max(1, int(x
) - 5)
216 print '*** Error in argument:', `arg`
218 elif self
.lineno
is None:
219 first
= max(1, self
.curframe
.f_lineno
- 5)
221 first
= self
.lineno
+ 1
224 filename
= self
.curframe
.f_code
.co_filename
225 breaklist
= self
.get_file_breaks(filename
)
227 for lineno
in range(first
, last
+1):
228 line
= linecache
.getline(filename
, lineno
)
233 s
= string
.rjust(`lineno`
, 3)
234 if len(s
) < 4: s
= s
+ ' '
235 if lineno
in breaklist
: s
= s
+ 'B'
237 if lineno
== self
.curframe
.f_lineno
:
239 print s
+ '\t' + line
,
241 except KeyboardInterrupt:
245 def do_whatis(self
, arg
):
247 value
= eval(arg
, self
.curframe
.f_globals
, \
248 self
.curframe
.f_locals
)
250 print '***', sys
.exc_type
+ ':', `sys
.exc_value`
254 try: code
= value
.func_code
257 print 'Function', code
.co_name
259 # Is it an instance method?
260 try: code
= value
.im_func
.func_code
263 print 'Method', code
.co_name
265 # None of the above...
268 # Print a traceback starting at the top stack frame.
269 # The most recently entered frame is printed last;
270 # this is different from dbx and gdb, but consistent with
271 # the Python interpreter's stack trace.
272 # It is also consistent with the up/down commands (which are
273 # compatible with dbx and gdb: up moves towards 'main()'
274 # and down moves towards the most recent stack frame).
276 def print_stack_trace(self
):
278 for frame_lineno
in self
.stack
:
279 self
.print_stack_entry(frame_lineno
)
280 except KeyboardInterrupt:
283 def print_stack_entry(self
, frame_lineno
):
284 frame
, lineno
= frame_lineno
285 if frame
is self
.curframe
:
289 print self
.format_stack_entry(frame_lineno
)
292 # Help methods (derived from pdb.doc)
299 Without argument, print the list of available commands.
300 With a command name as argument, print help about that command
301 "help pdb" pipes the full documentation file to the $PAGER
302 "help exec" gives help on the ! command"""
304 def help_where(self
):
309 Print a stack trace, with the most recent frame at the bottom.
310 An arrow indicates the "current frame", which determines the
311 context of most commands."""
318 Move the current frame one level down in the stack trace
319 (to an older frame)."""
326 Move the current frame one level up in the stack trace
327 (to a newer frame)."""
329 def help_break(self
):
333 print """b(reak) [lineno | function]
334 With a line number argument, set a break there in the current
335 file. With a function name, set a break at the entry of that
336 function. Without argument, list all breaks."""
338 def help_clear(self
):
342 print """cl(ear) [lineno]
343 With a line number argument, clear that break in the current file.
344 Without argument, clear all breaks (but first ask confirmation)."""
351 Execute the current line, stop at the first possible occasion
352 (either in a function that is called or in the current function)."""
359 Continue execution until the next line in the current function
360 is reached or it returns."""
362 def help_return(self
):
367 Continue execution until the current function returns."""
369 def help_continue(self
):
376 print """c(ont(inue))
377 Continue execution, only stop when a breakpoint is encountered."""
383 print """l(ist) [first [,last]]
384 List source code for the current file.
385 Without arguments, list 11 lines around the current line
386 or continue the previous listing.
387 With one argument, list 11 lines starting at that line.
388 With two arguments, list the given range;
389 if the second argument is less than the first, it is a count."""
396 Print the argument list of the current function."""
399 print """p expression
400 Print the value of the expression."""
403 print """(!) statement
404 Execute the (one-line) statement in the context of
405 the current stack frame.
406 The exclamation point can be omitted unless the first word
407 of the statement resembles a debugger command.
408 To assign to a global variable you must always prefix the
409 command with a 'global' command, e.g.:
410 (Pdb) global list_options; list_options = ['-l']
417 print """q(uit) Quit from the debugger.
418 The program being executed is aborted."""
423 # Simplified interface
428 def runctx(statement
, globals, locals):
429 Pdb().runctx(statement
, globals, locals)
432 apply(Pdb().runcall
, args
)
437 # Post-Mortem interface
442 while t
.tb_next
<> None: t
= t
.tb_next
443 p
.interaction(t
.tb_frame
, t
)
447 post_mortem(sys
.last_traceback
)
450 # Main program for testing
452 TESTCMD
= 'import x; x.main()'
460 for dirname
in sys
.path
:
461 fullname
= os
.path
.join(dirname
, 'pdb.doc')
462 if os
.path
.exists(fullname
):
463 sts
= os
.system('${PAGER-more} '+fullname
)
464 if sts
: print '*** Pager exit status:', sts
467 print 'Sorry, can\'t find the help file "pdb.doc"',
468 print 'along the Python search path'