Several improvements to allow for debugging , error handling :

- added twitter's http status codes to twitter_endpoints.py ( dict index on status code, value is a tuple of name + description )
- created an internal stash called '_last_call' that stores details of the last api call ( the call, response data, headers, url, etc )
- better error handling for api issues:
- - raises an error when the status code is not 200 or 304
- - raises TwythonAPILimit when a 420 rate limit code is returned
- - raises a TwythonError on other issues, setting the correct status code and using messages that are from the twitter API
- wraps a successful read in a try/except block.  there's an error i haven't been able to reproduce where invalid content can get in there, it would be nice to catch it and write a handler for it.  ( the previous functions were all introducted to allow this to be debugged )
- added a 'get_lastfunction_header' method. if the API has not been called yet , raises a TwythonError.  otherwise it attempts to return the header value twitter last sent.  useful for x-ratelimit-limit , x-ratelimit-remaining , x-ratelimit-class , x-ratelimit-reset
This commit is contained in:
jonathan vanasco 2012-04-08 18:37:47 -04:00
parent 9153fdf41b
commit 59b0386564
2 changed files with 70 additions and 2 deletions

View file

@ -328,3 +328,18 @@ api_table = {
'method': 'POST',
},
}
# from https://dev.twitter.com/docs/error-codes-responses
twitter_http_status_codes= {
200 : ('OK','Success!'),
304 : ('Not Modified','There was no new data to return.'),
400 : ('Bad Request','The request was invalid. An accompanying error message will explain why. This is the status code will be returned during rate limiting.'),
401 : ('Unauthorized','Authentication credentials were missing or incorrect.'),
403 : ('Forbidden','The request is understood, but it has been refused. An accompanying error message will explain why. This code is used when requests are being denied due to update limits.'),
404 : ('Not Found','The URI requested is invalid or the resource requested, such as a user, does not exists.'),
406 : ('Not Acceptable','Returned by the Search API when an invalid format is specified in the request.'),
420 : ('Enhance Your Calm','Returned by the Search and Trends API when you are being rate limited.'),
500 : ('Internal Server Error','Something is broken. Please post to the group so the Twitter team can investigate.'),
502 : ('Bad Gateway','Twitter is down or being upgraded.'),
503 : ('Service Unavailable','The Twitter servers are up, but overloaded with requests. Try again later.'),
}

View file

@ -28,7 +28,7 @@ except ImportError:
# Twython maps keyword based arguments to Twitter API endpoints. The endpoints
# table is a file with a dictionary of every API endpoint that Twython supports.
from twitter_endpoints import base_url, api_table
from twitter_endpoints import base_url, api_table , twitter_http_status_codes
# There are some special setups (like, oh, a Django application) where
@ -207,6 +207,9 @@ class Twython(object):
for key in api_table.keys():
self.__dict__[key] = setFunc(key)
# create stash for last call intel
self._last_call= None
def _constructFunc(self, api_call, **kwargs):
# Go through and replace any mustaches that are in our API url.
fn = api_table[api_call]
@ -229,8 +232,58 @@ class Twython(object):
func = getattr(self.client, method)
response = func(url, data=myargs)
content= response.content.decode('utf-8')
return simplejson.loads(response.content.decode('utf-8'))
# create stash for last function intel
self._last_call= {
'api_call':api_call,
'api_error':None,
'cookies':response.cookies,
'error':response.error,
'headers':response.headers,
'status_code':response.status_code,
'url':response.url,
'content':content,
}
if response.status_code not in ( 200 , 304 ):
# handle rate limiting first
if response.status_code == 420 :
raise TwythonAPILimit( "420 || %s || %s" % twitter_http_status_codes[420] )
if content:
try:
as_json= simplejson.loads(content)
if 'error' in as_json:
self._last_call['api_error']= as_json['error']
except:
pass
raise TwythonError( "%s || %s || %s" % ( response.status_code , twitter_http_status_codes[response.status_code][0] , twitter_http_status_codes[response.status_code][1] ) , error_code=response.status_code )
try:
# sometimes this causes an error, and i haven't caught it yet!
return simplejson.loads(content)
except:
raise
def get_lastfunction_header(self,header):
"""
get_lastfunction_header(self)
returns the header in the last function
this must be called after an API call, as it returns header based information.
this will return None if the header is not present
most useful for the following header information:
x-ratelimit-limit
x-ratelimit-remaining
x-ratelimit-class
x-ratelimit-reset
"""
if self._last_call is None:
raise TwythonError('This function must be called after an API call. It delivers header information.')
if header in self._last_call['headers']:
return self._last_call['headers'][header]
return None
def get_authentication_tokens(self):
"""