Handle non-ascii characters in npipe error handler

Signed-off-by: Joffrey F <joffrey@docker.com>
This commit is contained in:
Joffrey F 2017-12-08 14:16:14 -08:00
parent f79f06ca4a
commit 45d2eb4003
3 changed files with 28 additions and 5 deletions

View File

@ -7,7 +7,6 @@ import socket
from distutils.spawn import find_executable from distutils.spawn import find_executable
from textwrap import dedent from textwrap import dedent
import six
from docker.errors import APIError from docker.errors import APIError
from requests.exceptions import ConnectionError as RequestsConnectionError from requests.exceptions import ConnectionError as RequestsConnectionError
from requests.exceptions import ReadTimeout from requests.exceptions import ReadTimeout
@ -15,6 +14,7 @@ from requests.exceptions import SSLError
from requests.packages.urllib3.exceptions import ReadTimeoutError from requests.packages.urllib3.exceptions import ReadTimeoutError
from ..const import API_VERSION_TO_ENGINE_VERSION from ..const import API_VERSION_TO_ENGINE_VERSION
from .utils import binarystr_to_unicode
from .utils import is_docker_for_mac_installed from .utils import is_docker_for_mac_installed
from .utils import is_mac from .utils import is_mac
from .utils import is_ubuntu from .utils import is_ubuntu
@ -75,7 +75,9 @@ def log_windows_pipe_error(exc):
) )
else: else:
log.error( log.error(
"Windows named pipe error: {} (code: {})".format(exc.strerror, exc.winerror) "Windows named pipe error: {} (code: {})".format(
binarystr_to_unicode(exc.strerror), exc.winerror
)
) )
@ -89,9 +91,7 @@ def log_timeout_error(timeout):
def log_api_error(e, client_version): def log_api_error(e, client_version):
explanation = e.explanation explanation = binarystr_to_unicode(e.explanation)
if isinstance(explanation, six.binary_type):
explanation = explanation.decode('utf-8')
if 'client is newer than server' not in explanation: if 'client is newer than server' not in explanation:
log.error(explanation) log.error(explanation)

View File

@ -10,6 +10,7 @@ import subprocess
import sys import sys
import docker import docker
import six
import compose import compose
from ..const import IS_WINDOWS_PLATFORM from ..const import IS_WINDOWS_PLATFORM
@ -148,3 +149,15 @@ def human_readable_file_size(size):
size / float(1 << (order * 10)), size / float(1 << (order * 10)),
suffixes[order] suffixes[order]
) )
def binarystr_to_unicode(s):
if not isinstance(s, six.binary_type):
return s
if IS_WINDOWS_PLATFORM:
try:
return s.decode('windows-1250')
except UnicodeDecodeError:
pass
return s.decode('utf-8', 'replace')

View File

@ -86,3 +86,13 @@ class TestHandleConnectionErrors(object):
_, args, _ = mock_logging.error.mock_calls[0] _, args, _ = mock_logging.error.mock_calls[0]
assert "Windows named pipe error: The pipe is busy. (code: 231)" == args[0] assert "Windows named pipe error: The pipe is busy. (code: 231)" == args[0]
@pytest.mark.skipif(not IS_WINDOWS_PLATFORM, reason='Needs pywin32')
def test_windows_pipe_error_encoding_issue(self, mock_logging):
import pywintypes
with pytest.raises(errors.ConnectionError):
with handle_connection_errors(mock.Mock(api_version='1.22')):
raise pywintypes.error(9999, 'WriteFile', 'I use weird characters \xe9')
_, args, _ = mock_logging.error.mock_calls[0]
assert 'Windows named pipe error: I use weird characters \xe9 (code: 9999)' == args[0]