Pārlūkot izejas kodu

Handle non-ascii characters in npipe error handler

Signed-off-by: Joffrey F <[email protected]>
Joffrey F 7 gadi atpakaļ
vecāks
revīzija
45d2eb4003
3 mainītis faili ar 28 papildinājumiem un 5 dzēšanām
  1. 5 5
      compose/cli/errors.py
  2. 13 0
      compose/cli/utils.py
  3. 10 0
      tests/unit/cli/errors_test.py

+ 5 - 5
compose/cli/errors.py

@@ -7,7 +7,6 @@ import socket
 from distutils.spawn import find_executable
 from textwrap import dedent
 
-import six
 from docker.errors import APIError
 from requests.exceptions import ConnectionError as RequestsConnectionError
 from requests.exceptions import ReadTimeout
@@ -15,6 +14,7 @@ from requests.exceptions import SSLError
 from requests.packages.urllib3.exceptions import ReadTimeoutError
 
 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_mac
 from .utils import is_ubuntu
@@ -75,7 +75,9 @@ def log_windows_pipe_error(exc):
         )
     else:
         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):
-    explanation = e.explanation
-    if isinstance(explanation, six.binary_type):
-        explanation = explanation.decode('utf-8')
+    explanation = binarystr_to_unicode(e.explanation)
 
     if 'client is newer than server' not in explanation:
         log.error(explanation)

+ 13 - 0
compose/cli/utils.py

@@ -10,6 +10,7 @@ import subprocess
 import sys
 
 import docker
+import six
 
 import compose
 from ..const import IS_WINDOWS_PLATFORM
@@ -148,3 +149,15 @@ def human_readable_file_size(size):
         size / float(1 << (order * 10)),
         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')

+ 10 - 0
tests/unit/cli/errors_test.py

@@ -86,3 +86,13 @@ class TestHandleConnectionErrors(object):
 
         _, args, _ = mock_logging.error.mock_calls[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]