blob: bab14189f9458acf16b638aa924bab3d3db71771 [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
22__author__ = 'jcgregorio@google.com (Joe Gregorio)'
23
Craig Citro6ae34d72014-08-18 23:10:09 -070024import json
Joe Gregorio3ad5e9a2010-12-09 15:01:04 -050025
Jon Wayne Parrott6755f612016-08-15 10:52:26 -070026# Oauth2client < 3 has the positional helper in 'util', >= 3 has it
27# in '_helpers'.
28try:
29 from oauth2client import util
30except ImportError:
31 from oauth2client import _helpers as util
Ali Afshar2dcc6522010-12-16 10:11:53 +010032
33
Joe Gregorio3ad5e9a2010-12-09 15:01:04 -050034class Error(Exception):
35 """Base error for this module."""
36 pass
37
38
39class HttpError(Error):
40 """HTTP data was invalid or unexpected."""
41
Joe Gregorio68a8cfe2012-08-03 16:17:40 -040042 @util.positional(3)
Joe Gregorio49396552011-03-08 10:39:00 -050043 def __init__(self, resp, content, uri=None):
Joe Gregorio3ad5e9a2010-12-09 15:01:04 -050044 self.resp = resp
INADA Naoki09157612015-03-25 01:51:03 +090045 if not isinstance(content, bytes):
46 raise TypeError("HTTP content should be bytes")
Ali Afshar2dcc6522010-12-16 10:11:53 +010047 self.content = content
Joe Gregorio49396552011-03-08 10:39:00 -050048 self.uri = uri
Son CHUf6e26612017-07-17 18:02:18 +020049 self.error_details = ''
Joe Gregorio3ad5e9a2010-12-09 15:01:04 -050050
Ali Afshar2dcc6522010-12-16 10:11:53 +010051 def _get_reason(self):
Joe Gregoriofdf7c802011-06-30 12:33:38 -040052 """Calculate the reason for the error from the response content."""
Joe Gregorio20b54fb2012-07-26 09:59:35 -040053 reason = self.resp.reason
54 try:
INADA Naoki09157612015-03-25 01:51:03 +090055 data = json.loads(self.content.decode('utf-8'))
Thang Minh Vub7122b32016-10-15 01:57:15 +080056 if isinstance(data, dict):
57 reason = data['error']['message']
Son CHUf6e26612017-07-17 18:02:18 +020058 if 'details' in data['error']:
59 self.error_details = data['error']['details']
Thang Minh Vub7122b32016-10-15 01:57:15 +080060 elif isinstance(data, list) and len(data) > 0:
61 first_error = data[0]
62 reason = first_error['error']['message']
Son CHUf6e26612017-07-17 18:02:18 +020063 if 'details' in first_error['error']:
64 self.error_details = first_error['error']['details']
Thang Minh Vub7122b32016-10-15 01:57:15 +080065 except (ValueError, KeyError, TypeError):
Joe Gregorio20b54fb2012-07-26 09:59:35 -040066 pass
Joe Gregorioe7bbbb92013-02-20 15:37:24 -050067 if reason is None:
68 reason = ''
Ali Afshar2dcc6522010-12-16 10:11:53 +010069 return reason
70
71 def __repr__(self):
Son CHUf6e26612017-07-17 18:02:18 +020072 reason = self._get_reason()
73 if self.error_details:
74 return '<HttpError %s when requesting %s returned "%s". Details: "%s">' % \
75 (self.resp.status, self.uri, reason.strip(), self.error_details)
76 elif self.uri:
Joe Gregorio49396552011-03-08 10:39:00 -050077 return '<HttpError %s when requesting %s returned "%s">' % (
Joe Gregorio3fb93672012-07-25 11:31:11 -040078 self.resp.status, self.uri, self._get_reason().strip())
Joe Gregorio49396552011-03-08 10:39:00 -050079 else:
80 return '<HttpError %s "%s">' % (self.resp.status, self._get_reason())
Ali Afshar2dcc6522010-12-16 10:11:53 +010081
82 __str__ = __repr__
Joe Gregorio3ad5e9a2010-12-09 15:01:04 -050083
84
Joe Gregorio49396552011-03-08 10:39:00 -050085class InvalidJsonError(Error):
86 """The JSON returned could not be parsed."""
87 pass
88
89
Joe Gregoriodc106fc2012-11-20 14:30:14 -050090class UnknownFileType(Error):
91 """File type unknown or unexpected."""
92 pass
93
94
Joe Gregorio3ad5e9a2010-12-09 15:01:04 -050095class UnknownLinkType(Error):
96 """Link type unknown or unexpected."""
97 pass
Joe Gregoriofdf7c802011-06-30 12:33:38 -040098
Joe Gregorio66f57522011-11-30 11:00:00 -050099
Joe Gregoriodae2f552011-11-21 08:16:56 -0500100class UnknownApiNameOrVersion(Error):
Joe Gregorio8b4df3f2011-11-18 15:44:48 -0500101 """No API with that name and version exists."""
102 pass
103
Joe Gregorioa388ce32011-09-09 17:19:13 -0400104
Joe Gregoriofdf7c802011-06-30 12:33:38 -0400105class UnacceptableMimeTypeError(Error):
106 """That is an unacceptable mimetype for this operation."""
107 pass
108
Joe Gregorioa388ce32011-09-09 17:19:13 -0400109
Joe Gregoriofdf7c802011-06-30 12:33:38 -0400110class MediaUploadSizeError(Error):
111 """Media is larger than the method can accept."""
112 pass
Joe Gregorioa388ce32011-09-09 17:19:13 -0400113
114
Joe Gregoriobaf04802013-03-01 12:27:06 -0500115class ResumableUploadError(HttpError):
Joe Gregoriod0bd3882011-11-22 09:49:47 -0500116 """Error occured during resumable upload."""
117 pass
118
119
Joe Gregorioc80ac9d2012-08-21 14:09:09 -0400120class InvalidChunkSizeError(Error):
121 """The given chunksize is not valid."""
122 pass
123
Joe Gregorio1a5e30e2013-06-25 15:35:47 -0400124class InvalidNotificationError(Error):
125 """The channel Notification is invalid."""
126 pass
Joe Gregorioc80ac9d2012-08-21 14:09:09 -0400127
Joe Gregorio5d1171b2012-01-05 10:48:24 -0500128class BatchError(HttpError):
Joe Gregorio66f57522011-11-30 11:00:00 -0500129 """Error occured during batch operations."""
Joe Gregorio5d1171b2012-01-05 10:48:24 -0500130
Joe Gregorio68a8cfe2012-08-03 16:17:40 -0400131 @util.positional(2)
Joe Gregorio5d1171b2012-01-05 10:48:24 -0500132 def __init__(self, reason, resp=None, content=None):
133 self.resp = resp
134 self.content = content
135 self.reason = reason
136
137 def __repr__(self):
ittus5f00cad2016-10-15 10:32:40 +0800138 if getattr(self.resp, 'status', None) is None:
139 return '<BatchError "%s">' % (self.reason)
140 else:
Joe Gregorio5d1171b2012-01-05 10:48:24 -0500141 return '<BatchError %s "%s">' % (self.resp.status, self.reason)
142
143 __str__ = __repr__
Joe Gregorio66f57522011-11-30 11:00:00 -0500144
145
Joe Gregorioa388ce32011-09-09 17:19:13 -0400146class UnexpectedMethodError(Error):
147 """Exception raised by RequestMockBuilder on unexpected calls."""
148
Joe Gregorio68a8cfe2012-08-03 16:17:40 -0400149 @util.positional(1)
Joe Gregorioa388ce32011-09-09 17:19:13 -0400150 def __init__(self, methodId=None):
151 """Constructor for an UnexpectedMethodError."""
152 super(UnexpectedMethodError, self).__init__(
153 'Received unexpected call %s' % methodId)
154
155
156class UnexpectedBodyError(Error):
157 """Exception raised by RequestMockBuilder on unexpected bodies."""
158
159 def __init__(self, expected, provided):
160 """Constructor for an UnexpectedMethodError."""
161 super(UnexpectedBodyError, self).__init__(
162 'Expected: [%s] - Provided: [%s]' % (expected, provided))