import os import logging import logging.handlers import mimeparse import md5 from genshi.template import TemplateLoader from cgi import parse_qs import StringIO TEMPLATE_DIRS = ["templates"] def genshi_templater(template_dir_paths, template_file, vars, serialization): loader = TemplateLoader(template_dir_paths) tmpl = loader.load(template_file) stream = tmpl.generate(**vars) body = stream.render(method=serialization) return body def simplejson_templater(template_dir_paths, template_file, vars, serialization): import simplejson return simplejson.dumps(vars) def form_parser(body): """Parses the incoming x-www-form-urlencoded data into a dictionary""" return dict([(key, "".join(value)) for key, value in parse_qs(body).iteritems()]) def json_parser(body): import simplejson return simplejson.loads(body) extensions = { 'html': ('text/html; charset=utf-8', 'html', genshi_templater, form_parser), # 'atom': ('application/atom+xml; charset=utf-8', 'xml', genshi_templater, atom_parser), # 'svc': ('application/atomsvc+xml; charset=utf-8', 'xml', genshi_templater, None), 'json': ('application/json', 'json', simplejson_templater, json_parser) } def find_parser(ext): if ext in extensions: return extensions[ext][3] else: return None def find_renderer(ext): return render def find_template(template_file): for dir in TEMPLATE_DIRS: full_name = os.path.join(dir, template_file) if os.path.exists(full_name) and os.path.isfile(full_name): return full_name return None def etag_from_raw_etag(raw_etag, template_file): file = find_template(template_file) if file: last_modified = str(os.stat(file).st_mtime) hash = md5.new(raw_etag) hash.update(last_modified) return '"%s"' % hash.hexdigest() return None def render(environ, start_response, template_file, vars, headers={}, status="200 Ok", raw_etag=None): if raw_etag: etag = etag_from_raw_etag(raw_etag, template_file) headers['etag'] = etag if etag == environ.get('HTTP_IF_NONE_MATCH', ''): return http304(environ, start_response) (contenttype, serialization, templater) = ('text/html; charset=utf-8', 'html', genshi_templater) ext = template_file.rsplit(".") if len(ext) > 1 and (ext[1] in extensions): (contenttype, serialization, templater, parser) = extensions[ext[1]] body = templater(TEMPLATE_DIRS, template_file, vars, serialization) if 'content-type' not in headers: headers['content-type'] = contenttype start_response(status, list(headers.iteritems())) return [body] def deferred_collection(environ, start_response): """Look for a views.* module to handle this incoming request. Presumes the module has an 'app' that is a WSGI application.""" # Pull out the view name from the template parameters view = environ['wsgiorg.routing_args'][1]['view'] # Load the named view from the 'views' directory m = __import__("views." + view, globals(), locals()) # Pass along the WSGI call into the given application logging.getLogger('robaccia').debug("View: %s" % view) return getattr(getattr(m, view), 'app')(environ, start_response) def render_json(start_response, struct): import simplejson body = simplejson.dumps(struct) start_response("200 OK", [('Content-Type', 'text/plain')]) return [body] def http200(environ, start_response): logging.getLogger('robaccia').info("200: %s" % environ.get('PATH_INFO', '')) start_response("200 Ok", []) return [] def http404(environ, start_response): logging.getLogger('robaccia').warning("404: %s" % environ.get('PATH_INFO', '')) start_response("404 Not Found", [('Content-Type', "text/html")]) return ["