Skip to content
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 fails to render template with more than 98 if/elif statements #759

Closed
dseira opened this issue Aug 22, 2017 · 3 comments

Comments

@dseira
Copy link

commented Aug 22, 2017

Expected Behavior

No errors on rendering a template.

Actual Behavior

Having the following jinja template (this.jinja2 ) with 99 if/elif statements lines; when the template is rendered it shows the following error:

IndentationError: too many levels of indentation

On the other hand, if one of the elif statements line is removed (keeping 98 elif) the template is rendered correctly without any error.

It seems that there is a hard limit on the number of if/elif statements.

Template Code

this.jinja2

{% if name == 'server0' %}
{% elif name == 'server1' %}
{% elif name == 'server2' %}
{% elif name == 'server3' %}
....
{% elif name == 'server96' %}
{% elif name == 'server97' %}
{% elif name == 'server98' %}
{% endif %}

this.py

import os
import jinja2
def render(tpl_path, context):
    path, filename = os.path.split(tpl_path)
    return jinja2.Environment(
        loader=jinja2.FileSystemLoader(path or './')
    ).get_template(filename).render(context)

print(render('./this.jinja2', {'name': 'test'}))

Full Traceback

Traceback (most recent call last):
  File "this.py", line 9, in <module>
    print(render('./this.jinja2', {'name': 'test'}))
  File "this.py", line 7, in render
    ).get_template(filename).render(context)
  File "/usr/lib/python2.7/dist-packages/jinja2/environment.py", line 791, in get_template
    return self._load_template(name, self.make_globals(globals))
  File "/usr/lib/python2.7/dist-packages/jinja2/environment.py", line 765, in _load_template
    template = self.loader.load(self, name, globals)
  File "/usr/lib/python2.7/dist-packages/jinja2/loaders.py", line 125, in load
    code = environment.compile(source, name, filename)
  File "/usr/lib/python2.7/dist-packages/jinja2/environment.py", line 551, in compile
    return self._compile(source, filename)
  File "/usr/lib/python2.7/dist-packages/jinja2/environment.py", line 512, in _compile
    return compile(source, filename, 'exec')
  File "./this.jinja2", line 499
    if 0: yield None
                   ^
IndentationError: too many levels of indentation

Your Environment

  • Python version: 2.7.6
  • Jinja version: 2.7.2-2
@ThiefMaster

This comment has been minimized.

Copy link
Member

commented Aug 22, 2017

This happens because elif actually compiles to else: if ...:. Not sure what's the reason for that (probably there is one though).

Either way, I would recommend you to refactor your code to not have that many elifs - that sounds rather awful to have in the first place (but at least it seems to be generated code, so maybe not that bad)

ThiefMaster added a commit to ThiefMaster/jinja that referenced this issue Aug 22, 2017

Compile `elif` tag to `elif` instead of `else: if`
This avoids deep nesting in case of many `{% elif .. %}` blocks (which
would fail during execution) and also deep recursion (which may fail
during compilation)

fixes pallets#759

ThiefMaster added a commit to ThiefMaster/jinja that referenced this issue Aug 22, 2017

Compile `elif` tag to `elif` instead of `else: if`
This avoids deep nesting in case of many `{% elif .. %}` blocks (which
would fail during execution) and also deep recursion (which may fail
during compilation)

fixes pallets#759

ThiefMaster added a commit to ThiefMaster/jinja that referenced this issue Aug 22, 2017

Compile `elif` tag to `elif` instead of `else: if`
This avoids deep nesting in case of many `{% elif .. %}` blocks (which
would fail during execution) and also deep recursion (which may fail
during compilation)

fixes pallets#759
@ThiefMaster

This comment has been minimized.

Copy link
Member

commented Aug 22, 2017

I might have a fix for it - see the referenced PR. However, your Jinja version is ancient. This fix would go into 2.9.5

@dseira

This comment has been minimized.

Copy link
Author

commented Aug 22, 2017

The thing is that I've found this bug using salt configuration management (that uses jinja templating for the states), not writing a python program directly. But of course, a state can be splitted in several files.

Thanks @ThiefMaster

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants
You can’t perform that action at this time.