From f5a473edfc03bebcd429766f76299bc9e132250c Mon Sep 17 00:00:00 2001
From: Monty Taylor <mordred@inaugust.com>
Date: Sun, 29 Mar 2015 01:38:16 -0400
Subject: [PATCH] Add socket-level read timeout parameter

The underlying requests library supports a timeout input parameter. The
other python-*client libraries support passing it in, so while working
on shade, it seemed like a great idea to be able to pass in timeout to
swiftclient too. For reference, there's a change in shade:
I095c1240693abf024bda2315dd77f4400b24a45b that shows interaction with
the other libs, and a tentative patch that would consume this one.

Change-Id: I699ebb1e092aa010af678de7ba15712da6ed5315
---
 swiftclient/client.py          | 13 ++++++++++---
 tests/unit/test_swiftclient.py |  3 ++-
 tests/unit/utils.py            |  2 +-
 3 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/swiftclient/client.py b/swiftclient/client.py
index 0c6d8d34..11725f81 100644
--- a/swiftclient/client.py
+++ b/swiftclient/client.py
@@ -140,7 +140,8 @@ def encode_meta_headers(headers):
 
 class HTTPConnection(object):
     def __init__(self, url, proxy=None, cacert=None, insecure=False,
-                 ssl_compression=False, default_user_agent=None):
+                 ssl_compression=False, default_user_agent=None,
+                 timeout=None):
         """
         Make an HTTPConnection or HTTPSConnection
 
@@ -160,6 +161,8 @@ class HTTPConnection(object):
                                    may be overridden on a per-request basis by
                                    explicitly setting the user-agent header on
                                    a call to request().
+        :param timeout: socket read timeout value, passed directly to
+                        the requests library.
         :raises ClientException: Unable to handle protocol scheme
         """
         self.url = url
@@ -189,6 +192,8 @@ class HTTPConnection(object):
             default_user_agent = \
                 'python-swiftclient-%s' % swiftclient_version.version_string
         self.default_user_agent = default_user_agent
+        if timeout:
+            self.requests_args['timeout'] = timeout
 
     def _request(self, *arg, **kwarg):
         """ Final wrapper before requests call, to be patched in tests """
@@ -1154,7 +1159,7 @@ class Connection(object):
                  starting_backoff=1, max_backoff=64, tenant_name=None,
                  os_options=None, auth_version="1", cacert=None,
                  insecure=False, ssl_compression=True,
-                 retry_on_ratelimit=False):
+                 retry_on_ratelimit=False, timeout=None):
         """
         :param authurl: authentication URL
         :param user: user name to authenticate as
@@ -1207,6 +1212,7 @@ class Connection(object):
         self.ssl_compression = ssl_compression
         self.auth_end_time = 0
         self.retry_on_ratelimit = retry_on_ratelimit
+        self.timeout = timeout
 
     def close(self):
         if (self.http_conn and isinstance(self.http_conn, tuple)
@@ -1230,7 +1236,8 @@ class Connection(object):
         return http_connection(url if url else self.url,
                                cacert=self.cacert,
                                insecure=self.insecure,
-                               ssl_compression=self.ssl_compression)
+                               ssl_compression=self.ssl_compression,
+                               timeout=self.timeout)
 
     def _add_response_dict(self, target_dict, kwargs):
         if target_dict is not None and 'response_dict' in kwargs:
diff --git a/tests/unit/test_swiftclient.py b/tests/unit/test_swiftclient.py
index d1990506..9737520c 100644
--- a/tests/unit/test_swiftclient.py
+++ b/tests/unit/test_swiftclient.py
@@ -1441,7 +1441,8 @@ class TestConnection(MockHttpTest):
                 return ''
 
         def local_http_connection(url, proxy=None, cacert=None,
-                                  insecure=False, ssl_compression=True):
+                                  insecure=False, ssl_compression=True,
+                                  timeout=None):
             parsed = urlparse(url)
             return parsed, LocalConnection()
 
diff --git a/tests/unit/utils.py b/tests/unit/utils.py
index 3e87ea28..4958c131 100644
--- a/tests/unit/utils.py
+++ b/tests/unit/utils.py
@@ -220,7 +220,7 @@ class MockHttpTest(testtools.TestCase):
             on_request = kwargs.get('on_request')
 
             def wrapper(url, proxy=None, cacert=None, insecure=False,
-                        ssl_compression=True):
+                        ssl_compression=True, timeout=None):
                 if storage_url:
                     self.assertEqual(storage_url, url)