diff --git a/CHANGELOG.md b/CHANGELOG.md index a8e0b8df5..3709e263d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ Change log ========== -1.21.0 (2018-04-11) +1.21.0 (2018-04-10) ------------------- ### New features diff --git a/compose/__init__.py b/compose/__init__.py index d7ed9198c..693a1ab18 100644 --- a/compose/__init__.py +++ b/compose/__init__.py @@ -1,4 +1,4 @@ from __future__ import absolute_import from __future__ import unicode_literals -__version__ = '1.21.0-rc1' +__version__ = '1.21.0' diff --git a/compose/parallel.py b/compose/parallel.py index 5d4791f97..a2eb160e5 100644 --- a/compose/parallel.py +++ b/compose/parallel.py @@ -279,9 +279,7 @@ class ParallelStreamWriter(object): def write_initial(self, msg, obj_index): if msg is None: return - self.stream.write("{:<{width}} ... \r\n".format( - msg + ' ' + obj_index, width=self.width)) - self.stream.flush() + return self._write_noansi(msg, obj_index, '') def _write_ansi(self, msg, obj_index, status): self.lock.acquire() @@ -299,8 +297,11 @@ class ParallelStreamWriter(object): self.lock.release() def _write_noansi(self, msg, obj_index, status): - self.stream.write("{:<{width}} ... {}\r\n".format(msg + ' ' + obj_index, - status, width=self.width)) + self.stream.write( + "{:<{width}} ... {}\r\n".format( + msg + ' ' + obj_index, status, width=self.width + ) + ) self.stream.flush() def write(self, msg, obj_index, status, color_func): diff --git a/compose/project.py b/compose/project.py index afbec183f..924390b4e 100644 --- a/compose/project.py +++ b/compose/project.py @@ -556,7 +556,11 @@ class Project(object): limit=5, ) if len(errors): - raise ProjectError(b"\n".join(errors.values())) + combined_errors = '\n'.join([ + e.decode('utf-8') if isinstance(e, six.binary_type) else e for e in errors.values() + ]) + raise ProjectError(combined_errors) + else: for service in services: service.pull(ignore_pull_failures, silent=silent) diff --git a/script/run/run.sh b/script/run/run.sh index fb4cb8b4b..1e4bd9853 100755 --- a/script/run/run.sh +++ b/script/run/run.sh @@ -15,7 +15,7 @@ set -e -VERSION="1.21.0-rc1" +VERSION="1.21.0" IMAGE="docker/compose:$VERSION" diff --git a/tests/unit/project_test.py b/tests/unit/project_test.py index eb6209723..83a014758 100644 --- a/tests/unit/project_test.py +++ b/tests/unit/project_test.py @@ -5,6 +5,7 @@ from __future__ import unicode_literals import datetime import docker +import pytest from docker.errors import NotFound from .. import mock @@ -16,8 +17,10 @@ from compose.const import COMPOSEFILE_V2_0 as V2_0 from compose.const import COMPOSEFILE_V2_4 as V2_4 from compose.const import LABEL_SERVICE from compose.container import Container +from compose.errors import OperationFailedError from compose.project import NoSuchService from compose.project import Project +from compose.project import ProjectError from compose.service import ImageType from compose.service import Service @@ -588,3 +591,29 @@ class ProjectTest(unittest.TestCase): name='test', client=self.mock_client, config_data=config_data, default_platform='windows' ) assert project.get_service('web').options.get('platform') == 'linux/s390x' + + @mock.patch('compose.parallel.ParallelStreamWriter._write_noansi') + def test_error_parallel_pull(self, mock_write): + project = Project.from_config( + name='test', + client=self.mock_client, + config_data=Config( + version=V2_0, + services=[{ + 'name': 'web', + 'image': 'busybox:latest', + }], + networks=None, + volumes=None, + secrets=None, + configs=None, + ), + ) + + self.mock_client.pull.side_effect = OperationFailedError('pull error') + with pytest.raises(ProjectError): + project.pull(parallel_pull=True) + + self.mock_client.pull.side_effect = OperationFailedError(b'pull error') + with pytest.raises(ProjectError): + project.pull(parallel_pull=True)