]> git.ipfire.org Git - thirdparty/jinja.git/commitdiff
Made groupby work with async
authorArmin Ronacher <armin.ronacher@active-4.com>
Wed, 28 Dec 2016 22:39:03 +0000 (23:39 +0100)
committerArmin Ronacher <armin.ronacher@active-4.com>
Wed, 28 Dec 2016 22:39:03 +0000 (23:39 +0100)
jinja2/asyncfilters.py
tests/test_asyncfilters.py

index 31222d0dc7fc6e78eea72cb293ad498fd68cb64a..e879893c854334b2f002fbfc924858eeace4e4fe 100644 (file)
@@ -1,4 +1,5 @@
 from functools import wraps
+
 from jinja2.asyncsupport import auto_aiter
 from jinja2 import filters
 
@@ -53,6 +54,15 @@ async def do_first(environment, seq):
         return environment.undefined('No first item, sequence was empty.')
 
 
+@asyncfiltervariant(filters.do_groupby)
+async def do_groupby(environment, value, attribute):
+    expr = filters.make_attrgetter(environment, attribute)
+    return [filters._GroupTuple(key, await auto_to_seq(values))
+            for key, values in filters.groupby(sorted(
+                await auto_to_seq(value), key=expr), expr)]
+
+
 ASYNC_FILTERS = {
     'first':        do_first,
+    'groupby':      do_groupby,
 }
index 75ee4a3bf1dfa01d67d6b15e4f0f54eed97a3945..5133f9cba5ef82eb91bca202c8c01be3d8d5155e 100644 (file)
@@ -2,21 +2,81 @@ import pytest
 from jinja2 import Environment
 
 
+async def make_aiter(iter):
+    for item in iter:
+        yield item
+
+
 @pytest.fixture
 def env_async():
     return Environment(enable_async=True)
 
 
-def test_first(env_async):
-    tmpl = env_async.from_string('{{ foo|first }}')
-    out = tmpl.render(foo=list(range(10)))
-    assert out == '0'
-
-
-def test_first_aiter(env_async):
-    async def foo():
-        for x in range(10):
-            yield x
+@pytest.mark.parametrize('foo', [
+    lambda: range(10),
+    lambda: make_aiter(range(10)),
+])
+def test_first(env_async, foo):
     tmpl = env_async.from_string('{{ foo()|first }}')
     out = tmpl.render(foo=foo)
     assert out == '0'
+
+
+def test_groupby(env_async):
+    tmpl = env_async.from_string('''
+    {%- for grouper, list in [{'foo': 1, 'bar': 2},
+                              {'foo': 2, 'bar': 3},
+                              {'foo': 1, 'bar': 1},
+                              {'foo': 3, 'bar': 4}]|groupby('foo') -%}
+        {{ grouper }}{% for x in list %}: {{ x.foo }}, {{ x.bar }}{% endfor %}|
+    {%- endfor %}''')
+    assert tmpl.render().split('|') == [
+        "1: 1, 2: 1, 1",
+        "2: 2, 3",
+        "3: 3, 4",
+        ""
+    ]
+
+
+def test_groupby_tuple_index(env_async):
+    tmpl = env_async.from_string('''
+    {%- for grouper, list in [('a', 1), ('a', 2), ('b', 1)]|groupby(0) -%}
+        {{ grouper }}{% for x in list %}:{{ x.1 }}{% endfor %}|
+    {%- endfor %}''')
+    assert tmpl.render() == 'a:1:2|b:1|'
+
+
+def make_articles():
+    class Date(object):
+        def __init__(self, day, month, year):
+            self.day = day
+            self.month = month
+            self.year = year
+
+    class Article(object):
+        def __init__(self, title, *date):
+            self.date = Date(*date)
+            self.title = title
+
+    return [
+        Article('aha', 1, 1, 1970),
+        Article('interesting', 2, 1, 1970),
+        Article('really?', 3, 1, 1970),
+        Article('totally not', 1, 1, 1971)
+    ]
+
+
+@pytest.mark.parametrize('articles', [
+    make_articles,
+    lambda: make_aiter(make_articles()),
+])
+def test_groupby_multidot(env_async, articles):
+    tmpl = env_async.from_string('''
+    {%- for year, list in articles()|groupby('date.year') -%}
+        {{ year }}{% for x in list %}[{{ x.title }}]{% endfor %}|
+    {%- endfor %}''')
+    assert tmpl.render(articles=articles).split('|') == [
+        '1970[aha][interesting][really?]',
+        '1971[totally not]',
+        ''
+    ]