• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1"""Debugger basics"""
2
3import fnmatch
4import sys
5import os
6from inspect import CO_GENERATOR, CO_COROUTINE, CO_ASYNC_GENERATOR
7
8__all__ = ["BdbQuit", "Bdb", "Breakpoint"]
9
10GENERATOR_AND_COROUTINE_FLAGS = CO_GENERATOR | CO_COROUTINE | CO_ASYNC_GENERATOR
11
12
13class BdbQuit(Exception):
14    """Exception to give up completely."""
15
16
17class Bdb:
18    """Generic Python debugger base class.
19
20    This class takes care of details of the trace facility;
21    a derived class should implement user interaction.
22    The standard debugger class (pdb.Pdb) is an example.
23
24    The optional skip argument must be an iterable of glob-style
25    module name patterns.  The debugger will not step into frames
26    that originate in a module that matches one of these patterns.
27    Whether a frame is considered to originate in a certain module
28    is determined by the __name__ in the frame globals.
29    """
30
31    def __init__(self, skip=None):
32        self.skip = set(skip) if skip else None
33        self.breaks = {}
34        self.fncache = {}
35        self.frame_returning = None
36
37    def canonic(self, filename):
38        """Return canonical form of filename.
39
40        For real filenames, the canonical form is a case-normalized (on
41        case insensitive filesystems) absolute path.  'Filenames' with
42        angle brackets, such as "<stdin>", generated in interactive
43        mode, are returned unchanged.
44        """
45        if filename == "<" + filename[1:-1] + ">":
46            return filename
47        canonic = self.fncache.get(filename)
48        if not canonic:
49            canonic = os.path.abspath(filename)
50            canonic = os.path.normcase(canonic)
51            self.fncache[filename] = canonic
52        return canonic
53
54    def reset(self):
55        """Set values of attributes as ready to start debugging."""
56        import linecache
57        linecache.checkcache()
58        self.botframe = None
59        self._set_stopinfo(None, None)
60
61    def trace_dispatch(self, frame, event, arg):
62        """Dispatch a trace function for debugged frames based on the event.
63
64        This function is installed as the trace function for debugged
65        frames. Its return value is the new trace function, which is
66        usually itself. The default implementation decides how to
67        dispatch a frame, depending on the type of event (passed in as a
68        string) that is about to be executed.
69
70        The event can be one of the following:
71            line: A new line of code is going to be executed.
72            call: A function is about to be called or another code block
73                  is entered.
74            return: A function or other code block is about to return.
75            exception: An exception has occurred.
76            c_call: A C function is about to be called.
77            c_return: A C function has returned.
78            c_exception: A C function has raised an exception.
79
80        For the Python events, specialized functions (see the dispatch_*()
81        methods) are called.  For the C events, no action is taken.
82
83        The arg parameter depends on the previous event.
84        """
85        if self.quitting:
86            return # None
87        if event == 'line':
88            return self.dispatch_line(frame)
89        if event == 'call':
90            return self.dispatch_call(frame, arg)
91        if event == 'return':
92            return self.dispatch_return(frame, arg)
93        if event == 'exception':
94            return self.dispatch_exception(frame, arg)
95        if event == 'c_call':
96            return self.trace_dispatch
97        if event == 'c_exception':
98            return self.trace_dispatch
99        if event == 'c_return':
100            return self.trace_dispatch
101        print('bdb.Bdb.dispatch: unknown debugging event:', repr(event))
102        return self.trace_dispatch
103
104    def dispatch_line(self, frame):
105        """Invoke user function and return trace function for line event.
106
107        If the debugger stops on the current line, invoke
108        self.user_line(). Raise BdbQuit if self.quitting is set.
109        Return self.trace_dispatch to continue tracing in this scope.
110        """
111        if self.stop_here(frame) or self.break_here(frame):
112            self.user_line(frame)
113            if self.quitting: raise BdbQuit
114        return self.trace_dispatch
115
116    def dispatch_call(self, frame, arg):
117        """Invoke user function and return trace function for call event.
118
119        If the debugger stops on this function call, invoke
120        self.user_call(). Raise BbdQuit if self.quitting is set.
121        Return self.trace_dispatch to continue tracing in this scope.
122        """
123        # XXX 'arg' is no longer used
124        if self.botframe is None:
125            # First call of dispatch since reset()
126            self.botframe = frame.f_back # (CT) Note that this may also be None!
127            return self.trace_dispatch
128        if not (self.stop_here(frame) or self.break_anywhere(frame)):
129            # No need to trace this function
130            return # None
131        # Ignore call events in generator except when stepping.
132        if self.stopframe and frame.f_code.co_flags & GENERATOR_AND_COROUTINE_FLAGS:
133            return self.trace_dispatch
134        self.user_call(frame, arg)
135        if self.quitting: raise BdbQuit
136        return self.trace_dispatch
137
138    def dispatch_return(self, frame, arg):
139        """Invoke user function and return trace function for return event.
140
141        If the debugger stops on this function return, invoke
142        self.user_return(). Raise BdbQuit if self.quitting is set.
143        Return self.trace_dispatch to continue tracing in this scope.
144        """
145        if self.stop_here(frame) or frame == self.returnframe:
146            # Ignore return events in generator except when stepping.
147            if self.stopframe and frame.f_code.co_flags & GENERATOR_AND_COROUTINE_FLAGS:
148                return self.trace_dispatch
149            try:
150                self.frame_returning = frame
151                self.user_return(frame, arg)
152            finally:
153                self.frame_returning = None
154            if self.quitting: raise BdbQuit
155            # The user issued a 'next' or 'until' command.
156            if self.stopframe is frame and self.stoplineno != -1:
157                self._set_stopinfo(None, None)
158        return self.trace_dispatch
159
160    def dispatch_exception(self, frame, arg):
161        """Invoke user function and return trace function for exception event.
162
163        If the debugger stops on this exception, invoke
164        self.user_exception(). Raise BdbQuit if self.quitting is set.
165        Return self.trace_dispatch to continue tracing in this scope.
166        """
167        if self.stop_here(frame):
168            # When stepping with next/until/return in a generator frame, skip
169            # the internal StopIteration exception (with no traceback)
170            # triggered by a subiterator run with the 'yield from' statement.
171            if not (frame.f_code.co_flags & GENERATOR_AND_COROUTINE_FLAGS
172                    and arg[0] is StopIteration and arg[2] is None):
173                self.user_exception(frame, arg)
174                if self.quitting: raise BdbQuit
175        # Stop at the StopIteration or GeneratorExit exception when the user
176        # has set stopframe in a generator by issuing a return command, or a
177        # next/until command at the last statement in the generator before the
178        # exception.
179        elif (self.stopframe and frame is not self.stopframe
180                and self.stopframe.f_code.co_flags & GENERATOR_AND_COROUTINE_FLAGS
181                and arg[0] in (StopIteration, GeneratorExit)):
182            self.user_exception(frame, arg)
183            if self.quitting: raise BdbQuit
184
185        return self.trace_dispatch
186
187    # Normally derived classes don't override the following
188    # methods, but they may if they want to redefine the
189    # definition of stopping and breakpoints.
190
191    def is_skipped_module(self, module_name):
192        "Return True if module_name matches any skip pattern."
193        if module_name is None:  # some modules do not have names
194            return False
195        for pattern in self.skip:
196            if fnmatch.fnmatch(module_name, pattern):
197                return True
198        return False
199
200    def stop_here(self, frame):
201        "Return True if frame is below the starting frame in the stack."
202        # (CT) stopframe may now also be None, see dispatch_call.
203        # (CT) the former test for None is therefore removed from here.
204        if self.skip and \
205               self.is_skipped_module(frame.f_globals.get('__name__')):
206            return False
207        if frame is self.stopframe:
208            if self.stoplineno == -1:
209                return False
210            return frame.f_lineno >= self.stoplineno
211        if not self.stopframe:
212            return True
213        return False
214
215    def break_here(self, frame):
216        """Return True if there is an effective breakpoint for this line.
217
218        Check for line or function breakpoint and if in effect.
219        Delete temporary breakpoints if effective() says to.
220        """
221        filename = self.canonic(frame.f_code.co_filename)
222        if filename not in self.breaks:
223            return False
224        lineno = frame.f_lineno
225        if lineno not in self.breaks[filename]:
226            # The line itself has no breakpoint, but maybe the line is the
227            # first line of a function with breakpoint set by function name.
228            lineno = frame.f_code.co_firstlineno
229            if lineno not in self.breaks[filename]:
230                return False
231
232        # flag says ok to delete temp. bp
233        (bp, flag) = effective(filename, lineno, frame)
234        if bp:
235            self.currentbp = bp.number
236            if (flag and bp.temporary):
237                self.do_clear(str(bp.number))
238            return True
239        else:
240            return False
241
242    def do_clear(self, arg):
243        """Remove temporary breakpoint.
244
245        Must implement in derived classes or get NotImplementedError.
246        """
247        raise NotImplementedError("subclass of bdb must implement do_clear()")
248
249    def break_anywhere(self, frame):
250        """Return True if there is any breakpoint for frame's filename.
251        """
252        return self.canonic(frame.f_code.co_filename) in self.breaks
253
254    # Derived classes should override the user_* methods
255    # to gain control.
256
257    def user_call(self, frame, argument_list):
258        """Called if we might stop in a function."""
259        pass
260
261    def user_line(self, frame):
262        """Called when we stop or break at a line."""
263        pass
264
265    def user_return(self, frame, return_value):
266        """Called when a return trap is set here."""
267        pass
268
269    def user_exception(self, frame, exc_info):
270        """Called when we stop on an exception."""
271        pass
272
273    def _set_stopinfo(self, stopframe, returnframe, stoplineno=0):
274        """Set the attributes for stopping.
275
276        If stoplineno is greater than or equal to 0, then stop at line
277        greater than or equal to the stopline.  If stoplineno is -1, then
278        don't stop at all.
279        """
280        self.stopframe = stopframe
281        self.returnframe = returnframe
282        self.quitting = False
283        # stoplineno >= 0 means: stop at line >= the stoplineno
284        # stoplineno -1 means: don't stop at all
285        self.stoplineno = stoplineno
286
287    # Derived classes and clients can call the following methods
288    # to affect the stepping state.
289
290    def set_until(self, frame, lineno=None):
291        """Stop when the line with the lineno greater than the current one is
292        reached or when returning from current frame."""
293        # the name "until" is borrowed from gdb
294        if lineno is None:
295            lineno = frame.f_lineno + 1
296        self._set_stopinfo(frame, frame, lineno)
297
298    def set_step(self):
299        """Stop after one line of code."""
300        # Issue #13183: pdb skips frames after hitting a breakpoint and running
301        # step commands.
302        # Restore the trace function in the caller (that may not have been set
303        # for performance reasons) when returning from the current frame.
304        if self.frame_returning:
305            caller_frame = self.frame_returning.f_back
306            if caller_frame and not caller_frame.f_trace:
307                caller_frame.f_trace = self.trace_dispatch
308        self._set_stopinfo(None, None)
309
310    def set_next(self, frame):
311        """Stop on the next line in or below the given frame."""
312        self._set_stopinfo(frame, None)
313
314    def set_return(self, frame):
315        """Stop when returning from the given frame."""
316        if frame.f_code.co_flags & GENERATOR_AND_COROUTINE_FLAGS:
317            self._set_stopinfo(frame, None, -1)
318        else:
319            self._set_stopinfo(frame.f_back, frame)
320
321    def set_trace(self, frame=None):
322        """Start debugging from frame.
323
324        If frame is not specified, debugging starts from caller's frame.
325        """
326        if frame is None:
327            frame = sys._getframe().f_back
328        self.reset()
329        while frame:
330            frame.f_trace = self.trace_dispatch
331            self.botframe = frame
332            frame = frame.f_back
333        self.set_step()
334        sys.settrace(self.trace_dispatch)
335
336    def set_continue(self):
337        """Stop only at breakpoints or when finished.
338
339        If there are no breakpoints, set the system trace function to None.
340        """
341        # Don't stop except at breakpoints or when finished
342        self._set_stopinfo(self.botframe, None, -1)
343        if not self.breaks:
344            # no breakpoints; run without debugger overhead
345            sys.settrace(None)
346            frame = sys._getframe().f_back
347            while frame and frame is not self.botframe:
348                del frame.f_trace
349                frame = frame.f_back
350
351    def set_quit(self):
352        """Set quitting attribute to True.
353
354        Raises BdbQuit exception in the next call to a dispatch_*() method.
355        """
356        self.stopframe = self.botframe
357        self.returnframe = None
358        self.quitting = True
359        sys.settrace(None)
360
361    # Derived classes and clients can call the following methods
362    # to manipulate breakpoints.  These methods return an
363    # error message if something went wrong, None if all is well.
364    # Set_break prints out the breakpoint line and file:lineno.
365    # Call self.get_*break*() to see the breakpoints or better
366    # for bp in Breakpoint.bpbynumber: if bp: bp.bpprint().
367
368    def set_break(self, filename, lineno, temporary=False, cond=None,
369                  funcname=None):
370        """Set a new breakpoint for filename:lineno.
371
372        If lineno doesn't exist for the filename, return an error message.
373        The filename should be in canonical form.
374        """
375        filename = self.canonic(filename)
376        import linecache # Import as late as possible
377        line = linecache.getline(filename, lineno)
378        if not line:
379            return 'Line %s:%d does not exist' % (filename, lineno)
380        list = self.breaks.setdefault(filename, [])
381        if lineno not in list:
382            list.append(lineno)
383        bp = Breakpoint(filename, lineno, temporary, cond, funcname)
384        return None
385
386    def _prune_breaks(self, filename, lineno):
387        """Prune breakpoints for filename:lineno.
388
389        A list of breakpoints is maintained in the Bdb instance and in
390        the Breakpoint class.  If a breakpoint in the Bdb instance no
391        longer exists in the Breakpoint class, then it's removed from the
392        Bdb instance.
393        """
394        if (filename, lineno) not in Breakpoint.bplist:
395            self.breaks[filename].remove(lineno)
396        if not self.breaks[filename]:
397            del self.breaks[filename]
398
399    def clear_break(self, filename, lineno):
400        """Delete breakpoints for filename:lineno.
401
402        If no breakpoints were set, return an error message.
403        """
404        filename = self.canonic(filename)
405        if filename not in self.breaks:
406            return 'There are no breakpoints in %s' % filename
407        if lineno not in self.breaks[filename]:
408            return 'There is no breakpoint at %s:%d' % (filename, lineno)
409        # If there's only one bp in the list for that file,line
410        # pair, then remove the breaks entry
411        for bp in Breakpoint.bplist[filename, lineno][:]:
412            bp.deleteMe()
413        self._prune_breaks(filename, lineno)
414        return None
415
416    def clear_bpbynumber(self, arg):
417        """Delete a breakpoint by its index in Breakpoint.bpbynumber.
418
419        If arg is invalid, return an error message.
420        """
421        try:
422            bp = self.get_bpbynumber(arg)
423        except ValueError as err:
424            return str(err)
425        bp.deleteMe()
426        self._prune_breaks(bp.file, bp.line)
427        return None
428
429    def clear_all_file_breaks(self, filename):
430        """Delete all breakpoints in filename.
431
432        If none were set, return an error message.
433        """
434        filename = self.canonic(filename)
435        if filename not in self.breaks:
436            return 'There are no breakpoints in %s' % filename
437        for line in self.breaks[filename]:
438            blist = Breakpoint.bplist[filename, line]
439            for bp in blist:
440                bp.deleteMe()
441        del self.breaks[filename]
442        return None
443
444    def clear_all_breaks(self):
445        """Delete all existing breakpoints.
446
447        If none were set, return an error message.
448        """
449        if not self.breaks:
450            return 'There are no breakpoints'
451        for bp in Breakpoint.bpbynumber:
452            if bp:
453                bp.deleteMe()
454        self.breaks = {}
455        return None
456
457    def get_bpbynumber(self, arg):
458        """Return a breakpoint by its index in Breakpoint.bybpnumber.
459
460        For invalid arg values or if the breakpoint doesn't exist,
461        raise a ValueError.
462        """
463        if not arg:
464            raise ValueError('Breakpoint number expected')
465        try:
466            number = int(arg)
467        except ValueError:
468            raise ValueError('Non-numeric breakpoint number %s' % arg) from None
469        try:
470            bp = Breakpoint.bpbynumber[number]
471        except IndexError:
472            raise ValueError('Breakpoint number %d out of range' % number) from None
473        if bp is None:
474            raise ValueError('Breakpoint %d already deleted' % number)
475        return bp
476
477    def get_break(self, filename, lineno):
478        """Return True if there is a breakpoint for filename:lineno."""
479        filename = self.canonic(filename)
480        return filename in self.breaks and \
481            lineno in self.breaks[filename]
482
483    def get_breaks(self, filename, lineno):
484        """Return all breakpoints for filename:lineno.
485
486        If no breakpoints are set, return an empty list.
487        """
488        filename = self.canonic(filename)
489        return filename in self.breaks and \
490            lineno in self.breaks[filename] and \
491            Breakpoint.bplist[filename, lineno] or []
492
493    def get_file_breaks(self, filename):
494        """Return all lines with breakpoints for filename.
495
496        If no breakpoints are set, return an empty list.
497        """
498        filename = self.canonic(filename)
499        if filename in self.breaks:
500            return self.breaks[filename]
501        else:
502            return []
503
504    def get_all_breaks(self):
505        """Return all breakpoints that are set."""
506        return self.breaks
507
508    # Derived classes and clients can call the following method
509    # to get a data structure representing a stack trace.
510
511    def get_stack(self, f, t):
512        """Return a list of (frame, lineno) in a stack trace and a size.
513
514        List starts with original calling frame, if there is one.
515        Size may be number of frames above or below f.
516        """
517        stack = []
518        if t and t.tb_frame is f:
519            t = t.tb_next
520        while f is not None:
521            stack.append((f, f.f_lineno))
522            if f is self.botframe:
523                break
524            f = f.f_back
525        stack.reverse()
526        i = max(0, len(stack) - 1)
527        while t is not None:
528            stack.append((t.tb_frame, t.tb_lineno))
529            t = t.tb_next
530        if f is None:
531            i = max(0, len(stack) - 1)
532        return stack, i
533
534    def format_stack_entry(self, frame_lineno, lprefix=': '):
535        """Return a string with information about a stack entry.
536
537        The stack entry frame_lineno is a (frame, lineno) tuple.  The
538        return string contains the canonical filename, the function name
539        or '<lambda>', the input arguments, the return value, and the
540        line of code (if it exists).
541
542        """
543        import linecache, reprlib
544        frame, lineno = frame_lineno
545        filename = self.canonic(frame.f_code.co_filename)
546        s = '%s(%r)' % (filename, lineno)
547        if frame.f_code.co_name:
548            s += frame.f_code.co_name
549        else:
550            s += "<lambda>"
551        if '__args__' in frame.f_locals:
552            args = frame.f_locals['__args__']
553        else:
554            args = None
555        if args:
556            s += reprlib.repr(args)
557        else:
558            s += '()'
559        if '__return__' in frame.f_locals:
560            rv = frame.f_locals['__return__']
561            s += '->'
562            s += reprlib.repr(rv)
563        line = linecache.getline(filename, lineno, frame.f_globals)
564        if line:
565            s += lprefix + line.strip()
566        return s
567
568    # The following methods can be called by clients to use
569    # a debugger to debug a statement or an expression.
570    # Both can be given as a string, or a code object.
571
572    def run(self, cmd, globals=None, locals=None):
573        """Debug a statement executed via the exec() function.
574
575        globals defaults to __main__.dict; locals defaults to globals.
576        """
577        if globals is None:
578            import __main__
579            globals = __main__.__dict__
580        if locals is None:
581            locals = globals
582        self.reset()
583        if isinstance(cmd, str):
584            cmd = compile(cmd, "<string>", "exec")
585        sys.settrace(self.trace_dispatch)
586        try:
587            exec(cmd, globals, locals)
588        except BdbQuit:
589            pass
590        finally:
591            self.quitting = True
592            sys.settrace(None)
593
594    def runeval(self, expr, globals=None, locals=None):
595        """Debug an expression executed via the eval() function.
596
597        globals defaults to __main__.dict; locals defaults to globals.
598        """
599        if globals is None:
600            import __main__
601            globals = __main__.__dict__
602        if locals is None:
603            locals = globals
604        self.reset()
605        sys.settrace(self.trace_dispatch)
606        try:
607            return eval(expr, globals, locals)
608        except BdbQuit:
609            pass
610        finally:
611            self.quitting = True
612            sys.settrace(None)
613
614    def runctx(self, cmd, globals, locals):
615        """For backwards-compatibility.  Defers to run()."""
616        # B/W compatibility
617        self.run(cmd, globals, locals)
618
619    # This method is more useful to debug a single function call.
620
621    def runcall(*args, **kwds):
622        """Debug a single function call.
623
624        Return the result of the function call.
625        """
626        if len(args) >= 2:
627            self, func, *args = args
628        elif not args:
629            raise TypeError("descriptor 'runcall' of 'Bdb' object "
630                            "needs an argument")
631        elif 'func' in kwds:
632            func = kwds.pop('func')
633            self, *args = args
634            import warnings
635            warnings.warn("Passing 'func' as keyword argument is deprecated",
636                          DeprecationWarning, stacklevel=2)
637        else:
638            raise TypeError('runcall expected at least 1 positional argument, '
639                            'got %d' % (len(args)-1))
640
641        self.reset()
642        sys.settrace(self.trace_dispatch)
643        res = None
644        try:
645            res = func(*args, **kwds)
646        except BdbQuit:
647            pass
648        finally:
649            self.quitting = True
650            sys.settrace(None)
651        return res
652    runcall.__text_signature__ = '($self, func, /, *args, **kwds)'
653
654
655def set_trace():
656    """Start debugging with a Bdb instance from the caller's frame."""
657    Bdb().set_trace()
658
659
660class Breakpoint:
661    """Breakpoint class.
662
663    Implements temporary breakpoints, ignore counts, disabling and
664    (re)-enabling, and conditionals.
665
666    Breakpoints are indexed by number through bpbynumber and by
667    the (file, line) tuple using bplist.  The former points to a
668    single instance of class Breakpoint.  The latter points to a
669    list of such instances since there may be more than one
670    breakpoint per line.
671
672    When creating a breakpoint, its associated filename should be
673    in canonical form.  If funcname is defined, a breakpoint hit will be
674    counted when the first line of that function is executed.  A
675    conditional breakpoint always counts a hit.
676    """
677
678    # XXX Keeping state in the class is a mistake -- this means
679    # you cannot have more than one active Bdb instance.
680
681    next = 1        # Next bp to be assigned
682    bplist = {}     # indexed by (file, lineno) tuple
683    bpbynumber = [None] # Each entry is None or an instance of Bpt
684                # index 0 is unused, except for marking an
685                # effective break .... see effective()
686
687    def __init__(self, file, line, temporary=False, cond=None, funcname=None):
688        self.funcname = funcname
689        # Needed if funcname is not None.
690        self.func_first_executable_line = None
691        self.file = file    # This better be in canonical form!
692        self.line = line
693        self.temporary = temporary
694        self.cond = cond
695        self.enabled = True
696        self.ignore = 0
697        self.hits = 0
698        self.number = Breakpoint.next
699        Breakpoint.next += 1
700        # Build the two lists
701        self.bpbynumber.append(self)
702        if (file, line) in self.bplist:
703            self.bplist[file, line].append(self)
704        else:
705            self.bplist[file, line] = [self]
706
707    def deleteMe(self):
708        """Delete the breakpoint from the list associated to a file:line.
709
710        If it is the last breakpoint in that position, it also deletes
711        the entry for the file:line.
712        """
713
714        index = (self.file, self.line)
715        self.bpbynumber[self.number] = None   # No longer in list
716        self.bplist[index].remove(self)
717        if not self.bplist[index]:
718            # No more bp for this f:l combo
719            del self.bplist[index]
720
721    def enable(self):
722        """Mark the breakpoint as enabled."""
723        self.enabled = True
724
725    def disable(self):
726        """Mark the breakpoint as disabled."""
727        self.enabled = False
728
729    def bpprint(self, out=None):
730        """Print the output of bpformat().
731
732        The optional out argument directs where the output is sent
733        and defaults to standard output.
734        """
735        if out is None:
736            out = sys.stdout
737        print(self.bpformat(), file=out)
738
739    def bpformat(self):
740        """Return a string with information about the breakpoint.
741
742        The information includes the breakpoint number, temporary
743        status, file:line position, break condition, number of times to
744        ignore, and number of times hit.
745
746        """
747        if self.temporary:
748            disp = 'del  '
749        else:
750            disp = 'keep '
751        if self.enabled:
752            disp = disp + 'yes  '
753        else:
754            disp = disp + 'no   '
755        ret = '%-4dbreakpoint   %s at %s:%d' % (self.number, disp,
756                                                self.file, self.line)
757        if self.cond:
758            ret += '\n\tstop only if %s' % (self.cond,)
759        if self.ignore:
760            ret += '\n\tignore next %d hits' % (self.ignore,)
761        if self.hits:
762            if self.hits > 1:
763                ss = 's'
764            else:
765                ss = ''
766            ret += '\n\tbreakpoint already hit %d time%s' % (self.hits, ss)
767        return ret
768
769    def __str__(self):
770        "Return a condensed description of the breakpoint."
771        return 'breakpoint %s at %s:%s' % (self.number, self.file, self.line)
772
773# -----------end of Breakpoint class----------
774
775
776def checkfuncname(b, frame):
777    """Return True if break should happen here.
778
779    Whether a break should happen depends on the way that b (the breakpoint)
780    was set.  If it was set via line number, check if b.line is the same as
781    the one in the frame.  If it was set via function name, check if this is
782    the right function and if it is on the first executable line.
783    """
784    if not b.funcname:
785        # Breakpoint was set via line number.
786        if b.line != frame.f_lineno:
787            # Breakpoint was set at a line with a def statement and the function
788            # defined is called: don't break.
789            return False
790        return True
791
792    # Breakpoint set via function name.
793    if frame.f_code.co_name != b.funcname:
794        # It's not a function call, but rather execution of def statement.
795        return False
796
797    # We are in the right frame.
798    if not b.func_first_executable_line:
799        # The function is entered for the 1st time.
800        b.func_first_executable_line = frame.f_lineno
801
802    if b.func_first_executable_line != frame.f_lineno:
803        # But we are not at the first line number: don't break.
804        return False
805    return True
806
807
808# Determines if there is an effective (active) breakpoint at this
809# line of code.  Returns breakpoint number or 0 if none
810def effective(file, line, frame):
811    """Determine which breakpoint for this file:line is to be acted upon.
812
813    Called only if we know there is a breakpoint at this location.  Return
814    the breakpoint that was triggered and a boolean that indicates if it is
815    ok to delete a temporary breakpoint.  Return (None, None) if there is no
816    matching breakpoint.
817    """
818    possibles = Breakpoint.bplist[file, line]
819    for b in possibles:
820        if not b.enabled:
821            continue
822        if not checkfuncname(b, frame):
823            continue
824        # Count every hit when bp is enabled
825        b.hits += 1
826        if not b.cond:
827            # If unconditional, and ignoring go on to next, else break
828            if b.ignore > 0:
829                b.ignore -= 1
830                continue
831            else:
832                # breakpoint and marker that it's ok to delete if temporary
833                return (b, True)
834        else:
835            # Conditional bp.
836            # Ignore count applies only to those bpt hits where the
837            # condition evaluates to true.
838            try:
839                val = eval(b.cond, frame.f_globals, frame.f_locals)
840                if val:
841                    if b.ignore > 0:
842                        b.ignore -= 1
843                        # continue
844                    else:
845                        return (b, True)
846                # else:
847                #   continue
848            except:
849                # if eval fails, most conservative thing is to stop on
850                # breakpoint regardless of ignore count.  Don't delete
851                # temporary, as another hint to user.
852                return (b, False)
853    return (None, None)
854
855
856# -------------------- testing --------------------
857
858class Tdb(Bdb):
859    def user_call(self, frame, args):
860        name = frame.f_code.co_name
861        if not name: name = '???'
862        print('+++ call', name, args)
863    def user_line(self, frame):
864        import linecache
865        name = frame.f_code.co_name
866        if not name: name = '???'
867        fn = self.canonic(frame.f_code.co_filename)
868        line = linecache.getline(fn, frame.f_lineno, frame.f_globals)
869        print('+++', fn, frame.f_lineno, name, ':', line.strip())
870    def user_return(self, frame, retval):
871        print('+++ return', retval)
872    def user_exception(self, frame, exc_stuff):
873        print('+++ exception', exc_stuff)
874        self.set_continue()
875
876def foo(n):
877    print('foo(', n, ')')
878    x = bar(n*10)
879    print('bar returned', x)
880
881def bar(a):
882    print('bar(', a, ')')
883    return a/2
884
885def test():
886    t = Tdb()
887    t.run('import bdb; bdb.foo(10)')
888