Source

tonfa/sphinx / sphinx / jinja2glue.py

# -*- coding: utf-8 -*-
"""
    sphinx.jinja2glue
    ~~~~~~~~~~~~~~~~~

    Glue code for the jinja2 templating engine.

    :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
    :license: BSD, see LICENSE for details.
"""

import codecs
from os import path

import jinja2

from sphinx.util import mtimes_of_files
from sphinx.application import TemplateBridge


class SphinxLoader(jinja2.BaseLoader):
    """
    A jinja2 reimplementation of `sphinx._jinja.SphinxFileSystemLoader`.
    """

    def __init__(self, basepath, extpaths, encoding='utf-8'):
        """
        Create a new loader for sphinx.

        *extpaths* is a list of directories, which provide additional templates
        to sphinx.

        *encoding* is used to decode the templates into unicode strings.
        Defaults to utf-8.

        If *basepath* is set, this path is used to load sphinx core templates.
        If False, these templates are loaded from the sphinx package.
        """
        self.core_loader = jinja2.FileSystemLoader(basepath)
        self.all_loaders = jinja2.ChoiceLoader(
            [jinja2.FileSystemLoader(extpath) for extpath in extpaths] +
            [self.core_loader])

    def get_source(self, environment, template):
        # exclamation mark forces loading from core
        if template.startswith('!'):
            return self.core_loader.get_source(environment, template[1:])
        # check if the template is probably an absolute path
        fs_path = template.replace('/', path.sep)
        if path.isabs(fs_path):
            if not path.exists(fs_path):
                raise jinja2.TemplateNotFound(template)
            f = codecs.open(fs_path, 'r', self.encoding)
            try:
                mtime = path.getmtime(path)
                return (f.read(), fs_path,
                        lambda: mtime == path.getmtime(path))
            finally:
                f.close()
        # finally try to load from custom templates
        return self.all_loaders.get_source(environment, template)


class BuiltinTemplates(TemplateBridge):
    """
    Interfaces the rendering environment of jinja2 for use in sphinx.
    """

    def init(self, builder):
        base_templates_path = path.join(path.dirname(__file__), 'templates')
        ext_templates_path = [path.join(builder.confdir, dir)
                              for dir in builder.config.templates_path]
        self.templates_path = [base_templates_path] + ext_templates_path
        loader = SphinxLoader(base_templates_path, ext_templates_path)
        use_i18n = builder.translator is not None
        extensions = use_i18n and ['jinja2.ext.i18n'] or []
        self.environment = jinja2.Environment(loader=loader,
                                              extensions=extensions)
        if use_i18n:
            self.environment.install_gettext_translations(builder.translator)

    def render(self, template, context):
        return self.environment.get_template(template).render(context)

    def newest_template_mtime(self):
        return max(mtimes_of_files(self.templates_path, '.html'))