From: Richard Gibson Date: Thu, 22 Oct 2020 23:26:01 +0000 (-0400) Subject: detect custom async filters in as_const X-Git-Tag: 3.0.0rc1~66^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e1d0131a7fda35029f48cac994e1635025f95461;p=thirdparty%2Fjinja.git detect custom async filters in as_const --- diff --git a/CHANGES.rst b/CHANGES.rst index 298cf0ab..6f4649fd 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -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 -------------- diff --git a/src/jinja2/nodes.py b/src/jinja2/nodes.py index 95e7b730..3d4b6fde 100644 --- a/src/jinja2/nodes.py +++ b/src/jinja2/nodes.py @@ -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() diff --git a/tests/test_asyncfilters.py b/tests/test_asyncfilters.py index 524a6d9d..b6025aca 100644 --- a/tests/test_asyncfilters.py +++ b/tests/test_asyncfilters.py @@ -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"