From f3bc9c6a915badd3871eb1bc5aae5421d2f6496d Mon Sep 17 00:00:00 2001 From: Amy Date: Fri, 21 May 2021 13:56:58 -0400 Subject: clear assignments in loops at end of iteration --- CHANGES.rst | 3 +++ src/jinja2/compiler.py | 5 +++++ tests/test_regression.py | 7 +++++++ 3 files changed, 15 insertions(+) diff --git a/CHANGES.rst b/CHANGES.rst index fc540af..7bfebff 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -5,6 +5,9 @@ Version 3.0.2 Unreleased +- Fix a loop scoping bug that caused assignments in nested loops + to still be referenced outside of it. :issue:`1427` + Version 3.0.1 ------------- diff --git a/src/jinja2/compiler.py b/src/jinja2/compiler.py index ef4c0a1..5fe9349 100644 --- a/src/jinja2/compiler.py +++ b/src/jinja2/compiler.py @@ -1290,6 +1290,11 @@ class CodeGenerator(NodeVisitor): self.write(", loop)") self.end_write(frame) + # at the end of the iteration, clear any assignments made in the + # loop from the top level + if self._assign_stack: + self._assign_stack[-1].difference_update(loop_frame.symbols.stores) + def visit_If(self, node: nodes.If, frame: Frame) -> None: if_frame = frame.soft() self.writeline("if ", node) diff --git a/tests/test_regression.py b/tests/test_regression.py index 4491dab..7e23369 100644 --- a/tests/test_regression.py +++ b/tests/test_regression.py @@ -746,6 +746,13 @@ End""" tmpl = env.get_template("base") assert tmpl.render() == "42 y" + def test_nested_loop_scoping(self, env): + tmpl = env.from_string( + "{% set output %}{% for x in [1,2,3] %}hello{% endfor %}" + "{% endset %}{{ output }}" + ) + assert tmpl.render() == "hellohellohello" + @pytest.mark.parametrize("unicode_char", ["\N{FORM FEED}", "\x85"]) def test_unicode_whitespace(env, unicode_char): -- cgit v1.2.1