Skip to content

Commit 523bfa6

Browse files
Merge pull request #2667 from nicoddemus/py36-windows-workaround-error
Fix windows console workaround error with non-standard io-streams
2 parents 76c55b3 + cc0f247 commit 523bfa6

File tree

3 files changed

+31
-4
lines changed

3 files changed

+31
-4
lines changed

_pytest/capture.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ def pytest_addoption(parser):
3636
def pytest_load_initial_conftests(early_config, parser, args):
3737
ns = early_config.known_args_namespace
3838
if ns.capture == "fd":
39-
_py36_windowsconsoleio_workaround()
39+
_py36_windowsconsoleio_workaround(sys.stdout)
4040
_colorama_workaround()
4141
_readline_workaround()
4242
pluginmanager = early_config.pluginmanager
@@ -524,7 +524,7 @@ def _readline_workaround():
524524
pass
525525

526526

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

549-
buffered = hasattr(sys.stdout.buffer, 'raw')
550-
raw_stdout = sys.stdout.buffer.raw if buffered else sys.stdout.buffer
552+
# bail out if ``stream`` doesn't seem like a proper ``io`` stream (#2666)
553+
if not hasattr(stream, 'buffer'):
554+
return
555+
556+
buffered = hasattr(stream.buffer, 'raw')
557+
raw_stdout = stream.buffer.raw if buffered else stream.buffer
551558

552559
if not isinstance(raw_stdout, io._WindowsConsoleIO):
553560
return

changelog/2666.bugfix

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix error on Windows and Python 3.6+ when ``sys.stdout`` has been replaced with
2+
a stream-like object which does not implement the full ``io`` module buffer protocol. In particular this
3+
affects ``pytest-xdist`` users on the aforementioned platform.

testing/test_capture.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1140,6 +1140,23 @@ def test_capattr():
11401140
reprec.assertoutcome(passed=1)
11411141

11421142

1143+
@pytest.mark.skipif(not sys.platform.startswith('win') and sys.version_info[:2] >= (3, 6),
1144+
reason='only py3.6+ on windows')
1145+
def test_py36_windowsconsoleio_workaround_non_standard_streams():
1146+
"""
1147+
Ensure _py36_windowsconsoleio_workaround function works with objects that
1148+
do not implement the full ``io``-based stream protocol, for example execnet channels (#2666).
1149+
"""
1150+
from _pytest.capture import _py36_windowsconsoleio_workaround
1151+
1152+
class DummyStream:
1153+
def write(self, s):
1154+
pass
1155+
1156+
stream = DummyStream()
1157+
_py36_windowsconsoleio_workaround(stream)
1158+
1159+
11431160
def test_dontreadfrominput_has_encoding(testdir):
11441161
testdir.makepyfile("""
11451162
import sys

0 commit comments

Comments
 (0)