/
rendr
executable file
·138 lines (110 loc) · 3.9 KB
/
rendr
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#!/usr/bin/env python
import sys, re
import json, urllib2, socket
from optparse import OptionParser
from tumblelog import Tumblelog
import templater
def parse_tumblr_json(stream):
'''
Load in the contents of a stream and get rid of the bad stuff (i.e. the
Javascript variable assignment and end semicolon)
'''
contents = load_stream(stream)
# Strip out 'var tumblr_api_read = ' at the start
# and ';\n' at the end
return json.loads(contents[22:].strip(';\n'))
def load_stream(stream):
contents = u''
while True:
chunk = stream.read()
contents = contents + chunk.decode('utf8')
if chunk == '':
break
return contents
def load_blog(url):
'''
Open the URL, load the JSON and instantiate a Tumbleblog object
'''
if re.search(r'^https?://', url):
if not re.search(r'/api/read/json/?$', url):
if not re.search(r'/$', url):
url = url + '/'
url = url + 'api/read/json'
stream = urllib2.urlopen(url)
else:
stream = open(url, 'r')
tumblr = parse_tumblr_json(stream)
stream.close()
blog = Tumblelog(tumblr)
return blog
def save_blog(url, theme, output, **optional_args):
'''
Load the blog and theme, render it, and save the output.
'''
blog = load_blog(url)
blog.twitterUsername = optional_args.get('twitter', None)
with open(theme, 'r') as f:
template = load_stream(f)
result = templater.render(blog, template)
html = result.encode('utf8')
with open(output, 'w') as out:
out.write(html)
def serve_blog(url, theme, port, **optional_args):
'''
Load the blog and start a WSGI server. When a request is made, load the
theme and render it.
'''
from wsgiref.simple_server import make_server
blog = load_blog(url)
blog.twitterUsername = optional_args.get('twitter', None)
def application(environ, start_response):
from wsgiref.util import setup_testing_defaults
setup_testing_defaults(environ)
status = '200 OK'
headers = [('Content-type', 'text/html')]
start_response(status, headers)
with open(theme) as f:
template = load_stream(f)
result = templater.render(blog, template)
html = result.encode('utf8')
return html
httpd = make_server('', port, application)
print "Listening on http://localhost:%d/" % port
httpd.serve_forever()
def main(args):
parser = OptionParser('%prog [options] {blog url} {theme file}')
parser.add_option('-o','--output-file', dest='output',
help='instead of starting a webserver, save output to a file')
parser.add_option('-t','--twitter', dest='twitter',
help='a twitter username to use when rendering the theme')
parser.add_option('-p','--port', dest='port', type='int', default=88625,
help='port on which the server will listen')
options, args = parser.parse_args(args)
try:
url = args[0]
except IndexError:
parser.error('you must specify a valid Tumblr url (or local file of '+
'JSON data)')
try:
theme = args[1]
except IndexError:
parser.error('you must specify a theme file')
try:
with open(theme) as f:
pass
except IOError:
parser.error('invalid theme file, "%s" could not be found' % theme)
if options.output:
save_blog(url, theme, options.output)
else:
try:
serve_blog(url, theme, options.port, twitter=options.twitter)
except urllib2.HTTPError, e:
return 'Could not connect to %s: %s' % (url, e)
except socket.error, e:
return 'Unable to open socket: %s' % e
except KeyboardInterrupt, e:
print 'Goodbye'
return 0
if __name__ == '__main__':
sys.exit(main(sys.argv[1:]))