From 4bfe35d1eac0a3a463da1bab51f04667ef26bbc3 Mon Sep 17 00:00:00 2001 From: Dmitry Bazhal Date: Thu, 20 Jun 2019 21:33:48 +0300 Subject: [PATCH] Fix ```UnicodeDecodeError: 'utf-8' codec can't decode byte 0xd0 in position 2047: unexpected end of data``` on kubernetes/watch/watch.py:49 --- watch/watch.py | 18 +++++++++++++----- watch/watch_test.py | 18 ++++++++++++++++++ 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/watch/watch.py b/watch/watch.py index 5966eace..67c1ce80 100644 --- a/watch/watch.py +++ b/watch/watch.py @@ -16,6 +16,7 @@ import json import pydoc +import six from kubernetes import client @@ -45,19 +46,26 @@ def _find_return_type(func): def iter_resp_lines(resp): prev = "" + newline_symbol = "\n" + if six.PY3: + prev = b"" + newline_symbol = b"\n" for seg in resp.read_chunked(decode_content=False): - if isinstance(seg, bytes): - seg = seg.decode('utf8') seg = prev + seg - lines = seg.split("\n") - if not seg.endswith("\n"): + lines = seg.split(newline_symbol) + if not seg.endswith(newline_symbol): prev = lines[-1] lines = lines[:-1] else: prev = "" + if six.PY3: + prev = b"" for line in lines: if line: - yield line + if isinstance(line, bytes): + yield line.decode('utf8', 'replace') + else: + yield line class Watch(object): diff --git a/watch/watch_test.py b/watch/watch_test.py index ebc400af..56278d2d 100644 --- a/watch/watch_test.py +++ b/watch/watch_test.py @@ -14,6 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +import six import unittest from mock import Mock, call @@ -40,6 +41,17 @@ def test_watch_with_decode(self): '{"type": "ADDED", "object": {"metadata": {"name": "test3",' '"resourceVersion": "3"}, "spec": {}, "status": {}}}\n', 'should_not_happened\n']) + if six.PY3: + fake_resp.read_chunked = Mock( + return_value=[ + b'{"type": "ADDED", "object": {"metadata": {"name": "test1",' + b'"resourceVersion": "1"}, "spec": {}, "status": {}}}\n', + b'{"type": "ADDED", "object": {"metadata": {"name": "test2",' + b'"resourceVersion": "2"}, "spec": {}, "sta', + b'tus": {}}}\n' + b'{"type": "ADDED", "object": {"metadata": {"name": "test3",' + b'"resourceVersion": "3"}, "spec": {}, "status": {}}}\n', + b'should_not_happened\n']) fake_api = Mock() fake_api.get_namespaces = Mock(return_value=fake_resp) @@ -172,6 +184,9 @@ def test_watch_stream_twice(self): fake_resp.release_conn = Mock() fake_resp.read_chunked = Mock( return_value=['{"type": "ADDED", "object": 1}\n'] * 4) + if six.PY3: + fake_resp.read_chunked = Mock( + return_value=[b'{"type": "ADDED", "object": 1}\n'] * 4) fake_api = Mock() fake_api.get_namespaces = Mock(return_value=fake_resp) @@ -199,6 +214,9 @@ def test_watch_stream_loop(self): fake_resp.release_conn = Mock() fake_resp.read_chunked = Mock( return_value=['{"type": "ADDED", "object": 1}\n']) + if six.PY3: + fake_resp.read_chunked = Mock( + return_value=[b'{"type": "ADDED", "object": 1}\n']) fake_api = Mock() fake_api.get_namespaces = Mock(return_value=fake_resp)