From c78c32c2e819cdbf83f9e9ed2dc16ff9e62b78dc Mon Sep 17 00:00:00 2001 From: Daniel Nephin Date: Mon, 16 Nov 2015 12:35:26 -0500 Subject: [PATCH] Fixes #2398 - the build progress stream can contain empty json objects. Previously these empty objects would hit a bug in splitting objects causing it crash. With this fix the empty objects are returned properly. Signed-off-by: Daniel Nephin --- compose/utils.py | 12 ++++++------ tests/unit/utils_test.py | 28 ++++++++++++++++++++-------- 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/compose/utils.py b/compose/utils.py index 2c6c4584d..a013035e9 100644 --- a/compose/utils.py +++ b/compose/utils.py @@ -102,7 +102,7 @@ def stream_as_text(stream): def line_splitter(buffer, separator=u'\n'): index = buffer.find(six.text_type(separator)) if index == -1: - return None, None + return None return buffer[:index + 1], buffer[index + 1:] @@ -120,11 +120,11 @@ def split_buffer(stream, splitter=None, decoder=lambda a: a): for data in stream_as_text(stream): buffered += data while True: - item, rest = splitter(buffered) - if not item: + buffer_split = splitter(buffered) + if buffer_split is None: break - buffered = rest + item, buffered = buffer_split yield item if buffered: @@ -140,7 +140,7 @@ def json_splitter(buffer): rest = buffer[json.decoder.WHITESPACE.match(buffer, index).end():] return obj, rest except ValueError: - return None, None + return None def json_stream(stream): @@ -148,7 +148,7 @@ def json_stream(stream): This handles streams which are inconsistently buffered (some entries may be newline delimited, and others are not). """ - return split_buffer(stream_as_text(stream), json_splitter, json_decoder.decode) + return split_buffer(stream, json_splitter, json_decoder.decode) def write_out_msg(stream, lines, msg_index, msg, status="done"): diff --git a/tests/unit/utils_test.py b/tests/unit/utils_test.py index e3d0bc00b..15999dde9 100644 --- a/tests/unit/utils_test.py +++ b/tests/unit/utils_test.py @@ -1,25 +1,21 @@ # encoding: utf-8 from __future__ import unicode_literals -from .. import unittest from compose import utils -class JsonSplitterTestCase(unittest.TestCase): +class TestJsonSplitter(object): def test_json_splitter_no_object(self): data = '{"foo": "bar' - self.assertEqual(utils.json_splitter(data), (None, None)) + assert utils.json_splitter(data) is None def test_json_splitter_with_object(self): data = '{"foo": "bar"}\n \n{"next": "obj"}' - self.assertEqual( - utils.json_splitter(data), - ({'foo': 'bar'}, '{"next": "obj"}') - ) + assert utils.json_splitter(data) == ({'foo': 'bar'}, '{"next": "obj"}') -class StreamAsTextTestCase(unittest.TestCase): +class TestStreamAsText(object): def test_stream_with_non_utf_unicode_character(self): stream = [b'\xed\xf3\xf3'] @@ -30,3 +26,19 @@ class StreamAsTextTestCase(unittest.TestCase): stream = ['ěĝ'.encode('utf-8')] output, = utils.stream_as_text(stream) assert output == 'ěĝ' + + +class TestJsonStream(object): + + def test_with_falsy_entries(self): + stream = [ + '{"one": "two"}\n{}\n', + "[1, 2, 3]\n[]\n", + ] + output = list(utils.json_stream(stream)) + assert output == [ + {'one': 'two'}, + {}, + [1, 2, 3], + [], + ]