Merge branch 'master' into 4232-slow-pipes-n-jobs
[arvados.git] / sdk / python / arvados / errors.py
1 # errors.py - Arvados-specific exceptions.
2
3 import json
4 import requests
5
6 from apiclient import errors as apiclient_errors
7 from collections import OrderedDict
8
9 class ApiError(apiclient_errors.HttpError):
10     def _get_reason(self):
11         try:
12             return '; '.join(json.loads(self.content)['errors'])
13         except (KeyError, TypeError, ValueError):
14             return super(ApiError, self)._get_reason()
15
16
17 class KeepRequestError(Exception):
18     """Base class for errors accessing Keep services."""
19     def __init__(self, message='', service_errors=()):
20         """KeepRequestError(message='', service_errors=())
21
22         Arguments:
23         * message: A human-readable message describing what Keep operation
24           failed.
25         * service_errors: An iterable that yields 2-tuples of Keep
26           service URLs to the error encountered when talking to
27           it--either an exception, or an HTTP response object.  These
28           will be packed into an OrderedDict, available through the
29           service_errors() method.
30         """
31         self._service_errors = OrderedDict(service_errors)
32         if self._service_errors:
33             exc_reports = [self._format_error(*err_pair)
34                            for err_pair in self._service_errors.iteritems()]
35             base_msg = "{}: {}".format(message, "; ".join(exc_reports))
36         else:
37             base_msg = message
38         super(KeepRequestError, self).__init__(base_msg)
39         self.message = message
40
41     def _format_error(self, service_root, error):
42         if isinstance(error, requests.Response):
43             err_fmt = "{} responded with {e.status_code} {e.reason}"
44         else:
45             err_fmt = "{} raised {e.__class__.__name__} ({e})"
46         return err_fmt.format(service_root, e=error)
47
48     def service_errors(self):
49         """service_errors() -> OrderedDict
50
51         The keys of the dictionary are Keep service URLs.
52         The corresponding value is the exception raised when sending the
53         request to it."""
54         return self._service_errors
55
56
57 class ArgumentError(Exception):
58     pass
59 class SyntaxError(Exception):
60     pass
61 class AssertionError(Exception):
62     pass
63 class CommandFailedError(Exception):
64     pass
65 class KeepReadError(KeepRequestError):
66     pass
67 class KeepWriteError(KeepRequestError):
68     pass
69 class NotFoundError(KeepReadError):
70     pass
71 class NotImplementedError(Exception):
72     pass
73 class NoKeepServersError(Exception):
74     pass
75 class StaleWriterStateError(Exception):
76     pass