@@ -45,9 +45,31 @@ def load_from_vcap_services(service_name):
4545
4646
4747class WatsonException (Exception ):
48+ """
49+ Custom exception class for Watson Services.
50+ """
4851 pass
4952
5053
54+ class WatsonApiException (WatsonException ):
55+ """
56+ Custom exception class for errors returned from Watson APIs.
57+
58+ :param int code: The HTTP status code returned.
59+ :param str message: A message describing the error.
60+ :param dict info: A dictionary of additional information about the error.
61+ """
62+ def __init__ (self , code , message , info = None ):
63+ # Call the base class constructor with the parameters it needs
64+ super (WatsonApiException , self ).__init__ (message )
65+ self .message = message
66+ self .code = code
67+ self .info = info
68+
69+ def __str__ (self ):
70+ return 'Error: ' + self .message + ', Code: ' + str (self .code )
71+
72+
5173class WatsonInvalidArgument (WatsonException ):
5274 pass
5375
@@ -115,7 +137,7 @@ def __init__(self, vcap_services_name, url, username=None, password=None,
115137
116138 if api_key is not None :
117139 if username is not None or password is not None :
118- raise WatsonInvalidArgument (
140+ raise ValueError (
119141 'Cannot set api_key and username and password together' )
120142 self .set_api_key (api_key )
121143 else :
@@ -138,10 +160,9 @@ def __init__(self, vcap_services_name, url, username=None, password=None,
138160
139161 if (self .username is None or self .password is None )\
140162 and self .api_key is None :
141- raise WatsonException (
163+ raise ValueError (
142164 'You must specify your username and password service '
143- 'credentials ' +
144- '(Note: these are different from your Bluemix id)' )
165+ 'credentials (Note: these are different from your Bluemix id)' )
145166
146167 def set_username_and_password (self , username = None , password = None ):
147168 if username == 'YOUR SERVICE USERNAME' :
@@ -171,7 +192,7 @@ def set_default_headers(self, headers):
171192 if isinstance (headers , dict ):
172193 self .default_headers = headers
173194 else :
174- raise WatsonException ("headers parameter must be a dictionary" )
195+ raise TypeError ("headers parameter must be a dictionary" )
175196
176197 # Could make this compute the label_id based on the variable name of the
177198 # dictionary passed in (using **kwargs), but
@@ -192,33 +213,45 @@ def _convert_model(val):
192213 def _get_error_message (response ):
193214 """
194215 Gets the error message from a JSON response.
195- {
196- code: 400
197- error: 'Bad request'
198- }
216+ :return: the error message
217+ :rtype: string
199218 """
200219 error_message = 'Unknown error'
201220 try :
202221 error_json = response .json ()
203222 if 'error' in error_json :
204223 if isinstance (error_json ['error' ], dict ) and 'description' in \
205224 error_json ['error' ]:
206- error_message = 'Error: ' + error_json ['error' ][
207- 'description' ]
225+ error_message = error_json ['error' ]['description' ]
208226 else :
209- error_message = 'Error: ' + error_json ['error' ]
227+ error_message = error_json ['error' ]
210228 elif 'error_message' in error_json :
211- error_message = 'Error: ' + error_json ['error_message' ]
229+ error_message = error_json ['error_message' ]
212230 elif 'msg' in error_json :
213- error_message = 'Error: ' + error_json ['msg' ]
231+ error_message = error_json ['msg' ]
214232 elif 'statusInfo' in error_json :
215- error_message = 'Error: ' + error_json ['statusInfo' ]
216- if 'description' in error_json :
217- error_message += ', Description: ' + error_json ['description' ]
218- error_message += ', Code: ' + str (response .status_code )
233+ error_message = error_json ['statusInfo' ]
219234 return error_message
220235 except :
221- return {'error' : response .text or error_message , 'code' : str (response .status_code )}
236+ return response .text or error_message
237+
238+
239+ @staticmethod
240+ def _get_error_info (response ):
241+ """
242+ Gets the error info (if any) from a JSON response.
243+ :return: A `dict` containing additional information about the error.
244+ :rtype: dict
245+ """
246+ info_keys = ['code_description' , 'description' , 'errors' , 'help' ,
247+ 'sub_code' , 'warnings' ]
248+ error_info = {}
249+ try :
250+ error_json = response .json ()
251+ error_info = {k :v for k , v in error_json .items () if k in info_keys }
252+ except :
253+ pass
254+ return error_info if any (error_info ) else None
222255
223256
224257 def _alchemy_html_request (self , method_name = None , url = None , html = None ,
@@ -333,13 +366,14 @@ def request(self, method, url, accept_json=False, headers=None,
333366 response_json = response .json ()
334367 if 'status' in response_json and response_json ['status' ] \
335368 == 'ERROR' :
336- response . status_code = 400
369+ status_code = 400
337370 error_message = 'Unknown error'
371+
338372 if 'statusInfo' in response_json :
339373 error_message = response_json ['statusInfo' ]
340374 if error_message == 'invalid-api-key' :
341- response . status_code = 401
342- raise WatsonException ( 'Error: ' + error_message )
375+ status_code = 401
376+ raise WatsonApiException ( status_code , error_message )
343377 return response_json
344378 return response
345379 else :
@@ -348,4 +382,6 @@ def request(self, method, url, accept_json=False, headers=None,
348382 'invalid credentials '
349383 else :
350384 error_message = self ._get_error_message (response )
351- raise WatsonException (error_message )
385+ error_info = self ._get_error_info (response )
386+ raise WatsonApiException (response .status_code , error_message ,
387+ error_info )
0 commit comments