]> git.ipfire.org Git - thirdparty/jinja.git/commitdiff
Fixed async macro autoescape. Fixes #671
authorArmin Ronacher <armin.ronacher@active-4.com>
Sat, 28 Jan 2017 14:33:09 +0000 (15:33 +0100)
committerArmin Ronacher <armin.ronacher@active-4.com>
Sat, 28 Jan 2017 14:33:09 +0000 (15:33 +0100)
CHANGES
jinja2/asyncsupport.py
jinja2/runtime.py
tests/test_async.py

diff --git a/CHANGES b/CHANGES
index cfaf85e9dab4a7e076c8e77a6997f2816cb1d732..7f112297688db1d828f08eb041eada0fbf1bbbf3 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -17,6 +17,7 @@ Version 2.9.5
   async environments. (#668)
 - Reduce memory footprint slightly by reducing our unicode database dump
   we use for identifier matching on Python 3 (#666)
+- Fixed autoescaping not working for macros in async compilation mode. (#671)
 
 Version 2.9.4
 -------------
index 6e82d75b1b384bb31f7adf1d6b2dbd34f479fc5f..f4f264ad8cf3e67256785decce76cbb8b857bd4e 100644 (file)
@@ -96,6 +96,22 @@ def wrap_block_reference_call(original_call):
     return update_wrapper(__call__, original_call)
 
 
+def wrap_macro_invoke(original_invoke):
+    @internalcode
+    async def async_invoke(self, arguments, autoescape):
+        rv = await self._func(*arguments)
+        if autoescape:
+            rv = Markup(rv)
+        return rv
+
+    @internalcode
+    def _invoke(self, arguments, autoescape):
+        if not self._environment.is_async:
+            return original_invoke(self, arguments, autoescape)
+        return async_invoke(self, arguments, autoescape)
+    return update_wrapper(_invoke, original_invoke)
+
+
 @internalcode
 async def get_default_module_async(self):
     if self._module is not None:
@@ -138,9 +154,10 @@ def patch_template():
 
 
 def patch_runtime():
-    from jinja2.runtime import BlockReference
+    from jinja2.runtime import BlockReference, Macro
     BlockReference.__call__ = wrap_block_reference_call(
         BlockReference.__call__)
+    Macro._invoke = wrap_macro_invoke(Macro._invoke)
 
 
 def patch_filters():
index f39e89bd0eabdf355128d60443a326b10c5fb011..24430016962c1cb541a42d35cf5289bf93d8c3e6 100644 (file)
@@ -544,6 +544,10 @@ class Macro(object):
             raise TypeError('macro %r takes not more than %d argument(s)' %
                             (self.name, len(self.arguments)))
 
+        return self._invoke(arguments, autoescape)
+
+    def _invoke(self, arguments, autoescape):
+        """This method is being swapped out by the async implementation."""
         rv = self._func(*arguments)
         if autoescape:
             rv = Markup(rv)
index 8618d8d0cbce149512357b90ebb4b7ae53941c5a..279a4bb3721624f65b60405592368add8950bf21 100644 (file)
@@ -243,6 +243,21 @@ class TestAsyncIncludes(object):
         """)
         assert t.render().strip() == '(FOO)'
 
+    def test_unoptimized_scopes_autoescape(self):
+        env = Environment(loader=DictLoader(dict(
+            o_printer='({{ o }})',
+        )), autoescape=True, enable_async=True)
+        t = env.from_string("""
+            {% macro outer(o) %}
+            {% macro inner() %}
+            {% include "o_printer" %}
+            {% endmacro %}
+            {{ inner() }}
+            {% endmacro %}
+            {{ outer("FOO") }}
+        """)
+        assert t.render().strip() == '(FOO)'
+
 
 @pytest.mark.core_tags
 @pytest.mark.for_loop