prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  tlsv1 alert protocol version on 1.7.1 and 1.7.2 but not on 1.7.0
  Similar to #949 I'm discovering issues with latest versions of `docker-py` running against docker 1.10.2 instance. I'm using `docker.utils.kwargs_from_env(assert_hostname=False)`. Things work fine with version 1.7.0.
  
  Docker client is initialized via
  
  ```
  client = docker.Client(
      version='auto',
      **docker.utils.kwargs_from_env(assert_hostname=False))
  ```
  
  with docker environment variables being set to the following (via docker-machine)
  
  ```
  DOCKER_HOST=tcp://192.168.156.137:2376
  DOCKER_MACHINE_NAME=dev2
  DOCKER_TLS_VERIFY=1
  DOCKER_CERT_PATH=/Users/benjixx/.docker/machine/machines/dev2
  ```
  
  docker-py 1.7.1 and 1.7.2 now raise the following exception:
  
  ```
  DockerException: Error while fetching server API version: [Errno 1] _ssl.c:507: error:1407742E:SSL routines:SSL23_GET_SERVER_HELLO:tlsv1 alert protocol version
  ```
  
  Any idea what's happening here?
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `docker/tls.py`
  Content:
  ```
  1 import os
  2 
  3 from . import errors
  4 from .ssladapter import ssladapter
  5 
  6 
  7 class TLSConfig(object):
  8     cert = None
  9     ca_cert = None
  10     verify = None
  11     ssl_version = None
  12 
  13     def __init__(self, client_cert=None, ca_cert=None, verify=None,
  14                  ssl_version=None, assert_hostname=None,
  15                  assert_fingerprint=None):
  16         # Argument compatibility/mapping with
  17         # https://docs.docker.com/engine/articles/https/
  18         # This diverges from the Docker CLI in that users can specify 'tls'
  19         # here, but also disable any public/default CA pool verification by
  20         # leaving tls_verify=False
  21 
  22         self.ssl_version = ssl_version
  23         self.assert_hostname = assert_hostname
  24         self.assert_fingerprint = assert_fingerprint
  25 
  26         # "tls" and "tls_verify" must have both or neither cert/key files
  27         # In either case, Alert the user when both are expected, but any are
  28         # missing.
  29 
  30         if client_cert:
  31             try:
  32                 tls_cert, tls_key = client_cert
  33             except ValueError:
  34                 raise errors.TLSParameterError(
  35                     'client_config must be a tuple of'
  36                     ' (client certificate, key file)'
  37                 )
  38 
  39             if not (tls_cert and tls_key) or (not os.path.isfile(tls_cert) or
  40                not os.path.isfile(tls_key)):
  41                 raise errors.TLSParameterError(
  42                     'Path to a certificate and key files must be provided'
  43                     ' through the client_config param'
  44                 )
  45             self.cert = (tls_cert, tls_key)
  46 
  47         # If verify is set, make sure the cert exists
  48         self.verify = verify
  49         self.ca_cert = ca_cert
  50         if self.verify and self.ca_cert and not os.path.isfile(self.ca_cert):
  51             raise errors.TLSParameterError(
  52                 'Invalid CA certificate provided for `tls_ca_cert`.'
  53             )
  54 
  55     def configure_client(self, client):
  56         client.ssl_version = self.ssl_version
  57 
  58         if self.verify and self.ca_cert:
  59             client.verify = self.ca_cert
  60         else:
  61             client.verify = self.verify
  62 
  63         if self.cert:
  64             client.cert = self.cert
  65 
  66         client.mount('https://', ssladapter.SSLAdapter(
  67             ssl_version=self.ssl_version,
  68             assert_hostname=self.assert_hostname,
  69             assert_fingerprint=self.assert_fingerprint,
  70         ))
  71
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/docker/tls.py b/docker/tls.py
  --- a/docker/tls.py
  +++ b/docker/tls.py
  @@ -1,4 +1,5 @@
   import os
  +import ssl
   
   from . import errors
   from .ssladapter import ssladapter
  @@ -19,10 +20,14 @@
           # here, but also disable any public/default CA pool verification by
           # leaving tls_verify=False
   
  -        self.ssl_version = ssl_version
           self.assert_hostname = assert_hostname
           self.assert_fingerprint = assert_fingerprint
   
  +        # TLS v1.0 seems to be the safest default; SSLv23 fails in mysterious
  +        # ways: https://github.com/docker/docker-py/issues/963
  +
  +        self.ssl_version = ssl_version or ssl.PROTOCOL_TLSv1
  +
           # "tls" and "tls_verify" must have both or neither cert/key files
           # In either case, Alert the user when both are expected, but any are
           # missing.
  
verification_info: {"golden_diff": "diff --git a/docker/tls.py b/docker/tls.py\n--- a/docker/tls.py\n+++ b/docker/tls.py\n@@ -1,4 +1,5 @@\n import os\n+import ssl\n \n from . import errors\n from .ssladapter import ssladapter\n@@ -19,10 +20,14 @@\n         # here, but also disable any public/default CA pool verification by\n         # leaving tls_verify=False\n \n-        self.ssl_version = ssl_version\n         self.assert_hostname = assert_hostname\n         self.assert_fingerprint = assert_fingerprint\n \n+        # TLS v1.0 seems to be the safest default; SSLv23 fails in mysterious\n+        # ways: https://github.com/docker/docker-py/issues/963\n+\n+        self.ssl_version = ssl_version or ssl.PROTOCOL_TLSv1\n+\n         # \"tls\" and \"tls_verify\" must have both or neither cert/key files\n         # In either case, Alert the user when both are expected, but any are\n         # missing.\n", "issue": "tlsv1 alert protocol version on 1.7.1 and 1.7.2 but not on 1.7.0\nSimilar to #949 I'm discovering issues with latest versions of `docker-py` running against docker 1.10.2 instance. I'm using `docker.utils.kwargs_from_env(assert_hostname=False)`. Things work fine with version 1.7.0.\n\nDocker client is initialized via\n\n```\nclient = docker.Client(\n    version='auto',\n    **docker.utils.kwargs_from_env(assert_hostname=False))\n```\n\nwith docker environment variables being set to the following (via docker-machine)\n\n```\nDOCKER_HOST=tcp://192.168.156.137:2376\nDOCKER_MACHINE_NAME=dev2\nDOCKER_TLS_VERIFY=1\nDOCKER_CERT_PATH=/Users/benjixx/.docker/machine/machines/dev2\n```\n\ndocker-py 1.7.1 and 1.7.2 now raise the following exception:\n\n```\nDockerException: Error while fetching server API version: [Errno 1] _ssl.c:507: error:1407742E:SSL routines:SSL23_GET_SERVER_HELLO:tlsv1 alert protocol version\n```\n\nAny idea what's happening here?\n\n", "before_files": [{"content": "import os\n\nfrom . import errors\nfrom .ssladapter import ssladapter\n\n\nclass TLSConfig(object):\n    cert = None\n    ca_cert = None\n    verify = None\n    ssl_version = None\n\n    def __init__(self, client_cert=None, ca_cert=None, verify=None,\n                 ssl_version=None, assert_hostname=None,\n                 assert_fingerprint=None):\n        # Argument compatibility/mapping with\n        # https://docs.docker.com/engine/articles/https/\n        # This diverges from the Docker CLI in that users can specify 'tls'\n        # here, but also disable any public/default CA pool verification by\n        # leaving tls_verify=False\n\n        self.ssl_version = ssl_version\n        self.assert_hostname = assert_hostname\n        self.assert_fingerprint = assert_fingerprint\n\n        # \"tls\" and \"tls_verify\" must have both or neither cert/key files\n        # In either case, Alert the user when both are expected, but any are\n        # missing.\n\n        if client_cert:\n            try:\n                tls_cert, tls_key = client_cert\n            except ValueError:\n                raise errors.TLSParameterError(\n                    'client_config must be a tuple of'\n                    ' (client certificate, key file)'\n                )\n\n            if not (tls_cert and tls_key) or (not os.path.isfile(tls_cert) or\n               not os.path.isfile(tls_key)):\n                raise errors.TLSParameterError(\n                    'Path to a certificate and key files must be provided'\n                    ' through the client_config param'\n                )\n            self.cert = (tls_cert, tls_key)\n\n        # If verify is set, make sure the cert exists\n        self.verify = verify\n        self.ca_cert = ca_cert\n        if self.verify and self.ca_cert and not os.path.isfile(self.ca_cert):\n            raise errors.TLSParameterError(\n                'Invalid CA certificate provided for `tls_ca_cert`.'\n            )\n\n    def configure_client(self, client):\n        client.ssl_version = self.ssl_version\n\n        if self.verify and self.ca_cert:\n            client.verify = self.ca_cert\n        else:\n            client.verify = self.verify\n\n        if self.cert:\n            client.cert = self.cert\n\n        client.mount('https://', ssladapter.SSLAdapter(\n            ssl_version=self.ssl_version,\n            assert_hostname=self.assert_hostname,\n            assert_fingerprint=self.assert_fingerprint,\n        ))\n", "path": "docker/tls.py"}], "after_files": [{"content": "import os\nimport ssl\n\nfrom . import errors\nfrom .ssladapter import ssladapter\n\n\nclass TLSConfig(object):\n    cert = None\n    ca_cert = None\n    verify = None\n    ssl_version = None\n\n    def __init__(self, client_cert=None, ca_cert=None, verify=None,\n                 ssl_version=None, assert_hostname=None,\n                 assert_fingerprint=None):\n        # Argument compatibility/mapping with\n        # https://docs.docker.com/engine/articles/https/\n        # This diverges from the Docker CLI in that users can specify 'tls'\n        # here, but also disable any public/default CA pool verification by\n        # leaving tls_verify=False\n\n        self.assert_hostname = assert_hostname\n        self.assert_fingerprint = assert_fingerprint\n\n        # TLS v1.0 seems to be the safest default; SSLv23 fails in mysterious\n        # ways: https://github.com/docker/docker-py/issues/963\n\n        self.ssl_version = ssl_version or ssl.PROTOCOL_TLSv1\n\n        # \"tls\" and \"tls_verify\" must have both or neither cert/key files\n        # In either case, Alert the user when both are expected, but any are\n        # missing.\n\n        if client_cert:\n            try:\n                tls_cert, tls_key = client_cert\n            except ValueError:\n                raise errors.TLSParameterError(\n                    'client_config must be a tuple of'\n                    ' (client certificate, key file)'\n                )\n\n            if not (tls_cert and tls_key) or (not os.path.isfile(tls_cert) or\n               not os.path.isfile(tls_key)):\n                raise errors.TLSParameterError(\n                    'Path to a certificate and key files must be provided'\n                    ' through the client_config param'\n                )\n            self.cert = (tls_cert, tls_key)\n\n        # If verify is set, make sure the cert exists\n        self.verify = verify\n        self.ca_cert = ca_cert\n        if self.verify and self.ca_cert and not os.path.isfile(self.ca_cert):\n            raise errors.TLSParameterError(\n                'Invalid CA certificate provided for `tls_ca_cert`.'\n            )\n\n    def configure_client(self, client):\n        client.ssl_version = self.ssl_version\n\n        if self.verify and self.ca_cert:\n            client.verify = self.ca_cert\n        else:\n            client.verify = self.verify\n\n        if self.cert:\n            client.cert = self.cert\n\n        client.mount('https://', ssladapter.SSLAdapter(\n            ssl_version=self.ssl_version,\n            assert_hostname=self.assert_hostname,\n            assert_fingerprint=self.assert_fingerprint,\n        ))\n", "path": "docker/tls.py"}]}