]> git.ipfire.org Git - thirdparty/jinja.git/commitdiff
Documented loop.depth and added loop.depth0.
authorArmin Ronacher <armin.ronacher@active-4.com>
Mon, 20 May 2013 08:26:57 +0000 (09:26 +0100)
committerArmin Ronacher <armin.ronacher@active-4.com>
Mon, 20 May 2013 08:26:57 +0000 (09:26 +0100)
CHANGES
docs/templates.rst
jinja2/compiler.py
jinja2/runtime.py
jinja2/testsuite/core_tags.py

diff --git a/CHANGES b/CHANGES
index d45f78cce483ca3678a8bc23906f72c535bdf52c..7dac016565a4971f92c3677674a0057e2d743cf5 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -28,6 +28,8 @@ Version 2.7
   of blocks.
 - Added `map`, `select`, `reject`, `selectattr` and `rejectattr`
   filters.
+- Added support for `loop.depth` to figure out how deep inside a recursive
+  loop the code is.
 
 Version 2.6
 -----------
index 6bc6e04aa9bb34c94c1aac8157947796b03de472..e0a19fa3d86a19ec681fc2b8aaca1c44fa3b6e64 100644 (file)
@@ -576,6 +576,12 @@ Inside of a for-loop block you can access some special variables:
 | `loop.cycle`          | A helper function to cycle between a list of      |
 |                       | sequences.  See the explanation below.            |
 +-----------------------+---------------------------------------------------+
+| `loop.depth`          | Indicates how deep in deep in a recursive loop    |
+|                       | the rendering currently is.  Starts at level 1    |
++-----------------------+---------------------------------------------------+
+| `loop.depth0          | Indicates how deep in deep in a recursive loop    |
+|                       | the rendering currently is.  Starts at level 0    |
++-----------------------+---------------------------------------------------+
 
 Within a for-loop, it's possible to cycle among a list of strings/variables
 each time through the loop by using the special `loop.cycle` helper::
index 7a42c6d4503a5be60bd3f4d2a76b9a1056c62a7e..d9d7ef97fc841fb3566c409a697288232bd07c02 100644 (file)
@@ -1066,7 +1066,7 @@ class CodeGenerator(NodeVisitor):
 
         # otherwise we set up a buffer and add a function def
         else:
-            self.writeline('def loop(reciter, loop_render_func):', node)
+            self.writeline('def loop(reciter, loop_render_func, depth=0):', node)
             self.indent()
             self.buffer(loop_frame)
             aliases = {}
@@ -1125,7 +1125,7 @@ class CodeGenerator(NodeVisitor):
             self.visit(node.iter, loop_frame)
 
         if node.recursive:
-            self.write(', recurse=loop_render_func):')
+            self.write(', loop_render_func, depth):')
         else:
             self.write(extended_loop and '):' or ':')
 
index 38a86974586f22720797ccfc16771612a67e4641..d27ca537cd7259872b54d96851a3b497443fdd0d 100644 (file)
@@ -280,11 +280,12 @@ class BlockReference(object):
 class LoopContext(object):
     """A loop context for dynamic iteration."""
 
-    def __init__(self, iterable, recurse=None):
+    def __init__(self, iterable, recurse=None, depth0=0):
         self._iterator = iter(iterable)
         self._recurse = recurse
         self._after = self._safe_next()
         self.index0 = -1
+        self.depth0 = depth0
 
         # try to get the length of the iterable early.  This must be done
         # here because there are some broken iterators around where there
@@ -306,6 +307,7 @@ class LoopContext(object):
     index = property(lambda x: x.index0 + 1)
     revindex = property(lambda x: x.length - x.index0)
     revindex0 = property(lambda x: x.length - x.index)
+    depth = property(lambda x: x.depth0 + 1)
 
     def __len__(self):
         return self.length
@@ -324,7 +326,7 @@ class LoopContext(object):
         if self._recurse is None:
             raise TypeError('Tried to call non recursive loop.  Maybe you '
                             "forgot the 'recursive' modifier.")
-        return self._recurse(iterable, self._recurse)
+        return self._recurse(iterable, self._recurse, self.depth0 + 1)
 
     # a nifty trick to enhance the error message if someone tried to call
     # the the loop without or with too many arguments.
index 409a5791fecf95463605ab4e313511b17f889be7..f1a20fd44d60c6d43f3a85656d9cac529cae746b 100644 (file)
@@ -85,6 +85,26 @@ class ForLoopTestCase(JinjaTestCase):
             dict(a=3, b=[dict(a='a')])
         ]) == '[1<[1][2]>][2<[1][2]>][3<[a]>]'
 
+    def test_recursive_depth0(self):
+        tmpl = env.from_string('''{% for item in seq recursive -%}
+            [{{ loop.depth0 }}:{{ item.a }}{% if item.b %}<{{ loop(item.b) }}>{% endif %}]
+        {%- endfor %}''')
+        self.assertEqual(tmpl.render(seq=[
+            dict(a=1, b=[dict(a=1), dict(a=2)]),
+            dict(a=2, b=[dict(a=1), dict(a=2)]),
+            dict(a=3, b=[dict(a='a')])
+        ]), '[0:1<[1:1][1:2]>][0:2<[1:1][1:2]>][0:3<[1:a]>]')
+
+    def test_recursive_depth(self):
+        tmpl = env.from_string('''{% for item in seq recursive -%}
+            [{{ loop.depth }}:{{ item.a }}{% if item.b %}<{{ loop(item.b) }}>{% endif %}]
+        {%- endfor %}''')
+        self.assertEqual(tmpl.render(seq=[
+            dict(a=1, b=[dict(a=1), dict(a=2)]),
+            dict(a=2, b=[dict(a=1), dict(a=2)]),
+            dict(a=3, b=[dict(a='a')])
+        ]), '[1:1<[2:1][2:2]>][1:2<[2:1][2:2]>][1:3<[2:a]>]')
+
     def test_looploop(self):
         tmpl = env.from_string('''{% for row in table %}
             {%- set rowloop = loop -%}