Merge remote-tracking branch 'upstream/main' into ruffify

This commit is contained in:
Milas Bowman 2023-08-14 15:39:25 -04:00
commit 6d2b1772aa
11 changed files with 23 additions and 27 deletions

View File

@ -1,6 +1,6 @@
# Docker SDK for Python # Docker SDK for Python
[![Build Status](https://github.com/docker/docker-py/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/docker/docker-py/actions/workflows/ci.yml/) [![Build Status](https://github.com/docker/docker-py/actions/workflows/ci.yml/badge.svg)](https://github.com/docker/docker-py/actions/workflows/ci.yml)
A Python library for the Docker Engine API. It lets you do anything the `docker` command does, but from within Python apps run containers, manage containers, manage Swarms, etc. A Python library for the Docker Engine API. It lets you do anything the `docker` command does, but from within Python apps run containers, manage containers, manage Swarms, etc.

View File

@ -112,7 +112,7 @@ class ContainerApiMixin:
@utils.check_resource('container') @utils.check_resource('container')
def commit(self, container, repository=None, tag=None, message=None, def commit(self, container, repository=None, tag=None, message=None,
author=None, changes=None, conf=None): author=None, pause=True, changes=None, conf=None):
""" """
Commit a container to an image. Similar to the ``docker commit`` Commit a container to an image. Similar to the ``docker commit``
command. command.
@ -123,6 +123,7 @@ class ContainerApiMixin:
tag (str): The tag to push tag (str): The tag to push
message (str): A commit message message (str): A commit message
author (str): The name of the author author (str): The name of the author
pause (bool): Whether to pause the container before committing
changes (str): Dockerfile instructions to apply while committing changes (str): Dockerfile instructions to apply while committing
conf (dict): The configuration for the container. See the conf (dict): The configuration for the container. See the
`Engine API documentation `Engine API documentation
@ -139,6 +140,7 @@ class ContainerApiMixin:
'tag': tag, 'tag': tag,
'comment': message, 'comment': message,
'author': author, 'author': author,
'pause': pause,
'changes': changes 'changes': changes
} }
u = self._url("/commit") u = self._url("/commit")

View File

@ -27,7 +27,7 @@ def create_api_error_from_http_exception(e):
try: try:
explanation = response.json()['message'] explanation = response.json()['message']
except ValueError: except ValueError:
explanation = (response.content or '').strip() explanation = (response.text or '').strip()
cls = APIError cls = APIError
if response.status_code == 404: if response.status_code == 404:
explanation_msg = (explanation or '').lower() explanation_msg = (explanation or '').lower()

View File

@ -121,6 +121,7 @@ class Container(Model):
tag (str): The tag to push tag (str): The tag to push
message (str): A commit message message (str): A commit message
author (str): The name of the author author (str): The name of the author
pause (bool): Whether to pause the container before committing
changes (str): Dockerfile instructions to apply while committing changes (str): Dockerfile instructions to apply while committing
conf (dict): The configuration for the container. See the conf (dict): The configuration for the container. See the
`Engine API documentation `Engine API documentation

View File

@ -16,10 +16,13 @@ Prepare the command we are going to use. It prints "hello stdout"
in `stdout`, followed by "hello stderr" in `stderr`: in `stdout`, followed by "hello stderr" in `stderr`:
>>> cmd = '/bin/sh -c "echo hello stdout ; echo hello stderr >&2"' >>> cmd = '/bin/sh -c "echo hello stdout ; echo hello stderr >&2"'
We'll run this command with all four the combinations of ``stream`` We'll run this command with all four the combinations of ``stream``
and ``demux``. and ``demux``.
With ``stream=False`` and ``demux=False``, the output is a string With ``stream=False`` and ``demux=False``, the output is a string
that contains both the `stdout` and the `stderr` output: that contains both the `stdout` and the `stderr` output:
>>> res = container.exec_run(cmd, stream=False, demux=False) >>> res = container.exec_run(cmd, stream=False, demux=False)
>>> res.output >>> res.output
b'hello stderr\nhello stdout\n' b'hello stderr\nhello stdout\n'
@ -52,15 +55,8 @@ Traceback (most recent call last):
File "<stdin>", line 1, in <module> File "<stdin>", line 1, in <module>
StopIteration StopIteration
Finally, with ``stream=False`` and ``demux=True``, the whole output Finally, with ``stream=False`` and ``demux=True``, the output is a tuple ``(stdout, stderr)``:
is returned, but the streams are still separated:
>>> res = container.exec_run(cmd, stream=True, demux=True) >>> res = container.exec_run(cmd, stream=False, demux=True)
>>> next(res.output) >>> res.output
(b'hello stdout\n', None) (b'hello stdout\n', b'hello stderr\n')
>>> next(res.output)
(None, b'hello stderr\n')
>>> next(res.output)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration

View File

