Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/googleapiclient/errors.py: 50%

86 statements  

« prev     ^ index     » next       coverage.py v7.3.2, created at 2023-12-08 06:51 +0000

1# Copyright 2014 Google Inc. All Rights Reserved. 

2# 

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. 

14 

15"""Errors for the library. 

16 

17All exceptions defined by the library 

18should be defined in this file. 

19""" 

20from __future__ import absolute_import 

21 

22__author__ = "jcgregorio@google.com (Joe Gregorio)" 

23 

24import json 

25 

26from googleapiclient import _helpers as util 

27 

28 

29class Error(Exception): 

30 """Base error for this module.""" 

31 

32 pass 

33 

34 

35class HttpError(Error): 

36 """HTTP data was invalid or unexpected.""" 

37 

38 @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 = "" 

46 self.reason = self._get_reason() 

47 

48 @property 

49 def status_code(self): 

50 """Return the HTTP status code from the response content.""" 

51 return self.resp.status 

52 

53 def _get_reason(self): 

54 """Calculate the reason for the error from the response content.""" 

55 reason = self.resp.reason 

56 try: 

57 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") 

62 if isinstance(data, dict): 

63 reason = data["error"]["message"] 

64 error_detail_keyword = next( 

65 ( 

66 kw 

67 for kw in ["detail", "details", "errors", "message"] 

68 if kw in data["error"] 

69 ), 

70 "", 

71 ) 

72 if error_detail_keyword: 

73 self.error_details = data["error"][error_detail_keyword] 

74 elif isinstance(data, list) and len(data) > 0: 

75 first_error = data[0] 

76 reason = first_error["error"]["message"] 

77 if "details" in first_error["error"]: 

78 self.error_details = first_error["error"]["details"] 

79 else: 

80 self.error_details = data 

81 except (ValueError, KeyError, TypeError): 

82 pass 

83 if reason is None: 

84 reason = "" 

85 return reason.strip() 

86 

87 def __repr__(self): 

88 if self.error_details: 

89 return '<HttpError %s when requesting %s returned "%s". Details: "%s">' % ( 

90 self.resp.status, 

91 self.uri, 

92 self.reason, 

93 self.error_details, 

94 ) 

95 elif self.uri: 

96 return '<HttpError %s when requesting %s returned "%s">' % ( 

97 self.resp.status, 

98 self.uri, 

99 self.reason, 

100 ) 

101 else: 

102 return '<HttpError %s "%s">' % (self.resp.status, self.reason) 

103 

104 __str__ = __repr__ 

105 

106 

107class InvalidJsonError(Error): 

108 """The JSON returned could not be parsed.""" 

109 

110 pass 

111 

112 

113class UnknownFileType(Error): 

114 """File type unknown or unexpected.""" 

115 

116 pass 

117 

118 

119class UnknownLinkType(Error): 

120 """Link type unknown or unexpected.""" 

121 

122 pass 

123 

124 

125class UnknownApiNameOrVersion(Error): 

126 """No API with that name and version exists.""" 

127 

128 pass 

129 

130 

131class UnacceptableMimeTypeError(Error): 

132 """That is an unacceptable mimetype for this operation.""" 

133 

134 pass 

135 

136 

137class MediaUploadSizeError(Error): 

138 """Media is larger than the method can accept.""" 

139 

140 pass 

141 

142 

143class ResumableUploadError(HttpError): 

144 """Error occurred during resumable upload.""" 

145 

146 pass 

147 

148 

149class InvalidChunkSizeError(Error): 

150 """The given chunksize is not valid.""" 

151 

152 pass 

153 

154 

155class InvalidNotificationError(Error): 

156 """The channel Notification is invalid.""" 

157 

158 pass 

159 

160 

161class BatchError(HttpError): 

162 """Error occurred during batch operations.""" 

163 

164 @util.positional(2) 

165 def __init__(self, reason, resp=None, content=None): 

166 self.resp = resp 

167 self.content = content 

168 self.reason = reason 

169 

170 def __repr__(self): 

171 if getattr(self.resp, "status", None) is None: 

172 return '<BatchError "%s">' % (self.reason) 

173 else: 

174 return '<BatchError %s "%s">' % (self.resp.status, self.reason) 

175 

176 __str__ = __repr__ 

177 

178 

179class UnexpectedMethodError(Error): 

180 """Exception raised by RequestMockBuilder on unexpected calls.""" 

181 

182 @util.positional(1) 

183 def __init__(self, methodId=None): 

184 """Constructor for an UnexpectedMethodError.""" 

185 super(UnexpectedMethodError, self).__init__( 

186 "Received unexpected call %s" % methodId 

187 ) 

188 

189 

190class UnexpectedBodyError(Error): 

191 """Exception raised by RequestMockBuilder on unexpected bodies.""" 

192 

193 def __init__(self, expected, provided): 

194 """Constructor for an UnexpectedMethodError.""" 

195 super(UnexpectedBodyError, self).__init__( 

196 "Expected: [%s] - Provided: [%s]" % (expected, provided) 

197 )