7 __all__ = [
"BdbQuit",
"Bdb",
"Breakpoint"]
9 BdbQuit =
'bdb.BdbQuit'
14 """Generic Python debugger base class.
16 This class takes care of details of the trace facility;
17 a derived class should implement user interaction.
18 The standard debugger class (pdb.Pdb) is an example.
26 if filename ==
"<" + filename[1:-1] +
">":
28 canonic = self.fncache.get(filename)
30 canonic = os.path.abspath(filename)
31 canonic = os.path.normcase(canonic)
32 self.
fncache[filename] = canonic
52 if event ==
'exception':
54 print 'bdb.Bdb.dispatch: unknown debugging event:', `event`
97 while frame
is not None and frame
is not self.
stopframe:
104 filename = self.
canonic(frame.f_code.co_filename)
105 if not self.breaks.has_key(filename):
107 lineno = frame.f_lineno
108 if not lineno
in self.
breaks[filename]:
111 (bp, flag) =
effective(filename, lineno, frame)
114 if (flag
and bp.temporary):
121 raise NotImplementedError,
"subclass of bdb must implement do_clear()"
124 return self.breaks.has_key(
125 self.
canonic(frame.f_code.co_filename))
131 """This method is called when there is the remote possibility
132 that we ever need to stop in this function."""
136 """This method is called when we stop or break at this line."""
140 """This method is called when a return trap is set here."""
144 """This method is called if an exception occurs,
145 but only if we are to stop at or just below this level."""
152 """Stop after one line of code."""
158 """Stop on the next line in or below the given frame."""
164 """Stop when returning from the given frame."""
170 """Start debugging from here."""
174 frame = sys.exc_info()[2].tb_frame.f_back
194 frame = sys.exc_info()[2].tb_frame.f_back
195 while frame
and frame
is not self.
botframe:
212 def set_break(self, filename, lineno, temporary=0, cond = None):
213 filename = self.
canonic(filename)
217 return 'Line %s:%d does not exist' % (filename,
219 if not self.breaks.has_key(filename):
220 self.
breaks[filename] = []
221 list = self.
breaks[filename]
222 if not lineno
in list:
224 bp =
Breakpoint(filename, lineno, temporary, cond)
227 filename = self.
canonic(filename)
228 if not self.breaks.has_key(filename):
229 return 'There are no breakpoints in %s' % filename
230 if lineno
not in self.
breaks[filename]:
231 return 'There is no breakpoint at %s:%d' % (filename,
235 for bp
in Breakpoint.bplist[filename, lineno][:]:
237 if not Breakpoint.bplist.has_key((filename, lineno)):
238 self.
breaks[filename].remove(lineno)
239 if not self.
breaks[filename]:
246 return 'Non-numeric breakpoint number (%s)' % arg
248 bp = Breakpoint.bpbynumber[number]
250 return 'Breakpoint number (%d) out of range' % number
252 return 'Breakpoint (%d) already deleted' % number
256 filename = self.
canonic(filename)
257 if not self.breaks.has_key(filename):
258 return 'There are no breakpoints in %s' % filename
259 for line
in self.
breaks[filename]:
260 blist = Breakpoint.bplist[filename, line]
267 return 'There are no breakpoints'
268 for bp
in Breakpoint.bpbynumber:
274 filename = self.
canonic(filename)
275 return self.breaks.has_key(filename)
and \
276 lineno
in self.
breaks[filename]
279 filename = self.
canonic(filename)
280 return self.breaks.has_key(filename)
and \
281 lineno
in self.
breaks[filename]
and \
282 Breakpoint.bplist[filename, lineno]
or []
285 filename = self.
canonic(filename)
286 if self.breaks.has_key(filename):
287 return self.
breaks[filename]
299 if t
and t.tb_frame
is f:
302 stack.append((f, f.f_lineno))
307 i =
max(0, len(stack) - 1)
309 stack.append((t.tb_frame, t.tb_lineno))
316 import linecache, repr
317 frame, lineno = frame_lineno
318 filename = self.
canonic(frame.f_code.co_filename)
319 s = filename +
'(' + `lineno` +
')'
320 if frame.f_code.co_name:
321 s = s + frame.f_code.co_name
324 if frame.f_locals.has_key(
'__args__'):
325 args = frame.f_locals[
'__args__']
332 if frame.f_locals.has_key(
'__return__'):
333 rv = frame.f_locals[
'__return__']
337 if line: s = s + lprefix + line.strip()
343 def run(self, cmd, globals=None, locals=None):
346 globals = __main__.__dict__
351 if not isinstance(cmd, types.CodeType):
355 exec cmd
in globals, locals
362 def runeval(self, expr, globals=None, locals=None):
365 globals = __main__.__dict__
370 if not isinstance(expr, types.CodeType):
374 return eval(expr, globals, locals)
383 self.
run(cmd, globals, locals)
393 res = apply(func, args)
410 Implements temporary breakpoints, ignore counts, disabling and
411 (re)-enabling, and conditionals.
413 Breakpoints are indexed by number through bpbynumber and by
414 the file,line tuple using bplist. The former points to a
415 single instance of class Breakpoint. The latter points to a
416 list of such instances since there may be more than one
430 def __init__(self, file, line, temporary=0, cond = None):
439 Breakpoint.next = Breakpoint.next + 1
441 self.bpbynumber.append(self)
442 if self.bplist.has_key((file, line)):
445 self.
bplist[file, line] = [self]
451 self.
bplist[index].remove(self)
452 if not self.
bplist[index]:
471 print '%-4dbreakpoint %s at %s:%d' % (self.
number, disp,
474 print '\tstop only if %s' % (self.
cond,)
476 print '\tignore next %d hits' % (self.
ignore)
478 if (self.
hits > 1): ss =
's'
480 print (
'\tbreakpoint already hit %d time%s' %
488 """Determine which breakpoint for this file:line is to be acted upon.
490 Called only if we know there is a bpt at this
491 location. Returns breakpoint that was triggered and a flag
492 that indicates if it is ok to delete a temporary bp.
495 possibles = Breakpoint.bplist[file,line]
496 for i
in range(0, len(possibles)):
506 b.ignore = b.ignore -1
517 val = eval(b.cond, frame.f_globals,
521 b.ignore = b.ignore -1
540 name = frame.f_code.co_name
541 if not name: name =
'???'
542 print '+++ call', name, args
545 name = frame.f_code.co_name
546 if not name: name =
'???'
547 fn = self.
canonic(frame.f_code.co_filename)
549 print '+++', fn, frame.f_lineno, name,
':', line.strip()
551 print '+++ return', retval
553 print '+++ exception', exc_stuff
559 print 'bar returned', x
567 t.run(
'import bdb; bdb.foo(10)')