summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGiuseppe Lavagetto <lavagetto@gmail.com>2015-02-22 11:52:59 +0100
committerGiuseppe Lavagetto <lavagetto@gmail.com>2015-02-22 11:52:59 +0100
commitce3e8f0fa3f4802afebba7990260e07f5b8f0e4e (patch)
treed87bf31cd95626d773ca6726bc1dfd00f52a8908 /src
parent2cfb11a75f6605b87da3f01b79a8ee2d0d632662 (diff)
parent31d5257a491cf9f7f19a9420a75e4b141007b8ca (diff)
Merge branch 'shakim-enhance-exception-information'
Diffstat (limited to 'src')
-rw-r--r--src/etcd/__init__.py58
-rw-r--r--src/etcd/client.py2
-rw-r--r--src/etcd/tests/integration/test_election.py2
-rw-r--r--src/etcd/tests/integration/test_simple.py11
-rw-r--r--src/etcd/tests/unit/test_old_request.py10
-rw-r--r--src/etcd/tests/unit/test_request.py2
6 files changed, 65 insertions, 20 deletions
diff --git a/src/etcd/__init__.py b/src/etcd/__init__.py
index 600a60c..9da1049 100644
--- a/src/etcd/__init__.py
+++ b/src/etcd/__init__.py
@@ -105,19 +105,56 @@ class EtcdException(Exception):
"""
Generic Etcd Exception.
"""
+ def __init__(self, message=None, payload=None):
+ super(Exception, self).__init__(message)
+ self.payload=payload
+
+class EtcdKeyError(EtcdException):
+ """
+ Etcd Generic KeyError Exception
+ """
+ pass
+
+class EtcdKeyNotFound(EtcdKeyError):
+ """
+ Etcd key not found exception (100)
+ """
+ pass
+
+class EtcdNotFile(EtcdKeyError):
+ """
+ Etcd not a file exception (102)
+ """
pass
+class EtcdNotDir(EtcdKeyError):
+ """
+ Etcd not a directory exception (104)
+ """
+ pass
+
+class EtcdAlreadyExist(EtcdKeyError):
+ """
+ Etcd already exist exception (105)
+ """
+ pass
+
+class EtcdEventIndexCleared(EtcdException):
+ """
+ Etcd event index is outdated and cleared exception (401)
+ """
+ pass
class EtcdError(object):
# See https://github.com/coreos/etcd/blob/master/Documentation/errorcode.md
error_exceptions = {
- 100: KeyError,
+ 100: EtcdKeyNotFound,
101: ValueError,
- 102: KeyError,
+ 102: EtcdNotFile,
103: Exception,
- 104: KeyError,
- 105: KeyError,
+ 104: EtcdNotDir,
+ 105: EtcdAlreadyExist,
106: KeyError,
200: ValueError,
201: ValueError,
@@ -126,7 +163,7 @@ class EtcdError(object):
300: Exception,
301: Exception,
400: Exception,
- 401: EtcdException,
+ 401: EtcdEventIndexCleared,
500: EtcdException
}
@@ -134,12 +171,19 @@ class EtcdError(object):
def handle(cls, errorCode=None, message=None, cause=None, **kwdargs):
""" Decodes the error and throws the appropriate error message"""
try:
- msg = "{} : {}".format(message, cause)
+ msg = '{} : {}'.format(message, cause)
+ payload={'errorCode': errorCode, 'message': message, 'cause': cause}
+ if len(kwdargs) > 0:
+ for key in kwdargs:
+ payload[key]=kwdargs[key]
exc = cls.error_exceptions[errorCode]
except:
msg = "Unable to decode server response"
exc = EtcdException
- raise exc(msg)
+ if exc in [EtcdException, EtcdKeyNotFound, EtcdNotFile, EtcdNotDir, EtcdAlreadyExist, EtcdEventIndexCleared]:
+ raise exc(msg, payload)
+ else:
+ raise exc(msg)
# Attempt to enable urllib3's SNI support, if possible
diff --git a/src/etcd/client.py b/src/etcd/client.py
index 271d85e..516e335 100644
--- a/src/etcd/client.py
+++ b/src/etcd/client.py
@@ -202,7 +202,7 @@ class Client(object):
try:
self.get(key)
return True
- except KeyError:
+ except etcd.EtcdKeyNotFound:
return False
def _sanitize_key(self, key):
diff --git a/src/etcd/tests/integration/test_election.py b/src/etcd/tests/integration/test_election.py
index 76f397b..46ea2bb 100644
--- a/src/etcd/tests/integration/test_election.py
+++ b/src/etcd/tests/integration/test_election.py
@@ -31,4 +31,4 @@ class TestElection(test_simple.EtcdIntegrationTest):
e.set('/mysql', name='foo', ttl=1)
time.sleep(2)
self.assertRaises(etcd.EtcdException, e.get, '/mysql')
- self.assertRaises(KeyError, e.delete, '/mysql', name='foo')
+ self.assertRaises(etcd.EtcdKeyNotFound, e.delete, '/mysql', name='foo')
diff --git a/src/etcd/tests/integration/test_simple.py b/src/etcd/tests/integration/test_simple.py
index 50530e9..9283cc5 100644
--- a/src/etcd/tests/integration/test_simple.py
+++ b/src/etcd/tests/integration/test_simple.py
@@ -74,7 +74,7 @@ class TestSimple(EtcdIntegrationTest):
try:
get_result = self.client.get('/test_set')
assert False
- except KeyError as e:
+ except etcd.EtcdKeyNotFound as e:
pass
self.assertFalse('/test_set' in self.client)
@@ -100,7 +100,7 @@ class TestSimple(EtcdIntegrationTest):
try:
get_result = self.client.get('/test_set')
assert False
- except KeyError as e:
+ except etcd.EtcdKeyNotFound as e:
pass
def test_update(self):
@@ -120,7 +120,7 @@ class TestSimple(EtcdIntegrationTest):
set_result = self.client.write('/subtree/test_set2', 'test-key3')
get_result = self.client.read('/subtree', recursive=True)
result = [subkey.value for subkey in get_result.leaves]
- self.assertEquals(['test-key1', 'test-key2', 'test-key3'], result)
+ self.assertEquals(['test-key1', 'test-key2', 'test-key3'].sort(), result.sort())
def test_directory_ttl_update(self):
""" INTEGRATION: should be able to update a dir TTL """
@@ -140,7 +140,7 @@ class TestErrors(EtcdIntegrationTest):
""" INTEGRATION: try to write value to an existing directory """
self.client.set('/directory/test-key', 'test-value')
- self.assertRaises(KeyError, self.client.set, '/directory', 'test-value')
+ self.assertRaises(etcd.EtcdNotFile, self.client.set, '/directory', 'test-value')
def test_test_and_set(self):
""" INTEGRATION: try test_and_set operation """
@@ -159,7 +159,8 @@ class TestErrors(EtcdIntegrationTest):
`prevExist=True` should fail """
self.client.write('/mydir', None, dir=True)
- self.assertRaises(KeyError, self.client.write, '/mydir', None, dir=True)
+ self.assertRaises(etcd.EtcdNotFile, self.client.write, '/mydir', None, dir=True)
+ self.assertRaises(etcd.EtcdAlreadyExist, self.client.write, '/mydir', None, dir=True, prevExist=False)
class TestClusterFunctions(EtcdIntegrationTest):
diff --git a/src/etcd/tests/unit/test_old_request.py b/src/etcd/tests/unit/test_old_request.py
index e449b7d..9367ebd 100644
--- a/src/etcd/tests/unit/test_old_request.py
+++ b/src/etcd/tests/unit/test_old_request.py
@@ -171,7 +171,7 @@ class TestClientRequest(unittest.TestCase):
def test_not_in(self):
""" Can check if key is not in client """
client = etcd.Client()
- client.get = mock.Mock(side_effect=KeyError())
+ client.get = mock.Mock(side_effect=etcd.EtcdKeyNotFound())
result = '/testkey' not in client
self.assertEquals(True, result)
@@ -307,8 +307,8 @@ class TestClientApiExecutor(unittest.TestCase):
try:
client.api_execute('/v2/keys/testkey', client._MGET)
assert False
- except KeyError as e:
- self.assertEquals(str(e), "'message : cause'")
+ except etcd.EtcdKeyNotFound as e:
+ self.assertEquals(str(e), 'message : cause')
def test_put(self):
""" http put request """
@@ -357,8 +357,8 @@ class TestClientApiExecutor(unittest.TestCase):
try:
client.api_execute('/v2/keys/testkey', client._MPUT, payload)
self.fail()
- except KeyError as e:
- self.assertEquals("'message : cause'", str(e))
+ except etcd.EtcdNotFile as e:
+ self.assertEquals('message : cause', str(e))
def test_get_error_unknown(self):
""" http get error request unknown """
diff --git a/src/etcd/tests/unit/test_request.py b/src/etcd/tests/unit/test_request.py
index 7103fa1..df1ae57 100644
--- a/src/etcd/tests/unit/test_request.py
+++ b/src/etcd/tests/unit/test_request.py
@@ -282,7 +282,7 @@ class TestClientApiInterface(TestClientApiBase):
def test_not_in(self):
""" Can check if key is not in client """
- self._mock_exception(KeyError, 'Key not Found : /testKey')
+ self._mock_exception(etcd.EtcdKeyNotFound, 'Key not Found : /testKey')
self.assertTrue('/testey' not in self.client)
def test_in(self):