mirror of
https://github.com/docker/compose.git
synced 2025-07-21 04:34:38 +02:00
Merge pull request #3789 from shin-/3788-json-splitter-fix
json_splitter: Don't break when buffer contains leading whitespace.
This commit is contained in:
commit
d29f8e1022
@ -23,6 +23,7 @@ from ..config.environment import Environment
|
|||||||
from ..config.serialize import serialize_config
|
from ..config.serialize import serialize_config
|
||||||
from ..const import DEFAULT_TIMEOUT
|
from ..const import DEFAULT_TIMEOUT
|
||||||
from ..const import IS_WINDOWS_PLATFORM
|
from ..const import IS_WINDOWS_PLATFORM
|
||||||
|
from ..errors import StreamParseError
|
||||||
from ..progress_stream import StreamOutputError
|
from ..progress_stream import StreamOutputError
|
||||||
from ..project import NoSuchService
|
from ..project import NoSuchService
|
||||||
from ..project import OneOffFilter
|
from ..project import OneOffFilter
|
||||||
@ -75,7 +76,7 @@ def main():
|
|||||||
except NeedsBuildError as e:
|
except NeedsBuildError as e:
|
||||||
log.error("Service '%s' needs to be built, but --no-build was passed." % e.service.name)
|
log.error("Service '%s' needs to be built, but --no-build was passed." % e.service.name)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
except errors.ConnectionError:
|
except (errors.ConnectionError, StreamParseError):
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
@ -5,3 +5,8 @@ from __future__ import unicode_literals
|
|||||||
class OperationFailedError(Exception):
|
class OperationFailedError(Exception):
|
||||||
def __init__(self, reason):
|
def __init__(self, reason):
|
||||||
self.msg = reason
|
self.msg = reason
|
||||||
|
|
||||||
|
|
||||||
|
class StreamParseError(RuntimeError):
|
||||||
|
def __init__(self, reason):
|
||||||
|
self.msg = reason
|
||||||
|
@ -5,11 +5,15 @@ import codecs
|
|||||||
import hashlib
|
import hashlib
|
||||||
import json
|
import json
|
||||||
import json.decoder
|
import json.decoder
|
||||||
|
import logging
|
||||||
|
|
||||||
import six
|
import six
|
||||||
|
|
||||||
|
from .errors import StreamParseError
|
||||||
|
|
||||||
|
|
||||||
json_decoder = json.JSONDecoder()
|
json_decoder = json.JSONDecoder()
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def get_output_stream(stream):
|
def get_output_stream(stream):
|
||||||
@ -60,13 +64,21 @@ def split_buffer(stream, splitter=None, decoder=lambda a: a):
|
|||||||
yield item
|
yield item
|
||||||
|
|
||||||
if buffered:
|
if buffered:
|
||||||
|
try:
|
||||||
yield decoder(buffered)
|
yield decoder(buffered)
|
||||||
|
except Exception as e:
|
||||||
|
log.error(
|
||||||
|
'Compose tried decoding the following data chunk, but failed:'
|
||||||
|
'\n%s' % repr(buffered)
|
||||||
|
)
|
||||||
|
raise StreamParseError(e)
|
||||||
|
|
||||||
|
|
||||||
def json_splitter(buffer):
|
def json_splitter(buffer):
|
||||||
"""Attempt to parse a json object from a buffer. If there is at least one
|
"""Attempt to parse a json object from a buffer. If there is at least one
|
||||||
object, return it and the rest of the buffer, otherwise return None.
|
object, return it and the rest of the buffer, otherwise return None.
|
||||||
"""
|
"""
|
||||||
|
buffer = buffer.strip()
|
||||||
try:
|
try:
|
||||||
obj, index = json_decoder.raw_decode(buffer)
|
obj, index = json_decoder.raw_decode(buffer)
|
||||||
rest = buffer[json.decoder.WHITESPACE.match(buffer, index).end():]
|
rest = buffer[json.decoder.WHITESPACE.match(buffer, index).end():]
|
||||||
|
@ -15,6 +15,10 @@ class TestJsonSplitter(object):
|
|||||||
data = '{"foo": "bar"}\n \n{"next": "obj"}'
|
data = '{"foo": "bar"}\n \n{"next": "obj"}'
|
||||||
assert utils.json_splitter(data) == ({'foo': 'bar'}, '{"next": "obj"}')
|
assert utils.json_splitter(data) == ({'foo': 'bar'}, '{"next": "obj"}')
|
||||||
|
|
||||||
|
def test_json_splitter_leading_whitespace(self):
|
||||||
|
data = '\n \r{"foo": "bar"}\n\n {"next": "obj"}'
|
||||||
|
assert utils.json_splitter(data) == ({'foo': 'bar'}, '{"next": "obj"}')
|
||||||
|
|
||||||
|
|
||||||
class TestStreamAsText(object):
|
class TestStreamAsText(object):
|
||||||
|
|
||||||
@ -43,3 +47,16 @@ class TestJsonStream(object):
|
|||||||
[1, 2, 3],
|
[1, 2, 3],
|
||||||
[],
|
[],
|
||||||
]
|
]
|
||||||
|
|
||||||
|
def test_with_leading_whitespace(self):
|
||||||
|
stream = [
|
||||||
|
'\n \r\n {"one": "two"}{"x": 1}',
|
||||||
|
' {"three": "four"}\t\t{"x": 2}'
|
||||||
|
]
|
||||||
|
output = list(utils.json_stream(stream))
|
||||||
|
assert output == [
|
||||||
|
{'one': 'two'},
|
||||||
|
{'x': 1},
|
||||||
|
{'three': 'four'},
|
||||||
|
{'x': 2}
|
||||||
|
]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user