8000 Add HTTPResponseError to expose underlying http error codes and causes. by mikeybtn · Pull Request #30 · button/button-client-python · GitHub
[go: up one dir, main page]

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Current Version
-
2.6.0 May 17, 2018
- Added `HTTPResponseError`

2.5.0 December 5, 2017
- Add links resource
Expand Down
16 changes: 9 additions & 7 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -37,28 +37,30 @@ key <https://app.usebutton.com/settings/organization>`__.
client = Client('sk-XXX')

The client will always attempt to raise a ``pybutton.ButtonClientError``
in an error condition.
or a subclass in an error condition.

All API requests will return a ``pybutton.response.Response`` instance,
which supports accessing data via the `#data` method. For instance:

.. code:: python

from pybutton import Client
from pybutton import ButtonClientError
from pybutton import ButtonClientError, HTTPResponseError

client = Client("sk-XXX")

try:
response = client.orders.get("btnorder-XXX")
except HTTPResponseError as e:
print('API request failed: http status {}'.format(e.status_code))
except ButtonClientError as e:
print(e)
else:
print(response)
# <class pybutton.Response status: open, btn_ref: None, line_items: [], ...>

print(response)
# <class pybutton.Response status: open, btn_ref: None, line_items: [], ...>

print(response.data())
# {'status': open, 'btn_ref': None, 'line_items': [], ...}
print(response.data())
# {'status': open, 'btn_ref': None, 'line_items': [], ...}


Configuration
Expand Down
15 changes: 15 additions & 0 deletions pybutton/error.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,18 @@
class ButtonClientError(Exception):
'''An Exception class for all pybutton understood errors.
'''


class HTTPResponseError(ButtonClientError):
'''A non-success HTTP response was returned from the remote API.

The HTTP response status code can be retrieved from the
`.status_code` property.

The original error object can be retrieved from the
`.cause` property.
'''
def __init__(self, message, status_code, cause):
super(HTTPResponseError, self).__init__(message)
self.status_code = status_code
self.cause = cause
5 changes: 3 additions & 2 deletions pybutton/resources/resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import json

from pybutton.response import Response
from pybutton.error import ButtonClientError
from pybutton.error import HTTPResponseError
from pybutton.version import VERSION
from pybutton.request import request
from pybutton.request import request_url
Expand Down Expand Up @@ -38,6 +38,7 @@ class Resource(object):

Raises:
pybutton.ButtonClientError
pybutton.HTTPResponseError

'''

Expand Down Expand Up @@ -151,4 +152,4 @@ def _api_request(self, path, method, data=None, query=None):

error = json.loads(data).get('error', {})
message = error.get('message', fallback)
raise ButtonClientError(message)
raise HTTPResponseError(message, status_code=e.code, cause=e)
6 changes: 4 additions & 2 deletions pybutton/test/request_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,10 @@ def test_raises_with_invalid_response_data(self, MockRequest,
try:
request(url, method, headers)
self.assertTrue(False)
except ButtonClientError:
pass
except ButtonClientError as e:
# We expect the generic ButtonClientError, and not a subclass,
# in this condition.
assert type(e) is ButtonClientError


class RequestTestCasePy3(TestCase):
Expand Down
10 changes: 7 additions & 3 deletions pybutton/test/resources/resource_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

from pybutton.request import HTTPError
from pybutton.resources.resource import Resource
from pybutton.error import ButtonClientError
from pybutton.error import HTTPResponseError

config = {
'hostname': 'api.usebutton.com',
Expand Down Expand Up @@ -117,8 +117,10 @@ def side_effect(*args):
try:
resource._api_request('/v2/api', 'GET', data)
self.assertTrue(False)
except ButtonClientError as e:
except HTTPResponseError as e:
self.assertEqual(str(e), '404 bloop')
self.assertEqual(e.status_code, 404)
self.assertTrue(e.cause is not None)

@patch('pybutton.resources.resource.request')
def test_api_request_with_byte_response(self, request):
Expand All @@ -138,8 +140,10 @@ def side_effect(*args):
try:
resource._api_request('/v2/api', 'GET', data)
self.assertTrue(False)
except ButtonClientError as e:
except HTTPResponseError as e:
self.assertEqual(str(e), 'bloop failed')
self.assertEqual(e.status_code, 404)
self.assertTrue(e.cause is not None)

@patch('pybutton.resources.resource.request')
def test_api_get(self, request):
Expand Down
2 changes: 1 addition & 1 deletion pybutton/version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
VERSION = '2.5.0'
VERSION = '2.6.0'
0