Skip to content

Commit da81c1e

Browse files
authored
Merge pull request #4950 from blueyed/capture
Revisit capturing module: repr, doc fixes, minor
2 parents 23ab432 + 7395501 commit da81c1e

File tree

2 files changed

+50
-41
lines changed

2 files changed

+50
-41
lines changed

src/_pytest/capture.py

Lines changed: 49 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -91,15 +91,21 @@ def __init__(self, method):
9191
self._global_capturing = None
9292
self._current_item = None
9393

94+
def __repr__(self):
95+
return "<CaptureManager _method=%r _global_capturing=%r _current_item=%r>" % (
96+
self._method,
97+
self._global_capturing,
98+
self._current_item,
99+
)
100+
94101
def _getcapture(self, method):
95102
if method == "fd":
96103
return MultiCapture(out=True, err=True, Capture=FDCapture)
97104
elif method == "sys":
98105
return MultiCapture(out=True, err=True, Capture=SysCapture)
99106
elif method == "no":
100107
return MultiCapture(out=False, err=False, in_=False)
101-
else:
102-
raise ValueError("unknown capturing method: %r" % method)
108+
raise ValueError("unknown capturing method: %r" % method) # pragma: no cover
103109

104110
# Global capturing control
105111

@@ -161,8 +167,8 @@ def resume_fixture(self, item):
161167

162168
@contextlib.contextmanager
163169
def global_and_fixture_disabled(self):
164-
"""Context manager to temporarily disables global and current fixture capturing."""
165-
# Need to undo local capsys-et-al if exists before disabling global capture
170+
"""Context manager to temporarily disable global and current fixture capturing."""
171+
# Need to undo local capsys-et-al if it exists before disabling global capture.
166172
self.suspend_fixture(self._current_item)
167173
self.suspend_global_capture(in_=False)
168174
try:
@@ -247,10 +253,11 @@ def _ensure_only_one_capture_fixture(request, name):
247253

248254
@pytest.fixture
249255
def capsys(request):
250-
"""Enable capturing of writes to ``sys.stdout`` and ``sys.stderr`` and make
251-
captured output available via ``capsys.readouterr()`` method calls
252-
which return a ``(out, err)`` namedtuple. ``out`` and ``err`` will be ``text``
253-
objects.
256+
"""Enable text capturing of writes to ``sys.stdout`` and ``sys.stderr``.
257+
258+
The captured output is made available via ``capsys.readouterr()`` method
259+
calls, which return a ``(out, err)`` namedtuple.
260+
``out`` and ``err`` will be ``text`` objects.
254261
"""
255262
_ensure_only_one_capture_fixture(request, "capsys")
256263
with _install_capture_fixture_on_item(request, SysCapture) as fixture:
@@ -259,26 +266,28 @@ def capsys(request):
259266

260267
@pytest.fixture
261268
def capsysbinary(request):
262-
"""Enable capturing of writes to ``sys.stdout`` and ``sys.stderr`` and make
263-
captured output available via ``capsys.readouterr()`` method calls
264-
which return a ``(out, err)`` tuple. ``out`` and ``err`` will be ``bytes``
265-
objects.
269+
"""Enable bytes capturing of writes to ``sys.stdout`` and ``sys.stderr``.
270+
271+
The captured output is made available via ``capsysbinary.readouterr()``
272+
method calls, which return a ``(out, err)`` namedtuple.
273+
``out`` and ``err`` will be ``bytes`` objects.
266274
"""
267275
_ensure_only_one_capture_fixture(request, "capsysbinary")
268276
# Currently, the implementation uses the python3 specific `.buffer`
269277
# property of CaptureIO.
270278
if sys.version_info < (3,):
271-
raise request.raiseerror("capsysbinary is only supported on python 3")
279+
raise request.raiseerror("capsysbinary is only supported on Python 3")
272280
with _install_capture_fixture_on_item(request, SysCaptureBinary) as fixture:
273281
yield fixture
274282

275283

