From 706ea86bbae448ac9a1689ecfa2b1eaf630b106f Mon Sep 17 00:00:00 2001 From: Daniel Hahler Date: Sat, 22 Feb 2020 23:39:20 +0100 Subject: [PATCH] capture: factor out _get_multicapture (#6788) Ref: https://github.com/pytest-dev/pytest/pull/6671#issuecomment-588408992 --- src/_pytest/capture.py | 33 ++++++++++++++++++++------------- testing/test_capture.py | 9 +++++++++ 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/src/_pytest/capture.py b/src/_pytest/capture.py index 3643d782d..a1335d654 100644 --- a/src/_pytest/capture.py +++ b/src/_pytest/capture.py @@ -17,9 +17,15 @@ from typing import Optional 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"} @@ -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 @@ -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] @@ -89,17 +107,6 @@ class CaptureManager: 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" @@ -114,7 +121,7 @@ class CaptureManager: 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): diff --git a/testing/test_capture.py b/testing/test_capture.py index e8e09ae73..7396fd260 100644 --- a/testing/test_capture.py +++ b/testing/test_capture.py @@ -14,7 +14,9 @@ from typing import TextIO 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 @@ -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'" + )