@ -1,6 +1,6 @@
packaging==21.3 packaging==21.3
paramiko==2.11.0 paramiko==2.11.0
pywin32==304; sys_platform == 'win32' pywin32==304; sys_platform == 'win32'
requests==2.28.1 requests==2.31.0
urllib3==1.26.11 urllib3==1.26.11
websocket-client==1.3.3 websocket-client==1.3.3

View File

@ -4,10 +4,6 @@ ARG PYTHON_VERSION=3.10
FROM python:${PYTHON_VERSION} FROM python:${PYTHON_VERSION}
ARG APT_MIRROR
RUN sed -ri "s/(httpredir|deb).debian.org/${APT_MIRROR:-deb.debian.org}/g" /etc/apt/sources.list \
&& sed -ri "s/(security).debian.org/${APT_MIRROR:-security.debian.org}/g" /etc/apt/sources.list
RUN apt-get update && apt-get -y install --no-install-recommends \ RUN apt-get update && apt-get -y install --no-install-recommends \
gnupg2 \ gnupg2 \
pass pass

View File

@ -122,8 +122,8 @@ class CreateContainerTest(BaseAPIIntegrationTest):
self.client.wait(id) self.client.wait(id)
with pytest.raises(docker.errors.APIError) as exc: with pytest.raises(docker.errors.APIError) as exc:
self.client.remove_container(id) self.client.remove_container(id)
err = exc.value.explanation err = exc.value.explanation.lower()
assert 'You cannot remove ' in err assert 'stop the container before' in err
self.client.remove_container(id, force=True) self.client.remove_container(id, force=True)
def test_create_container_with_volumes_from(self): def test_create_container_with_volumes_from(self):
@ -1390,7 +1390,7 @@ class GetContainerStatsTest(BaseAPIIntegrationTest):
response = self.client.stats(container, stream=0) response = self.client.stats(container, stream=0)
self.client.kill(container) self.client.kill(container)
assert type(response) == dict assert isinstance(response, dict)
for key in ['read', 'networks', 'precpu_stats', 'cpu_stats', for key in ['read', 'networks', 'precpu_stats', 'cpu_stats',
'memory_stats', 'blkio_stats']: 'memory_stats', 'blkio_stats']:
assert key in response assert key in response
@ -1403,7 +1403,7 @@ class GetContainerStatsTest(BaseAPIIntegrationTest):
self.client.start(container) self.client.start(container)
stream = self.client.stats(container) stream = self.client.stats(container)
for chunk in stream: for chunk in stream:
assert type(chunk) == dict assert isinstance(chunk, dict)
for key in ['read', 'network', 'precpu_stats', 'cpu_stats', for key in ['read', 'network', 'precpu_stats', 'cpu_stats',
'memory_stats', 'blkio_stats']: 'memory_stats', 'blkio_stats']:
assert key in chunk assert key in chunk

View File

@ -32,7 +32,7 @@ class ListImagesTest(BaseAPIIntegrationTest):
def test_images_quiet(self): def test_images_quiet(self):
res1 = self.client.images(quiet=True) res1 = self.client.images(quiet=True)
assert type(res1[0]) == str assert isinstance(res1[0], str)
class PullImageTest(BaseAPIIntegrationTest): class PullImageTest(BaseAPIIntegrationTest):
@ -43,7 +43,7 @@ class PullImageTest(BaseAPIIntegrationTest):
pass pass
res = self.client.pull('hello-world') res = self.client.pull('hello-world')
self.tmp_imgs.append('hello-world') self.tmp_imgs.append('hello-world')
assert type(res) == str assert isinstance(res, str)
assert len(self.client.images('hello-world')) >= 1 assert len(self.client.images('hello-world')) >= 1
img_info = self.client.inspect_image('hello-world') img_info = self.client.inspect_image('hello-world')
assert 'Id' in img_info assert 'Id' in img_info

View File

@ -9,7 +9,7 @@ class ErrorsTest(BaseAPIIntegrationTest):
self.client.start(container['Id']) self.client.start(container['Id'])
with pytest.raises(APIError) as cm: with pytest.raises(APIError) as cm:
self.client.remove_container(container['Id']) self.client.remove_container(container['Id'])
explanation = cm.value.explanation explanation = cm.value.explanation.lower()
assert 'You cannot remove a running container' in explanation assert 'stop the container before' in explanation
assert '{"message":' not in explanation assert '{"message":' not in explanation
self.client.remove_container(container['Id'], force=True) self.client.remove_container(container['Id'], force=True)

View File

@ -102,6 +102,7 @@ class ImageTest(BaseAPIClientTest):
'tag': None, 'tag': None,
'container': fake_api.FAKE_CONTAINER_ID, 'container': fake_api.FAKE_CONTAINER_ID,
'author': None, 'author': None,
'pause': True,
'changes': None 'changes': None
}, },
timeout=DEFAULT_TIMEOUT_SECONDS timeout=DEFAULT_TIMEOUT_SECONDS