]> jfr.im git - z_archive/twitter.git/blame - twitter/update.py
Automatically generating _POST_ACTIONS list.
[z_archive/twitter.git] / twitter / update.py
CommitLineData
4e9d6343
HN
1'''
2This is a development script, intended for office use only.
3
4This script generates output the _POST_ACTIONS variable
5for placement in the twitter_globals.py
6
7Example Util:
8
9 python update.py >twitter_globals.py
10
11Dependencies:
12
13 * (easy_install) BeautifulSoup
14'''
15
16import sys
17from urllib import urlopen as _open
18from BeautifulSoup import BeautifulSoup
19from htmlentitydefs import codepoint2name
20
21def uni2html(u):
22 '''
23 Convert unicode to html.
24
25 Basically leaves ascii chars as is, and attempts to encode unicode chars as
26 HTML entities. If the conversion fails the character is skipped.
27 '''
28 htmlentities = list()
29 for c in u:
30 ord_c = ord(c)
31 if ord_c < 128:
32 # ignoring all ^chars like ^M ^R ^E
33 if ord_c >31:
34 htmlentities.append(c)
35 else:
36 try:
37 htmlentities.append('&%s;' % codepoint2name[ord_c])
38 except KeyError:
39 pass # Charachter unknown
40 return ''.join(htmlentities)
41
42def print_fw(iterable, joins=', ', prefix='', indent=0, width=79, trail=False):
43 '''
44 PPrint an iterable (of stringable elements).
45
46 Entries are joined using `joins`
47 A fixed_width (fw) is maintained of `width` chars per line
48 Each line is indented with `indent`*4 spaces
49 Lines are then prefixed with `prefix` string
50 if `trail` a trailing comma is sent to stdout
51 A newline is written after all is printed.
52 '''
53 shift_width = 4
54 preline = '%s%s' %(' '*shift_width, prefix)
55 linew = len(preline)
56 sys.stdout.write(preline)
57 for i, entry in enumerate(iterable):
58 if not trail and i == len(iterable) - 1:
59 sentry = str(entry)
60 else:
61 sentry = '%s%s' %(str(entry), joins)
62 if linew + len(sentry) > width:
63 sys.stdout.write('\n%s' %(preline))
64 linew = len(preline)
65 sys.stdout.write(sentry)
66 linew += len(sentry)
67 sys.stdout.write('\n')
68
69
70def main():
71 '''
72 Main function the prints twitter's _POST_ACTIONS to stdout
73
74 TODO: look at possibly dividing up this function
75 '''
76
77 apifile = _open('http://apiwiki.twitter.com/REST+API+Documentation')
78 try:
79 apihtml = uni2html(apifile.read())
80 finally:
81 apifile.close()
82
83 ## Parsing the ApiWiki Page
84
85 apidoc = BeautifulSoup(apihtml)
86 toc = apidoc.find('div', {'class':'toc'})
87 toc_entries = toc.findAll('li', text=lambda text: 'Methods' in text)
88 method_links = {}
89 for entry in toc_entries:
90 links = entry.parent.parent.findAll('a')
91 method_links[links[0].string] = [x['href'] for x in links[1:]]
92
93 # Create unique hash of mehods with POST_ACTIONS
94 POST_ACTION_HASH = {}
95 for method_type, methods in method_links.items():
96 for method in methods:
97 # Strip the hash (#) mark from the method id/name
98 method = method[1:]
99 method_body = apidoc.find('a', {'name': method})
100 value = list(method_body.findNext(
101 'b', text=lambda text: 'Method' in text
102 ).parent.parent.childGenerator())[-1]
103 if 'POST' in value:
104 method_name = method_body.findNext('h3').string
105 try:
106 POST_ACTION_HASH[method_name] += (method_type,)
107 except KeyError:
108 POST_ACTION_HASH[method_name] = (method_type,)
109
110 # Reverse the POST_ACTION_HASH
111 # this is really only done to generate comment strings
112 POST_ACTION_HASH_R = {}
113 for method, method_types in POST_ACTION_HASH.items():
114 try:
115 POST_ACTION_HASH_R[method_types].append(method)
116 except KeyError:
117 POST_ACTION_HASH_R[method_types] = [method]
118
119 ## Print the _POST_ACTIONS to stdout as a Python List
120 print """'''
121 This module is automatically generated using `update.py`
122
123 ..data::
124
125 `_POST_ACTIONS`: Methods that require the use of POST
126'''
127"""
128 print '_POST_ACTIONS = [\n'
129 for method_types, methods in POST_ACTION_HASH_R.items():
130 print_fw(method_types, prefix='# ', indent=1)
131 print_fw([repr(str(x)) for x in methods], indent=1, trail=True)
132 print ""
133 print ']'
134
135if __name__ == "__main__":
136 main()