annotate webcalc/webcalc.py @ 0:1eea6356d2e5

initial import of webcalc
author k0s <k0scist@gmail.com>
date Mon, 07 Sep 2009 15:09:03 -0400
parents
children 12ac99c240ca
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
1 """
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
2 webcalc: a view with webob
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
3 """
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
4
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
5 import math
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
6 from pkg_resources import iter_entry_points
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
7 from pkg_resources import resource_filename
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
8 from webob import Request, Response, exc
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
9
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
10 class WebcalcView(object):
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
11
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
12 ### class level variables
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
13 defaults = { 'formatter': 'text/plain' }
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
14
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
15 def __init__(self, **kw):
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
16 for key in self.defaults:
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
17 setattr(self, key, kw.get(key, self.defaults[key]))
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
18 self.formatters = {}
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
19 for entry_point in iter_entry_points('webcalc.formatters'):
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
20 try:
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
21 formatter = entry_point.load()
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
22 except:
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
23 continue
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
24 self.formatters[entry_point.name] = formatter
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
25
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
26 assert self.formatter in self.formatters
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
27
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
28 self.response_functions = { 'GET': self.get,
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
29 'POST': self.get,
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
30 }
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
31
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
32 ### methods dealing with HTTP
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
33 def __call__(self, environ, start_response):
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
34 request = Request(environ)
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
35 res = self.make_response(request)
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
36 return res(environ, start_response)
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
37
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
38 def make_response(self, request):
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
39 return self.response_functions.get(request.method, self.error)(request)
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
40
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
41 def get_response(self, text, content_type='text/html'):
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
42 res = Response(content_type=content_type, body=text)
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
43 return res
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
44
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
45 def get(self, request):
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
46 """
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
47 return response to a GET requst
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
48 """
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
49
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
50
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
51 equation = request.path_info.strip('/').strip()
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
52 if not equation:
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
53 return self.get_response('<html><body><form method="post"><input type="text" name="equation"/></form></body></html>')
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
54
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
55
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
56 # limit scope of execution
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
57 forbidden = set([';', '=', 'import', 'from', 'with'])
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
58 forbidden.update(dir(__builtins__))
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
59 assert not [ i for i in forbidden
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
60 if i in equation ]
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
61 math_globals = dict([(i, getattr(math, i))
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
62 for i in dir(math)
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
63 if not i.startswith('_')])
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
64
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
65 # get the range of variables
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
66 variables = []
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
67 assert 'result' not in request.GET
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
68 for name, value in request.GET.items():
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
69 if name == 'format':
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
70 continue
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
71 values = self.values(value)
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
72 if variables:
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
73 if len(values) == 1:
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
74 for var in variables:
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
75 var[name] = values[0]
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
76 else:
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
77 old_variables = [ i.copy() for i in variables[:] ]
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
78 variables = []
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
79 for val in values:
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
80 row = [ i.copy() for i in old_variables ]
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
81 for item in row:
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
82 item[name] = val
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
83 variables.extend(row)
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
84 else:
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
85 variables = [ { name: val }
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
86 for val in values ]
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
87
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
88 # evaluate the equation
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
89 if variables:
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
90 for var in variables:
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
91 result = float(eval(equation, math_globals, var))
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
92 var['result'] = result
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
93 else:
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
94 result = float(eval(equation, math_globals, {}))
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
95 variables = [{'result': result}]
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
96
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
97 # format the result
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
98 format = request.params.get('format') or request.content_type or self.formatter
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
99 formatter = self.formatters.get(format, self.formatters[self.formatter])
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
100 return self.get_response(formatter(variables), format)
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
101
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
102 def post(self, request):
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
103 """
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
104 return response to a POST request
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
105 """
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
106 import pdb; pdb.set_trace()
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
107
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
108 return exc.HTTPOk("Ok")
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
109
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
110 def error(self, request):
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
111 """deal with non-supported methods"""
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
112 return exc.HTTPMethodNotAllowed("Only %r operations are allowed" % self.response_functions.keys())
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
113
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
114
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
115 def values(self, string):
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
116 """
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
117 >>> values('1,2,3,4')
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
118 [1,2,3,4]
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
119 >>> values('1..0.2..2')
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
120 [1,1.2,1.4,1.6,1.8,2]
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
121 """
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
122 retval = []
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
123 tokens = [i.strip() for i in string.split(',')
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
124 if i.strip()]
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
125 for token in tokens:
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
126 try:
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
127 value = float(token)
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
128 retval.append(value)
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
129 continue
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
130 except ValueError:
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
131 pass
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
132 start, step, end = token.split('..')
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
133 start = float(start)
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
134 step = float(step)
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
135 end = float(end)
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
136
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
137 values = [ start ]
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
138 npoints = (end - start)/step
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
139 npoints = int(npoints)
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
140 values.extend([i*step + start
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
141 for i in range(1, npoints)])
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
142 values.append(end)
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
143 retval.extend(values)
1eea6356d2e5 initial import of webcalc
k0s <k0scist@gmail.com>
parents:
diff changeset
144 return retval