Mercurial > hg > webcalc
view 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 |
line wrap: on
line source
""" webcalc: a view with webob """ import math from pkg_resources import iter_entry_points from pkg_resources import resource_filename from webob import Request, Response, exc class WebcalcView(object): ### class level variables defaults = { 'formatter': 'text/plain' } def __init__(self, **kw): for key in self.defaults: setattr(self, key, kw.get(key, self.defaults[key])) self.formatters = {} for entry_point in iter_entry_points('webcalc.formatters'): try: formatter = entry_point.load() except: continue self.formatters[entry_point.name] = formatter assert self.formatter in self.formatters self.response_functions = { 'GET': self.get, 'POST': self.get, } ### methods dealing with HTTP def __call__(self, environ, start_response): request = Request(environ) res = self.make_response(request) return res(environ, start_response) def make_response(self, request): return self.response_functions.get(request.method, self.error)(request) def get_response(self, text, content_type='text/html'): res = Response(content_type=content_type, body=text) return res def get(self, request): """ return response to a GET requst """ equation = request.path_info.strip('/').strip() if not equation: return self.get_response('<html><body><form method="post"><input type="text" name="equation"/></form></body></html>') # limit scope of execution forbidden = set([';', '=', 'import', 'from', 'with']) forbidden.update(dir(__builtins__)) assert not [ i for i in forbidden if i in equation ] math_globals = dict([(i, getattr(math, i)) for i in dir(math) if not i.startswith('_')]) # get the range of variables variables = [] assert 'result' not in request.GET for name, value in request.GET.items(): if name == 'format': continue values = self.values(value) if variables: if len(values) == 1: for var in variables: var[name] = values[0] else: old_variables = [ i.copy() for i in variables[:] ] variables = [] for val in values: row = [ i.copy() for i in old_variables ] for item in row: item[name] = val variables.extend(row) else: variables = [ { name: val } for val in values ] # evaluate the equation if variables: for var in variables: result = float(eval(equation, math_globals, var)) var['result'] = result else: result = float(eval(equation, math_globals, {})) variables = [{'result': result}] # format the result format = request.params.get('format') or request.content_type or self.formatter formatter = self.formatters.get(format, self.formatters[self.formatter]) return self.get_response(formatter(variables), format) def post(self, request): """ return response to a POST request """ import pdb; pdb.set_trace() return exc.HTTPOk("Ok") def error(self, request): """deal with non-supported methods""" return exc.HTTPMethodNotAllowed("Only %r operations are allowed" % self.response_functions.keys()) def values(self, string): """ >>> values('1,2,3,4') [1,2,3,4] >>> values('1..0.2..2') [1,1.2,1.4,1.6,1.8,2] """ retval = [] tokens = [i.strip() for i in string.split(',') if i.strip()] for token in tokens: try: value = float(token) retval.append(value) continue except ValueError: pass start, step, end = token.split('..') start = float(start) step = float(step) end = float(end) values = [ start ] npoints = (end - start)/step npoints = int(npoints) values.extend([i*step + start for i in range(1, npoints)]) values.append(end) retval.extend(values) return retval