Merge pull request #4287 from blueyed/pdb-unconfigure-twice

debugging: make pytest_configure re-entrant
This commit is contained in:
Daniel Hahler 2018-11-03 21:09:13 +01:00 committed by GitHub
commit f2b9bbdd4a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 43 additions and 7 deletions

View File

@ -0,0 +1 @@
Fix nested usage of debugging plugin (pdb), e.g. with pytester's ``testdir.runpytest``.

View File

@ -47,17 +47,24 @@ def pytest_configure(config):
if config.getvalue("usepdb"): if config.getvalue("usepdb"):
config.pluginmanager.register(PdbInvoke(), "pdbinvoke") config.pluginmanager.register(PdbInvoke(), "pdbinvoke")
old = (pdb.set_trace, pytestPDB._pluginmanager) pytestPDB._saved.append(
(pdb.set_trace, pytestPDB._pluginmanager, pytestPDB._config, pytestPDB._pdb_cls)
def fin(): )
pdb.set_trace, pytestPDB._pluginmanager = old
pytestPDB._config = None
pytestPDB._pdb_cls = pdb.Pdb
pdb.set_trace = pytestPDB.set_trace pdb.set_trace = pytestPDB.set_trace
pytestPDB._pluginmanager = config.pluginmanager pytestPDB._pluginmanager = config.pluginmanager
pytestPDB._config = config pytestPDB._config = config
pytestPDB._pdb_cls = pdb_cls pytestPDB._pdb_cls = pdb_cls
# NOTE: not using pytest_unconfigure, since it might get called although
# pytest_configure was not (if another plugin raises UsageError).
def fin():
(
pdb.set_trace,
pytestPDB._pluginmanager,
pytestPDB._config,
pytestPDB._pdb_cls,
) = pytestPDB._saved.pop()
config._cleanup.append(fin) config._cleanup.append(fin)
@ -67,6 +74,7 @@ class pytestPDB(object):
_pluginmanager = None _pluginmanager = None
_config = None _config = None
_pdb_cls = pdb.Pdb _pdb_cls = pdb.Pdb
_saved = []
@classmethod @classmethod
def set_trace(cls, set_break=True): def set_trace(cls, set_break=True):

View File

@ -784,3 +784,30 @@ class TestTraceOption:
assert "1 passed" in rest assert "1 passed" in rest
assert "reading from stdin while output" not in rest assert "reading from stdin while output" not in rest
TestPDB.flush(child) TestPDB.flush(child)
def test_trace_after_runpytest(testdir):
"""Test that debugging's pytest_configure is re-entrant."""
p1 = testdir.makepyfile(
"""
from _pytest.debugging import pytestPDB
def test_outer(testdir):
from _pytest.debugging import pytestPDB
assert len(pytestPDB._saved) == 1
testdir.runpytest("-k test_inner")
__import__('pdb').set_trace()
def test_inner(testdir):
assert len(pytestPDB._saved) == 2
"""
)
child = testdir.spawn_pytest("-p pytester %s -k test_outer" % p1)
child.expect(r"\(Pdb")
child.sendline("c")
rest = child.read().decode("utf8")
TestPDB.flush(child)
assert child.exitstatus == 0, rest