Skip to content

Commit

Permalink
Raise a unique exception if an error has no JSON (#102)
Browse files Browse the repository at this point in the history
  • Loading branch information
brettcannon committed Mar 17, 2020
1 parent 9bd6eb7 commit 860ccb2
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 1 deletion.
12 changes: 12 additions & 0 deletions docs/__init__.rst
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,18 @@ Exceptions
Inherits from :exc:`HTTPException`.


.. exception:: BadRequestUnknownError

Exception for ``422`` status code responses which do not include a JSON
response.

.. versionadded:: XXX

.. attribute:: response

The response as returned by GitHub.


.. exception:: RateLimitExceeded(rate_limit)

Raised when one's rate limit has been reached. A subclass of
Expand Down
2 changes: 2 additions & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ Changelog
.. note::
Under development

- Add :exc:`gidgethub.BadRequestUnknownError` when something other than JSON is
returned for a 422 response.
- Remove `gidgethub.treq`; tests were not passing and a request for help on
Twitter came back with no reponse (happy to add back if someone steps forward
to help out).
Expand Down
9 changes: 9 additions & 0 deletions gidgethub/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,15 @@ class BadRequest(HTTPException):
# https://developer.github.com/v3/#client-errors


class BadRequestUnknownError(BadRequest):

"""A bad request whose response body is not JSON."""

def __init__(self, response: str) -> None:
self.response = response
super().__init__(http.HTTPStatus.UNPROCESSABLE_ENTITY)


class RateLimitExceeded(BadRequest):

"""Request rejected due to the rate limit being exceeded."""
Expand Down
7 changes: 6 additions & 1 deletion gidgethub/sansio.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

from . import (
BadRequest,
BadRequestUnknownError,
GitHubBroken,
HTTPException,
InvalidField,
Expand Down Expand Up @@ -329,7 +330,11 @@ def decipher_response(
if rate_limit and not rate_limit.remaining:
raise RateLimitExceeded(rate_limit, message)
elif status_code == 422:
errors = data.get("errors", None)
try:
errors = data.get("errors", None)
except AttributeError:
# Not JSON so don't know why the request failed.
raise BadRequestUnknownError(data)
exc_type = InvalidField
if errors:
if any(
Expand Down
7 changes: 7 additions & 0 deletions tests/test_exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from gidgethub import (
BadRequest,
BadRequestUnknownError,
GitHubBroken,
HTTPException,
InvalidField,
Expand Down Expand Up @@ -36,6 +37,12 @@ def test_BadRequest():
assert exc.status_code == http.HTTPStatus.BAD_REQUEST


def test_BadRequestUnknownError():
exc = BadRequestUnknownError("uh-oh")
assert exc.status_code == http.HTTPStatus.UNPROCESSABLE_ENTITY
assert exc.response == "uh-oh"


def test_RateLimitExceeded():
rate = sansio.RateLimit(limit=1, remaining=0, reset_epoch=1)
exc = RateLimitExceeded(rate)
Expand Down
12 changes: 12 additions & 0 deletions tests/test_sansio.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

from gidgethub import (
BadRequest,
BadRequestUnknownError,
GitHubBroken,
HTTPException,
InvalidField,
Expand Down Expand Up @@ -376,6 +377,17 @@ def test_422_no_errors_object(self):
assert exc_info.value.status_code == http.HTTPStatus(status_code)
assert str(exc_info.value) == "Reference does not exist"

def test_422_html_response(self):
# https://github.com/brettcannon/gidgethub/issues/81
status_code = 422
body = "<html><body>Mistakes were made ...</body></html>"
encoded_body = body.encode("utf-8")
headers = {"content-type": "text/html; charset=utf-8"}
with pytest.raises(BadRequestUnknownError) as exc_info:
sansio.decipher_response(status_code, headers, encoded_body)
assert exc_info.value.status_code == http.HTTPStatus(status_code)
assert exc_info.value.response == body

def test_3XX(self):
status_code = 301
with pytest.raises(RedirectionException) as exc_info:
Expand Down

0 comments on commit 860ccb2

Please sign in to comment.