Repository: googleapis/google-api-python-client

Issue:
errors.py: Add support for JSON content that has `errors` instead of `detail` or `details`
Thanks for stopping by to let us know something could be better!

**PLEASE READ**: If you have a support contract with Google, please create an issue in the [support console](https://cloud.google.com/support/) instead of filing on GitHub. This will ensure a timely response.

 **Is your feature request related to a problem? Please describe.**

We have been using [errors.py](https://github.com/googleapis/google-api-python-client/blob/master/googleapiclient/errors.py) to raise HttpError errors. Unfortunately, many of our instances have content that matches the following format:
```
{
  error: {
    errors: {
    }
  }
}
```
versus what [_get_reason](https://github.com/googleapis/google-api-python-client/blob/master/googleapiclient/errors.py#L64) is looking for i.e. only one of `detail`, `details`, or `message`
This results us seeing the errors being logged but not the details:

```
<HttpError 503 when requesting url returned "Internal error. Please try again.">
```

 **Describe the solution you'd like**

The solution involves modifying [_get_reason](https://github.com/googleapis/google-api-python-client/blob/master/googleapiclient/errors.py#L64) to also support `error_detail_keyword` with an additional value of `errors`. This modifies the order to: `detail`, `details`, `errors`, `message`

 **Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
 **Additional context**
Add any other context or screenshots about the feature request here.



Discussion:

Resolving patch:
diff --git a/googleapiclient/errors.py b/googleapiclient/errors.py
--- a/googleapiclient/errors.py
+++ b/googleapiclient/errors.py
@@ -61,7 +61,7 @@ def _get_reason(self):
                 data = self.content.decode("utf-8")
             if isinstance(data, dict):
                 reason = data["error"]["message"]
-                error_detail_keyword = next((kw for kw in ["detail", "details", "message"] if kw in data["error"]), "")
+                error_detail_keyword = next((kw for kw in ["detail", "details", "errors", "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:


Test patch:
diff --git a/tests/test_errors.py b/tests/test_errors.py
--- a/tests/test_errors.py
+++ b/tests/test_errors.py
@@ -141,5 +141,6 @@ def test_error_detail_for_missing_message_in_error(self):
             reason="Failed",
         )
         error = HttpError(resp, content)
-        self.assertEqual(str(error), '<HttpError 400 when requesting None returned "country is required". Details: "country is required">')
-        self.assertEqual(error.error_details, 'country is required')
+        expected_error_details = "[{'domain': 'global', 'reason': 'required', 'message': 'country is required', 'locationType': 'parameter', 'location': 'country'}]"
+        self.assertEqual(str(error), '<HttpError 400 when requesting None returned "country is required". Details: "%s">' % expected_error_details)
+        self.assertEqual(str(error.error_details), expected_error_details)
diff --git a/tests/test_http.py b/tests/test_http.py
--- a/tests/test_http.py
+++ b/tests/test_http.py
@@ -1587,7 +1587,7 @@ def test_execute_batch_http_error(self):
             "<HttpError 403 when requesting "
             "https://www.googleapis.com/someapi/v1/collection/?foo=bar returned "
             '"Access Not Configured". '
-            'Details: "Access Not Configured">'
+            "Details: \"[{'domain': 'usageLimits', 'reason': 'accessNotConfigured', 'message': 'Access Not Configured', 'debugInfo': 'QuotaState: BLOCKED'}]\">"
         )
         self.assertEqual(expected, str(callbacks.exceptions["2"]))