From c8fba210a222d4f7fde90da8f48db1e7faa637ec Mon Sep 17 00:00:00 2001 From: Ulysses Souza Date: Wed, 10 Mar 2021 20:43:37 -0300 Subject: Remove support to pre python 3.6 Signed-off-by: Ulysses Souza --- .github/workflows/ci.yml | 6 ++-- .readthedocs.yml | 2 +- Dockerfile | 6 +--- Dockerfile-py3 | 15 ---------- Jenkinsfile | 5 +--- Makefile | 50 ++++++--------------------------- docker/api/client.py | 18 ++++++------ docker/context/context.py | 7 +++-- docker/transport/sshconn.py | 4 +-- docker/utils/utils.py | 49 +++++++++++++------------------- requirements.txt | 1 - setup.py | 12 +------- test-requirements.txt | 2 +- tests/Dockerfile-dind-certs | 2 +- tests/integration/api_container_test.py | 48 +++++++++---------------------- tests/integration/api_image_test.py | 11 ++++---- tests/integration/api_service_test.py | 3 +- tests/unit/sshadapter_test.py | 27 +++++++++++------- tox.ini | 2 +- 19 files changed, 88 insertions(+), 182 deletions(-) delete mode 100644 Dockerfile-py3 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1f119c9..b692508 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,7 +8,7 @@ jobs: strategy: max-parallel: 1 matrix: - python-version: [2.7, 3.5, 3.6, 3.7, 3.8, 3.9] + python-version: [3.6, 3.7, 3.8, 3.9] steps: - uses: actions/checkout@v2 @@ -18,8 +18,8 @@ jobs: python-version: ${{ matrix.python-version }} - name: Install dependencies run: | - python -m pip install --upgrade pip - pip install -r test-requirements.txt -r requirements.txt + python3 -m pip install --upgrade pip + pip3 install -r test-requirements.txt -r requirements.txt - name: Test with pytest run: | docker logout diff --git a/.readthedocs.yml b/.readthedocs.yml index 7679f80..32113fe 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -4,7 +4,7 @@ sphinx: configuration: docs/conf.py python: - version: 3.5 + version: 3.6 install: - requirements: docs-requirements.txt - requirements: requirements.txt diff --git a/Dockerfile b/Dockerfile index 7309a83..22732de 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,11 +1,7 @@ -ARG PYTHON_VERSION=2.7 +ARG PYTHON_VERSION=3.7 FROM python:${PYTHON_VERSION} -# Add SSH keys and set permissions -COPY tests/ssh-keys /root/.ssh -RUN chmod -R 600 /root/.ssh - RUN mkdir /src WORKDIR /src diff --git a/Dockerfile-py3 b/Dockerfile-py3 deleted file mode 100644 index 22732de..0000000 --- a/Dockerfile-py3 +++ /dev/null @@ -1,15 +0,0 @@ -ARG PYTHON_VERSION=3.7 - -FROM python:${PYTHON_VERSION} - -RUN mkdir /src -WORKDIR /src - -COPY requirements.txt /src/requirements.txt -RUN pip install -r requirements.txt - -COPY test-requirements.txt /src/test-requirements.txt -RUN pip install -r test-requirements.txt - -COPY . /src -RUN pip install . diff --git a/Jenkinsfile b/Jenkinsfile index 471072b..f524ae7 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,7 +1,6 @@ #!groovy def imageNameBase = "dockerpinata/docker-py" -def imageNamePy2 def imageNamePy3 def imageDindSSH def images = [:] @@ -22,12 +21,10 @@ def buildImages = { -> stage("build image") { checkout(scm) - imageNamePy2 = "${imageNameBase}:py2-${gitCommit()}" imageNamePy3 = "${imageNameBase}:py3-${gitCommit()}" imageDindSSH = "${imageNameBase}:sshdind-${gitCommit()}" withDockerRegistry(credentialsId:'dockerbuildbot-index.docker.io') { buildImage(imageDindSSH, "-f tests/Dockerfile-ssh-dind .", "") - buildImage(imageNamePy2, "-f tests/Dockerfile --build-arg PYTHON_VERSION=2.7 .", "py2.7") buildImage(imageNamePy3, "-f tests/Dockerfile --build-arg PYTHON_VERSION=3.7 .", "py3.7") } } @@ -73,7 +70,7 @@ def runTests = { Map settings -> throw new Exception("Need Docker version to test, e.g.: `runTests(dockerVersion: '19.03.12')`") } if (!pythonVersion) { - throw new Exception("Need Python version being tested, e.g.: `runTests(pythonVersion: 'py2.7')`") + throw new Exception("Need Python version being tested, e.g.: `runTests(pythonVersion: 'py3.7')`") } { -> diff --git a/Makefile b/Makefile index 70d7083..60d9984 100644 --- a/Makefile +++ b/Makefile @@ -6,13 +6,9 @@ all: test .PHONY: clean clean: - -docker rm -f dpy-dind-py2 dpy-dind-py3 dpy-dind-certs dpy-dind-ssl + -docker rm -f dpy-dind-py3 dpy-dind-certs dpy-dind-ssl find -name "__pycache__" | xargs rm -rf -.PHONY: build -build: - docker build -t docker-sdk-python -f tests/Dockerfile --build-arg PYTHON_VERSION=2.7 --build-arg APT_MIRROR . - .PHONY: build-dind-ssh build-dind-ssh: docker build -t docker-dind-ssh -f tests/Dockerfile-ssh-dind --build-arg ENGINE_VERSION=${TEST_ENGINE_VERSION} --build-arg API_VERSION=${TEST_API_VERSION} --build-arg APT_MIRROR . @@ -30,20 +26,12 @@ build-dind-certs: docker build -t dpy-dind-certs -f tests/Dockerfile-dind-certs . .PHONY: test -test: flake8 unit-test unit-test-py3 integration-dind integration-dind-ssl - -.PHONY: unit-test -unit-test: build - docker run -t --rm docker-sdk-python py.test tests/unit +test: flake8 unit-test-py3 integration-dind integration-dind-ssl .PHONY: unit-test-py3 unit-test-py3: build-py3 docker run -t --rm docker-sdk-python3 py.test tests/unit -.PHONY: integration-test -integration-test: build - docker run -t --rm -v /var/run/docker.sock:/var/run/docker.sock docker-sdk-python py.test -v tests/integration/${file} - .PHONY: integration-test-py3 integration-test-py3: build-py3 docker run -t --rm -v /var/run/docker.sock:/var/run/docker.sock docker-sdk-python3 py.test -v tests/integration/${file} @@ -53,16 +41,7 @@ setup-network: docker network inspect dpy-tests || docker network create dpy-tests .PHONY: integration-dind -integration-dind: integration-dind-py2 integration-dind-py3 - -.PHONY: integration-dind-py2 -integration-dind-py2: build setup-network - docker rm -vf dpy-dind-py2 || : - docker run -d --network dpy-tests --name dpy-dind-py2 --privileged\ - docker:${TEST_ENGINE_VERSION}-dind dockerd -H tcp://0.0.0.0:2375 --experimental - docker run -t --rm --env="DOCKER_HOST=tcp://dpy-dind-py2:2375" --env="DOCKER_TEST_API_VERSION=${TEST_API_VERSION}"\ - --network dpy-tests docker-sdk-python py.test tests/integration/${file} - docker rm -vf dpy-dind-py2 +integration-dind: integration-dind-py3 .PHONY: integration-dind-py3 integration-dind-py3: build-py3 setup-network @@ -73,16 +52,6 @@ integration-dind-py3: build-py3 setup-network --network dpy-tests docker-sdk-python3 py.test tests/integration/${file} docker rm -vf dpy-dind-py3 -.PHONY: integration-ssh-py2 -integration-ssh-py2: build-dind-ssh build setup-network - docker rm -vf dpy-dind-py2 || : - docker run -d --network dpy-tests --name dpy-dind-py2 --privileged\ - docker-dind-ssh dockerd --experimental - # start SSH daemon - docker exec dpy-dind-py2 sh -c "/usr/sbin/sshd" - docker run -t --rm --env="DOCKER_HOST=ssh://dpy-dind-py2" --env="DOCKER_TEST_API_VERSION=${TEST_API_VERSION}"\ - --network dpy-tests docker-sdk-python py.test tests/ssh/${file} - docker rm -vf dpy-dind-py2 .PHONY: integration-ssh-py3 integration-ssh-py3: build-dind-ssh build-py3 setup-network @@ -97,7 +66,7 @@ integration-ssh-py3: build-dind-ssh build-py3 setup-network .PHONY: integration-dind-ssl -integration-dind-ssl: build-dind-certs build build-py3 +integration-dind-ssl: build-dind-certs build-py3 docker rm -vf dpy-dind-certs dpy-dind-ssl || : docker run -d --name dpy-dind-certs dpy-dind-certs docker run -d --env="DOCKER_HOST=tcp://localhost:2375" --env="DOCKER_TLS_VERIFY=1"\ @@ -106,22 +75,19 @@ integration-dind-ssl: build-dind-certs build build-py3 docker:${TEST_ENGINE_VERSION}-dind\ dockerd --tlsverify --tlscacert=/certs/ca.pem --tlscert=/certs/server-cert.pem\ --tlskey=/certs/server-key.pem -H tcp://0.0.0.0:2375 --experimental - docker run -t --rm --volumes-from dpy-dind-ssl --env="DOCKER_HOST=tcp://docker:2375"\ - --env="DOCKER_TLS_VERIFY=1" --env="DOCKER_CERT_PATH=/certs" --env="DOCKER_TEST_API_VERSION=${TEST_API_VERSION}"\ - --network dpy-tests docker-sdk-python py.test tests/integration/${file} docker run -t --rm --volumes-from dpy-dind-ssl --env="DOCKER_HOST=tcp://docker:2375"\ --env="DOCKER_TLS_VERIFY=1" --env="DOCKER_CERT_PATH=/certs" --env="DOCKER_TEST_API_VERSION=${TEST_API_VERSION}"\ --network dpy-tests docker-sdk-python3 py.test tests/integration/${file} docker rm -vf dpy-dind-ssl dpy-dind-certs .PHONY: flake8 -flake8: build - docker run -t --rm docker-sdk-python flake8 docker tests +flake8: build-py3 + docker run -t --rm docker-sdk-python3 flake8 docker tests .PHONY: docs docs: build-docs docker run --rm -t -v `pwd`:/src docker-sdk-python-docs sphinx-build docs docs/_build .PHONY: shell -shell: build - docker run -it -v /var/run/docker.sock:/var/run/docker.sock docker-sdk-python python +shell: build-py3 + docker run -it -v /var/run/docker.sock:/var/run/docker.sock docker-sdk-python3 python diff --git a/docker/api/client.py b/docker/api/client.py index 2b67291..ee9ad9c 100644 --- a/docker/api/client.py +++ b/docker/api/client.py @@ -1,10 +1,10 @@ import json import struct +import urllib from functools import partial import requests import requests.exceptions -import six import websocket from .. import auth @@ -192,12 +192,12 @@ class APIClient( # version detection needs to be after unix adapter mounting if version is None or (isinstance( version, - six.string_types + str ) and version.lower() == 'auto'): self._version = self._retrieve_server_version() else: self._version = version - if not isinstance(self._version, six.string_types): + if not isinstance(self._version, str): raise DockerException( 'Version parameter must be a string or None. Found {0}'.format( type(version).__name__ @@ -246,13 +246,13 @@ class APIClient( def _url(self, pathfmt, *args, **kwargs): for arg in args: - if not isinstance(arg, six.string_types): + if not isinstance(arg, str): raise ValueError( 'Expected a string but found {0} ({1}) ' 'instead'.format(arg, type(arg)) ) - quote_f = partial(six.moves.urllib.parse.quote, safe="/:") + quote_f = partial(urllib.parse.quote, safe="/:") args = map(quote_f, args) if kwargs.get('versioned_api', True): @@ -284,7 +284,7 @@ class APIClient( # so we do this disgusting thing here. data2 = {} if data is not None and isinstance(data, dict): - for k, v in six.iteritems(data): + for k, v in iter(data.items()): if v is not None: data2[k] = v elif data is not None: @@ -320,12 +320,10 @@ class APIClient( sock = response.raw._fp.fp.raw.sock elif self.base_url.startswith('http+docker://ssh'): sock = response.raw._fp.fp.channel - elif six.PY3: + else: sock = response.raw._fp.fp.raw if self.base_url.startswith("https://"): sock = sock._sock - else: - sock = response.raw._fp.fp._sock try: # Keep a reference to the response to stop it being garbage # collected. If the response is garbage collected, it will @@ -465,7 +463,7 @@ class APIClient( self._result(res, binary=True) self._raise_for_status(res) - sep = six.binary_type() + sep = b'' if stream: return self._multiplexed_response_stream_helper(res) else: diff --git a/docker/context/context.py b/docker/context/context.py index b1cacf9..f4aff6b 100644 --- a/docker/context/context.py +++ b/docker/context/context.py @@ -11,6 +11,7 @@ from docker.context.config import get_context_host class Context: """A context.""" + def __init__(self, name, orchestrator=None, host=None, endpoints=None, tls=False): if not name: @@ -128,9 +129,9 @@ class Context: key = os.path.join(tls_dir, endpoint, filename) if all([ca_cert, cert, key]): verify = None - if endpoint == "docker": - if not self.endpoints["docker"].get("SkipTLSVerify", False): - verify = True + if endpoint == "docker" and not self.endpoints["docker"].get( + "SkipTLSVerify", False): + verify = True certs[endpoint] = TLSConfig( client_cert=(cert, key), ca_cert=ca_cert, verify=verify) self.tls_cfg = certs diff --git a/docker/transport/sshconn.py b/docker/transport/sshconn.py index a761ef5..fb5c6bb 100644 --- a/docker/transport/sshconn.py +++ b/docker/transport/sshconn.py @@ -53,7 +53,7 @@ class SSHSocket(socket.socket): signal.signal(signal.SIGINT, signal.SIG_IGN) preexec_func = f - env = dict(os.environ) + env = dict(os.environ) # drop LD_LIBRARY_PATH and SSL_CERT_FILE env.pop('LD_LIBRARY_PATH', None) @@ -65,7 +65,7 @@ class SSHSocket(socket.socket): shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE, - preexec_fn=preexec_func) + preexec_fn=None if constants.IS_WINDOWS_PLATFORM else preexec_func) def _write(self, data): if not self.proc or self.proc.stdin.closed: diff --git a/docker/utils/utils.py b/docker/utils/utils.py index 1b195e2..f703cbd 100644 --- a/docker/utils/utils.py +++ b/docker/utils/utils.py @@ -7,8 +7,6 @@ import string from datetime import datetime from distutils.version import StrictVersion -import six - from .. import errors from .. import tls from ..constants import DEFAULT_HTTP_HOST @@ -16,11 +14,7 @@ from ..constants import DEFAULT_UNIX_SOCKET from ..constants import DEFAULT_NPIPE from ..constants import BYTE_UNITS -if six.PY2: - from urllib import splitnport - from urlparse import urlparse -else: - from urllib.parse import splitnport, urlparse +from urllib.parse import splitnport, urlparse def create_ipam_pool(*args, **kwargs): @@ -39,8 +33,7 @@ def create_ipam_config(*args, **kwargs): def decode_json_header(header): data = base64.b64decode(header) - if six.PY3: - data = data.decode('utf-8') + data = data.decode('utf-8') return json.loads(data) @@ -80,7 +73,7 @@ def _convert_port_binding(binding): if len(binding) == 2: result['HostPort'] = binding[1] result['HostIp'] = binding[0] - elif isinstance(binding[0], six.string_types): + elif isinstance(binding[0], str): result['HostIp'] = binding[0] else: result['HostPort'] = binding[0] @@ -104,7 +97,7 @@ def _convert_port_binding(binding): def convert_port_bindings(port_bindings): result = {} - for k, v in six.iteritems(port_bindings): + for k, v in iter(port_bindings.items()): key = str(k) if '/' not in key: key += '/tcp' @@ -121,7 +114,7 @@ def convert_volume_binds(binds): result = [] for k, v in binds.items(): - if isinstance(k, six.binary_type): + if isinstance(k, bytes): k = k.decode('utf-8') if isinstance(v, dict): @@ -132,7 +125,7 @@ def convert_volume_binds(binds): ) bind = v['bind'] - if isinstance(bind, six.binary_type): + if isinstance(bind, bytes): bind = bind.decode('utf-8') if 'ro' in v: @@ -143,13 +136,13 @@ def convert_volume_binds(binds): mode = 'rw' result.append( - six.text_type('{0}:{1}:{2}').format(k, bind, mode) + str('{0}:{1}:{2}').format(k, bind, mode) ) else: - if isinstance(v, six.binary_type): + if isinstance(v, bytes): v = v.decode('utf-8') result.append( - six.text_type('{0}:{1}:rw').format(k, v) + str('{0}:{1}:rw').format(k, v) ) return result @@ -166,7 +159,7 @@ def convert_tmpfs_mounts(tmpfs): result = {} for mount in tmpfs: - if isinstance(mount, six.string_types): + if isinstance(mount, str): if ":" in mount: name, options = mount.split(":", 1) else: @@ -191,7 +184,7 @@ def convert_service_networks(networks): result = [] for n in networks: - if isinstance(n, six.string_types): + if isinstance(n, str): n = {'Target': n} result.append(n) return result @@ -302,7 +295,7 @@ def parse_devices(devices): if isinstance(device, dict): device_list.append(device) continue - if not isinstance(device, six.string_types): + if not isinstance(device, str): raise errors.DockerException( 'Invalid device type {0}'.format(type(device)) ) @@ -372,13 +365,13 @@ def kwargs_from_env(ssl_version=None, assert_hostname=None, environment=None): def convert_filters(filters): result = {} - for k, v in six.iteritems(filters): + for k, v in iter(filters.items()): if isinstance(v, bool): v = 'true' if v else 'false' if not isinstance(v, list): v = [v, ] result[k] = [ - str(item) if not isinstance(item, six.string_types) else item + str(item) if not isinstance(item, str) else item for item in v ] return json.dumps(result) @@ -391,7 +384,7 @@ def datetime_to_timestamp(dt): def parse_bytes(s): - if isinstance(s, six.integer_types + (float,)): + if isinstance(s, (int, float,)): return s if len(s) == 0: return 0 @@ -433,7 +426,7 @@ def parse_bytes(s): def normalize_links(links): if isinstance(links, dict): - links = six.iteritems(links) + links = iter(links.items()) return ['{0}:{1}'.format(k, v) if v else k for k, v in sorted(links)] @@ -468,8 +461,6 @@ def parse_env_file(env_file): def split_command(command): - if six.PY2 and not isinstance(command, six.binary_type): - command = command.encode('utf-8') return shlex.split(command) @@ -477,22 +468,22 @@ def format_environment(environment): def format_env(key, value): if value is None: return key - if isinstance(value, six.binary_type): + if isinstance(value, bytes): value = value.decode('utf-8') return u'{key}={value}'.format(key=key, value=value) - return [format_env(*var) for var in six.iteritems(environment)] + return [format_env(*var) for var in iter(environment.items())] def format_extra_hosts(extra_hosts, task=False): # Use format dictated by Swarm API if container is part of a task if task: return [ - '{} {}'.format(v, k) for k, v in sorted(six.iteritems(extra_hosts)) + '{} {}'.format(v, k) for k, v in sorted(iter(extra_hosts.items())) ] return [ - '{}:{}'.format(k, v) for k, v in sorted(six.iteritems(extra_hosts)) + '{}:{}'.format(k, v) for k, v in sorted(iter(extra_hosts.items())) ] diff --git a/requirements.txt b/requirements.txt index 43a688f..f86a7bd 100644 --- a/requirements.txt +++ b/requirements.txt @@ -13,6 +13,5 @@ pyOpenSSL==18.0.0 pyparsing==2.2.0 pywin32==227; sys_platform == 'win32' requests==2.20.0 -six==1.10.0 urllib3==1.24.3 websocket-client==0.56.0 diff --git a/setup.py b/setup.py index 330ab3e..b86016e 100644 --- a/setup.py +++ b/setup.py @@ -11,18 +11,11 @@ ROOT_DIR = os.path.dirname(__file__) SOURCE_DIR = os.path.join(ROOT_DIR) requirements = [ - 'six >= 1.4.0', 'websocket-client >= 0.32.0', 'requests >= 2.14.2, != 2.18.0', ] extras_require = { - ':python_version < "3.5"': 'backports.ssl_match_hostname >= 3.5', - # While not imported explicitly, the ipaddress module is required for - # ssl_match_hostname to verify hosts match with certificates via - # ServerAltname: https://pypi.python.org/pypi/backports.ssl_match_hostname - ':python_version < "3.3"': 'ipaddress >= 1.0.16', - # win32 APIs if on Windows (required for npipe support) ':sys_platform == "win32"': 'pywin32==227', @@ -69,7 +62,7 @@ setup( install_requires=requirements, tests_require=test_requirements, extras_require=extras_require, - python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*', + python_requires='>=3.6', zip_safe=False, test_suite='tests', classifiers=[ @@ -78,10 +71,7 @@ setup( 'Intended Audience :: Developers', 'Operating System :: OS Independent', 'Programming Language :: Python', - 'Programming Language :: Python :: 2', - 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: 3.8', diff --git a/test-requirements.txt b/test-requirements.txt index 24078e2..40161bb 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -1,4 +1,4 @@ -setuptools==44.0.0 # last version with python 2.7 support +setuptools==54.1.1 coverage==4.5.2 flake8==3.6.0 mock==1.0.1 diff --git a/tests/Dockerfile-dind-certs b/tests/Dockerfile-dind-certs index 2ab87ef..8829ff7 100644 --- a/tests/Dockerfile-dind-certs +++ b/tests/Dockerfile-dind-certs @@ -1,4 +1,4 @@ -ARG PYTHON_VERSION=2.7 +ARG PYTHON_VERSION=3.6 FROM python:${PYTHON_VERSION} RUN mkdir /tmp/certs diff --git a/tests/integration/api_container_test.py b/tests/integration/api_container_test.py index 65e611b..3087045 100644 --- a/tests/integration/api_container_test.py +++ b/tests/integration/api_container_test.py @@ -7,7 +7,6 @@ from datetime import datetime import pytest import requests -import six import docker from .. import helpers @@ -35,7 +34,7 @@ class ListContainersTest(BaseAPIIntegrationTest): assert len(retrieved) == 1 retrieved = retrieved[0] assert 'Command' in retrieved - assert retrieved['Command'] == six.text_type('true') + assert retrieved['Command'] == str('true') assert 'Image' in retrieved assert re.search(r'alpine:.*', retrieved['Image']) assert 'Status' in retrieved @@ -104,9 +103,7 @@ class CreateContainerTest(BaseAPIIntegrationTest): self.client.start(container3_id) assert self.client.wait(container3_id)['StatusCode'] == 0 - logs = self.client.logs(container3_id) - if six.PY3: - logs = logs.decode('utf-8') + logs = self.client.logs(container3_id).decode('utf-8') assert '{0}_NAME='.format(link_env_prefix1) in logs assert '{0}_ENV_FOO=1'.format(link_env_prefix1) in logs assert '{0}_NAME='.format(link_env_prefix2) in logs @@ -227,9 +224,7 @@ class CreateContainerTest(BaseAPIIntegrationTest): self.client.start(container) self.client.wait(container) - logs = self.client.logs(container) - if six.PY3: - logs = logs.decode('utf-8') + logs = self.client.logs(container).decode('utf-8') groups = logs.strip().split(' ') assert '1000' in groups assert '1001' in groups @@ -244,9 +239,7 @@ class CreateContainerTest(BaseAPIIntegrationTest): self.client.start(container) self.client.wait(container) - logs = self.client.logs(container) - if six.PY3: - logs = logs.decode('utf-8') + logs = self.client.logs(container).decode('utf-8') groups = logs.strip().split(' ') assert '1000' in groups @@ -515,10 +508,7 @@ class VolumeBindTest(BaseAPIIntegrationTest): TEST_IMG, ['ls', self.mount_dest], ) - logs = self.client.logs(container) - - if six.PY3: - logs = logs.decode('utf-8') + logs = self.client.logs(container).decode('utf-8') assert self.filename in logs inspect_data = self.client.inspect_container(container) self.check_container_data(inspect_data, True) @@ -534,10 +524,8 @@ class VolumeBindTest(BaseAPIIntegrationTest): TEST_IMG, ['ls', self.mount_dest], ) - logs = self.client.logs(container) + logs = self.client.logs(container).decode('utf-8') - if six.PY3: - logs = logs.decode('utf-8') assert self.filename in logs inspect_data = self.client.inspect_container(container) @@ -554,9 +542,7 @@ class VolumeBindTest(BaseAPIIntegrationTest): host_config=host_config ) assert container - logs = self.client.logs(container) - if six.PY3: - logs = logs.decode('utf-8') + logs = self.client.logs(container).decode('utf-8') assert self.filename in logs inspect_data = self.client.inspect_container(container) self.check_container_data(inspect_data, True) @@ -573,9 +559,7 @@ class VolumeBindTest(BaseAPIIntegrationTest): host_config=host_config ) assert container - logs = self.client.logs(container) - if six.PY3: - logs = logs.decode('utf-8') + logs = self.client.logs(container).decode('utf-8') assert self.filename in logs inspect_data = self.client.inspect_container(container) self.check_container_data(inspect_data, False) @@ -645,9 +629,8 @@ class ArchiveTest(BaseAPIIntegrationTest): for d in strm: destination.write(d) destination.seek(0) - retrieved_data = helpers.untar_file(destination, 'data.txt') - if six.PY3: - retrieved_data = retrieved_data.decode('utf-8') + retrieved_data = helpers.untar_file(destination, 'data.txt')\ + .decode('utf-8') assert data == retrieved_data.strip() def test_get_file_stat_from_container(self): @@ -683,9 +666,6 @@ class ArchiveTest(BaseAPIIntegrationTest): self.client.start(ctnr) self.client.wait(ctnr) logs = self.client.logs(ctnr) - if six.PY3: - logs = logs.decode('utf-8') - data = data.decode('utf-8') assert logs.strip() == data def test_copy_directory_to_container(self): @@ -700,9 +680,7 @@ class ArchiveTest(BaseAPIIntegrationTest): self.client.put_archive(ctnr, '/vol1', test_tar) self.client.start(ctnr) self.client.wait(ctnr) - logs = self.client.logs(ctnr) - if six.PY3: - logs = logs.decode('utf-8') + logs = self.client.logs(ctnr).decode('utf-8') results = logs.strip().split() assert 'a.py' in results assert 'b.py' in results @@ -861,7 +839,7 @@ Line2''' id = container['Id'] self.tmp_containers.append(id) self.client.start(id) - logs = six.binary_type() + logs = b'' for chunk in self.client.logs(id, stream=True, follow=True): logs += chunk @@ -881,7 +859,7 @@ Line2''' id = container['Id'] self.tmp_containers.append(id) self.client.start(id) - logs = six.binary_type() + logs = b'' generator = self.client.logs(id, stream=True, follow=True) threading.Timer(1, generator.close).start() diff --git a/tests/integration/api_image_test.py b/tests/integration/api_image_test.py index 37e26a3..d5f8989 100644 --- a/tests/integration/api_image_test.py +++ b/tests/integration/api_image_test.py @@ -7,9 +7,8 @@ import tempfile import threading import pytest -import six -from six.moves import BaseHTTPServer -from six.moves import socketserver +from http.server import SimpleHTTPRequestHandler +import socketserver import docker @@ -33,7 +32,7 @@ class ListImagesTest(BaseAPIIntegrationTest): def test_images_quiet(self): res1 = self.client.images(quiet=True) - assert type(res1[0]) == six.text_type + assert type(res1[0]) == str class PullImageTest(BaseAPIIntegrationTest): @@ -44,7 +43,7 @@ class PullImageTest(BaseAPIIntegrationTest): pass res = self.client.pull('hello-world') self.tmp_imgs.append('hello-world') - assert type(res) == six.text_type + assert type(res) == str assert len(self.client.images('hello-world')) >= 1 img_info = self.client.inspect_image('hello-world') assert 'Id' in img_info @@ -273,7 +272,7 @@ class ImportImageTest(BaseAPIIntegrationTest): def temporary_http_file_server(self, stream): '''Serve data from an IO stream over HTTP.''' - class Handler(BaseHTTPServer.BaseHTTPRequestHandler): + class Handler(SimpleHTTPRequestHandler): def do_GET(self): self.send_response(200) self.send_header('Content-Type', 'application/x-tar') diff --git a/tests/integration/api_service_test.py b/tests/integration/api_service_test.py index 7e5336e..1bee46e 100644 --- a/tests/integration/api_service_test.py +++ b/tests/integration/api_service_test.py @@ -5,7 +5,6 @@ import time import docker import pytest -import six from ..helpers import ( force_leave_swarm, requires_api_version, requires_experimental @@ -150,7 +149,7 @@ class ServiceTest(BaseAPIIntegrationTest): else: break - if six.PY3: + if log_line is not None: log_line = log_line.decode('utf-8') assert 'hello\n' in log_line diff --git a/tests/unit/sshadapter_test.py b/tests/unit/sshadapter_test.py index ddee592..874239a 100644 --- a/tests/unit/sshadapter_test.py +++ b/tests/unit/sshadapter_test.py @@ -2,31 +2,38 @@ import unittest import docker from docker.transport.sshconn import SSHSocket + class SSHAdapterTest(unittest.TestCase): - def test_ssh_hostname_prefix_trim(self): - conn = docker.transport.SSHHTTPAdapter(base_url="ssh://user@hostname:1234", shell_out=True) + @staticmethod + def test_ssh_hostname_prefix_trim(): + conn = docker.transport.SSHHTTPAdapter( + base_url="ssh://user@hostname:1234", shell_out=True) assert conn.ssh_host == "user@hostname:1234" - def test_ssh_parse_url(self): + @staticmethod + def test_ssh_parse_url(): c = SSHSocket(host="user@hostname:1234") assert c.host == "hostname" assert c.port == "1234" assert c.user == "user" - def test_ssh_parse_hostname_only(self): + @staticmethod + def test_ssh_parse_hostname_only(): c = SSHSocket(host="hostname") assert c.host == "hostname" - assert c.port == None - assert c.user == None + assert c.port is None + assert c.user is None - def test_ssh_parse_user_and_hostname(self): + @staticmethod + def test_ssh_parse_user_and_hostname(): c = SSHSocket(host="user@hostname") assert c.host == "hostname" - assert c.port == None + assert c.port is None assert c.user == "user" - def test_ssh_parse_hostname_and_port(self): + @staticmethod + def test_ssh_parse_hostname_and_port(): c = SSHSocket(host="hostname:22") assert c.host == "hostname" assert c.port == "22" - assert c.user == None \ No newline at end of file + assert c.user is None diff --git a/tox.ini b/tox.ini index df797f4..d35d41a 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py27, py35, py36, py37, flake8 +envlist = py36, py37, flake8 skipsdist=True [testenv] -- cgit v1.2.1