Skip to content

Commit 5e94c69

Browse files
committed
(a)close generators when delgating to template blocks and includes
1 parent 3fd91e4 commit 5e94c69

File tree

1 file changed

+26
-14
lines changed

1 file changed

+26
-14
lines changed

src/jinja2/compiler.py

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -898,12 +898,15 @@ def visit_Template(
898898
if not self.environment.is_async:
899899
self.writeline("yield from parent_template.root_render_func(context)")
900900
else:
901-
self.writeline(
902-
"async for event in parent_template.root_render_func(context):"
903-
)
901+
self.writeline("agen = parent_template.root_render_func(context)")
902+
self.writeline("try:")
903+
self.indent()
904+
self.writeline("async for event in agen:")
904905
self.indent()
905906
self.writeline("yield event")
906907
self.outdent()
908+
self.outdent()
909+
self.writeline("finally: await agen.aclose()")
907910
self.outdent(1 + (not self.has_known_extends))
908911

909912
# at this point we now have the blocks collected and can visit them too.
@@ -973,14 +976,18 @@ def visit_Block(self, node: nodes.Block, frame: Frame) -> None:
973976
f"yield from context.blocks[{node.name!r}][0]({context})", node
974977
)
975978
else:
979+
self.writeline(f"gen = context.blocks[{node.name!r}][0]({context})")
980+
self.writeline("try:")
981+
self.indent()
976982
self.writeline(
977-
f"{self.choose_async()}for event in"
978-
f" context.blocks[{node.name!r}][0]({context}):",
983+
f"{self.choose_async()}for event in gen:",
979984
node,
980985
)
981986
self.indent()
982987
self.simple_write("event", frame)
983988
self.outdent()
989+
self.outdent()
990+
self.writeline(f"finally: {self.choose_async('await gen.aclose()', 'gen.close()')}")
984991

985992
self.outdent(level)
986993

@@ -1053,26 +1060,31 @@ def visit_Include(self, node: nodes.Include, frame: Frame) -> None:
10531060
self.writeline("else:")
10541061
self.indent()
10551062

1056-
skip_event_yield = False
1063+
def loop_body() -> None:
1064+
self.indent()
1065+
self.simple_write("event", frame)
1066+
self.outdent()
1067+
10571068
if node.with_context:
10581069
self.writeline(
1059-
f"{self.choose_async()}for event in template.root_render_func("
1070+
f"gen = template.root_render_func("
10601071
"template.new_context(context.get_all(), True,"
1061-
f" {self.dump_local_context(frame)})):"
1072+
f" {self.dump_local_context(frame)}))"
10621073
)
1074+
self.writeline("try:")
1075+
self.indent()
1076+
self.writeline(f"{self.choose_async()}for event in gen:")
1077+
loop_body()
1078+
self.outdent()
1079+
self.writeline(f"finally: {self.choose_async('await gen.aclose()', 'gen.close()')}")
10631080
elif self.environment.is_async:
10641081
self.writeline(
10651082
"for event in (await template._get_default_module_async())"
10661083
"._body_stream:"
10671084
)
1085+
loop_body()
10681086
else:
10691087
self.writeline("yield from template._get_default_module()._body_stream")
1070-
skip_event_yield = True
1071-
1072-
if not skip_event_yield:
1073-
self.indent()
1074-
self.simple_write("event", frame)
1075-
self.outdent()
10761088

10771089
if node.ignore_missing:
10781090
self.outdent()

0 commit comments

Comments
 (0)