diff --git a/CHANGES.rst b/CHANGES.rst index 7ee75a6a7..5668e549d 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -5,6 +5,9 @@ Version 3.2.0 Unreleased +- Fix ``unique()`` when chained with `reject()` or `rejectattr()` + :issue:`1781` + Version 3.1.2 ------------- diff --git a/src/jinja2/filters.py b/src/jinja2/filters.py index ed07c4c0e..60dc1046b 100644 --- a/src/jinja2/filters.py +++ b/src/jinja2/filters.py @@ -410,7 +410,7 @@ def do_sort( @pass_environment -def do_unique( +def sync_do_unique( environment: "Environment", value: "t.Iterable[V]", case_sensitive: bool = False, @@ -442,6 +442,18 @@ def do_unique( yield item +@async_variant(sync_do_unique) # type: ignore +async def do_unique( + environment: "Environment", + value: "t.Union[t.AsyncIterable[V], t.Iterable[V]]", + case_sensitive: bool = False, + attribute: t.Optional[t.Union[str, int]] = None, +) -> "t.Iterator[V]": + return sync_do_unique( + environment, await auto_to_list(value), case_sensitive, attribute + ) + + def _min_or_max( environment: "Environment", value: "t.Iterable[V]", diff --git a/tests/test_async_filters.py b/tests/test_async_filters.py index f5b2627ad..b8aadf509 100644 --- a/tests/test_async_filters.py +++ b/tests/test_async_filters.py @@ -245,6 +245,13 @@ def test_slice(env_async, items): ) +def test_unique_with_async_gen(env_async): + items = ["a", "b", "c", "c", "a", "d", "z"] + tmpl = env_async.from_string("{{ items|reject('==', 'z')|unique|list }}") + out = tmpl.render(items=items) + assert out == "['a', 'b', 'c', 'd']" + + def test_custom_async_filter(env_async): async def customfilter(val): return str(val)