Remove support to pre python 3.6

Signed-off-by: Ulysses Souza <ulyssessouza@gmail.com>
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 @@
         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 @@
                   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 @@
   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 @@
     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 @@
     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 @@
 
 .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 @@
 	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 @@
 	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 @@
 		--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 @@
 
 
 .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"\
@@ -108,20 +77,17 @@
 		--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 @@
         # 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 @@
 
     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 @@
         # 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 @@
             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 @@
                 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 @@
 
 class Context:
     """A context."""
+
     def __init__(self, name, orchestrator=None, host=None, endpoints=None,
                  tls=False):
         if not name:
@@ -128,9 +129,9 @@
                     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 @@
                 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 @@
             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 @@
 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_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 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 @@
         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_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 @@
 
     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 @@
                 )
 
             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 @@
                 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 @@
 
     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 @@
 
     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 @@
         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 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 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 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 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_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 @@
 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 @@
 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 @@
     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 @@
         '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 @@
 
 import pytest
 import requests
-import six
 
 import docker
 from .. import helpers
@@ -35,7 +34,7 @@
         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 @@
         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 @@
         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 @@
         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 @@
             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 @@
             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 @@
             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 @@
             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 @@
             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 @@
         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 @@
             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 @@
         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 @@
         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 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 @@
 
     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 @@
             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 @@
     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 docker
 import pytest
-import six
 
 from ..helpers import (
     force_leave_swarm, requires_api_version, requires_experimental
@@ -150,7 +149,7 @@
             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 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]