Implemented a sort filter that sorts arbitrary sequences.
authorArmin Ronacher <armin.ronacher@active-4.com>
Wed, 17 Sep 2008 11:57:45 +0000 (13:57 +0200)
committerArmin Ronacher <armin.ronacher@active-4.com>
Wed, 17 Sep 2008 11:57:45 +0000 (13:57 +0200)
--HG--
branch : trunk

CHANGES
jinja2/filters.py
tests/test_filters.py

diff --git a/CHANGES b/CHANGES
index 14ee198e869164d81e581e2c075ed84719bb8b6b..079d2fc668659960481048ebfb2da57bdb2aded8 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -26,6 +26,8 @@ Version 2.1
   executed under some conditions even though they were not part of a visible
   area.
 
+- added `sort` filter that works like `dictsort` but for arbitrary sequences.
+
 Version 2.0
 -----------
 (codename jinjavitus, released on July 17th 2008)
index da5f99d7a22dea4117109c86af1c0589ea638263..78d4cb6899769f53ab499272afa59e1b302cf9e9 100644 (file)
@@ -137,7 +137,7 @@ def do_title(s):
 
 
 def do_dictsort(value, case_sensitive=False, by='key'):
-    """ Sort a dict and yield (key, value) pairs. Because python dicts are
+    """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:
 
@@ -162,15 +162,34 @@ def do_dictsort(value, case_sensitive=False, by='key'):
                                   '"key" or "value"')
     def sort_func(item):
         value = item[pos]
-        if isinstance(value, basestring):
-            value = unicode(value)
-            if not case_sensitive:
-                value = value.lower()
+        if isinstance(value, basestring) and not case_sensitive:
+            value = value.lower()
         return value
 
     return sorted(value.items(), key=sort_func)
 
 
+def do_sort(value, case_sensitive=False):
+    """Sort an iterable.  If the iterable is made of strings the second
+    parameter can be used to control the case sensitiveness of the
+    comparison which is disabled by default.
+
+    .. sourcecode:: jinja
+
+        {% for item in iterable|sort %}
+            ...
+        {% endfor %}
+    """
+    if not case_sensitive:
+        def sort_func(item):
+            if isinstance(item, basestring):
+                item = item.lower()
+            return item
+    else:
+        sort_func = None
+    return sorted(seq, key=sort_func)
+
+
 def do_default(value, default_value=u'', boolean=False):
     """If the value is undefined it will return the passed default value,
     otherwise the value of the variable:
@@ -653,6 +672,7 @@ FILTERS = {
     'join':                 do_join,
     'count':                len,
     'dictsort':             do_dictsort,
+    'sort':                 do_sort,
     'length':               len,
     'reverse':              do_reverse,
     'center':               do_center,
index b2d4340abdb2f8574589b3ce07632671e220cd6e..f70bb4c7be19d5dda9b931b58ff8fc892af11325 100644 (file)
@@ -67,6 +67,7 @@ GROUPBY = '''{% for grouper, list in [{'foo': 1, 'bar': 2},
 {{ grouper }}: {{ list|join(', ') }}
 {% endfor %}'''
 FILTERTAG = '''{% filter upper|replace('FOO', 'foo') %}foobar{% endfilter %}'''
+SORT = '''{{ ['foo', 'Bar', 'blah']|sort }}'''
 
 
 def test_capitalize(env):
@@ -324,3 +325,7 @@ def test_safe():
     assert tmpl.render() == '<div>foo</div>'
     tmpl = env.from_string('{{ "<div>foo</div>" }}')
     assert tmpl.render() == '&lt;div&gt;foo&lt;/div&gt;'
+
+
+def test_sort(env):
+    assert env.from_string(SORT).render() == "['Bar', 'blah', 'foo']"