From: Hatem Nassrat Date: Wed, 18 Feb 2009 07:04:03 +0000 (-0400) Subject: Automatically generating _POST_ACTIONS list. X-Git-Tag: twitter-1.1~6 X-Git-Url: https://jfr.im/git/z_archive/twitter.git/commitdiff_plain/4e9d63435b514ee669b2fb0045180aa1b49abfdc?hp=327e556bac9b74a1fe975d4c632c698493ff31cd Automatically generating _POST_ACTIONS list. added script to generate _POST_ACTIONS added auto generated _POST_ACTIONS file removed _POST_ACTIONS from api.py --- diff --git a/twitter/api.py b/twitter/api.py index c913dc2..118d4fb 100644 --- a/twitter/api.py +++ b/twitter/api.py @@ -6,6 +6,8 @@ import urllib2 from exceptions import Exception +from twitter.twitter_globals import _POST_ACTIONS + def _py26OrGreater(): import sys return sys.hexversion > 0x20600f0 @@ -22,11 +24,6 @@ class TwitterError(Exception): """ pass -# These actions require POST http requests instead of GET -_POST_ACTIONS = [ - "create", "update", "destroy", "new", "follow", "leave", - ] - class TwitterCall(object): def __init__( self, username, password, format, domain, uri="", agent=None): @@ -56,7 +53,7 @@ class TwitterCall(object): id = kwargs.pop('id', None) if id: uri += "/%s" %(id) - + encoded_kwargs = urlencode(kwargs.items()) argStr = "" argData = None @@ -95,7 +92,7 @@ class TwitterCall(object): class Twitter(TwitterCall): """ The minimalist yet fully featured Twitter API class. - + Get RESTful data by accessing members of this class. The result is decoded python objects (lists and dicts). @@ -103,27 +100,27 @@ class Twitter(TwitterCall): http://apiwiki.twitter.com/ http://groups.google.com/group/twitter-development-talk/web/api-documentation - + Examples:: - + twitter = Twitter("hello@foo.com", "password123") - + # Get the public timeline twitter.statuses.public_timeline() - + # Get a particular friend's timeline twitter.statuses.friends_timeline(id="billybob") - + # Also supported (but totally weird) twitter.statuses.friends_timeline.billybob() - + # Send a direct message twitter.direct_messages.new( user="billybob", text="I think yer swell!") Searching Twitter:: - + twitter_search = Twitter(domain="search.twitter.com") # Find the latest search trends @@ -144,14 +141,14 @@ class Twitter(TwitterCall): # The screen name of the user who wrote the first 'tweet' x[0]['user']['screen_name'] - + Getting raw XML data:: - + If you prefer to get your Twitter data in XML format, pass format="xml" to the Twitter object when you instantiate it: - + twitter = Twitter(format="xml") - + The output will not be parsed in any way. It will be a raw string of XML. """ diff --git a/twitter/twitter_globals.py b/twitter/twitter_globals.py new file mode 100644 index 0000000..46e1005 --- /dev/null +++ b/twitter/twitter_globals.py @@ -0,0 +1,32 @@ +''' + This module is automatically generated using `update.py` + + ..data:: + + `_POST_ACTIONS`: Methods that require the use of POST +''' + +_POST_ACTIONS = [ + + # Status Methods + 'update', + + # Direct Message Methods + 'new', + + # Account Methods + 'update_profile_image', 'update_delivery_device', 'update_profile', + 'update_profile_background_image', 'update_profile_colors', + 'update_location', 'end_session', + + # Notification Methods + 'leave', 'follow', + + # Status Methods, Block Methods, Direct Message Methods, + # Friendship Methods, Favorite Methods + 'destroy', + + # Block Methods, Friendship Methods, Favorite Methods + 'create', + +] diff --git a/twitter/update.py b/twitter/update.py new file mode 100644 index 0000000..9ad8374 --- /dev/null +++ b/twitter/update.py @@ -0,0 +1,136 @@ +''' +This is a development script, intended for office use only. + +This script generates output the _POST_ACTIONS variable +for placement in the twitter_globals.py + +Example Util: + + python update.py >twitter_globals.py + +Dependencies: + + * (easy_install) BeautifulSoup +''' + +import sys +from urllib import urlopen as _open +from BeautifulSoup import BeautifulSoup +from htmlentitydefs import codepoint2name + +def uni2html(u): + ''' + Convert unicode to html. + + Basically leaves ascii chars as is, and attempts to encode unicode chars as + HTML entities. If the conversion fails the character is skipped. + ''' + htmlentities = list() + for c in u: + ord_c = ord(c) + if ord_c < 128: + # ignoring all ^chars like ^M ^R ^E + if ord_c >31: + htmlentities.append(c) + else: + try: + htmlentities.append('&%s;' % codepoint2name[ord_c]) + except KeyError: + pass # Charachter unknown + return ''.join(htmlentities) + +def print_fw(iterable, joins=', ', prefix='', indent=0, width=79, trail=False): + ''' + PPrint an iterable (of stringable elements). + + Entries are joined using `joins` + A fixed_width (fw) is maintained of `width` chars per line + Each line is indented with `indent`*4 spaces + Lines are then prefixed with `prefix` string + if `trail` a trailing comma is sent to stdout + A newline is written after all is printed. + ''' + shift_width = 4 + preline = '%s%s' %(' '*shift_width, prefix) + linew = len(preline) + sys.stdout.write(preline) + for i, entry in enumerate(iterable): + if not trail and i == len(iterable) - 1: + sentry = str(entry) + else: + sentry = '%s%s' %(str(entry), joins) + if linew + len(sentry) > width: + sys.stdout.write('\n%s' %(preline)) + linew = len(preline) + sys.stdout.write(sentry) + linew += len(sentry) + sys.stdout.write('\n') + + +def main(): + ''' + Main function the prints twitter's _POST_ACTIONS to stdout + + TODO: look at possibly dividing up this function + ''' + + apifile = _open('http://apiwiki.twitter.com/REST+API+Documentation') + try: + apihtml = uni2html(apifile.read()) + finally: + apifile.close() + + ## Parsing the ApiWiki Page + + apidoc = BeautifulSoup(apihtml) + toc = apidoc.find('div', {'class':'toc'}) + toc_entries = toc.findAll('li', text=lambda text: 'Methods' in text) + method_links = {} + for entry in toc_entries: + links = entry.parent.parent.findAll('a') + method_links[links[0].string] = [x['href'] for x in links[1:]] + + # Create unique hash of mehods with POST_ACTIONS + POST_ACTION_HASH = {} + for method_type, methods in method_links.items(): + for method in methods: + # Strip the hash (#) mark from the method id/name + method = method[1:] + method_body = apidoc.find('a', {'name': method}) + value = list(method_body.findNext( + 'b', text=lambda text: 'Method' in text + ).parent.parent.childGenerator())[-1] + if 'POST' in value: + method_name = method_body.findNext('h3').string + try: + POST_ACTION_HASH[method_name] += (method_type,) + except KeyError: + POST_ACTION_HASH[method_name] = (method_type,) + + # Reverse the POST_ACTION_HASH + # this is really only done to generate comment strings + POST_ACTION_HASH_R = {} + for method, method_types in POST_ACTION_HASH.items(): + try: + POST_ACTION_HASH_R[method_types].append(method) + except KeyError: + POST_ACTION_HASH_R[method_types] = [method] + + ## Print the _POST_ACTIONS to stdout as a Python List + print """''' + This module is automatically generated using `update.py` + + ..data:: + + `_POST_ACTIONS`: Methods that require the use of POST +''' +""" + print '_POST_ACTIONS = [\n' + for method_types, methods in POST_ACTION_HASH_R.items(): + print_fw(method_types, prefix='# ', indent=1) + print_fw([repr(str(x)) for x in methods], indent=1, trail=True) + print "" + print ']' + +if __name__ == "__main__": + main()