pdb: import pdbcls lazily (#5307)

pdb: import pdbcls lazily
This commit is contained in:
Bruno Oliveira 2019-05-27 20:23:39 -03:00 committed by GitHub
commit ece774f0eb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 38 additions and 32 deletions

View File

@ -0,0 +1 @@
The debugging plugin imports the wrapped ``Pdb`` class (``--pdbcls``) on-demand now.

View File

@ -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):
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._pluginmanager, pytestPDB._config)
)
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).
@ -93,7 +69,6 @@ def pytest_configure(config):
pdb.set_trace,
pytestPDB._pluginmanager,
pytestPDB._config,
pytestPDB._pdb_cls,
) = pytestPDB._saved.pop()
config._cleanup.append(fin)
@ -104,7 +79,6 @@ class pytestPDB(object):
_pluginmanager = None
_config = None
_pdb_cls = pdb.Pdb
_saved = []
_recursive_debug = 0
@ -114,6 +88,33 @@ class pytestPDB(object):
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]
# 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
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

View File

@ -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