diff --git a/requests/exceptions.py b/requests/exceptions.py index 79697635a5..06b9ebe4b0 100644 --- a/requests/exceptions.py +++ b/requests/exceptions.py @@ -34,6 +34,16 @@ class InvalidJSONError(RequestException): class JSONDecodeError(InvalidJSONError, CompatJSONDecodeError): """Couldn't decode the text into json""" + def __init__(self, *args, **kwargs): + """ + Construct the JSONDecodeError instance first with all + args. Then use it's args to construct the IOError so that + the json specific args aren't used as IOError specific args + and the error message from JSONDecodeError is preserved. + """ + CompatJSONDecodeError.__init__(self, *args) + InvalidJSONError.__init__(self, *self.args, **kwargs) + class HTTPError(RequestException): """An HTTP error occurred.""" diff --git a/tests/test_requests.py b/tests/test_requests.py index 29b3aca84e..328da4bd43 100644 --- a/tests/test_requests.py +++ b/tests/test_requests.py @@ -23,14 +23,14 @@ cookiejar_from_dict, morsel_to_cookie) from requests.exceptions import ( ConnectionError, ConnectTimeout, InvalidSchema, InvalidURL, - MissingSchema, ReadTimeout, Timeout, RetryError, TooManyRedirects, + MissingSchema, ReadTimeout, Timeout, RetryError, RequestException, TooManyRedirects, ProxyError, InvalidHeader, UnrewindableBodyError, SSLError, InvalidProxyURL, InvalidJSONError) from requests.models import PreparedRequest from requests.structures import CaseInsensitiveDict from requests.sessions import SessionRedirectMixin from requests.models import urlencode from requests.hooks import default_hooks -from requests.compat import MutableMapping +from requests.compat import JSONDecodeError, is_py3, MutableMapping from .compat import StringIO, u from .utils import override_environ @@ -2585,5 +2585,15 @@ def test_post_json_nan(self, httpbin): def test_json_decode_compatibility(self, httpbin): r = requests.get(httpbin('bytes/20')) - with pytest.raises(requests.exceptions.JSONDecodeError): + with pytest.raises(requests.exceptions.JSONDecodeError) as excinfo: r.json() + assert isinstance(excinfo.value, RequestException) + assert isinstance(excinfo.value, JSONDecodeError) + assert r.text not in str(excinfo.value) + + @pytest.mark.skipif(not is_py3, reason="doc attribute is only present on py3") + def test_json_decode_persists_doc_attr(self, httpbin): + r = requests.get(httpbin('bytes/20')) + with pytest.raises(requests.exceptions.JSONDecodeError) as excinfo: + r.json() + assert excinfo.value.doc == r.text