+# Copyright (C) The Arvados Authors. All rights reserved.
+#
+# SPDX-License-Identifier: Apache-2.0
+
# errors.py - Arvados-specific exceptions.
import json
-import requests
from apiclient import errors as apiclient_errors
from collections import OrderedDict
class ApiError(apiclient_errors.HttpError):
def _get_reason(self):
try:
- return '; '.join(json.loads(self.content)['errors'])
+ return '; '.join(json.loads(self.content.decode('utf-8'))['errors'])
except (KeyError, TypeError, ValueError):
return super(ApiError, self)._get_reason()
class KeepRequestError(Exception):
"""Base class for errors accessing Keep services."""
- def __init__(self, message='', service_errors=()):
- """KeepRequestError(message='', service_errors=())
+ def __init__(self, message='', request_errors=(), label=""):
+ """KeepRequestError(message='', request_errors=(), label="")
- Arguments:
- * message: A human-readable message describing what Keep operation
+ :message:
+ A human-readable message describing what Keep operation
failed.
- * service_errors: An iterable that yields 2-tuples of Keep
- service URLs to the error encountered when talking to
- it--either an exception, or an HTTP response object. These
- will be packed into an OrderedDict, available through the
- service_errors() method.
+
+ :request_errors:
+ An iterable that yields 2-tuples of keys (where the key refers to
+ some operation that was attempted) to the error encountered when
+ talking to it--either an exception, or an HTTP response object.
+ These will be packed into an OrderedDict, available through the
+ request_errors() method.
+
+ :label:
+ A label indicating the type of value in the 'key' position of request_errors.
+
"""
- self._service_errors = OrderedDict(service_errors)
- if self._service_errors:
+ self.label = label
+ self._request_errors = OrderedDict(request_errors)
+ if self._request_errors:
exc_reports = [self._format_error(*err_pair)
- for err_pair in self._service_errors.iteritems()]
+ for err_pair in self._request_errors.items()]
base_msg = "{}: {}".format(message, "; ".join(exc_reports))
else:
base_msg = message
super(KeepRequestError, self).__init__(base_msg)
self.message = message
- def _format_error(self, service_root, error):
- if isinstance(error, requests.Response):
- err_fmt = "{} responded with {e.status_code} {e.reason}"
+ def _format_error(self, key, error):
+ if isinstance(error, HttpError):
+ err_fmt = "{} {} responded with {e.status_code} {e.reason}"
else:
- err_fmt = "{} raised {e.__class__.__name__} ({e})"
- return err_fmt.format(service_root, e=error)
+ err_fmt = "{} {} raised {e.__class__.__name__} ({e})"
+ return err_fmt.format(self.label, key, e=error)
- def service_errors(self):
- """service_errors() -> OrderedDict
+ def request_errors(self):
+ """request_errors() -> OrderedDict
- The keys of the dictionary are Keep service URLs.
+ The keys of the dictionary are described by `self.label`
The corresponding value is the exception raised when sending the
request to it."""
- return self._service_errors
+ return self._request_errors
+
+
+class HttpError(Exception):
+ def __init__(self, status_code, reason):
+ self.status_code = status_code
+ self.reason = reason
class ArgumentError(Exception):
pass
class KeepWriteError(KeepRequestError):
pass
+class KeepCacheError(KeepRequestError):
+ pass
class NotFoundError(KeepReadError):
pass
class NotImplementedError(Exception):