From a341c5a5e31ba16da109658127b58cb7e5dbeedd Mon Sep 17 00:00:00 2001 From: Muad Mohamed Date: Sun, 8 Nov 2020 20:30:02 +0000 Subject: [PATCH] docs: Change error parsing to check for 'message' (#1083) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Thank you for opening a Pull Request! Before submitting your PR, there are a few things you can do to make sure it goes smoothly: - [x] Make sure to open an issue as a [bug/issue](https://github.com/googleapis/google-api-python-client/issues/new/choose) before writing your code! That way we can discuss the change, evaluate designs, and agree on the general idea - [x] Ensure the tests and linter pass - [x] Code coverage does not decrease (if any source code was changed) - [x] Appropriate docs were updated (if necessary) Fixes #1082 🦕 --- docs/start.md | 5 ++++- googleapiclient/errors.py | 7 +++---- tests/test_errors.py | 29 +++++++++++++++++++++++++++++ tests/test_http.py | 3 ++- 4 files changed, 38 insertions(+), 6 deletions(-) diff --git a/docs/start.md b/docs/start.md index ceac5dd3364..5efdcade1f0 100644 --- a/docs/start.md +++ b/docs/start.md @@ -94,7 +94,10 @@ request = collection.list(cents=5) Creating a request does not actually call the API. To execute the request and get a response, call the `execute()` function: ```python -response = request.execute() +try: + response = request.execute() +except HttpError as e: + print('Error response status code : {0}, reason : {1}'.format(e.resp.status, e.error_details)) ``` Alternatively, you can combine previous steps on a single line: diff --git a/googleapiclient/errors.py b/googleapiclient/errors.py index 2f7b112f0d8..c9e884e58e1 100644 --- a/googleapiclient/errors.py +++ b/googleapiclient/errors.py @@ -51,10 +51,9 @@ def _get_reason(self): data = json.loads(self.content.decode("utf-8")) if isinstance(data, dict): reason = data["error"]["message"] - if "details" in data["error"]: - self.error_details = data["error"]["details"] - elif "detail" in data["error"]: - self.error_details = data["error"]["detail"] + error_detail_keyword = next((kw for kw in ["detail", "details", "message"] if kw in data["error"]), "") + if error_detail_keyword: + self.error_details = data["error"][error_detail_keyword] elif isinstance(data, list) and len(data) > 0: first_error = data[0] reason = first_error["error"]["message"] diff --git a/tests/test_errors.py b/tests/test_errors.py index b0d1e43d26b..8b99532b1dd 100644 --- a/tests/test_errors.py +++ b/tests/test_errors.py @@ -47,6 +47,24 @@ } """ +JSON_ERROR_CONTENT_NO_DETAIL = b""" +{ + "error": { + "errors": [ + { + "domain": "global", + "reason": "required", + "message": "country is required", + "locationType": "parameter", + "location": "country" + } + ], + "code": 400, + "message": "country is required" + } +} +""" + def fake_response(data, headers, reason="Ok"): response = httplib2.Response(headers) @@ -112,3 +130,14 @@ def test_missing_reason(self): resp, content = fake_response(b"}NOT OK", {"status": "400"}, reason=None) error = HttpError(resp, content) self.assertEqual(str(error), '') + + def test_error_detail_for_missing_message_in_error(self): + """Test handling of data with missing 'details' or 'detail' element.""" + resp, content = fake_response( + JSON_ERROR_CONTENT_NO_DETAIL, + {"status": "400", "content-type": "application/json"}, + reason="Failed", + ) + error = HttpError(resp, content) + self.assertEqual(str(error), '') + self.assertEqual(error.error_details, 'country is required') diff --git a/tests/test_http.py b/tests/test_http.py index 00db06eee39..5293a6a3bfc 100644 --- a/tests/test_http.py +++ b/tests/test_http.py @@ -1567,7 +1567,8 @@ def test_execute_batch_http_error(self): expected = ( "' + '"Access Not Configured". ' + 'Details: "Access Not Configured">' ) self.assertEqual(expected, str(callbacks.exceptions["2"]))