Merge pull request #4950 from blueyed/capture
Revisit capturing module: repr, doc fixes, minor
This commit is contained in:
		
						commit
						da81c1e49a
					
				|  | @ -91,6 +91,13 @@ class CaptureManager(object): | ||||||
|         self._global_capturing = None |         self._global_capturing = None | ||||||
|         self._current_item = None |         self._current_item = None | ||||||
| 
 | 
 | ||||||
|  |     def __repr__(self): | ||||||
|  |         return "<CaptureManager _method=%r _global_capturing=%r _current_item=%r>" % ( | ||||||
|  |             self._method, | ||||||
|  |             self._global_capturing, | ||||||
|  |             self._current_item, | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|     def _getcapture(self, method): |     def _getcapture(self, method): | ||||||
|         if method == "fd": |         if method == "fd": | ||||||
|             return MultiCapture(out=True, err=True, Capture=FDCapture) |             return MultiCapture(out=True, err=True, Capture=FDCapture) | ||||||
|  | @ -98,8 +105,7 @@ class CaptureManager(object): | ||||||
|             return MultiCapture(out=True, err=True, Capture=SysCapture) |             return MultiCapture(out=True, err=True, Capture=SysCapture) | ||||||
|         elif method == "no": |         elif method == "no": | ||||||
|             return MultiCapture(out=False, err=False, in_=False) |             return MultiCapture(out=False, err=False, in_=False) | ||||||
|         else: |         raise ValueError("unknown capturing method: %r" % method)  # pragma: no cover | ||||||
|             raise ValueError("unknown capturing method: %r" % method) |  | ||||||
| 
 | 
 | ||||||
|     # Global capturing control |     # Global capturing control | ||||||
| 
 | 
 | ||||||
|  | @ -161,8 +167,8 @@ class CaptureManager(object): | ||||||
| 
 | 
 | ||||||
|     @contextlib.contextmanager |     @contextlib.contextmanager | ||||||
|     def global_and_fixture_disabled(self): |     def global_and_fixture_disabled(self): | ||||||
|         """Context manager to temporarily disables global and current fixture capturing.""" |         """Context manager to temporarily disable global and current fixture capturing.""" | ||||||
|         # Need to undo local capsys-et-al if exists before disabling global capture |         # Need to undo local capsys-et-al if it exists before disabling global capture. | ||||||
|         self.suspend_fixture(self._current_item) |         self.suspend_fixture(self._current_item) | ||||||
|         self.suspend_global_capture(in_=False) |         self.suspend_global_capture(in_=False) | ||||||
|         try: |         try: | ||||||
|  | @ -247,10 +253,11 @@ def _ensure_only_one_capture_fixture(request, name): | ||||||
| 
 | 
 | ||||||
| @pytest.fixture | @pytest.fixture | ||||||
| def capsys(request): | def capsys(request): | ||||||
|     """Enable capturing of writes to ``sys.stdout`` and ``sys.stderr`` and make |     """Enable text capturing of writes to ``sys.stdout`` and ``sys.stderr``. | ||||||
|     captured output available via ``capsys.readouterr()`` method calls | 
 | ||||||
|     which return a ``(out, err)`` namedtuple.  ``out`` and ``err`` will be ``text`` |     The captured output is made available via ``capsys.readouterr()`` method | ||||||
|     objects. |     calls, which return a ``(out, err)`` namedtuple. | ||||||
|  |     ``out`` and ``err`` will be ``text`` objects. | ||||||
|     """ |     """ | ||||||
|     _ensure_only_one_capture_fixture(request, "capsys") |     _ensure_only_one_capture_fixture(request, "capsys") | ||||||
|     with _install_capture_fixture_on_item(request, SysCapture) as fixture: |     with _install_capture_fixture_on_item(request, SysCapture) as fixture: | ||||||
|  | @ -259,26 +266,28 @@ def capsys(request): | ||||||
| 
 | 
 | ||||||
| @pytest.fixture | @pytest.fixture | ||||||
| def capsysbinary(request): | def capsysbinary(request): | ||||||
|     """Enable capturing of writes to ``sys.stdout`` and ``sys.stderr`` and make |     """Enable bytes capturing of writes to ``sys.stdout`` and ``sys.stderr``. | ||||||
|     captured output available via ``capsys.readouterr()`` method calls | 
 | ||||||
|     which return a ``(out, err)`` tuple.  ``out`` and ``err`` will be ``bytes`` |     The captured output is made available via ``capsysbinary.readouterr()`` | ||||||
|     objects. |     method calls, which return a ``(out, err)`` namedtuple. | ||||||
|  |     ``out`` and ``err`` will be ``bytes`` objects. | ||||||
|     """ |     """ | ||||||
|     _ensure_only_one_capture_fixture(request, "capsysbinary") |     _ensure_only_one_capture_fixture(request, "capsysbinary") | ||||||
|     # Currently, the implementation uses the python3 specific `.buffer` |     # Currently, the implementation uses the python3 specific `.buffer` | ||||||
|     # property of CaptureIO. |     # property of CaptureIO. | ||||||
|     if sys.version_info < (3,): |     if sys.version_info < (3,): | ||||||
|         raise request.raiseerror("capsysbinary is only supported on python 3") |         raise request.raiseerror("capsysbinary is only supported on Python 3") | ||||||
|     with _install_capture_fixture_on_item(request, SysCaptureBinary) as fixture: |     with _install_capture_fixture_on_item(request, SysCaptureBinary) as fixture: | ||||||
|         yield fixture |         yield fixture | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @pytest.fixture | @pytest.fixture | ||||||
| def capfd(request): | def capfd(request): | ||||||
|     """Enable capturing of writes to file descriptors ``1`` and ``2`` and make |     """Enable text capturing of writes to file descriptors ``1`` and ``2``. | ||||||
|     captured output available via ``capfd.readouterr()`` method calls | 
 | ||||||
|     which return a ``(out, err)`` tuple.  ``out`` and ``err`` will be ``text`` |     The captured output is made available via ``capfd.readouterr()`` method | ||||||
|     objects. |     calls, which return a ``(out, err)`` namedtuple. | ||||||
|  |     ``out`` and ``err`` will be ``text`` objects. | ||||||
|     """ |     """ | ||||||
|     _ensure_only_one_capture_fixture(request, "capfd") |     _ensure_only_one_capture_fixture(request, "capfd") | ||||||
|     if not hasattr(os, "dup"): |     if not hasattr(os, "dup"): | ||||||
|  | @ -291,10 +300,11 @@ def capfd(request): | ||||||
| 
 | 
 | ||||||
| @pytest.fixture | @pytest.fixture | ||||||
| def capfdbinary(request): | def capfdbinary(request): | ||||||
|     """Enable capturing of write to file descriptors 1 and 2 and make |     """Enable bytes capturing of writes to file descriptors ``1`` and ``2``. | ||||||
|     captured output available via ``capfdbinary.readouterr`` method calls | 
 | ||||||
|     which return a ``(out, err)`` tuple.  ``out`` and ``err`` will be |     The captured output is made available via ``capfd.readouterr()`` method | ||||||
|     ``bytes`` objects. |     calls, which return a ``(out, err)`` namedtuple. | ||||||
|  |     ``out`` and ``err`` will be ``byte`` objects. | ||||||
|     """ |     """ | ||||||
|     _ensure_only_one_capture_fixture(request, "capfdbinary") |     _ensure_only_one_capture_fixture(request, "capfdbinary") | ||||||
|     if not hasattr(os, "dup"): |     if not hasattr(os, "dup"): | ||||||
|  | @ -316,9 +326,9 @@ def _install_capture_fixture_on_item(request, capture_class): | ||||||
|     """ |     """ | ||||||
|     request.node._capture_fixture = fixture = CaptureFixture(capture_class, request) |     request.node._capture_fixture = fixture = CaptureFixture(capture_class, request) | ||||||
|     capmanager = request.config.pluginmanager.getplugin("capturemanager") |     capmanager = request.config.pluginmanager.getplugin("capturemanager") | ||||||
|     # need to active this fixture right away in case it is being used by another fixture (setup phase) |     # Need to active this fixture right away in case it is being used by another fixture (setup phase). | ||||||
|     # if this fixture is being used only by a test function (call phase), then we wouldn't need this |     # If this fixture is being used only by a test function (call phase), then we wouldn't need this | ||||||
|     # activation, but it doesn't hurt |     # activation, but it doesn't hurt. | ||||||
|     capmanager.activate_fixture(request.node) |     capmanager.activate_fixture(request.node) | ||||||
|     yield fixture |     yield fixture | ||||||
|     fixture.close() |     fixture.close() | ||||||
|  | @ -446,6 +456,9 @@ class MultiCapture(object): | ||||||
|         if err: |         if err: | ||||||
|             self.err = Capture(2) |             self.err = Capture(2) | ||||||
| 
 | 
 | ||||||
|  |     def __repr__(self): | ||||||
|  |         return "<MultiCapture out=%r err=%r in_=%r>" % (self.out, self.err, self.in_) | ||||||
|  | 
 | ||||||
|     def start_capturing(self): |     def start_capturing(self): | ||||||
|         if self.in_: |         if self.in_: | ||||||
|             self.in_.start() |             self.in_.start() | ||||||
|  | @ -593,7 +606,7 @@ class FDCapture(FDCaptureBinary): | ||||||
|     EMPTY_BUFFER = str() |     EMPTY_BUFFER = str() | ||||||
| 
 | 
 | ||||||
|     def snap(self): |     def snap(self): | ||||||
|         res = FDCaptureBinary.snap(self) |         res = super(FDCapture, self).snap() | ||||||
|         enc = getattr(self.tmpfile, "encoding", None) |         enc = getattr(self.tmpfile, "encoding", None) | ||||||
|         if enc and isinstance(res, bytes): |         if enc and isinstance(res, bytes): | ||||||
|             res = six.text_type(res, enc, "replace") |             res = six.text_type(res, enc, "replace") | ||||||
|  | @ -696,11 +709,9 @@ def _colorama_workaround(): | ||||||
|     first import of colorama while I/O capture is active, colorama will |     first import of colorama while I/O capture is active, colorama will | ||||||
|     fail in various ways. |     fail in various ways. | ||||||
|     """ |     """ | ||||||
| 
 |     if sys.platform.startswith("win32"): | ||||||
|     if not sys.platform.startswith("win32"): |  | ||||||
|         return |  | ||||||
|         try: |         try: | ||||||
|         import colorama  # noqa |             import colorama  # noqa: F401 | ||||||
|         except ImportError: |         except ImportError: | ||||||
|             pass |             pass | ||||||
| 
 | 
 | ||||||
|  | @ -723,11 +734,9 @@ def _readline_workaround(): | ||||||
| 
 | 
 | ||||||
|     See https://github.com/pytest-dev/pytest/pull/1281 |     See https://github.com/pytest-dev/pytest/pull/1281 | ||||||
|     """ |     """ | ||||||
| 
 |     if sys.platform.startswith("win32"): | ||||||
|     if not sys.platform.startswith("win32"): |  | ||||||
|         return |  | ||||||
|         try: |         try: | ||||||
|         import readline  # noqa |             import readline  # noqa: F401 | ||||||
|         except ImportError: |         except ImportError: | ||||||
|             pass |             pass | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -566,7 +566,7 @@ class TestCaptureFixture(object): | ||||||
|         result.stdout.fnmatch_lines( |         result.stdout.fnmatch_lines( | ||||||
|             [ |             [ | ||||||
|                 "*test_hello*", |                 "*test_hello*", | ||||||
|                 "*capsysbinary is only supported on python 3*", |                 "*capsysbinary is only supported on Python 3*", | ||||||
|                 "*1 error in*", |                 "*1 error in*", | ||||||
|             ] |             ] | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue