pdb: support kwargs with `pdb.set_trace`
This handles `header` similar to Python 3.7 does it, and forwards any other keyword arguments to the Pdb constructor. This allows for `__import__("pdb").set_trace(skip=["foo.*"])`. Fixes https://github.com/pytest-dev/pytest/issues/4416.
This commit is contained in:
parent
62967b3110
commit
92a2884b09
|
@ -0,0 +1,6 @@
|
||||||
|
pdb: support keyword arguments with ``pdb.set_trace``
|
||||||
|
|
||||||
|
It handles ``header`` similar to Python 3.7 does it, and forwards any
|
||||||
|
other keyword arguments to the ``Pdb`` constructor.
|
||||||
|
|
||||||
|
This allows for ``__import__("pdb").set_trace(skip=["foo.*"])``.
|
|
@ -77,18 +77,21 @@ class pytestPDB(object):
|
||||||
_saved = []
|
_saved = []
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def set_trace(cls, set_break=True):
|
def _init_pdb(cls, *args, **kwargs):
|
||||||
""" invoke PDB set_trace debugging, dropping any IO capturing. """
|
""" Initialize PDB debugging, dropping any IO capturing. """
|
||||||
import _pytest.config
|
import _pytest.config
|
||||||
|
|
||||||
frame = sys._getframe().f_back
|
|
||||||
if cls._pluginmanager is not None:
|
if cls._pluginmanager is not None:
|
||||||
capman = cls._pluginmanager.getplugin("capturemanager")
|
capman = cls._pluginmanager.getplugin("capturemanager")
|
||||||
if capman:
|
if capman:
|
||||||
capman.suspend_global_capture(in_=True)
|
capman.suspend_global_capture(in_=True)
|
||||||
tw = _pytest.config.create_terminal_writer(cls._config)
|
tw = _pytest.config.create_terminal_writer(cls._config)
|
||||||
tw.line()
|
tw.line()
|
||||||
if capman and capman.is_globally_capturing():
|
# Handle header similar to pdb.set_trace in py37+.
|
||||||
|
header = kwargs.pop("header", None)
|
||||||
|
if header is not None:
|
||||||
|
tw.sep(">", header)
|
||||||
|
elif capman and capman.is_globally_capturing():
|
||||||
tw.sep(">", "PDB set_trace (IO-capturing turned off)")
|
tw.sep(">", "PDB set_trace (IO-capturing turned off)")
|
||||||
else:
|
else:
|
||||||
tw.sep(">", "PDB set_trace")
|
tw.sep(">", "PDB set_trace")
|
||||||
|
@ -129,12 +132,17 @@ class pytestPDB(object):
|
||||||
self._pytest_capman.suspend_global_capture(in_=True)
|
self._pytest_capman.suspend_global_capture(in_=True)
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
_pdb = _PdbWrapper()
|
_pdb = _PdbWrapper(**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()
|
_pdb = cls._pdb_cls(**kwargs)
|
||||||
|
return _pdb
|
||||||
|
|
||||||
if set_break:
|
@classmethod
|
||||||
|
def set_trace(cls, *args, **kwargs):
|
||||||
|
"""Invoke debugging via ``Pdb.set_trace``, dropping any IO capturing."""
|
||||||
|
frame = sys._getframe().f_back
|
||||||
|
_pdb = cls._init_pdb(*args, **kwargs)
|
||||||
_pdb.set_trace(frame)
|
_pdb.set_trace(frame)
|
||||||
|
|
||||||
|
|
||||||
|
@ -161,9 +169,9 @@ class PdbTrace(object):
|
||||||
|
|
||||||
|
|
||||||
def _test_pytest_function(pyfuncitem):
|
def _test_pytest_function(pyfuncitem):
|
||||||
pytestPDB.set_trace(set_break=False)
|
_pdb = pytestPDB._init_pdb()
|
||||||
testfunction = pyfuncitem.obj
|
testfunction = pyfuncitem.obj
|
||||||
pyfuncitem.obj = pdb.runcall
|
pyfuncitem.obj = _pdb.runcall
|
||||||
if pyfuncitem._isyieldedfunction():
|
if pyfuncitem._isyieldedfunction():
|
||||||
arg_list = list(pyfuncitem._args)
|
arg_list = list(pyfuncitem._args)
|
||||||
arg_list.insert(0, testfunction)
|
arg_list.insert(0, testfunction)
|
||||||
|
|
|
@ -390,6 +390,28 @@ class TestPDB(object):
|
||||||
assert "hello17" in rest # out is captured
|
assert "hello17" in rest # out is captured
|
||||||
self.flush(child)
|
self.flush(child)
|
||||||
|
|
||||||
|
def test_pdb_set_trace_kwargs(self, testdir):
|
||||||
|
p1 = testdir.makepyfile(
|
||||||
|
"""
|
||||||
|
import pytest
|
||||||
|
def test_1():
|
||||||
|
i = 0
|
||||||
|
print("hello17")
|
||||||
|
pytest.set_trace(header="== my_header ==")
|
||||||
|
x = 3
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
child = testdir.spawn_pytest(str(p1))
|
||||||
|
child.expect("== my_header ==")
|
||||||
|
assert "PDB set_trace" not in child.before.decode()
|
||||||
|
child.expect("Pdb")
|
||||||
|
child.sendeof()
|
||||||
|
rest = child.read().decode("utf-8")
|
||||||
|
assert "1 failed" in rest
|
||||||
|
assert "def test_1" in rest
|
||||||
|
assert "hello17" in rest # out is captured
|
||||||
|
self.flush(child)
|
||||||
|
|
||||||
def test_pdb_set_trace_interception(self, testdir):
|
def test_pdb_set_trace_interception(self, testdir):
|
||||||
p1 = testdir.makepyfile(
|
p1 = testdir.makepyfile(
|
||||||
"""
|
"""
|
||||||
|
@ -634,6 +656,12 @@ class TestPDB(object):
|
||||||
testdir.makepyfile(
|
testdir.makepyfile(
|
||||||
custom_pdb="""
|
custom_pdb="""
|
||||||
class CustomPdb(object):
|
class CustomPdb(object):
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
skip = kwargs.pop("skip")
|
||||||
|
assert skip == ["foo.*"]
|
||||||
|
print("__init__")
|
||||||
|
super(CustomPdb, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
def set_trace(*args, **kwargs):
|
def set_trace(*args, **kwargs):
|
||||||
print('custom set_trace>')
|
print('custom set_trace>')
|
||||||
"""
|
"""
|
||||||
|
@ -643,12 +671,13 @@ class TestPDB(object):
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
def test_foo():
|
def test_foo():
|
||||||
pytest.set_trace()
|
pytest.set_trace(skip=['foo.*'])
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
monkeypatch.setenv("PYTHONPATH", str(testdir.tmpdir))
|
monkeypatch.setenv("PYTHONPATH", str(testdir.tmpdir))
|
||||||
child = testdir.spawn_pytest("--pdbcls=custom_pdb:CustomPdb %s" % str(p1))
|
child = testdir.spawn_pytest("--pdbcls=custom_pdb:CustomPdb %s" % str(p1))
|
||||||
|
|
||||||
|
child.expect("__init__")
|
||||||
child.expect("custom set_trace>")
|
child.expect("custom set_trace>")
|
||||||
self.flush(child)
|
self.flush(child)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue