Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dictsort reverse #692

Merged
merged 2 commits into from Jul 8, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGES
Expand Up @@ -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
Expand All @@ -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
-------------
Expand Down
19 changes: 13 additions & 6 deletions jinja2/filters.py
Expand Up @@ -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:
Expand All @@ -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

Expand All @@ -224,15 +227,19 @@ def do_dictsort(value, case_sensitive=False, by='key'):
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)
return sorted(value.items(), key=sort_func, reverse=reverse)


@environmentfilter
Expand Down
20 changes: 10 additions & 10 deletions tests/test_filters.py
Expand Up @@ -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 }}|"
Expand Down