Mercurial > piecrust2
comparison piecrust/templating/jinjaengine.py @ 907:3e69f18912f5
jinja: Remove Twig compatibility, add timer, improve code.
- Add a timer for keeping track of extensions' performance.
- Use the `select_template` function from Jinja to cut down on a few lines
of code.
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Sun, 23 Jul 2017 08:30:47 -0700 |
parents | 5c5b85d4f17d |
children | 1bb704434ee2 |
comparison
equal
deleted
inserted
replaced
906:1c6a4d2ec16e | 907:3e69f18912f5 |
---|---|
7 | 7 |
8 logger = logging.getLogger(__name__) | 8 logger = logging.getLogger(__name__) |
9 | 9 |
10 | 10 |
11 class JinjaTemplateEngine(TemplateEngine): | 11 class JinjaTemplateEngine(TemplateEngine): |
12 # Name `twig` is for backwards compatibility with PieCrust 1.x. | 12 ENGINE_NAMES = ['jinja', 'jinja2', 'j2'] |
13 ENGINE_NAMES = ['jinja', 'jinja2', 'j2', 'twig'] | 13 EXTENSIONS = ['html', 'jinja', 'jinja2', 'j2'] |
14 EXTENSIONS = ['html', 'jinja', 'jinja2', 'j2', 'twig'] | |
15 | 14 |
16 def __init__(self): | 15 def __init__(self): |
17 self.env = None | 16 self.env = None |
18 self._jinja_syntax_error = None | 17 self._jinja_syntax_error = None |
19 self._jinja_not_found = None | 18 self._jinja_not_found = None |
20 | 19 |
21 def renderSegmentPart(self, path, seg_part, data): | 20 def renderSegmentPart(self, path, seg_part, data): |
22 self._ensureLoaded() | |
23 | |
24 if not _string_needs_render(seg_part.content): | 21 if not _string_needs_render(seg_part.content): |
25 return seg_part.content | 22 return seg_part.content |
23 | |
24 self._ensureLoaded() | |
26 | 25 |
27 part_path = _make_segment_part_path(path, seg_part.offset) | 26 part_path = _make_segment_part_path(path, seg_part.offset) |
28 self.env.loader.segment_parts_cache[part_path] = ( | 27 self.env.loader.segment_parts_cache[part_path] = ( |
29 path, seg_part.content) | 28 path, seg_part.content) |
30 try: | 29 try: |
47 rel_path = os.path.relpath(path, self.app.root_dir) | 46 rel_path = os.path.relpath(path, self.app.root_dir) |
48 raise TemplatingError(msg, rel_path) from ex | 47 raise TemplatingError(msg, rel_path) from ex |
49 | 48 |
50 def renderFile(self, paths, data): | 49 def renderFile(self, paths, data): |
51 self._ensureLoaded() | 50 self._ensureLoaded() |
52 tpl = None | |
53 logger.debug("Looking for template: %s" % paths) | |
54 rendered_path = None | |
55 for p in paths: | |
56 try: | |
57 tpl = self.env.get_template(p) | |
58 rendered_path = p | |
59 break | |
60 except self._jinja_syntax_error as tse: | |
61 raise self._getTemplatingError(tse) | |
62 except self._jinja_not_found: | |
63 pass | |
64 | 51 |
65 if tpl is None: | 52 try: |
53 tpl = self.env.select_template(paths) | |
54 except self._jinja_syntax_error as tse: | |
55 raise self._getTemplatingError(tse) | |
56 except self._jinja_not_found: | |
66 raise TemplateNotFoundError() | 57 raise TemplateNotFoundError() |
67 | 58 |
68 try: | 59 try: |
69 return tpl.render(data) | 60 return tpl.render(data) |
70 except self._jinja_syntax_error as tse: | 61 except self._jinja_syntax_error as tse: |
73 raise | 64 raise |
74 except Exception as ex: | 65 except Exception as ex: |
75 if self.app.debug: | 66 if self.app.debug: |
76 raise | 67 raise |
77 msg = "Error rendering Jinja markup" | 68 msg = "Error rendering Jinja markup" |
78 rel_path = os.path.relpath(rendered_path, self.app.root_dir) | 69 name = getattr(tpl, 'name', '<unknown template>') |
79 raise TemplatingError(msg, rel_path) from ex | 70 raise TemplatingError(msg, name) from ex |
80 | 71 |
81 def _getTemplatingError(self, tse, filename=None): | 72 def _getTemplatingError(self, tse, filename=None): |
82 filename = tse.filename or filename | 73 filename = tse.filename or filename |
83 if filename and os.path.isabs(filename): | 74 if filename and os.path.isabs(filename): |
84 filename = os.path.relpath(filename, self.env.app.root_dir) | 75 filename = os.path.relpath(filename, self.env.app.root_dir) |
88 def _ensureLoaded(self): | 79 def _ensureLoaded(self): |
89 if self.env is not None: | 80 if self.env is not None: |
90 return | 81 return |
91 | 82 |
92 stats = self.app.env.stats | 83 stats = self.app.env.stats |
93 stats.registerTimer('JinjaTemplateEngineEnvironmentSetup', | 84 stats.registerTimer('JinjaTemplateEngine_setup', |
94 raise_if_registered=False) | 85 raise_if_registered=False) |
95 with stats.timerScope('JinjaTemplateEngineEnvironmentSetup'): | 86 stats.registerTimer('JinjaTemplateEngine_extensions', |
87 raise_if_registered=False) | |
88 with stats.timerScope('JinjaTemplateEngine_setup'): | |
96 self._load() | 89 self._load() |
97 | 90 |
98 def _load(self): | 91 def _load(self): |
99 get_config = self.app.config.get | 92 get_config = self.app.config.get |
100 | 93 |
102 ext_names = get_config('jinja/extensions', []) | 95 ext_names = get_config('jinja/extensions', []) |
103 if not isinstance(ext_names, list): | 96 if not isinstance(ext_names, list): |
104 ext_names = [ext_names] | 97 ext_names = [ext_names] |
105 | 98 |
106 # Turn on autoescape by default. | 99 # Turn on autoescape by default. |
107 autoescape = get_config('twig/auto_escape') | 100 autoescape = get_config('jinja/auto_escape', True) |
108 if autoescape is not None: | |
109 logger.warning("The `twig/auto_escape` setting is now called " | |
110 "`jinja/auto_escape`.") | |
111 else: | |
112 autoescape = get_config('jinja/auto_escape', True) | |
113 if autoescape: | 101 if autoescape: |
114 ext_names.append('autoescape') | 102 ext_names.append('autoescape') |
115 | 103 |
116 # Create the final list of extensions. | 104 # Create the final list of extensions. |
117 from piecrust.templating.jinja.extensions import ( | 105 from piecrust.templating.jinja.extensions import ( |
158 | 146 |
159 | 147 |
160 def _make_segment_part_path(path, start): | 148 def _make_segment_part_path(path, start): |
161 return '$part=%s:%d' % (path, start) | 149 return '$part=%s:%d' % (path, start) |
162 | 150 |
163 |