• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  pass
32
33
34class HttpError(Error):
35  """HTTP data was invalid or unexpected."""
36
37  @util.positional(3)
38  def __init__(self, resp, content, uri=None):
39    self.resp = resp
40    if not isinstance(content, bytes):
41        raise TypeError("HTTP content should be bytes")
42    self.content = content
43    self.uri = uri
44    self.error_details = ''
45
46  def _get_reason(self):
47    """Calculate the reason for the error from the response content."""
48    reason = self.resp.reason
49    try:
50      data = json.loads(self.content.decode('utf-8'))
51      if isinstance(data, dict):
52        reason = data['error']['message']
53        if 'details' in data['error']:
54            self.error_details = data['error']['details']
55      elif isinstance(data, list) and len(data) > 0:
56        first_error = data[0]
57        reason = first_error['error']['message']
58        if 'details' in first_error['error']:
59            self.error_details = first_error['error']['details']
60    except (ValueError, KeyError, TypeError):
61      pass
62    if reason is None:
63      reason = ''
64    return reason
65
66  def __repr__(self):
67    reason = self._get_reason()
68    if self.error_details:
69      return '<HttpError %s when requesting %s returned "%s". Details: "%s">' % \
70             (self.resp.status, self.uri, reason.strip(), self.error_details)
71    elif self.uri:
72      return '<HttpError %s when requesting %s returned "%s">' % (
73          self.resp.status, self.uri, self._get_reason().strip())
74    else:
75      return '<HttpError %s "%s">' % (self.resp.status, self._get_reason())
76
77  __str__ = __repr__
78
79
80class InvalidJsonError(Error):
81  """The JSON returned could not be parsed."""
82  pass
83
84
85class UnknownFileType(Error):
86  """File type unknown or unexpected."""
87  pass
88
89
90class UnknownLinkType(Error):
91  """Link type unknown or unexpected."""
92  pass
93
94
95class UnknownApiNameOrVersion(Error):
96  """No API with that name and version exists."""
97  pass
98
99
100class UnacceptableMimeTypeError(Error):
101  """That is an unacceptable mimetype for this operation."""
102  pass
103
104
105class MediaUploadSizeError(Error):
106  """Media is larger than the method can accept."""
107  pass
108
109
110class ResumableUploadError(HttpError):
111  """Error occured during resumable upload."""
112  pass
113
114
115class InvalidChunkSizeError(Error):
116  """The given chunksize is not valid."""
117  pass
118
119class InvalidNotificationError(Error):
120  """The channel Notification is invalid."""
121  pass
122
123class BatchError(HttpError):
124  """Error occured during batch operations."""
125
126  @util.positional(2)
127  def __init__(self, reason, resp=None, content=None):
128    self.resp = resp
129    self.content = content
130    self.reason = reason
131
132  def __repr__(self):
133    if getattr(self.resp, 'status', None) is None:
134      return '<BatchError "%s">' % (self.reason)
135    else:
136      return '<BatchError %s "%s">' % (self.resp.status, self.reason)
137
138  __str__ = __repr__
139
140
141class UnexpectedMethodError(Error):
142  """Exception raised by RequestMockBuilder on unexpected calls."""
143
144  @util.positional(1)
145  def __init__(self, methodId=None):
146    """Constructor for an UnexpectedMethodError."""
147    super(UnexpectedMethodError, self).__init__(
148        'Received unexpected call %s' % methodId)
149
150
151class UnexpectedBodyError(Error):
152  """Exception raised by RequestMockBuilder on unexpected bodies."""
153
154  def __init__(self, expected, provided):
155    """Constructor for an UnexpectedMethodError."""
156    super(UnexpectedBodyError, self).__init__(
157        'Expected: [%s] - Provided: [%s]' % (expected, provided))
158