pdb: import pdbcls lazily
Fixes https://github.com/pytest-dev/pytest/issues/2064.
This commit is contained in:
parent
e393a73890
commit
f2ed796c41
|
@ -0,0 +1 @@
|
|||
The debugging plugin imports the wrapped ``Pdb`` class (``--pdbcls``) on-demand now.
|
|
@ -49,7 +49,57 @@ def pytest_addoption(parser):
|
|||
)
|
||||
|
||||
|
||||
def _import_pdbcls(modname, classname):
|
||||
def pytest_configure(config):
|
||||
if config.getvalue("trace"):
|
||||
config.pluginmanager.register(PdbTrace(), "pdbtrace")
|
||||
if config.getvalue("usepdb"):
|
||||
config.pluginmanager.register(PdbInvoke(), "pdbinvoke")
|
||||
|
||||
pytestPDB._saved.append(
|
||||
(pdb.set_trace, pytestPDB._pluginmanager, pytestPDB._config)
|
||||
)
|
||||
pdb.set_trace = pytestPDB.set_trace
|
||||
pytestPDB._pluginmanager = config.pluginmanager
|
||||
pytestPDB._config = config
|
||||
|
||||
# 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._saved.pop()
|
||||
|
||||
config._cleanup.append(fin)
|
||||
|
||||
|
||||
class pytestPDB(object):
|
||||
""" Pseudo PDB that defers to the real pdb. """
|
||||
|
||||
_pluginmanager = None
|
||||
_config = None
|
||||
_saved = []
|
||||
_recursive_debug = 0
|
||||
|
||||
@classmethod
|
||||
def _is_capturing(cls, capman):
|
||||
if capman:
|
||||
return capman.is_capturing()
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
def _import_pdb_cls(cls):
|
||||
if not cls._config:
|
||||
# Happens when using pytest.set_trace outside of a test.
|
||||
return pdb.Pdb
|
||||
|
||||
pdb_cls = cls._config.getvalue("usepdb_cls")
|
||||
if not pdb_cls:
|
||||
return pdb.Pdb
|
||||
|
||||
modname, classname = pdb_cls
|
||||
|
||||
try:
|
||||
__import__(modname)
|
||||
mod = sys.modules[modname]
|
||||
|
@ -65,55 +115,6 @@ def _import_pdbcls(modname, classname):
|
|||
value = ":".join((modname, classname))
|
||||
raise UsageError("--pdbcls: could not import {!r}: {}".format(value, exc))
|
||||
|
||||
|
||||
def pytest_configure(config):
|
||||
pdb_cls = config.getvalue("usepdb_cls")
|
||||
if pdb_cls:
|
||||
pdb_cls = _import_pdbcls(*pdb_cls)
|
||||
else:
|
||||
pdb_cls = pdb.Pdb
|
||||
|
||||
if config.getvalue("trace"):
|
||||
config.pluginmanager.register(PdbTrace(), "pdbtrace")
|
||||
if config.getvalue("usepdb"):
|
||||
config.pluginmanager.register(PdbInvoke(), "pdbinvoke")
|
||||
|
||||
pytestPDB._saved.append(
|
||||
(pdb.set_trace, pytestPDB._pluginmanager, pytestPDB._config, pytestPDB._pdb_cls)
|
||||
)
|
||||
pdb.set_trace = pytestPDB.set_trace
|
||||
pytestPDB._pluginmanager = config.pluginmanager
|
||||
pytestPDB._config = config
|
||||
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)
|
||||
|
||||
|
||||
class pytestPDB(object):
|
||||
""" Pseudo PDB that defers to the real pdb. """
|
||||
|
||||
_pluginmanager = None
|
||||
_config = None
|
||||
_pdb_cls = pdb.Pdb
|
||||
_saved = []
|
||||
_recursive_debug = 0
|
||||
|
||||
@classmethod
|
||||
def _is_capturing(cls, capman):
|
||||
if capman:
|
||||
return capman.is_capturing()
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
def _init_pdb(cls, *args, **kwargs):
|
||||
""" Initialize PDB debugging, dropping any IO capturing. """
|
||||
|
@ -144,7 +145,9 @@ class pytestPDB(object):
|
|||
else:
|
||||
tw.sep(">", "PDB set_trace")
|
||||
|
||||
class PytestPdbWrapper(cls._pdb_cls, object):
|
||||
pdb_cls = cls._import_pdb_cls()
|
||||
|
||||
class PytestPdbWrapper(pdb_cls, object):
|
||||
_pytest_capman = capman
|
||||
_continued = False
|
||||
|
||||
|
@ -227,7 +230,8 @@ class pytestPDB(object):
|
|||
_pdb = PytestPdbWrapper(**kwargs)
|
||||
cls._pluginmanager.hook.pytest_enter_pdb(config=cls._config, pdb=_pdb)
|
||||
else:
|
||||
_pdb = cls._pdb_cls(**kwargs)
|
||||
pdb_cls = cls._import_pdb_cls()
|
||||
_pdb = pdb_cls(**kwargs)
|
||||
return _pdb
|
||||
|
||||
@classmethod
|
||||
|
|
|
@ -1157,12 +1157,13 @@ def test_pdbcls_via_local_module(testdir):
|
|||
result = testdir.runpytest(
|
||||
str(p1), "--pdbcls=really.invalid:Value", syspathinsert=True
|
||||
)
|
||||
result.stderr.fnmatch_lines(
|
||||
result.stdout.fnmatch_lines(
|
||||
[
|
||||
"ERROR: --pdbcls: could not import 'really.invalid:Value': No module named *really*"
|
||||
"*= FAILURES =*",
|
||||
"E * --pdbcls: could not import 'really.invalid:Value': No module named *really*",
|
||||
]
|
||||
)
|
||||
assert result.ret == 4
|
||||
assert result.ret == 1
|
||||
|
||||
result = testdir.runpytest(
|
||||
str(p1), "--pdbcls=mypdb:Wrapped.MyPdb", syspathinsert=True
|
||||
|
|
Loading…
Reference in New Issue