Mercurial > piecrust2
annotate piecrust/templating/pystacheengine.py @ 1188:a7c43131d871
bake: Fix file write flushing problem with Python 3.8+
Writing the cache files fails in Python 3.8 because it looks like flushing
behaviour has changed. We need to explicitly flush. And even then, in very
rare occurrences, it looks like it can still run into racing conditions,
so we do a very hacky and ugly "retry" loop when fetching cached data :(
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Tue, 15 Jun 2021 22:36:23 -0700 |
parents | 8adc27285d93 |
children |
rev | line source |
---|---|
185
139179dc7abd
render: Add support for a Mustache template engine.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff
changeset
|
1 import logging |
440
32c7c2d219d2
performance: Refactor how data is managed to reduce copying.
Ludovic Chabant <ludovic@chabant.com>
parents:
429
diff
changeset
|
2 import collections.abc |
185
139179dc7abd
render: Add support for a Mustache template engine.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff
changeset
|
3 from piecrust.templating.base import ( |
850
370e74941d32
optimize: Only load some 3rd party packages when needed.
Ludovic Chabant <ludovic@chabant.com>
parents:
519
diff
changeset
|
4 TemplateEngine, TemplateNotFoundError, TemplatingError) |
185
139179dc7abd
render: Add support for a Mustache template engine.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff
changeset
|
5 |
139179dc7abd
render: Add support for a Mustache template engine.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff
changeset
|
6 |
139179dc7abd
render: Add support for a Mustache template engine.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff
changeset
|
7 logger = logging.getLogger(__name__) |
139179dc7abd
render: Add support for a Mustache template engine.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff
changeset
|
8 |
139179dc7abd
render: Add support for a Mustache template engine.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff
changeset
|
9 |
139179dc7abd
render: Add support for a Mustache template engine.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff
changeset
|
10 class PystacheTemplateEngine(TemplateEngine): |
139179dc7abd
render: Add support for a Mustache template engine.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff
changeset
|
11 ENGINE_NAMES = ['mustache'] |
139179dc7abd
render: Add support for a Mustache template engine.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff
changeset
|
12 EXTENSIONS = ['mustache'] |
139179dc7abd
render: Add support for a Mustache template engine.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff
changeset
|
13 |
139179dc7abd
render: Add support for a Mustache template engine.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff
changeset
|
14 def __init__(self): |
139179dc7abd
render: Add support for a Mustache template engine.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff
changeset
|
15 self.renderer = None |
850
370e74941d32
optimize: Only load some 3rd party packages when needed.
Ludovic Chabant <ludovic@chabant.com>
parents:
519
diff
changeset
|
16 self._not_found_error = None |
370e74941d32
optimize: Only load some 3rd party packages when needed.
Ludovic Chabant <ludovic@chabant.com>
parents:
519
diff
changeset
|
17 self._pystache_error = None |
185
139179dc7abd
render: Add support for a Mustache template engine.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff
changeset
|
18 |
924
1bb704434ee2
formatting: Remove segment parts, you can use template tags instead.
Ludovic Chabant <ludovic@chabant.com>
parents:
850
diff
changeset
|
19 def renderSegment(self, path, segment, data): |
185
139179dc7abd
render: Add support for a Mustache template engine.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff
changeset
|
20 self._ensureLoaded() |
139179dc7abd
render: Add support for a Mustache template engine.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff
changeset
|
21 try: |
989
8adc27285d93
bake: Big pass on bake performance.
Ludovic Chabant <ludovic@chabant.com>
parents:
924
diff
changeset
|
22 return self.renderer.render(segment.content, data), True |
850
370e74941d32
optimize: Only load some 3rd party packages when needed.
Ludovic Chabant <ludovic@chabant.com>
parents:
519
diff
changeset
|
23 except self._not_found_error as ex: |
185
139179dc7abd
render: Add support for a Mustache template engine.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff
changeset
|
24 raise TemplateNotFoundError() from ex |
850
370e74941d32
optimize: Only load some 3rd party packages when needed.
Ludovic Chabant <ludovic@chabant.com>
parents:
519
diff
changeset
|
25 except self._pystache_error as ex: |
454
96d363e2da4b
templating: Let Jinja2 cache the parsed template for page contents.
Ludovic Chabant <ludovic@chabant.com>
parents:
440
diff
changeset
|
26 raise TemplatingError(str(ex), path) from ex |
185
139179dc7abd
render: Add support for a Mustache template engine.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff
changeset
|
27 |
139179dc7abd
render: Add support for a Mustache template engine.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff
changeset
|
28 def renderFile(self, paths, data): |
139179dc7abd
render: Add support for a Mustache template engine.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff
changeset
|
29 self._ensureLoaded() |
139179dc7abd
render: Add support for a Mustache template engine.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff
changeset
|
30 tpl = None |
139179dc7abd
render: Add support for a Mustache template engine.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff
changeset
|
31 logger.debug("Looking for template: %s" % paths) |
139179dc7abd
render: Add support for a Mustache template engine.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff
changeset
|
32 for p in paths: |
139179dc7abd
render: Add support for a Mustache template engine.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff
changeset
|
33 if not p.endswith('.mustache'): |
139179dc7abd
render: Add support for a Mustache template engine.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff
changeset
|
34 raise TemplatingError( |
850
370e74941d32
optimize: Only load some 3rd party packages when needed.
Ludovic Chabant <ludovic@chabant.com>
parents:
519
diff
changeset
|
35 "The Mustache template engine only accepts template " |
370e74941d32
optimize: Only load some 3rd party packages when needed.
Ludovic Chabant <ludovic@chabant.com>
parents:
519
diff
changeset
|
36 "filenames with a `.mustache` extension. Got: %s" % |
370e74941d32
optimize: Only load some 3rd party packages when needed.
Ludovic Chabant <ludovic@chabant.com>
parents:
519
diff
changeset
|
37 p) |
185
139179dc7abd
render: Add support for a Mustache template engine.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff
changeset
|
38 name = p[:-9] # strip `.mustache` |
139179dc7abd
render: Add support for a Mustache template engine.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff
changeset
|
39 try: |
139179dc7abd
render: Add support for a Mustache template engine.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff
changeset
|
40 tpl = self.renderer.load_template(name) |
139179dc7abd
render: Add support for a Mustache template engine.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff
changeset
|
41 except Exception as ex: |
519
9d1a89cd8146
cosmetic: Remove debug print here too.
Ludovic Chabant <ludovic@chabant.com>
parents:
454
diff
changeset
|
42 logger.debug("Mustache error: %s" % ex) |
185
139179dc7abd
render: Add support for a Mustache template engine.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff
changeset
|
43 pass |
139179dc7abd
render: Add support for a Mustache template engine.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff
changeset
|
44 |
139179dc7abd
render: Add support for a Mustache template engine.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff
changeset
|
45 if tpl is None: |
139179dc7abd
render: Add support for a Mustache template engine.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff
changeset
|
46 raise TemplateNotFoundError() |
139179dc7abd
render: Add support for a Mustache template engine.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff
changeset
|
47 |
139179dc7abd
render: Add support for a Mustache template engine.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff
changeset
|
48 try: |
139179dc7abd
render: Add support for a Mustache template engine.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff
changeset
|
49 return self.renderer.render(tpl, data) |
850
370e74941d32
optimize: Only load some 3rd party packages when needed.
Ludovic Chabant <ludovic@chabant.com>
parents:
519
diff
changeset
|
50 except self._pystache_error as ex: |
185
139179dc7abd
render: Add support for a Mustache template engine.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff
changeset
|
51 raise TemplatingError(str(ex)) from ex |
139179dc7abd
render: Add support for a Mustache template engine.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff
changeset
|
52 |
139179dc7abd
render: Add support for a Mustache template engine.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff
changeset
|
53 def _ensureLoaded(self): |
139179dc7abd
render: Add support for a Mustache template engine.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff
changeset
|
54 if self.renderer: |
139179dc7abd
render: Add support for a Mustache template engine.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff
changeset
|
55 return |
139179dc7abd
render: Add support for a Mustache template engine.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff
changeset
|
56 |
850
370e74941d32
optimize: Only load some 3rd party packages when needed.
Ludovic Chabant <ludovic@chabant.com>
parents:
519
diff
changeset
|
57 import pystache |
370e74941d32
optimize: Only load some 3rd party packages when needed.
Ludovic Chabant <ludovic@chabant.com>
parents:
519
diff
changeset
|
58 import pystache.common |
370e74941d32
optimize: Only load some 3rd party packages when needed.
Ludovic Chabant <ludovic@chabant.com>
parents:
519
diff
changeset
|
59 |
370e74941d32
optimize: Only load some 3rd party packages when needed.
Ludovic Chabant <ludovic@chabant.com>
parents:
519
diff
changeset
|
60 self._not_found_error = pystache.common.TemplateNotFoundError |
370e74941d32
optimize: Only load some 3rd party packages when needed.
Ludovic Chabant <ludovic@chabant.com>
parents:
519
diff
changeset
|
61 self._pystache_error = pystache.common.PystacheError |
370e74941d32
optimize: Only load some 3rd party packages when needed.
Ludovic Chabant <ludovic@chabant.com>
parents:
519
diff
changeset
|
62 |
370e74941d32
optimize: Only load some 3rd party packages when needed.
Ludovic Chabant <ludovic@chabant.com>
parents:
519
diff
changeset
|
63 class _WorkaroundRenderer(pystache.Renderer): |
370e74941d32
optimize: Only load some 3rd party packages when needed.
Ludovic Chabant <ludovic@chabant.com>
parents:
519
diff
changeset
|
64 def _make_resolve_context(self): |
370e74941d32
optimize: Only load some 3rd party packages when needed.
Ludovic Chabant <ludovic@chabant.com>
parents:
519
diff
changeset
|
65 mrc = super(_WorkaroundRenderer, self)._make_resolve_context() |
370e74941d32
optimize: Only load some 3rd party packages when needed.
Ludovic Chabant <ludovic@chabant.com>
parents:
519
diff
changeset
|
66 |
370e74941d32
optimize: Only load some 3rd party packages when needed.
Ludovic Chabant <ludovic@chabant.com>
parents:
519
diff
changeset
|
67 def _workaround(stack, name): |
370e74941d32
optimize: Only load some 3rd party packages when needed.
Ludovic Chabant <ludovic@chabant.com>
parents:
519
diff
changeset
|
68 # Pystache will treat anything that's not a string or |
370e74941d32
optimize: Only load some 3rd party packages when needed.
Ludovic Chabant <ludovic@chabant.com>
parents:
519
diff
changeset
|
69 # a dict as a list. This is just plain wrong, but it will |
370e74941d32
optimize: Only load some 3rd party packages when needed.
Ludovic Chabant <ludovic@chabant.com>
parents:
519
diff
changeset
|
70 # take a while before the project can get patches on Pypi. |
370e74941d32
optimize: Only load some 3rd party packages when needed.
Ludovic Chabant <ludovic@chabant.com>
parents:
519
diff
changeset
|
71 res = mrc(stack, name) |
370e74941d32
optimize: Only load some 3rd party packages when needed.
Ludovic Chabant <ludovic@chabant.com>
parents:
519
diff
changeset
|
72 if res is not None and ( |
370e74941d32
optimize: Only load some 3rd party packages when needed.
Ludovic Chabant <ludovic@chabant.com>
parents:
519
diff
changeset
|
73 res.__class__.__name__ in _knowns or |
370e74941d32
optimize: Only load some 3rd party packages when needed.
Ludovic Chabant <ludovic@chabant.com>
parents:
519
diff
changeset
|
74 isinstance(res, collections.abc.Mapping)): |
370e74941d32
optimize: Only load some 3rd party packages when needed.
Ludovic Chabant <ludovic@chabant.com>
parents:
519
diff
changeset
|
75 res = [res] |
370e74941d32
optimize: Only load some 3rd party packages when needed.
Ludovic Chabant <ludovic@chabant.com>
parents:
519
diff
changeset
|
76 return res |
370e74941d32
optimize: Only load some 3rd party packages when needed.
Ludovic Chabant <ludovic@chabant.com>
parents:
519
diff
changeset
|
77 |
370e74941d32
optimize: Only load some 3rd party packages when needed.
Ludovic Chabant <ludovic@chabant.com>
parents:
519
diff
changeset
|
78 return _workaround |
370e74941d32
optimize: Only load some 3rd party packages when needed.
Ludovic Chabant <ludovic@chabant.com>
parents:
519
diff
changeset
|
79 |
429
ca5a3c970263
templating: Workaround for a bug with Pystache.
Ludovic Chabant <ludovic@chabant.com>
parents:
428
diff
changeset
|
80 self.renderer = _WorkaroundRenderer( |
850
370e74941d32
optimize: Only load some 3rd party packages when needed.
Ludovic Chabant <ludovic@chabant.com>
parents:
519
diff
changeset
|
81 search_dirs=self.app.templates_dirs) |
185
139179dc7abd
render: Add support for a Mustache template engine.
Ludovic Chabant <ludovic@chabant.com>
parents:
diff
changeset
|
82 |
429
ca5a3c970263
templating: Workaround for a bug with Pystache.
Ludovic Chabant <ludovic@chabant.com>
parents:
428
diff
changeset
|
83 |
ca5a3c970263
templating: Workaround for a bug with Pystache.
Ludovic Chabant <ludovic@chabant.com>
parents:
428
diff
changeset
|
84 _knowns = ['PieCrustData', 'LazyPageConfigData', 'Paginator', 'Assetor', |
ca5a3c970263
templating: Workaround for a bug with Pystache.
Ludovic Chabant <ludovic@chabant.com>
parents:
428
diff
changeset
|
85 'PageLinkerData'] |