Skip to content

Commit c262579

Browse files
edcohen08thibaudcolas
authored andcommitted
move everything into lib
1 parent a1f9fad commit c262579

File tree

3 files changed

+91
-1
lines changed

3 files changed

+91
-1
lines changed

pattern_library/__init__.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,3 +64,11 @@ def get_sections():
6464

6565
def get_pattern_context_var_name():
6666
return "is_pattern_library"
67+
68+
if get_pattern_template_suffix() == ".jinja":
69+
from jinja2.compiler import CodeGenerator as JinjaCodeGenerator
70+
from jinja2.environment import Template as JinjaTemplate
71+
from .loader_tags import template_new_context, visit_extends
72+
73+
JinjaTemplate.new_context = template_new_context
74+
JinjaCodeGenerator.visit_Extends = visit_extends

pattern_library/loader_tags.py

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,3 +150,85 @@ def do_include(parser, token):
150150
extra_context=namemap,
151151
isolated_context=isolated_context,
152152
)
153+
154+
def visit_extends(self, node, frame):
155+
"""Dupe of the jinja2.compiler.CodeGenerator visit_Extends
156+
except for
157+
self.writeline(
158+
"parent_template.new_context(context.get_all(), True,"
159+
f" {self.dump_local_context(frame)})"
160+
)
161+
which is how we pull in context from yaml files to extended templates
162+
"""
163+
from jinja2.compiler import CompilerExit
164+
165+
if not frame.toplevel:
166+
self.fail("cannot use extend from a non top-level scope", node.lineno)
167+
# if the number of extends statements in general is zero so
168+
# far, we don't have to add a check if something extended
169+
# the template before this one.
170+
if self.extends_so_far > 0:
171+
# if we have a known extends we just add a template runtime
172+
# error into the generated code. We could catch that at compile
173+
# time too, but i welcome it not to confuse users by throwing the
174+
# same error at different times just "because we can".
175+
if not self.has_known_extends:
176+
self.writeline("if parent_template is not None:")
177+
self.indent()
178+
self.writeline('raise TemplateRuntimeError("extended multiple times")')
179+
180+
# if we have a known extends already we don't need that code here
181+
# as we know that the template execution will end here.
182+
if self.has_known_extends:
183+
raise CompilerExit()
184+
else:
185+
self.outdent()
186+
self.writeline("parent_template = environment.get_template(", node)
187+
self.visit(node.template, frame)
188+
self.write(f", {self.name!r})")
189+
# addition to update the context with dpl context
190+
# calls the template_new_context method below when
191+
# invoked at runtime
192+
self.writeline(
193+
"parent_template.new_context(context.get_all(), True,"
194+
f" {self.dump_local_context(frame)})"
195+
)
196+
self.writeline("for name, parent_block in parent_template.blocks.items():")
197+
self.indent()
198+
self.writeline("context.blocks.setdefault(name, []).append(parent_block)")
199+
self.outdent()
200+
201+
# if this extends statement was in the root level we can take
202+
# advantage of that information and simplify the generated code
203+
# in the top level from this point onwards
204+
if frame.rootlevel:
205+
self.has_known_extends = True
206+
207+
# and now we have one more
208+
self.extends_so_far += 1
209+
210+
211+
def template_new_context(
212+
self,
213+
vars=None, # noqa A002
214+
shared=False,
215+
locals=None, # noqa A002
216+
):
217+
"""Create a new :class:`Context` for this template. The vars
218+
provided will be passed to the template. Per default the globals
219+
are added to the context. If shared is set to `True` the data
220+
is passed as is to the context without adding the globals.
221+
222+
`locals` can be a dict of local variables for internal usage.
223+
"""
224+
from jinja2.runtime import new_context
225+
226+
if is_pattern_library_context(vars or {}) and (
227+
pattern_context := get_pattern_context(self.name)
228+
):
229+
for k, v in pattern_context.items():
230+
vars.setdefault(k, v)
231+
232+
return new_context(
233+
self.environment, self.name, self.blocks, vars, shared, self.globals, locals
234+
)

pattern_library/monkey_utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,4 +116,4 @@ def node_render(context):
116116

117117
return original_node
118118

119-
return tag_func
119+
return tag_func

0 commit comments

Comments
 (0)