"""Some utilities for Python CGI [brendan oconnor feb 2010, anyall.org/cgiutil.py] OK, it's 2010 and there are now a zillion alternatives to CGI. But every time I try one, I always come back. It's just so much easier from a unix-based deployment perspective. (PHP is ideal. CGI is close though not quite as good.) If you run this you get a skeleton cgi app with example usage. It requires the following Apache directives. AddHandler cgi-script .cgi Options [... bla bla ...] ExecCGI And maybe (ubuntu/debian) $ sudo a2enmod cgi && sudo /etc/init.d/apache2 reload """ from __future__ import with_statement import sys,os,cgi from copy import copy import codecs; sys.stdout = codecs.open('/dev/stdout','w',encoding='utf8',buffering=0) def safehtml(x): return cgi.escape(str(x),quote=True) def unicodify(s, encoding='utf8', *args): """ because {str,unicode}.{encode,decode} is anti-polymorphic, but sometimes you can't control which you have. """ if isinstance(s,unicode): return s if isinstance(s,str): return s.decode(encoding, *args) return unicode(s) class Struct(dict): def __getattr__(self, a): if a.startswith('__'): raise AttributeError return self[a] def __setattr__(self, a, v): self[a] = v def type_clean(val,type): if type==bool: if val in (False,0,'0','f','false','False','no','n'): return False if val in (True,1,'1','t','true','True','yes','y'): return True raise Exception("bad bool value %s" % repr(val)) if type==str or type==unicode: # nope no strings, you're gonna get unicode instead! return unicodify(val) return type(val) class Opt(object): pass type_builtin = type def opt(name, type=None, default=None, values=None): o = Opt() o.__dict__.update(name=name,type=type,default=default,values=values) if type is None: if default is not None: o.type = type_builtin(default) else: o.type = str #raise Exception("need type for %s" % name) #if o.type==bool: o.type=int return o class Opts(Struct): " modelled on trollop.rubyforge.org and gist.github.com/5682 " def __init__(self, *optlist): self.optspecs = {} environ = os.environ # can't use cgi.py's form processing: we want to handle POST content ourselves now vars = cgi.parse_qs(environ['QUERY_STRING'] or sys.stdin.read()) for opt in optlist: # fix up the opt spec if opt.values and not opt.default: opt.default = opt.values[0] # save it for later self.optspecs[opt.name] = opt # value processing from GET/POST info val = vars.get(opt.name) val = val[0] if val else None if val is None and opt.default is not None: val = copy(opt.default) elif val is None: raise Exception("option not given: %s" % opt.name) val = type_clean(val, opt.type) self[opt.name] = val def input(self, name, **kwargs): val = self[name] h = '''' for value in self.optspecs[name].values: h += '