really the last log entry for 1.1
[python/dscho.git] / Lib / pdb.py
bloba77dd29f89842fb80b2e17a2121acbab3ebdb3d4
1 # pdb.py -- finally, a Python debugger!
3 # (See pdb.doc for documentation.)
5 import string
6 import sys
7 import linecache
8 import cmd
9 import bdb
10 import repr
13 class Pdb(bdb.Bdb, cmd.Cmd):
15 def __init__(self):
16 bdb.Bdb.__init__(self)
17 cmd.Cmd.__init__(self)
18 self.prompt = '(Pdb) '
20 def reset(self):
21 bdb.Bdb.reset(self)
22 self.forget()
24 def forget(self):
25 self.lineno = None
26 self.stack = []
27 self.curindex = 0
28 self.curframe = None
30 def setup(self, f, t):
31 self.forget()
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
44 print '--Return--'
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])
59 self.cmdloop()
60 self.forget()
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
67 try:
68 exec(line + '\n', globals, locals)
69 except:
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):
79 if not arg:
80 print self.get_all_breaks() # XXX
81 return
82 # Try line number as argument
83 try:
84 lineno = int(eval(arg))
85 filename = self.curframe.f_code.co_filename
86 except:
87 # Try function name as the argument
88 import codehack
89 try:
90 func = eval(arg, self.curframe.f_globals,
91 self.curframe.f_locals)
92 if hasattr(func, 'im_func'):
93 func = func.im_func
94 code = func.func_code
95 except:
96 print '*** Could not eval argument:', arg
97 return
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
104 do_b = do_break
106 def do_clear(self, arg):
107 if not arg:
108 try:
109 reply = raw_input('Clear all breaks? ')
110 except EOFError:
111 reply = 'no'
112 reply = string.lower(string.strip(reply))
113 if reply in ('y', 'yes'):
114 self.clear_all_breaks()
115 return
116 try:
117 lineno = int(eval(arg))
118 except:
119 print '*** Error in argument:', `arg`
120 return
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()
128 do_w = do_where
130 def do_up(self, arg):
131 if self.curindex == 0:
132 print '*** Oldest frame'
133 else:
134 self.curindex = self.curindex - 1
135 self.curframe = self.stack[self.curindex][0]
136 self.print_stack_entry(self.stack[self.curindex])
137 self.lineno = None
138 do_u = do_up
140 def do_down(self, arg):
141 if self.curindex + 1 == len(self.stack):
142 print '*** Newest frame'
143 else:
144 self.curindex = self.curindex + 1
145 self.curframe = self.stack[self.curindex][0]
146 self.print_stack_entry(self.stack[self.curindex])
147 self.lineno = None
148 do_d = do_down
150 def do_step(self, arg):
151 self.set_step()
152 return 1
153 do_s = do_step
155 def do_next(self, arg):
156 self.set_next(self.curframe)
157 return 1
158 do_n = do_next
160 def do_return(self, arg):
161 self.set_return(self.curframe)
162 return 1
163 do_r = do_return
165 def do_continue(self, arg):
166 self.set_continue()
167 return 1
168 do_c = do_cont = do_continue
170 def do_quit(self, arg):
171 self.set_quit()
172 return 1
173 do_q = do_quit
175 def do_args(self, arg):
176 if self.curframe.f_locals.has_key('__args__'):
177 print `self.curframe.f_locals['__args__']`
178 else:
179 print '*** No arguments?!'
180 do_a = do_args
182 def do_retval(self, arg):
183 if self.curframe.f_locals.has_key('__return__'):
184 print self.curframe.f_locals['__return__']
185 else:
186 print '*** Not yet returned!'
187 do_rv = do_retval
189 def do_p(self, arg):
190 self.curframe.f_globals['__privileged__'] = 1
191 try:
192 value = eval(arg, self.curframe.f_globals, \
193 self.curframe.f_locals)
194 except:
195 print '***', sys.exc_type + ':', `sys.exc_value`
196 return
198 print `value`
200 def do_list(self, arg):
201 self.lastcmd = 'list'
202 last = None
203 if arg:
204 try:
205 x = eval(arg, {}, {})
206 if type(x) == type(()):
207 first, last = x
208 first = int(first)
209 last = int(last)
210 if last < first:
211 # Assume it's a count
212 last = first + last
213 else:
214 first = max(1, int(x) - 5)
215 except:
216 print '*** Error in argument:', `arg`
217 return
218 elif self.lineno is None:
219 first = max(1, self.curframe.f_lineno - 5)
220 else:
221 first = self.lineno + 1
222 if last == None:
223 last = first + 10
224 filename = self.curframe.f_code.co_filename
225 breaklist = self.get_file_breaks(filename)
226 try:
227 for lineno in range(first, last+1):
228 line = linecache.getline(filename, lineno)
229 if not line:
230 print '[EOF]'
231 break
232 else:
233 s = string.rjust(`lineno`, 3)
234 if len(s) < 4: s = s + ' '
235 if lineno in breaklist: s = s + 'B'
236 else: s = s + ' '
237 if lineno == self.curframe.f_lineno:
238 s = s + '->'
239 print s + '\t' + line,
240 self.lineno = lineno
241 except KeyboardInterrupt:
242 pass
243 do_l = do_list
245 def do_whatis(self, arg):
246 try:
247 value = eval(arg, self.curframe.f_globals, \
248 self.curframe.f_locals)
249 except:
250 print '***', sys.exc_type + ':', `sys.exc_value`
251 return
252 code = None
253 # Is it a function?
254 try: code = value.func_code
255 except: pass
256 if code:
257 print 'Function', code.co_name
258 return
259 # Is it an instance method?
260 try: code = value.im_func.func_code
261 except: pass
262 if code:
263 print 'Method', code.co_name
264 return
265 # None of the above...
266 print type(value)
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):
277 try:
278 for frame_lineno in self.stack:
279 self.print_stack_entry(frame_lineno)
280 except KeyboardInterrupt:
281 pass
283 def print_stack_entry(self, frame_lineno):
284 frame, lineno = frame_lineno
285 if frame is self.curframe:
286 print '>',
287 else:
288 print ' ',
289 print self.format_stack_entry(frame_lineno)
292 # Help methods (derived from pdb.doc)
294 def help_help(self):
295 self.help_h()
297 def help_h(self):
298 print """h(elp)
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):
305 self.help_w()
307 def help_w(self):
308 print """w(here)
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."""
313 def help_down(self):
314 self.help_d()
316 def help_d(self):
317 print """d(own)
318 Move the current frame one level down in the stack trace
319 (to an older frame)."""
321 def help_up(self):
322 self.help_u()
324 def help_u(self):
325 print """u(p)
326 Move the current frame one level up in the stack trace
327 (to a newer frame)."""
329 def help_break(self):
330 self.help_b()
332 def help_b(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):
339 self.help_cl()
341 def help_cl(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)."""
346 def help_step(self):
347 self.help_s()
349 def help_s(self):
350 print """s(tep)
351 Execute the current line, stop at the first possible occasion
352 (either in a function that is called or in the current function)."""
354 def help_next(self):
355 self.help_n()
357 def help_n(self):
358 print """n(ext)
359 Continue execution until the next line in the current function
360 is reached or it returns."""
362 def help_return(self):
363 self.help_r()
365 def help_r(self):
366 print """r(eturn)
367 Continue execution until the current function returns."""
369 def help_continue(self):
370 self.help_c()
372 def help_cont(self):
373 self.help_c()
375 def help_c(self):
376 print """c(ont(inue))
377 Continue execution, only stop when a breakpoint is encountered."""
379 def help_list(self):
380 self.help_l()
382 def help_l(self):
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."""
391 def help_args(self):
392 self.help_a()
394 def help_a(self):
395 print """a(rgs)
396 Print the argument list of the current function."""
398 def help_p(self):
399 print """p expression
400 Print the value of the expression."""
402 def help_exec(self):
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']
411 (Pdb)"""
413 def help_quit(self):
414 self.help_q()
416 def help_q(self):
417 print """q(uit) Quit from the debugger.
418 The program being executed is aborted."""
420 def help_pdb(self):
421 help()
423 # Simplified interface
425 def run(statement):
426 Pdb().run(statement)
428 def runctx(statement, globals, locals):
429 Pdb().runctx(statement, globals, locals)
431 def runcall(*args):
432 apply(Pdb().runcall, args)
434 def set_trace():
435 Pdb().set_trace()
437 # Post-Mortem interface
439 def post_mortem(t):
440 p = Pdb()
441 p.reset()
442 while t.tb_next <> None: t = t.tb_next
443 p.interaction(t.tb_frame, t)
445 def pm():
446 import sys
447 post_mortem(sys.last_traceback)
450 # Main program for testing
452 TESTCMD = 'import x; x.main()'
454 def test():
455 run(TESTCMD)
457 # print help
458 def help():
459 import os
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
465 break
466 else:
467 print 'Sorry, can\'t find the help file "pdb.doc"',
468 print 'along the Python search path'