capture: overcome a mypy limitation by making CaptureResult a regular class
See the code comment for the rationale.
This commit is contained in:
parent
bee72e1925
commit
8a66f0a96d
|
@ -1,6 +1,6 @@
|
|||
"""Per-test stdout/stderr capturing mechanism."""
|
||||
import collections
|
||||
import contextlib
|
||||
import functools
|
||||
import io
|
||||
import os
|
||||
import sys
|
||||
|
@ -488,7 +488,59 @@ class FDCapture(FDCaptureBinary):
|
|||
|
||||
# MultiCapture
|
||||
|
||||
CaptureResult = collections.namedtuple("CaptureResult", ["out", "err"])
|
||||
|
||||
# This class was a namedtuple, but due to mypy limitation[0] it could not be
|
||||
# made generic, so was replaced by a regular class which tries to emulate the
|
||||
# pertinent parts of a namedtuple. If the mypy limitation is ever lifted, can
|
||||
# make it a namedtuple again.
|
||||
# [0]: https://github.com/python/mypy/issues/685
|
||||
@functools.total_ordering
|
||||
class CaptureResult:
|
||||
"""The result of :method:`CaptureFixture.readouterr`."""
|
||||
|
||||
# Can't use slots in Python<3.5.3 due to https://bugs.python.org/issue31272
|
||||
if sys.version_info >= (3, 5, 3):
|
||||
__slots__ = ("out", "err")
|
||||
|
||||
def __init__(self, out, err) -> None:
|
||||
self.out = out
|
||||
self.err = err
|
||||
|
||||
def __len__(self) -> int:
|
||||
return 2
|
||||
|
||||
def __iter__(self):
|
||||
return iter((self.out, self.err))
|
||||
|
||||
def __getitem__(self, item: int):
|
||||
return tuple(self)[item]
|
||||
|
||||
def _replace(self, out=None, err=None) -> "CaptureResult":
|
||||
return CaptureResult(
|
||||
out=self.out if out is None else out, err=self.err if err is None else err
|
||||
)
|
||||
|
||||
def count(self, value) -> int:
|
||||
return tuple(self).count(value)
|
||||
|
||||
def index(self, value) -> int:
|
||||
return tuple(self).index(value)
|
||||
|
||||
def __eq__(self, other: object) -> bool:
|
||||
if not isinstance(other, (CaptureResult, tuple)):
|
||||
return NotImplemented
|
||||
return tuple(self) == tuple(other)
|
||||
|
||||
def __hash__(self) -> int:
|
||||
return hash(tuple(self))
|
||||
|
||||
def __lt__(self, other: object) -> bool:
|
||||
if not isinstance(other, (CaptureResult, tuple)):
|
||||
return NotImplemented
|
||||
return tuple(self) < tuple(other)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return "CaptureResult(out={!r}, err={!r})".format(self.out, self.err)
|
||||
|
||||
|
||||
class MultiCapture:
|
||||
|
|
|
@ -14,6 +14,7 @@ import pytest
|
|||
from _pytest import capture
|
||||
from _pytest.capture import _get_multicapture
|
||||
from _pytest.capture import CaptureManager
|
||||
from _pytest.capture import CaptureResult
|
||||
from _pytest.capture import MultiCapture
|
||||
from _pytest.config import ExitCode
|
||||
|
||||
|
@ -856,6 +857,36 @@ def test_dontreadfrominput():
|
|||
f.close() # just for completeness
|
||||
|
||||
|
||||
def test_captureresult() -> None:
|
||||
cr = CaptureResult("out", "err")
|
||||
assert len(cr) == 2
|
||||
assert cr.out == "out"
|
||||
assert cr.err == "err"
|
||||
out, err = cr
|
||||
assert out == "out"
|
||||
assert err == "err"
|
||||
assert cr[0] == "out"
|
||||
assert cr[1] == "err"
|
||||
assert cr == cr
|
||||
assert cr == CaptureResult("out", "err")
|
||||
assert cr != CaptureResult("wrong", "err")
|
||||
assert cr == ("out", "err")
|
||||
assert cr != ("out", "wrong")
|
||||
assert hash(cr) == hash(CaptureResult("out", "err"))
|
||||
assert hash(cr) == hash(("out", "err"))
|
||||
assert hash(cr) != hash(("out", "wrong"))
|
||||
assert cr < ("z",)
|
||||
assert cr < ("z", "b")
|
||||
assert cr < ("z", "b", "c")
|
||||
assert cr.count("err") == 1
|
||||
assert cr.count("wrong") == 0
|
||||
assert cr.index("err") == 1
|
||||
with pytest.raises(ValueError):
|
||||
assert cr.index("wrong") == 0
|
||||
assert next(iter(cr)) == "out"
|
||||
assert cr._replace(err="replaced") == ("out", "replaced")
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def tmpfile(testdir) -> Generator[BinaryIO, None, None]:
|
||||
f = testdir.makepyfile("").open("wb+")
|
||||
|
|
Loading…
Reference in New Issue