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

Benjamin Mako Hill || Want to submit a patch?