aboutsummaryrefslogtreecommitdiffstats
path: root/nikola/plugins/template/jinja.py
diff options
context:
space:
mode:
Diffstat (limited to 'nikola/plugins/template/jinja.py')
-rw-r--r--nikola/plugins/template/jinja.py75
1 files changed, 44 insertions, 31 deletions
diff --git a/nikola/plugins/template/jinja.py b/nikola/plugins/template/jinja.py
index b02d75c..5a2135f 100644
--- a/nikola/plugins/template/jinja.py
+++ b/nikola/plugins/template/jinja.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-# Copyright © 2012-2015 Roberto Alsina and others.
+# Copyright © 2012-2016 Roberto Alsina and others.
# Permission is hereby granted, free of charge, to any
# person obtaining a copy of this software and associated
@@ -29,8 +29,8 @@
from __future__ import unicode_literals
import os
+import io
import json
-from collections import deque
try:
import jinja2
from jinja2 import meta
@@ -42,29 +42,32 @@ from nikola.utils import makedirs, req_missing
class JinjaTemplates(TemplateSystem):
-
"""Support for Jinja2 templates."""
name = "jinja"
lookup = None
dependency_cache = {}
+ per_file_cache = {}
def __init__(self):
"""Initialize Jinja2 environment with extended set of filters."""
if jinja2 is None:
return
- self.lookup = jinja2.Environment()
+
+ def set_directories(self, directories, cache_folder):
+ """Create a new template lookup with set directories."""
+ if jinja2 is None:
+ req_missing(['jinja2'], 'use this theme')
+ cache_folder = os.path.join(cache_folder, 'jinja')
+ makedirs(cache_folder)
+ cache = jinja2.FileSystemBytecodeCache(cache_folder)
+ self.lookup = jinja2.Environment(bytecode_cache=cache)
self.lookup.trim_blocks = True
self.lookup.lstrip_blocks = True
self.lookup.filters['tojson'] = json.dumps
self.lookup.globals['enumerate'] = enumerate
self.lookup.globals['isinstance'] = isinstance
self.lookup.globals['tuple'] = tuple
-
- def set_directories(self, directories, cache_folder):
- """Create a new template lookup with set directories."""
- if jinja2 is None:
- req_missing(['jinja2'], 'use this theme')
self.directories = directories
self.create_lookup()
@@ -89,36 +92,46 @@ class JinjaTemplates(TemplateSystem):
if jinja2 is None:
req_missing(['jinja2'], 'use this theme')
template = self.lookup.get_template(template_name)
- output = template.render(**context)
+ data = template.render(**context)
if output_name is not None:
makedirs(os.path.dirname(output_name))
- with open(output_name, 'w+') as output:
- output.write(output.encode('utf8'))
- return output
+ with io.open(output_name, 'w', encoding='utf-8') as output:
+ output.write(data)
+ return data
def render_template_to_string(self, template, context):
"""Render template to a string using context."""
return self.lookup.from_string(template).render(**context)
+ def get_string_deps(self, text):
+ """Find dependencies for a template string."""
+ deps = set([])
+ ast = self.lookup.parse(text)
+ dep_names = meta.find_referenced_templates(ast)
+ for dep_name in dep_names:
+ filename = self.lookup.loader.get_source(self.lookup, dep_name)[1]
+ sub_deps = [filename] + self.get_deps(filename)
+ self.dependency_cache[dep_name] = sub_deps
+ deps |= set(sub_deps)
+ return list(deps)
+
+ def get_deps(self, filename):
+ """Return paths to dependencies for the template loaded from filename."""
+ with io.open(filename, 'r', encoding='utf-8') as fd:
+ text = fd.read()
+ return self.get_string_deps(text)
+
def template_deps(self, template_name):
"""Generate list of dependencies for a template."""
- # Cache the lists of dependencies for each template name.
if self.dependency_cache.get(template_name) is None:
- # Use a breadth-first search to find all templates this one
- # depends on.
- queue = deque([template_name])
- visited_templates = set([template_name])
- deps = []
- while len(queue) > 0:
- curr = queue.popleft()
- source, filename = self.lookup.loader.get_source(self.lookup,
- curr)[:2]
- deps.append(filename)
- ast = self.lookup.parse(source)
- dep_names = meta.find_referenced_templates(ast)
- for dep_name in dep_names:
- if (dep_name not in visited_templates and dep_name is not None):
- visited_templates.add(dep_name)
- queue.append(dep_name)
- self.dependency_cache[template_name] = deps
+ filename = self.lookup.loader.get_source(self.lookup, template_name)[1]
+ self.dependency_cache[template_name] = [filename] + self.get_deps(filename)
return self.dependency_cache[template_name]
+
+ def get_template_path(self, template_name):
+ """Get the path to a template or return None."""
+ try:
+ t = self.lookup.get_template(template_name)
+ return t.filename
+ except jinja2.TemplateNotFound:
+ return None