7 __all__
= ["BdbQuit","Bdb","Breakpoint"]
9 class BdbQuit(Exception):
10 """Exception to give up completely"""
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.
26 def canonic(self
, filename
):
27 if filename
== "<" + filename
[1:-1] + ">":
29 canonic
= self
.fncache
.get(filename
)
31 canonic
= os
.path
.abspath(filename
)
32 canonic
= os
.path
.normcase(canonic
)
33 self
.fncache
[filename
] = canonic
38 linecache
.checkcache()
41 self
.returnframe
= None
44 def trace_dispatch(self
, frame
, event
, arg
):
48 return self
.dispatch_line(frame
)
50 return self
.dispatch_call(frame
, arg
)
52 return self
.dispatch_return(frame
, arg
)
53 if event
== 'exception':
54 return self
.dispatch_exception(frame
, arg
)
56 return self
.trace_dispatch
57 if event
== 'c_exception':
58 return self
.trace_dispatch
59 if event
== 'c_return':
60 return self
.trace_dispatch
61 print 'bdb.Bdb.dispatch: unknown debugging event:', repr(event
)
62 return self
.trace_dispatch
64 def dispatch_line(self
, frame
):
65 if self
.stop_here(frame
) or self
.break_here(frame
):
67 if self
.quitting
: raise BdbQuit
68 return self
.trace_dispatch
70 def dispatch_call(self
, frame
, arg
):
71 # XXX 'arg' is no longer used
72 if self
.botframe
is None:
73 # First call of dispatch since reset()
74 self
.botframe
= frame
.f_back
# (CT) Note that this may also be None!
75 return self
.trace_dispatch
76 if not (self
.stop_here(frame
) or self
.break_anywhere(frame
)):
77 # No need to trace this function
79 self
.user_call(frame
, arg
)
80 if self
.quitting
: raise BdbQuit
81 return self
.trace_dispatch
83 def dispatch_return(self
, frame
, arg
):
84 if self
.stop_here(frame
) or frame
== self
.returnframe
:
85 self
.user_return(frame
, arg
)
86 if self
.quitting
: raise BdbQuit
87 return self
.trace_dispatch
89 def dispatch_exception(self
, frame
, arg
):
90 if self
.stop_here(frame
):
91 self
.user_exception(frame
, arg
)
92 if self
.quitting
: raise BdbQuit
93 return self
.trace_dispatch
95 # Normally derived classes don't override the following
96 # methods, but they may if they want to redefine the
97 # definition of stopping and breakpoints.
99 def stop_here(self
, frame
):
100 # (CT) stopframe may now also be None, see dispatch_call.
101 # (CT) the former test for None is therefore removed from here.
102 if frame
is self
.stopframe
:
104 while frame
is not None and frame
is not self
.stopframe
:
105 if frame
is self
.botframe
:
110 def break_here(self
, frame
):
111 filename
= self
.canonic(frame
.f_code
.co_filename
)
112 if not filename
in self
.breaks
:
114 lineno
= frame
.f_lineno
115 if not lineno
in self
.breaks
[filename
]:
116 # The line itself has no breakpoint, but maybe the line is the
117 # first line of a function with breakpoint set by function name.
118 lineno
= frame
.f_code
.co_firstlineno
119 if not lineno
in self
.breaks
[filename
]:
122 # flag says ok to delete temp. bp
123 (bp
, flag
) = effective(filename
, lineno
, frame
)
125 self
.currentbp
= bp
.number
126 if (flag
and bp
.temporary
):
127 self
.do_clear(str(bp
.number
))
132 def do_clear(self
, arg
):
133 raise NotImplementedError, "subclass of bdb must implement do_clear()"
135 def break_anywhere(self
, frame
):
136 return self
.breaks
.has_key(
137 self
.canonic(frame
.f_code
.co_filename
))
139 # Derived classes should override the user_* methods
142 def user_call(self
, frame
, argument_list
):
143 """This method is called when there is the remote possibility
144 that we ever need to stop in this function."""
147 def user_line(self
, frame
):
148 """This method is called when we stop or break at this line."""
151 def user_return(self
, frame
, return_value
):
152 """This method is called when a return trap is set here."""
155 def user_exception(self
, frame
, (exc_type
, exc_value
, exc_traceback
)):
156 """This method is called if an exception occurs,
157 but only if we are to stop at or just below this level."""
160 # Derived classes and clients can call the following methods
161 # to affect the stepping state.
164 """Stop after one line of code."""
165 self
.stopframe
= None
166 self
.returnframe
= None
169 def set_next(self
, frame
):
170 """Stop on the next line in or below the given frame."""
171 self
.stopframe
= frame
172 self
.returnframe
= None
175 def set_return(self
, frame
):
176 """Stop when returning from the given frame."""
177 self
.stopframe
= frame
.f_back
178 self
.returnframe
= frame
181 def set_trace(self
, frame
=None):
182 """Start debugging from `frame`.
184 If frame is not specified, debugging starts from caller's frame.
187 frame
= sys
._getframe
().f_back
190 frame
.f_trace
= self
.trace_dispatch
191 self
.botframe
= frame
194 sys
.settrace(self
.trace_dispatch
)
196 def set_continue(self
):
197 # Don't stop except at breakpoints or when finished
198 self
.stopframe
= self
.botframe
199 self
.returnframe
= None
202 # no breakpoints; run without debugger overhead
204 frame
= sys
._getframe
().f_back
205 while frame
and frame
is not self
.botframe
:
210 self
.stopframe
= self
.botframe
211 self
.returnframe
= None
215 # Derived classes and clients can call the following methods
216 # to manipulate breakpoints. These methods return an
217 # error message is something went wrong, None if all is well.
218 # Set_break prints out the breakpoint line and file:lineno.
219 # Call self.get_*break*() to see the breakpoints or better
220 # for bp in Breakpoint.bpbynumber: if bp: bp.bpprint().
222 def set_break(self
, filename
, lineno
, temporary
=0, cond
= None,
224 filename
= self
.canonic(filename
)
225 import linecache
# Import as late as possible
226 line
= linecache
.getline(filename
, lineno
)
228 return 'Line %s:%d does not exist' % (filename
,
230 if not filename
in self
.breaks
:
231 self
.breaks
[filename
] = []
232 list = self
.breaks
[filename
]
233 if not lineno
in list:
235 bp
= Breakpoint(filename
, lineno
, temporary
, cond
, funcname
)
237 def clear_break(self
, filename
, lineno
):
238 filename
= self
.canonic(filename
)
239 if not filename
in self
.breaks
:
240 return 'There are no breakpoints in %s' % filename
241 if lineno
not in self
.breaks
[filename
]:
242 return 'There is no breakpoint at %s:%d' % (filename
,
244 # If there's only one bp in the list for that file,line
245 # pair, then remove the breaks entry
246 for bp
in Breakpoint
.bplist
[filename
, lineno
][:]:
248 if not Breakpoint
.bplist
.has_key((filename
, lineno
)):
249 self
.breaks
[filename
].remove(lineno
)
250 if not self
.breaks
[filename
]:
251 del self
.breaks
[filename
]
253 def clear_bpbynumber(self
, arg
):
257 return 'Non-numeric breakpoint number (%s)' % arg
259 bp
= Breakpoint
.bpbynumber
[number
]
261 return 'Breakpoint number (%d) out of range' % number
263 return 'Breakpoint (%d) already deleted' % number
264 self
.clear_break(bp
.file, bp
.line
)
266 def clear_all_file_breaks(self
, filename
):
267 filename
= self
.canonic(filename
)
268 if not filename
in self
.breaks
:
269 return 'There are no breakpoints in %s' % filename
270 for line
in self
.breaks
[filename
]:
271 blist
= Breakpoint
.bplist
[filename
, line
]
274 del self
.breaks
[filename
]
276 def clear_all_breaks(self
):
278 return 'There are no breakpoints'
279 for bp
in Breakpoint
.bpbynumber
:
284 def get_break(self
, filename
, lineno
):
285 filename
= self
.canonic(filename
)
286 return filename
in self
.breaks
and \
287 lineno
in self
.breaks
[filename
]
289 def get_breaks(self
, filename
, lineno
):
290 filename
= self
.canonic(filename
)
291 return filename
in self
.breaks
and \
292 lineno
in self
.breaks
[filename
] and \
293 Breakpoint
.bplist
[filename
, lineno
] or []
295 def get_file_breaks(self
, filename
):
296 filename
= self
.canonic(filename
)
297 if filename
in self
.breaks
:
298 return self
.breaks
[filename
]
302 def get_all_breaks(self
):
305 # Derived classes and clients can call the following method
306 # to get a data structure representing a stack trace.
308 def get_stack(self
, f
, t
):
310 if t
and t
.tb_frame
is f
:
313 stack
.append((f
, f
.f_lineno
))
314 if f
is self
.botframe
:
318 i
= max(0, len(stack
) - 1)
320 stack
.append((t
.tb_frame
, t
.tb_lineno
))
326 def format_stack_entry(self
, frame_lineno
, lprefix
=': '):
327 import linecache
, repr
328 frame
, lineno
= frame_lineno
329 filename
= self
.canonic(frame
.f_code
.co_filename
)
330 s
= '%s(%r)' % (filename
, lineno
)
331 if frame
.f_code
.co_name
:
332 s
= s
+ frame
.f_code
.co_name
335 if '__args__' in frame
.f_locals
:
336 args
= frame
.f_locals
['__args__']
340 s
= s
+ repr.repr(args
)
343 if '__return__' in frame
.f_locals
:
344 rv
= frame
.f_locals
['__return__']
346 s
= s
+ repr.repr(rv
)
347 line
= linecache
.getline(filename
, lineno
)
348 if line
: s
= s
+ lprefix
+ line
.strip()
351 # The following two methods can be called by clients to use
352 # a debugger to debug a statement, given as a string.
354 def run(self
, cmd
, globals=None, locals=None):
357 globals = __main__
.__dict
__
361 sys
.settrace(self
.trace_dispatch
)
362 if not isinstance(cmd
, types
.CodeType
):
366 exec cmd
in globals, locals
373 def runeval(self
, expr
, globals=None, locals=None):
376 globals = __main__
.__dict
__
380 sys
.settrace(self
.trace_dispatch
)
381 if not isinstance(expr
, types
.CodeType
):
385 return eval(expr
, globals, locals)
392 def runctx(self
, cmd
, globals, locals):
394 self
.run(cmd
, globals, locals)
396 # This method is more useful to debug a single function call.
398 def runcall(self
, func
, *args
, **kwds
):
400 sys
.settrace(self
.trace_dispatch
)
404 res
= func(*args
, **kwds
)
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
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!
447 self
.temporary
= temporary
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
)
459 self
.bplist
[file, line
] = [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
]
476 def bpprint(self
, out
=None):
487 print >>out
, '%-4dbreakpoint %s at %s:%d' % (self
.number
, disp
,
488 self
.file, self
.line
)
490 print >>out
, '\tstop only if %s' % (self
.cond
,)
492 print >>out
, '\tignore next %d hits' % (self
.ignore
)
494 if (self
.hits
> 1): ss
= 's'
496 print >>out
, ('\tbreakpoint already hit %d time%s' %
499 # -----------end of Breakpoint class----------
501 def checkfuncname(b
, frame
):
502 """Check whether we should break here because of `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.
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.
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.
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
)):
542 if not checkfuncname(b
, frame
):
544 # Count every hit when bp is enabled
547 # If unconditional, and ignoring,
548 # go on to next, else break
550 b
.ignore
= b
.ignore
-1
553 # breakpoint and marker that's ok
554 # to delete if temporary
558 # Ignore count applies only to those bpt hits where the
559 # condition evaluates to true.
561 val
= eval(b
.cond
, frame
.f_globals
,
565 b
.ignore
= b
.ignore
-1
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.
580 # -------------------- testing --------------------
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
):
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
)
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
603 print 'bar returned', x
611 t
.run('import bdb; bdb.foo(10)')