From 33adf142656bf283205445e7ce74e5b57ff5872e Mon Sep 17 00:00:00 2001 From: "Gavin M. Roy" Date: Tue, 14 Jun 2016 12:11:48 -0400 Subject: [PATCH 1/3] Handle gaierror and ConnectionError --- sprockets/clients/dynamodb/__init__.py | 2 +- sprockets/clients/dynamodb/connector.py | 3 +++ sprockets/clients/dynamodb/exceptions.py | 8 ++++++++ tests/api_tests.py | 16 ++++++++++++++++ 4 files changed, 28 insertions(+), 1 deletion(-) diff --git a/sprockets/clients/dynamodb/__init__.py b/sprockets/clients/dynamodb/__init__.py index 30a10bd..c53b607 100644 --- a/sprockets/clients/dynamodb/__init__.py +++ b/sprockets/clients/dynamodb/__init__.py @@ -4,7 +4,7 @@ except ImportError as error: def DynamoDB(*args, **kwargs): raise error -version_info = (0, 2, 1) +version_info = (0, 2, 2) __version__ = '.'.join(str(v) for v in version_info) # Response constants diff --git a/sprockets/clients/dynamodb/connector.py b/sprockets/clients/dynamodb/connector.py index 5a0882b..be3fedf 100644 --- a/sprockets/clients/dynamodb/connector.py +++ b/sprockets/clients/dynamodb/connector.py @@ -1,6 +1,7 @@ import json import logging import os +import socket from tornado import concurrent, httpclient, ioloop import tornado_aws @@ -126,6 +127,8 @@ class DynamoDB(object): future.set_exception(exceptions.NoCredentialsError(str(error))) except aws_exceptions.NoProfileError as error: future.set_exception(exceptions.NoProfileError(str(error))) + except (socket.gaierror, ConnectionError) as req_err: + future.set_exception(exceptions.RequestException(req_err)) except httpclient.HTTPError as err: if err.code == 599: future.set_exception(exceptions.TimeoutException()) diff --git a/sprockets/clients/dynamodb/exceptions.py b/sprockets/clients/dynamodb/exceptions.py index 976cf3f..7b8c1bb 100644 --- a/sprockets/clients/dynamodb/exceptions.py +++ b/sprockets/clients/dynamodb/exceptions.py @@ -17,6 +17,14 @@ class DynamoDBException(Exception): super(DynamoDBException, self).__init__(*args, **kwargs) +class RequestException(DynamoDBException): + """Raised when the HTTP request failed due to a network or DNS related + issue. + + """ + pass + + class ConditionalCheckFailedException(DynamoDBException): """A condition specified in the operation could not be evaluated.""" pass diff --git a/tests/api_tests.py b/tests/api_tests.py index d585aa7..930a60d 100644 --- a/tests/api_tests.py +++ b/tests/api_tests.py @@ -1,5 +1,6 @@ import datetime import os +import socket import uuid import mock @@ -103,6 +104,21 @@ class AWSClientTests(AsyncTestCase): with self.assertRaises(exceptions.DynamoDBException): yield self.client.create_table(self.generic_table_definition()) + @testing.gen_test + def test_gaierror_raises_request_exception(self): + with mock.patch('tornado_aws.client.AsyncAWSClient.fetch') as fetch: + fetch.side_effect = socket.gaierror + with self.assertRaises(exceptions.RequestException): + yield self.client.create_table(self.generic_table_definition()) + + + @testing.gen_test + def test_connection_error_request_exception(self): + with mock.patch('tornado_aws.client.AsyncAWSClient.fetch') as fetch: + fetch.side_effect = ConnectionError + with self.assertRaises(exceptions.RequestException): + yield self.client.create_table(self.generic_table_definition()) + class CreateTableTests(AsyncTestCase): From 1ab58a01beda76cf9d3d8015e69a1b8ea46418ab Mon Sep 17 00:00:00 2001 From: "Gavin M. Roy" Date: Tue, 14 Jun 2016 12:18:34 -0400 Subject: [PATCH 2/3] Insert an exception stub for Python 2.7 --- sprockets/clients/dynamodb/connector.py | 7 +++++++ tests/api_tests.py | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/sprockets/clients/dynamodb/connector.py b/sprockets/clients/dynamodb/connector.py index be3fedf..d3acf8b 100644 --- a/sprockets/clients/dynamodb/connector.py +++ b/sprockets/clients/dynamodb/connector.py @@ -10,6 +10,13 @@ from tornado_aws import exceptions as aws_exceptions from . import utils from . import exceptions +# Stub ConnectionError for Python 2.7 that doesn't support it +try: + ConnectionError +except NameError: + class ConnectionError(Exception): + pass + LOGGER = logging.getLogger(__name__) diff --git a/tests/api_tests.py b/tests/api_tests.py index 930a60d..4a5fb9a 100644 --- a/tests/api_tests.py +++ b/tests/api_tests.py @@ -13,6 +13,13 @@ from tornado_aws import exceptions as aws_exceptions from sprockets.clients import dynamodb from sprockets.clients.dynamodb import exceptions +# Stub ConnectionError for Python 2.7 that doesn't support it +try: + ConnectionError +except NameError: + class ConnectionError(Exception): + pass + class AsyncTestCase(testing.AsyncTestCase): From 26f4030438a06769af85ec5ff9fdcbc675dd4bb5 Mon Sep 17 00:00:00 2001 From: "Gavin M. Roy" Date: Tue, 14 Jun 2016 12:26:54 -0400 Subject: [PATCH 3/3] Skip the ConnectionError test in Python 2.7 --- tests/api_tests.py | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/tests/api_tests.py b/tests/api_tests.py index 4a5fb9a..1a90c8f 100644 --- a/tests/api_tests.py +++ b/tests/api_tests.py @@ -1,7 +1,9 @@ import datetime import os import socket +import sys import uuid +import unittest import mock @@ -11,14 +13,7 @@ from tornado import testing from tornado_aws import exceptions as aws_exceptions from sprockets.clients import dynamodb -from sprockets.clients.dynamodb import exceptions - -# Stub ConnectionError for Python 2.7 that doesn't support it -try: - ConnectionError -except NameError: - class ConnectionError(Exception): - pass +from sprockets.clients.dynamodb import connector, exceptions class AsyncTestCase(testing.AsyncTestCase): @@ -118,7 +113,8 @@ class AWSClientTests(AsyncTestCase): with self.assertRaises(exceptions.RequestException): yield self.client.create_table(self.generic_table_definition()) - + @unittest.skipIf(sys.version_info.major < 3, + 'ConnectionError is Python3 only') @testing.gen_test def test_connection_error_request_exception(self): with mock.patch('tornado_aws.client.AsyncAWSClient.fetch') as fetch: