jinja icon indicating copy to clipboard operation
jinja copied to clipboard

meta.find_undeclared_variables returning variables set in if blocks as of 3.1.5

Open alext opened this issue 11 months ago • 3 comments

I've observed a change in behaviour between 3.1.4 and 3.1.5 where meta.find_undeclared_variables is now returning variables that are set in all branches of an if statement.

For example with the following:

from jinja2 import Environment, meta

env = Environment()

template = """\
{% if control == 'something' %}
    {% set output = 1 %}
{% elif control == 'something else' %}
    {% set output = 2 %}
{% else %}
    {% set output = 3 %}
{% endif %}
{{ output }}
"""
result = meta.find_undeclared_variables(env.parse(template))
assert result == {'control'}

With jinja2 version 3.1.4, this runs without error. With jinja2 version 3.1.5, this errors becasue result contains both "control" and "output". I believe the 3.1.4 behaviour is correct in this instance.

Reading the changelog, I suspect that the fix for #1253 (PR #1665) looks likely to be the cause of this change.

Environment:

  • Python version: 3.10.12
  • Jinja version: 3.1.5

alext avatar Jan 10 '25 14:01 alext

I've just tested using jinja2 3.1.5 with the changes from #1665 reverted, and this results in the same behaviour as 3.1.4.

alext avatar Jan 10 '25 14:01 alext

I'm happy to review a PR or suggested fix.

davidism avatar Mar 05 '25 18:03 davidism

I was running into this issue as well in https://github.com/deepset-ai/haystack/issues/9916 and I was hoping rolling back to 3.1.4 would fix my issue as mentioned here in this thread.

Unfortunately, I found that 3.1.4 still has an issue. If you modify the original example by removing the elif branch and only keeping one if statement then the variable output is returned by meta.find_undeclared_variables(env.parse(template)).

from jinja2 import Environment, meta

env = Environment()

template = """\
{% if control == 'something' %}
    {% set output = 1 %}
{% else %}
    {% set output = 3 %}
{% endif %}
{{ output }}
"""
result = meta.find_undeclared_variables(env.parse(template))
# >> {'output', 'control'}
assert result == {'control'}

Environment

  • Python: 3.12.11
  • Jinja version: 3.1.4

sjrl avatar Nov 18 '25 12:11 sjrl