diff options
-rw-r--r-- | README.md | 2 | ||||
-rw-r--r-- | docker/api/client.py | 49 | ||||
-rw-r--r-- | docker/models/images.py | 8 | ||||
-rw-r--r-- | docker/models/resource.py | 3 | ||||
-rw-r--r-- | docs/index.rst | 2 | ||||
-rw-r--r-- | setup.py | 10 | ||||
-rw-r--r-- | tests/unit/models_images_test.py | 5 | ||||
-rw-r--r-- | tests/unit/models_resources_test.py | 14 |
8 files changed, 61 insertions, 32 deletions
@@ -6,7 +6,7 @@ A Python library for the Docker Engine API. It lets you do anything the `docker` ## Installation -The latest stable version [is available on PyPi](https://pypi.python.org/pypi/docker/). Either add `docker` to your `requirements.txt` file or install with pip: +The latest stable version [is available on PyPI](https://pypi.python.org/pypi/docker/). Either add `docker` to your `requirements.txt` file or install with pip: pip install docker diff --git a/docker/api/client.py b/docker/api/client.py index a9fe7d0..22c32b4 100644 --- a/docker/api/client.py +++ b/docker/api/client.py @@ -18,16 +18,20 @@ from .service import ServiceApiMixin from .swarm import SwarmApiMixin from .volume import VolumeApiMixin from .. import auth -from ..constants import (DEFAULT_TIMEOUT_SECONDS, DEFAULT_USER_AGENT, - IS_WINDOWS_PLATFORM, DEFAULT_DOCKER_API_VERSION, - STREAM_HEADER_SIZE_BYTES, DEFAULT_NUM_POOLS, - MINIMUM_DOCKER_API_VERSION) -from ..errors import (DockerException, TLSParameterError, - create_api_error_from_http_exception) +from ..constants import ( + DEFAULT_TIMEOUT_SECONDS, DEFAULT_USER_AGENT, IS_WINDOWS_PLATFORM, + DEFAULT_DOCKER_API_VERSION, STREAM_HEADER_SIZE_BYTES, DEFAULT_NUM_POOLS, + MINIMUM_DOCKER_API_VERSION +) +from ..errors import ( + DockerException, TLSParameterError, + create_api_error_from_http_exception +) from ..tls import TLSConfig from ..transport import SSLAdapter, UnixAdapter from ..utils import utils, check_resource, update_headers from ..utils.socket import frames_iter +from ..utils.json_stream import json_stream try: from ..transport import NpipeAdapter except ImportError: @@ -274,27 +278,20 @@ class APIClient( def _stream_helper(self, response, decode=False): """Generator for data coming from a chunked-encoded HTTP response.""" + if response.raw._fp.chunked: - reader = response.raw - while not reader.closed: - # this read call will block until we get a chunk - data = reader.read(1) - if not data: - break - if reader._fp.chunk_left: - data += reader.read(reader._fp.chunk_left) - if decode: - if six.PY3: - data = data.decode('utf-8') - # remove the trailing newline - data = data.strip() - # split the data at any newlines - data_list = data.split("\r\n") - # load and yield each line seperately - for data in data_list: - data = json.loads(data) - yield data - else: + if decode: + for chunk in json_stream(self._stream_helper(response, False)): + yield chunk + else: + reader = response.raw + while not reader.closed: + # this read call will block until we get a chunk + data = reader.read(1) + if not data: + break + if reader._fp.chunk_left: + data += reader.read(reader._fp.chunk_left) yield data else: # Response isn't chunked, meaning we probably diff --git a/docker/models/images.py b/docker/models/images.py index 32068e6..6f8f4fe 100644 --- a/docker/models/images.py +++ b/docker/models/images.py @@ -30,10 +30,10 @@ class Image(Model): """ The image's tags. """ - return [ - tag for tag in self.attrs.get('RepoTags', []) - if tag != '<none>:<none>' - ] + tags = self.attrs.get('RepoTags') + if tags is None: + tags = [] + return [tag for tag in tags if tag != '<none>:<none>'] def history(self): """ diff --git a/docker/models/resource.py b/docker/models/resource.py index 95712ae..ed3900a 100644 --- a/docker/models/resource.py +++ b/docker/models/resource.py @@ -23,6 +23,9 @@ class Model(object): def __eq__(self, other): return isinstance(other, self.__class__) and self.id == other.id + def __hash__(self): + return hash("%s:%s" % (self.__class__.__name__, self.id)) + @property def id(self): """ diff --git a/docs/index.rst b/docs/index.rst index 9f484cd..8a86cc6 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -8,7 +8,7 @@ For more information about the Remote API, `see its documentation <https://docs. Installation ------------ -The latest stable version `is available on PyPi <https://pypi.python.org/pypi/docker/>`_. Either add ``docker`` to your ``requirements.txt`` file or install with pip:: +The latest stable version `is available on PyPI <https://pypi.python.org/pypi/docker/>`_. Either add ``docker`` to your ``requirements.txt`` file or install with pip:: pip install docker @@ -1,10 +1,20 @@ #!/usr/bin/env python +from __future__ import print_function + import codecs import os import sys +import pip + from setuptools import setup, find_packages +if 'docker-py' in [x.project_name for x in pip.get_installed_distributions()]: + print( + 'ERROR: "docker-py" needs to be uninstalled before installing this' + ' package:\npip uninstall docker-py', file=sys.stderr + ) + sys.exit(1) ROOT_DIR = os.path.dirname(__file__) SOURCE_DIR = os.path.join(ROOT_DIR) diff --git a/tests/unit/models_images_test.py b/tests/unit/models_images_test.py index 392c58d..efb2116 100644 --- a/tests/unit/models_images_test.py +++ b/tests/unit/models_images_test.py @@ -83,6 +83,11 @@ class ImageTest(unittest.TestCase): }) assert image.tags == [] + image = Image(attrs={ + 'RepoTags': None + }) + assert image.tags == [] + def test_history(self): client = make_fake_client() image = client.images.get(FAKE_IMAGE_ID) diff --git a/tests/unit/models_resources_test.py b/tests/unit/models_resources_test.py index 25c6a3e..5af24ee 100644 --- a/tests/unit/models_resources_test.py +++ b/tests/unit/models_resources_test.py @@ -12,3 +12,17 @@ class ModelTest(unittest.TestCase): container.reload() assert client.api.inspect_container.call_count == 2 assert container.attrs['Name'] == "foobar" + + def test_hash(self): + client = make_fake_client() + container1 = client.containers.get(FAKE_CONTAINER_ID) + my_set = set([container1]) + assert len(my_set) == 1 + + container2 = client.containers.get(FAKE_CONTAINER_ID) + my_set.add(container2) + assert len(my_set) == 1 + + image1 = client.images.get(FAKE_CONTAINER_ID) + my_set.add(image1) + assert len(my_set) == 2 |