This commit was manufactured by cvs2svn to create tag 'mac102'.
[python/dscho.git] / Lib / pdb.py
blob16e14cedd3648bd4ba4491690640e07ea1bc594c
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 g_frame = self.curframe.f_globals
90 try:
91 code = eval(arg, g_frame).func_code
92 except:
93 print '*** Could not eval argument:', arg
94 return
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
101 do_b = do_break
103 def do_clear(self, arg):
104 if not arg:
105 try:
106 reply = raw_input('Clear all breaks? ')
107 except EOFError:
108 reply = 'no'
109 reply = string.lower(string.strip(reply))
110 if reply in ('y', 'yes'):
111 self.clear_all_breaks()
112 return
113 try:
114 lineno = int(eval(arg))
115 except:
116 print '*** Error in argument:', `arg`
117 return
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()
125 do_w = do_where
127 def do_up(self, arg):
128 if self.curindex == 0:
129 print '*** Oldest frame'
130 else:
131 self.curindex = self.curindex - 1
132 self.curframe = self.stack[self.curindex][0]
133 self.print_stack_entry(self.stack[self.curindex])
134 self.lineno = None
135 do_u = do_up
137 def do_down(self, arg):
138 if self.curindex + 1 == len(self.stack):
139 print '*** Newest frame'
140 else:
141 self.curindex = self.curindex + 1
142 self.curframe = self.stack[self.curindex][0]
143 self.print_stack_entry(self.stack[self.curindex])
144 self.lineno = None
145 do_d = do_down
147 def do_step(self, arg):
148 self.set_step()
149 return 1
150 do_s = do_step
152 def do_next(self, arg):
153 self.set_next(self.curframe)
154 return 1
155 do_n = do_next
157 def do_return(self, arg):
158 self.set_return(self.curframe)
159 return 1
160 do_r = do_return
162 def do_continue(self, arg):
163 self.set_continue()
164 return 1
165 do_c = do_cont = do_continue
167 def do_quit(self, arg):
168 self.set_quit()
169 return 1
170 do_q = do_quit
172 def do_args(self, arg):
173 if self.curframe.f_locals.has_key('__return__'):
174 print `self.curframe.f_locals['__return__']`
175 else:
176 print '*** Not arguments?!'
177 do_a = do_args
179 def do_retval(self, arg):
180 if self.curframe.f_locals.has_key('__return__'):
181 print self.curframe.f_locals['__return__']
182 else:
183 print '*** Not yet returned!'
184 do_rv = do_retval
186 def do_p(self, arg):
187 self.curframe.f_globals['__privileged__'] = 1
188 try:
189 value = eval(arg, self.curframe.f_globals, \
190 self.curframe.f_locals)
191 except:
192 print '***', sys.exc_type + ':', `sys.exc_value`
193 return
195 print `value`
197 def do_list(self, arg):
198 self.lastcmd = 'list'
199 last = None
200 if arg:
201 try:
202 x = eval(arg, {}, {})
203 if type(x) == type(()):
204 first, last = x
205 first = int(first)
206 last = int(last)
207 if last < first:
208 # Assume it's a count
209 last = first + last
210 else:
211 first = max(1, int(x) - 5)
212 except:
213 print '*** Error in argument:', `arg`
214 return
215 elif self.lineno is None:
216 first = max(1, self.curframe.f_lineno - 5)
217 else:
218 first = self.lineno + 1
219 if last == None:
220 last = first + 10
221 filename = self.curframe.f_code.co_filename
222 breaklist = self.get_file_breaks(filename)
223 try:
224 for lineno in range(first, last+1):
225 line = linecache.getline(filename, lineno)
226 if not line:
227 print '[EOF]'
228 break
229 else:
230 s = string.rjust(`lineno`, 3)
231 if len(s) < 4: s = s + ' '
232 if lineno in breaklist: s = s + 'B'
233 else: s = s + ' '
234 if lineno == self.curframe.f_lineno:
235 s = s + '->'
236 print s + '\t' + line,
237 self.lineno = lineno
238 except KeyboardInterrupt:
239 pass
240 do_l = do_list
242 def do_whatis(self, arg):
243 try:
244 value = eval(arg, self.curframe.f_globals, \
245 self.curframe.f_locals)
246 except:
247 print '***', sys.exc_type + ':', `sys.exc_value`
248 return
249 code = None
250 # Is it a function?
251 try: code = value.func_code
252 except: pass
253 if code:
254 print 'Function', code.co_name
255 return
256 # Is it an instance method?
257 try: code = value.im_func.func_code
258 except: pass
259 if code:
260 print 'Method', code.co_name
261 return
262 # None of the above...
263 print type(value)
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):
274 try:
275 for frame_lineno in self.stack:
276 self.print_stack_entry(frame_lineno)
277 except KeyboardInterrupt:
278 pass
280 def print_stack_entry(self, frame_lineno):
281 frame, lineno = frame_lineno
282 if frame is self.curframe:
283 print '>',
284 else:
285 print ' ',
286 print self.format_stack_entry(frame_lineno)
289 # Simplified interface
291 def run(statement):
292 Pdb().run(statement)
294 def runctx(statement, globals, locals):
295 Pdb().runctx(statement, globals, locals)
297 def runcall(*args):
298 apply(Pdb().runcall, args)
301 # Post-Mortem interface
303 def post_mortem(t):
304 p = Pdb()
305 p.reset()
306 while t.tb_next <> None: t = t.tb_next
307 p.interaction(t.tb_frame, t)
309 def pm():
310 import sys
311 post_mortem(sys.last_traceback)
314 # Main program for testing
316 TESTCMD = 'import x; x.main()'
318 def test():
319 run(TESTCMD)
321 # print help
322 def help():
323 import os
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
329 break
330 else:
331 print 'Sorry, can\'t find the help file "pdb.doc"',
332 print 'along the Python search path'