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

Benjamin Mako Hill || Want to submit a patch?