Merge pull request #7651 from bluetech/capture-safe-disable
capture: fix disabled()/global_and_fixture_disabled() enabling capturing when it was disabled
This commit is contained in:
commit
bb38ae9c52
|
@ -0,0 +1 @@
|
||||||
|
Fixed ``--log-cli`` potentially causing unrelated ``print`` output to be swallowed.
|
|
@ -592,7 +592,7 @@ class MultiCapture(Generic[AnyStr]):
|
||||||
self._in_suspended = True
|
self._in_suspended = True
|
||||||
|
|
||||||
def resume_capturing(self) -> None:
|
def resume_capturing(self) -> None:
|
||||||
self._state = "resumed"
|
self._state = "started"
|
||||||
if self.out:
|
if self.out:
|
||||||
self.out.resume()
|
self.out.resume()
|
||||||
if self.err:
|
if self.err:
|
||||||
|
@ -613,6 +613,10 @@ class MultiCapture(Generic[AnyStr]):
|
||||||
if self.in_:
|
if self.in_:
|
||||||
self.in_.done()
|
self.in_.done()
|
||||||
|
|
||||||
|
def is_started(self) -> bool:
|
||||||
|
"""Whether actively capturing -- not suspended or stopped."""
|
||||||
|
return self._state == "started"
|
||||||
|
|
||||||
def readouterr(self) -> CaptureResult[AnyStr]:
|
def readouterr(self) -> CaptureResult[AnyStr]:
|
||||||
if self.out:
|
if self.out:
|
||||||
out = self.out.snap()
|
out = self.out.snap()
|
||||||
|
@ -757,11 +761,19 @@ class CaptureManager:
|
||||||
@contextlib.contextmanager
|
@contextlib.contextmanager
|
||||||
def global_and_fixture_disabled(self) -> Generator[None, None, None]:
|
def global_and_fixture_disabled(self) -> Generator[None, None, None]:
|
||||||
"""Context manager to temporarily disable global and current fixture capturing."""
|
"""Context manager to temporarily disable global and current fixture capturing."""
|
||||||
self.suspend()
|
do_fixture = self._capture_fixture and self._capture_fixture._is_started()
|
||||||
|
if do_fixture:
|
||||||
|
self.suspend_fixture()
|
||||||
|
do_global = self._global_capturing and self._global_capturing.is_started()
|
||||||
|
if do_global:
|
||||||
|
self.suspend_global_capture()
|
||||||
try:
|
try:
|
||||||
yield
|
yield
|
||||||
finally:
|
finally:
|
||||||
self.resume()
|
if do_global:
|
||||||
|
self.resume_global_capture()
|
||||||
|
if do_fixture:
|
||||||
|
self.resume_fixture()
|
||||||
|
|
||||||
@contextlib.contextmanager
|
@contextlib.contextmanager
|
||||||
def item_capture(self, when: str, item: Item) -> Generator[None, None, None]:
|
def item_capture(self, when: str, item: Item) -> Generator[None, None, None]:
|
||||||
|
@ -871,6 +883,12 @@ class CaptureFixture(Generic[AnyStr]):
|
||||||
if self._capture is not None:
|
if self._capture is not None:
|
||||||
self._capture.resume_capturing()
|
self._capture.resume_capturing()
|
||||||
|
|
||||||
|
def _is_started(self) -> bool:
|
||||||
|
"""Whether actively capturing -- not disabled or closed."""
|
||||||
|
if self._capture is not None:
|
||||||
|
return self._capture.is_started()
|
||||||
|
return False
|
||||||
|
|
||||||
@contextlib.contextmanager
|
@contextlib.contextmanager
|
||||||
def disabled(self) -> Generator[None, None, None]:
|
def disabled(self) -> Generator[None, None, None]:
|
||||||
"""Temporarily disable capturing while inside the ``with`` block."""
|
"""Temporarily disable capturing while inside the ``with`` block."""
|
||||||
|
|
|
@ -17,6 +17,7 @@ from _pytest.capture import CaptureManager
|
||||||
from _pytest.capture import CaptureResult
|
from _pytest.capture import CaptureResult
|
||||||
from _pytest.capture import MultiCapture
|
from _pytest.capture import MultiCapture
|
||||||
from _pytest.config import ExitCode
|
from _pytest.config import ExitCode
|
||||||
|
from _pytest.pytester import Testdir
|
||||||
|
|
||||||
# note: py.io capture tests where copied from
|
# note: py.io capture tests where copied from
|
||||||
# pylib 1.4.20.dev2 (rev 13d9af95547e)
|
# pylib 1.4.20.dev2 (rev 13d9af95547e)
|
||||||
|
@ -640,6 +641,34 @@ class TestCaptureFixture:
|
||||||
else:
|
else:
|
||||||
result.stdout.no_fnmatch_line("*test_normal executed*")
|
result.stdout.no_fnmatch_line("*test_normal executed*")
|
||||||
|
|
||||||
|
def test_disabled_capture_fixture_twice(self, testdir: Testdir) -> None:
|
||||||
|
"""Test that an inner disabled() exit doesn't undo an outer disabled().
|
||||||
|
|
||||||
|
Issue #7148.
|
||||||
|
"""
|
||||||
|
testdir.makepyfile(
|
||||||
|
"""
|
||||||
|
def test_disabled(capfd):
|
||||||
|
print('captured before')
|
||||||
|
with capfd.disabled():
|
||||||
|
print('while capture is disabled 1')
|
||||||
|
with capfd.disabled():
|
||||||
|
print('while capture is disabled 2')
|
||||||
|
print('while capture is disabled 1 after')
|
||||||
|
print('captured after')
|
||||||
|
assert capfd.readouterr() == ('captured before\\ncaptured after\\n', '')
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
result = testdir.runpytest_subprocess()
|
||||||
|
result.stdout.fnmatch_lines(
|
||||||
|
[
|
||||||
|
"*while capture is disabled 1",
|
||||||
|
"*while capture is disabled 2",
|
||||||
|
"*while capture is disabled 1 after",
|
||||||
|
],
|
||||||
|
consecutive=True,
|
||||||
|
)
|
||||||
|
|
||||||
@pytest.mark.parametrize("fixture", ["capsys", "capfd"])
|
@pytest.mark.parametrize("fixture", ["capsys", "capfd"])
|
||||||
def test_fixture_use_by_other_fixtures(self, testdir, fixture):
|
def test_fixture_use_by_other_fixtures(self, testdir, fixture):
|
||||||
"""Ensure that capsys and capfd can be used by other fixtures during
|
"""Ensure that capsys and capfd can be used by other fixtures during
|
||||||
|
|
Loading…
Reference in New Issue