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 insenstive 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        for pattern in self.skip:
194            if fnmatch.fnmatch(module_name, pattern):
195                return True
196        return False
197
198    def stop_here(self, frame):
199        "Return True if frame is below the starting frame in the stack."
200        # (CT) stopframe may now also be None, see dispatch_call.
201        # (CT) the former test for None is therefore removed from here.
202        if self.skip and \
203               self.is_skipped_module(frame.f_globals.get('__name__')):
204            return False
205        if frame is self.stopframe:
206            if self.stoplineno == -1:
207                return False
208            return frame.f_lineno >= self.stoplineno
209        if not self.stopframe:
210            return True
211        return False
212
213    def break_here(self, frame):
214        """Return True if there is an effective breakpoint for this line.
215
216        Check for line or function breakpoint and if in effect.
217        Delete temporary breakpoints if effective() says to.
218        """
219        filename = self.canonic(frame.f_code.co_filename)
220        if filename not in self.breaks:
221            return False
222        lineno = frame.f_lineno
223        if lineno not in self.breaks[filename]:
224            # The line itself has no breakpoint, but maybe the line is the
225            # first line of a function with breakpoint set by function name.
226            lineno = frame.f_code.co_firstlineno
227            if lineno not in self.breaks[filename]:
228                return False
229
230        # flag says ok to delete temp. bp
231        (bp, flag) = effective(filename, lineno, frame)
232        if bp:
233            self.currentbp = bp.number
234            if (flag and bp.temporary):
235                self.do_clear(str(bp.number))
236            return True
237        else:
238            return False
239
240    def do_clear(self, arg):
241        """Remove temporary breakpoint.
242
243        Must implement in derived classes or get NotImplementedError.
244        """
245        raise NotImplementedError("subclass of bdb must implement do_clear()")
246
247    def break_anywhere(self, frame):
248        """Return True if there is any breakpoint for frame's filename.
249        """
250        return self.canonic(frame.f_code.co_filename) in self.breaks
251
252    # Derived classes should override the user_* methods
253    # to gain control.
254
255    def user_call(self, frame, argument_list):
256        """Called if we might stop in a function."""
257        pass
258
259    def user_line(self, frame):
260        """Called when we stop or break at a line."""
261        pass
262
263    def user_return(self, frame, return_value):
264        """Called when a return trap is set here."""
265        pass
266
267    def user_exception(self, frame, exc_info):
268        """Called when we stop on an exception."""
269        pass
270
271    def _set_stopinfo(self, stopframe, returnframe, stoplineno=0):
272        """Set the attributes for stopping.
273
274        If stoplineno is greater than or equal to 0, then stop at line
275        greater than or equal to the stopline.  If stoplineno is -1, then
276        don't stop at all.
277        """
278        self.stopframe = stopframe
279        self.returnframe = returnframe
280        self.quitting = False
281        # stoplineno >= 0 means: stop at line >= the stoplineno
282        # stoplineno -1 means: don't stop at all
283        self.stoplineno = stoplineno
284
285    # Derived classes and clients can call the following methods
286    # to affect the stepping state.
287
288    def set_until(self, frame, lineno=None):
289        """Stop when the line with the lineno greater than the current one is
290        reached or when returning from current frame."""
291        # the name "until" is borrowed from gdb
292        if lineno is None:
293            lineno = frame.f_lineno + 1
294        self._set_stopinfo(frame, frame, lineno)
295
296    def set_step(self):
297        """Stop after one line of code."""
298        # Issue #13183: pdb skips frames after hitting a breakpoint and running
299        # step commands.
300        # Restore the trace function in the caller (that may not have been set
301        # for performance reasons) when returning from the current frame.
302        if self.frame_returning:
303            caller_frame = self.frame_returning.f_back
304            if caller_frame and not caller_frame.f_trace:
305                caller_frame.f_trace = self.trace_dispatch
306        self._set_stopinfo(None, None)
307
308    def set_next(self, frame):
309        """Stop on the next line in or below the given frame."""
310        self._set_stopinfo(frame, None)
311
312    def set_return(self, frame):
313        """Stop when returning from the given frame."""
314        if frame.f_code.co_flags & GENERATOR_AND_COROUTINE_FLAGS:
315            self._set_stopinfo(frame, None, -1)
316        else:
317            self._set_stopinfo(frame.f_back, frame)
318
319    def set_trace(self, frame=None):
320        """Start debugging from frame.
321
322        If frame is not specified, debugging starts from caller's frame.
323        """
324        if frame is None:
325            frame = sys._getframe().f_back
326        self.reset()
327        while frame:
328            frame.f_trace = self.trace_dispatch
329            self.botframe = frame
330            frame = frame.f_back
331        self.set_step()
332        sys.settrace(self.trace_dispatch)
333
334    def set_continue(self):
335        """Stop only at breakpoints or when finished.
336
337        If there are no breakpoints, set the system trace function to None.
338        """
339        # Don't stop except at breakpoints or when finished
340        self._set_stopinfo(self.botframe, None, -1)
341        if not self.breaks:
342            # no breakpoints; run without debugger overhead
343            sys.settrace(None)
344            frame = sys._getframe().f_back
345            while frame and frame is not self.botframe:
346                del frame.f_trace
347                frame = frame.f_back
348
349    def set_quit(self):
350        """Set quitting attribute to True.
351
352        Raises BdbQuit exception in the next call to a dispatch_*() method.
353        """
354        self.stopframe = self.botframe
355        self.returnframe = None
356        self.quitting = True
357        sys.settrace(None)
358
359    # Derived classes and clients can call the following methods
360    # to manipulate breakpoints.  These methods return an
361    # error message if something went wrong, None if all is well.
362    # Set_break prints out the breakpoint line and file:lineno.
363    # Call self.get_*break*() to see the breakpoints or better
364    # for bp in Breakpoint.bpbynumber: if bp: bp.bpprint().
365
366    def set_break(self, filename, lineno, temporary=False, cond=None,
367                  funcname=None):
368        """Set a new breakpoint for filename:lineno.
369
370        If lineno doesn't exist for the filename, return an error message.
371        The filename should be in canonical form.
372        """
373        filename = self.canonic(filename)
374        import linecache # Import as late as possible
375        line = linecache.getline(filename, lineno)
376        if not line:
377            return 'Line %s:%d does not exist' % (filename, lineno)
378        list = self.breaks.setdefault(filename, [])
379        if lineno not in list:
380            list.append(lineno)
381        bp = Breakpoint(filename, lineno, temporary, cond, funcname)
382        return None
383
384    def _prune_breaks(self, filename, lineno):
385        """Prune breakpoints for filname:lineno.
386
387        A list of breakpoints is maintained in the Bdb instance and in
388        the Breakpoint class.  If a breakpoint in the Bdb instance no
389        longer exists in the Breakpoint class, then it's removed from the
390        Bdb instance.
391        """
392        if (filename, lineno) not in Breakpoint.bplist:
393            self.breaks[filename].remove(lineno)
394        if not self.breaks[filename]:
395            del self.breaks[filename]
396
397    def clear_break(self, filename, lineno):
398        """Delete breakpoints for filename:lineno.
399
400        If no breakpoints were set, return an error message.
401        """
402        filename = self.canonic(filename)
403        if filename not in self.breaks:
404            return 'There are no breakpoints in %s' % filename
405        if lineno not in self.breaks[filename]:
406            return 'There is no breakpoint at %s:%d' % (filename, lineno)
407        # If there's only one bp in the list for that file,line
408        # pair, then remove the breaks entry
409        for bp in Breakpoint.bplist[filename, lineno][:]:
410            bp.deleteMe()
411        self._prune_breaks(filename, lineno)
412        return None
413
414    def clear_bpbynumber(self, arg):
415        """Delete a breakpoint by its index in Breakpoint.bpbynumber.
416
417        If arg is invalid, return an error message.
418        """
419        try:
420            bp = self.get_bpbynumber(arg)
421        except ValueError as err:
422            return str(err)
423        bp.deleteMe()
424        self._prune_breaks(bp.file, bp.line)
425        return None
426
427    def clear_all_file_breaks(self, filename):
428        """Delete all breakpoints in filename.
429
430        If none were set, return an error message.
431        """
432        filename = self.canonic(filename)
433        if filename not in self.breaks:
434            return 'There are no breakpoints in %s' % filename
435        for line in self.breaks[filename]:
436            blist = Breakpoint.bplist[filename, line]
437            for bp in blist:
438                bp.deleteMe()
439        del self.breaks[filename]
440        return None
441
442    def clear_all_breaks(self):
443        """Delete all existing breakpoints.
444
445        If none were set, return an error message.
446        """
447        if not self.breaks:
448            return 'There are no breakpoints'
449        for bp in Breakpoint.bpbynumber:
450            if bp:
451                bp.deleteMe()
452        self.breaks = {}
453        return None
454
455    def get_bpbynumber(self, arg):
456        """Return a breakpoint by its index in Breakpoint.bybpnumber.
457
458        For invalid arg values or if the breakpoint doesn't exist,
459        raise a ValueError.
460        """
461        if not arg:
462            raise ValueError('Breakpoint number expected')
463        try:
464            number = int(arg)
465        except ValueError:
466            raise ValueError('Non-numeric breakpoint number %s' % arg) from None
467        try:
468            bp = Breakpoint.bpbynumber[number]
469        except IndexError:
470            raise ValueError('Breakpoint number %d out of range' % number) from None
471        if bp is None:
472            raise ValueError('Breakpoint %d already deleted' % number)
473        return bp
474
475    def get_break(self, filename, lineno):
476        """Return True if there is a breakpoint for filename:lineno."""
477        filename = self.canonic(filename)
478        return filename in self.breaks and \
479            lineno in self.breaks[filename]
480
481    def get_breaks(self, filename, lineno):
482        """Return all breakpoints for filename:lineno.
483
484        If no breakpoints are set, return an empty list.
485        """
486        filename = self.canonic(filename)
487        return filename in self.breaks and \
488            lineno in self.breaks[filename] and \
489            Breakpoint.bplist[filename, lineno] or []
490
491    def get_file_breaks(self, filename):
492        """Return all lines with breakpoints for filename.
493
494        If no breakpoints are set, return an empty list.
495        """
496        filename = self.canonic(filename)
497        if filename in self.breaks:
498            return self.breaks[filename]
499        else:
500            return []
501
502    def get_all_breaks(self):
503        """Return all breakpoints that are set."""
504        return self.breaks
505
506    # Derived classes and clients can call the following method
507    # to get a data structure representing a stack trace.
508
509    def get_stack(self, f, t):
510        """Return a list of (frame, lineno) in a stack trace and a size.
511
512        List starts with original calling frame, if there is one.
513        Size may be number of frames above or below f.
514        """
515        stack = []
516        if t and t.tb_frame is f:
517            t = t.tb_next
518        while f is not None:
519            stack.append((f, f.f_lineno))
520            if f is self.botframe:
521                break
522            f = f.f_back
523        stack.reverse()
524        i = max(0, len(stack) - 1)
525        while t is not None:
526            stack.append((t.tb_frame, t.tb_lineno))
527            t = t.tb_next
528        if f is None:
529            i = max(0, len(stack) - 1)
530        return stack, i
531
532    def format_stack_entry(self, frame_lineno, lprefix=': '):
533        """Return a string with information about a stack entry.
534
535        The stack entry frame_lineno is a (frame, lineno) tuple.  The
536        return string contains the canonical filename, the function name
537        or '<lambda>', the input arguments, the return value, and the
538        line of code (if it exists).
539
540        """
541        import linecache, reprlib
542        frame, lineno = frame_lineno
543        filename = self.canonic(frame.f_code.co_filename)
544        s = '%s(%r)' % (filename, lineno)
545        if frame.f_code.co_name:
546            s += frame.f_code.co_name
547        else:
548            s += "<lambda>"
549        s += '()'
550        if '__return__' in frame.f_locals:
551            rv = frame.f_locals['__return__']
552            s += '->'
553            s += reprlib.repr(rv)
554        line = linecache.getline(filename, lineno, frame.f_globals)
555        if line:
556            s += lprefix + line.strip()
557        return s
558
559    # The following methods can be called by clients to use
560    # a debugger to debug a statement or an expression.
561    # Both can be given as a string, or a code object.
562
563    def run(self, cmd, globals=None, locals=None):
564        """Debug a statement executed via the exec() function.
565
566        globals defaults to __main__.dict; locals defaults to globals.
567        """
568        if globals is None:
569            import __main__
570            globals = __main__.__dict__
571        if locals is None:
572            locals = globals
573        self.reset()
574        if isinstance(cmd, str):
575            cmd = compile(cmd, "<string>", "exec")
576        sys.settrace(self.trace_dispatch)
577        try:
578            exec(cmd, globals, locals)
579        except BdbQuit:
580            pass
581        finally:
582            self.quitting = True
583            sys.settrace(None)
584
585    def runeval(self, expr, globals=None, locals=None):
586        """Debug an expression executed via the eval() function.
587
588        globals defaults to __main__.dict; locals defaults to globals.
589        """
590        if globals is None:
591            import __main__
592            globals = __main__.__dict__
593        if locals is None:
594            locals = globals
595        self.reset()
596        sys.settrace(self.trace_dispatch)
597        try:
598            return eval(expr, globals, locals)
599        except BdbQuit:
600            pass
601        finally:
602            self.quitting = True
603            sys.settrace(None)
604
605    def runctx(self, cmd, globals, locals):
606        """For backwards-compatibility.  Defers to run()."""
607        # B/W compatibility
608        self.run(cmd, globals, locals)
609
610    # This method is more useful to debug a single function call.
611
612    def runcall(*args, **kwds):
613        """Debug a single function call.
614
615        Return the result of the function call.
616        """
617        if len(args) >= 2:
618            self, func, *args = args
619        elif not args:
620            raise TypeError("descriptor 'runcall' of 'Bdb' object "
621                            "needs an argument")
622        elif 'func' in kwds:
623            func = kwds.pop('func')
624            self, *args = args
625        else:
626            raise TypeError('runcall expected at least 1 positional argument, '
627                            'got %d' % (len(args)-1))
628
629        self.reset()
630        sys.settrace(self.trace_dispatch)
631        res = None
632        try:
633            res = func(*args, **kwds)
634        except BdbQuit:
635            pass
636        finally:
637            self.quitting = True
638            sys.settrace(None)
639        return res
640
641
642def set_trace():
643    """Start debugging with a Bdb instance from the caller's frame."""
644    Bdb().set_trace()
645
646
647class Breakpoint:
648    """Breakpoint class.
649
650    Implements temporary breakpoints, ignore counts, disabling and
651    (re)-enabling, and conditionals.
652
653    Breakpoints are indexed by number through bpbynumber and by
654    the (file, line) tuple using bplist.  The former points to a
655    single instance of class Breakpoint.  The latter points to a
656    list of such instances since there may be more than one
657    breakpoint per line.
658
659    When creating a breakpoint, its associated filename should be
660    in canonical form.  If funcname is defined, a breakpoint hit will be
661    counted when the first line of that function is executed.  A
662    conditional breakpoint always counts a hit.
663    """
664
665    # XXX Keeping state in the class is a mistake -- this means
666    # you cannot have more than one active Bdb instance.
667
668    next = 1        # Next bp to be assigned
669    bplist = {}     # indexed by (file, lineno) tuple
670    bpbynumber = [None] # Each entry is None or an instance of Bpt
671                # index 0 is unused, except for marking an
672                # effective break .... see effective()
673
674    def __init__(self, file, line, temporary=False, cond=None, funcname=None):
675        self.funcname = funcname
676        # Needed if funcname is not None.
677        self.func_first_executable_line = None
678        self.file = file    # This better be in canonical form!
679        self.line = line
680        self.temporary = temporary
681        self.cond = cond
682        self.enabled = True
683        self.ignore = 0
684        self.hits = 0
685        self.number = Breakpoint.next
686        Breakpoint.next += 1
687        # Build the two lists
688        self.bpbynumber.append(self)
689        if (file, line) in self.bplist:
690            self.bplist[file, line].append(self)
691        else:
692            self.bplist[file, line] = [self]
693
694    def deleteMe(self):
695        """Delete the breakpoint from the list associated to a file:line.
696
697        If it is the last breakpoint in that position, it also deletes
698        the entry for the file:line.
699        """
700
701        index = (self.file, self.line)
702        self.bpbynumber[self.number] = None   # No longer in list
703        self.bplist[index].remove(self)
704        if not self.bplist[index]:
705            # No more bp for this f:l combo
706            del self.bplist[index]
707
708    def enable(self):
709        """Mark the breakpoint as enabled."""
710        self.enabled = True
711
712    def disable(self):
713        """Mark the breakpoint as disabled."""
714        self.enabled = False
715
716    def bpprint(self, out=None):
717        """Print the output of bpformat().
718
719        The optional out argument directs where the output is sent
720        and defaults to standard output.
721        """
722        if out is None:
723            out = sys.stdout
724        print(self.bpformat(), file=out)
725
726    def bpformat(self):
727        """Return a string with information about the breakpoint.
728
729        The information includes the breakpoint number, temporary
730        status, file:line position, break condition, number of times to
731        ignore, and number of times hit.
732
733        """
734        if self.temporary:
735            disp = 'del  '
736        else:
737            disp = 'keep '
738        if self.enabled:
739            disp = disp + 'yes  '
740        else:
741            disp = disp + 'no   '
742        ret = '%-4dbreakpoint   %s at %s:%d' % (self.number, disp,
743                                                self.file, self.line)
744        if self.cond:
745            ret += '\n\tstop only if %s' % (self.cond,)
746        if self.ignore:
747            ret += '\n\tignore next %d hits' % (self.ignore,)
748        if self.hits:
749            if self.hits > 1:
750                ss = 's'
751            else:
752                ss = ''
753            ret += '\n\tbreakpoint already hit %d time%s' % (self.hits, ss)
754        return ret
755
756    def __str__(self):
757        "Return a condensed description of the breakpoint."
758        return 'breakpoint %s at %s:%s' % (self.number, self.file, self.line)
759
760# -----------end of Breakpoint class----------
761
762
763def checkfuncname(b, frame):
764    """Return True if break should happen here.
765
766    Whether a break should happen depends on the way that b (the breakpoint)
767    was set.  If it was set via line number, check if b.line is the same as
768    the one in the frame.  If it was set via function name, check if this is
769    the right function and if it is on the first executable line.
770    """
771    if not b.funcname:
772        # Breakpoint was set via line number.
773        if b.line != frame.f_lineno:
774            # Breakpoint was set at a line with a def statement and the function
775            # defined is called: don't break.
776            return False
777        return True
778
779    # Breakpoint set via function name.
780    if frame.f_code.co_name != b.funcname:
781        # It's not a function call, but rather execution of def statement.
782        return False
783
784    # We are in the right frame.
785    if not b.func_first_executable_line:
786        # The function is entered for the 1st time.
787        b.func_first_executable_line = frame.f_lineno
788
789    if b.func_first_executable_line != frame.f_lineno:
790        # But we are not at the first line number: don't break.
791        return False
792    return True
793
794
795# Determines if there is an effective (active) breakpoint at this
796# line of code.  Returns breakpoint number or 0 if none
797def effective(file, line, frame):
798    """Determine which breakpoint for this file:line is to be acted upon.
799
800    Called only if we know there is a breakpoint at this location.  Return
801    the breakpoint that was triggered and a boolean that indicates if it is
802    ok to delete a temporary breakpoint.  Return (None, None) if there is no
803    matching breakpoint.
804    """
805    possibles = Breakpoint.bplist[file, line]
806    for b in possibles:
807        if not b.enabled:
808            continue
809        if not checkfuncname(b, frame):
810            continue
811        # Count every hit when bp is enabled
812        b.hits += 1
813        if not b.cond:
814            # If unconditional, and ignoring go on to next, else break
815            if b.ignore > 0:
816                b.ignore -= 1
817                continue
818            else:
819                # breakpoint and marker that it's ok to delete if temporary
820                return (b, True)
821        else:
822            # Conditional bp.
823            # Ignore count applies only to those bpt hits where the
824            # condition evaluates to true.
825            try:
826                val = eval(b.cond, frame.f_globals, frame.f_locals)
827                if val:
828                    if b.ignore > 0:
829                        b.ignore -= 1
830                        # continue
831                    else:
832                        return (b, True)
833                # else:
834                #   continue
835            except:
836                # if eval fails, most conservative thing is to stop on
837                # breakpoint regardless of ignore count.  Don't delete
838                # temporary, as another hint to user.
839                return (b, False)
840    return (None, None)
841
842
843# -------------------- testing --------------------
844
845class Tdb(Bdb):
846    def user_call(self, frame, args):
847        name = frame.f_code.co_name
848        if not name: name = '???'
849        print('+++ call', name, args)
850    def user_line(self, frame):
851        import linecache
852        name = frame.f_code.co_name
853        if not name: name = '???'
854        fn = self.canonic(frame.f_code.co_filename)
855        line = linecache.getline(fn, frame.f_lineno, frame.f_globals)
856        print('+++', fn, frame.f_lineno, name, ':', line.strip())
857    def user_return(self, frame, retval):
858        print('+++ return', retval)
859    def user_exception(self, frame, exc_stuff):
860        print('+++ exception', exc_stuff)
861        self.set_continue()
862
863def foo(n):
864    print('foo(', n, ')')
865    x = bar(n*10)
866    print('bar returned', x)
867
868def bar(a):
869    print('bar(', a, ')')
870    return a/2
871
872def test():
873    t = Tdb()
874    t.run('import bdb; bdb.foo(10)')
875