added with-statement extension.
authorArmin Ronacher <armin.ronacher@active-4.com>
Sun, 7 Feb 2010 02:55:15 +0000 (03:55 +0100)
committerArmin Ronacher <armin.ronacher@active-4.com>
Sun, 7 Feb 2010 02:55:15 +0000 (03:55 +0100)
--HG--
branch : trunk

CHANGES
docs/extensions.rst
docs/templates.rst
jinja2/ext.py
tests/test_ext.py

diff --git a/CHANGES b/CHANGES
index d915c2f910494e5c8f3145dda1ff951cc1cc992c..1b6f7d67adce1ba2f73087fc422716a8962e4197 100644 (file)
--- 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
 -------------
index 1d25a2b9852e8ef9ba3e10f2134c286e753f0716..cfd79eff5c3d311aaab749a805d3f99f4cee86b4 100644 (file)
@@ -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:
 
index e03cd8aabb18172d4381bce520096301bbeea331..06a339be54c9493acb737f82fbf9abb90aa271fd 100644 (file)
@@ -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 %}
index 482ca6c0188b55d0922815c17c36be5facfd5e16..c3c8eec0bead7a40d4463dfe1a177ea1ed0917da 100644 (file)
@@ -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
index a12ca334dc9c212d3cfe757663104c58c8715308..ef33de7ec608f6c194b2d6c32cb71e229fd74578 100644 (file)
@@ -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 %}')