Unverified Kaydet (Commit) 9daa3204 authored tarafından Ben Firshman's avatar Ben Firshman

Rename Client to APIClient

Signed-off-by: 's avatarBen Firshman <ben@firshman.co.uk>
üst c7903f08
# flake8: noqa
from .api import APIClient
from .version import version, version_info
__version__ = version
__title__ = 'docker-py'
from .client import Client, from_env # flake8: noqa
# flake8: noqa
from .build import BuildApiMixin
from .container import ContainerApiMixin
from .daemon import DaemonApiMixin
from .exec_api import ExecApiMixin
from .image import ImageApiMixin
from .network import NetworkApiMixin
from .service import ServiceApiMixin
from .swarm import SwarmApiMixin
from .volume import VolumeApiMixin
from .client import APIClient
......@@ -8,41 +8,59 @@ import requests.exceptions
import six
import websocket
from . import api, auth, constants, errors, ssladapter
from .tls import TLSConfig
from .transport import UnixAdapter
from .utils import utils, check_resource, update_headers, kwargs_from_env
from .utils.socket import frames_iter
from .build import BuildApiMixin
from .container import ContainerApiMixin
from .daemon import DaemonApiMixin
from .exec_api import ExecApiMixin
from .image import ImageApiMixin
from .network import NetworkApiMixin
from .service import ServiceApiMixin
from .swarm import SwarmApiMixin
from .volume import VolumeApiMixin
from .. import auth, ssladapter
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, APIError, TLSParameterError, NotFound
from ..tls import TLSConfig
from ..transport import UnixAdapter
from ..utils import utils, check_resource, update_headers, kwargs_from_env
from ..utils.socket import frames_iter
try:
from .transport import NpipeAdapter
from ..transport import NpipeAdapter
except ImportError:
pass
def from_env(**kwargs):
return Client.from_env(**kwargs)
return APIClient.from_env(**kwargs)
class Client(
class APIClient(
requests.Session,
api.BuildApiMixin,
api.ContainerApiMixin,
api.DaemonApiMixin,
api.ExecApiMixin,
api.ImageApiMixin,
api.NetworkApiMixin,
api.ServiceApiMixin,
api.SwarmApiMixin,
api.VolumeApiMixin):
BuildApiMixin,
ContainerApiMixin,
DaemonApiMixin,
ExecApiMixin,
ImageApiMixin,
NetworkApiMixin,
ServiceApiMixin,
SwarmApiMixin,
VolumeApiMixin):
"""
A low-level client for the Docker Remote API.
Each method maps one-to-one with a REST API endpoint, so calling each
method results in a single API call.
"""
def __init__(self, base_url=None, version=None,
timeout=constants.DEFAULT_TIMEOUT_SECONDS, tls=False,
user_agent=constants.DEFAULT_USER_AGENT,
num_pools=constants.DEFAULT_NUM_POOLS):
super(Client, self).__init__()
timeout=DEFAULT_TIMEOUT_SECONDS, tls=False,
user_agent=DEFAULT_USER_AGENT, num_pools=DEFAULT_NUM_POOLS):
super(APIClient, self).__init__()
if tls and not base_url:
raise errors.TLSParameterError(
raise TLSParameterError(
'If using TLS, the base_url argument must be provided.'
)
......@@ -53,7 +71,7 @@ class Client(
self._auth_configs = auth.load_config()
base_url = utils.parse_host(
base_url, constants.IS_WINDOWS_PLATFORM, tls=bool(tls)
base_url, IS_WINDOWS_PLATFORM, tls=bool(tls)
)
if base_url.startswith('http+unix://'):
self._custom_adapter = UnixAdapter(
......@@ -63,8 +81,8 @@ class Client(
self._unmount('http://', 'https://')
self.base_url = 'http+docker://localunixsocket'
elif base_url.startswith('npipe://'):
if not constants.IS_WINDOWS_PLATFORM:
raise errors.DockerException(
if not IS_WINDOWS_PLATFORM:
raise DockerException(
'The npipe:// protocol is only supported on Windows'
)
try:
......@@ -72,7 +90,7 @@ class Client(
base_url, timeout, pool_connections=num_pools
)
except NameError:
raise errors.DockerException(
raise DockerException(
'Install pypiwin32 package to enable npipe:// support'
)
self.mount('http+docker://', self._custom_adapter)
......@@ -90,24 +108,24 @@ class Client(
# version detection needs to be after unix adapter mounting
if version is None:
self._version = constants.DEFAULT_DOCKER_API_VERSION
self._version = DEFAULT_DOCKER_API_VERSION
elif isinstance(version, six.string_types):
if version.lower() == 'auto':
self._version = self._retrieve_server_version()
else:
self._version = version
else:
raise errors.DockerException(
raise DockerException(
'Version parameter must be a string or None. Found {0}'.format(
type(version).__name__
)
)
if utils.version_lt(self._version, constants.MINIMUM_DOCKER_API_VERSION):
if utils.version_lt(self._version, MINIMUM_DOCKER_API_VERSION):
warnings.warn(
'The minimum API version supported is {}, but you are using '
'version {}. It is recommended you either upgrade Docker '
'Engine or use an older version of docker-py.'.format(
constants.MINIMUM_DOCKER_API_VERSION, self._version)
MINIMUM_DOCKER_API_VERSION, self._version)
)
@classmethod
......@@ -121,12 +139,12 @@ class Client(
try:
return self.version(api_version=False)["ApiVersion"]
except KeyError:
raise errors.DockerException(
raise DockerException(
'Invalid response from docker daemon: key "ApiVersion"'
' is missing.'
)
except Exception as e:
raise errors.DockerException(
raise DockerException(
'Error while fetching server API version: {0}'.format(e)
)
......@@ -176,8 +194,8 @@ class Client(
response.raise_for_status()
except requests.exceptions.HTTPError as e:
if e.response.status_code == 404:
raise errors.NotFound(e, response, explanation=explanation)
raise errors.APIError(e, response, explanation=explanation)
raise NotFound(e, response, explanation=explanation)
raise APIError(e, response, explanation=explanation)
def _result(self, response, json=False, binary=False):
assert not (json and binary)
......@@ -282,7 +300,7 @@ class Client(
if len(buf[walker:]) < 8:
break
_, length = struct.unpack_from('>BxxxL', buf[walker:])
start = walker + constants.STREAM_HEADER_SIZE_BYTES
start = walker + STREAM_HEADER_SIZE_BYTES
end = start + length
walker = end
yield buf[start:end]
......@@ -297,7 +315,7 @@ class Client(
self._disable_socket_timeout(socket)
while True:
header = response.raw.read(constants.STREAM_HEADER_SIZE_BYTES)
header = response.raw.read(STREAM_HEADER_SIZE_BYTES)
if not header:
break
_, length = struct.unpack('>BxxxL', header)
......@@ -390,7 +408,7 @@ class Client(
def get_adapter(self, url):
try:
return super(Client, self).get_adapter(url)
return super(APIClient, self).get_adapter(url)
except requests.exceptions.InvalidSchema as e:
if self._custom_adapter:
return self._custom_adapter
......
......@@ -25,7 +25,7 @@ class InformationTest(BaseIntegrationTest):
self.assertIn('Debug', res)
def test_search(self):
client = docker.from_env(timeout=10)
client = docker.APIClient(timeout=10, **kwargs_from_env())
res = client.search('busybox')
self.assertTrue(len(res) >= 1)
base_img = [x for x in res if x['name'] == 'busybox']
......@@ -114,7 +114,7 @@ class LoadConfigTest(BaseIntegrationTest):
class AutoDetectVersionTest(unittest.TestCase):
def test_client_init(self):
client = docker.from_env(version='auto')
client = docker.APIClient(version='auto', **kwargs_from_env())
client_version = client._version
api_version = client.version(api_version=False)['ApiVersion']
self.assertEqual(client_version, api_version)
......@@ -126,7 +126,7 @@ class AutoDetectVersionTest(unittest.TestCase):
class ConnectionTimeoutTest(unittest.TestCase):
def setUp(self):
self.timeout = 0.5
self.client = docker.client.Client(base_url='http://192.168.10.2:4243',
self.client = docker.api.APIClient(base_url='http://192.168.10.2:4243',
timeout=self.timeout)
def test_timeout(self):
......@@ -155,7 +155,7 @@ class UnixconnTest(unittest.TestCase):
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('always')
client = docker.from_env()
client = docker.APIClient(**kwargs_from_env())
client.images()
client.close()
del client
......
from .base import BaseIntegrationTest
from .base import BUSYBOX
from .base import BaseAPIIntegrationTest, BUSYBOX
from .. import helpers
SECOND = 1000000000
......@@ -12,7 +11,7 @@ def wait_on_health_status(client, container, status):
return helpers.wait_on_condition(condition)
class HealthcheckTest(BaseIntegrationTest):
class HealthcheckTest(BaseAPIIntegrationTest):
@helpers.requires_api_version('1.24')
def test_healthcheck_shell_command(self):
......
......@@ -2,6 +2,7 @@ import shutil
import unittest
import docker
from docker.utils import kwargs_from_env
import six
......@@ -23,7 +24,7 @@ class BaseIntegrationTest(unittest.TestCase):
if six.PY2:
self.assertRegex = self.assertRegexpMatches
self.assertCountEqual = self.assertItemsEqual
self.client = docker.from_env(timeout=60)
self.client = docker.APIClient(timeout=60, **kwargs_from_env())
self.tmp_imgs = []
self.tmp_containers = []
self.tmp_folders = []
......
......@@ -4,6 +4,7 @@ import sys
import warnings
import docker.errors
from docker.utils import kwargs_from_env
import pytest
from .base import BUSYBOX
......@@ -12,7 +13,7 @@ from .base import BUSYBOX
@pytest.fixture(autouse=True, scope='session')
def setup_test_session():
warnings.simplefilter('error')
c = docker.from_env()
c = docker.APIClient(**kwargs_from_env())
try:
c.inspect_image(BUSYBOX)
except docker.errors.NotFound:
......
import os
import unittest
from docker.client import Client
from docker.api import APIClient
TEST_CERT_DIR = os.path.join(
os.path.dirname(__file__),
......@@ -23,14 +23,14 @@ class ClientTest(unittest.TestCase):
os.environ.update(DOCKER_HOST='tcp://192.168.59.103:2376',
DOCKER_CERT_PATH=TEST_CERT_DIR,
DOCKER_TLS_VERIFY='1')
client = Client.from_env()
client = APIClient.from_env()
self.assertEqual(client.base_url, "https://192.168.59.103:2376")
def test_from_env_with_version(self):
os.environ.update(DOCKER_HOST='tcp://192.168.59.103:2376',
DOCKER_CERT_PATH=TEST_CERT_DIR,
DOCKER_TLS_VERIFY='1')
client = Client.from_env(version='2.32')
client = APIClient.from_env(version='2.32')
self.assertEqual(client.base_url, "https://192.168.59.103:2376")
self.assertEqual(client._version, '2.32')
......@@ -47,7 +47,7 @@ class DisableSocketTest(unittest.TestCase):
return self.timeout
def setUp(self):
self.client = Client()
self.client = APIClient()
def test_disable_socket_timeout(self):
"""Test that the timeout is disabled on a generic socket object."""
......
......@@ -1244,7 +1244,7 @@ class ContainerTest(DockerClientTest):
)
def test_logs(self):
with mock.patch('docker.Client.inspect_container',
with mock.patch('docker.api.client.APIClient.inspect_container',
fake_inspect_container):
logs = self.client.logs(fake_api.FAKE_CONTAINER_ID)
......@@ -1263,7 +1263,7 @@ class ContainerTest(DockerClientTest):
)
def test_logs_with_dict_instead_of_id(self):
with mock.patch('docker.Client.inspect_container',
with mock.patch('docker.api.client.APIClient.inspect_container',
fake_inspect_container):
logs = self.client.logs({'Id': fake_api.FAKE_CONTAINER_ID})
......@@ -1282,7 +1282,7 @@ class ContainerTest(DockerClientTest):
)
def test_log_streaming(self):
with mock.patch('docker.Client.inspect_container',
with mock.patch('docker.api.client.APIClient.inspect_container',
fake_inspect_container):
self.client.logs(fake_api.FAKE_CONTAINER_ID, stream=True,
follow=False)
......@@ -1297,7 +1297,7 @@ class ContainerTest(DockerClientTest):
)
def test_log_following(self):
with mock.patch('docker.Client.inspect_container',
with mock.patch('docker.api.client.APIClient.inspect_container',
fake_inspect_container):
self.client.logs(fake_api.FAKE_CONTAINER_ID, stream=False,
follow=True)
......@@ -1312,7 +1312,7 @@ class ContainerTest(DockerClientTest):
)
def test_log_following_backwards(self):
with mock.patch('docker.Client.inspect_container',
with mock.patch('docker.api.client.APIClient.inspect_container',
fake_inspect_container):
self.client.logs(fake_api.FAKE_CONTAINER_ID, stream=True)
......@@ -1326,7 +1326,7 @@ class ContainerTest(DockerClientTest):
)
def test_log_streaming_and_following(self):
with mock.patch('docker.Client.inspect_container',
with mock.patch('docker.api.client.APIClient.inspect_container',
fake_inspect_container):
self.client.logs(fake_api.FAKE_CONTAINER_ID, stream=True,
follow=True)
......@@ -1342,7 +1342,7 @@ class ContainerTest(DockerClientTest):
def test_log_tail(self):
with mock.patch('docker.Client.inspect_container',
with mock.patch('docker.api.client.APIClient.inspect_container',
fake_inspect_container):
self.client.logs(fake_api.FAKE_CONTAINER_ID, stream=False,
follow=False, tail=10)
......@@ -1358,7 +1358,7 @@ class ContainerTest(DockerClientTest):
def test_log_since(self):
ts = 809222400
with mock.patch('docker.Client.inspect_container',
with mock.patch('docker.api.client.APIClient.inspect_container',
fake_inspect_container):
self.client.logs(fake_api.FAKE_CONTAINER_ID, stream=False,
follow=False, since=ts)
......@@ -1375,7 +1375,7 @@ class ContainerTest(DockerClientTest):
def test_log_since_with_datetime(self):
ts = 809222400
time = datetime.datetime.utcfromtimestamp(ts)
with mock.patch('docker.Client.inspect_container',
with mock.patch('docker.api.client.APIClient.inspect_container',
fake_inspect_container):
self.client.logs(fake_api.FAKE_CONTAINER_ID, stream=False,
follow=False, since=time)
......@@ -1391,9 +1391,9 @@ class ContainerTest(DockerClientTest):
def test_log_tty(self):
m = mock.Mock()
with mock.patch('docker.Client.inspect_container',
with mock.patch('docker.api.client.APIClient.inspect_container',
fake_inspect_container_tty):
with mock.patch('docker.Client._stream_raw_result',
with mock.patch('docker.api.client.APIClient._stream_raw_result',
m):
self.client.logs(fake_api.FAKE_CONTAINER_ID,
follow=True, stream=True)
......
......@@ -33,7 +33,7 @@ class NetworkTest(DockerClientTest):
get = mock.Mock(return_value=response(
status_code=200, content=json.dumps(networks).encode('utf-8')))
with mock.patch('docker.Client.get', get):
with mock.patch('docker.api.client.APIClient.get', get):
self.assertEqual(self.client.networks(), networks)
self.assertEqual(get.call_args[0][0], url_prefix + 'networks')
......@@ -59,7 +59,7 @@ class NetworkTest(DockerClientTest):
network_response = response(status_code=200, content=network_data)
post = mock.Mock(return_value=network_response)
with mock.patch('docker.Client.post', post):
with mock.patch('docker.api.client.APIClient.post', post):
result = self.client.create_network('foo')
self.assertEqual(result, network_data)
......@@ -109,7 +109,7 @@ class NetworkTest(DockerClientTest):
network_id = 'abc12345'
delete = mock.Mock(return_value=response(status_code=200))
with mock.patch('docker.Client.delete', delete):
with mock.patch('docker.api.client.APIClient.delete', delete):
self.client.remove_network(network_id)
args = delete.call_args
......@@ -130,7 +130,7 @@ class NetworkTest(DockerClientTest):
network_response = response(status_code=200, content=network_data)
get = mock.Mock(return_value=network_response)
with mock.patch('docker.Client.get', get):
with mock.patch('docker.api.client.APIClient.get', get):
result = self.client.inspect_network(network_id)
self.assertEqual(result, network_data)
......@@ -145,7 +145,7 @@ class NetworkTest(DockerClientTest):
post = mock.Mock(return_value=response(status_code=201))
with mock.patch('docker.Client.post', post):
with mock.patch('docker.api.client.APIClient.post', post):
self.client.connect_container_to_network(
{'Id': container_id},
network_id,
......@@ -174,7 +174,7 @@ class NetworkTest(DockerClientTest):
post = mock.Mock(return_value=response(status_code=201))
with mock.patch('docker.Client.post', post):
with mock.patch('docker.api.client.APIClient.post', post):
self.client.disconnect_container_from_network(
{'Id': container_id}, network_id)
......
......@@ -11,6 +11,7 @@ import time
import unittest
import docker
from docker.api import APIClient
import requests
from requests.packages import urllib3
import six
......@@ -95,12 +96,15 @@ url_prefix = '{0}v{1}/'.format(
class DockerClientTest(unittest.TestCase):
def setUp(self):
self.patcher = mock.patch.multiple(
'docker.Client', get=fake_get, post=fake_post, put=fake_put,
'docker.api.client.APIClient',
get=fake_get,
post=fake_post,
put=fake_put,
delete=fake_delete,
_read_from_socket=fake_read_from_socket
)
self.patcher.start()
self.client = docker.Client()
self.client = APIClient()
# Force-clear authconfig to avoid tampering with the tests
self.client._cfg = {'Configs': {}}
......@@ -122,7 +126,7 @@ class DockerClientTest(unittest.TestCase):
class DockerApiTest(DockerClientTest):
def test_ctor(self):
with pytest.raises(docker.errors.DockerException) as excinfo:
docker.Client(version=1.12)
APIClient(version=1.12)
self.assertEqual(
str(excinfo.value),
......@@ -189,7 +193,7 @@ class DockerApiTest(DockerClientTest):
)
def test_retrieve_server_version(self):
client = docker.Client(version="auto")
client = APIClient(version="auto")
self.assertTrue(isinstance(client._version, six.string_types))
self.assertFalse(client._version == "auto")
client.close()
......@@ -269,27 +273,27 @@ class DockerApiTest(DockerClientTest):
return socket_adapter.socket_path
def test_url_compatibility_unix(self):
c = docker.Client(base_url="unix://socket")
c = APIClient(base_url="unix://socket")
assert self._socket_path_for_client_session(c) == '/socket'
def test_url_compatibility_unix_triple_slash(self):
c = docker.Client(base_url="unix:///socket")
c = APIClient(base_url="unix:///socket")
assert self._socket_path_for_client_session(c) == '/socket'
def test_url_compatibility_http_unix_triple_slash(self):
c = docker.Client(base_url="http+unix:///socket")
c = APIClient(base_url="http+unix:///socket")
assert self._socket_path_for_client_session(c) == '/socket'
def test_url_compatibility_http(self):
c = docker.Client(base_url="http://hostname:1234")
c = APIClient(base_url="http://hostname:1234")
assert c.base_url == "http://hostname:1234"
def test_url_compatibility_tcp(self):
c = docker.Client(base_url="tcp://hostname:1234")
c = APIClient(base_url="tcp://hostname:1234")
assert c.base_url == "http://hostname:1234"
......@@ -435,7 +439,7 @@ class StreamTest(unittest.TestCase):
b'\r\n'
) + b'\r\n'.join(lines)
with docker.Client(base_url="http+unix://" + self.socket_file) \
with APIClient(base_url="http+unix://" + self.socket_file) \
as client:
for i in range(5):
try:
......@@ -455,7 +459,7 @@ class StreamTest(unittest.TestCase):
class UserAgentTest(unittest.TestCase):
def setUp(self):
self.patcher = mock.patch.object(
docker.Client,
APIClient,
'send',
return_value=fake_resp("GET", "%s/version" % fake_api.prefix)
)
......@@ -465,7 +469,7 @@ class UserAgentTest(unittest.TestCase):
self.patcher.stop()
def test_default_user_agent(self):
client = docker.Client()
client = APIClient()
client.version()
self.assertEqual(self.mock_send.call_count, 1)
......@@ -474,7 +478,7 @@ class UserAgentTest(unittest.TestCase):
self.assertEqual(headers['User-Agent'], expected)
def test_custom_user_agent(self):
client = docker.Client(user_agent='foo/bar')
client = APIClient(user_agent='foo/bar')
client.version()
self.assertEqual(self.mock_send.call_count, 1)
......
......@@ -13,10 +13,8 @@ import unittest
import pytest
import six
from docker.client import Client
from docker.constants import (
DEFAULT_DOCKER_API_VERSION, IS_WINDOWS_PLATFORM
)
from docker.api.client import APIClient
from docker.constants import DEFAULT_DOCKER_API_VERSION, IS_WINDOWS_PLATFORM
from docker.errors import DockerException, InvalidVersion
from docker.utils import (
parse_repository_tag, parse_host, convert_filters, kwargs_from_env,
......@@ -47,7 +45,7 @@ class DecoratorsTest(unittest.TestCase):
def f(self, headers=None):
return headers
client = Client()
client = APIClient()
client._auth_configs = {}
g = update_headers(f)
......@@ -305,7 +303,7 @@ class KwargsFromEnvTest(unittest.TestCase):
self.assertEqual(False, kwargs['tls'].assert_hostname)
self.assertTrue(kwargs['tls'].verify)
try:
client = Client(**kwargs)
client = APIClient(**kwargs)
self.assertEqual(kwargs['base_url'], client.base_url)
self.assertEqual(kwargs['tls'].ca_cert, client.verify)
self.assertEqual(kwargs['tls'].cert, client.cert)
......@@ -324,7 +322,7 @@ class KwargsFromEnvTest(unittest.TestCase):
self.assertEqual(True, kwargs['tls'].assert_hostname)
self.assertEqual(False, kwargs['tls'].verify)
try:
client = Client(**kwargs)
client = APIClient(**kwargs)
self.assertEqual(kwargs['base_url'], client.base_url)
self.assertEqual(kwargs['tls'].cert, client.cert)
self.assertFalse(kwargs['tls'].verify)
......@@ -821,6 +819,7 @@ class PortsTest(unittest.TestCase):
self.assertEqual(port_bindings["1000"], [("127.0.0.1", "1000")])
self.assertEqual(port_bindings["2000"], [("127.0.0.1", "2000")])
def convert_paths(collection):
if not IS_WINDOWS_PLATFORM:
return collection
......@@ -1093,7 +1092,7 @@ class TarTest(unittest.TestCase):
)
class FormatEnvironmentTest(base.BaseTestCase):
class FormatEnvironmentTest(unittest.TestCase):
def test_format_env_binary_unicode_value(self):
env_dict = {
'ARTIST_NAME': b'\xec\x86\xa1\xec\xa7\x80\xec\x9d\x80'
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment