]> git.ipfire.org Git - thirdparty/jinja.git/commitdiff
detect custom async filters in as_const 1303/head
authorRichard Gibson <richard.gibson@gmail.com>
Thu, 22 Oct 2020 23:26:01 +0000 (19:26 -0400)
committerDavid Lord <davidism@gmail.com>
Sun, 1 Nov 2020 02:07:26 +0000 (19:07 -0700)
CHANGES.rst
src/jinja2/nodes.py
tests/test_asyncfilters.py

index 298cf0ab854eb4eae21b1dd4a359deaa44dfae6a..6f4649fd3c65e2aa8ceebd5047f92eabca843b20 100644 (file)
@@ -14,6 +14,9 @@ Unreleased
 -   Fix a bug that caused imported macros to not have access to the
     current template's globals. :issue:`688`
 -   Add ability to ignore ``trim_blocks`` using ``+%}``. :issue:`1036`
+-   Fix a bug that caused custom async-only filters to fail with
+    constant input. :issue:`1279`
+
 
 Version 2.11.2
 --------------
index 95e7b73064ee21de02dad87e8fb4dbebbc509637..3d4b6fdeda118f4523abe66750f5ed95fbdf7f5b 100644 (file)
@@ -2,6 +2,7 @@
 some node tree helper functions used by the parser and compiler in order
 to normalize nodes.
 """
+import inspect
 import operator
 from collections import deque
 from typing import Any
@@ -649,10 +650,12 @@ class Filter(Expr):
         if filter_ is None or getattr(filter_, "contextfilter", False) is True:
             raise Impossible()
 
-        # We cannot constant handle async filters, so we need to make sure
-        # to not go down this path.
-        if eval_ctx.environment.is_async and getattr(
-            filter_, "asyncfiltervariant", False
+        # We cannot constant handle async filters, so we need to make
+        # sure to not go down this path. Account for both sync/async and
+        # pure-async filters.
+        if eval_ctx.environment.is_async and (
+            getattr(filter_, "asyncfiltervariant", False)
+            or inspect.iscoroutinefunction(filter_)
         ):
             raise Impossible()
 
index 524a6d9db1c6080acb3b3e25b293fc903de7f759..b6025aca040306adbade761e99292a874039bbd3 100644 (file)
@@ -3,6 +3,7 @@ from collections import namedtuple
 import pytest
 
 from jinja2 import Environment
+from jinja2.asyncsupport import auto_aiter
 from jinja2.utils import Markup
 
 
@@ -222,3 +223,31 @@ def test_slice(env_async, items):
         "[[0, 1, 2, 3], [4, 5, 6], [7, 8, 9]]|"
         "[[0, 1, 2, 3], [4, 5, 6, 'X'], [7, 8, 9, 'X']]"
     )
+
+
+def test_custom_async_filter(env_async):
+    async def customfilter(val):
+        return str(val)
+
+    env_async.filters["customfilter"] = customfilter
+    tmpl = env_async.from_string("{{ 'static'|customfilter }} {{ arg|customfilter }}")
+    out = tmpl.render(arg="dynamic")
+    assert out == "static dynamic"
+
+
+@mark_dualiter("items", lambda: range(10))
+def test_custom_async_iteratable_filter(env_async, items):
+    async def customfilter(iterable):
+        items = []
+        async for item in auto_aiter(iterable):
+            items.append(str(item))
+            if len(items) == 3:
+                break
+        return ",".join(items)
+
+    env_async.filters["customfilter"] = customfilter
+    tmpl = env_async.from_string(
+        "{{ items()|customfilter }} .. {{ [3, 4, 5, 6]|customfilter }}"
+    )
+    out = tmpl.render(items=items)
+    assert out == "0,1,2 .. 3,4,5"