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

Benjamin Mako Hill || Want to submit a patch?