Skip to content

Commit f2b9bbd

Browse files
authored
Merge pull request #4287 from blueyed/pdb-unconfigure-twice
debugging: make pytest_configure re-entrant
2 parents 21725e9 + e61e81a commit f2b9bbd

File tree

3 files changed

+43
-7
lines changed

3 files changed

+43
-7
lines changed

changelog/4287.bugfix.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix nested usage of debugging plugin (pdb), e.g. with pytester's ``testdir.runpytest``.

src/_pytest/debugging.py

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -47,17 +47,24 @@ def pytest_configure(config):
4747
if config.getvalue("usepdb"):
4848
config.pluginmanager.register(PdbInvoke(), "pdbinvoke")
4949

50-
old = (pdb.set_trace, pytestPDB._pluginmanager)
51-
52-
def fin():
53-
pdb.set_trace, pytestPDB._pluginmanager = old
54-
pytestPDB._config = None
55-
pytestPDB._pdb_cls = pdb.Pdb
56-
50+
pytestPDB._saved.append(
51+
(pdb.set_trace, pytestPDB._pluginmanager, pytestPDB._config, pytestPDB._pdb_cls)
52+
)
5753
pdb.set_trace = pytestPDB.set_trace
5854
pytestPDB._pluginmanager = config.pluginmanager
5955
pytestPDB._config = config
6056
pytestPDB._pdb_cls = pdb_cls
57+
58+
# NOTE: not using pytest_unconfigure, since it might get called although
59+
# pytest_configure was not (if another plugin raises UsageError).
60+
def fin():
61+
(
62+
pdb.set_trace,
63+
pytestPDB._pluginmanager,
64+
pytestPDB._config,
65+
pytestPDB._pdb_cls,
66+
) = pytestPDB._saved.pop()
67+
6168
config._cleanup.append(fin)
6269

6370

@@ -67,6 +74,7 @@ class pytestPDB(object):
6774
_pluginmanager = None
6875
_config = None
6976
_pdb_cls = pdb.Pdb
77+
_saved = []
7078

7179
@classmethod
7280
def set_trace(cls, set_break=True):

testing/test_pdb.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -784,3 +784,30 @@ def test_1():
784784
assert "1 passed" in rest
785785
assert "reading from stdin while output" not in rest
786786
TestPDB.flush(child)
787+
788+
789+
def test_trace_after_runpytest(testdir):
790+
"""Test that debugging's pytest_configure is re-entrant."""
791+
p1 = testdir.makepyfile(
792+
"""
793+
from _pytest.debugging import pytestPDB
794+
795+
def test_outer(testdir):
796+
from _pytest.debugging import pytestPDB
797+
798+
assert len(pytestPDB._saved) == 1
799+
800+
testdir.runpytest("-k test_inner")
801+
802+
__import__('pdb').set_trace()
803+
804+
def test_inner(testdir):
805+
assert len(pytestPDB._saved) == 2
806+
"""
807+
)
808+
child = testdir.spawn_pytest("-p pytester %s -k test_outer" % p1)
809+
child.expect(r"\(Pdb")
810+
child.sendline("c")
811+
rest = child.read().decode("utf8")
812+
TestPDB.flush(child)
813+
assert child.exitstatus == 0, rest

0 commit comments

Comments
 (0)