Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support filters in set block #489

Merged
merged 1 commit into from Oct 31, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGES
Expand Up @@ -33,10 +33,12 @@ Version 2.10
- Add ``reverse`` argument for ``dictsort`` filter. (`#692`_)
- Add a ``NativeEnvironment`` that renders templates to native Python types
instead of strings. (`#708`_)
- Added filter support to the block ``set`` tag. (`#489`_)

.. _#469: https://github.com/pallets/jinja/pull/469
.. _#475: https://github.com/pallets/jinja/pull/475
.. _#478: https://github.com/pallets/jinja/pull/478
.. _#489: https://github.com/pallets/jinja/pull/489
.. _#617: https://github.com/pallets/jinja/pull/617
.. _#618: https://github.com/pallets/jinja/pull/618
.. _#665: https://github.com/pallets/jinja/pull/665
Expand Down
11 changes: 11 additions & 0 deletions docs/templates.rst
Expand Up @@ -947,6 +947,17 @@ Example::

The `navigation` variable then contains the navigation HTML source.

.. versionchanged:: 2.10

Starting with Jinja 2.10, the block assignment supports filters.

Example::

{% set reply | wordwrap %}
You wrote:
{{ message }}
{% endset %}


.. _extends:

Expand Down
7 changes: 6 additions & 1 deletion jinja2/compiler.py
Expand Up @@ -1385,7 +1385,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(')')

This comment was marked as off-topic.

This comment was marked as off-topic.

This comment was marked as off-topic.

self.pop_assign_tracking(frame)
self.leave_frame(block_frame)

Expand Down
2 changes: 1 addition & 1 deletion jinja2/nodes.py
Expand Up @@ -387,7 +387,7 @@ class Assign(Stmt):

class AssignBlock(Stmt):
"""Assigns a block to a target."""
fields = ('target', 'body')
fields = ('target', 'filter', 'body')


class Expr(Node):
Expand Down
3 changes: 2 additions & 1 deletion jinja2/parser.py
Expand Up @@ -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."""
Expand Down
27 changes: 27 additions & 0 deletions tests/test_core_tags.py
Expand Up @@ -453,6 +453,33 @@ def test_namespace_macro(self, env_trim):
'{{ ns.a }}|{{ ns.b }}')
assert tmpl.render() == '13|37'

def test_block_escaping_filtered(self):
env = Environment(autoescape=True)
tmpl = env.from_string('{% set foo | trim %}<em>{{ test }}</em> '
'{% endset %}foo: {{ foo }}')
assert tmpl.render(test='<unsafe>') == 'foo: <em>&lt;unsafe&gt;</em>'

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'

def test_block_filtered_set(self, env_trim):
def _myfilter(val, arg):
assert arg == ' xxx '
return val
env_trim.filters['myfilter'] = _myfilter
tmpl = env_trim.from_string(
'{% set a = " xxx " %}'
'{% set foo | myfilter(a) | trim | length | string %}'
' {% set b = " yy " %} 42 {{ a }}{{ b }} '
'{% endset %}'
'{{ foo }}')
assert tmpl.render() == '11'
assert tmpl.module.foo == u'11'


@pytest.mark.core_tags
@pytest.mark.with_
Expand Down