return seq
+async def async_select_or_reject(args, kwargs, modfunc, lookup_attr):
+ seq, func = filters.prepare_select_or_reject(
+ args, kwargs, modfunc, lookup_attr)
+ if seq:
+ async for item in auto_aiter(seq):
+ if func(item):
+ yield item
+
+
def dualfilter(normal_filter, async_filter):
wrap_evalctx = False
if getattr(normal_filter, 'environmentfilter', False):
is_async = lambda args: args[0].is_async
wrap_evalctx = False
else:
- if not getattr(normal_filter, 'evalcontextfilter', False):
+ if not getattr(normal_filter, 'evalcontextfilter', False) and \
+ not getattr(normal_filter, 'contextfilter', False):
wrap_evalctx = True
is_async = lambda args: args[0].environment.is_async
return filters.do_join(eval_ctx, await auto_to_seq(value), d, attribute)
+@asyncfiltervariant(filters.do_reject)
+async def do_reject(*args, **kwargs):
+ return async_select_or_reject(args, kwargs, lambda x: not x, False)
+
+
+@asyncfiltervariant(filters.do_rejectattr)
+async def do_rejectattr(*args, **kwargs):
+ return async_select_or_reject(args, kwargs, lambda x: not x, True)
+
+
ASYNC_FILTERS = {
'first': do_first,
'groupby': do_groupby,
'join': do_join,
+ # we intentionally do not support do_last because that would be
+ # ridiculous
+ 'reject': do_reject,
+ 'rejectattr': do_rejectattr,
}
.. versionadded:: 2.7
"""
- return _select_or_reject(args, kwargs, lambda x: x, False)
+ return select_or_reject(args, kwargs, lambda x: x, False)
@contextfilter
.. versionadded:: 2.7
"""
- return _select_or_reject(args, kwargs, lambda x: not x, False)
+ return select_or_reject(args, kwargs, lambda x: not x, False)
@contextfilter
.. versionadded:: 2.7
"""
- return _select_or_reject(args, kwargs, lambda x: x, True)
+ return select_or_reject(args, kwargs, lambda x: x, True)
@contextfilter
.. versionadded:: 2.7
"""
- return _select_or_reject(args, kwargs, lambda x: not x, True)
+ return select_or_reject(args, kwargs, lambda x: not x, True)
-def _select_or_reject(args, kwargs, modfunc, lookup_attr):
+def prepare_select_or_reject(args, kwargs, modfunc, lookup_attr):
context = args[0]
seq = args[1]
if lookup_attr:
except LookupError:
func = bool
+ return seq, lambda item: modfunc(func(transfunc(item)))
+
+
+def select_or_reject(args, kwargs, modfunc, lookup_attr):
+ seq, func = prepare_select_or_reject(args, kwargs, modfunc, lookup_attr)
if seq:
for item in seq:
- if modfunc(func(transfunc(item))):
+ if func(item):
yield item
def test_join_attribute(env_async, users):
tmpl = env_async.from_string('''{{ users()|join(', ', 'username') }}''')
assert tmpl.render(users=users) == 'foo, bar'
+
+
+def test_simple_reject(env_async):
+ tmpl = env_async.from_string('{{ [1, 2, 3, 4, 5]|reject("odd")|join("|") }}')
+ assert tmpl.render() == '2|4'
+
+
+def test_bool_reject(env_async):
+ tmpl = env_async.from_string(
+ '{{ [none, false, 0, 1, 2, 3, 4, 5]|reject|join("|") }}'
+ )
+ assert tmpl.render() == 'None|False|0'