Skip to content

capture: factor out _get_multicapture #6788

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Feb 22, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 20 additions & 13 deletions src/_pytest/capture.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,15 @@
import pytest
from _pytest.compat import CaptureAndPassthroughIO
from _pytest.compat import CaptureIO
from _pytest.compat import TYPE_CHECKING
from _pytest.config import Config
from _pytest.fixtures import FixtureRequest

if TYPE_CHECKING:
from typing_extensions import Literal

_CaptureMethod = Literal["fd", "sys", "no", "tee-sys"]

patchsysdict = {0: "stdin", 1: "stdout", 2: "stderr"}


Expand Down Expand Up @@ -66,6 +72,18 @@ def pytest_load_initial_conftests(early_config: Config):
sys.stderr.write(err)


def _get_multicapture(method: "_CaptureMethod") -> "MultiCapture":
if method == "fd":
return MultiCapture(out=True, err=True, Capture=FDCapture)
elif method == "sys":
return MultiCapture(out=True, err=True, Capture=SysCapture)
elif method == "no":
return MultiCapture(out=False, err=False, in_=False)
elif method == "tee-sys":
return MultiCapture(out=True, err=True, in_=False, Capture=TeeSysCapture)
raise ValueError("unknown capturing method: {!r}".format(method))


class CaptureManager:
"""
Capture plugin, manages that the appropriate capture method is enabled/disabled during collection and each
Expand All @@ -79,7 +97,7 @@ class CaptureManager:
case special handling is needed to ensure the fixtures take precedence over the global capture.
"""

def __init__(self, method) -> None:
def __init__(self, method: "_CaptureMethod") -> None:
self._method = method
self._global_capturing = None
self._capture_fixture = None # type: Optional[CaptureFixture]
Expand All @@ -89,17 +107,6 @@ def __repr__(self):
self._method, self._global_capturing, self._capture_fixture
)

def _getcapture(self, method):
if method == "fd":
return MultiCapture(out=True, err=True, Capture=FDCapture)
elif method == "sys":
return MultiCapture(out=True, err=True, Capture=SysCapture)
elif method == "no":
return MultiCapture(out=False, err=False, in_=False)
elif method == "tee-sys":
return MultiCapture(out=True, err=True, in_=False, Capture=TeeSysCapture)
raise ValueError("unknown capturing method: %r" % method) # pragma: no cover

def is_capturing(self):
if self.is_globally_capturing():
return "global"
Expand All @@ -114,7 +121,7 @@ def is_globally_capturing(self):

def start_global_capturing(self):
assert self._global_capturing is None
self._global_capturing = self._getcapture(self._method)
self._global_capturing = _get_multicapture(self._method)
self._global_capturing.start_capturing()

def stop_global_capturing(self):
Expand Down
9 changes: 9 additions & 0 deletions testing/test_capture.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@

import pytest
from _pytest import capture
from _pytest.capture import _get_multicapture
from _pytest.capture import CaptureManager
from _pytest.capture import MultiCapture
from _pytest.config import ExitCode

# note: py.io capture tests where copied from
Expand Down Expand Up @@ -1563,3 +1565,10 @@ def test_encodedfile_writelines(tmpfile: BinaryIO) -> None:
tmpfile.close()
with pytest.raises(ValueError):
ef.read()


def test__get_multicapture() -> None:
assert isinstance(_get_multicapture("fd"), MultiCapture)
pytest.raises(ValueError, _get_multicapture, "unknown").match(
r"^unknown capturing method: 'unknown'"
)