aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/python/pytest/py3/_pytest/capture.py
diff options
context:
space:
mode:
authorrobot-piglet <robot-piglet@yandex-team.com>2025-05-05 12:31:52 +0300
committerrobot-piglet <robot-piglet@yandex-team.com>2025-05-05 12:41:33 +0300
commit6ff49ec58061f642c3a2f83c61eba12820787dfc (patch)
treec733ec9bdb15ed280080d31dea8725bfec717acd /contrib/python/pytest/py3/_pytest/capture.py
parenteefca8305c6a545cc6b16dca3eb0d91dcef2adcd (diff)
downloadydb-6ff49ec58061f642c3a2f83c61eba12820787dfc.tar.gz
Intermediate changes
commit_hash:8b3bb826b17db8329ed1221f545c0645f12c552d
Diffstat (limited to 'contrib/python/pytest/py3/_pytest/capture.py')
-rw-r--r--contrib/python/pytest/py3/_pytest/capture.py77
1 files changed, 40 insertions, 37 deletions
diff --git a/contrib/python/pytest/py3/_pytest/capture.py b/contrib/python/pytest/py3/_pytest/capture.py
index a8ca0869f33..d4cabedba29 100644
--- a/contrib/python/pytest/py3/_pytest/capture.py
+++ b/contrib/python/pytest/py3/_pytest/capture.py
@@ -1,21 +1,25 @@
"""Per-test stdout/stderr capturing mechanism."""
+
import abc
import collections
import contextlib
import io
+from io import UnsupportedOperation
import os
import sys
-from io import UnsupportedOperation
from tempfile import TemporaryFile
from types import TracebackType
from typing import Any
from typing import AnyStr
from typing import BinaryIO
+from typing import Final
+from typing import final
from typing import Generator
from typing import Generic
from typing import Iterable
from typing import Iterator
from typing import List
+from typing import Literal
from typing import NamedTuple
from typing import Optional
from typing import TextIO
@@ -24,7 +28,6 @@ from typing import Type
from typing import TYPE_CHECKING
from typing import Union
-from _pytest.compat import final
from _pytest.config import Config
from _pytest.config import hookimpl
from _pytest.config.argparsing import Parser
@@ -34,12 +37,10 @@ from _pytest.fixtures import SubRequest
from _pytest.nodes import Collector
from _pytest.nodes import File
from _pytest.nodes import Item
+from _pytest.reports import CollectReport
-if TYPE_CHECKING:
- from typing_extensions import Final
- from typing_extensions import Literal
- _CaptureMethod = Literal["fd", "sys", "no", "tee-sys"]
+_CaptureMethod = Literal["fd", "sys", "no", "tee-sys"]
def pytest_addoption(parser: Parser) -> None:
@@ -132,8 +133,8 @@ def _windowsconsoleio_workaround(stream: TextIO) -> None:
sys.stderr = _reopen_stdio(sys.stderr, "wb")
-@hookimpl(hookwrapper=True)
-def pytest_load_initial_conftests(early_config: Config):
+@hookimpl(wrapper=True)
+def pytest_load_initial_conftests(early_config: Config) -> Generator[None, None, None]:
ns = early_config.known_args_namespace
if ns.capture == "fd":
_windowsconsoleio_workaround(sys.stdout)
@@ -147,12 +148,16 @@ def pytest_load_initial_conftests(early_config: Config):
# Finally trigger conftest loading but while capturing (issue #93).
capman.start_global_capturing()
- outcome = yield
- capman.suspend_global_capture()
- if outcome.excinfo is not None:
+ try:
+ try:
+ yield
+ finally:
+ capman.suspend_global_capture()
+ except BaseException:
out, err = capman.read_global_capture()
sys.stdout.write(out)
sys.stderr.write(err)
+ raise
# IO Helpers.
@@ -585,7 +590,7 @@ if sys.version_info >= (3, 11) or TYPE_CHECKING:
@final
class CaptureResult(NamedTuple, Generic[AnyStr]):
- """The result of :method:`CaptureFixture.readouterr`."""
+ """The result of :method:`caplog.readouterr() <pytest.CaptureFixture.readouterr>`."""
out: AnyStr
err: AnyStr
@@ -595,7 +600,7 @@ else:
class CaptureResult(
collections.namedtuple("CaptureResult", ["out", "err"]), Generic[AnyStr]
):
- """The result of :method:`CaptureFixture.readouterr`."""
+ """The result of :method:`caplog.readouterr() <pytest.CaptureFixture.readouterr>`."""
__slots__ = ()
@@ -687,7 +692,7 @@ class MultiCapture(Generic[AnyStr]):
return CaptureResult(out, err) # type: ignore[arg-type]
-def _get_multicapture(method: "_CaptureMethod") -> MultiCapture[str]:
+def _get_multicapture(method: _CaptureMethod) -> MultiCapture[str]:
if method == "fd":
return MultiCapture(in_=FDCapture(0), out=FDCapture(1), err=FDCapture(2))
elif method == "sys":
@@ -723,7 +728,7 @@ class CaptureManager:
needed to ensure the fixtures take precedence over the global capture.
"""
- def __init__(self, method: "_CaptureMethod") -> None:
+ def __init__(self, method: _CaptureMethod) -> None:
self._method: Final = method
self._global_capturing: Optional[MultiCapture[str]] = None
self._capture_fixture: Optional[CaptureFixture[Any]] = None
@@ -786,9 +791,7 @@ class CaptureManager:
current_fixture = self._capture_fixture.request.fixturename
requested_fixture = capture_fixture.request.fixturename
capture_fixture.request.raiseerror(
- "cannot use {} and {} at the same time".format(
- requested_fixture, current_fixture
- )
+ f"cannot use {requested_fixture} and {current_fixture} at the same time"
)
self._capture_fixture = capture_fixture
@@ -843,41 +846,45 @@ class CaptureManager:
self.deactivate_fixture()
self.suspend_global_capture(in_=False)
- out, err = self.read_global_capture()
- item.add_report_section(when, "stdout", out)
- item.add_report_section(when, "stderr", err)
+ out, err = self.read_global_capture()
+ item.add_report_section(when, "stdout", out)
+ item.add_report_section(when, "stderr", err)
# Hooks
- @hookimpl(hookwrapper=True)
- def pytest_make_collect_report(self, collector: Collector):
+ @hookimpl(wrapper=True)
+ def pytest_make_collect_report(
+ self, collector: Collector
+ ) -> Generator[None, CollectReport, CollectReport]:
if isinstance(collector, File):
self.resume_global_capture()
- outcome = yield
- self.suspend_global_capture()
+ try:
+ rep = yield
+ finally:
+ self.suspend_global_capture()
out, err = self.read_global_capture()
- rep = outcome.get_result()
if out:
rep.sections.append(("Captured stdout", out))
if err:
rep.sections.append(("Captured stderr", err))
else:
- yield
+ rep = yield
+ return rep
- @hookimpl(hookwrapper=True)
+ @hookimpl(wrapper=True)
def pytest_runtest_setup(self, item: Item) -> Generator[None, None, None]:
with self.item_capture("setup", item):
- yield
+ return (yield)
- @hookimpl(hookwrapper=True)
+ @hookimpl(wrapper=True)
def pytest_runtest_call(self, item: Item) -> Generator[None, None, None]:
with self.item_capture("call", item):
- yield
+ return (yield)
- @hookimpl(hookwrapper=True)
+ @hookimpl(wrapper=True)
def pytest_runtest_teardown(self, item: Item) -> Generator[None, None, None]:
with self.item_capture("teardown", item):
- yield
+ return (yield)
@hookimpl(tryfirst=True)
def pytest_keyboard_interrupt(self) -> None:
@@ -980,7 +987,6 @@ def capsys(request: SubRequest) -> Generator[CaptureFixture[str], None, None]:
Returns an instance of :class:`CaptureFixture[str] <pytest.CaptureFixture>`.
Example:
-
.. code-block:: python
def test_output(capsys):
@@ -1008,7 +1014,6 @@ def capsysbinary(request: SubRequest) -> Generator[CaptureFixture[bytes], None,
Returns an instance of :class:`CaptureFixture[bytes] <pytest.CaptureFixture>`.
Example:
-
.. code-block:: python
def test_output(capsysbinary):
@@ -1036,7 +1041,6 @@ def capfd(request: SubRequest) -> Generator[CaptureFixture[str], None, None]:
Returns an instance of :class:`CaptureFixture[str] <pytest.CaptureFixture>`.
Example:
-
.. code-block:: python
def test_system_echo(capfd):
@@ -1064,7 +1068,6 @@ def capfdbinary(request: SubRequest) -> Generator[CaptureFixture[bytes], None, N
Returns an instance of :class:`CaptureFixture[bytes] <pytest.CaptureFixture>`.
Example:
-
.. code-block:: python
def test_system_echo(capfdbinary):