diff options
author | Armin Ronacher <armin.ronacher@active-4.com> | 2013-05-20 09:26:57 +0100 |
---|---|---|
committer | Armin Ronacher <armin.ronacher@active-4.com> | 2013-05-20 09:26:57 +0100 |
commit | 568352e07d74cb4f333d47ae054de3a2991b97ba (patch) | |
tree | 1443ddb9d161a701936a7cce417d993cc3ada61d | |
parent | dcd0cb73120e2d924e7064933cefd3246f3cfffa (diff) | |
download | jinja2-568352e07d74cb4f333d47ae054de3a2991b97ba.tar.gz |
Documented loop.depth and added loop.depth0.
-rw-r--r-- | CHANGES | 2 | ||||
-rw-r--r-- | docs/templates.rst | 6 | ||||
-rw-r--r-- | jinja2/compiler.py | 4 | ||||
-rw-r--r-- | jinja2/runtime.py | 6 | ||||
-rw-r--r-- | jinja2/testsuite/core_tags.py | 20 |
5 files changed, 34 insertions, 4 deletions
@@ -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 ----------- diff --git a/docs/templates.rst b/docs/templates.rst index 6bc6e04..e0a19fa 100644 --- a/docs/templates.rst +++ b/docs/templates.rst @@ -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:: diff --git a/jinja2/compiler.py b/jinja2/compiler.py index 7a42c6d..d9d7ef9 100644 --- a/jinja2/compiler.py +++ b/jinja2/compiler.py @@ -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 ':') diff --git a/jinja2/runtime.py b/jinja2/runtime.py index 38a8697..d27ca53 100644 --- a/jinja2/runtime.py +++ b/jinja2/runtime.py @@ -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. diff --git a/jinja2/testsuite/core_tags.py b/jinja2/testsuite/core_tags.py index 409a579..f1a20fd 100644 --- a/jinja2/testsuite/core_tags.py +++ b/jinja2/testsuite/core_tags.py @@ -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 -%} |