From 10fc8afc15b973ed3e547508e2bc160c3fbf8966 Mon Sep 17 00:00:00 2001 From: Dick Visser Date: Thu, 9 Mar 2017 21:37:42 +0100 Subject: [PATCH 1/2] 'reverse' option for dictsort --- jinja2/filters.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/jinja2/filters.py b/jinja2/filters.py index da15a1a75..2496d3aad 100644 --- a/jinja2/filters.py +++ b/jinja2/filters.py @@ -203,7 +203,7 @@ def do_title(s): if item]) -def do_dictsort(value, case_sensitive=False, by='key'): +def do_dictsort(value, case_sensitive=False, by='key', reverse=False): """Sort a dict and yield (key, value) pairs. Because python dicts are unsorted you may want to use this function to order them by either key or value: @@ -213,6 +213,9 @@ def do_dictsort(value, case_sensitive=False, by='key'): {% for item in mydict|dictsort %} sort the dict by key, case insensitive + {% for item in mydict|dictsort(reverse=true) %} + sort the dict by key, case insensitive, reverse order + {% for item in mydict|dictsort(true) %} sort the dict by key, case sensitive @@ -232,7 +235,7 @@ def sort_func(item): value = value.lower() return value - return sorted(value.items(), key=sort_func) + return sorted(value.items(), key=sort_func, reverse=reverse) @environmentfilter From 34ca7f17c26ddb1bbdf7b59384fb5e96e66070e7 Mon Sep 17 00:00:00 2001 From: David Lord Date: Sat, 8 Jul 2017 09:04:29 -0700 Subject: [PATCH 2/2] add test and changelog use ignore_case function --- CHANGES | 2 ++ jinja2/filters.py | 12 ++++++++---- tests/test_filters.py | 20 ++++++++++---------- 3 files changed, 20 insertions(+), 14 deletions(-) diff --git a/CHANGES b/CHANGES index 4240a63dc..c7d78b917 100644 --- a/CHANGES +++ b/CHANGES @@ -30,6 +30,7 @@ Version 2.10 ``gt``, ``ge``. (`#665`_) - ``import`` statement cannot end with a trailing comma. (`#617`_, `#618`_) - ``indent`` filter will not indent blank lines by default. (`#685`_) +- Add ``reverse`` argument for ``dictsort`` filter. (`#692`_) .. _#469: https://github.com/pallets/jinja/pull/469 .. _#475: https://github.com/pallets/jinja/pull/475 @@ -38,6 +39,7 @@ Version 2.10 .. _#618: https://github.com/pallets/jinja/pull/618 .. _#665: https://github.com/pallets/jinja/pull/665 .. _#685: https://github.com/pallets/jinja/pull/685 +.. _#692: https://github.com/pallets/jinja/pull/692 Version 2.9.6 ------------- diff --git a/jinja2/filters.py b/jinja2/filters.py index 2496d3aad..07e8ccae8 100644 --- a/jinja2/filters.py +++ b/jinja2/filters.py @@ -227,12 +227,16 @@ def do_dictsort(value, case_sensitive=False, by='key', reverse=False): elif by == 'value': pos = 1 else: - raise FilterArgumentError('You can only sort by either ' - '"key" or "value"') + raise FilterArgumentError( + 'You can only sort by either "key" or "value"' + ) + def sort_func(item): value = item[pos] - if isinstance(value, string_types) and not case_sensitive: - value = value.lower() + + if not case_sensitive: + value = ignore_case(value) + return value return sorted(value.items(), key=sort_func, reverse=reverse) diff --git a/tests/test_filters.py b/tests/test_filters.py index 2ef3249ea..f323f761f 100644 --- a/tests/test_filters.py +++ b/tests/test_filters.py @@ -45,16 +45,16 @@ def test_default(self, env): ) assert tmpl.render(given='yes') == 'no|False|no|yes' - def test_dictsort(self, env): - tmpl = env.from_string( - '{{ foo|dictsort }}|' - '{{ foo|dictsort(true) }}|' - '{{ foo|dictsort(false, "value") }}' - ) - out = tmpl.render(foo={"aa": 0, "b": 1, "c": 2, "AB": 3}) - assert out == ("[('aa', 0), ('AB', 3), ('b', 1), ('c', 2)]|" - "[('AB', 3), ('aa', 0), ('b', 1), ('c', 2)]|" - "[('aa', 0), ('b', 1), ('c', 2), ('AB', 3)]") + @pytest.mark.parametrize('args,expect', ( + ('', "[('aa', 0), ('AB', 3), ('b', 1), ('c', 2)]"), + ('true', "[('AB', 3), ('aa', 0), ('b', 1), ('c', 2)]"), + ('by="value"', "[('aa', 0), ('b', 1), ('c', 2), ('AB', 3)]"), + ('reverse=true', "[('c', 2), ('b', 1), ('AB', 3), ('aa', 0)]") + )) + def test_dictsort(self, env, args, expect): + t = env.from_string('{{{{ foo|dictsort({args}) }}}}'.format(args=args)) + out = t.render(foo={"aa": 0, "b": 1, "c": 2, "AB": 3}) + assert out == expect def test_batch(self, env): tmpl = env.from_string("{{ foo|batch(3)|list }}|"