New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Jinja2 2.9.4 - {% set %} and {% include %} don't work in the same template. #659

Closed
andymcc opened this Issue Jan 12, 2017 · 6 comments

Comments

Projects
None yet
3 participants
@andymcc

andymcc commented Jan 12, 2017

Expected Behavior

When a template contains:

{% set myvar = "foo" %}
{{ myvar }}
{% include "include.j2" %}

And the include.j2 template contains anything, for example:

bar

The original template should render:

foo
bar

Actual Behavior

In 2.8 this works normally.

In 2.9.3 & 2.9.4 the template doesn't render at all and drops an error:

KeyError: 'undefined variable: 0'

However, it will render with the {% set %} line templated when no {% include %} line exists, e.g.:

{% set myvar = "foo" %}
{{ myvar }}

Or with the {% include %} line without the {% set %} line, e.g.:

{% include "include.j2" %}

Template Code

root@jinja2fix# cat templates/setincl.j2
{% set myvar = "foo" %}
{{ myvar }}
{% include "include.j2" %}

root@jinja2fix# cat templates/include.j2
bar

Actual Run

I'm using Ansible 2.2.0 (I'll file a bug with Ansible too as I know this may not be considered a Jinja2 bug) - it's easily repeatable with the ad-hoc ansible command though:

root@jinja2fix:/opt/test_jinja# ansible localhost -m template -a "src=setincl.j2 dest=/tmp/test.file"

localhost | FAILED! => {
    "changed": false,
    "failed": true,
    "msg": "KeyError: 'undefined variable: 0'"
}

Here is a more "complete" run to show the failure and success (in 2.8). Additionally, it shows that it will render properly with either just the {% set %} line, or just the {% include %} line - but not both.

https://gist.github.com/andymcc/2ddf98b50fa07e3f8b8648a440499fb8

I've added to a bug in Ansible, that already exists and seems related: ansible/ansible#20063

Your Environment

  • Python version: 2.7.12
  • Jinja version: 2.9.3 & 2.9.4 (tested on both)

mitsuhiko added a commit that referenced this issue Jan 12, 2017

@mitsuhiko

This comment has been minimized.

Member

mitsuhiko commented Jan 12, 2017

I cannot reproduce this at all in Jinja2. Added this regression test in 3e9937c but it passes.

@mitsuhiko

This comment has been minimized.

Member

mitsuhiko commented Jan 12, 2017

There must be more to this story. I'm going to close this bug however I will monitor the mentioned issue over here: ansible/ansible#20063

@ghost

This comment has been minimized.

ghost commented Jan 28, 2017

I have the same bug.

<div id="owl{{ carousel_count }}" class="owl-carousel owl-theme">
    {% set owl_count=0 %}
    {% set owl_all = channels | length %}
    {% for owl_channel in channels %}

        {% set owl_count=owl_count+1 %}

        {% if owl_all<14 or owl_count % 2 != 0 %}
            <div class="item">
        {% endif %}

    <div class="ps-bl">
        <img src="{{ owl_channel.image }}" style="cursor: pointer;"
             onclick="goChannel('{{ owl_channel.url }}')"/>
        <div class="tit-chanel" style="cursor: pointer;">{{ owl_channel.name }}</div>
        <div class="flg j1 ato-flag"><img src="{{ owl_channel.flag }}" alt=""></div>
        <a class="love" href="#" data-id="{{ owl_channel.id }}"></a>
    </div>

    {% if owl_all < 14 or owl_count %2 == 0 or owl_count == owl_all %}
        </div>
        <!-- .item-->
    {% endif %}

    {% endfor %}

</div>

The problem with owl_count. It always equals 1.
With Jinja2 2.8 it works fine.

@ThiefMaster

This comment has been minimized.

Member

ThiefMaster commented Jan 28, 2017

This looks a lot like something that could be done much cleaner with the batch filter. Also, check out the various attributes exposed on the loop object.

@mitsuhiko

This comment has been minimized.

Member

mitsuhiko commented Jan 28, 2017

Variables cannot be set in loops and that is intentional. It was never documented that you can override variables from higher scopes and that was considered a bug. See also #641

@ThiefMaster

This comment has been minimized.

Member

ThiefMaster commented Jan 28, 2017

Maybe it'd be worth raising an exception when trying to do this in a way that worked in 2.8 but breaks in 2.9 to make it very clear that something is going wrong (except for weird behavior one might not notice immediately)?

drybjed added a commit to drybjed/debops that referenced this issue Mar 14, 2018

[debops.nginx] Fix old bug with Jinja2 >= 2.9.4
This patch fixes the bug with backwards-incompatible change in Jinja2 >=
2.9.4 which breaks use of the 'import' keyword in loops. More details:

    pallets/jinja#659

In this case, the 'normalize.css' file cannot be directly included in
the 'index.html' welcome page, therefore it will be copied alongside it
instead.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment