introduce resume/suspend functionality for FDCapture and SysCapture,

fixing problems with early bailouts (from argparse's parse() function e.g.)
that wrote to stdout.
This commit is contained in:
holger krekel 2014-04-01 14:19:58 +02:00
parent ca5e6830c6
commit 2e1f6c85f6
2 changed files with 25 additions and 11 deletions

View File

@ -46,13 +46,7 @@ def pytest_load_initial_conftests(early_config, parser, args, __multicall__):
pluginmanager.register(capman, "capturemanager") pluginmanager.register(capman, "capturemanager")
# make sure that capturemanager is properly reset at final shutdown # make sure that capturemanager is properly reset at final shutdown
def teardown(): pluginmanager.add_shutdown(capman.reset_capturings)
try:
capman.reset_capturings()
except ValueError:
pass
pluginmanager.add_shutdown(teardown)
# make sure logging does not raise exceptions at the end # make sure logging does not raise exceptions at the end
def silence_logging_at_shutdown(): def silence_logging_at_shutdown():
@ -124,16 +118,18 @@ class CaptureManager:
self._method2capture[method] = cap = self._getcapture(method) self._method2capture[method] = cap = self._getcapture(method)
cap.start_capturing() cap.start_capturing()
else: else:
cap.pop_outerr_to_orig() cap.resume_capturing()
def suspendcapture(self, item=None): def suspendcapture(self, item=None):
self.deactivate_funcargs() self.deactivate_funcargs()
method = self.__dict__.pop("_capturing", None) method = self.__dict__.pop("_capturing", None)
outerr = "", ""
if method is not None: if method is not None:
cap = self._method2capture.get(method) cap = self._method2capture.get(method)
if cap is not None: if cap is not None:
return cap.readouterr() outerr = cap.readouterr()
return "", "" cap.suspend_capturing()
return outerr
def activate_funcargs(self, pyfuncitem): def activate_funcargs(self, pyfuncitem):
capfuncarg = pyfuncitem.__dict__.pop("_capfuncarg", None) capfuncarg = pyfuncitem.__dict__.pop("_capfuncarg", None)
@ -316,6 +312,18 @@ class MultiCapture(object):
if err: if err:
self.err.writeorg(err) self.err.writeorg(err)
def suspend_capturing(self):
if self.out:
self.out.suspend()
if self.err:
self.err.suspend()
def resume_capturing(self):
if self.out:
self.out.resume()
if self.err:
self.err.resume()
def stop_capturing(self): def stop_capturing(self):
""" stop capturing and reset capturing streams """ """ stop capturing and reset capturing streams """
if hasattr(self, '_reset'): if hasattr(self, '_reset'):
@ -334,7 +342,7 @@ class MultiCapture(object):
self.err.snap() if self.err is not None else "") self.err.snap() if self.err is not None else "")
class NoCapture: class NoCapture:
__init__ = start = done = lambda *args: None __init__ = start = done = suspend = resume = lambda *args: None
class FDCapture: class FDCapture:
""" Capture IO to/from a given os-level filedescriptor. """ """ Capture IO to/from a given os-level filedescriptor. """

View File

@ -335,6 +335,12 @@ class TestGeneralUsage:
res = testdir.runpytest(p.basename) res = testdir.runpytest(p.basename)
assert res.ret == 0 assert res.ret == 0
def test_unknown_option(self, testdir):
result = testdir.runpytest("--qwlkej")
result.stderr.fnmatch_lines("""
*unrecognized*
""")
class TestInvocationVariants: class TestInvocationVariants:
def test_earlyinit(self, testdir): def test_earlyinit(self, testdir):