Index: third_party/cloud_storage/cloudstorage/errors.py |
diff --git a/third_party/cloud_storage/cloudstorage/errors.py b/third_party/cloud_storage/cloudstorage/errors.py |
new file mode 100644 |
index 0000000000000000000000000000000000000000..21743806d481fdb12f94545101a8bbcd3bb9634d |
--- /dev/null |
+++ b/third_party/cloud_storage/cloudstorage/errors.py |
@@ -0,0 +1,143 @@ |
+# Copyright 2012 Google Inc. All Rights Reserved. |
+# |
+# Licensed under the Apache License, Version 2.0 (the "License"); |
+# you may not use this file except in compliance with the License. |
+# You may obtain a copy of the License at |
+# |
+# http://www.apache.org/licenses/LICENSE-2.0 |
+# |
+# Unless required by applicable law or agreed to in writing, |
+# software distributed under the License is distributed on an |
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, |
+# either express or implied. See the License for the specific |
+# language governing permissions and limitations under the License. |
+ |
+"""Google Cloud Storage specific Files API calls.""" |
+ |
+ |
+ |
+ |
+ |
+__all__ = ['AuthorizationError', |
+ 'check_status', |
+ 'Error', |
+ 'FatalError', |
+ 'FileClosedError', |
+ 'ForbiddenError', |
+ 'InvalidRange', |
+ 'NotFoundError', |
+ 'ServerError', |
+ 'TimeoutError', |
+ 'TransientError', |
+ ] |
+ |
+import httplib |
+ |
+ |
+class Error(Exception): |
+ """Base error for all gcs operations. |
+ |
+ Error can happen on GAE side or GCS server side. |
+ For details on a particular GCS HTTP response code, see |
+ https://developers.google.com/storage/docs/reference-status#standardcodes |
+ """ |
+ |
+ |
+class TransientError(Error): |
+ """TransientError could be retried.""" |
+ |
+ |
+class TimeoutError(TransientError): |
+ """HTTP 408 timeout.""" |
+ |
+ |
+class FatalError(Error): |
+ """FatalError shouldn't be retried.""" |
+ |
+ |
+class FileClosedError(FatalError): |
+ """File is already closed. |
+ |
+ This can happen when the upload has finished but 'write' is called on |
+ a stale upload handle. |
+ """ |
+ |
+ |
+class NotFoundError(FatalError): |
+ """HTTP 404 resource not found.""" |
+ |
+ |
+class ForbiddenError(FatalError): |
+ """HTTP 403 Forbidden. |
+ |
+ While GCS replies with a 403 error for many reasons, the most common one |
+ is due to bucket permission not correctly setup for your app to access. |
+ """ |
+ |
+ |
+class AuthorizationError(FatalError): |
+ """HTTP 401 authentication required. |
+ |
+ Unauthorized request has been received by GCS. |
+ |
+ This error is mostly handled by GCS client. GCS client will request |
+ a new access token and retry the request. |
+ """ |
+ |
+ |
+class InvalidRange(FatalError): |
+ """HTTP 416 RequestRangeNotSatifiable.""" |
+ |
+ |
+class ServerError(TransientError): |
+ """HTTP >= 500 server side error.""" |
+ |
+ |
+def check_status(status, expected, path, headers=None, |
+ resp_headers=None, body=None, extras=None): |
+ """Check HTTP response status is expected. |
+ |
+ Args: |
+ status: HTTP response status. int. |
+ expected: a list of expected statuses. A list of ints. |
+ path: filename or a path prefix. |
+ headers: HTTP request headers. |
+ resp_headers: HTTP response headers. |
+ body: HTTP response body. |
+ extras: extra info to be logged verbatim if error occurs. |
+ |
+ Raises: |
+ AuthorizationError: if authorization failed. |
+ NotFoundError: if an object that's expected to exist doesn't. |
+ TimeoutError: if HTTP request timed out. |
+ ServerError: if server experienced some errors. |
+ FatalError: if any other unexpected errors occurred. |
+ """ |
+ if status in expected: |
+ return |
+ |
+ msg = ('Expect status %r from Google Storage. But got status %d.\n' |
+ 'Path: %r.\n' |
+ 'Request headers: %r.\n' |
+ 'Response headers: %r.\n' |
+ 'Body: %r.\n' |
+ 'Extra info: %r.\n' % |
+ (expected, status, path, headers, resp_headers, body, extras)) |
+ |
+ if status == httplib.UNAUTHORIZED: |
+ raise AuthorizationError(msg) |
+ elif status == httplib.FORBIDDEN: |
+ raise ForbiddenError(msg) |
+ elif status == httplib.NOT_FOUND: |
+ raise NotFoundError(msg) |
+ elif status == httplib.REQUEST_TIMEOUT: |
+ raise TimeoutError(msg) |
+ elif status == httplib.REQUESTED_RANGE_NOT_SATISFIABLE: |
+ raise InvalidRange(msg) |
+ elif (status == httplib.OK and 308 in expected and |
+ httplib.OK not in expected): |
+ raise FileClosedError(msg) |
+ elif status >= 500: |
+ raise ServerError(msg) |
+ else: |
+ raise FatalError(msg) |