Skip to content

Commit 9a879ee

Browse files
committed
Merge pull request #7651 from bluetech/capture-safe-disable
capture: fix disabled()/global_and_fixture_disabled() enabling capturing when it was disabled (cherry picked from commit bb38ae9)
1 parent e9d18bd commit 9a879ee

File tree

3 files changed

+51
-3
lines changed

3 files changed

+51
-3
lines changed

changelog/7148.bugfix.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fixed ``--log-cli`` potentially causing unrelated ``print`` output to be swallowed.

src/_pytest/capture.py

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -537,7 +537,7 @@ def suspend_capturing(self, in_: bool = False) -> None:
537537
self._in_suspended = True
538538

539539
def resume_capturing(self) -> None:
540-
self._state = "resumed"
540+
self._state = "started"
541541
if self.out:
542542
self.out.resume()
543543
if self.err:
@@ -558,6 +558,10 @@ def stop_capturing(self) -> None:
558558
if self.in_:
559559
self.in_.done()
560560

561+
def is_started(self) -> bool:
562+
"""Whether actively capturing -- not suspended or stopped."""
563+
return self._state == "started"
564+
561565
def readouterr(self) -> CaptureResult:
562566
if self.out:
563567
out = self.out.snap()
@@ -697,11 +701,19 @@ def resume_fixture(self) -> None:
697701
@contextlib.contextmanager
698702
def global_and_fixture_disabled(self) -> Generator[None, None, None]:
699703
"""Context manager to temporarily disable global and current fixture capturing."""
700-
self.suspend()
704+
do_fixture = self._capture_fixture and self._capture_fixture._is_started()
705+
if do_fixture:
706+
self.suspend_fixture()
707+
do_global = self._global_capturing and self._global_capturing.is_started()
708+
if do_global:
709+
self.suspend_global_capture()
701710
try:
702711
yield
703712
finally:
704-
self.resume()
713+
if do_global:
714+
self.resume_global_capture()
715+
if do_fixture:
716+
self.resume_fixture()
705717

706718
@contextlib.contextmanager
707719
def item_capture(self, when: str, item: Item) -> Generator[None, None, None]:
@@ -810,6 +822,12 @@ def _resume(self) -> None:
810822
if self._capture is not None:
811823
self._capture.resume_capturing()
812824

825+
def _is_started(self) -> bool:
826+
"""Whether actively capturing -- not disabled or closed."""
827+
if self._capture is not None:
828+
return self._capture.is_started()
829+
return False
830+
813831
@contextlib.contextmanager
814832
def disabled(self) -> Generator[None, None, None]:
815833
"""Temporarily disables capture while inside the 'with' block."""

testing/test_capture.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from _pytest.capture import CaptureManager
1717
from _pytest.capture import MultiCapture
1818
from _pytest.config import ExitCode
19+
from _pytest.pytester import Testdir
1920

2021
# note: py.io capture tests where copied from
2122
# pylib 1.4.20.dev2 (rev 13d9af95547e)
@@ -633,6 +634,34 @@ def test_normal():
633634
else:
634635
result.stdout.no_fnmatch_line("*test_normal executed*")
635636

637+
def test_disabled_capture_fixture_twice(self, testdir: Testdir) -> None:
638+
"""Test that an inner disabled() exit doesn't undo an outer disabled().
639+
640+
Issue #7148.
641+
"""
642+
testdir.makepyfile(
643+
"""
644+
def test_disabled(capfd):
645+
print('captured before')
646+
with capfd.disabled():
647+
print('while capture is disabled 1')
648+
with capfd.disabled():
649+
print('while capture is disabled 2')
650+
print('while capture is disabled 1 after')
651+
print('captured after')
652+
assert capfd.readouterr() == ('captured before\\ncaptured after\\n', '')
653+
"""
654+
)
655+
result = testdir.runpytest_subprocess()
656+
result.stdout.fnmatch_lines(
657+
[
658+
"*while capture is disabled 1",
659+
"*while capture is disabled 2",
660+
"*while capture is disabled 1 after",
661+
],
662+
consecutive=True,
663+
)
664+
636665
@pytest.mark.parametrize("fixture", ["capsys", "capfd"])
637666
def test_fixture_use_by_other_fixtures(self, testdir, fixture):
638667
"""

0 commit comments

Comments
 (0)