Jinja 2.3 Released
As promised, the libraries I am maintaining get new releases around now :) The first one in a series is Jinja 2, the sandboxed template engine for Python. First it was planned for this to be a bugfix release for 2.2 which came with two scoping bugs, but along the way I was able to fix more problems on the way and integrate cool new features as well. So what is new in Jinja 2.3? First of all, it's 100% backwards compatible so don't hesitate to upgrade.
Changelog
- Fixed a couple of bugs with the code generator. Added many new tests for edge cases where Jinja's and Python's scoping rules fight each other. Hopefully no more
UnboundLocalError: local variable 'l_foo' referenced before assignment. - Include tags can now select between multiple templates, and so you can do when loading templates.
- Greatly improved error reporting for syntax errors
- The i18n extension can now extract translation comments preceding translatable strings.
- Added support for a
withblock that works similar to Django'swithblock, just with support for multiple variables. - Experimental Python 3 support
New Include Tags and Template Selection
As proposed by Justin Lilly an include tag can now accept multiple template names and will use the firs that succeeds. So that means you can do stuff like this:
{% include ["custom/article_%s.html" % article.id, "article.html", "page.html"] %}
Of course, that list can be a list-variable as well. This also lead to a two method on the environment that attempts to select from a list of templates and uses the first that succeeds. There are in total three methods now to load templates:
environment.get_template('template_name.html') environment.select_template(['template1.html', 'template2.html']) environment.get_or_select_template(...)
get_or_select_template will check the type of the argument and either call get_template or select_template. This is mainly used internally by the include tag if it has to figure out at runtime what to do. However you can of course use that in your code as well which could be handy. Just replace get_template in your general-purpose render function with get_or_select_template to support the alternative list-based lookup as well.
Improved Error Messages
For a long time Jinja 2 did not really give good hints if you wrote end-tags wrong. Now it will give you something more friendly than just unknown tag endif if you nest the tags wrong:
{% for item in seq %} {{ item }}
jinja2.exceptions.TemplateSyntaxError: Unexpected end of template. Jinja was looking for the following tags: 'endfor' or 'else'. The innermost block that needs to be closed is 'for'.
{% for item in seq %} {% if item.something %}...{% endi %} {% endfor %}
jinja2.exceptions.TemplateSyntaxError: Encountered unknown tag 'endi'. Jinja was looking for the following tags: 'elif' or 'else' or 'endif'. The innermost block that needs to be closed is 'if'.
{% block invalid-name %} ... {% endblock %}
jinja2.exceptions.TemplateSyntaxError: Block names in Jinja have to be valid Python identifiers and may not contain hypens, use an underscore instead.
Especially the latter will come in handy for people switching over from Django who are used to hypens in identifiers. Before that change it would have printed "expected block_end" instead which is not very friendly and helpful.
Translator Comments
If you are using the i18n extension with Babel you can now provide comments for the translators. Just put the comment in the line before the gettext call / trans block or in the same line (before or after the call) and prefix it with one of the comment tags you have babel configured to use. For example you could use "trans", "l" or "_" for the comment tags. Here some examples how you could use it:
{#_ this is not shown to the user under regular circumstances #} <p>{{ _('Tempered with form data') }} <dl> <dd>{{ _('Username') }}: {# trans the actual login name of the user #} </dl> {# trans count is the number of logged in users. Message shown in a small dialog #} <p>{% trans count=users|length %} {{ count }} user is online {% pluralize %} {{ count }} users are online {% endtrans %}
Python 3 Support
This is the first Jinja 2 release that comes with experimental support for Python 3. All regular unittests pass but there are certainly some parts of Jinja 2 which have to be rewritten or re-specified for better Python 3 support. If you are using Jinja 2 with Python 3, please give feedback. Also the error reporting on Python 3 does not work yet like it should. In order to use it with Python 3 you must have the excellent distribute library installed. Also for Python 2.x I strongly recommend using distribute instead of setuptools, although both are supported.
Grab it while it's hot from the cheeseshop.
Expect a blog post about unittesting and 2to3 soon. Got some experiences to share :)
Thanks for the i18n enhancements!
— Jeff Balogh on Wednesday, February 10, 2010 2:29 #
Any GAE improvements in the pipeline? Thanks!
— Steve on Wednesday, February 10, 2010 6:52 #
GAE improvements are planned, but I can't promise anything yet.
— Armin Ronacher on Wednesday, February 10, 2010 7:21 #