blob: 385558c4897316d76ec7247df36ba42c3306f023 [file] [log] [blame]
Craig Citro751b7fb2014-09-23 11:20:38 -07001# Copyright 2014 Google Inc. All Rights Reserved.
Joe Gregorio20a5aa92011-04-01 17:44:25 -04002#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
Joe Gregorio3ad5e9a2010-12-09 15:01:04 -050014
15"""Errors for the library.
16
17All exceptions defined by the library
18should be defined in this file.
19"""
INADA Naokie4ea1a92015-03-04 03:45:42 +090020from __future__ import absolute_import
Joe Gregorio3ad5e9a2010-12-09 15:01:04 -050021
Bu Sun Kim66bb32c2019-10-30 10:11:58 -070022__author__ = "jcgregorio@google.com (Joe Gregorio)"
Joe Gregorio3ad5e9a2010-12-09 15:01:04 -050023
Craig Citro6ae34d72014-08-18 23:10:09 -070024import json
Joe Gregorio3ad5e9a2010-12-09 15:01:04 -050025
Helen Koikede13e3b2018-04-26 16:05:16 -030026from googleapiclient import _helpers as util
Ali Afshar2dcc6522010-12-16 10:11:53 +010027
28
Joe Gregorio3ad5e9a2010-12-09 15:01:04 -050029class Error(Exception):
Bu Sun Kim66bb32c2019-10-30 10:11:58 -070030 """Base error for this module."""
31
32 pass
Joe Gregorio3ad5e9a2010-12-09 15:01:04 -050033
34
35class HttpError(Error):
Bu Sun Kim66bb32c2019-10-30 10:11:58 -070036 """HTTP data was invalid or unexpected."""
Joe Gregorio3ad5e9a2010-12-09 15:01:04 -050037
Bu Sun Kim66bb32c2019-10-30 10:11:58 -070038 @util.positional(3)
39 def __init__(self, resp, content, uri=None):
40 self.resp = resp
41 if not isinstance(content, bytes):
42 raise TypeError("HTTP content should be bytes")
43 self.content = content
44 self.uri = uri
45 self.error_details = ""
Cheskel Twerskyd5cf4e02021-09-02 12:06:09 +030046 self.reason = self._get_reason()
William Marquardtdb2a7662021-03-17 16:02:04 -030047
48 @property
49 def status_code(self):
50 """Return the HTTP status code from the response content."""
51 return self.resp.status
Joe Gregorio3ad5e9a2010-12-09 15:01:04 -050052
Bu Sun Kim66bb32c2019-10-30 10:11:58 -070053 def _get_reason(self):
54 """Calculate the reason for the error from the response content."""
55 reason = self.resp.reason
56 try:
Anthonios Parthenioue6a1da32020-12-09 17:00:03 -050057 try:
58 data = json.loads(self.content.decode("utf-8"))
59 except json.JSONDecodeError:
60 # In case it is not json
61 data = self.content.decode("utf-8")
Bu Sun Kim66bb32c2019-10-30 10:11:58 -070062 if isinstance(data, dict):
63 reason = data["error"]["message"]
vinay-googlea5d20812021-04-03 03:00:05 -070064 error_detail_keyword = next((kw for kw in ["detail", "details", "errors", "message"] if kw in data["error"]), "")
Muad Mohameda341c5a2020-11-08 20:30:02 +000065 if error_detail_keyword:
66 self.error_details = data["error"][error_detail_keyword]
Bu Sun Kim66bb32c2019-10-30 10:11:58 -070067 elif isinstance(data, list) and len(data) > 0:
68 first_error = data[0]
69 reason = first_error["error"]["message"]
70 if "details" in first_error["error"]:
71 self.error_details = first_error["error"]["details"]
Anthonios Parthenioue6a1da32020-12-09 17:00:03 -050072 else:
73 self.error_details = data
Bu Sun Kim66bb32c2019-10-30 10:11:58 -070074 except (ValueError, KeyError, TypeError):
75 pass
76 if reason is None:
77 reason = ""
Cheskel Twerskyd5cf4e02021-09-02 12:06:09 +030078 return reason.strip()
Ali Afshar2dcc6522010-12-16 10:11:53 +010079
Bu Sun Kim66bb32c2019-10-30 10:11:58 -070080 def __repr__(self):
Bu Sun Kim66bb32c2019-10-30 10:11:58 -070081 if self.error_details:
82 return '<HttpError %s when requesting %s returned "%s". Details: "%s">' % (
83 self.resp.status,
84 self.uri,
Cheskel Twerskyd5cf4e02021-09-02 12:06:09 +030085 self.reason,
Bu Sun Kim66bb32c2019-10-30 10:11:58 -070086 self.error_details,
87 )
88 elif self.uri:
89 return '<HttpError %s when requesting %s returned "%s">' % (
90 self.resp.status,
91 self.uri,
Cheskel Twerskyd5cf4e02021-09-02 12:06:09 +030092 self.reason,
Bu Sun Kim66bb32c2019-10-30 10:11:58 -070093 )
94 else:
Cheskel Twerskyd5cf4e02021-09-02 12:06:09 +030095 return '<HttpError %s "%s">' % (self.resp.status, self.reason)
Ali Afshar2dcc6522010-12-16 10:11:53 +010096
Bu Sun Kim66bb32c2019-10-30 10:11:58 -070097 __str__ = __repr__
Joe Gregorio3ad5e9a2010-12-09 15:01:04 -050098
99
Joe Gregorio49396552011-03-08 10:39:00 -0500100class InvalidJsonError(Error):
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700101 """The JSON returned could not be parsed."""
102
103 pass
Joe Gregorio49396552011-03-08 10:39:00 -0500104
105
Joe Gregoriodc106fc2012-11-20 14:30:14 -0500106class UnknownFileType(Error):
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700107 """File type unknown or unexpected."""
108
109 pass
Joe Gregoriodc106fc2012-11-20 14:30:14 -0500110
111
Joe Gregorio3ad5e9a2010-12-09 15:01:04 -0500112class UnknownLinkType(Error):
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700113 """Link type unknown or unexpected."""
114
115 pass
Joe Gregoriofdf7c802011-06-30 12:33:38 -0400116
Joe Gregorio66f57522011-11-30 11:00:00 -0500117
Joe Gregoriodae2f552011-11-21 08:16:56 -0500118class UnknownApiNameOrVersion(Error):
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700119 """No API with that name and version exists."""
120
121 pass
Joe Gregorio8b4df3f2011-11-18 15:44:48 -0500122
Joe Gregorioa388ce32011-09-09 17:19:13 -0400123
Joe Gregoriofdf7c802011-06-30 12:33:38 -0400124class UnacceptableMimeTypeError(Error):
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700125 """That is an unacceptable mimetype for this operation."""
126
127 pass
Joe Gregoriofdf7c802011-06-30 12:33:38 -0400128
Joe Gregorioa388ce32011-09-09 17:19:13 -0400129
Joe Gregoriofdf7c802011-06-30 12:33:38 -0400130class MediaUploadSizeError(Error):
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700131 """Media is larger than the method can accept."""
132
133 pass
Joe Gregorioa388ce32011-09-09 17:19:13 -0400134
135
Joe Gregoriobaf04802013-03-01 12:27:06 -0500136class ResumableUploadError(HttpError):
Tim Gates43fc0cf2020-04-21 08:03:25 +1000137 """Error occurred during resumable upload."""
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700138
139 pass
Joe Gregoriod0bd3882011-11-22 09:49:47 -0500140
141
Joe Gregorioc80ac9d2012-08-21 14:09:09 -0400142class InvalidChunkSizeError(Error):
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700143 """The given chunksize is not valid."""
144
145 pass
146
Joe Gregorioc80ac9d2012-08-21 14:09:09 -0400147
Joe Gregorio1a5e30e2013-06-25 15:35:47 -0400148class InvalidNotificationError(Error):
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700149 """The channel Notification is invalid."""
150
151 pass
152
Joe Gregorioc80ac9d2012-08-21 14:09:09 -0400153
Joe Gregorio5d1171b2012-01-05 10:48:24 -0500154class BatchError(HttpError):
Tim Gates43fc0cf2020-04-21 08:03:25 +1000155 """Error occurred during batch operations."""
Joe Gregorio5d1171b2012-01-05 10:48:24 -0500156
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700157 @util.positional(2)
158 def __init__(self, reason, resp=None, content=None):
159 self.resp = resp
160 self.content = content
161 self.reason = reason
Joe Gregorio5d1171b2012-01-05 10:48:24 -0500162
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700163 def __repr__(self):
164 if getattr(self.resp, "status", None) is None:
165 return '<BatchError "%s">' % (self.reason)
166 else:
167 return '<BatchError %s "%s">' % (self.resp.status, self.reason)
Joe Gregorio5d1171b2012-01-05 10:48:24 -0500168
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700169 __str__ = __repr__
Joe Gregorio66f57522011-11-30 11:00:00 -0500170
171
Joe Gregorioa388ce32011-09-09 17:19:13 -0400172class UnexpectedMethodError(Error):
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700173 """Exception raised by RequestMockBuilder on unexpected calls."""
Joe Gregorioa388ce32011-09-09 17:19:13 -0400174
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700175 @util.positional(1)
176 def __init__(self, methodId=None):
177 """Constructor for an UnexpectedMethodError."""
178 super(UnexpectedMethodError, self).__init__(
179 "Received unexpected call %s" % methodId
180 )
Joe Gregorioa388ce32011-09-09 17:19:13 -0400181
182
183class UnexpectedBodyError(Error):
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700184 """Exception raised by RequestMockBuilder on unexpected bodies."""
Joe Gregorioa388ce32011-09-09 17:19:13 -0400185
Bu Sun Kim66bb32c2019-10-30 10:11:58 -0700186 def __init__(self, expected, provided):
187 """Constructor for an UnexpectedMethodError."""
188 super(UnexpectedBodyError, self).__init__(
189 "Expected: [%s] - Provided: [%s]" % (expected, provided)
190 )