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 return frame
.f_lineno
>= self
.stoplineno
113 while frame
is not None and frame
is not self
.stopframe
:
114 if frame
is self
.botframe
:
119 def break_here(self
, frame
):
120 filename
= self
.canonic(frame
.f_code
.co_filename
)
121 if not filename
in self
.breaks
:
123 lineno
= frame
.f_lineno
124 if not lineno
in self
.breaks
[filename
]:
125 # The line itself has no breakpoint, but maybe the line is the
126 # first line of a function with breakpoint set by function name.
127 lineno
= frame
.f_code
.co_firstlineno
128 if not lineno
in self
.breaks
[filename
]:
131 # flag says ok to delete temp. bp
132 (bp
, flag
) = effective(filename
, lineno
, frame
)
134 self
.currentbp
= bp
.number
135 if (flag
and bp
.temporary
):
136 self
.do_clear(str(bp
.number
))
141 def do_clear(self
, arg
):
142 raise NotImplementedError, "subclass of bdb must implement do_clear()"
144 def break_anywhere(self
, frame
):
145 return self
.canonic(frame
.f_code
.co_filename
) in self
.breaks
147 # Derived classes should override the user_* methods
150 def user_call(self
, frame
, argument_list
):
151 """This method is called when there is the remote possibility
152 that we ever need to stop in this function."""
155 def user_line(self
, frame
):
156 """This method is called when we stop or break at this line."""
159 def user_return(self
, frame
, return_value
):
160 """This method is called when a return trap is set here."""
163 def user_exception(self
, frame
, exc_info
):
164 exc_type
, exc_value
, exc_traceback
= exc_info
165 """This method is called if an exception occurs,
166 but only if we are to stop at or just below this level."""
169 def _set_stopinfo(self
, stopframe
, returnframe
, stoplineno
=-1):
170 self
.stopframe
= stopframe
171 self
.returnframe
= returnframe
173 self
.stoplineno
= stoplineno
175 # Derived classes and clients can call the following methods
176 # to affect the stepping state.
178 def set_until(self
, frame
): #the name "until" is borrowed from gdb
179 """Stop when the line with the line no greater than the current one is
180 reached or when returning from current frame"""
181 self
._set
_stopinfo
(frame
, frame
, frame
.f_lineno
+1)
184 """Stop after one line of code."""
185 self
._set
_stopinfo
(None,None)
187 def set_next(self
, frame
):
188 """Stop on the next line in or below the given frame."""
189 self
._set
_stopinfo
(frame
, None)
191 def set_return(self
, frame
):
192 """Stop when returning from the given frame."""
193 self
._set
_stopinfo
(frame
.f_back
, frame
)
195 def set_trace(self
, frame
=None):
196 """Start debugging from `frame`.
198 If frame is not specified, debugging starts from caller's frame.
201 frame
= sys
._getframe
().f_back
204 frame
.f_trace
= self
.trace_dispatch
205 self
.botframe
= frame
208 sys
.settrace(self
.trace_dispatch
)
210 def set_continue(self
):
211 # Don't stop except at breakpoints or when finished
212 self
._set
_stopinfo
(self
.botframe
, None)
214 # no breakpoints; run without debugger overhead
216 frame
= sys
._getframe
().f_back
217 while frame
and frame
is not self
.botframe
:
222 self
.stopframe
= self
.botframe
223 self
.returnframe
= None
227 # Derived classes and clients can call the following methods
228 # to manipulate breakpoints. These methods return an
229 # error message is something went wrong, None if all is well.
230 # Set_break prints out the breakpoint line and file:lineno.
231 # Call self.get_*break*() to see the breakpoints or better
232 # for bp in Breakpoint.bpbynumber: if bp: bp.bpprint().
234 def set_break(self
, filename
, lineno
, temporary
=0, cond
= None,
236 filename
= self
.canonic(filename
)
237 import linecache
# Import as late as possible
238 line
= linecache
.getline(filename
, lineno
)
240 return 'Line %s:%d does not exist' % (filename
,
242 if not filename
in self
.breaks
:
243 self
.breaks
[filename
] = []
244 list = self
.breaks
[filename
]
245 if not lineno
in list:
247 bp
= Breakpoint(filename
, lineno
, temporary
, cond
, funcname
)
249 def clear_break(self
, filename
, lineno
):
250 filename
= self
.canonic(filename
)
251 if not filename
in self
.breaks
:
252 return 'There are no breakpoints in %s' % filename
253 if lineno
not in self
.breaks
[filename
]:
254 return 'There is no breakpoint at %s:%d' % (filename
,
256 # If there's only one bp in the list for that file,line
257 # pair, then remove the breaks entry
258 for bp
in Breakpoint
.bplist
[filename
, lineno
][:]:
260 if (filename
, lineno
) not in Breakpoint
.bplist
:
261 self
.breaks
[filename
].remove(lineno
)
262 if not self
.breaks
[filename
]:
263 del self
.breaks
[filename
]
265 def clear_bpbynumber(self
, arg
):
269 return 'Non-numeric breakpoint number (%s)' % arg
271 bp
= Breakpoint
.bpbynumber
[number
]
273 return 'Breakpoint number (%d) out of range' % number
275 return 'Breakpoint (%d) already deleted' % number
276 self
.clear_break(bp
.file, bp
.line
)
278 def clear_all_file_breaks(self
, filename
):
279 filename
= self
.canonic(filename
)
280 if not filename
in self
.breaks
:
281 return 'There are no breakpoints in %s' % filename
282 for line
in self
.breaks
[filename
]:
283 blist
= Breakpoint
.bplist
[filename
, line
]
286 del self
.breaks
[filename
]
288 def clear_all_breaks(self
):
290 return 'There are no breakpoints'
291 for bp
in Breakpoint
.bpbynumber
:
296 def get_break(self
, filename
, lineno
):
297 filename
= self
.canonic(filename
)
298 return filename
in self
.breaks
and \
299 lineno
in self
.breaks
[filename
]
301 def get_breaks(self
, filename
, lineno
):
302 filename
= self
.canonic(filename
)
303 return filename
in self
.breaks
and \
304 lineno
in self
.breaks
[filename
] and \
305 Breakpoint
.bplist
[filename
, lineno
] or []
307 def get_file_breaks(self
, filename
):
308 filename
= self
.canonic(filename
)
309 if filename
in self
.breaks
:
310 return self
.breaks
[filename
]
314 def get_all_breaks(self
):
317 # Derived classes and clients can call the following method
318 # to get a data structure representing a stack trace.
320 def get_stack(self
, f
, t
):
322 if t
and t
.tb_frame
is f
:
325 stack
.append((f
, f
.f_lineno
))
326 if f
is self
.botframe
:
330 i
= max(0, len(stack
) - 1)
332 stack
.append((t
.tb_frame
, t
.tb_lineno
))
335 i
= max(0, len(stack
) - 1)
340 def format_stack_entry(self
, frame_lineno
, lprefix
=': '):
341 import linecache
, repr
342 frame
, lineno
= frame_lineno
343 filename
= self
.canonic(frame
.f_code
.co_filename
)
344 s
= '%s(%r)' % (filename
, lineno
)
345 if frame
.f_code
.co_name
:
346 s
= s
+ frame
.f_code
.co_name
349 if '__args__' in frame
.f_locals
:
350 args
= frame
.f_locals
['__args__']
354 s
= s
+ repr.repr(args
)
357 if '__return__' in frame
.f_locals
:
358 rv
= frame
.f_locals
['__return__']
360 s
= s
+ repr.repr(rv
)
361 line
= linecache
.getline(filename
, lineno
, frame
.f_globals
)
362 if line
: s
= s
+ lprefix
+ line
.strip()
365 # The following two methods can be called by clients to use
366 # a debugger to debug a statement, given as a string.
368 def run(self
, cmd
, globals=None, locals=None):
371 globals = __main__
.__dict
__
375 sys
.settrace(self
.trace_dispatch
)
376 if not isinstance(cmd
, types
.CodeType
):
379 exec cmd
in globals, locals
386 def runeval(self
, expr
, globals=None, locals=None):
389 globals = __main__
.__dict
__
393 sys
.settrace(self
.trace_dispatch
)
394 if not isinstance(expr
, types
.CodeType
):
397 return eval(expr
, globals, locals)
404 def runctx(self
, cmd
, globals, locals):
406 self
.run(cmd
, globals, locals)
408 # This method is more useful to debug a single function call.
410 def runcall(self
, func
, *args
, **kwds
):
412 sys
.settrace(self
.trace_dispatch
)
415 res
= func(*args
, **kwds
)
432 Implements temporary breakpoints, ignore counts, disabling and
433 (re)-enabling, and conditionals.
435 Breakpoints are indexed by number through bpbynumber and by
436 the file,line tuple using bplist. The former points to a
437 single instance of class Breakpoint. The latter points to a
438 list of such instances since there may be more than one
443 # XXX Keeping state in the class is a mistake -- this means
444 # you cannot have more than one active Bdb instance.
446 next
= 1 # Next bp to be assigned
447 bplist
= {} # indexed by (file, lineno) tuple
448 bpbynumber
= [None] # Each entry is None or an instance of Bpt
449 # index 0 is unused, except for marking an
450 # effective break .... see effective()
452 def __init__(self
, file, line
, temporary
=0, cond
=None, funcname
=None):
453 self
.funcname
= funcname
454 # Needed if funcname is not None.
455 self
.func_first_executable_line
= None
456 self
.file = file # This better be in canonical form!
458 self
.temporary
= temporary
463 self
.number
= Breakpoint
.next
464 Breakpoint
.next
= Breakpoint
.next
+ 1
465 # Build the two lists
466 self
.bpbynumber
.append(self
)
467 if (file, line
) in self
.bplist
:
468 self
.bplist
[file, line
].append(self
)
470 self
.bplist
[file, line
] = [self
]
474 index
= (self
.file, self
.line
)
475 self
.bpbynumber
[self
.number
] = None # No longer in list
476 self
.bplist
[index
].remove(self
)
477 if not self
.bplist
[index
]:
478 # No more bp for this f:l combo
479 del self
.bplist
[index
]
487 def bpprint(self
, out
=None):
498 print >>out
, '%-4dbreakpoint %s at %s:%d' % (self
.number
, disp
,
499 self
.file, self
.line
)
501 print >>out
, '\tstop only if %s' % (self
.cond
,)
503 print >>out
, '\tignore next %d hits' % (self
.ignore
)
505 if (self
.hits
> 1): ss
= 's'
507 print >>out
, ('\tbreakpoint already hit %d time%s' %
510 # -----------end of Breakpoint class----------
512 def checkfuncname(b
, frame
):
513 """Check whether we should break here because of `b.funcname`."""
515 # Breakpoint was set via line number.
516 if b
.line
!= frame
.f_lineno
:
517 # Breakpoint was set at a line with a def statement and the function
518 # defined is called: don't break.
522 # Breakpoint set via function name.
524 if frame
.f_code
.co_name
!= b
.funcname
:
525 # It's not a function call, but rather execution of def statement.
528 # We are in the right frame.
529 if not b
.func_first_executable_line
:
530 # The function is entered for the 1st time.
531 b
.func_first_executable_line
= frame
.f_lineno
533 if b
.func_first_executable_line
!= frame
.f_lineno
:
534 # But we are not at the first line number: don't break.
538 # Determines if there is an effective (active) breakpoint at this
539 # line of code. Returns breakpoint number or 0 if none
540 def effective(file, line
, frame
):
541 """Determine which breakpoint for this file:line is to be acted upon.
543 Called only if we know there is a bpt at this
544 location. Returns breakpoint that was triggered and a flag
545 that indicates if it is ok to delete a temporary bp.
548 possibles
= Breakpoint
.bplist
[file,line
]
549 for i
in range(0, len(possibles
)):
553 if not checkfuncname(b
, frame
):
555 # Count every hit when bp is enabled
558 # If unconditional, and ignoring,
559 # go on to next, else break
561 b
.ignore
= b
.ignore
-1
564 # breakpoint and marker that's ok
565 # to delete if temporary
569 # Ignore count applies only to those bpt hits where the
570 # condition evaluates to true.
572 val
= eval(b
.cond
, frame
.f_globals
,
576 b
.ignore
= b
.ignore
-1
583 # if eval fails, most conservative
584 # thing is to stop on breakpoint
585 # regardless of ignore count.
586 # Don't delete temporary,
587 # as another hint to user.
591 # -------------------- testing --------------------
594 def user_call(self
, frame
, args
):
595 name
= frame
.f_code
.co_name
596 if not name
: name
= '???'
597 print '+++ call', name
, args
598 def user_line(self
, frame
):
600 name
= frame
.f_code
.co_name
601 if not name
: name
= '???'
602 fn
= self
.canonic(frame
.f_code
.co_filename
)
603 line
= linecache
.getline(fn
, frame
.f_lineno
, frame
.f_globals
)
604 print '+++', fn
, frame
.f_lineno
, name
, ':', line
.strip()
605 def user_return(self
, frame
, retval
):
606 print '+++ return', retval
607 def user_exception(self
, frame
, exc_stuff
):
608 print '+++ exception', exc_stuff
614 print 'bar returned', x
622 t
.run('import bdb; bdb.foo(10)')