diff --git a/Lib/bdb.py b/Lib/bdb.py index 18491da897..75d6113576 100644 --- a/Lib/bdb.py +++ b/Lib/bdb.py @@ -34,6 +34,8 @@ class Bdb: self.fncache = {} self.frame_returning = None + self._load_breaks() + def canonic(self, filename): """Return canonical form of filename. @@ -117,7 +119,7 @@ class Bdb: """Invoke user function and return trace function for call event. If the debugger stops on this function call, invoke - self.user_call(). Raise BbdQuit if self.quitting is set. + self.user_call(). Raise BdbQuit if self.quitting is set. Return self.trace_dispatch to continue tracing in this scope. """ # XXX 'arg' is no longer used @@ -365,6 +367,12 @@ class Bdb: # Call self.get_*break*() to see the breakpoints or better # for bp in Breakpoint.bpbynumber: if bp: bp.bpprint(). + def _add_to_breaks(self, filename, lineno): + """Add breakpoint to breaks, if not already there.""" + bp_linenos = self.breaks.setdefault(filename, []) + if lineno not in bp_linenos: + bp_linenos.append(lineno) + def set_break(self, filename, lineno, temporary=False, cond=None, funcname=None): """Set a new breakpoint for filename:lineno. @@ -377,12 +385,21 @@ class Bdb: line = linecache.getline(filename, lineno) if not line: return 'Line %s:%d does not exist' % (filename, lineno) - list = self.breaks.setdefault(filename, []) - if lineno not in list: - list.append(lineno) + self._add_to_breaks(filename, lineno) bp = Breakpoint(filename, lineno, temporary, cond, funcname) return None + def _load_breaks(self): + """Apply all breakpoints (set in other instances) to this one. + + Populates this instance's breaks list from the Breakpoint class's + list, which can have breakpoints set by another Bdb instance. This + is necessary for interactive sessions to keep the breakpoints + active across multiple calls to run(). + """ + for (filename, lineno) in Breakpoint.bplist.keys(): + self._add_to_breaks(filename, lineno) + def _prune_breaks(self, filename, lineno): """Prune breakpoints for filename:lineno. @@ -611,26 +628,11 @@ class Bdb: # This method is more useful to debug a single function call. - def runcall(*args, **kwds): + def runcall(self, func, /, *args, **kwds): """Debug a single function call. Return the result of the function call. """ - if len(args) >= 2: - self, func, *args = args - elif not args: - raise TypeError("descriptor 'runcall' of 'Bdb' object " - "needs an argument") - elif 'func' in kwds: - func = kwds.pop('func') - self, *args = args - import warnings - warnings.warn("Passing 'func' as keyword argument is deprecated", - DeprecationWarning, stacklevel=2) - else: - raise TypeError('runcall expected at least 1 positional argument, ' - 'got %d' % (len(args)-1)) - self.reset() sys.settrace(self.trace_dispatch) res = None @@ -642,7 +644,6 @@ class Bdb: self.quitting = True sys.settrace(None) return res - runcall.__text_signature__ = '($self, func, /, *args, **kwds)' def set_trace(): @@ -697,6 +698,12 @@ class Breakpoint: else: self.bplist[file, line] = [self] + @staticmethod + def clearBreakpoints(): + Breakpoint.next = 1 + Breakpoint.bplist = {} + Breakpoint.bpbynumber = [None] + def deleteMe(self): """Delete the breakpoint from the list associated to a file:line.