276284
@pytest.fixture
277285
def capfd(request):
278-
"""Enable capturing of writes to file descriptors ``1`` and ``2`` and make
279-
captured output available via ``capfd.readouterr()`` method calls
280-
which return a ``(out, err)`` tuple. ``out`` and ``err`` will be ``text``
281-
objects.
286+
"""Enable text capturing of writes to file descriptors ``1`` and ``2``.
287+
288+
The captured output is made available via ``capfd.readouterr()`` method
289+
calls, which return a ``(out, err)`` namedtuple.
290+
``out`` and ``err`` will be ``text`` objects.
282291
"""
283292
_ensure_only_one_capture_fixture(request, "capfd")
284293
if not hasattr(os, "dup"):
@@ -291,10 +300,11 @@ def capfd(request):
291300

292301
@pytest.fixture
293302
def capfdbinary(request):
294-
"""Enable capturing of write to file descriptors 1 and 2 and make
295-
captured output available via ``capfdbinary.readouterr`` method calls
296-
which return a ``(out, err)`` tuple. ``out`` and ``err`` will be
297-
``bytes`` objects.
303+
"""Enable bytes capturing of writes to file descriptors ``1`` and ``2``.
304+
305+
The captured output is made available via ``capfd.readouterr()`` method
306+
calls, which return a ``(out, err)`` namedtuple.
307+
``out`` and ``err`` will be ``byte`` objects.
298308
"""
299309
_ensure_only_one_capture_fixture(request, "capfdbinary")
300310
if not hasattr(os, "dup"):
@@ -316,9 +326,9 @@ def _install_capture_fixture_on_item(request, capture_class):
316326
"""
317327
request.node._capture_fixture = fixture = CaptureFixture(capture_class, request)
318328
capmanager = request.config.pluginmanager.getplugin("capturemanager")
319-
# need to active this fixture right away in case it is being used by another fixture (setup phase)
320-
# if this fixture is being used only by a test function (call phase), then we wouldn't need this
321-
# activation, but it doesn't hurt
329+
# Need to active this fixture right away in case it is being used by another fixture (setup phase).
330+
# If this fixture is being used only by a test function (call phase), then we wouldn't need this
331+
# activation, but it doesn't hurt.
322332
capmanager.activate_fixture(request.node)
323333
yield fixture
324334
fixture.close()
@@ -357,7 +367,7 @@ def close(self):
357367
def readouterr(self):
358368
"""Read and return the captured output so far, resetting the internal buffer.
359369
360-
:return: captured content as a namedtuple with ``out`` and ``err`` string attributes
370+
:return: captured content as a namedtuple with ``out`` and ``err`` string attributes
361371
"""
362372
captured_out, captured_err = self._captured_out, self._captured_err
363373
if self._capture is not None:
@@ -446,6 +456,9 @@ def __init__(self, out=True, err=True, in_=True, Capture=None):
446456
if err:
447457
self.err = Capture(2)
448458

459+
def __repr__(self):
460+
return "<MultiCapture out=%r err=%r in_=%r>" % (self.out, self.err, self.in_)
461+
449462
def start_capturing(self):
450463
if self.in_:
451464
self.in_.start()
@@ -593,7 +606,7 @@ class FDCapture(FDCaptureBinary):
593606
EMPTY_BUFFER = str()
594607

595608
def snap(self):
596-
res = FDCaptureBinary.snap(self)
609+
res = super(FDCapture, self).snap()
597610
enc = getattr(self.tmpfile, "encoding", None)
598611
if enc and isinstance(res, bytes):
599612
res = six.text_type(res, enc, "replace")
@@ -696,13 +709,11 @@ def _colorama_workaround():
696709
first import of colorama while I/O capture is active, colorama will
697710
fail in various ways.
698711
"""
699-
700-
if not sys.platform.startswith("win32"):
701-
return
702-
try:
703-
import colorama # noqa
704-
except ImportError:
705-
pass
712+
if sys.platform.startswith("win32"):
713+
try:
714+
import colorama # noqa: F401
715+
except ImportError:
716+
pass
706717

707718

708719
def _readline_workaround():
@@ -723,13 +734,11 @@ def _readline_workaround():
723734
724735
See https://github.com/pytest-dev/pytest/pull/1281
725736
"""
726-
727-
if not sys.platform.startswith("win32"):
728-
return
729-
try:
730-
import readline # noqa
731-
except ImportError:
732-
pass
737+
if sys.platform.startswith("win32"):
738+
try:
739+
import readline # noqa: F401
740+
except ImportError:
741+
pass
733742

734743

735744
def _py36_windowsconsoleio_workaround(stream):

testing/test_capture.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -566,7 +566,7 @@ def test_hello(capsysbinary):
566566
result.stdout.fnmatch_lines(
567567
[
568568
"*test_hello*",
569-
"*capsysbinary is only supported on python 3*",
569+
"*capsysbinary is only supported on Python 3*",
570570
"*1 error in*",
571571
]
572572
)

0 commit comments

Comments
 (0)