Merge pull request #4951 from blueyed/fix-pdb-capfix

pdb: handle capturing with fixtures only
This commit is contained in:
Bruno Oliveira
2019-03-28 20:34:28 -03:00
committed by GitHub
4 changed files with 198 additions and 15 deletions

View File

@@ -107,6 +107,16 @@ class CaptureManager(object):
return MultiCapture(out=False, err=False, in_=False)
raise ValueError("unknown capturing method: %r" % method) # pragma: no cover
def is_capturing(self):
if self.is_globally_capturing():
return "global"
capture_fixture = getattr(self._current_item, "_capture_fixture", None)
if capture_fixture is not None:
return (
"fixture %s" % self._current_item._capture_fixture.request.fixturename
)
return False
# Global capturing control
def is_globally_capturing(self):
@@ -134,6 +144,15 @@ class CaptureManager(object):
if cap is not None:
cap.suspend_capturing(in_=in_)
def suspend(self, in_=False):
# Need to undo local capsys-et-al if it exists before disabling global capture.
self.suspend_fixture(self._current_item)
self.suspend_global_capture(in_)
def resume(self):
self.resume_global_capture()
self.resume_fixture(self._current_item)
def read_global_capture(self):
return self._global_capturing.readouterr()
@@ -168,14 +187,11 @@ class CaptureManager(object):
@contextlib.contextmanager
def global_and_fixture_disabled(self):
"""Context manager to temporarily disable global and current fixture capturing."""
# Need to undo local capsys-et-al if it exists before disabling global capture.
self.suspend_fixture(self._current_item)
self.suspend_global_capture(in_=False)
self.suspend()
try:
yield
finally:
self.resume_global_capture()
self.resume_fixture(self._current_item)
self.resume()
@contextlib.contextmanager
def item_capture(self, when, item):

View File

@@ -101,6 +101,12 @@ class pytestPDB(object):
_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. """
@@ -109,7 +115,7 @@ class pytestPDB(object):
if cls._pluginmanager is not None:
capman = cls._pluginmanager.getplugin("capturemanager")
if capman:
capman.suspend_global_capture(in_=True)
capman.suspend(in_=True)
tw = _pytest.config.create_terminal_writer(cls._config)
tw.line()
if cls._recursive_debug == 0:
@@ -117,10 +123,19 @@ class pytestPDB(object):
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)")
else:
tw.sep(">", "PDB set_trace")
capturing = cls._is_capturing(capman)
if capturing:
if capturing == "global":
tw.sep(">", "PDB set_trace (IO-capturing turned off)")
else:
tw.sep(
">",
"PDB set_trace (IO-capturing turned off for %s)"
% capturing,
)
else:
tw.sep(">", "PDB set_trace")
class _PdbWrapper(cls._pdb_cls, object):
_pytest_capman = capman
@@ -134,15 +149,24 @@ class pytestPDB(object):
def do_continue(self, arg):
ret = super(_PdbWrapper, self).do_continue(arg)
if self._pytest_capman:
if cls._recursive_debug == 0:
tw = _pytest.config.create_terminal_writer(cls._config)
tw.line()
if cls._recursive_debug == 0:
if self._pytest_capman.is_globally_capturing():
capman = self._pytest_capman
capturing = pytestPDB._is_capturing(capman)
if capturing:
if capturing == "global":
tw.sep(">", "PDB continue (IO-capturing resumed)")
else:
tw.sep(">", "PDB continue")
self._pytest_capman.resume_global_capture()
tw.sep(
">",
"PDB continue (IO-capturing resumed for %s)"
% capturing,
)
capman.resume()
else:
tw.sep(">", "PDB continue")
cls._pluginmanager.hook.pytest_leave_pdb(
config=cls._config, pdb=self
)