summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin von Gagern <gagern@google.com>2019-07-04 09:37:20 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2019-07-08 11:25:00 -0400
commitc0697963498a934a6323b8e04adf1a92aad25620 (patch)
treecadae59d2d6cd85d2bd2d9709f3c4a44977d8330
parent8648759895b8778f06528ecebf5170f67a0dc65e (diff)
downloadmako-c0697963498a934a6323b8e04adf1a92aad25620.tar.gz
Support n filter in the page tag
In some situations, it is inconvenient to pass default_filters in the Template constructor depending on the template in question. It might be easier in such situations to express page filters in the template itself. However, dropping the existing default_filters (either explicitly set or the default of ["str"] resp. ["unicode"]) might break existing templates. The code change here comes to the rescue in such situations. Existing templates keep working as they are, but editors of templates get a tool to replace the default filters for specific templates. They do take on the responsibility of turning all encountered inputs into strings, lest they fail along the lines of https://github.com/sqlalchemy/mako/issues/272. This change should be sufficiently backwards compatible to not cause any concerns. Sure, technically a "n" filter at page tag level was treated as a no-op so far. So theoretically existing templates could break. But there was no incentive to have such an "n" filter at the page tag level, and the expressed semantics of the "n" filter is to suppress default filters, so semantically anyone relying on it being a no-op in that situation was using unsupported hacks anyway. Closes: #299 Pull-request: https://github.com/sqlalchemy/mako/pull/299 Pull-request-sha: f8d5a22db3230634d2b42c59909985f31875a9f5 Change-Id: Ide030975229c1df7c0cef534976f740a03c17ca6
-rw-r--r--doc/build/filtering.rst16
-rw-r--r--doc/build/unreleased/n_page.rst13
-rw-r--r--mako/codegen.py2
-rw-r--r--test/test_filters.py11
4 files changed, 41 insertions, 1 deletions
diff --git a/doc/build/filtering.rst b/doc/build/filtering.rst
index c8765d3..c657b01 100644
--- a/doc/build/filtering.rst
+++ b/doc/build/filtering.rst
@@ -152,6 +152,8 @@ The above will generate templates something like this:
def render_body(context):
context.write(myfilter(unicode("some text")))
+.. _expression_filtering_nfilter:
+
Turning off Filtering with the ``n`` Filter
-------------------------------------------
@@ -171,6 +173,20 @@ will render ``myexpression`` with no filtering of any kind, and:
will render ``myexpression`` using the ``trim`` filter only.
+Including the ``n`` filter in a ``<%page>`` tag will only disable
+``default_filters``. In effect this makes the filters from the tag replace
+default filters instead of adding to them. For example:
+
+.. sourcecode:: mako
+
+ <%page expression_filter="n, json.dumps"/>
+ data = {a: ${123}, b: ${"123"}};
+
+will suppress turning the values into strings using the default filter, so that
+``json.dumps`` (which requires ``imports=["import json"]`` or something
+equivalent) can take the value type into account, formatting numbers as numeric
+literals and strings as string literals.
+
Filtering Defs and Blocks
=========================
diff --git a/doc/build/unreleased/n_page.rst b/doc/build/unreleased/n_page.rst
new file mode 100644
index 0000000..958a5ba
--- /dev/null
+++ b/doc/build/unreleased/n_page.rst
@@ -0,0 +1,13 @@
+.. change::
+ :tags: feature, template
+
+ The ``n`` filter is now supported in the ``<%page>`` tag. This allows a
+ template to omit the default expression filters throughout a whole
+ template, for those cases where a template-wide filter needs to have
+ default filtering disabled. Pull request courtesy Martin von Gagern.
+
+ .. seealso::
+
+ :ref:`expression_filtering_nfilter`
+
+
diff --git a/mako/codegen.py b/mako/codegen.py
index 1acc5e6..5ca7b04 100644
--- a/mako/codegen.py
+++ b/mako/codegen.py
@@ -802,7 +802,7 @@ class _GenerateRenderMethod(object):
if is_expression:
if self.compiler.pagetag:
args = self.compiler.pagetag.filter_args.args + args
- if self.compiler.default_filters:
+ if self.compiler.default_filters and "n" not in args:
args = self.compiler.default_filters + args
for e in args:
# if filter given as a function, get just the identifier portion
diff --git a/test/test_filters.py b/test/test_filters.py
index 598cb45..a58a01f 100644
--- a/test/test_filters.py
+++ b/test/test_filters.py
@@ -294,6 +294,17 @@ class FilterTest(TemplateTest):
)
assert t.render().strip() == "&lt;tag&gt;this is html&lt;/tag&gt;"
+ def test_global_json(self):
+ t = Template(
+ """
+<%!
+import json
+%><%page expression_filter="n, json.dumps"/>
+data = {a: ${123}, b: ${"123"}};
+ """
+ )
+ assert t.render().strip() == """data = {a: 123, b: "123"};"""
+
def test_non_expression(self):
t = Template(
"""