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
« 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.
15"""Errors for the library.
17All exceptions defined by the library
18should be defined in this file.
19"""
20from __future__ import absolute_import
22__author__ = "jcgregorio@google.com (Joe Gregorio)"
24import json
26from googleapiclient import _helpers as util
29class Error(Exception):
30 """Base error for this module."""
32 pass
35class HttpError(Error):
36 """HTTP data was invalid or unexpected."""
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()
48 @property
49 def status_code(self):
50 """Return the HTTP status code from the response content."""
51 return self.resp.status
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()
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)
104 __str__ = __repr__
107class InvalidJsonError(Error):
108 """The JSON returned could not be parsed."""
110 pass
113class UnknownFileType(Error):
114 """File type unknown or unexpected."""
116 pass
119class UnknownLinkType(Error):
120 """Link type unknown or unexpected."""
122 pass
125class UnknownApiNameOrVersion(Error):
126 """No API with that name and version exists."""
128 pass
131class UnacceptableMimeTypeError(Error):
132 """That is an unacceptable mimetype for this operation."""
134 pass
137class MediaUploadSizeError(Error):
138 """Media is larger than the method can accept."""
140 pass
143class ResumableUploadError(HttpError):
144 """Error occurred during resumable upload."""
146 pass
149class InvalidChunkSizeError(Error):
150 """The given chunksize is not valid."""
152 pass
155class InvalidNotificationError(Error):
156 """The channel Notification is invalid."""
158 pass
161class BatchError(HttpError):
162 """Error occurred during batch operations."""
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
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)
176 __str__ = __repr__
179class UnexpectedMethodError(Error):
180 """Exception raised by RequestMockBuilder on unexpected calls."""
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 )
190class UnexpectedBodyError(Error):
191 """Exception raised by RequestMockBuilder on unexpected bodies."""
193 def __init__(self, expected, provided):
194 """Constructor for an UnexpectedMethodError."""
195 super(UnexpectedBodyError, self).__init__(
196 "Expected: [%s] - Provided: [%s]" % (expected, provided)
197 )