blob: da3cd7d9496d721b87d4aa48f180eac6b68e8653 [file] [log] [blame]
Guido van Rossum6fe08b01992-01-16 13:50:21 +00001# pdb.py -- finally, a Python debugger!
2# See file pdb.doc for instructions.
Guido van Rossum92df0c61992-01-14 18:30:15 +00003
4# To do:
Guido van Rossum6fe08b01992-01-16 13:50:21 +00005# - It should be possible to intercept KeyboardInterrupt
6# - Handle return events differently -- always printing the r.v. can be bad!
7# - Merge with tb, to get a single debugger for active and post-mortem usage
8# - Solve bugs in termination (e.g., 'continue' after the program
9# is done proceeds to debug the debugger; 'quit' sometimes complains
10# about the PdbQuit exception...)
Guido van Rossumb9142571992-01-12 23:32:55 +000011
Guido van Rossum921c8241992-01-10 14:54:42 +000012
13import string
14import sys
15import linecache
Guido van Rossum6fe08b01992-01-16 13:50:21 +000016from cmd import Cmd
Guido van Rossum921c8241992-01-10 14:54:42 +000017
18
19# A specialization of Cmd for use by the debugger
20
Guido van Rossumb9142571992-01-12 23:32:55 +000021PdbQuit = 'pdb.PdbQuit' # Exception to give up
Guido van Rossum921c8241992-01-10 14:54:42 +000022
23class Pdb(Cmd):
24
25 def init(self):
26 self = Cmd.init(self)
27 self.prompt = '(Pdb) '
28 self.reset()
Guido van Rossum921c8241992-01-10 14:54:42 +000029 return self
30
31 def reset(self):
Guido van Rossum6fe08b01992-01-16 13:50:21 +000032 self.quitting = 0
Guido van Rossumb9142571992-01-12 23:32:55 +000033 self.breaks = {}
Guido van Rossum921c8241992-01-10 14:54:42 +000034 self.botframe = None
Guido van Rossumb9142571992-01-12 23:32:55 +000035 self.stopframe = None
Guido van Rossum7ac1c811992-01-16 13:55:21 +000036 self.lastretval = None
Guido van Rossum921c8241992-01-10 14:54:42 +000037 self.forget()
38
39 def forget(self):
Guido van Rossum6fe08b01992-01-16 13:50:21 +000040 self.setup(None, None)
Guido van Rossum921c8241992-01-10 14:54:42 +000041
Guido van Rossum6fe08b01992-01-16 13:50:21 +000042 def setup(self, f, t):
Guido van Rossum921c8241992-01-10 14:54:42 +000043 self.lineno = None
Guido van Rossum6fe08b01992-01-16 13:50:21 +000044 self.stack = []
Guido van Rossum7ac1c811992-01-16 13:55:21 +000045 self.curindex = 0
46 self.curframe = None
47 if f is None and t is None:
48 return
Guido van Rossum6fe08b01992-01-16 13:50:21 +000049 if t and t.tb_frame is f:
50 t = t.tb_next
Guido van Rossum7ac1c811992-01-16 13:55:21 +000051 while f is not None:
Guido van Rossum6fe08b01992-01-16 13:50:21 +000052 self.stack.append((f, f.f_lineno))
Guido van Rossum7ac1c811992-01-16 13:55:21 +000053 if f is self.botframe:
54 break
Guido van Rossum6fe08b01992-01-16 13:50:21 +000055 f = f.f_back
Guido van Rossum7ac1c811992-01-16 13:55:21 +000056 else:
57 print '[Weird: bottom frame not in stack trace.]'
Guido van Rossum6fe08b01992-01-16 13:50:21 +000058 self.stack.reverse()
59 self.curindex = max(0, len(self.stack) - 1)
Guido van Rossum7ac1c811992-01-16 13:55:21 +000060 while t is not None:
Guido van Rossum6fe08b01992-01-16 13:50:21 +000061 self.stack.append((t.tb_frame, t.tb_lineno))
62 t = t.tb_next
Guido van Rossum7ac1c811992-01-16 13:55:21 +000063 self.curframe = self.stack[self.curindex][0]
Guido van Rossum921c8241992-01-10 14:54:42 +000064
65 def run(self, cmd):
Guido van Rossumb9142571992-01-12 23:32:55 +000066 import __main__
67 dict = __main__.__dict__
68 self.runctx(cmd, dict, dict)
69
70 def runctx(self, cmd, globals, locals):
Guido van Rossum7ac1c811992-01-16 13:55:21 +000071 t = None
Guido van Rossum921c8241992-01-10 14:54:42 +000072 self.reset()
73 sys.trace = self.dispatch
74 try:
Guido van Rossumb9142571992-01-12 23:32:55 +000075 exec(cmd + '\n', globals, locals)
Guido van Rossum921c8241992-01-10 14:54:42 +000076 except PdbQuit:
Guido van Rossum7ac1c811992-01-16 13:55:21 +000077 return
Guido van Rossum6fe08b01992-01-16 13:50:21 +000078 except:
79 print '***', sys.exc_type + ':', `sys.exc_value`
Guido van Rossum7ac1c811992-01-16 13:55:21 +000080 t = sys.exc_traceback
Guido van Rossum6fe08b01992-01-16 13:50:21 +000081 finally:
Guido van Rossum7ac1c811992-01-16 13:55:21 +000082 self.trace = None
83 del self.trace
84 self.forget()
85 print '!!! Post-mortem debugging'
86 self.pmd(t)
87
88 def pmd(self, traceback):
89 t = traceback
90 if self.botframe is not None:
91 while t is not None:
92 if t.tb_frame is not self.botframe:
93 break
94 t = t.tb_next
95 else:
96 t = sys.exc_traceback
97 try:
98 self.ask_user(self.botframe, t)
99 except PdbQuit:
100 pass
101 finally:
102 self.forget()
Guido van Rossum921c8241992-01-10 14:54:42 +0000103
Guido van Rossumb9142571992-01-12 23:32:55 +0000104 def dispatch(self, frame, event, arg):
Guido van Rossum6fe08b01992-01-16 13:50:21 +0000105 if self.quitting:
106 return None
Guido van Rossumb9142571992-01-12 23:32:55 +0000107 if event == 'line':
108 return self.dispatch_line(frame)
109 if event == 'call':
110 return self.dispatch_call(frame, arg)
111 if event == 'return':
112 return self.dispatch_return(frame, arg)
113 if event == 'exception':
114 return self.dispatch_exception(frame, arg)
115 print '*** dispatch: unknown event type', `event`
Guido van Rossum921c8241992-01-10 14:54:42 +0000116 return self.dispatch
117
Guido van Rossumb9142571992-01-12 23:32:55 +0000118 def dispatch_line(self, frame):
119 if self.stop_here(frame) or self.break_here(frame):
Guido van Rossum6fe08b01992-01-16 13:50:21 +0000120 self.ask_user(frame, None)
Guido van Rossumb9142571992-01-12 23:32:55 +0000121 return self.dispatch
122
123 def dispatch_call(self, frame, arg):
124 if self.botframe is None:
Guido van Rossum7ac1c811992-01-16 13:55:21 +0000125 # First call dispatch since reset()
Guido van Rossumb9142571992-01-12 23:32:55 +0000126 self.botframe = frame
Guido van Rossum7ac1c811992-01-16 13:55:21 +0000127 return None
Guido van Rossumb9142571992-01-12 23:32:55 +0000128 if not (self.stop_here(frame) or self.break_anywhere(frame)):
Guido van Rossum7ac1c811992-01-16 13:55:21 +0000129 return None
130 if arg is None:
131 print '[Entering non-function block.]'
132 else:
133 frame.f_locals['__args__'] = arg
Guido van Rossumb9142571992-01-12 23:32:55 +0000134 return self.dispatch
135
136 def dispatch_return(self, frame, arg):
Guido van Rossum7ac1c811992-01-16 13:55:21 +0000137 self.lastretval = arg
138 return None
Guido van Rossumb9142571992-01-12 23:32:55 +0000139
140 def dispatch_exception(self, frame, arg):
Guido van Rossumb9142571992-01-12 23:32:55 +0000141 if self.stop_here(frame):
Guido van Rossum7ac1c811992-01-16 13:55:21 +0000142 print '!!!', arg[0] + ':', `arg[1]`
Guido van Rossum6fe08b01992-01-16 13:50:21 +0000143 self.ask_user(frame, arg[2])
Guido van Rossumb9142571992-01-12 23:32:55 +0000144 return self.dispatch
145
146 def stop_here(self, frame):
147 if self.stopframe is None:
148 return 1
149 if frame is self.stopframe:
150 return 1
Guido van Rossum6fe08b01992-01-16 13:50:21 +0000151 while frame is not None and frame is not self.stopframe:
152 if frame is self.botframe:
Guido van Rossumb9142571992-01-12 23:32:55 +0000153 return 1
154 frame = frame.f_back
155 return 0
156
157 def break_here(self, frame):
158 if not self.breaks.has_key(frame.f_code.co_filename):
159 return 0
160 if not frame.f_lineno in \
161 self.breaks[frame.f_code.co_filename]:
162 return 0
163 return 1
164
165 def break_anywhere(self, frame):
166 return self.breaks.has_key(frame.f_code.co_filename)
167
Guido van Rossum6fe08b01992-01-16 13:50:21 +0000168 def ask_user(self, frame, traceback):
169 self.setup(frame, traceback)
170 self.printframelineno(self.stack[self.curindex])
171 self.cmdloop()
Guido van Rossumb9142571992-01-12 23:32:55 +0000172 self.forget()
Guido van Rossum921c8241992-01-10 14:54:42 +0000173
174 def default(self, line):
175 if not line:
Guido van Rossumb9142571992-01-12 23:32:55 +0000176 return self.do_next('')
Guido van Rossum921c8241992-01-10 14:54:42 +0000177 else:
178 if line[0] == '!': line = line[1:]
179 try:
180 exec(line + '\n', \
181 self.curframe.f_globals, \
182 self.curframe.f_locals)
183 except:
Guido van Rossumb9142571992-01-12 23:32:55 +0000184 print '***', sys.exc_type + ':',
Guido van Rossum921c8241992-01-10 14:54:42 +0000185 print `sys.exc_value`
186
187 do_h = Cmd.do_help
188
189 def do_break(self, arg):
190 if not arg:
191 print self.breaks # XXX
192 return
193 try:
194 lineno = int(eval(arg))
195 except:
196 print '*** Error in argument:', `arg`
197 return
198 filename = self.curframe.f_code.co_filename
199 line = linecache.getline(filename, lineno)
200 if not line:
201 print '*** That line does not exist!'
202 return
203 if not self.breaks.has_key(filename):
204 self.breaks[filename] = []
205 list = self.breaks[filename]
206 if lineno in list:
207 print '*** There is already a break there!'
208 return
209 list.append(lineno)
210 do_b = do_break
211
212 def do_clear(self, arg):
213 if not arg:
Guido van Rossumb9142571992-01-12 23:32:55 +0000214 try:
215 reply = raw_input('Clear all breaks? ')
216 except EOFError:
217 reply = 'no'
218 reply = string.lower(string.strip(reply))
219 if reply in ('y', 'yes'):
220 self.breaks = {}
Guido van Rossum921c8241992-01-10 14:54:42 +0000221 return
222 try:
223 lineno = int(eval(arg))
224 except:
225 print '*** Error in argument:', `arg`
226 return
227 filename = self.curframe.f_code.co_filename
228 try:
229 self.breaks[filename].remove(lineno)
Guido van Rossum921c8241992-01-10 14:54:42 +0000230 except (ValueError, KeyError):
231 print '*** There is no break there!'
232 return
Guido van Rossumb9142571992-01-12 23:32:55 +0000233 if not self.breaks[filename]:
234 del self.breaks[filename]
235 do_cl = do_clear # 'c' is already an abbreviation for 'continue'
Guido van Rossum921c8241992-01-10 14:54:42 +0000236
237 def do_where(self, arg):
Guido van Rossum6fe08b01992-01-16 13:50:21 +0000238 self.printstacktrace()
Guido van Rossum921c8241992-01-10 14:54:42 +0000239 do_w = do_where
240
241 def do_up(self, arg):
Guido van Rossum6fe08b01992-01-16 13:50:21 +0000242 if self.curindex == 0:
243 print '*** Oldest frame'
Guido van Rossum921c8241992-01-10 14:54:42 +0000244 else:
Guido van Rossum6fe08b01992-01-16 13:50:21 +0000245 self.curindex = self.curindex - 1
246 self.curframe = self.stack[self.curindex][0]
247 self.printframelineno(self.stack[self.curindex])
Guido van Rossumb9142571992-01-12 23:32:55 +0000248 do_u = do_up
249
250 def do_down(self, arg):
Guido van Rossum6fe08b01992-01-16 13:50:21 +0000251 if self.curindex + 1 == len(self.stack):
252 print '*** Newest frame'
Guido van Rossumb9142571992-01-12 23:32:55 +0000253 else:
Guido van Rossum6fe08b01992-01-16 13:50:21 +0000254 self.curindex = self.curindex + 1
255 self.curframe = self.stack[self.curindex][0]
256 self.printframelineno(self.stack[self.curindex])
Guido van Rossum921c8241992-01-10 14:54:42 +0000257 do_d = do_down
258
259 def do_step(self, arg):
Guido van Rossumb9142571992-01-12 23:32:55 +0000260 self.stopframe = None
261 return 1
Guido van Rossum921c8241992-01-10 14:54:42 +0000262 do_s = do_step
263
264 def do_next(self, arg):
Guido van Rossumb9142571992-01-12 23:32:55 +0000265 self.stopframe = self.curframe
266 return 1
Guido van Rossum921c8241992-01-10 14:54:42 +0000267 do_n = do_next
268
Guido van Rossumb9142571992-01-12 23:32:55 +0000269 def do_return(self, arg):
270 self.stopframe = self.curframe.f_back
271 return 1
272 do_r = do_return
273
Guido van Rossum7ac1c811992-01-16 13:55:21 +0000274 def do_retval(self, arg):
275 print self.lastretval
276 do_rv = do_retval
277
Guido van Rossum921c8241992-01-10 14:54:42 +0000278 def do_continue(self, arg):
Guido van Rossumb9142571992-01-12 23:32:55 +0000279 self.stopframe = self.botframe
280 return 1
Guido van Rossum921c8241992-01-10 14:54:42 +0000281 do_c = do_cont = do_continue
282
283 def do_quit(self, arg):
Guido van Rossum6fe08b01992-01-16 13:50:21 +0000284 self.quitting = 1
285 sys.trace = None; del sys.trace
Guido van Rossumb9142571992-01-12 23:32:55 +0000286 raise PdbQuit
Guido van Rossum921c8241992-01-10 14:54:42 +0000287 do_q = do_quit
288
289 def do_list(self, arg):
Guido van Rossumb9142571992-01-12 23:32:55 +0000290 self.lastcmd = 'list'
Guido van Rossum921c8241992-01-10 14:54:42 +0000291 last = None
292 if arg:
293 try:
294 x = eval(arg, {}, {})
295 if type(x) == type(()):
296 first, last = x
297 first = int(first)
298 last = int(last)
299 if last < first:
300 # Assume it's a count
301 last = first + last
302 else:
303 first = int(x)
304 except:
305 print '*** Error in argument:', `arg`
306 return
307 elif self.lineno is None:
308 first = max(1, self.curframe.f_lineno - 5)
309 else:
310 first = self.lineno + 1
311 if last is None:
312 last = first + 10
313 filename = self.curframe.f_code.co_filename
314 if self.breaks.has_key(filename):
315 breaklist = self.breaks[filename]
316 else:
317 breaklist = []
318 try:
319 for lineno in range(first, last+1):
320 line = linecache.getline(filename, lineno)
321 if not line:
322 print '[EOF]'
323 break
324 else:
325 s = string.rjust(`lineno`, 3)
326 if len(s) < 4: s = s + ' '
327 if lineno in breaklist: s = s + 'B'
328 else: s = s + ' '
329 if lineno == self.curframe.f_lineno:
330 s = s + '->'
331 print s + '\t' + line,
332 self.lineno = lineno
333 except KeyboardInterrupt:
334 pass
335 do_l = do_list
Guido van Rossumb9142571992-01-12 23:32:55 +0000336
337 def do_args(self, arg):
338 try:
339 value = eval('__args__', self.curframe.f_globals, \
340 self.curframe.f_locals)
341 except:
342 print '***', sys.exc_type + ':', `sys.exc_value`
343 return
344 print `value`
345 do_a = do_args
346
347 def do_p(self, arg):
348 try:
349 value = eval(arg, self.curframe.f_globals, \
350 self.curframe.f_locals)
351 except:
352 print '***', sys.exc_type + ':', `sys.exc_value`
353 return
354 print `value`
Guido van Rossum921c8241992-01-10 14:54:42 +0000355
Guido van Rossum6fe08b01992-01-16 13:50:21 +0000356 # Print a traceback starting at the top stack frame.
357 # Note that the most recently entered frame is printed last;
358 # this is different from dbx and gdb, but consistent with
359 # the Python interpreter's stack trace.
360 # It is also consistent with the up/down commands (which are
361 # compatible with dbx and gdb: up moves towards 'main()'
362 # and down moves towards the most recent stack frame).
Guido van Rossum921c8241992-01-10 14:54:42 +0000363
Guido van Rossum6fe08b01992-01-16 13:50:21 +0000364 def printstacktrace(self):
365 for x in self.stack:
366 self.printframelineno(x)
367
368 def printframelineno(self, (frame, lineno)):
Guido van Rossum921c8241992-01-10 14:54:42 +0000369 if frame is self.curframe: print '->',
370 code = frame.f_code
371 filename = code.co_filename
Guido van Rossum921c8241992-01-10 14:54:42 +0000372 print filename + '(' + `lineno` + ')',
373 line = linecache.getline(filename, lineno)
Guido van Rossum6fe08b01992-01-16 13:50:21 +0000374 print string.strip(line),
Guido van Rossum921c8241992-01-10 14:54:42 +0000375 print
376
377
Guido van Rossum6fe08b01992-01-16 13:50:21 +0000378def run(statement):
379 Pdb().init().run(statement)
380
381def runctx(statement, globals, locals):
382 Pdb().init().runctx(statement, globals, locals)
383
384
Guido van Rossum921c8241992-01-10 14:54:42 +0000385# --------------------- testing ---------------------
386
387# The Ackermann function -- a highly recursive beast
Guido van Rossum6fe08b01992-01-16 13:50:21 +0000388cheat = 2
Guido van Rossum921c8241992-01-10 14:54:42 +0000389cache = {}
390def ack(x, y):
391 key = `(long(x), long(y))`
392 if cache.has_key(key):
393 res = cache[key]
394 else:
395 if x == 0:
396 res = 1L
397 elif y == 0:
398 if x == 1:
399 res = 2L
400 else:
401 res = 2L + x
402 elif y == 1 and cheat >= 1:
403 res = 2L * x
404 elif y == 2 and cheat >= 2:
405 res = pow(2L, x)
406 else:
407 res = ack(ack(x-1, y), y-1)
408 cache[key] = res
409 return res
410
411def foo(n):
412 print 'foo', n
413 x = bar(n*2)
414 print 'bar returned', x
Guido van Rossum6fe08b01992-01-16 13:50:21 +0000415 y = ack(4, 3)
416 return y
Guido van Rossum921c8241992-01-10 14:54:42 +0000417
418def bar(a):
419 print 'bar', a
420 return a*10
421
Guido van Rossum6fe08b01992-01-16 13:50:21 +0000422def melt(n):
423 print 1.0/n
424 melt(n-1)
425
Guido van Rossum921c8241992-01-10 14:54:42 +0000426def test():
427 linecache.checkcache()
Guido van Rossum6fe08b01992-01-16 13:50:21 +0000428 runctx('from pdb import foo; foo(12)', {}, {})
429 runctx('from pdb import melt; melt(5)', {}, {})
Guido van Rossum921c8241992-01-10 14:54:42 +0000430
431
432# --------------------- main ---------------------
433
434import os
435
436def main():
437 if sys.argv[1:]:
438 file = sys.argv[1]
439 head, tail = os.path.split(file)
440 if tail[-3:] != '.py':
441 print 'Sorry, file arg must be a python module'
442 print '(i.e., must end in \'.py\')'
443 # XXX Or we could copy it to a temp file
444 sys.exit(2)
445 del sys.argv[0]
446 sys.path.insert(0, head)
Guido van Rossumb9142571992-01-12 23:32:55 +0000447 run('import ' + tail[:-3])
Guido van Rossum921c8241992-01-10 14:54:42 +0000448 else:
Guido van Rossum6fe08b01992-01-16 13:50:21 +0000449 run(raw_input('Python statement to debug: '))