Skip to content

Commit

Permalink
fix: patch also stdout.flush() from colorama for pypa#4170
Browse files Browse the repository at this point in the history
bc on Windows it breaks with OSError(errno.EINVAL) after pip has broken.
+ Fix a bit the TC according to PY2 behavior.
  • Loading branch information
ankostis committed Aug 22, 2018
1 parent 28beeeb commit b84dfe7
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 12 deletions.
18 changes: 16 additions & 2 deletions src/pip/_vendor/colorama/ansitowin32.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
import errno
import re
import sys
import os
Expand Down Expand Up @@ -136,12 +137,25 @@ def get_win32_calls(self):
}
return dict()

def _flush(self):
"""Ignore `BrokenPipeErrors` eg. when piped in `head` UNIX cmd."""
try:
self.wrapped.flush()
except (IOError, OSError) as ex: # Python-2 has no `BrokenPipeError`
# Windows also fails with:
# File "pip\_vendor\colorama\ansitowin32.py", line 143, in _flush
# self.wrapped.flush()
# OSError: [Errno 22] Invalid argument
#
if ex.errno not in (errno.EPIPE, errno.EINVAL):
raise

def write(self, text):
if self.strip or self.convert:
self.write_and_convert(text)
else:
self.wrapped.write(text)
self.wrapped.flush()
self._flush()
if self.autoreset:
self.reset_all()

Expand Down Expand Up @@ -172,7 +186,7 @@ def write_and_convert(self, text):
def write_plain_text(self, text, start, end):
if start < end:
self.wrapped.write(text[start:end])
self.wrapped.flush()
self._flush()


def convert_ansi(self, paramstring, command):
Expand Down
22 changes: 12 additions & 10 deletions tests/functional/test_logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import subprocess

import pytest
from pip._vendor.six import PY2


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

# When the stream where logging is writting is broken,
# at least these 2 lines are emitted in stderr:
stderr = _run_and_brake_stdout(cmd, shell=True, check=True)
# When breaks the stream that the logging is writing into,
# in PY3 these 2 lines are emitted in stderr:
# Exception ignored in: <_io.TextIOWrapper name='<stdout>' mode='w' ...
# BrokenPipeError: [Errno 32] Broken pipe\n"
exp_stder_nlines = 2
exp_stderr_msg = b'Exception ignored in'

stderr = _run_and_brake_stdout(cmd, shell=True, check=True)
# Before #5721, it command does not stop, but it continued
# printing ~4 lines per each broken-pipe error!
assert stderr.count(b'\n') == exp_stder_nlines, stderr
assert exp_stderr_msg in stderr, stderr
#
# Before #5721, pip did not stop the 1st time, but it continued
# printing them lines on each `stream.flush()`!
if PY2:
assert not stderr, stderr
else:
assert stderr.count(b'\n') == 2
assert b'Exception ignored in' in stderr, stderr

0 comments on commit b84dfe7

Please sign in to comment.