diff --git a/AUTHORS.rst b/AUTHORS.rst index 6bbddfde..99639230 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -121,3 +121,4 @@ Patches and Suggestions - Vinod Chandru - Johnny Goodnow - Denis Ryzhkov +- Wilfred Hughes @dontYetKnow diff --git a/requests/adapters.py b/requests/adapters.py index 6f507da8..c38cd080 100644 --- a/requests/adapters.py +++ b/requests/adapters.py @@ -45,7 +45,6 @@ class BaseAdapter(object): class HTTPAdapter(BaseAdapter): """Built-In HTTP Adapter for Urllib3.""" def __init__(self, pool_connections=DEFAULT_POOLSIZE, pool_maxsize=DEFAULT_POOLSIZE): - self.max_retries = DEFAULT_RETRIES self.config = {} super(HTTPAdapter, self).__init__() @@ -166,7 +165,7 @@ class HTTPAdapter(BaseAdapter): request.headers['Proxy-Authorization'] = _basic_auth_str(username, password) - def send(self, request, stream=False, timeout=None, verify=True, cert=None, proxies=None): + def send(self, request, stream=False, timeout=None, max_retries=DEFAULT_RETRIES, verify=True, cert=None, proxies=None): """Sends PreparedRequest object. Returns Response object.""" conn = self.get_connection(request.url, proxies) @@ -188,7 +187,7 @@ class HTTPAdapter(BaseAdapter): assert_same_host=False, preload_content=False, decode_content=False, - retries=self.max_retries, + retries=max_retries, timeout=timeout ) diff --git a/requests/api.py b/requests/api.py index baf43dd6..d0023807 100644 --- a/requests/api.py +++ b/requests/api.py @@ -27,6 +27,7 @@ def request(method, url, **kwargs): :param files: (optional) Dictionary of 'name': file-like-objects (or {'name': ('filename', fileobj)}) for multipart encoding upload. :param auth: (optional) Auth tuple to enable Basic/Digest/Custom HTTP Auth. :param timeout: (optional) Float describing the timeout of the request. + :param max_retries: (optional) The maximum number of retries (defaults to 0). :param allow_redirects: (optional) Boolean. Set to True if POST/PUT/DELETE redirect following is allowed. :param proxies: (optional) Dictionary mapping protocol to the URL of the proxy. :param verify: (optional) if ``True``, the SSL cert will be verified. A CA_BUNDLE path can also be provided. diff --git a/requests/sessions.py b/requests/sessions.py index 615075a3..73862991 100644 --- a/requests/sessions.py +++ b/requests/sessions.py @@ -80,7 +80,7 @@ def merge_kwargs(local_kwarg, default_kwarg): class SessionRedirectMixin(object): def resolve_redirects(self, resp, req, stream=False, timeout=None, - verify=True, cert=None, proxies=None): + max_retries=0, verify=True, cert=None, proxies=None): """Receives a Response. Returns a generator of Responses.""" i = 0 @@ -149,6 +149,7 @@ class SessionRedirectMixin(object): prepared_request, stream=stream, timeout=timeout, + max_retries=max_retries, verify=verify, cert=cert, proxies=proxies, @@ -237,6 +238,7 @@ class Session(SessionRedirectMixin): files=None, auth=None, timeout=None, + max_retries=0, allow_redirects=True, proxies=None, hooks=None, @@ -304,6 +306,7 @@ class Session(SessionRedirectMixin): send_kwargs = { 'stream': stream, 'timeout': timeout, + 'max_retries': max_retries, 'verify': verify, 'cert': cert, 'proxies': proxies, @@ -399,6 +402,7 @@ class Session(SessionRedirectMixin): req = kwargs.pop('req', None) stream = kwargs.get('stream', False) timeout = kwargs.get('timeout') + max_retries = kwargs.get('max_retries') verify = kwargs.get('verify') cert = kwargs.get('cert') proxies = kwargs.get('proxies') @@ -419,7 +423,8 @@ class Session(SessionRedirectMixin): # Redirect resolving generator. gen = self.resolve_redirects(r, request, stream=stream, - timeout=timeout, verify=verify, cert=cert, + timeout=timeout, max_retries=max_retries, + verify=verify, cert=cert, proxies=proxies) # Resolve redirects if allowed. diff --git a/test_requests.py b/test_requests.py index e12722d1..51719e67 100644 --- a/test_requests.py +++ b/test_requests.py @@ -354,5 +354,26 @@ class RequestsTestCase(unittest.TestCase): r = requests.Request(url=HTTPBIN) self.assertRaises(ValueError, requests.Session().send, r) + def test_can_specify_retries(self): + # monkey patch urlopen + from requests.packages.urllib3.poolmanager import HTTPConnectionPool + old_urlopen = HTTPConnectionPool.urlopen + + max_retries_used = [] + def urlopen(*args, **kwargs): + """Save what value we used for retries each time we call urlopen.""" + max_retries_used.append(kwargs.get('retries')) + return old_urlopen(*args, **kwargs) + + HTTPConnectionPool.urlopen = urlopen + + # do the request and check that max_retries was passed through + requests.get(httpbin('get'), max_retries=5) + self.assertEqual(max_retries_used, [5]) + + # undo monkey patch + HTTPConnectionPool.urlopen = old_urlopen + + if __name__ == '__main__': unittest.main()