Remove uses of cmp from the decimal module.
[python.git] / Lib / bdb.py
blobf29fa46b5b8e20017a8f74ef12d062ca40d737b0
1 """Debugger basics"""
3 import sys
4 import os
5 import types
7 __all__ = ["BdbQuit","Bdb","Breakpoint"]
9 class BdbQuit(Exception):
10 """Exception to give up completely"""
13 class Bdb:
15 """Generic Python debugger base class.
17 This class takes care of details of the trace facility;
18 a derived class should implement user interaction.
19 The standard debugger class (pdb.Pdb) is an example.
20 """
22 def __init__(self):
23 self.breaks = {}
24 self.fncache = {}
26 def canonic(self, filename):
27 if filename == "<" + filename[1:-1] + ">":
28 return filename
29 canonic = self.fncache.get(filename)
30 if not canonic:
31 canonic = os.path.abspath(filename)
32 canonic = os.path.normcase(canonic)
33 self.fncache[filename] = canonic
34 return canonic
36 def reset(self):
37 import linecache
38 linecache.checkcache()
39 self.botframe = None
40 self._set_stopinfo(None, None)
42 def trace_dispatch(self, frame, event, arg):
43 if self.quitting:
44 return # None
45 if event == 'line':
46 return self.dispatch_line(frame)
47 if event == 'call':
48 return self.dispatch_call(frame, arg)
49 if event == 'return':
50 return self.dispatch_return(frame, arg)
51 if event == 'exception':
52 return self.dispatch_exception(frame, arg)
53 if event == 'c_call':
54 return self.trace_dispatch
55 if event == 'c_exception':
56 return self.trace_dispatch
57 if event == 'c_return':
58 return self.trace_dispatch
59 print 'bdb.Bdb.dispatch: unknown debugging event:', repr(event)
60 return self.trace_dispatch
62 def dispatch_line(self, frame):
63 if self.stop_here(frame) or self.break_here(frame):
64 self.user_line(frame)
65 if self.quitting: raise BdbQuit
66 return self.trace_dispatch
68 def dispatch_call(self, frame, arg):
69 # XXX 'arg' is no longer used
70 if self.botframe is None:
71 # First call of dispatch since reset()
72 self.botframe = frame.f_back # (CT) Note that this may also be None!
73 return self.trace_dispatch
74 if not (self.stop_here(frame) or self.break_anywhere(frame)):
75 # No need to trace this function
76 return # None
77 self.user_call(frame, arg)
78 if self.quitting: raise BdbQuit
79 return self.trace_dispatch
81 def dispatch_return(self, frame, arg):
82 if self.stop_here(frame) or frame == self.returnframe:
83 self.user_return(frame, arg)
84 if self.quitting: raise BdbQuit
85 return self.trace_dispatch
87 def dispatch_exception(self, frame, arg):
88 if self.stop_here(frame):
89 self.user_exception(frame, arg)
90 if self.quitting: raise BdbQuit
91 return self.trace_dispatch
93 # Normally derived classes don't override the following
94 # methods, but they may if they want to redefine the
95 # definition of stopping and breakpoints.
97 def stop_here(self, frame):
98 # (CT) stopframe may now also be None, see dispatch_call.
99 # (CT) the former test for None is therefore removed from here.
100 if frame is self.stopframe:
101 return frame.f_lineno >= self.stoplineno
102 while frame is not None and frame is not self.stopframe:
103 if frame is self.botframe:
104 return True
105 frame = frame.f_back
106 return False
108 def break_here(self, frame):
109 filename = self.canonic(frame.f_code.co_filename)
110 if not filename in self.breaks:
111 return False
112 lineno = frame.f_lineno
113 if not lineno in self.breaks[filename]:
114 # The line itself has no breakpoint, but maybe the line is the
115 # first line of a function with breakpoint set by function name.
116 lineno = frame.f_code.co_firstlineno
117 if not lineno in self.breaks[filename]:
118 return False
120 # flag says ok to delete temp. bp
121 (bp, flag) = effective(filename, lineno, frame)
122 if bp:
123 self.currentbp = bp.number
124 if (flag and bp.temporary):
125 self.do_clear(str(bp.number))
126 return True
127 else:
128 return False
130 def do_clear(self, arg):
131 raise NotImplementedError, "subclass of bdb must implement do_clear()"
133 def break_anywhere(self, frame):
134 return self.canonic(frame.f_code.co_filename) in self.breaks
136 # Derived classes should override the user_* methods
137 # to gain control.
139 def user_call(self, frame, argument_list):
140 """This method is called when there is the remote possibility
141 that we ever need to stop in this function."""
142 pass
144 def user_line(self, frame):
145 """This method is called when we stop or break at this line."""
146 pass
148 def user_return(self, frame, return_value):
149 """This method is called when a return trap is set here."""
150 pass
152 def user_exception(self, frame, exc_info):
153 exc_type, exc_value, exc_traceback = exc_info
154 """This method is called if an exception occurs,
155 but only if we are to stop at or just below this level."""
156 pass
158 def _set_stopinfo(self, stopframe, returnframe, stoplineno=-1):
159 self.stopframe = stopframe
160 self.returnframe = returnframe
161 self.quitting = 0
162 self.stoplineno = stoplineno
164 # Derived classes and clients can call the following methods
165 # to affect the stepping state.
167 def set_until(self, frame): #the name "until" is borrowed from gdb
168 """Stop when the line with the line no greater than the current one is
169 reached or when returning from current frame"""
170 self._set_stopinfo(frame, frame, frame.f_lineno+1)
172 def set_step(self):
173 """Stop after one line of code."""
174 self._set_stopinfo(None,None)
176 def set_next(self, frame):
177 """Stop on the next line in or below the given frame."""
178 self._set_stopinfo(frame, None)
180 def set_return(self, frame):
181 """Stop when returning from the given frame."""
182 self._set_stopinfo(frame.f_back, frame)
184 def set_trace(self, frame=None):
185 """Start debugging from `frame`.
187 If frame is not specified, debugging starts from caller's frame.
189 if frame is None:
190 frame = sys._getframe().f_back
191 self.reset()
192 while frame:
193 frame.f_trace = self.trace_dispatch
194 self.botframe = frame
195 frame = frame.f_back
196 self.set_step()
197 sys.settrace(self.trace_dispatch)
199 def set_continue(self):
200 # Don't stop except at breakpoints or when finished
201 self._set_stopinfo(self.botframe, None)
202 if not self.breaks:
203 # no breakpoints; run without debugger overhead
204 sys.settrace(None)
205 frame = sys._getframe().f_back
206 while frame and frame is not self.botframe:
207 del frame.f_trace
208 frame = frame.f_back
210 def set_quit(self):
211 self.stopframe = self.botframe
212 self.returnframe = None
213 self.quitting = 1
214 sys.settrace(None)
216 # Derived classes and clients can call the following methods
217 # to manipulate breakpoints. These methods return an
218 # error message is something went wrong, None if all is well.
219 # Set_break prints out the breakpoint line and file:lineno.
220 # Call self.get_*break*() to see the breakpoints or better
221 # for bp in Breakpoint.bpbynumber: if bp: bp.bpprint().
223 def set_break(self, filename, lineno, temporary=0, cond = None,
224 funcname=None):
225 filename = self.canonic(filename)
226 import linecache # Import as late as possible
227 line = linecache.getline(filename, lineno)
228 if not line:
229 return 'Line %s:%d does not exist' % (filename,
230 lineno)
231 if not filename in self.breaks:
232 self.breaks[filename] = []
233 list = self.breaks[filename]
234 if not lineno in list:
235 list.append(lineno)
236 bp = Breakpoint(filename, lineno, temporary, cond, funcname)
238 def clear_break(self, filename, lineno):
239 filename = self.canonic(filename)
240 if not filename in self.breaks:
241 return 'There are no breakpoints in %s' % filename
242 if lineno not in self.breaks[filename]:
243 return 'There is no breakpoint at %s:%d' % (filename,
244 lineno)
245 # If there's only one bp in the list for that file,line
246 # pair, then remove the breaks entry
247 for bp in Breakpoint.bplist[filename, lineno][:]:
248 bp.deleteMe()
249 if not Breakpoint.bplist.has_key((filename, lineno)):
250 self.breaks[filename].remove(lineno)
251 if not self.breaks[filename]:
252 del self.breaks[filename]
254 def clear_bpbynumber(self, arg):
255 try:
256 number = int(arg)
257 except:
258 return 'Non-numeric breakpoint number (%s)' % arg
259 try:
260 bp = Breakpoint.bpbynumber[number]
261 except IndexError:
262 return 'Breakpoint number (%d) out of range' % number
263 if not bp:
264 return 'Breakpoint (%d) already deleted' % number
265 self.clear_break(bp.file, bp.line)
267 def clear_all_file_breaks(self, filename):
268 filename = self.canonic(filename)
269 if not filename in self.breaks:
270 return 'There are no breakpoints in %s' % filename
271 for line in self.breaks[filename]:
272 blist = Breakpoint.bplist[filename, line]
273 for bp in blist:
274 bp.deleteMe()
275 del self.breaks[filename]
277 def clear_all_breaks(self):
278 if not self.breaks:
279 return 'There are no breakpoints'
280 for bp in Breakpoint.bpbynumber:
281 if bp:
282 bp.deleteMe()
283 self.breaks = {}
285 def get_break(self, filename, lineno):
286 filename = self.canonic(filename)
287 return filename in self.breaks and \
288 lineno in self.breaks[filename]
290 def get_breaks(self, filename, lineno):
291 filename = self.canonic(filename)
292 return filename in self.breaks and \
293 lineno in self.breaks[filename] and \
294 Breakpoint.bplist[filename, lineno] or []
296 def get_file_breaks(self, filename):
297 filename = self.canonic(filename)
298 if filename in self.breaks:
299 return self.breaks[filename]
300 else:
301 return []
303 def get_all_breaks(self):
304 return self.breaks
306 # Derived classes and clients can call the following method
307 # to get a data structure representing a stack trace.
309 def get_stack(self, f, t):
310 stack = []
311 if t and t.tb_frame is f:
312 t = t.tb_next
313 while f is not None:
314 stack.append((f, f.f_lineno))
315 if f is self.botframe:
316 break
317 f = f.f_back
318 stack.reverse()
319 i = max(0, len(stack) - 1)
320 while t is not None:
321 stack.append((t.tb_frame, t.tb_lineno))
322 t = t.tb_next
323 if f is None:
324 i = max(0, len(stack) - 1)
325 return stack, i
329 def format_stack_entry(self, frame_lineno, lprefix=': '):
330 import linecache, repr
331 frame, lineno = frame_lineno
332 filename = self.canonic(frame.f_code.co_filename)
333 s = '%s(%r)' % (filename, lineno)
334 if frame.f_code.co_name:
335 s = s + frame.f_code.co_name
336 else:
337 s = s + "<lambda>"
338 if '__args__' in frame.f_locals:
339 args = frame.f_locals['__args__']
340 else:
341 args = None
342 if args:
343 s = s + repr.repr(args)
344 else:
345 s = s + '()'
346 if '__return__' in frame.f_locals:
347 rv = frame.f_locals['__return__']
348 s = s + '->'
349 s = s + repr.repr(rv)
350 line = linecache.getline(filename, lineno, frame.f_globals)
351 if line: s = s + lprefix + line.strip()
352 return s
354 # The following two methods can be called by clients to use
355 # a debugger to debug a statement, given as a string.
357 def run(self, cmd, globals=None, locals=None):
358 if globals is None:
359 import __main__
360 globals = __main__.__dict__
361 if locals is None:
362 locals = globals
363 self.reset()
364 sys.settrace(self.trace_dispatch)
365 if not isinstance(cmd, types.CodeType):
366 cmd = cmd+'\n'
367 try:
368 exec cmd in globals, locals
369 except BdbQuit:
370 pass
371 finally:
372 self.quitting = 1
373 sys.settrace(None)
375 def runeval(self, expr, globals=None, locals=None):
376 if globals is None:
377 import __main__
378 globals = __main__.__dict__
379 if locals is None:
380 locals = globals
381 self.reset()
382 sys.settrace(self.trace_dispatch)
383 if not isinstance(expr, types.CodeType):
384 expr = expr+'\n'
385 try:
386 return eval(expr, globals, locals)
387 except BdbQuit:
388 pass
389 finally:
390 self.quitting = 1
391 sys.settrace(None)
393 def runctx(self, cmd, globals, locals):
394 # B/W compatibility
395 self.run(cmd, globals, locals)
397 # This method is more useful to debug a single function call.
399 def runcall(self, func, *args, **kwds):
400 self.reset()
401 sys.settrace(self.trace_dispatch)
402 res = None
403 try:
404 res = func(*args, **kwds)
405 except BdbQuit:
406 pass
407 finally:
408 self.quitting = 1
409 sys.settrace(None)
410 return res
413 def set_trace():
414 Bdb().set_trace()
417 class Breakpoint:
419 """Breakpoint class
421 Implements temporary breakpoints, ignore counts, disabling and
422 (re)-enabling, and conditionals.
424 Breakpoints are indexed by number through bpbynumber and by
425 the file,line tuple using bplist. The former points to a
426 single instance of class Breakpoint. The latter points to a
427 list of such instances since there may be more than one
428 breakpoint per line.
432 # XXX Keeping state in the class is a mistake -- this means
433 # you cannot have more than one active Bdb instance.
435 next = 1 # Next bp to be assigned
436 bplist = {} # indexed by (file, lineno) tuple
437 bpbynumber = [None] # Each entry is None or an instance of Bpt
438 # index 0 is unused, except for marking an
439 # effective break .... see effective()
441 def __init__(self, file, line, temporary=0, cond=None, funcname=None):
442 self.funcname = funcname
443 # Needed if funcname is not None.
444 self.func_first_executable_line = None
445 self.file = file # This better be in canonical form!
446 self.line = line
447 self.temporary = temporary
448 self.cond = cond
449 self.enabled = 1
450 self.ignore = 0
451 self.hits = 0
452 self.number = Breakpoint.next
453 Breakpoint.next = Breakpoint.next + 1
454 # Build the two lists
455 self.bpbynumber.append(self)
456 if self.bplist.has_key((file, line)):
457 self.bplist[file, line].append(self)
458 else:
459 self.bplist[file, line] = [self]
462 def deleteMe(self):
463 index = (self.file, self.line)
464 self.bpbynumber[self.number] = None # No longer in list
465 self.bplist[index].remove(self)
466 if not self.bplist[index]:
467 # No more bp for this f:l combo
468 del self.bplist[index]
470 def enable(self):
471 self.enabled = 1
473 def disable(self):
474 self.enabled = 0
476 def bpprint(self, out=None):
477 if out is None:
478 out = sys.stdout
479 if self.temporary:
480 disp = 'del '
481 else:
482 disp = 'keep '
483 if self.enabled:
484 disp = disp + 'yes '
485 else:
486 disp = disp + 'no '
487 print >>out, '%-4dbreakpoint %s at %s:%d' % (self.number, disp,
488 self.file, self.line)
489 if self.cond:
490 print >>out, '\tstop only if %s' % (self.cond,)
491 if self.ignore:
492 print >>out, '\tignore next %d hits' % (self.ignore)
493 if (self.hits):
494 if (self.hits > 1): ss = 's'
495 else: ss = ''
496 print >>out, ('\tbreakpoint already hit %d time%s' %
497 (self.hits, ss))
499 # -----------end of Breakpoint class----------
501 def checkfuncname(b, frame):
502 """Check whether we should break here because of `b.funcname`."""
503 if not b.funcname:
504 # Breakpoint was set via line number.
505 if b.line != frame.f_lineno:
506 # Breakpoint was set at a line with a def statement and the function
507 # defined is called: don't break.
508 return False
509 return True
511 # Breakpoint set via function name.
513 if frame.f_code.co_name != b.funcname:
514 # It's not a function call, but rather execution of def statement.
515 return False
517 # We are in the right frame.
518 if not b.func_first_executable_line:
519 # The function is entered for the 1st time.
520 b.func_first_executable_line = frame.f_lineno
522 if b.func_first_executable_line != frame.f_lineno:
523 # But we are not at the first line number: don't break.
524 return False
525 return True
527 # Determines if there is an effective (active) breakpoint at this
528 # line of code. Returns breakpoint number or 0 if none
529 def effective(file, line, frame):
530 """Determine which breakpoint for this file:line is to be acted upon.
532 Called only if we know there is a bpt at this
533 location. Returns breakpoint that was triggered and a flag
534 that indicates if it is ok to delete a temporary bp.
537 possibles = Breakpoint.bplist[file,line]
538 for i in range(0, len(possibles)):
539 b = possibles[i]
540 if b.enabled == 0:
541 continue
542 if not checkfuncname(b, frame):
543 continue
544 # Count every hit when bp is enabled
545 b.hits = b.hits + 1
546 if not b.cond:
547 # If unconditional, and ignoring,
548 # go on to next, else break
549 if b.ignore > 0:
550 b.ignore = b.ignore -1
551 continue
552 else:
553 # breakpoint and marker that's ok
554 # to delete if temporary
555 return (b,1)
556 else:
557 # Conditional bp.
558 # Ignore count applies only to those bpt hits where the
559 # condition evaluates to true.
560 try:
561 val = eval(b.cond, frame.f_globals,
562 frame.f_locals)
563 if val:
564 if b.ignore > 0:
565 b.ignore = b.ignore -1
566 # continue
567 else:
568 return (b,1)
569 # else:
570 # continue
571 except:
572 # if eval fails, most conservative
573 # thing is to stop on breakpoint
574 # regardless of ignore count.
575 # Don't delete temporary,
576 # as another hint to user.
577 return (b,0)
578 return (None, None)
580 # -------------------- testing --------------------
582 class Tdb(Bdb):
583 def user_call(self, frame, args):
584 name = frame.f_code.co_name
585 if not name: name = '???'
586 print '+++ call', name, args
587 def user_line(self, frame):
588 import linecache
589 name = frame.f_code.co_name
590 if not name: name = '???'
591 fn = self.canonic(frame.f_code.co_filename)
592 line = linecache.getline(fn, frame.f_lineno, frame.f_globals)
593 print '+++', fn, frame.f_lineno, name, ':', line.strip()
594 def user_return(self, frame, retval):
595 print '+++ return', retval
596 def user_exception(self, frame, exc_stuff):
597 print '+++ exception', exc_stuff
598 self.set_continue()
600 def foo(n):
601 print 'foo(', n, ')'
602 x = bar(n*10)
603 print 'bar returned', x
605 def bar(a):
606 print 'bar(', a, ')'
607 return a/2
609 def test():
610 t = Tdb()
611 t.run('import bdb; bdb.foo(10)')
613 # end