@@ -137,6 +137,11 @@ def __init__(self, message, http_body=None, http_status=None, json_body=None):
137
137
class AuthenticationError (CleverError ):
138
138
pass
139
139
140
+ class TooManyRequestsError (CleverError ):
141
+ def __init__ (self , message , res ):
142
+ self .headers = res
143
+ pass
144
+
140
145
141
146
def convert_to_clever_object (klass , resp , auth ):
142
147
# TODO: to support includes we'll have to infer klass from resp['uri']
@@ -209,11 +214,12 @@ def jsonencode(cls, d):
209
214
return json .dumps (d )
210
215
211
216
def request (self , meth , url , params = {}):
212
- rbody , rcode , my_auth = self .request_raw (meth , url , params )
213
- resp = self .interpret_response (rbody , rcode )
217
+ res , my_auth = self .request_raw (meth , url , params )
218
+ resp = self .interpret_response (res )
214
219
return resp , my_auth
215
220
216
- def handle_api_error (self , rbody , rcode , resp ):
221
+ def handle_api_error (self , res , resp ):
222
+ rbody , header , rcode , error = res ['body' ], res ['header' ], res ['code' ], None
217
223
try :
218
224
error = resp ['error' ]
219
225
except (KeyError , TypeError ):
@@ -224,6 +230,8 @@ def handle_api_error(self, rbody, rcode, resp):
224
230
raise InvalidRequestError (error , rbody , rcode , resp )
225
231
elif rcode == 401 :
226
232
raise AuthenticationError (error , rbody , rcode , resp )
233
+ elif rcode == 429 :
234
+ raise TooManyRequestsError (error , res )
227
235
else :
228
236
raise APIError (error , rbody , rcode , resp )
229
237
@@ -276,17 +284,18 @@ def request_raw(self, meth, url, params={}):
276
284
raise CleverError (
277
285
"Clever Python library bug discovered: invalid httplib %s. Please report to support@clever.com" % (_httplib , ))
278
286
logger .debug ('API request to %s returned (response code, response body) of (%d, %r)' %
279
- (abs_url , rcode , rbody ))
280
- return rbody , rcode , my_auth
287
+ (abs_url , res [ 'code' ], res [ 'body' ] ))
288
+ return res , my_auth
281
289
282
- def interpret_response (self , rbody , rcode ):
290
+ def interpret_response (self , http_res ):
291
+ rbody , rheader , rcode = http_res ['body' ], http_res ['header' ], http_res ['code' ]
283
292
try :
284
- resp = json .loads (rbody )
293
+ resp = json .loads (rbody ) if rcode != 429 else { 'error' : 'Too Many Requests' }
285
294
except Exception :
286
295
raise APIError ("Invalid response body from API: %s (HTTP response code was %d)" %
287
296
(rbody , rcode ), rbody , rcode )
288
297
if not (200 <= rcode < 300 ):
289
- self .handle_api_error (rbody , rcode , resp )
298
+ self .handle_api_error (http_res , resp )
290
299
return resp
291
300
292
301
def requests_request (self , meth , abs_url , headers , params ):
@@ -328,11 +337,12 @@ def requests_request(self, meth, abs_url, headers, params):
328
337
# are succeptible to the same and should be updated.
329
338
content = result .content
330
339
status_code = result .status_code
340
+ header = result .headers
331
341
except Exception , e :
332
342
# Would catch just requests.exceptions.RequestException, but can
333
343
# also raise ValueError, RuntimeError, etc.
334
344
self .handle_requests_error (e )
335
- return content , status_code
345
+ return { 'body' : content , 'header' : header , 'code' : status_code }
336
346
337
347
def handle_requests_error (self , e ):
338
348
if isinstance (e , requests .exceptions .RequestException ):
@@ -387,9 +397,7 @@ def pycurl_request(self, meth, abs_url, headers, params):
387
397
curl .perform ()
388
398
except pycurl .error , e :
389
399
self .handle_pycurl_error (e )
390
- rbody = s .getvalue ()
391
- rcode = curl .getinfo (pycurl .RESPONSE_CODE )
392
- return rbody , rcode
400
+ return {'body' : s .getvalue (), 'header' : 'feature pending' , 'code' : curl .getinfo (pycurl .RESPONSE_CODE )}
393
401
394
402
def handle_pycurl_error (self , e ):
395
403
if e [0 ] in [pycurl .E_COULDNT_CONNECT ,
@@ -433,7 +441,7 @@ def urlfetch_request(self, meth, abs_url, headers, params):
433
441
result = urlfetch .fetch (** args )
434
442
except urlfetch .Error , e :
435
443
self .handle_urlfetch_error (e , abs_url )
436
- return result .content , result .status_code
444
+ return { 'body' : result .content , 'header' : result .headers , 'code' : result . status_code }
437
445
438
446
def handle_urlfetch_error (self , e , abs_url ):
439
447
if isinstance (e , urlfetch .InvalidURLError ):
@@ -472,12 +480,13 @@ def urllib2_request(self, meth, abs_url, headers, params):
472
480
response = urllib2 .urlopen (req )
473
481
rbody = response .read ()
474
482
rcode = response .code
483
+ rheader = 'feature pending'
475
484
except urllib2 .HTTPError , e :
476
485
rcode = e .code
477
486
rbody = e .read ()
478
487
except (urllib2 .URLError , ValueError ), e :
479
488
self .handle_urllib2_error (e , abs_url )
480
- return rbody , rcode
489
+ return { 'body' : rbody , 'header' : rheader , 'code' : rcode }
481
490
482
491
def handle_urllib2_error (self , e , abs_url ):
483
492
msg = "Unexpected error communicating with Clever. If this problem persists, let us know at support@clever.com."
0 commit comments