8 __all__
= ["BdbQuit","Bdb","Breakpoint"]
10 class BdbQuit(Exception):
11 """Exception to give up completely"""
16 """Generic Python debugger base class.
18 This class takes care of details of the trace facility;
19 a derived class should implement user interaction.
20 The standard debugger class (pdb.Pdb) is an example.
23 def __init__(self
, skip
=None):
24 self
.skip
= set(skip
) if skip
else None
28 def canonic(self
, filename
):
29 if filename
== "<" + filename
[1:-1] + ">":
31 canonic
= self
.fncache
.get(filename
)
33 canonic
= os
.path
.abspath(filename
)
34 canonic
= os
.path
.normcase(canonic
)
35 self
.fncache
[filename
] = canonic
40 linecache
.checkcache()
42 self
._set
_stopinfo
(None, 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 is_skipped_module(self
, module_name
):
100 for pattern
in self
.skip
:
101 if fnmatch
.fnmatch(module_name
, pattern
):
105 def stop_here(self
, frame
):
106 # (CT) stopframe may now also be None, see dispatch_call.
107 # (CT) the former test for None is therefore removed from here.
109 self
.is_skipped_module(frame
.f_globals
.get('__name__')):
111 if frame
is self
.stopframe
:
112 if self
.stoplineno
== -1:
114 return frame
.f_lineno
>= self
.stoplineno
115 while frame
is not None and frame
is not self
.stopframe
:
116 if frame
is self
.botframe
:
121 def break_here(self
, frame
):
122 filename
= self
.canonic(frame
.f_code
.co_filename
)
123 if not filename
in self
.breaks
:
125 lineno
= frame
.f_lineno
126 if not lineno
in self
.breaks
[filename
]:
127 # The line itself has no breakpoint, but maybe the line is the
128 # first line of a function with breakpoint set by function name.
129 lineno
= frame
.f_code
.co_firstlineno
130 if not lineno
in self
.breaks
[filename
]:
133 # flag says ok to delete temp. bp
134 (bp
, flag
) = effective(filename
, lineno
, frame
)
136 self
.currentbp
= bp
.number
137 if (flag
and bp
.temporary
):
138 self
.do_clear(str(bp
.number
))
143 def do_clear(self
, arg
):
144 raise NotImplementedError, "subclass of bdb must implement do_clear()"
146 def break_anywhere(self
, frame
):
147 return self
.canonic(frame
.f_code
.co_filename
) in self
.breaks
149 # Derived classes should override the user_* methods
152 def user_call(self
, frame
, argument_list
):
153 """This method is called when there is the remote possibility
154 that we ever need to stop in this function."""
157 def user_line(self
, frame
):
158 """This method is called when we stop or break at this line."""
161 def user_return(self
, frame
, return_value
):
162 """This method is called when a return trap is set here."""
165 def user_exception(self
, frame
, exc_info
):
166 exc_type
, exc_value
, exc_traceback
= exc_info
167 """This method is called if an exception occurs,
168 but only if we are to stop at or just below this level."""
171 def _set_stopinfo(self
, stopframe
, returnframe
, stoplineno
=0):
172 self
.stopframe
= stopframe
173 self
.returnframe
= returnframe
175 # stoplineno >= 0 means: stop at line >= the stoplineno
176 # stoplineno -1 means: don't stop at all
177 self
.stoplineno
= stoplineno
179 # Derived classes and clients can call the following methods
180 # to affect the stepping state.
182 def set_until(self
, frame
): #the name "until" is borrowed from gdb
183 """Stop when the line with the line no greater than the current one is
184 reached or when returning from current frame"""
185 self
._set
_stopinfo
(frame
, frame
, frame
.f_lineno
+1)
188 """Stop after one line of code."""
189 self
._set
_stopinfo
(None, None)
191 def set_next(self
, frame
):
192 """Stop on the next line in or below the given frame."""
193 self
._set
_stopinfo
(frame
, None)
195 def set_return(self
, frame
):
196 """Stop when returning from the given frame."""
197 self
._set
_stopinfo
(frame
.f_back
, frame
)
199 def set_trace(self
, frame
=None):
200 """Start debugging from `frame`.
202 If frame is not specified, debugging starts from caller's frame.
205 frame
= sys
._getframe
().f_back
208 frame
.f_trace
= self
.trace_dispatch
209 self
.botframe
= frame
212 sys
.settrace(self
.trace_dispatch
)
214 def set_continue(self
):
215 # Don't stop except at breakpoints or when finished
216 self
._set
_stopinfo
(self
.botframe
, None, -1)
218 # no breakpoints; run without debugger overhead
220 frame
= sys
._getframe
().f_back
221 while frame
and frame
is not self
.botframe
:
226 self
.stopframe
= self
.botframe
227 self
.returnframe
= None
231 # Derived classes and clients can call the following methods
232 # to manipulate breakpoints. These methods return an
233 # error message is something went wrong, None if all is well.
234 # Set_break prints out the breakpoint line and file:lineno.
235 # Call self.get_*break*() to see the breakpoints or better
236 # for bp in Breakpoint.bpbynumber: if bp: bp.bpprint().
238 def set_break(self
, filename
, lineno
, temporary
=0, cond
= None,
240 filename
= self
.canonic(filename
)
241 import linecache
# Import as late as possible
242 line
= linecache
.getline(filename
, lineno
)
244 return 'Line %s:%d does not exist' % (filename
,
246 if not filename
in self
.breaks
:
247 self
.breaks
[filename
] = []
248 list = self
.breaks
[filename
]
249 if not lineno
in list:
251 bp
= Breakpoint(filename
, lineno
, temporary
, cond
, funcname
)
253 def _prune_breaks(self
, filename
, lineno
):
254 if (filename
, lineno
) not in Breakpoint
.bplist
:
255 self
.breaks
[filename
].remove(lineno
)
256 if not self
.breaks
[filename
]:
257 del self
.breaks
[filename
]
259 def clear_break(self
, filename
, lineno
):
260 filename
= self
.canonic(filename
)
261 if not filename
in self
.breaks
:
262 return 'There are no breakpoints in %s' % filename
263 if lineno
not in self
.breaks
[filename
]:
264 return 'There is no breakpoint at %s:%d' % (filename
,
266 # If there's only one bp in the list for that file,line
267 # pair, then remove the breaks entry
268 for bp
in Breakpoint
.bplist
[filename
, lineno
][:]:
270 self
._prune
_breaks
(filename
, lineno
)
272 def clear_bpbynumber(self
, arg
):
276 return 'Non-numeric breakpoint number (%s)' % arg
278 bp
= Breakpoint
.bpbynumber
[number
]
280 return 'Breakpoint number (%d) out of range' % number
282 return 'Breakpoint (%d) already deleted' % number
284 self
._prune
_breaks
(bp
.file, bp
.line
)
286 def clear_all_file_breaks(self
, filename
):
287 filename
= self
.canonic(filename
)
288 if not filename
in self
.breaks
:
289 return 'There are no breakpoints in %s' % filename
290 for line
in self
.breaks
[filename
]:
291 blist
= Breakpoint
.bplist
[filename
, line
]
294 del self
.breaks
[filename
]
296 def clear_all_breaks(self
):
298 return 'There are no breakpoints'
299 for bp
in Breakpoint
.bpbynumber
:
304 def get_break(self
, filename
, lineno
):
305 filename
= self
.canonic(filename
)
306 return filename
in self
.breaks
and \
307 lineno
in self
.breaks
[filename
]
309 def get_breaks(self
, filename
, lineno
):
310 filename
= self
.canonic(filename
)
311 return filename
in self
.breaks
and \
312 lineno
in self
.breaks
[filename
] and \
313 Breakpoint
.bplist
[filename
, lineno
] or []
315 def get_file_breaks(self
, filename
):
316 filename
= self
.canonic(filename
)
317 if filename
in self
.breaks
:
318 return self
.breaks
[filename
]
322 def get_all_breaks(self
):
325 # Derived classes and clients can call the following method
326 # to get a data structure representing a stack trace.
328 def get_stack(self
, f
, t
):
330 if t
and t
.tb_frame
is f
:
333 stack
.append((f
, f
.f_lineno
))
334 if f
is self
.botframe
:
338 i
= max(0, len(stack
) - 1)
340 stack
.append((t
.tb_frame
, t
.tb_lineno
))
343 i
= max(0, len(stack
) - 1)
348 def format_stack_entry(self
, frame_lineno
, lprefix
=': '):
349 import linecache
, repr
350 frame
, lineno
= frame_lineno
351 filename
= self
.canonic(frame
.f_code
.co_filename
)
352 s
= '%s(%r)' % (filename
, lineno
)
353 if frame
.f_code
.co_name
:
354 s
= s
+ frame
.f_code
.co_name
357 if '__args__' in frame
.f_locals
:
358 args
= frame
.f_locals
['__args__']
362 s
= s
+ repr.repr(args
)
365 if '__return__' in frame
.f_locals
:
366 rv
= frame
.f_locals
['__return__']
368 s
= s
+ repr.repr(rv
)
369 line
= linecache
.getline(filename
, lineno
, frame
.f_globals
)
370 if line
: s
= s
+ lprefix
+ line
.strip()
373 # The following two methods can be called by clients to use
374 # a debugger to debug a statement, given as a string.
376 def run(self
, cmd
, globals=None, locals=None):
379 globals = __main__
.__dict
__
383 sys
.settrace(self
.trace_dispatch
)
384 if not isinstance(cmd
, types
.CodeType
):
387 exec cmd
in globals, locals
394 def runeval(self
, expr
, globals=None, locals=None):
397 globals = __main__
.__dict
__
401 sys
.settrace(self
.trace_dispatch
)
402 if not isinstance(expr
, types
.CodeType
):
405 return eval(expr
, globals, locals)
412 def runctx(self
, cmd
, globals, locals):
414 self
.run(cmd
, globals, locals)
416 # This method is more useful to debug a single function call.
418 def runcall(self
, func
, *args
, **kwds
):
420 sys
.settrace(self
.trace_dispatch
)
423 res
= func(*args
, **kwds
)
440 Implements temporary breakpoints, ignore counts, disabling and
441 (re)-enabling, and conditionals.
443 Breakpoints are indexed by number through bpbynumber and by
444 the file,line tuple using bplist. The former points to a
445 single instance of class Breakpoint. The latter points to a
446 list of such instances since there may be more than one
451 # XXX Keeping state in the class is a mistake -- this means
452 # you cannot have more than one active Bdb instance.
454 next
= 1 # Next bp to be assigned
455 bplist
= {} # indexed by (file, lineno) tuple
456 bpbynumber
= [None] # Each entry is None or an instance of Bpt
457 # index 0 is unused, except for marking an
458 # effective break .... see effective()
460 def __init__(self
, file, line
, temporary
=0, cond
=None, funcname
=None):
461 self
.funcname
= funcname
462 # Needed if funcname is not None.
463 self
.func_first_executable_line
= None
464 self
.file = file # This better be in canonical form!
466 self
.temporary
= temporary
471 self
.number
= Breakpoint
.next
472 Breakpoint
.next
= Breakpoint
.next
+ 1
473 # Build the two lists
474 self
.bpbynumber
.append(self
)
475 if (file, line
) in self
.bplist
:
476 self
.bplist
[file, line
].append(self
)
478 self
.bplist
[file, line
] = [self
]
482 index
= (self
.file, self
.line
)
483 self
.bpbynumber
[self
.number
] = None # No longer in list
484 self
.bplist
[index
].remove(self
)
485 if not self
.bplist
[index
]:
486 # No more bp for this f:l combo
487 del self
.bplist
[index
]
495 def bpprint(self
, out
=None):
506 print >>out
, '%-4dbreakpoint %s at %s:%d' % (self
.number
, disp
,
507 self
.file, self
.line
)
509 print >>out
, '\tstop only if %s' % (self
.cond
,)
511 print >>out
, '\tignore next %d hits' % (self
.ignore
)
513 if (self
.hits
> 1): ss
= 's'
515 print >>out
, ('\tbreakpoint already hit %d time%s' %
518 # -----------end of Breakpoint class----------
520 def checkfuncname(b
, frame
):
521 """Check whether we should break here because of `b.funcname`."""
523 # Breakpoint was set via line number.
524 if b
.line
!= frame
.f_lineno
:
525 # Breakpoint was set at a line with a def statement and the function
526 # defined is called: don't break.
530 # Breakpoint set via function name.
532 if frame
.f_code
.co_name
!= b
.funcname
:
533 # It's not a function call, but rather execution of def statement.
536 # We are in the right frame.
537 if not b
.func_first_executable_line
:
538 # The function is entered for the 1st time.
539 b
.func_first_executable_line
= frame
.f_lineno
541 if b
.func_first_executable_line
!= frame
.f_lineno
:
542 # But we are not at the first line number: don't break.
546 # Determines if there is an effective (active) breakpoint at this
547 # line of code. Returns breakpoint number or 0 if none
548 def effective(file, line
, frame
):
549 """Determine which breakpoint for this file:line is to be acted upon.
551 Called only if we know there is a bpt at this
552 location. Returns breakpoint that was triggered and a flag
553 that indicates if it is ok to delete a temporary bp.
556 possibles
= Breakpoint
.bplist
[file,line
]
557 for i
in range(0, len(possibles
)):
561 if not checkfuncname(b
, frame
):
563 # Count every hit when bp is enabled
566 # If unconditional, and ignoring,
567 # go on to next, else break
569 b
.ignore
= b
.ignore
-1
572 # breakpoint and marker that's ok
573 # to delete if temporary
577 # Ignore count applies only to those bpt hits where the
578 # condition evaluates to true.
580 val
= eval(b
.cond
, frame
.f_globals
,
584 b
.ignore
= b
.ignore
-1
591 # if eval fails, most conservative
592 # thing is to stop on breakpoint
593 # regardless of ignore count.
594 # Don't delete temporary,
595 # as another hint to user.
599 # -------------------- testing --------------------
602 def user_call(self
, frame
, args
):
603 name
= frame
.f_code
.co_name
604 if not name
: name
= '???'
605 print '+++ call', name
, args
606 def user_line(self
, frame
):
608 name
= frame
.f_code
.co_name
609 if not name
: name
= '???'
610 fn
= self
.canonic(frame
.f_code
.co_filename
)
611 line
= linecache
.getline(fn
, frame
.f_lineno
, frame
.f_globals
)
612 print '+++', fn
, frame
.f_lineno
, name
, ':', line
.strip()
613 def user_return(self
, frame
, retval
):
614 print '+++ return', retval
615 def user_exception(self
, frame
, exc_stuff
):
616 print '+++ exception', exc_stuff
622 print 'bar returned', x
630 t
.run('import bdb; bdb.foo(10)')