This repository has been archived by the owner on Dec 31, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 8
/
jinjaengine.py
150 lines (124 loc) · 5.03 KB
/
jinjaengine.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
import os.path
import logging
from piecrust.sources.base import AbortedSourceUseError
from piecrust.templating.base import (TemplateEngine, TemplateNotFoundError,
TemplatingError)
logger = logging.getLogger(__name__)
class JinjaTemplateEngine(TemplateEngine):
ENGINE_NAMES = ['jinja', 'jinja2', 'j2']
EXTENSIONS = ['html', 'jinja', 'jinja2', 'j2']
def __init__(self):
self.env = None
self._jinja_syntax_error = None
self._jinja_not_found = None
def renderSegment(self, path, segment, data):
if not _string_needs_render(segment.content):
return segment.content
self._ensureLoaded()
seg_path = _make_segment_path(path, segment.offset)
self.env.loader.segments_cache[seg_path] = (
path, segment.content)
try:
tpl = self.env.get_template(seg_path)
except self._jinja_syntax_error as tse:
raise self._getTemplatingError(tse, filename=path)
except self._jinja_not_found:
raise TemplateNotFoundError()
try:
return tpl.render(data)
except self._jinja_syntax_error as tse:
raise self._getTemplatingError(tse)
except AbortedSourceUseError:
raise
except Exception as ex:
if self.app.debug:
raise
msg = "Error rendering Jinja markup"
rel_path = os.path.relpath(path, self.app.root_dir)
raise TemplatingError(msg, rel_path) from ex
def renderFile(self, paths, data):
self._ensureLoaded()
try:
tpl = self.env.select_template(paths)
except self._jinja_syntax_error as tse:
raise self._getTemplatingError(tse)
except self._jinja_not_found:
raise TemplateNotFoundError()
try:
return tpl.render(data)
except self._jinja_syntax_error as tse:
raise self._getTemplatingError(tse)
except AbortedSourceUseError:
raise
except Exception as ex:
if self.app.debug:
raise
msg = "Error rendering Jinja markup"
name = getattr(tpl, 'name', '<unknown template>')
raise TemplatingError(msg, name) from ex
def _getTemplatingError(self, tse, filename=None):
filename = tse.filename or filename
if filename and os.path.isabs(filename):
filename = os.path.relpath(filename, self.env.app.root_dir)
err = TemplatingError(str(tse), filename, tse.lineno)
raise err from tse
def _ensureLoaded(self):
if self.env is not None:
return
stats = self.app.env.stats
stats.registerTimer('JinjaTemplateEngine_setup',
raise_if_registered=False)
stats.registerTimer('JinjaTemplateEngine_extensions',
raise_if_registered=False)
with stats.timerScope('JinjaTemplateEngine_setup'):
self._load()
def _load(self):
get_config = self.app.config.get
# Get the list of extensions to load.
ext_names = get_config('jinja/extensions', [])
if not isinstance(ext_names, list):
ext_names = [ext_names]
# Turn on autoescape by default.
autoescape = get_config('jinja/auto_escape', True)
if autoescape:
ext_names.append('autoescape')
# Create the final list of extensions.
from piecrust.templating.jinja.extensions import (
PieCrustHighlightExtension, PieCrustCacheExtension,
PieCrustSpacelessExtension, PieCrustFormatExtension)
extensions = [
PieCrustHighlightExtension,
PieCrustCacheExtension,
PieCrustSpacelessExtension,
PieCrustFormatExtension]
for n in ext_names:
if '.' not in n:
n = 'jinja2.ext.' + n
extensions.append(n)
for je in self.app.plugin_loader.getTemplateEngineExtensions('jinja'):
extensions.append(je)
# Create the Jinja environment.
logger.debug("Creating Jinja environment with folders: %s" %
self.app.templates_dirs)
from piecrust.templating.jinja.loader import PieCrustLoader
loader = PieCrustLoader(self.app.templates_dirs)
from piecrust.templating.jinja.environment import PieCrustEnvironment
self.env = PieCrustEnvironment(
self.app,
loader=loader,
extensions=extensions)
# Get types we need later.
from jinja2 import TemplateNotFound
from jinja2.exceptions import TemplateSyntaxError
self._jinja_syntax_error = TemplateSyntaxError
self._jinja_not_found = TemplateNotFound
def _string_needs_render(txt):
index = txt.find('{')
while index >= 0:
ch = txt[index + 1]
if ch == '{' or ch == '%':
return True
index = txt.find('{', index + 1)
return False
def _make_segment_path(path, start):
return '$seg=%s:%d' % (path, start)