Skip to content

Instantly share code, notes, and snippets.

@mgax
Created June 4, 2009 20:55
Show Gist options
  • Save mgax/123841 to your computer and use it in GitHub Desktop.
Save mgax/123841 to your computer and use it in GitHub Desktop.
# wsgiapp.py - tiny web service wrapper. URL dispatch; req/resp objects; logging; static
# files, genshi templates, json and repr data; plays nice with mod_wsgi. 99 lines of code.
# http://grep.ro/blog/2009/06/python_web_service
from os import path
app_root_fspath = path.dirname(__file__)
# mod_wsgi: we need the virtualenv site-packages, and our current folder, on sys.path
import site
site.addsitedir(path.join(app_root_fspath,
'../python-2.5/lib/python2.5/site-packages'))
site.addsitedir(app_root_fspath)
import devel_monitor # auto-reloader (code at http://bit.ly/mod_wsgi_code_changes)
devel_monitor.start(interval=1.0)
from cStringIO import StringIO
import logging
try:
import json
except ImportError:
import simplejson as json
from werkzeug import Request, Response, SharedDataMiddleware
from werkzeug.routing import Map, Rule
from werkzeug.exceptions import NotFound, BadRequest
from genshi.template import TemplateLoader
import css_diff # the "busines logic"
genshi_templates = TemplateLoader(app_root_fspath, auto_reload=True)
def JsonResponse(data):
return Response(json.dumps(data), mimetype='application/json')
def ReprResponse(data):
return Response(repr(data), mimetype='text/plain')
def GenshiResponse(template_fname, **args):
template = genshi_templates.load(template_fname)
html = template.generate(**args).render()
return Response(html, mimetype='text/html')
def read_file(fname):
f = open(path.join(app_root_fspath, fname))
data = f.read()
f.close()
return data
def staticfile_view(request, thefile):
if thefile == 'index':
return Response(read_file('index.html'), mimetype='text/html')
elif thefile == 'zopext':
return Response(read_file('Naaya.cssfixer.py'), mimetype='text/plain')
else:
raise ValueError("Don't know how to serve file \"%s\"" % thefile)
def css_diff_view(request):
# process request, set up logging
if request.method != 'POST':
raise BadRequest("please use POST")
default_css = request.form.get('default_css')
current_css = request.form.get('current_css')
output_format = request.args.get('format')
if default_css is None:
raise BadRequest("missing POST parameter default_css")
if current_css is None:
raise BadRequest("missing POST parameter current_css")
log_data = StringIO()
log_handler = logging.StreamHandler(log_data)
css_diff.log.addHandler(log_handler)
# run the actual method
result = css_diff.study_css(default_css, current_css)
# tear down logger, compose response
css_diff.log.removeHandler(log_handler)
if output_format == 'log':
return Response(log_data.getvalue(), mimetype='text/plain')
elif output_format == 'html':
return GenshiResponse('css_diff_out.html',
log_data=log_data.getvalue(), **result)
elif output_format == 'json':
return JsonResponse(result)
else:
return ReprResponse(result)
url_map = Map([
Rule('/', endpoint=staticfile_view, defaults={'thefile': 'index'}),
Rule('/Naaya.cssfixer.py', endpoint=staticfile_view, defaults={'thefile': 'zopext'}),
Rule('/css_diff', endpoint=css_diff_view),
])
@Request.application
def application(request):
return url_map.bind_to_environ(request.environ).dispatch(
lambda view, params: view(request, **params), catch_http_exceptions=True)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment