2929 print_function ,
3030 unicode_literals ,
3131)
32+ from builtins import *
3233
34+ import logging
3335import sys
3436import textwrap
35- from builtins import *
37+ from json import JSONDecodeError
3638
3739import requests
3840from past .builtins import basestring
3941
4042from .response_codes import RESPONSE_CODES
4143
4244
45+ logger = logging .getLogger (__name__ )
46+
47+
4348def _to_unicode (string ):
4449 """Convert a string (bytes, str or unicode) to unicode."""
4550 assert isinstance (string , basestring )
@@ -135,36 +140,47 @@ class ApiError(webexteamssdkException):
135140 def __init__ (self , response ):
136141 assert isinstance (response , requests .Response )
137142
138- # Extended exception data attributes
139- self .request = response .request
140- """The :class:`requests.PreparedRequest` of the API call."""
141-
143+ # Extended exception attributes
142144 self .response = response
143145 """The :class:`requests.Response` object returned from the API call."""
144146
145- # Error message
146- response_code = response .status_code
147- response_reason = " " + response .reason if response .reason else ""
148- description = RESPONSE_CODES .get (
149- response_code ,
150- "Unknown Response Code" ,
151- )
152- detail = _response_to_string (response )
147+ self .request = self .response .request
148+ """The :class:`requests.PreparedRequest` of the API call."""
149+
150+ self .status_code = self .response .status_code
151+ """The HTTP status code from the API response."""
152+
153+ self .status = self .response .reason
154+ """The HTTP status from the API response."""
155+
156+ self .details = None
157+ """The parsed JSON details from the API response."""
158+ if "application/json" in \
159+ self .response .headers .get ("Content-Type" , "" ).lower ():
160+ try :
161+ self .details = self .response .json ()
162+ except JSONDecodeError :
163+ logger .warning ("Error parsing JSON response body" )
164+
165+ self .message = self .details .get ("message" ) if self .details else None
166+ """The error message from the parsed API response."""
167+
168+ self .description = RESPONSE_CODES .get (self .status_code )
169+ """A description of the HTTP Response Code from the API docs."""
153170
154171 super (ApiError , self ).__init__ (
155- "Response Code [{}]{} - {}\n {}"
156- "" .format (
157- response_code ,
158- response_reason ,
159- description ,
160- detail
172+ "[{status_code}]{status} - {message}" .format (
173+ status_code = self .status_code ,
174+ status = " " + self .status if self .status else "" ,
175+ message = self .message or self .description or "Unknown Error" ,
161176 )
162177 )
163178
164-
165- class MalformedResponse (webexteamssdkException ):
166- """Raised when a malformed response is received from Webex Teams."""
167- pass
179+ def __repr__ (self ):
180+ return "<{exception_name} [{status_code}]>" .format (
181+ exception_name = self .__class__ .__name__ ,
182+ status_code = self .status_code ,
183+ )
168184
169185
170186class RateLimitError (ApiError ):
@@ -175,18 +191,19 @@ class RateLimitError(ApiError):
175191 """
176192
177193 def __init__ (self , response ):
178- super ( RateLimitError , self ). __init__ ( response )
194+ assert isinstance ( response , requests . Response )
179195
180- # Extended exception data attributes
196+ # Extended exception attributes
181197 self .retry_after = max (1 , int (response .headers .get ('Retry-After' , 15 )))
182198 """The `Retry-After` time period (in seconds) provided by Webex Teams.
183199
184200 Defaults to 15 seconds if the response `Retry-After` header isn't
185201 present in the response headers, and defaults to a minimum wait time of
186202 1 second if Webex Teams returns a `Retry-After` header of 0 seconds.
187-
188203 """
189204
205+ super (RateLimitError , self ).__init__ (response )
206+
190207
191208class RateLimitWarning (UserWarning ):
192209 """Webex Teams rate-limit exceeded warning.
@@ -196,18 +213,20 @@ class RateLimitWarning(UserWarning):
196213 """
197214
198215 def __init__ (self , response ):
199- super (RateLimitWarning , self ).__init__ ()
216+ assert isinstance (response , requests .Response )
217+
218+ # Extended warning attributes
200219 self .retry_after = max (1 , int (response .headers .get ('Retry-After' , 15 )))
201220 """The `Retry-After` time period (in seconds) provided by Webex Teams.
202221
203222 Defaults to 15 seconds if the response `Retry-After` header isn't
204223 present in the response headers, and defaults to a minimum wait time of
205224 1 second if Webex Teams returns a `Retry-After` header of 0 seconds.
206-
207225 """
208226
209- def __str__ (self ):
210- """Webex Teams rate-limit exceeded warning message."""
211- return "Rate-limit response received; the request will " \
212- "automatically be retried in {0} seconds." \
213- "" .format (self .retry_after )
227+ super (RateLimitWarning , self ).__init__ ()
228+
229+
230+ class MalformedResponse (webexteamssdkException ):
231+ """Raised when a malformed response is received from Webex Teams."""
232+ pass
0 commit comments