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
89 g_frame
= self
.curframe
.f_globals
91 code
= eval(arg
, g_frame
).func_code
93 print '*** Could not eval argument:', arg
95 lineno
= codehack
.getlineno(code
)
96 filename
= code
.co_filename
98 # now set the break point
99 err
= self
.set_break(filename
, lineno
)
100 if err
: print '***', err
103 def do_clear(self
, arg
):
106 reply
= raw_input('Clear all breaks? ')
109 reply
= string
.lower(string
.strip(reply
))
110 if reply
in ('y', 'yes'):
111 self
.clear_all_breaks()
114 lineno
= int(eval(arg
))
116 print '*** Error in argument:', `arg`
118 filename
= self
.curframe
.f_code
.co_filename
119 err
= self
.clear_break(filename
, lineno
)
120 if err
: print '***', err
121 do_cl
= do_clear
# 'c' is already an abbreviation for 'continue'
123 def do_where(self
, arg
):
124 self
.print_stack_trace()
127 def do_up(self
, arg
):
128 if self
.curindex
== 0:
129 print '*** Oldest frame'
131 self
.curindex
= self
.curindex
- 1
132 self
.curframe
= self
.stack
[self
.curindex
][0]
133 self
.print_stack_entry(self
.stack
[self
.curindex
])
137 def do_down(self
, arg
):
138 if self
.curindex
+ 1 == len(self
.stack
):
139 print '*** Newest frame'
141 self
.curindex
= self
.curindex
+ 1
142 self
.curframe
= self
.stack
[self
.curindex
][0]
143 self
.print_stack_entry(self
.stack
[self
.curindex
])
147 def do_step(self
, arg
):
152 def do_next(self
, arg
):
153 self
.set_next(self
.curframe
)
157 def do_return(self
, arg
):
158 self
.set_return(self
.curframe
)
162 def do_continue(self
, arg
):
165 do_c
= do_cont
= do_continue
167 def do_quit(self
, arg
):
172 def do_args(self
, arg
):
173 if self
.curframe
.f_locals
.has_key('__return__'):
174 print `self
.curframe
.f_locals
['__return__']`
176 print '*** Not arguments?!'
179 def do_retval(self
, arg
):
180 if self
.curframe
.f_locals
.has_key('__return__'):
181 print self
.curframe
.f_locals
['__return__']
183 print '*** Not yet returned!'
187 self
.curframe
.f_globals
['__privileged__'] = 1
189 value
= eval(arg
, self
.curframe
.f_globals
, \
190 self
.curframe
.f_locals
)
192 print '***', sys
.exc_type
+ ':', `sys
.exc_value`
197 def do_list(self
, arg
):
198 self
.lastcmd
= 'list'
202 x
= eval(arg
, {}, {})
203 if type(x
) == type(()):
208 # Assume it's a count
211 first
= max(1, int(x
) - 5)
213 print '*** Error in argument:', `arg`
215 elif self
.lineno
is None:
216 first
= max(1, self
.curframe
.f_lineno
- 5)
218 first
= self
.lineno
+ 1
221 filename
= self
.curframe
.f_code
.co_filename
222 breaklist
= self
.get_file_breaks(filename
)
224 for lineno
in range(first
, last
+1):
225 line
= linecache
.getline(filename
, lineno
)
230 s
= string
.rjust(`lineno`
, 3)
231 if len(s
) < 4: s
= s
+ ' '
232 if lineno
in breaklist
: s
= s
+ 'B'
234 if lineno
== self
.curframe
.f_lineno
:
236 print s
+ '\t' + line
,
238 except KeyboardInterrupt:
242 def do_whatis(self
, arg
):
244 value
= eval(arg
, self
.curframe
.f_globals
, \
245 self
.curframe
.f_locals
)
247 print '***', sys
.exc_type
+ ':', `sys
.exc_value`
251 try: code
= value
.func_code
254 print 'Function', code
.co_name
256 # Is it an instance method?
257 try: code
= value
.im_func
.func_code
260 print 'Method', code
.co_name
262 # None of the above...
265 # Print a traceback starting at the top stack frame.
266 # The most recently entered frame is printed last;
267 # this is different from dbx and gdb, but consistent with
268 # the Python interpreter's stack trace.
269 # It is also consistent with the up/down commands (which are
270 # compatible with dbx and gdb: up moves towards 'main()'
271 # and down moves towards the most recent stack frame).
273 def print_stack_trace(self
):
275 for frame_lineno
in self
.stack
:
276 self
.print_stack_entry(frame_lineno
)
277 except KeyboardInterrupt:
280 def print_stack_entry(self
, frame_lineno
):
281 frame
, lineno
= frame_lineno
282 if frame
is self
.curframe
:
286 print self
.format_stack_entry(frame_lineno
)
289 # Simplified interface
294 def runctx(statement
, globals, locals):
295 Pdb().runctx(statement
, globals, locals)
298 apply(Pdb().runcall
, args
)
301 # Post-Mortem interface
306 while t
.tb_next
<> None: t
= t
.tb_next
307 p
.interaction(t
.tb_frame
, t
)
311 post_mortem(sys
.last_traceback
)
314 # Main program for testing
316 TESTCMD
= 'import x; x.main()'
324 for dirname
in sys
.path
:
325 fullname
= os
.path
.join(dirname
, 'pdb.doc')
326 if os
.path
.exists(fullname
):
327 sts
= os
.system('${PAGER-more} '+fullname
)
328 if sts
: print '*** Pager exit status:', sts
331 print 'Sorry, can\'t find the help file "pdb.doc"',
332 print 'along the Python search path'