Skip to content

Commit

Permalink
Merge pull request #2667 from nicoddemus/py36-windows-workaround-error
Browse files Browse the repository at this point in the history
Fix windows console workaround error with non-standard io-streams
  • Loading branch information
RonnyPfannschmidt committed Aug 8, 2017
2 parents 76c55b3 + cc0f247 commit 523bfa6
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 4 deletions.
15 changes: 11 additions & 4 deletions _pytest/capture.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def pytest_addoption(parser):
def pytest_load_initial_conftests(early_config, parser, args):
ns = early_config.known_args_namespace
if ns.capture == "fd":
_py36_windowsconsoleio_workaround()
_py36_windowsconsoleio_workaround(sys.stdout)
_colorama_workaround()
_readline_workaround()
pluginmanager = early_config.pluginmanager
Expand Down Expand Up @@ -524,7 +524,7 @@ def _readline_workaround():
pass


def _py36_windowsconsoleio_workaround():
def _py36_windowsconsoleio_workaround(stream):
"""
Python 3.6 implemented unicode console handling for Windows. This works
by reading/writing to the raw console handle using
Expand All @@ -541,13 +541,20 @@ def _py36_windowsconsoleio_workaround():
also means a different handle by replicating the logic in
"Py_lifecycle.c:initstdio/create_stdio".
:param stream: in practice ``sys.stdout`` or ``sys.stderr``, but given
here as parameter for unittesting purposes.
See https://github.com/pytest-dev/py/issues/103
"""
if not sys.platform.startswith('win32') or sys.version_info[:2] < (3, 6):
return

buffered = hasattr(sys.stdout.buffer, 'raw')
raw_stdout = sys.stdout.buffer.raw if buffered else sys.stdout.buffer
# bail out if ``stream`` doesn't seem like a proper ``io`` stream (#2666)
if not hasattr(stream, 'buffer'):
return

buffered = hasattr(stream.buffer, 'raw')
raw_stdout = stream.buffer.raw if buffered else stream.buffer

if not isinstance(raw_stdout, io._WindowsConsoleIO):
return
Expand Down
3 changes: 3 additions & 0 deletions changelog/2666.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Fix error on Windows and Python 3.6+ when ``sys.stdout`` has been replaced with
a stream-like object which does not implement the full ``io`` module buffer protocol. In particular this
affects ``pytest-xdist`` users on the aforementioned platform.
17 changes: 17 additions & 0 deletions testing/test_capture.py
Original file line number Diff line number Diff line change
Expand Up @@ -1140,6 +1140,23 @@ def test_capattr():
reprec.assertoutcome(passed=1)


@pytest.mark.skipif(not sys.platform.startswith('win') and sys.version_info[:2] >= (3, 6),
reason='only py3.6+ on windows')
def test_py36_windowsconsoleio_workaround_non_standard_streams():
"""
Ensure _py36_windowsconsoleio_workaround function works with objects that
do not implement the full ``io``-based stream protocol, for example execnet channels (#2666).
"""
from _pytest.capture import _py36_windowsconsoleio_workaround

class DummyStream:
def write(self, s):
pass

stream = DummyStream()
_py36_windowsconsoleio_workaround(stream)


def test_dontreadfrominput_has_encoding(testdir):
testdir.makepyfile("""
import sys
Expand Down

0 comments on commit 523bfa6

Please sign in to comment.