"""
Template handler
"""
# use Mako
from mako import exceptions
from mako.template import Template
import mako.lookup
# for http.ResponseError
import http
import helpers
# path to template files
TEMPLATE_DIR = "templates"
# path to cached templates
CACHE_DIR = "cache/templates"
# template file extension
TEMPLATE_EXT = "tmpl"
class TemplateError (http.ResponseError) :
"""
Raised by the template module functions
"""
pass
def render (tpl, **params) :
"""
Render the given template, returning the output as a unicode string, or raising a TemplateError
"""
try :
return tpl.render_unicode(
# global helper stuff
h = helpers,
# render-specific params
**params
)
# a template may render other templates
except TemplateError :
raise
except :
details = exceptions.text_error_template().render()
raise TemplateError("Template render failed", status='500 Internal Server Error', details=details)
class TemplateLoader (mako.lookup.TemplateLookup) :
"""
Our own specialization of mako's TemplateLookup
"""
def __init__ (self, path, fileext=TEMPLATE_EXT) :
"""
Initialize to load templates located at path, with the given file extension
"""
# store
self.path = path
self.fileext = fileext
# XXX: separate cache?
super(TemplateLoader, self).__init__(directories=[path], module_directory=CACHE_DIR)
def lookup (self, name) :
"""
Looks up a template based on the bare "name", which does not include the path or file extension
"""
try :
return self.get_template("%s.%s" % (name, self.fileext))
except :
raise TemplateError("Template broken: %r" % (name, ), status='500 Internal Server Error', details=exceptions.text_error_template().render())
def render (self, name, **params) :
"""
Render a template, using lookup() on the given name
"""
return render(self.lookup(name), **params)
def render_to_response (self, name, **params) :
"""
Render a template, returning a http.Response object
"""
return http.Response(self.render(name, **params))
@classmethod
def load (cls, path) :
"""
Loads a template from a specific file
"""
try :
return Template(filename=path, module_directory=CACHE_DIR)
except :
raise TemplateError("Template broken: %r" % (path, ), status='500 Internal Server Error', details=exceptions.text_error_template().render())
@classmethod
def render_file (cls, path, **params) :
"""
Render a template, using load() on the given path
"""
return render(cls.load(path), **params)