]> git.ipfire.org Git - thirdparty/jinja.git/commitdiff
Added reject/rejectattr with basic async support
authorArmin Ronacher <armin.ronacher@active-4.com>
Wed, 28 Dec 2016 23:05:02 +0000 (00:05 +0100)
committerArmin Ronacher <armin.ronacher@active-4.com>
Wed, 28 Dec 2016 23:05:02 +0000 (00:05 +0100)
jinja2/asyncfilters.py
jinja2/filters.py
tests/test_asyncfilters.py

index c621ae41f175bf548f06971870a5c59390d11352..78fafed88e64abe7cd02dccf8cd79836664a64c7 100644 (file)
@@ -15,13 +15,23 @@ async def auto_to_seq(value):
     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
 
@@ -67,8 +77,22 @@ async def do_join(eval_ctx, value, d=u'', attribute=None):
     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,
 }
index b5fa456f304cb42f14f6dae6b231ee9e472677dc..b16e73ee78bb87fe555a7b202c4cff2ba29ba282 100644 (file)
@@ -860,7 +860,7 @@ def do_select(*args, **kwargs):
 
     .. versionadded:: 2.7
     """
-    return _select_or_reject(args, kwargs, lambda x: x, False)
+    return select_or_reject(args, kwargs, lambda x: x, False)
 
 
 @contextfilter
@@ -878,7 +878,7 @@ def do_reject(*args, **kwargs):
 
     .. 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
@@ -899,7 +899,7 @@ def do_selectattr(*args, **kwargs):
 
     .. versionadded:: 2.7
     """
-    return _select_or_reject(args, kwargs, lambda x: x, True)
+    return select_or_reject(args, kwargs, lambda x: x, True)
 
 
 @contextfilter
@@ -918,10 +918,10 @@ def do_rejectattr(*args, **kwargs):
 
     .. 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:
@@ -943,9 +943,14 @@ def _select_or_reject(args, kwargs, modfunc, 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
 
 
index 4be25a3a92085387b9728b8d2681bdca66fcc271..69f4e924a38402b44cdd9be5bf43ffa3ebeffbcc 100644 (file)
@@ -116,3 +116,15 @@ def make_users():
 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'