Jinja2 Buffet Plugin

Pylons 0.9.6.2 から Jinja2 を利用するための Buffet Plugin を記述しました。
なお、最新の Pylons 0.9.7 はデフォルトで Jinja2 に対応しています。

# -*- coding: utf-8 -*-

from jinja2 import Environment
from jinja2 import FileSystemLoader, PackageLoader, FunctionLoader
from jinja2.sandbox import SandboxedEnvironment

class Jinja2TemplatePlugin(object):
    """ Implements the Jina2 buffet plugin

    This module is made referring to Jinja1's BuffetPlugin.

    .. seealso::

      `Template plugins (for developers) - Pylons Cookbook
      <http://docs.pythonweb.org/display/pylonscookbook/Template+plugins+(for+developers)>`_
    """

    def __init__(self, extra_vars_func=None, options=None):
        """ Store the two arguments (normally dicts of strings), and do any
        other initialization required.

        .. Note::

           Jinja2 uses URI notation for template name.
           If options['jinja2.extension'] is not provided, the module will
           take given tempate name as URI.
        """

        if 'jinja2.environment' in options:
            self.env = options['jinja2.environment']
        else:
            opt = {}
            for key, value in options.iteritems():
                if key.startswith('jinja2.') and key != 'jinja2.extension':
                    opt[key[7:]] = value
            loader_func = opt.pop('loader_func', None)
            if 'searchpath' in opt:
                opt['loader'] = FileSystemLoader(opt.pop('searchpath'))
            elif 'package' in opt:
                opt['loader'] = PackageLoader(opt.pop('package'),
                                              opt.pop('package_path', ''))
            elif loader_func is not None:
                opt['loader'] = FunctionLoader(loader_func)

            sandboxed = opt.pop('sandboxed', None)
            if sandboxed:
                self.env = SandboxedEnvironment(**opt)
            else:
                self.env = Environment(**opt)

        self.extra_vars_func = extra_vars_func
        self.extension = options.pop('jinja2.extension', None)

    def render(self, info, format="html", fragment=False, template=None):
        """ Return a rendered version of the template.

        'info' is a dict of context variables (string : anything).
        'format' is the desired output format.  This is engine-specific.
        'fragment' is true if the template should be rendered "standalone";
            i.e., bypassing any inherited templates or wrapper templates that
            would normally be applied.  The plugin may ignore this argument if
            the engine does not support this.
        'template' is the template name (string).  Buffet requires dotted
            notation (see below), while Pylons allows URI notation.

        The method should call the 'extra_vars_funcs' function given to the
        constructor, and merge those variables in with 'info'.
        """
        if isinstance(template, basestring):
            template = self.load_template(template)
        if self.extra_vars_func:
            info.update(self.extra_vars_func())
        return template.render(info)

    def load_template(self, templatename, template_string=None):
        """ Optional: not called by Pylons. Called by TurboGears in special
         circumstances; see Buffet interface for details.
        """
        if template_string is not None:
            return self.env.from_string(template_string)
        # Translate TG dot notation to normal / template path
        if self.extension is not None:
            templatename = templatename.replace('.', '/') + '.' + self.extension
        return self.env.get_template(templatename)

    # def transform(self, info, template):
    #     """ Optional: not called by Pylons.  Called by TurboGears to render the
    #     template as a tree of ElementTree nodes rather than as a string.  Kid
    #     is the only known engine that supports this.
    #     """
    #     pass

posted by id:junya_hayashi