capture: inline _capturing_for_request to simplify the control flow

With straight code, it is a little easier to understand, and simplify
further.
This commit is contained in:
Ran Benita 2020-04-12 21:09:39 +03:00
parent 491239d9b2
commit 2695b41df3
1 changed files with 33 additions and 42 deletions

View File

@ -9,14 +9,12 @@ import os
import sys import sys
from io import UnsupportedOperation from io import UnsupportedOperation
from tempfile import TemporaryFile from tempfile import TemporaryFile
from typing import Generator
from typing import Optional from typing import Optional
from typing import TextIO from typing import TextIO
import pytest import pytest
from _pytest.compat import TYPE_CHECKING from _pytest.compat import TYPE_CHECKING
from _pytest.config import Config from _pytest.config import Config
from _pytest.fixtures import FixtureRequest
if TYPE_CHECKING: if TYPE_CHECKING:
from typing_extensions import Literal from typing_extensions import Literal
@ -150,35 +148,20 @@ class CaptureManager:
def read_global_capture(self): def read_global_capture(self):
return self._global_capturing.readouterr() return self._global_capturing.readouterr()
# Fixture Control (it's just forwarding, think about removing this later) # Fixture Control
@contextlib.contextmanager def set_fixture(self, capture_fixture: "CaptureFixture") -> None:
def _capturing_for_request(
self, request: FixtureRequest
) -> Generator["CaptureFixture", None, None]:
"""
Context manager that creates a ``CaptureFixture`` instance for the
given ``request``, ensuring there is only a single one being requested
at the same time.
This is used as a helper with ``capsys``, ``capfd`` etc.
"""
if self._capture_fixture: if self._capture_fixture:
other_name = next( current_fixture = self._capture_fixture.request.fixturename
k requested_fixture = capture_fixture.request.fixturename
for k, v in map_fixname_class.items() capture_fixture.request.raiseerror(
if v is self._capture_fixture.captureclass
)
raise request.raiseerror(
"cannot use {} and {} at the same time".format( "cannot use {} and {} at the same time".format(
request.fixturename, other_name requested_fixture, current_fixture
) )
) )
capture_class = map_fixname_class[request.fixturename] self._capture_fixture = capture_fixture
self._capture_fixture = CaptureFixture(capture_class, request)
self.activate_fixture() def unset_fixture(self) -> None:
yield self._capture_fixture
self._capture_fixture.close()
self._capture_fixture = None self._capture_fixture = None
def activate_fixture(self): def activate_fixture(self):
@ -276,8 +259,12 @@ def capsys(request):
``out`` and ``err`` will be ``text`` objects. ``out`` and ``err`` will be ``text`` objects.
""" """
capman = request.config.pluginmanager.getplugin("capturemanager") capman = request.config.pluginmanager.getplugin("capturemanager")
with capman._capturing_for_request(request) as fixture: capture_fixture = CaptureFixture(SysCapture, request)
yield fixture capman.set_fixture(capture_fixture)
capture_fixture._start()
yield capture_fixture
capture_fixture.close()
capman.unset_fixture()
@pytest.fixture @pytest.fixture
@ -289,8 +276,12 @@ def capsysbinary(request):
``out`` and ``err`` will be ``bytes`` objects. ``out`` and ``err`` will be ``bytes`` objects.
""" """
capman = request.config.pluginmanager.getplugin("capturemanager") capman = request.config.pluginmanager.getplugin("capturemanager")
with capman._capturing_for_request(request) as fixture: capture_fixture = CaptureFixture(SysCaptureBinary, request)
yield fixture capman.set_fixture(capture_fixture)
capture_fixture._start()
yield capture_fixture
capture_fixture.close()
capman.unset_fixture()
@pytest.fixture @pytest.fixture
@ -302,8 +293,12 @@ def capfd(request):
``out`` and ``err`` will be ``text`` objects. ``out`` and ``err`` will be ``text`` objects.
""" """
capman = request.config.pluginmanager.getplugin("capturemanager") capman = request.config.pluginmanager.getplugin("capturemanager")
with capman._capturing_for_request(request) as fixture: capture_fixture = CaptureFixture(FDCapture, request)
yield fixture capman.set_fixture(capture_fixture)
capture_fixture._start()
yield capture_fixture
capture_fixture.close()
capman.unset_fixture()
@pytest.fixture @pytest.fixture
@ -315,8 +310,12 @@ def capfdbinary(request):
``out`` and ``err`` will be ``byte`` objects. ``out`` and ``err`` will be ``byte`` objects.
""" """
capman = request.config.pluginmanager.getplugin("capturemanager") capman = request.config.pluginmanager.getplugin("capturemanager")
with capman._capturing_for_request(request) as fixture: capture_fixture = CaptureFixture(FDCaptureBinary, request)
yield fixture capman.set_fixture(capture_fixture)
capture_fixture._start()
yield capture_fixture
capture_fixture.close()
capman.unset_fixture()
class CaptureIO(io.TextIOWrapper): class CaptureIO(io.TextIOWrapper):
@ -701,14 +700,6 @@ class TeeSysCapture(SysCapture):
self.tmpfile = tmpfile self.tmpfile = tmpfile
map_fixname_class = {
"capfd": FDCapture,
"capfdbinary": FDCaptureBinary,
"capsys": SysCapture,
"capsysbinary": SysCaptureBinary,
}
class DontReadFromInput: class DontReadFromInput:
encoding = None encoding = None