]> git.ipfire.org Git - thirdparty/jinja.git/commitdiff
Ported map and select
authorArmin Ronacher <armin.ronacher@active-4.com>
Wed, 28 Dec 2016 23:11:40 +0000 (00:11 +0100)
committerArmin Ronacher <armin.ronacher@active-4.com>
Wed, 28 Dec 2016 23:11:40 +0000 (00:11 +0100)
jinja2/asyncfilters.py
jinja2/filters.py
tests/test_asyncfilters.py

index 78fafed88e64abe7cd02dccf8cd79836664a64c7..2a6eb5200b744d078790c232de5adf2a54c80db8 100644 (file)
@@ -87,12 +87,33 @@ async def do_rejectattr(*args, **kwargs):
     return async_select_or_reject(args, kwargs, lambda x: not x, True)
 
 
+@asyncfiltervariant(filters.do_select)
+async def do_select(*args, **kwargs):
+    return async_select_or_reject(args, kwargs, lambda x: x, False)
+
+
+@asyncfiltervariant(filters.do_selectattr)
+async def do_selectattr(*args, **kwargs):
+    return async_select_or_reject(args, kwargs, lambda x: x, True)
+
+
+@asyncfiltervariant(filters.do_map)
+async def do_map(*args, **kwargs):
+    seq, func = filters.prepare_map(args, kwargs)
+    if seq:
+        async for item in seq:
+            yield func(item)
+
+
 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,
+    'reject':       do_reject,
+    'rejectattr':   do_rejectattr,
+    'map':          do_map,
+    'select':       do_select,
+    'selectattr':   do_selectattr,
 }
index b16e73ee78bb87fe555a7b202c4cff2ba29ba282..2d4597321bd5ba6e025a5ce7c1375cb6379f7320 100644 (file)
@@ -821,24 +821,7 @@ def do_map(*args, **kwargs):
 
     .. versionadded:: 2.7
     """
-    context = args[0]
-    seq = args[1]
-
-    if len(args) == 2 and 'attribute' in kwargs:
-        attribute = kwargs.pop('attribute')
-        if kwargs:
-            raise FilterArgumentError('Unexpected keyword argument %r' %
-                next(iter(kwargs)))
-        func = make_attrgetter(context.environment, attribute)
-    else:
-        try:
-            name = args[2]
-            args = args[3:]
-        except LookupError:
-            raise FilterArgumentError('map requires a filter argument')
-        func = lambda item: context.environment.call_filter(
-            name, item, args, kwargs, context=context)
-
+    seq, func = prepare_map(args, kwargs)
     if seq:
         for item in seq:
             yield func(item)
@@ -921,6 +904,28 @@ def do_rejectattr(*args, **kwargs):
     return select_or_reject(args, kwargs, lambda x: not x, True)
 
 
+def prepare_map(args, kwargs):
+    context = args[0]
+    seq = args[1]
+
+    if len(args) == 2 and 'attribute' in kwargs:
+        attribute = kwargs.pop('attribute')
+        if kwargs:
+            raise FilterArgumentError('Unexpected keyword argument %r' %
+                next(iter(kwargs)))
+        func = make_attrgetter(context.environment, attribute)
+    else:
+        try:
+            name = args[2]
+            args = args[3:]
+        except LookupError:
+            raise FilterArgumentError('map requires a filter argument')
+        func = lambda item: context.environment.call_filter(
+            name, item, args, kwargs, context=context)
+
+    return seq, func
+
+
 def prepare_select_or_reject(args, kwargs, modfunc, lookup_attr):
     context = args[0]
     seq = args[1]
index c5c55b7d3e6fcaa6ff38223d701fcae193618e9c..294a9b481ecf55df481b3769b0a97e47dec52a56 100644 (file)
@@ -130,3 +130,32 @@ def test_bool_reject(env_async, items):
         '{{ items()|reject|join("|") }}'
     )
     assert tmpl.render(items=items) == 'None|False|0'
+
+
+def test_simple_select(env_async):
+    tmpl = env_async.from_string('{{ [1, 2, 3, 4, 5]|select("odd")|join("|") }}')
+    assert tmpl.render() == '1|3|5'
+
+
+def test_bool_select(env_async):
+    tmpl = env_async.from_string(
+        '{{ [none, false, 0, 1, 2, 3, 4, 5]|select|join("|") }}'
+    )
+    assert tmpl.render() == '1|2|3|4|5'
+
+
+def test_simple_select_attr(env_async):
+    class User(object):
+        def __init__(self, name, is_active):
+            self.name = name
+            self.is_active = is_active
+    users = [
+        User('john', True),
+        User('jane', True),
+        User('mike', False),
+    ]
+    tmpl = env_async.from_string(
+        '{{ users|selectattr("is_active")|'
+        'map(attribute="name")|join("|") }}'
+    )
+    assert tmpl.render(users=users) == 'john|jane'