Skip to content

Commit 2e1f6c8

Browse files
committed
introduce resume/suspend functionality for FDCapture and SysCapture,
fixing problems with early bailouts (from argparse's parse() function e.g.) that wrote to stdout.
1 parent ca5e683 commit 2e1f6c8

File tree

2 files changed

+25
-11
lines changed

2 files changed

+25
-11
lines changed

_pytest/capture.py

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,7 @@ def pytest_load_initial_conftests(early_config, parser, args, __multicall__):
4646
pluginmanager.register(capman, "capturemanager")
4747

4848
# make sure that capturemanager is properly reset at final shutdown
49-
def teardown():
50-
try:
51-
capman.reset_capturings()
52-
except ValueError:
53-
pass
54-
55-
pluginmanager.add_shutdown(teardown)
49+
pluginmanager.add_shutdown(capman.reset_capturings)
5650

5751
# make sure logging does not raise exceptions at the end
5852
def silence_logging_at_shutdown():
@@ -124,16 +118,18 @@ def resumecapture(self, method=None):
124118
self._method2capture[method] = cap = self._getcapture(method)
125119
cap.start_capturing()
126120
else:
127-
cap.pop_outerr_to_orig()
121+
cap.resume_capturing()
128122

129123
def suspendcapture(self, item=None):
130124
self.deactivate_funcargs()
131125
method = self.__dict__.pop("_capturing", None)
126+
outerr = "", ""
132127
if method is not None:
133128
cap = self._method2capture.get(method)
134129
if cap is not None:
135-
return cap.readouterr()
136-
return "", ""
130+
outerr = cap.readouterr()
131+
cap.suspend_capturing()
132+
return outerr
137133

138134
def activate_funcargs(self, pyfuncitem):
139135
capfuncarg = pyfuncitem.__dict__.pop("_capfuncarg", None)
@@ -316,6 +312,18 @@ def pop_outerr_to_orig(self):
316312
if err:
317313
self.err.writeorg(err)
318314

315+
def suspend_capturing(self):
316+
if self.out:
317+
self.out.suspend()
318+
if self.err:
319+
self.err.suspend()
320+
321+
def resume_capturing(self):
322+
if self.out:
323+
self.out.resume()
324+
if self.err:
325+
self.err.resume()
326+
319327
def stop_capturing(self):
320328
""" stop capturing and reset capturing streams """
321329
if hasattr(self, '_reset'):
@@ -334,7 +342,7 @@ def readouterr(self):
334342
self.err.snap() if self.err is not None else "")
335343

336344
class NoCapture:
337-
__init__ = start = done = lambda *args: None
345+
__init__ = start = done = suspend = resume = lambda *args: None
338346

339347
class FDCapture:
340348
""" Capture IO to/from a given os-level filedescriptor. """

testing/acceptance_test.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,12 @@ def test_whatever():
335335
res = testdir.runpytest(p.basename)
336336
assert res.ret == 0
337337

338+
def test_unknown_option(self, testdir):
339+
result = testdir.runpytest("--qwlkej")
340+
result.stderr.fnmatch_lines("""
341+
*unrecognized*
342+
""")
343+
338344

339345
class TestInvocationVariants:
340346
def test_earlyinit(self, testdir):

0 commit comments

Comments
 (0)