moved templating system to jinja
[yourule] / yourule.py
1 #!/usr/bin/env python
2
3 from __future__ import division
4 import web
5 import sys, os, re
6 from storm.locals import *
7 from svgruler import SVGRuler
8
9 from jinja import Environment, FileSystemLoader
10 jinja_env = Environment('<%', '%>', '<%=', '%>', '<%#', '%>', 
11                         loader=FileSystemLoader('templates/'))
12
13 def render(filename, vars):
14     web.header("Content-Type","text/html; charset=utf-8")
15     tmpl = jinja_env.get_template(filename + '.tmpl')
16     print tmpl.render(vars)
17     web.debug(web.ctx)
18
19 # the url map for the application
20 urls = ( '/', 'index',
21          '/ruler_([0-9\.]+)px_([0-9\.]+)([A-Za-z]+).(svg|png|jpg)', 'ruler_img',
22          '/show/(.*(svg|png|jpg))', 'show_ruler',
23          '/gallery(.*)', 'gallery',
24          '/delete/(\d+)', 'delete',
25          '/undelete/(\d+)', 'undelete')
26
27 database = create_database("sqlite:yourule.db")
28 store = Store(database)
29
30 class Ruler(object):
31     __storm_table__ = "gallery"
32     id = Int(primary=True)
33     pixel_width = Float()
34     unit_width = Float()
35     model = Unicode()
36     units = Unicode()
37     show = Int()
38     cm_in_ratio = 0.3937
39
40     def __init__(self, **kw):
41         self.pixel_width = float(kw['pixel_width'])
42         self.unit_width = float(kw['unit_width'])
43         self.units = unicode(kw['units'])
44         if kw.has_key('model'):
45             self.model = unicode(kw['model'])
46         else:
47             self.model = u''
48
49     def cm_width(self):
50         if self.units == 'centimeters':
51             return self.unit_width
52         elif self.units == 'inches':
53             return(round(self.unit_width / self.cm_in_ratio, 2))
54
55     def in_width(self):
56         if self.units == 'inches':
57             return self.unit_width
58         elif self.units == 'centimeters':
59             return(round(self.unit_width * self.cm_in_ratio, 2))
60
61     def url(self):
62         return('ruler_%spx_%s%s.png' % (self.pixel_width,
63                                         self.unit_width, self.units))
64
65
66 class index:
67     def GET(self):
68         render('index', locals())
69
70     def POST(self):
71         input = web.input()
72
73         errormsg = validate_input(input)
74
75         if errormsg:
76             pixel_width = input['pixel_width']
77             unit_width = input['unit_width']
78             units = input['units']
79             render('index', locals())
80         else:
81             ruler = Ruler(pixel_width = input['pixel_width'], 
82                           unit_width = input['unit_width'], 
83                           units = input['units'])
84             
85             web.redirect('/show/%s' % ruler.url())
86
87 class show_ruler:
88     def GET(self, ruler_url, ext):
89         if web.input().has_key('fromgallery'):
90             fromgallery = True
91         else:
92             fromgallery = False
93
94         other_unit, other_unit_url = get_other_unit(ruler_url)
95
96         render('show_ruler', locals())
97
98 class ruler_img:
99     def GET(self, pixel_width=None, unit_width=None, units=None, ext=None):
100
101         # TODO check to see if it's a format that we support
102
103         # set ruler height to be 200 px always
104         pixel_width = float(pixel_width)
105         unit_width = float(unit_width)
106
107         ruler_height = 200
108
109         scale = pixel_width / unit_width
110         ruler_length = int(unit_width)
111
112         ruler = SVGRuler(scale, units, ruler_height, ruler_length)
113
114         # print the header
115         if ext == 'svg': ext = 'svg+xml'
116         web.header("Content-Type", "image/%s" % ext)
117
118         if ext == 'svg+xml':
119             sys.stdout.write(ruler.getxml())
120         else:
121             pin, pout = os.popen2('convert -size %sx%s - %s:-' % \
122                                   (pixel_width, ruler_height, ext))
123
124             pin.write(ruler.getxml())
125             pin.close()
126             sys.stdout.write(pout.read())
127
128 class gallery:
129     def GET(self, ruler_url):
130
131         if ruler_url:
132             pixel_width, unit_width, units = process_ruler_url(ruler_url)[0:3]
133
134         rulers = store.find(Ruler, Ruler.show == 1)
135         rulers.order_by(Ruler.model)
136         render('gallery', locals())
137
138     def POST(self, ruler_url):
139         input = web.input()
140
141         errormsg = validate_input(input)
142         if not input.model:
143             errormsg = 'Please fill out all fields.'
144
145         if errormsg:
146             pixel_width = input['pixel_width']
147             unit_width = input['unit_width']
148             units = input['units']
149             model = input['model']
150         else:
151             new_ruler = Ruler(pixel_width = input['pixel_width'],
152                               unit_width = input['unit_width'],
153                               units = input['units'],
154                               model = input['model'])
155
156             store.add(new_ruler)
157             store.commit()
158
159         rulers = store.find(Ruler, Ruler.show == 1)
160         rulers.order_by(Ruler.model)
161         render('gallery', locals())
162
163 class delete:
164     def GET(self, id):
165         ruler = store.get(Ruler, int(id))
166         ruler.show = 0
167         store.commit()
168         web.redirect('/gallery')
169
170
171 class undelete:
172     def GET(self, id):
173         ruler = store.get(Ruler, int(id))
174         ruler.show = 1
175         store.commit()
176         web.redirect('/gallery')
177
178 def get_other_unit(url):
179     pixel_width, unit_width, units = process_ruler_url(url)[0:3]
180
181     ruler = Ruler(pixel_width=pixel_width, unit_width=unit_width, units=units)
182     pixel_width, unit_width, units = process_ruler_url(url)[0:3]
183
184     if units == 'centimeters':
185         units = 'inches'
186         unit_width = ruler.in_width()
187     elif units == 'inches':
188         units = 'centimeters'
189         unit_width = ruler.cm_width()
190
191     new_ruler = Ruler(pixel_width=pixel_width, unit_width=unit_width,
192                       units=units)
193
194     web.debug(units)
195     return(units, new_ruler.url())
196
197
198 def process_ruler_url(url):
199     url = re.sub(r'^/?(ruler.*)$', r'\1', url)
200     return(re.match( r'ruler_([\d\.]+)px_([\d\.]+)(\w+).(png|svg|jpg)',
201            url).groups())
202
203 def validate_input(input):
204     errormsg = False
205
206     if not input.pixel_width \
207         or not input.unit_width:
208         errormsg = 'Please fill out all fields.'
209     elif not re.match('^[\d\.]+$', input.pixel_width) \
210         or not re.match('^[\d\.]+$', input.unit_width):
211         errormsg = "Widths must be numbers."
212     elif input['pixel_width'] < 0 \
213         or input['unit_width'] < 0:
214         errormsg = 'Widths must be greater than postive.'
215
216     return(errormsg)
217
218
219 web.webapi.internalerror = web.debugerror
220 if __name__ == "__main__":
221     web.run(urls, globals(), web.reloader)
222
223 #application = web.wsgifunc(web.webpyfunc(urls, globals()))
224

Benjamin Mako Hill || Want to submit a patch?