From: Armin Ronacher Date: Sun, 7 Feb 2010 02:55:15 +0000 (+0100) Subject: added with-statement extension. X-Git-Tag: 2.3~27 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=9b4cc9ff08b2a80c948c442344b6fca1650e64e6;p=jinja2.git added with-statement extension. --HG-- branch : trunk --- diff --git a/CHANGES b/CHANGES index d915c2f..1b6f7d6 100644 --- a/CHANGES +++ b/CHANGES @@ -19,6 +19,7 @@ Version 2.3 This change makes ``{% if %}...{% endif %}`` a syntax error now. (#364) - added support for translator comments if extracted via babel. +- added with-statement extension. Version 2.2.1 ------------- diff --git a/docs/extensions.rst b/docs/extensions.rst index 1d25a2b..cfd79ef 100644 --- a/docs/extensions.rst +++ b/docs/extensions.rst @@ -112,6 +112,20 @@ This extension adds support for `break` and `continue` in loops. After enabling Jinja2 provides those two keywords which work exactly like in Python. +.. _with-extension: + +With Statement +-------------- + +**Import name:** `jinja2.ext.with_` + +.. versionadded:: 2.3 + +This extension adds support for the with keyword. Using this keyword it +is possible to enforce a nested scope in a template. Variables can be +declared directly in the opening block of the with statement or using a +standard `set` statement directly within. + .. _writing-extensions: diff --git a/docs/templates.rst b/docs/templates.rst index e03cd8a..06a339b 100644 --- a/docs/templates.rst +++ b/docs/templates.rst @@ -1252,3 +1252,35 @@ Likewise a look that stops processing after the 10th iteration:: {% for user in users %} {%- if loop.index >= 10 %}{% break %}{% endif %} {%- endfor %} + + +With Statement +~~~~~~~~~~~~~~ + +.. versionadded:: 2.3 + +If the application enables the :ref:`with-extension` it is possible to +use the `with` keyword in templates. This makes it possible to create +a new inner scope. Variables set within this scope are not visible +outside of the scope. + +With in a nutshell:: + + {% with %} + {% set foo = 42 %} + {{ foo }} foo is 42 here + {% endwith %} + foo is not visible here any longer + +Because it is common to set variables at the beginning of the scope +you can do that within the with statement. The following two examples +are equivalent:: + + {% with foo = 42 %} + {{ foo }} + {% endwith %} + + {% with %} + {% set foo = 42 %} + {{ foo }} + {% endwith %} diff --git a/jinja2/ext.py b/jinja2/ext.py index 482ca6c..c3c8eec 100644 --- a/jinja2/ext.py +++ b/jinja2/ext.py @@ -336,6 +336,27 @@ class LoopControlExtension(Extension): return nodes.Continue(lineno=token.lineno) +class WithExtension(Extension): + """Adds support for a django-like with block.""" + tags = set(['with']) + + def parse(self, parser): + node = nodes.Scope(lineno=next(parser.stream).lineno) + assignments = [] + while parser.stream.current.type != 'block_end': + lineno = parser.stream.current.lineno + if assignments: + parser.stream.expect('comma') + target = parser.parse_assign_target() + parser.stream.expect('assign') + expr = parser.parse_expression() + assignments.append(nodes.Assign(target, expr, lineno=lineno)) + node.body = assignments + \ + list(parser.parse_statements(('name:endwith',), + drop_needle=True)) + return node + + def extract_from_ast(node, gettext_functions=GETTEXT_FUNCTIONS, babel_style=True): """Extract localizable strings from the given template node. Per @@ -507,3 +528,4 @@ def babel_extract(fileobj, keywords, comment_tags, options): i18n = InternationalizationExtension do = ExprStmtExtension loopcontrols = LoopControlExtension +with_ = WithExtension diff --git a/tests/test_ext.py b/tests/test_ext.py index a12ca33..ef33de7 100644 --- a/tests/test_ext.py +++ b/tests/test_ext.py @@ -106,6 +106,18 @@ def test_do(): assert tmpl.render() == '0f, 1o, 2o' +def test_with(): + env = Environment(extensions=['jinja2.ext.with_']) + tmpl = env.from_string('''\ + {% with a=42, b=23 -%} + {{ a }} = {{ b }} + {% endwith -%} + {{ a }} = {{ b }}\ + ''') + assert [x.strip() for x in tmpl.render(a=1, b=2).splitlines()] \ + == ['42 = 23', '1 = 2'] + + def test_extension_nodes(): env = Environment(extensions=[TestExtension]) tmpl = env.from_string('{% test %}')