Skip to content

Commit b84dfe7

Browse files
committed
fix: patch also stdout.flush() from colorama for #4170
bc on Windows it breaks with OSError(errno.EINVAL) after pip has broken. + Fix a bit the TC according to PY2 behavior.
1 parent 28beeeb commit b84dfe7

File tree

2 files changed

+28
-12
lines changed

2 files changed

+28
-12
lines changed

src/pip/_vendor/colorama/ansitowin32.py

+16-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
2+
import errno
23
import re
34
import sys
45
import os
@@ -136,12 +137,25 @@ def get_win32_calls(self):
136137
}
137138
return dict()
138139

140+
def _flush(self):
141+
"""Ignore `BrokenPipeErrors` eg. when piped in `head` UNIX cmd."""
142+
try:
143+
self.wrapped.flush()
144+
except (IOError, OSError) as ex: # Python-2 has no `BrokenPipeError`
145+
# Windows also fails with:
146+
# File "pip\_vendor\colorama\ansitowin32.py", line 143, in _flush
147+
# self.wrapped.flush()
148+
# OSError: [Errno 22] Invalid argument
149+
#
150+
if ex.errno not in (errno.EPIPE, errno.EINVAL):
151+
raise
152+
139153
def write(self, text):
140154
if self.strip or self.convert:
141155
self.write_and_convert(text)
142156
else:
143157
self.wrapped.write(text)
144-
self.wrapped.flush()
158+
self._flush()
145159
if self.autoreset:
146160
self.reset_all()
147161

@@ -172,7 +186,7 @@ def write_and_convert(self, text):
172186
def write_plain_text(self, text, start, end):
173187
if start < end:
174188
self.wrapped.write(text[start:end])
175-
self.wrapped.flush()
189+
self._flush()
176190

177191

178192
def convert_ansi(self, paramstring, command):

tests/functional/test_logging.py

+12-10
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import subprocess
77

88
import pytest
9+
from pip._vendor.six import PY2
910

1011

1112
@pytest.mark.usefixtures('script')
@@ -121,15 +122,16 @@ def test_broken_pipe_logger():
121122
# `download` cmd has a lot of log-statements.
122123
cmd = 'pip download -v pip'
123124

124-
# When the stream where logging is writting is broken,
125-
# at least these 2 lines are emitted in stderr:
125+
stderr = _run_and_brake_stdout(cmd, shell=True, check=True)
126+
# When breaks the stream that the logging is writing into,
127+
# in PY3 these 2 lines are emitted in stderr:
126128
# Exception ignored in: <_io.TextIOWrapper name='<stdout>' mode='w' ...
127129
# BrokenPipeError: [Errno 32] Broken pipe\n"
128-
exp_stder_nlines = 2
129-
exp_stderr_msg = b'Exception ignored in'
130-
131-
stderr = _run_and_brake_stdout(cmd, shell=True, check=True)
132-
# Before #5721, it command does not stop, but it continued
133-
# printing ~4 lines per each broken-pipe error!
134-
assert stderr.count(b'\n') == exp_stder_nlines, stderr
135-
assert exp_stderr_msg in stderr, stderr
130+
#
131+
# Before #5721, pip did not stop the 1st time, but it continued
132+
# printing them lines on each `stream.flush()`!
133+
if PY2:
134+
assert not stderr, stderr
135+
else:
136+
assert stderr.count(b'\n') == 2
137+
assert b'Exception ignored in' in stderr, stderr

0 commit comments

Comments
 (0)