diff --git a/Doc/library/bdb.rst b/Doc/library/bdb.rst index 85df7914a9a014..42817ec456af5d 100644 --- a/Doc/library/bdb.rst +++ b/Doc/library/bdb.rst @@ -20,16 +20,11 @@ The following exception is defined: The :mod:`bdb` module also defines two classes: -.. class:: Breakpoint(self, file, line, temporary=False, cond=None, funcname=None) +.. class:: Breakpoint(file, line, number, temporary=False, cond=None, funcname=None) This class implements temporary breakpoints, ignore counts, disabling and (re-)enabling, and conditionals. - Breakpoints are indexed by number through a list called :attr:`bpbynumber` - and by ``(file, line)`` pairs through :attr:`bplist`. The former points to - a single instance of class :class:`Breakpoint`. The latter points to a list - of such instances since there may be more than one breakpoint per line. - When creating a breakpoint, its associated :attr:`file name ` should be in canonical form. If a :attr:`funcname` is defined, a breakpoint :attr:`hit ` will be counted when the first line of that function is @@ -38,12 +33,6 @@ The :mod:`bdb` module also defines two classes: :class:`Breakpoint` instances have the following methods: - .. method:: deleteMe() - - Delete the breakpoint from the list associated to a file/line. If it is - the last breakpoint in that position, it also deletes the entry for the - file/line. - .. method:: enable() @@ -101,15 +90,6 @@ The :mod:`bdb` module also defines two classes: ``True`` if :class:`Breakpoint` is enabled. - .. attribute:: bpbynumber - - Numeric index for a single instance of a :class:`Breakpoint`. - - .. attribute:: bplist - - Dictionary of :class:`Breakpoint` instances indexed by - (:attr:`file`, :attr:`line`) tuples. - .. attribute:: ignore Number of times to ignore a :class:`Breakpoint`. @@ -221,6 +201,25 @@ The :mod:`bdb` module also defines two classes: Return ``True`` if *frame* is below the starting frame in the stack. + .. method:: effective(file, line, frame) + + Return ``(active breakpoint, delete temporary flag)`` or ``(None, None)`` as the + breakpoint to act upon. + + The *active breakpoint* is the first entry in `self.breaks[file][line]` + (which must exist) that is :attr:`enabled `, for + which :func:`checkfuncname` is true, and that has neither a false + :attr:`condition ` nor positive + :attr:`ignore ` count. The *flag*, meaning that a + temporary breakpoint should be deleted, is ``False`` only when the + :attr:`cond ` cannot be evaluated (in which case, + :attr:`ignore ` count is ignored). + + If no such entry exists, then ``(None, None)`` is returned. + + .. versionchanged:: 3.14 + ``effective`` was originally a function, but has been converted to a method. + .. method:: break_here(frame) Return ``True`` if there is an effective breakpoint for this line. @@ -323,8 +322,8 @@ The :mod:`bdb` module also defines two classes: .. method:: clear_bpbynumber(arg) - Delete the breakpoint which has the index *arg* in the - :attr:`Breakpoint.bpbynumber`. If *arg* is not numeric or out of range, + Delete the breakpoint which has the index *arg*. + If *arg* is not numeric or out of range, return an error message. .. method:: clear_all_file_breaks(filename) @@ -422,24 +421,6 @@ Finally, the module defines the following functions: the right *frame* (the right function) and if we are on its first executable line. -.. function:: effective(file, line, frame) - - Return ``(active breakpoint, delete temporary flag)`` or ``(None, None)`` as the - breakpoint to act upon. - - The *active breakpoint* is the first entry in - :attr:`bplist ` for the - (:attr:`file `, :attr:`line `) - (which must exist) that is :attr:`enabled `, for - which :func:`checkfuncname` is true, and that has neither a false - :attr:`condition ` nor positive - :attr:`ignore ` count. The *flag*, meaning that a - temporary breakpoint should be deleted, is ``False`` only when the - :attr:`cond ` cannot be evaluated (in which case, - :attr:`ignore ` count is ignored). - - If no such entry exists, then ``(None, None)`` is returned. - .. function:: set_trace() diff --git a/Lib/bdb.py b/Lib/bdb.py index 81bba8a130f97c..285480076e9394 100644 --- a/Lib/bdb.py +++ b/Lib/bdb.py @@ -27,11 +27,21 @@ class Bdb: that originate in a module that matches one of these patterns. Whether a frame is considered to originate in a certain module is determined by the __name__ in the frame globals. + + Each Bdb instance holds breakpoints. Breakpoints are indexed by + number through self.bpbynumber and by (file, line) using + self.breaks. The former maps to a single instance of the Breakpoint + class, while the latter maps to a list of such instances, as + there may be more than one breakpoint per line. """ def __init__(self, skip=None): self.skip = set(skip) if skip else None - self.breaks = {} + + self.next_bp_number = 1 + self.breaks = {} # self.breaks[file][line] -> list of breakpoints + self.bpbynumber = [None] # Each entry of bpbynumber is None or an + # instance of Breakpoint. index 0 is unused. self.fncache = {} self.frame_trace_lines_opcodes = {} self.frame_returning = None @@ -39,8 +49,6 @@ def __init__(self, skip=None): self.enterframe = None self.code_linenos = weakref.WeakKeyDictionary() - self._load_breaks() - def canonic(self, filename): """Return canonical form of filename. @@ -243,6 +251,56 @@ def stop_here(self, frame): return True return False + def effective(self, file, line, frame): + """Return (active breakpoint, delete temporary flag) or (None, None) as + breakpoint to act upon. + + The "active breakpoint" is the first entry in bplist[line, file] (which + must exist) that is enabled, for which checkfuncname is True, and that + has neither a False condition nor a positive ignore count. The flag, + meaning that a temporary breakpoint should be deleted, is False only + when the condiion cannot be evaluated (in which case, ignore count is + ignored). + + If no such entry exists, then (None, None) is returned. + """ + possibles = self.breaks[file][line] + for b in possibles: + if not b.enabled: + continue + if not checkfuncname(b, frame): + continue + # Count every hit when bp is enabled + b.hits += 1 + if not b.cond: + # If unconditional, and ignoring go on to next, else break + if b.ignore > 0: + b.ignore -= 1 + continue + else: + # breakpoint and marker that it's ok to delete if temporary + return (b, True) + else: + # Conditional bp. + # Ignore count applies only to those bpt hits where the + # condition evaluates to true. + try: + val = eval(b.cond, frame.f_globals, frame.f_locals) + if val: + if b.ignore > 0: + b.ignore -= 1 + # continue + else: + return (b, True) + # else: + # continue + except: + # if eval fails, most conservative thing is to stop on + # breakpoint regardless of ignore count. Don't delete + # temporary, as another hint to user. + return (b, False) + return (None, None) + def break_here(self, frame): """Return True if there is an effective breakpoint for this line. @@ -260,8 +318,8 @@ def break_here(self, frame): if lineno not in self.breaks[filename]: return False - # flag says ok to delete temp. bp - (bp, flag) = effective(filename, lineno, frame) + # flag says if it's ok to delete temporary bp + (bp, flag) = self.effective(filename, lineno, frame) if bp: self.currentbp = bp.number if (flag and bp.temporary): @@ -434,18 +492,43 @@ def set_quit(self): self.quitting = True sys.settrace(None) + def _add_bp(self, bp, filename, lineno): + """Add breakpoint to breaks and bpbynumber if not already there. + """ + bp_linenos = self.breaks.setdefault(filename, {}) + blist = bp_linenos.setdefault(lineno, []) + + if bp in blist: + return + + blist.append(bp) + self.bpbynumber.append(bp) + self.next_bp_number += 1 + + def _remove_bp(self, bp): + assert ( + bp in self.bpbynumber + and bp.file in self.breaks + and bp.line in self.breaks[bp.file] + and bp in self.breaks[bp.file][bp.line] + ), f"Breakpoint {bp} not in breaks" + + self.bpbynumber[bp.number] = None # No longer in list + self.breaks[bp.file][bp.line].remove(bp) + + if not self.breaks[bp.file][bp.line]: + # No more bp for this f:l combo + del self.breaks[bp.file][bp.line] + + if not self.breaks[bp.file]: + del self.breaks[bp.file] + # Derived classes and clients can call the following methods # to manipulate breakpoints. These methods return an # error message if something went wrong, None if all is well. # Set_break prints out the breakpoint line and file:lineno. # 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) + # for bp in self.bpbynumber: if bp: bp.bpprint(). def set_break(self, filename, lineno, temporary=False, cond=None, funcname=None): @@ -459,8 +542,10 @@ def set_break(self, filename, lineno, temporary=False, cond=None, line = linecache.getline(filename, lineno) if not line: return 'Line %s:%d does not exist' % (filename, lineno) - self._add_to_breaks(filename, lineno) - bp = Breakpoint(filename, lineno, temporary, cond, funcname) + + bp = Breakpoint(filename, lineno, self.next_bp_number, temporary, cond, funcname) + self._add_bp(bp, filename, lineno) + # After we set a new breakpoint, we need to search through all frames # and set f_trace to trace_dispatch if there could be a breakpoint in # that frame. @@ -471,30 +556,6 @@ def set_break(self, filename, lineno, temporary=False, cond=None, frame = frame.f_back 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. - - A list of breakpoints is maintained in the Bdb instance and in - the Breakpoint class. If a breakpoint in the Bdb instance no - longer exists in the Breakpoint class, then it's removed from the - Bdb instance. - """ - if (filename, lineno) not in Breakpoint.bplist: - self.breaks[filename].remove(lineno) - if not self.breaks[filename]: - del self.breaks[filename] - def clear_break(self, filename, lineno): """Delete breakpoints for filename:lineno. @@ -505,15 +566,13 @@ def clear_break(self, filename, lineno): return 'There are no breakpoints in %s' % filename if lineno not in self.breaks[filename]: return 'There is no breakpoint at %s:%d' % (filename, lineno) - # If there's only one bp in the list for that file,line - # pair, then remove the breaks entry - for bp in Breakpoint.bplist[filename, lineno][:]: - bp.deleteMe() - self._prune_breaks(filename, lineno) + + for bp in self.breaks[filename][lineno][:]: + self._remove_bp(bp) return None def clear_bpbynumber(self, arg): - """Delete a breakpoint by its index in Breakpoint.bpbynumber. + """Delete a breakpoint by its index in self.bpbynumber. If arg is invalid, return an error message. """ @@ -521,8 +580,7 @@ def clear_bpbynumber(self, arg): bp = self.get_bpbynumber(arg) except ValueError as err: return str(err) - bp.deleteMe() - self._prune_breaks(bp.file, bp.line) + self._remove_bp(bp) return None def clear_all_file_breaks(self, filename): @@ -534,9 +592,9 @@ def clear_all_file_breaks(self, filename): if filename not in self.breaks: return 'There are no breakpoints in %s' % filename for line in self.breaks[filename]: - blist = Breakpoint.bplist[filename, line] + blist = self.breaks[filename][line] for bp in blist: - bp.deleteMe() + self._remove_bp(bp) del self.breaks[filename] return None @@ -547,14 +605,14 @@ def clear_all_breaks(self): """ if not self.breaks: return 'There are no breakpoints' - for bp in Breakpoint.bpbynumber: + for bp in self.bpbynumber: if bp: - bp.deleteMe() + self._remove_bp(bp) self.breaks = {} return None def get_bpbynumber(self, arg): - """Return a breakpoint by its index in Breakpoint.bybpnumber. + """Return a breakpoint by its index in self.bybynumber. For invalid arg values or if the breakpoint doesn't exist, raise a ValueError. @@ -566,7 +624,7 @@ def get_bpbynumber(self, arg): except ValueError: raise ValueError('Non-numeric breakpoint number %s' % arg) from None try: - bp = Breakpoint.bpbynumber[number] + bp = self.bpbynumber[number] except IndexError: raise ValueError('Breakpoint number %d out of range' % number) from None if bp is None: @@ -577,7 +635,8 @@ def get_break(self, filename, lineno): """Return True if there is a breakpoint for filename:lineno.""" filename = self.canonic(filename) return filename in self.breaks and \ - lineno in self.breaks[filename] + lineno in self.breaks[filename] and \ + bool(self.breaks[filename][lineno]) def get_breaks(self, filename, lineno): """Return all breakpoints for filename:lineno. @@ -587,7 +646,7 @@ def get_breaks(self, filename, lineno): filename = self.canonic(filename) return filename in self.breaks and \ lineno in self.breaks[filename] and \ - Breakpoint.bplist[filename, lineno] or [] + self.breaks[filename][lineno] or [] def get_file_breaks(self, filename): """Return all lines with breakpoints for filename. @@ -596,13 +655,13 @@ def get_file_breaks(self, filename): """ filename = self.canonic(filename) if filename in self.breaks: - return self.breaks[filename] + return list(self.breaks[filename].keys()) else: return [] def get_all_breaks(self): """Return all breakpoints that are set.""" - return self.breaks + return {f: list(self.breaks[f].keys()) for f in self.breaks} # Derived classes and clients can call the following method # to get a data structure representing a stack trace. @@ -742,28 +801,13 @@ class Breakpoint: Implements temporary breakpoints, ignore counts, disabling and (re)-enabling, and conditionals. - Breakpoints are indexed by number through bpbynumber and by - the (file, line) tuple using bplist. The former points to a - single instance of class Breakpoint. The latter points to a - list of such instances since there may be more than one - breakpoint per line. - When creating a breakpoint, its associated filename should be in canonical form. If funcname is defined, a breakpoint hit will be counted when the first line of that function is executed. A conditional breakpoint always counts a hit. """ - # XXX Keeping state in the class is a mistake -- this means - # you cannot have more than one active Bdb instance. - - next = 1 # Next bp to be assigned - bplist = {} # indexed by (file, lineno) tuple - bpbynumber = [None] # Each entry is None or an instance of Bpt - # index 0 is unused, except for marking an - # effective break .... see effective() - - def __init__(self, file, line, temporary=False, cond=None, funcname=None): + def __init__(self, file, line, number, temporary=False, cond=None, funcname=None): self.funcname = funcname # Needed if funcname is not None. self.func_first_executable_line = None @@ -774,34 +818,7 @@ def __init__(self, file, line, temporary=False, cond=None, funcname=None): self.enabled = True self.ignore = 0 self.hits = 0 - self.number = Breakpoint.next - Breakpoint.next += 1 - # Build the two lists - self.bpbynumber.append(self) - if (file, line) in self.bplist: - self.bplist[file, line].append(self) - 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. - - If it is the last breakpoint in that position, it also deletes - the entry for the file:line. - """ - - index = (self.file, self.line) - self.bpbynumber[self.number] = None # No longer in list - self.bplist[index].remove(self) - if not self.bplist[index]: - # No more bp for this f:l combo - del self.bplist[index] + self.number = number def enable(self): """Mark the breakpoint as enabled.""" @@ -890,57 +907,6 @@ def checkfuncname(b, frame): return True -def effective(file, line, frame): - """Return (active breakpoint, delete temporary flag) or (None, None) as - breakpoint to act upon. - - The "active breakpoint" is the first entry in bplist[line, file] (which - must exist) that is enabled, for which checkfuncname is True, and that - has neither a False condition nor a positive ignore count. The flag, - meaning that a temporary breakpoint should be deleted, is False only - when the condiion cannot be evaluated (in which case, ignore count is - ignored). - - If no such entry exists, then (None, None) is returned. - """ - possibles = Breakpoint.bplist[file, line] - for b in possibles: - if not b.enabled: - continue - if not checkfuncname(b, frame): - continue - # Count every hit when bp is enabled - b.hits += 1 - if not b.cond: - # If unconditional, and ignoring go on to next, else break - if b.ignore > 0: - b.ignore -= 1 - continue - else: - # breakpoint and marker that it's ok to delete if temporary - return (b, True) - else: - # Conditional bp. - # Ignore count applies only to those bpt hits where the - # condition evaluates to true. - try: - val = eval(b.cond, frame.f_globals, frame.f_locals) - if val: - if b.ignore > 0: - b.ignore -= 1 - # continue - else: - return (b, True) - # else: - # continue - except: - # if eval fails, most conservative thing is to stop on - # breakpoint regardless of ignore count. Don't delete - # temporary, as another hint to user. - return (b, False) - return (None, None) - - # -------------------- testing -------------------- class Tdb(Bdb): diff --git a/Lib/pdb.py b/Lib/pdb.py index b7f6fd4323407e..fa9081e361902d 100644 --- a/Lib/pdb.py +++ b/Lib/pdb.py @@ -946,7 +946,7 @@ def _complete_bpnumber(self, text, line, begidx, endidx): # Complete a breakpoint number. (This would be more helpful if we could # display additional info along with the completions, such as file/line # of the breakpoint.) - return [str(i) for i, bp in enumerate(bdb.Breakpoint.bpbynumber) + return [str(i) for i, bp in enumerate(self.bpbynumber) if bp is not None and str(i).startswith(text)] def _complete_expression(self, text, line, begidx, endidx): @@ -1049,7 +1049,7 @@ def do_commands(self, arg): reached. """ if not arg: - bnum = len(bdb.Breakpoint.bpbynumber) - 1 + bnum = len(self.bpbynumber) - 1 else: try: bnum = int(arg) @@ -1107,7 +1107,7 @@ def do_break(self, arg, temporary=False): if not arg: if self.breaks: # There's at least one self.message("Num Type Disp Enb Where") - for bp in bdb.Breakpoint.bpbynumber: + for bp in self.bpbynumber: if bp: self.message(bp.bpformat()) return @@ -1391,7 +1391,7 @@ def do_clear(self, arg): reply = 'no' reply = reply.strip().lower() if reply in ('y', 'yes'): - bplist = [bp for bp in bdb.Breakpoint.bpbynumber if bp] + bplist = [bp for bp in self.bpbynumber if bp] self.clear_all_breaks() for bp in bplist: self.message('Deleted %s' % bp) diff --git a/Lib/test/test_bdb.py b/Lib/test/test_bdb.py index f15dae13eb384e..e26d35dc014424 100644 --- a/Lib/test/test_bdb.py +++ b/Lib/test/test_bdb.py @@ -73,9 +73,6 @@ class BdbNotExpectedError(BdbException): """Unexpected result.""" # after each 'line' event where a breakpoint has been hit. dry_run = 0 -def reset_Breakpoint(): - _bdb.Breakpoint.clearBreakpoints() - def info_breakpoints(): bp_list = [bp for bp in _bdb.Breakpoint.bpbynumber if bp] if not bp_list: @@ -426,12 +423,10 @@ def __init__(self, test_case, skip=None): def __enter__(self): # test_pdb does not reset Breakpoint class attributes on exit :-( - reset_Breakpoint() self._original_tracer = sys.gettrace() return self.tracer def __exit__(self, type_=None, value=None, traceback=None): - reset_Breakpoint() sys.settrace(self._original_tracer) not_empty = '' @@ -973,7 +968,6 @@ def test_clear_at_no_bp(self): self.assertRaises(BdbError, tracer.runcall, tfunc_import) def test_load_bps_from_previous_Bdb_instance(self): - reset_Breakpoint() db1 = Bdb() fname = db1.canonic(__file__) db1.set_break(__file__, 1) @@ -984,35 +978,34 @@ def test_load_bps_from_previous_Bdb_instance(self): db2.set_break(__file__, 3) db2.set_break(__file__, 4) self.assertEqual(db1.get_all_breaks(), {fname: [1]}) - self.assertEqual(db2.get_all_breaks(), {fname: [1, 2, 3, 4]}) - db2.clear_break(__file__, 1) + self.assertEqual(db2.get_all_breaks(), {fname: [2, 3, 4]}) self.assertEqual(db1.get_all_breaks(), {fname: [1]}) self.assertEqual(db2.get_all_breaks(), {fname: [2, 3, 4]}) db3 = Bdb() + db3.set_break(__file__, 5) self.assertEqual(db1.get_all_breaks(), {fname: [1]}) self.assertEqual(db2.get_all_breaks(), {fname: [2, 3, 4]}) - self.assertEqual(db3.get_all_breaks(), {fname: [2, 3, 4]}) + self.assertEqual(db3.get_all_breaks(), {fname: [5]}) db2.clear_break(__file__, 2) self.assertEqual(db1.get_all_breaks(), {fname: [1]}) self.assertEqual(db2.get_all_breaks(), {fname: [3, 4]}) - self.assertEqual(db3.get_all_breaks(), {fname: [2, 3, 4]}) + self.assertEqual(db3.get_all_breaks(), {fname: [5]}) db4 = Bdb() - db4.set_break(__file__, 5) + db4.set_break(__file__, 6) self.assertEqual(db1.get_all_breaks(), {fname: [1]}) self.assertEqual(db2.get_all_breaks(), {fname: [3, 4]}) - self.assertEqual(db3.get_all_breaks(), {fname: [2, 3, 4]}) - self.assertEqual(db4.get_all_breaks(), {fname: [3, 4, 5]}) - reset_Breakpoint() + self.assertEqual(db3.get_all_breaks(), {fname: [5]}) + self.assertEqual(db4.get_all_breaks(), {fname: [6]}) db5 = Bdb() - db5.set_break(__file__, 6) + db5.set_break(__file__, 7) self.assertEqual(db1.get_all_breaks(), {fname: [1]}) self.assertEqual(db2.get_all_breaks(), {fname: [3, 4]}) - self.assertEqual(db3.get_all_breaks(), {fname: [2, 3, 4]}) - self.assertEqual(db4.get_all_breaks(), {fname: [3, 4, 5]}) - self.assertEqual(db5.get_all_breaks(), {fname: [6]}) + self.assertEqual(db3.get_all_breaks(), {fname: [5]}) + self.assertEqual(db4.get_all_breaks(), {fname: [6]}) + self.assertEqual(db5.get_all_breaks(), {fname: [7]}) class RunTestCase(BaseTestCase): diff --git a/Lib/test/test_pdb.py b/Lib/test/test_pdb.py index e5f9848319021a..81e8b40c0b8bac 100644 --- a/Lib/test/test_pdb.py +++ b/Lib/test/test_pdb.py @@ -222,10 +222,6 @@ def test_pdb_basic_commands(): BAZ """ -def reset_Breakpoint(): - import bdb - bdb.Breakpoint.clearBreakpoints() - def test_pdb_breakpoint_commands(): """Test basic commands related to breakpoints. @@ -236,11 +232,6 @@ def test_pdb_breakpoint_commands(): ... print(3) ... print(4) - First, need to clear bdb state that might be left over from previous tests. - Otherwise, the new breakpoints might get assigned different numbers. - - >>> reset_Breakpoint() - Now test the breakpoint commands. NORMALIZE_WHITESPACE is needed because the breakpoint list outputs a tab for the "stop only" and "ignore next" lines, which we don't want to put in here. @@ -375,8 +366,6 @@ def test_pdb_breakpoint_on_annotated_function_def(): >>> def foobar[T]() -> int: ... return 0 - >>> reset_Breakpoint() - >>> def test_function(): ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() ... pass @@ -388,7 +377,7 @@ def test_pdb_breakpoint_on_annotated_function_def(): ... 'continue', ... ]): ... test_function() - > (2)test_function() + > (2)test_function() -> import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() (Pdb) break foo Breakpoint 1 at :2 @@ -408,8 +397,6 @@ def test_pdb_commands(): ... print(2) ... print(3) - >>> reset_Breakpoint() - >>> with PdbTestInput([ # doctest: +NORMALIZE_WHITESPACE ... 'b 3', ... 'commands', @@ -457,12 +444,6 @@ def test_pdb_breakpoint_with_filename(): ... mod2.func88() ... mod2.func114() ... # Be a good citizen and clean up the mess - ... reset_Breakpoint() - - First, need to clear bdb state that might be left over from previous tests. - Otherwise, the new breakpoints might get assigned different numbers. - - >>> reset_Breakpoint() >>> with PdbTestInput([ # doctest: +NORMALIZE_WHITESPACE +ELLIPSIS ... 'break test.test_inspect.inspect_fodder2:90', @@ -490,7 +471,7 @@ def test_pdb_breakpoint_with_filename(): def test_pdb_breakpoints_preserved_across_interactive_sessions(): """Breakpoints are remembered between interactive sessions - >>> reset_Breakpoint() + >>> pdb_instance = pdb.Pdb() >>> with PdbTestInput([ # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE ... 'import test.test_pdb', ... 'break test.test_pdb.do_something', @@ -498,7 +479,7 @@ def test_pdb_breakpoints_preserved_across_interactive_sessions(): ... 'break', ... 'continue', ... ]): - ... pdb.run('print()') + ... pdb_instance.run('print()') > (1)()... (Pdb) import test.test_pdb (Pdb) break test.test_pdb.do_something @@ -518,7 +499,7 @@ def test_pdb_breakpoints_preserved_across_interactive_sessions(): ... 'clear 1', ... 'continue', ... ]): - ... pdb.run('print()') + ... pdb_instance.run('print()') > (1)()... (Pdb) break Num Type Disp Enb Where @@ -541,7 +522,7 @@ def test_pdb_breakpoints_preserved_across_interactive_sessions(): ... 'clear 3', ... 'continue', ... ]): - ... pdb.run('print()') + ... pdb_instance.run('print()') > (1)()... (Pdb) break Num Type Disp Enb Where @@ -575,7 +556,6 @@ def test_pdb_break_anywhere(): >>> def test_function(): ... caller() - >>> reset_Breakpoint() >>> with PdbTestInput([ # doctest: +NORMALIZE_WHITESPACE ... 'b 3', ... 'c', @@ -1689,7 +1669,6 @@ def test_pdb_return_to_different_file(): ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() ... pprint.pprint(A()) - >>> reset_Breakpoint() >>> with PdbTestInput([ # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE ... 'b A.__repr__', ... 'continue', @@ -1936,7 +1915,6 @@ def test_next_until_return_at_return_event(): ... test_function_2() ... end = 1 - >>> reset_Breakpoint() >>> with PdbTestInput(['break test_function_2', ... 'continue', ... 'return', @@ -2394,7 +2372,6 @@ def test_pdb_next_command_in_generator_for_loop(): ... print('value', i) ... x = 123 - >>> reset_Breakpoint() >>> with PdbTestInput(['break test_gen', ... 'continue', ... 'next', @@ -2665,7 +2642,6 @@ def test_pdb_issue_20766(): ... print('pdb %d: %s' % (i, sess._previous_sigint_handler)) ... i += 1 - >>> reset_Breakpoint() >>> with PdbTestInput(['continue', ... 'continue']): ... test_function() @@ -2688,7 +2664,6 @@ def test_pdb_issue_43318(): ... print(2) ... print(3) ... print(4) - >>> reset_Breakpoint() >>> with PdbTestInput([ # doctest: +NORMALIZE_WHITESPACE ... 'break 3', ... 'clear :3', @@ -2725,7 +2700,6 @@ def test_pdb_issue_gh_91742(): ... about() - >>> reset_Breakpoint() >>> with PdbTestInput([ # doctest: +NORMALIZE_WHITESPACE ... 'step', ... 'step', @@ -2772,7 +2746,6 @@ def test_pdb_issue_gh_94215(): ... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() ... func() - >>> reset_Breakpoint() >>> with PdbTestInput([ # doctest: +NORMALIZE_WHITESPACE ... 'step', ... 'step', @@ -2987,8 +2960,6 @@ def test_pdb_f_trace_lines(): pdb should work even if f_trace_lines is set to False on some frames. - >>> reset_Breakpoint() - >>> def test_function(): ... import sys ... frame = sys._getframe() @@ -3001,7 +2972,7 @@ def test_pdb_f_trace_lines(): ... 'continue' ... ]): ... test_function() - > (5)test_function() + > (5)test_function() -> import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace() (Pdb) continue """