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,42 +49,18 @@ def pytest_addoption(parser):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def _import_pdbcls(modname, classname):
|
|
||||||
try:
|
|
||||||
__import__(modname)
|
|
||||||
mod = sys.modules[modname]
|
|
||||||
|
|
||||||
# Handle --pdbcls=pdb:pdb.Pdb (useful e.g. with pdbpp).
|
|
||||||
parts = classname.split(".")
|
|
||||||
pdb_cls = getattr(mod, parts[0])
|
|
||||||
for part in parts[1:]:
|
|
||||||
pdb_cls = getattr(pdb_cls, part)
|
|
||||||
|
|
||||||
return pdb_cls
|
|
||||||
except Exception as exc:
|
|
||||||
value = ":".join((modname, classname))
|
|
||||||
raise UsageError("--pdbcls: could not import {!r}: {}".format(value, exc))
|
|
||||||
|
|
||||||
|
|
||||||
def pytest_configure(config):
|
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"):
|
if config.getvalue("trace"):
|
||||||
config.pluginmanager.register(PdbTrace(), "pdbtrace")
|
config.pluginmanager.register(PdbTrace(), "pdbtrace")
|
||||||
if config.getvalue("usepdb"):
|
if config.getvalue("usepdb"):
|
||||||
config.pluginmanager.register(PdbInvoke(), "pdbinvoke")
|
config.pluginmanager.register(PdbInvoke(), "pdbinvoke")
|
||||||
|
|
||||||
pytestPDB._saved.append(
|
pytestPDB._saved.append(
|
||||||
(pdb.set_trace, pytestPDB._pluginmanager, pytestPDB._config, pytestPDB._pdb_cls)
|
(pdb.set_trace, pytestPDB._pluginmanager, pytestPDB._config)
|
||||||
)
|
)
|
||||||
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
|
|
||||||
|
|
||||||
# NOTE: not using pytest_unconfigure, since it might get called although
|
# NOTE: not using pytest_unconfigure, since it might get called although
|
||||||
# pytest_configure was not (if another plugin raises UsageError).
|
# pytest_configure was not (if another plugin raises UsageError).
|
||||||
|
@ -93,7 +69,6 @@ def pytest_configure(config):
|
||||||
pdb.set_trace,
|
pdb.set_trace,
|
||||||
pytestPDB._pluginmanager,
|
pytestPDB._pluginmanager,
|
||||||
pytestPDB._config,
|
pytestPDB._config,
|
||||||
pytestPDB._pdb_cls,
|
|
||||||
) = pytestPDB._saved.pop()
|
) = pytestPDB._saved.pop()
|
||||||
|
|
||||||
config._cleanup.append(fin)
|
config._cleanup.append(fin)
|
||||||
|
@ -104,7 +79,6 @@ class pytestPDB(object):
|
||||||
|
|
||||||
_pluginmanager = None
|
_pluginmanager = None
|
||||||
_config = None
|
_config = None
|
||||||
_pdb_cls = pdb.Pdb
|
|
||||||
_saved = []
|
_saved = []
|
||||||
_recursive_debug = 0
|
_recursive_debug = 0
|
||||||
|
|
||||||
|
@ -114,6 +88,33 @@ class pytestPDB(object):
|
||||||
return capman.is_capturing()
|
return capman.is_capturing()
|
||||||
return False
|
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]
|
||||||
|
|
||||||
|
# Handle --pdbcls=pdb:pdb.Pdb (useful e.g. with pdbpp).
|
||||||
|
parts = classname.split(".")
|
||||||
|
pdb_cls = getattr(mod, parts[0])
|
||||||
|
for part in parts[1:]:
|
||||||
|
pdb_cls = getattr(pdb_cls, part)
|
||||||
|
|
||||||
|
return pdb_cls
|
||||||
|
except Exception as exc:
|
||||||
|
value = ":".join((modname, classname))
|
||||||
|
raise UsageError("--pdbcls: could not import {!r}: {}".format(value, exc))
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _init_pdb(cls, *args, **kwargs):
|
def _init_pdb(cls, *args, **kwargs):
|
||||||
""" Initialize PDB debugging, dropping any IO capturing. """
|
""" Initialize PDB debugging, dropping any IO capturing. """
|
||||||
|
@ -144,7 +145,9 @@ class pytestPDB(object):
|
||||||
else:
|
else:
|
||||||
tw.sep(">", "PDB set_trace")
|
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
|
_pytest_capman = capman
|
||||||
_continued = False
|
_continued = False
|
||||||
|
|
||||||
|
@ -227,7 +230,8 @@ class pytestPDB(object):
|
||||||
_pdb = PytestPdbWrapper(**kwargs)
|
_pdb = PytestPdbWrapper(**kwargs)
|
||||||
cls._pluginmanager.hook.pytest_enter_pdb(config=cls._config, pdb=_pdb)
|
cls._pluginmanager.hook.pytest_enter_pdb(config=cls._config, pdb=_pdb)
|
||||||
else:
|
else:
|
||||||
_pdb = cls._pdb_cls(**kwargs)
|
pdb_cls = cls._import_pdb_cls()
|
||||||
|
_pdb = pdb_cls(**kwargs)
|
||||||
return _pdb
|
return _pdb
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|
|
@ -1157,12 +1157,13 @@ def test_pdbcls_via_local_module(testdir):
|
||||||
result = testdir.runpytest(
|
result = testdir.runpytest(
|
||||||
str(p1), "--pdbcls=really.invalid:Value", syspathinsert=True
|
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(
|
result = testdir.runpytest(
|
||||||
str(p1), "--pdbcls=mypdb:Wrapped.MyPdb", syspathinsert=True
|
str(p1), "--pdbcls=mypdb:Wrapped.MyPdb", syspathinsert=True
|
||||||
|
|
Loading…
Reference in New Issue