From e2da2f1647bba8274ed1410f96a0067ba61bea51 Mon Sep 17 00:00:00 2001 From: ThiefMaster Date: Sat, 12 Sep 2015 00:27:07 +0200 Subject: [PATCH] Support filters in set block - e.g {% set foo | trim %}...{% endset %} - closes #486 --- CHANGES | 1 + docs/templates.rst | 11 +++++++++++ jinja2/compiler.py | 7 ++++++- jinja2/nodes.py | 2 +- jinja2/parser.py | 3 ++- tests/test_core_tags.py | 13 +++++++++++++ 6 files changed, 34 insertions(+), 3 deletions(-) diff --git a/CHANGES b/CHANGES index 7ed12dc82..700627a31 100644 --- a/CHANGES +++ b/CHANGES @@ -35,6 +35,7 @@ Version 2.9 tests in one expression without extra parentheses. In particular you can now write ``foo is divisibleby 2 or foo is divisibleby 3`` as you would expect. +- Added filter support to the block ``set`` tag. Version 2.8.2 ------------- diff --git a/docs/templates.rst b/docs/templates.rst index 9c3e7d5fa..b99b4c519 100644 --- a/docs/templates.rst +++ b/docs/templates.rst @@ -865,6 +865,17 @@ Example:: The `navigation` variable then contains the navigation HTML source. +.. versionchanged:: 2.9 + +Starting with Jinja 2.9, the block assignment supports filters. + +Example:: + + {% set reply | wordwrap %} + You wrote: + {{ message }} + {% endset %} + .. _extends: diff --git a/jinja2/compiler.py b/jinja2/compiler.py index 6595d6321..594d7cf4a 100644 --- a/jinja2/compiler.py +++ b/jinja2/compiler.py @@ -1314,7 +1314,12 @@ def visit_AssignBlock(self, node, frame): self.newline(node) self.visit(node.target, frame) self.write(' = (Markup if context.eval_ctx.autoescape ' - 'else identity)(concat(%s))' % block_frame.buffer) + 'else identity)(') + if node.filter is not None: + self.visit_Filter(node.filter, block_frame) + else: + self.write('concat(%s)' % block_frame.buffer) + self.write(')') self.pop_assign_tracking(frame) self.leave_frame(block_frame) diff --git a/jinja2/nodes.py b/jinja2/nodes.py index 5e0726a36..3e784ad9c 100644 --- a/jinja2/nodes.py +++ b/jinja2/nodes.py @@ -378,7 +378,7 @@ class Assign(Stmt): class AssignBlock(Stmt): """Assigns a block to a target.""" - fields = ('target', 'body') + fields = ('target', 'filter', 'body') class Expr(Node): diff --git a/jinja2/parser.py b/jinja2/parser.py index 00e055807..fba39caf3 100644 --- a/jinja2/parser.py +++ b/jinja2/parser.py @@ -180,9 +180,10 @@ def parse_set(self): if self.stream.skip_if('assign'): expr = self.parse_tuple() return nodes.Assign(target, expr, lineno=lineno) + filter_node = self.parse_filter(None) body = self.parse_statements(('name:endset',), drop_needle=True) - return nodes.AssignBlock(target, body, lineno=lineno) + return nodes.AssignBlock(target, filter_node, body, lineno=lineno) def parse_for(self): """Parse a for loop.""" diff --git a/tests/test_core_tags.py b/tests/test_core_tags.py index 0a865f53e..17f59bd87 100644 --- a/tests/test_core_tags.py +++ b/tests/test_core_tags.py @@ -354,3 +354,16 @@ def test_block_escaping(self): tmpl = env.from_string('{% set foo %}{{ test }}' '{% endset %}foo: {{ foo }}') assert tmpl.render(test='') == 'foo: <unsafe>' + + def test_block_escaping_filtered(self): + env = Environment(autoescape=True) + tmpl = env.from_string('{% set foo | trim %}{{ test }} ' + '{% endset %}foo: {{ foo }}') + assert tmpl.render(test='') == 'foo: <unsafe>' + + def test_block_filtered(self, env_trim): + tmpl = env_trim.from_string( + '{% set foo | trim | length | string %} 42 {% endset %}' + '{{ foo }}') + assert tmpl.render() == '2' + assert tmpl.module.foo == u'2'