4823: Add flush() to ArvadosFile. Fix tests to avoid using internal APIs. Fix
[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='', request_errors=(), label=""):
20         """KeepRequestError(message='', request_errors=())
21
22         :message:
23           A human-readable message describing what Keep operation
24           failed.
25
26         :request_errors:
27           An iterable that yields 2-tuples of keys (where the key refers to
28           some operation that was attempted) to the error encountered when
29           talking to it--either an exception, or an HTTP response object.
30           These will be packed into an OrderedDict, available through the
31           request_errors() method.
32
33         """
34         self.label = label
35         self._request_errors = OrderedDict(request_errors)
36         if self._request_errors:
37             exc_reports = [self._format_error(*err_pair)
38                            for err_pair in self._request_errors.iteritems()]
39             base_msg = "{}: {}".format(message, "; ".join(exc_reports))
40         else:
41             base_msg = message
42         super(KeepRequestError, self).__init__(base_msg)
43         self.message = message
44
45     def _format_error(self, key, error):
46         if isinstance(error, requests.Response):
47             err_fmt = "{} {} responded with {e.status_code} {e.reason}"
48         else:
49             err_fmt = "{} {} raised {e.__class__.__name__} ({e})"
50         return err_fmt.format(self.label, key, e=error)
51
52     def request_errors(self):
53         """request_errors() -> OrderedDict
54
55         The keys of the dictionary are described by `self.label`
56         The corresponding value is the exception raised when sending the
57         request to it."""
58         return self._request_errors
59
60
61 class ArgumentError(Exception):
62     pass
63 class SyntaxError(Exception):
64     pass
65 class AssertionError(Exception):
66     pass
67 class CommandFailedError(Exception):
68     pass
69 class KeepReadError(KeepRequestError):
70     pass
71 class KeepWriteError(KeepRequestError):
72     pass
73 class NotFoundError(KeepReadError):
74     pass
75 class NotImplementedError(Exception):
76     pass
77 class NoKeepServersError(Exception):
78     pass
79 class StaleWriterStateError(Exception):
80     pass
81 class FeatureNotEnabledError(Exception):
82     pass