"""
Template handler
"""
from mako import exceptions, util
from mako.runtime import Context
from mako.template import Template
import mako.lookup
from qmsk.web import http, helpers
# path to template files
TEMPLATE_DIR = "templates"
# path to cached templates
CACHE_DIR = "cache/templates"
# template file extension
TEMPLATE_EXT = "tmpl"
class TemplateError (Exception) :
"""
Raised by the template module functions
"""
pass
def fmt_mako_exception () :
"""
Returns a string containing the Mako-ized error traceback (so that it includes the template data)
"""
return exceptions.text_error_template().render()
class TemplateLoader (mako.lookup.TemplateLookup) :
"""
Our own specialization of mako's TemplateLookup
"""
def __init__ (self, path, fileext=TEMPLATE_EXT, _helper_class=helpers.Helpers, **env) :
"""
Initialize to load templates located at path, with the given file extension.
The given Helpers class is used to provide the helper methods
The given **env list is supplied to every template render
"""
# store
self.path = path
self.fileext = fileext
self.helper_class = _helper_class
self.env = env
# build the TemplateLookup
super(TemplateLoader, self).__init__(directories=[path], module_directory=CACHE_DIR)
def _render (self, tpl, env, params) :
"""
Render the given template with given env/params, returning the output as a unicode string, or raising a TemplateError
"""
# build our Helpers class
helpers = self.helper_class()
# build the context from our env, and params
ctx = dict(
h = helpers,
)
ctx.update(env)
ctx.update(params)
# the buffer to use for unicode output
buf = util.FastEncodingBuffer(unicode=True)
# the context to use
context = Context(buf, **ctx)
# bind our helper
helpers._bind_ctx(context)
try :
# render template
tpl.render_context(context)
# a template may render other templates
except TemplateError :
raise
except :
# raise a TemplateError with the details
raise TemplateError("tpl=%r, params=%r: %s" % (tpl, params, fmt_mako_exception()))
else :
# return the unicode data
return buf.getvalue()
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("name=%r: %s" % (name, fmt_mako_exception()))
def render (self, name, **params) :
"""
Render a template, using lookup() on the given name
"""
return self._render(self.lookup(name), self.env, params)
def render_to_response (self, name, **params) :
"""
Render a template, returning a http.Response object
"""
return http.Response(self.render(name, **params))
def load (self, path) :
"""
Loads a template from a specific file
"""
try :
return Template(filename=path, module_directory=CACHE_DIR)
except :
raise TemplateError("path=%r: %s" % (path, fmt_mako_exception()))
def render_file (self, path, **params) :
"""
Render a template, using load() on the given path. No global environment vars are defined for the render.
"""
return self._render(self.load(path), dict(), params)
def render_template (self, template, **params) :
"""
Render the given template object. No global environment vars are defined for the render.
"""
return self._render(template, dict(), params)