diff --git a/google/cloud/storage/retry.py b/google/cloud/storage/retry.py index e17f3d5a0..7b9626ed5 100644 --- a/google/cloud/storage/retry.py +++ b/google/cloud/storage/retry.py @@ -21,7 +21,14 @@ import json -_RETRYABLE_TYPES = ( +# ConnectionError is a built-in exception only in Python3 and not in Python2. +try: + _RETRYABLE_STDLIB_TYPES = (ConnectionError,) +except NameError: + _RETRYABLE_STDLIB_TYPES = () + + +_RETRYABLE_TYPES = _RETRYABLE_STDLIB_TYPES + ( api_exceptions.TooManyRequests, # 429 api_exceptions.InternalServerError, # 500 api_exceptions.BadGateway, # 502 @@ -30,6 +37,7 @@ requests.ConnectionError, ) + # Some retriable errors don't have their own custom exception in api_core. _ADDITIONAL_RETRYABLE_STATUS_CODES = (408,) diff --git a/tests/unit/test_retry.py b/tests/unit/test_retry.py index 582fa8097..3111584cb 100644 --- a/tests/unit/test_retry.py +++ b/tests/unit/test_retry.py @@ -19,6 +19,14 @@ import mock +try: + ConnectionError +except NameError: + _HAS_STDLIB_CONNECTION_ERROR = False +else: + _HAS_STDLIB_CONNECTION_ERROR = True + + class Test_should_retry(unittest.TestCase): def _call_fut(self, exc): from google.cloud.storage import retry @@ -56,9 +64,22 @@ def test_w_google_api_call_error_miss(self): self.assertFalse(self._call_fut(exc)) def test_w_requests_connection_error(self): + import requests + + exc = requests.ConnectionError() + self.assertTrue(self._call_fut(exc)) + + def test_miss_w_stdlib_error(self): exc = ValueError("testing") self.assertFalse(self._call_fut(exc)) + @unittest.skipUnless( + _HAS_STDLIB_CONNECTION_ERROR, "No builtin 'ConnectionError' in Python 2", + ) + def test_w_stdlib_connection_error(self): + exc = ConnectionError() + self.assertTrue(self._call_fut(exc)) + class TestConditionalRetryPolicy(unittest.TestCase): def _make_one(self, retry_policy, conditional_predicate, required_kwargs):