18842: Turn disk write errors into KeepCacheError
[arvados.git] / sdk / python / arvados / errors.py
index f6681d602b4a45ce5d4bab4913c84297429c472b..15b1f6d4b9883b53c995fd2724a50131b7b28b44 100644 (file)
@@ -1,7 +1,10 @@
+# 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
@@ -9,7 +12,7 @@ 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()
 
@@ -17,7 +20,7 @@ class ApiError(apiclient_errors.HttpError):
 class KeepRequestError(Exception):
     """Base class for errors accessing Keep services."""
     def __init__(self, message='', request_errors=(), label=""):
-        """KeepRequestError(message='', request_errors=())
+        """KeepRequestError(message='', request_errors=(), label="")
 
         :message:
           A human-readable message describing what Keep operation
@@ -30,12 +33,15 @@ class KeepRequestError(Exception):
           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.label = label
         self._request_errors = OrderedDict(request_errors)
         if self._request_errors:
             exc_reports = [self._format_error(*err_pair)
-                           for err_pair in self._request_errors.iteritems()]
+                           for err_pair in self._request_errors.items()]
             base_msg = "{}: {}".format(message, "; ".join(exc_reports))
         else:
             base_msg = message
@@ -43,7 +49,7 @@ class KeepRequestError(Exception):
         self.message = message
 
     def _format_error(self, key, error):
-        if isinstance(error, requests.Response):
+        if isinstance(error, HttpError):
             err_fmt = "{} {} responded with {e.status_code} {e.reason}"
         else:
             err_fmt = "{} {} raised {e.__class__.__name__} ({e})"
@@ -58,6 +64,12 @@ class KeepRequestError(Exception):
         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 SyntaxError(Exception):
@@ -70,6 +82,8 @@ class KeepReadError(KeepRequestError):
     pass
 class KeepWriteError(KeepRequestError):
     pass
+class KeepCacheError(KeepRequestError):
+    pass
 class NotFoundError(KeepReadError):
     pass
 class NotImplementedError(Exception):