mirror of https://github.com/python/cpython
gh-121450: Make inline breakpoints use the most recent pdb instance (#121451)
This commit is contained in:
parent
6557af6698
commit
690b9355e0
|
@ -114,6 +114,16 @@ pathlib
|
||||||
another.
|
another.
|
||||||
(Contributed by Barney Gale in :gh:`73991`.)
|
(Contributed by Barney Gale in :gh:`73991`.)
|
||||||
|
|
||||||
|
pdb
|
||||||
|
---
|
||||||
|
|
||||||
|
* Hard-coded breakpoints (:func:`breakpoint` and :func:`pdb.set_trace()`) now
|
||||||
|
reuse the most recent :class:`~pdb.Pdb` instance that calls
|
||||||
|
:meth:`~pdb.Pdb.set_trace()`, instead of creating a new one each time.
|
||||||
|
As a result, all the instance specific data like :pdbcmd:`display` and
|
||||||
|
:pdbcmd:`commands` are preserved across hard-coded breakpoints.
|
||||||
|
(Contributed by Tian Gao in :gh:`121450`.)
|
||||||
|
|
||||||
symtable
|
symtable
|
||||||
--------
|
--------
|
||||||
|
|
||||||
|
|
|
@ -369,6 +369,7 @@ class Bdb:
|
||||||
|
|
||||||
If frame is not specified, debugging starts from caller's frame.
|
If frame is not specified, debugging starts from caller's frame.
|
||||||
"""
|
"""
|
||||||
|
sys.settrace(None)
|
||||||
if frame is None:
|
if frame is None:
|
||||||
frame = sys._getframe().f_back
|
frame = sys._getframe().f_back
|
||||||
self.reset()
|
self.reset()
|
||||||
|
|
13
Lib/pdb.py
13
Lib/pdb.py
|
@ -306,6 +306,8 @@ class Pdb(bdb.Bdb, cmd.Cmd):
|
||||||
|
|
||||||
_file_mtime_table = {}
|
_file_mtime_table = {}
|
||||||
|
|
||||||
|
_last_pdb_instance = None
|
||||||
|
|
||||||
def __init__(self, completekey='tab', stdin=None, stdout=None, skip=None,
|
def __init__(self, completekey='tab', stdin=None, stdout=None, skip=None,
|
||||||
nosigint=False, readrc=True):
|
nosigint=False, readrc=True):
|
||||||
bdb.Bdb.__init__(self, skip=skip)
|
bdb.Bdb.__init__(self, skip=skip)
|
||||||
|
@ -359,6 +361,12 @@ class Pdb(bdb.Bdb, cmd.Cmd):
|
||||||
self._chained_exceptions = tuple()
|
self._chained_exceptions = tuple()
|
||||||
self._chained_exception_index = 0
|
self._chained_exception_index = 0
|
||||||
|
|
||||||
|
def set_trace(self, frame=None):
|
||||||
|
Pdb._last_pdb_instance = self
|
||||||
|
if frame is None:
|
||||||
|
frame = sys._getframe().f_back
|
||||||
|
super().set_trace(frame)
|
||||||
|
|
||||||
def sigint_handler(self, signum, frame):
|
def sigint_handler(self, signum, frame):
|
||||||
if self.allow_kbdint:
|
if self.allow_kbdint:
|
||||||
raise KeyboardInterrupt
|
raise KeyboardInterrupt
|
||||||
|
@ -2350,7 +2358,10 @@ def set_trace(*, header=None):
|
||||||
an assertion fails). If given, *header* is printed to the console
|
an assertion fails). If given, *header* is printed to the console
|
||||||
just before debugging begins.
|
just before debugging begins.
|
||||||
"""
|
"""
|
||||||
pdb = Pdb()
|
if Pdb._last_pdb_instance is not None:
|
||||||
|
pdb = Pdb._last_pdb_instance
|
||||||
|
else:
|
||||||
|
pdb = Pdb()
|
||||||
if header is not None:
|
if header is not None:
|
||||||
pdb.message(header)
|
pdb.message(header)
|
||||||
pdb.set_trace(sys._getframe().f_back)
|
pdb.set_trace(sys._getframe().f_back)
|
||||||
|
|
|
@ -2448,6 +2448,49 @@ def test_pdb_show_attribute_and_item():
|
||||||
(Pdb) c
|
(Pdb) c
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
# doctest will modify pdb.set_trace during the test, so we need to backup
|
||||||
|
# the original function to use it in the test
|
||||||
|
original_pdb_settrace = pdb.set_trace
|
||||||
|
|
||||||
|
def test_pdb_with_inline_breakpoint():
|
||||||
|
"""Hard-coded breakpoint() calls should invoke the same debugger instance
|
||||||
|
|
||||||
|
>>> def test_function():
|
||||||
|
... x = 1
|
||||||
|
... import pdb; pdb.Pdb().set_trace()
|
||||||
|
... original_pdb_settrace()
|
||||||
|
... x = 2
|
||||||
|
|
||||||
|
>>> with PdbTestInput(['display x',
|
||||||
|
... 'n',
|
||||||
|
... 'n',
|
||||||
|
... 'n',
|
||||||
|
... 'n',
|
||||||
|
... 'undisplay',
|
||||||
|
... 'c']):
|
||||||
|
... test_function()
|
||||||
|
> <doctest test.test_pdb.test_pdb_with_inline_breakpoint[0]>(3)test_function()
|
||||||
|
-> import pdb; pdb.Pdb().set_trace()
|
||||||
|
(Pdb) display x
|
||||||
|
display x: 1
|
||||||
|
(Pdb) n
|
||||||
|
> <doctest test.test_pdb.test_pdb_with_inline_breakpoint[0]>(4)test_function()
|
||||||
|
-> original_pdb_settrace()
|
||||||
|
(Pdb) n
|
||||||
|
> <doctest test.test_pdb.test_pdb_with_inline_breakpoint[0]>(4)test_function()
|
||||||
|
-> original_pdb_settrace()
|
||||||
|
(Pdb) n
|
||||||
|
> <doctest test.test_pdb.test_pdb_with_inline_breakpoint[0]>(5)test_function()
|
||||||
|
-> x = 2
|
||||||
|
(Pdb) n
|
||||||
|
--Return--
|
||||||
|
> <doctest test.test_pdb.test_pdb_with_inline_breakpoint[0]>(5)test_function()->None
|
||||||
|
-> x = 2
|
||||||
|
display x: 2 [old: 1]
|
||||||
|
(Pdb) undisplay
|
||||||
|
(Pdb) c
|
||||||
|
"""
|
||||||
|
|
||||||
def test_pdb_issue_20766():
|
def test_pdb_issue_20766():
|
||||||
"""Test for reference leaks when the SIGINT handler is set.
|
"""Test for reference leaks when the SIGINT handler is set.
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
Hard-coded breakpoints (:func:`breakpoint` and :func:`pdb.set_trace()`) now
|
||||||
|
reuse the most recent ``Pdb`` instance that calls ``Pdb.set_trace()``,
|
||||||
|
instead of creating a new one each time. As a result, all the instance specific
|
||||||
|
data like ``display`` and ``commands`` are preserved across Hard-coded breakpoints.
|
Loading…
Reference in New Issue