Skip to content
This repository was archived by the owner on Aug 30, 2024. It is now read-only.

Commit 3995370

Browse files
authored
Merge pull request #209 from cloudant/65-improve-error-handling-message
Additional error details appended to HTTPError exception
2 parents 405ac98 + 0459212 commit 3995370

File tree

4 files changed

+48
-5
lines changed

4 files changed

+48
-5
lines changed

CHANGES.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
an ``adapter`` arg of a ``Replay429Adapter`` with the desired number of retries and initial backoff. To replicate
1616
the 2.0.0 behaviour use: ``adapter=Replay429Adapter(retries=10, initialBackoff=0.25)``. If ``retries`` or
1717
``initialBackoff`` are not specified they will default to 3 retries and a 0.25 s initial backoff.
18+
- [IMPROVED] Additional error reason details appended to HTTP response message errors.
1819
- [FIX] ``415 Client Error: Unsupported Media Type`` when using keys with ``db.all_docs``.
1920
- [FIX] Allowed strings as well as lists for search ``group_sort`` arguments.
2021

src/cloudant/_common_util.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,20 @@ def get_docs(r_session, url, encoder=None, headers=None, **params):
263263
resp.raise_for_status()
264264
return resp
265265

266+
#pylint: disable=unused-argument
267+
def append_response_error_content(response, **kwargs):
268+
"""
269+
Provides a helper to add HTTP response error and reason messages.
270+
"""
271+
try:
272+
if response.status_code >= 400 and response.json():
273+
reason = response.json().pop('reason', None)
274+
error = response.json().pop('error', None)
275+
response.reason += ' %s %s' % (error, reason)
276+
return response
277+
except ValueError:
278+
return
279+
266280
# Classes
267281

268282
class _Code(str):

src/cloudant/client.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@
2525
from .database import CloudantDatabase, CouchDatabase
2626
from .feed import Feed, InfiniteFeed
2727
from .error import CloudantException, CloudantArgumentError
28-
from ._common_util import USER_AGENT
28+
from ._common_util import USER_AGENT, append_response_error_content
29+
2930

3031
class CouchDB(dict):
3132
"""
@@ -75,6 +76,9 @@ def connect(self):
7576
self.r_session.auth = (self._user, self._auth_token)
7677
self.session_login(self._user, self._auth_token)
7778
self._client_session = self.session()
79+
# Utilize an event hook to append to the response message
80+
# using :func:`~cloudant.common_util.append_response_error_content`
81+
self.r_session.hooks['response'].append(append_response_error_content)
7882

7983
def disconnect(self):
8084
"""

tests/unit/document_tests.py

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -196,11 +196,13 @@ def test_create_existing_document(self):
196196
"""
197197
doc = Document(self.db, 'julia006')
198198
doc.create()
199-
try:
199+
with self.assertRaises(requests.HTTPError) as cm:
200200
doc.create()
201-
self.fail('Above statement should raise an Exception')
202-
except requests.HTTPError as err:
203-
self.assertEqual(err.response.status_code, 409)
201+
err = cm.exception
202+
self.assertEqual(
203+
err.response.status_code,
204+
409
205+
)
204206

205207
def test_fetch_document_without_docid(self):
206208
"""
@@ -240,6 +242,28 @@ def test_fetch_existing_document_with_docid(self):
240242
new_doc.fetch()
241243
self.assertEqual(new_doc, doc)
242244

245+
def test_appended_error_message_using_save_with_invalid_key(self):
246+
"""
247+
Test that saving a document with an invalid remote key will
248+
throw an HTTPError with additional error details from util
249+
method append_response_error_content.
250+
"""
251+
# First create the document
252+
doc = Document(self.db, 'julia006')
253+
# Add an invalid key and try to save document
254+
doc['_invalid_key'] = 'jules'
255+
with self.assertRaises(requests.HTTPError) as cm:
256+
doc.save()
257+
err = cm.exception
258+
self.assertEqual(
259+
str(err.response.reason),
260+
'Internal Server Error doc_validation Bad special document member: _invalid_key'
261+
)
262+
self.assertEqual(
263+
err.response.status_code,
264+
500
265+
)
266+
243267
def test_fetch_existing_document_with_docid_encoded_url(self):
244268
"""
245269
Test fetching document content from an existing document where the

0 commit comments

Comments
 (0)