1049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project# -*- coding: utf-8 -*-
2049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project"""
3049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    jinja2.filters
4049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ~~~~~~~~~~~~~~
5049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
6049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    Bundled jinja filters.
7a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
8049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    :copyright: (c) 2010 by the Jinja Team.
9049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    :license: BSD, see LICENSE for more details.
10049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project"""
11049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Projectimport re
12049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Projectimport math
13049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
14049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Projectfrom random import choice
15049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Projectfrom operator import itemgetter
16049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Projectfrom itertools import groupby
17049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Projectfrom jinja2.utils import Markup, escape, pformat, urlize, soft_unicode, \
18049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     unicode_urlencode
19049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Projectfrom jinja2.runtime import Undefined
20049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Projectfrom jinja2.exceptions import FilterArgumentError
21049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Projectfrom jinja2._compat import next, imap, string_types, text_type, iteritems
22049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
23049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
24049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project_word_re = re.compile(r'\w+(?u)')
25049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
26049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
27049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Projectdef contextfilter(f):
28049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """Decorator for marking context dependent filters. The current
29049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    :class:`Context` will be passed as first argument.
30049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """
31049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    f.contextfilter = True
32049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return f
33049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
34049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
35049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Projectdef evalcontextfilter(f):
36049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """Decorator for marking eval-context dependent filters.  An eval
37049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    context object is passed as first argument.  For more information
38295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    about the eval context, see :ref:`eval-context`.
39049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
40049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    .. versionadded:: 2.4
41049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """
42049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    f.evalcontextfilter = True
43049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return f
44049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
45049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
46049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Projectdef environmentfilter(f):
47049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """Decorator for marking evironment dependent filters.  The current
48049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    :class:`Environment` is passed to the filter as first argument.
49049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """
50049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    f.environmentfilter = True
51049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return f
52049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
53049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
54049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Projectdef make_attrgetter(environment, attribute):
55049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """Returns a callable that looks up the given attribute from a
56049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    passed object with the rules of the environment.  Dots are allowed
57049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    to access attributes of attributes.  Integer parts in paths are
58049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    looked up as integers.
59049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """
60049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if not isinstance(attribute, string_types) \
61049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project       or ('.' not in attribute and not attribute.isdigit()):
62049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        return lambda x: environment.getitem(x, attribute)
63049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    attribute = attribute.split('.')
64049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    def attrgetter(item):
65049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for part in attribute:
66049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if part.isdigit():
67049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                part = int(part)
68049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            item = environment.getitem(item, part)
69049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        return item
70049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return attrgetter
71049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
72049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
73049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Projectdef do_forceescape(value):
74049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """Enforce HTML escaping.  This will probably double escape variables."""
75049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if hasattr(value, '__html__'):
76049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        value = value.__html__()
77049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return escape(text_type(value))
78049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
79049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
80049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Projectdef do_urlencode(value):
81049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """Escape strings for use in URLs (uses UTF-8 encoding).  It accepts both
82049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    dictionaries and regular strings as well as pairwise iterables.
83049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
84049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    .. versionadded:: 2.7
85049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """
86049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    itemiter = None
87049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if isinstance(value, dict):
88049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        itemiter = iteritems(value)
89049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    elif not isinstance(value, string_types):
90049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        try:
91049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            itemiter = iter(value)
92049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        except TypeError:
93049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            pass
94049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if itemiter is None:
95049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        return unicode_urlencode(value)
96049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return u'&'.join(unicode_urlencode(k) + '=' +
97049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                     unicode_urlencode(v) for k, v in itemiter)
98049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
99049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
100049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project@evalcontextfilter
101049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Projectdef do_replace(eval_ctx, s, old, new, count=None):
102049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """Return a copy of the value with all occurrences of a substring
103049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    replaced with a new one. The first argument is the substring
104049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    that should be replaced, the second is the replacement string.
105049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    If the optional third argument ``count`` is given, only the first
106049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ``count`` occurrences are replaced:
107049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
108049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    .. sourcecode:: jinja
109049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
110049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {{ "Hello World"|replace("Hello", "Goodbye") }}
111049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            -> Goodbye World
112049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
113049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {{ "aaaaargh"|replace("a", "d'oh, ", 2) }}
114049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            -> d'oh, d'oh, aaargh
115049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """
116049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if count is None:
117049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        count = -1
118049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if not eval_ctx.autoescape:
119049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        return text_type(s).replace(text_type(old), text_type(new), count)
120049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if hasattr(old, '__html__') or hasattr(new, '__html__') and \
121049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project       not hasattr(s, '__html__'):
122049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        s = escape(s)
123049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else:
124049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        s = soft_unicode(s)
125049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return s.replace(soft_unicode(old), soft_unicode(new), count)
126049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
127049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
128049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Projectdef do_upper(s):
129049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """Convert a value to uppercase."""
130049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return soft_unicode(s).upper()
131049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
132049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
133049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Projectdef do_lower(s):
134049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """Convert a value to lowercase."""
135049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return soft_unicode(s).lower()
136049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
137049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
138049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project@evalcontextfilter
139049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Projectdef do_xmlattr(_eval_ctx, d, autospace=True):
140049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """Create an SGML/XML attribute string based on the items in a dict.
141049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    All values that are neither `none` nor `undefined` are automatically
142049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    escaped:
143049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
144049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    .. sourcecode:: html+jinja
145049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
146049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        <ul{{ {'class': 'my_list', 'missing': none,
147049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                'id': 'list-%d'|format(variable)}|xmlattr }}>
148049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ...
149049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        </ul>
150049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
151049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    Results in something like this:
152049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
153049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    .. sourcecode:: html
154049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
155049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        <ul class="my_list" id="list-42">
156049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        ...
157049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        </ul>
158049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
159049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    As you can see it automatically prepends a space in front of the item
160049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if the filter returned something unless the second parameter is false.
161049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """
162049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    rv = u' '.join(
163049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        u'%s="%s"' % (escape(key), escape(value))
164049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for key, value in iteritems(d)
165049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if value is not None and not isinstance(value, Undefined)
166049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    )
167049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if autospace and rv:
168049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        rv = u' ' + rv
169049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if _eval_ctx.autoescape:
170049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        rv = Markup(rv)
171049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return rv
172049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
173049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
174049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Projectdef do_capitalize(s):
175049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """Capitalize a value. The first character will be uppercase, all others
176049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    lowercase.
177049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """
178049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return soft_unicode(s).capitalize()
179049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
180049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
181049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Projectdef do_title(s):
182049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """Return a titlecased version of the value. I.e. words will start with
183049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    uppercase letters, all remaining characters are lowercase.
184049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """
185049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    rv = []
186049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for item in re.compile(r'([-\s]+)(?u)').split(s):
187049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if not item:
188049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            continue
189049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        rv.append(item[0].upper() + item[1:].lower())
190049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return ''.join(rv)
191049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
192049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
193049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Projectdef do_dictsort(value, case_sensitive=False, by='key'):
194049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """Sort a dict and yield (key, value) pairs. Because python dicts are
195049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    unsorted you may want to use this function to order them by either
196049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    key or value:
1970a9d06e2b5cf75c3d6ba958026bfdf4745f576d6The Android Open Source Project
198049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    .. sourcecode:: jinja
199049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
200049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {% for item in mydict|dictsort %}
201049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            sort the dict by key, case insensitive
202049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
203049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {% for item in mydict|dictsort(true) %}
204049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            sort the dict by key, case sensitive
205049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
206049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {% for item in mydict|dictsort(false, 'value') %}
207049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            sort the dict by key, case insensitive, sorted
208049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            normally and ordered by value.
209a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    """
210295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    if by == 'key':
211295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        pos = 0
212a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    elif by == 'value':
213a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        pos = 1
214a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    else:
215a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        raise FilterArgumentError('You can only sort by either '
216a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                                  '"key" or "value"')
217a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    def sort_func(item):
218a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        value = item[pos]
219a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        if isinstance(value, string_types) and not case_sensitive:
220a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            value = value.lower()
221a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        return value
222a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
223a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    return sorted(value.items(), key=sort_func)
224a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
225a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
226a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang@environmentfilter
227a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wangdef do_sort(environment, value, reverse=False, case_sensitive=False,
228a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            attribute=None):
229a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    """Sort an iterable.  Per default it sorts ascending, if you pass it
230a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    true as first argument it will reverse the sorting.
231a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
232a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    If the iterable is made of strings the third parameter can be used to
233a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    control the case sensitiveness of the comparison which is disabled by
234a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    default.
235a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
236a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    .. sourcecode:: jinja
237a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
238a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        {% for item in iterable|sort %}
239a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            ...
240295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        {% endfor %}
241a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
242295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    It is also possible to sort by an attribute (for example to sort
243295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    by the date of an object) by specifying the `attribute` parameter:
244a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
245a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    .. sourcecode:: jinja
246a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
247a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        {% for item in iterable|sort(attribute='date') %}
248a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            ...
249a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        {% endfor %}
250a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
251a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    .. versionchanged:: 2.6
252a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang       The `attribute` parameter was added.
253a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    """
254a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    if not case_sensitive:
255a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        def sort_func(item):
256a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            if isinstance(item, string_types):
257a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                item = item.lower()
258a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            return item
259a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    else:
260a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        sort_func = None
261a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    if attribute is not None:
262a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        getter = make_attrgetter(environment, attribute)
263a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        def sort_func(item, processor=sort_func or (lambda x: x)):
264a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            return processor(getter(item))
265a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    return sorted(value, key=sort_func, reverse=reverse)
266a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
267a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
268a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wangdef do_default(value, default_value=u'', boolean=False):
269a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    """If the value is undefined it will return the passed default value,
270a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    otherwise the value of the variable:
271a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
272a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    .. sourcecode:: jinja
273a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
274a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        {{ my_variable|default('my_variable is not defined') }}
275a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
276a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    This will output the value of ``my_variable`` if the variable was
277e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang    defined, otherwise ``'my_variable is not defined'``. If you want
278a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    to use default with variables that evaluate to false you have to
279295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    set the second parameter to `true`:
280049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
281a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    .. sourcecode:: jinja
282049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
283049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {{ ''|default('the string was empty', true) }}
284049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """
285049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if isinstance(value, Undefined) or (boolean and not value):
286049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        return default_value
287049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return value
288049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
289049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
290049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project@evalcontextfilter
291049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Projectdef do_join(eval_ctx, value, d=u'', attribute=None):
292049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """Return a string which is the concatenation of the strings in the
293049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    sequence. The separator between elements is an empty string per
294049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    default, you can define it with the optional parameter:
295049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
296049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    .. sourcecode:: jinja
297049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
298049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {{ [1, 2, 3]|join('|') }}
299049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            -> 1|2|3
300049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
301049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {{ [1, 2, 3]|join }}
302049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            -> 123
303049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
304049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    It is also possible to join certain attributes of an object:
305049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
306a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    .. sourcecode:: jinja
307049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
308049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {{ users|join(', ', attribute='username') }}
309049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
310049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    .. versionadded:: 2.6
311049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project       The `attribute` parameter was added.
312a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    """
313049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if attribute is not None:
314049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        value = imap(make_attrgetter(eval_ctx.environment, attribute), value)
315049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
316049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    # no automatic escaping?  joining is a lot eaiser then
317049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if not eval_ctx.autoescape:
318049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        return text_type(d).join(imap(text_type, value))
319049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
320049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    # if the delimiter doesn't have an html representation we check
321049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    # if any of the items has.  If yes we do a coercion to Markup
322049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if not hasattr(d, '__html__'):
323049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        value = list(value)
324049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        do_escape = False
325049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for idx, item in enumerate(value):
326049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if hasattr(item, '__html__'):
327049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                do_escape = True
328049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            else:
329049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                value[idx] = text_type(item)
330049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if do_escape:
331049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            d = escape(d)
332049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else:
333049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            d = text_type(d)
334049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        return d.join(value)
335049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
336049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    # no html involved, to normal joining
337049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return soft_unicode(d).join(imap(soft_unicode, value))
338049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
339049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
340049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Projectdef do_center(value, width=80):
341049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """Centers the value in a field of a given width."""
342049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return text_type(value).center(width)
343049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
344049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
345049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project@environmentfilter
346049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Projectdef do_first(environment, seq):
347aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich    """Return the first item of a sequence."""
348aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich    try:
349aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich        return next(iter(seq))
350aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich    except StopIteration:
351aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich        return environment.undefined('No first item, sequence was empty.')
352aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich
353049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
354049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project@environmentfilter
355049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Projectdef do_last(environment, seq):
356049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """Return the last item of a sequence."""
357049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    try:
358049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        return next(iter(reversed(seq)))
359049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    except StopIteration:
360049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        return environment.undefined('No last item, sequence was empty.')
361049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
362049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
363049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project@environmentfilter
364049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Projectdef do_random(environment, seq):
365049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """Return a random item from the sequence."""
366aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich    try:
367049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        return choice(seq)
368049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    except IndexError:
369049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        return environment.undefined('No random item, sequence was empty.')
370049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
371049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
372049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Projectdef do_filesizeformat(value, binary=False):
373049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """Format the value like a 'human-readable' file size (i.e. 13 kB,
374049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    4.1 MB, 102 Bytes, etc).  Per default decimal prefixes are used (Mega,
375049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    Giga, etc.), if the second parameter is set to `True` the binary
376049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    prefixes are used (Mebi, Gibi).
377049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """
378049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    bytes = float(value)
379049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    base = binary and 1024 or 1000
380049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    prefixes = [
381049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        (binary and 'KiB' or 'kB'),
382049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        (binary and 'MiB' or 'MB'),
383049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        (binary and 'GiB' or 'GB'),
384049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        (binary and 'TiB' or 'TB'),
385049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        (binary and 'PiB' or 'PB'),
386049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        (binary and 'EiB' or 'EB'),
387049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        (binary and 'ZiB' or 'ZB'),
388049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        (binary and 'YiB' or 'YB')
389049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ]
390049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if bytes == 1:
391049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        return '1 Byte'
392049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    elif bytes < base:
393049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        return '%d Bytes' % bytes
394049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else:
395049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for i, prefix in enumerate(prefixes):
396049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            unit = base ** (i + 2)
397049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if bytes < unit:
398049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                return '%.1f %s' % ((base * bytes / unit), prefix)
399049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        return '%.1f %s' % ((base * bytes / unit), prefix)
400049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
401049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
402049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Projectdef do_pprint(value, verbose=False):
403049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """Pretty print a variable. Useful for debugging.
404049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
405049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    With Jinja 1.2 onwards you can pass it a parameter.  If this parameter
406049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    is truthy the output will be more verbose (this requires `pretty`)
407049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """
408049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return pformat(value, verbose=verbose)
409049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
410049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
411049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project@evalcontextfilter
412049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Projectdef do_urlize(eval_ctx, value, trim_url_limit=None, nofollow=False):
413049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """Converts URLs in plain text into clickable links.
414049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
415049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    If you pass the filter an additional integer it will shorten the urls
416049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    to that number. Also a third argument exists that makes the urls
417049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    "nofollow":
418049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
419049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    .. sourcecode:: jinja
420049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
421049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {{ mytext|urlize(40, true) }}
422049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            links are shortened to 40 chars and defined with rel="nofollow"
423049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """
424049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    rv = urlize(value, trim_url_limit, nofollow)
425049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if eval_ctx.autoescape:
426049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        rv = Markup(rv)
427049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return rv
428049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
429049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
430049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Projectdef do_indent(s, width=4, indentfirst=False):
431049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """Return a copy of the passed string, each line indented by
432049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    4 spaces. The first line is not indented. If you want to
433049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    change the number of spaces or indent the first line too
434049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    you can pass additional parameters to the filter:
435049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
436049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    .. sourcecode:: jinja
437049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
438049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {{ mytext|indent(2, true) }}
439049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            indent by two spaces and indent the first line too.
440049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """
441049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    indention = u' ' * width
442049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    rv = (u'\n' + indention).join(s.splitlines())
443a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    if indentfirst:
444049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        rv = indention + rv
445049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return rv
446049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
447049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
448049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Projectdef do_truncate(s, length=255, killwords=False, end='...'):
449049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """Return a truncated copy of the string. The length is specified
450049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    with the first parameter which defaults to ``255``. If the second
451049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    parameter is ``true`` the filter will cut the text at length. Otherwise
452049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    it will discard the last word. If the text was in fact
453049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    truncated it will append an ellipsis sign (``"..."``). If you want a
454049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    different ellipsis sign than ``"..."`` you can specify it using the
455049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    third parameter.
456049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
457049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    .. sourcecode:: jinja
458049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
459049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {{ "foo bar"|truncate(5) }}
460049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            -> "foo ..."
461049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {{ "foo bar"|truncate(5, True) }}
462049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            -> "foo b..."
463049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """
464049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if len(s) <= length:
465049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        return s
466049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    elif killwords:
467049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        return s[:length] + end
468049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    words = s.split(' ')
469049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    result = []
470049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    m = 0
471049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for word in words:
472049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        m += len(word) + 1
473049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if m > length:
474049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            break
475049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        result.append(word)
476049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    result.append(end)
477049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return u' '.join(result)
478e3b631da8034f7c6ecc6d809cd9e46d306215c32Xianzhu Wang
479049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project@environmentfilter
480049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Projectdef do_wordwrap(environment, s, width=79, break_long_words=True,
481049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                wrapstring=None):
482049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """
483049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    Return a copy of the string passed to the filter wrapped after
484049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ``79`` characters.  You can override this default using the first
485049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    parameter.  If you set the second parameter to `false` Jinja will not
486049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    split words apart if they are longer than `width`. By default, the newlines
487049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    will be the default newlines for the environment, but this can be changed
488049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    using the wrapstring keyword argument.
489049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
490049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    .. versionadded:: 2.7
491049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project       Added support for the `wrapstring` parameter.
492049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """
493049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if not wrapstring:
494049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        wrapstring = environment.newline_sequence
495049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    import textwrap
496049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return wrapstring.join(textwrap.wrap(s, width=width, expand_tabs=False,
497049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                   replace_whitespace=False,
498049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                   break_long_words=break_long_words))
499049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
500049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
501049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Projectdef do_wordcount(s):
502049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """Count the words in that string."""
503049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return len(_word_re.findall(s))
504049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
505049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
506049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Projectdef do_int(value, default=0):
507049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """Convert the value into an integer. If the
508049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    conversion doesn't work it will return ``0``. You can
509049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    override this default using the first parameter.
510049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """
511049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    try:
512049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        return int(value)
513049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    except (TypeError, ValueError):
514049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        # this quirk is necessary so that "42.23"|int gives 42.
515049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        try:
516049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            return int(float(value))
517049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        except (TypeError, ValueError):
518049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            return default
519049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
520049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
521049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Projectdef do_float(value, default=0.0):
522049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """Convert the value into a floating point number. If the
523049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    conversion doesn't work it will return ``0.0``. You can
524049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    override this default using the first parameter.
525049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """
526049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    try:
527049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        return float(value)
528049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    except (TypeError, ValueError):
529049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        return default
530049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
531049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
532049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Projectdef do_format(value, *args, **kwargs):
533049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """
534049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    Apply python string formatting on an object:
535049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
536a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    .. sourcecode:: jinja
537049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
538049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {{ "%s - %s"|format("Hello?", "Foo!") }}
539049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            -> Hello? - Foo!
540049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """
541049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if args and kwargs:
542049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        raise FilterArgumentError('can\'t handle positional and keyword '
543049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                                  'arguments at the same time')
544a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    return soft_unicode(value) % (kwargs or args)
545049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
546049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
547049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Projectdef do_trim(value):
548049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """Strip leading and trailing whitespace."""
549049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return soft_unicode(value).strip()
550049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
551049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
552049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Projectdef do_striptags(value):
553049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """Strip SGML/XML tags and replace adjacent whitespace by one space.
554049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """
555049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if hasattr(value, '__html__'):
556049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        value = value.__html__()
557049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return Markup(text_type(value)).striptags()
558049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
559049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
560049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Projectdef do_slice(value, slices, fill_with=None):
561049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """Slice an iterator and return a list of lists containing
562049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    those items. Useful if you want to create a div containing
563049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    three ul tags that represent columns:
564049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
565049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    .. sourcecode:: html+jinja
566049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
567049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        <div class="columwrapper">
568049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {%- for column in items|slice(3) %}
569049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            <ul class="column-{{ loop.index }}">
570049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {%- for item in column %}
571049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project              <li>{{ item }}</li>
572049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {%- endfor %}
573049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            </ul>
574049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {%- endfor %}
575049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        </div>
576049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
577049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    If you pass it a second argument it's used to fill missing
578049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    values on the last iteration.
579049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """
580049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    seq = list(value)
581049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    length = len(seq)
582049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    items_per_slice = length // slices
583049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    slices_with_extra = length % slices
584049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    offset = 0
585049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for slice_number in range(slices):
586049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        start = offset + slice_number * items_per_slice
587049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if slice_number < slices_with_extra:
588049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            offset += 1
589049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        end = offset + (slice_number + 1) * items_per_slice
590049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        tmp = seq[start:end]
591049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if fill_with is not None and slice_number >= slices_with_extra:
592049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            tmp.append(fill_with)
593049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        yield tmp
594049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
595049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
596049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Projectdef do_batch(value, linecount, fill_with=None):
597049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """
598049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    A filter that batches items. It works pretty much like `slice`
599049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    just the other way round. It returns a list of lists with the
600049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    given number of items. If you provide a second parameter this
601049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    is used to fill up missing items. See this example:
602049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
603049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    .. sourcecode:: html+jinja
604049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
605049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        <table>
606049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {%- for row in items|batch(3, '&nbsp;') %}
607049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          <tr>
608049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {%- for column in row %}
609049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            <td>{{ column }}</td>
610049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          {%- endfor %}
611049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project          </tr>
612049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {%- endfor %}
613049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        </table>
614049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """
615049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    result = []
616049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    tmp = []
617049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    for item in value:
618049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if len(tmp) == linecount:
619049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            yield tmp
620049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            tmp = []
621049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        tmp.append(item)
622049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if tmp:
623049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if fill_with is not None and len(tmp) < linecount:
624049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            tmp += [fill_with] * (linecount - len(tmp))
625049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        yield tmp
626049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
627049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
628049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Projectdef do_round(value, precision=0, method='common'):
629049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """Round the number to a given precision. The first
630049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    parameter specifies the precision (default is ``0``), the
631049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    second the rounding method:
632049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
633049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    - ``'common'`` rounds either up or down
634049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    - ``'ceil'`` always rounds up
635049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    - ``'floor'`` always rounds down
636049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
637049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    If you don't specify a method ``'common'`` is used.
638049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
639049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    .. sourcecode:: jinja
640049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
641049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {{ 42.55|round }}
642049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            -> 43.0
643049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {{ 42.55|round(1, 'floor') }}
644049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            -> 42.5
645049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
646049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    Note that even if rounded to 0 precision, a float is returned.  If
647049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    you need a real integer, pipe it through `int`:
648049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
649049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    .. sourcecode:: jinja
650049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
651049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {{ 42.55|round|int }}
652049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            -> 43
653049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """
654049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if not method in ('common', 'ceil', 'floor'):
655049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        raise FilterArgumentError('method must be common, ceil or floor')
656049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if method == 'common':
657049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        return round(value, precision)
658049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    func = getattr(math, method)
659049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return func(value * (10 ** precision)) / (10 ** precision)
660049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
661049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
662049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project@environmentfilter
663049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Projectdef do_groupby(environment, value, attribute):
664049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """Group a sequence of objects by a common attribute.
665049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
666049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    If you for example have a list of dicts or objects that represent persons
667049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    with `gender`, `first_name` and `last_name` attributes and you want to
668049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    group all users by genders you can do something like the following
669049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    snippet:
670049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
671049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    .. sourcecode:: html+jinja
672049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
673049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        <ul>
674049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {% for group in persons|groupby('gender') %}
675049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            <li>{{ group.grouper }}<ul>
676049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {% for person in group.list %}
677049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                <li>{{ person.first_name }} {{ person.last_name }}</li>
678049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            {% endfor %}</ul></li>
679049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {% endfor %}
680049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        </ul>
681049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
682049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    Additionally it's possible to use tuple unpacking for the grouper and
683049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    list:
684049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
685049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    .. sourcecode:: html+jinja
686049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
687049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        <ul>
688049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {% for grouper, list in persons|groupby('gender') %}
689049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            ...
690049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {% endfor %}
691049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        </ul>
692049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
693049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    As you can see the item we're grouping by is stored in the `grouper`
694049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    attribute and the `list` contains all the objects that have this grouper
695049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    in common.
696049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
697049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    .. versionchanged:: 2.6
698049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project       It's now possible to use dotted notation to group by the child
699049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project       attribute of another attribute.
700049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """
701049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    expr = make_attrgetter(environment, attribute)
702049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return sorted(map(_GroupTuple, groupby(sorted(value, key=expr), expr)))
703049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
704049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
705049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Projectclass _GroupTuple(tuple):
706049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    __slots__ = ()
707049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    grouper = property(itemgetter(0))
708049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    list = property(itemgetter(1))
709049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
710049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    def __new__(cls, xxx_todo_changeme):
711049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        (key, value) = xxx_todo_changeme
712049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        return tuple.__new__(cls, (key, list(value)))
713049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
714049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
715049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project@environmentfilter
716049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Projectdef do_sum(environment, iterable, attribute=None, start=0):
717049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """Returns the sum of a sequence of numbers plus the value of parameter
718049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    'start' (which defaults to 0).  When the sequence is empty it returns
719049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    start.
720049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
721049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    It is also possible to sum up only certain attributes:
722049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
723049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    .. sourcecode:: jinja
724049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
725049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        Total: {{ items|sum(attribute='price') }}
726049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
727049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    .. versionchanged:: 2.6
728049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project       The `attribute` parameter was added to allow suming up over
729049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project       attributes.  Also the `start` parameter was moved on to the right.
730049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """
731049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if attribute is not None:
732049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        iterable = imap(make_attrgetter(environment, attribute), iterable)
733049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return sum(iterable, start)
734049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
735049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
736049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Projectdef do_list(value):
737049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """Convert the value into a list.  If it was a string the returned list
738049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    will be a list of characters.
739049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """
740049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return list(value)
741049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
742049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
743049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Projectdef do_mark_safe(value):
744049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """Mark the value as safe which means that in an environment with automatic
745049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    escaping enabled this variable will not be escaped.
746049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """
747049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return Markup(value)
748049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
749049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
750049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Projectdef do_mark_unsafe(value):
751049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """Mark a value as unsafe.  This is the reverse operation for :func:`safe`."""
752049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return text_type(value)
753049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
754049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
755049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Projectdef do_reverse(value):
756049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """Reverse the object or return an iterator the iterates over it the other
757049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    way round.
758049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """
759049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if isinstance(value, string_types):
760049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        return value[::-1]
761049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    try:
762049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        return reversed(value)
763049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    except TypeError:
764049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        try:
765049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            rv = list(value)
766049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            rv.reverse()
767049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            return rv
768049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        except TypeError:
769049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            raise FilterArgumentError('argument must be iterable')
770049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
771049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
772049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project@environmentfilter
773049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Projectdef do_attr(environment, obj, name):
774049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """Get an attribute of an object.  ``foo|attr("bar")`` works like
775049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ``foo["bar"]`` just that always an attribute is returned and items are not
776049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    looked up.
777049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
778049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    See :ref:`Notes on subscriptions <notes-on-subscriptions>` for more details.
779049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """
780049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    try:
781049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        name = str(name)
782049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    except UnicodeError:
783049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        pass
784049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else:
785049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        try:
786049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            value = getattr(obj, name)
787049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        except AttributeError:
788049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            pass
789049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        else:
790049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if environment.sandboxed and not \
791049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project               environment.is_safe_attribute(obj, name, value):
792049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                return environment.unsafe_undefined(obj, name)
793049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            return value
794049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return environment.undefined(obj=obj, name=name)
795049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
796049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
797049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project@contextfilter
798049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Projectdef do_map(*args, **kwargs):
799049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """Applies a filter on a sequence of objects or looks up an attribute.
800049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    This is useful when dealing with lists of objects but you are really
801049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    only interested in a certain value of it.
802049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
803049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    The basic usage is mapping on an attribute.  Imagine you have a list
804049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    of users but you are only interested in a list of usernames:
805049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
806049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    .. sourcecode:: jinja
807049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
808049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        Users on this page: {{ users|map(attribute='username')|join(', ') }}
809049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
810049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    Alternatively you can let it invoke a filter by passing the name of the
811049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    filter and the arguments afterwards.  A good example would be applying a
812049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    text conversion filter on a sequence:
813049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
814049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    .. sourcecode:: jinja
815049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
816049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        Users on this page: {{ titles|map('lower')|join(', ') }}
817049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
818049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    .. versionadded:: 2.7
819049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """
820049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    context = args[0]
821049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    seq = args[1]
822049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
823049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if len(args) == 2 and 'attribute' in kwargs:
824049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        attribute = kwargs.pop('attribute')
825049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        if kwargs:
826049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            raise FilterArgumentError('Unexpected keyword argument %r' %
827049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                next(iter(kwargs)))
828049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        func = make_attrgetter(context.environment, attribute)
829049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else:
830049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        try:
831049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            name = args[2]
832aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich            args = args[3:]
833aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich        except LookupError:
834aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich            raise FilterArgumentError('map requires a filter argument')
835aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich        func = lambda item: context.environment.call_filter(
836aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich            name, item, args, kwargs, context=context)
837aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich
838aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich    if seq:
839aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich        for item in seq:
840aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich            yield func(item)
841aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich
842aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich
843aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich@contextfilter
844295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turnerdef do_select(*args, **kwargs):
845295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    """Filters a sequence of objects by appying a test to either the object
846295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    or the attribute and only selecting the ones with the test succeeding.
847aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich
848aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich    Example usage:
849aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich
850aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich    .. sourcecode:: jinja
851aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich
852aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich        {{ numbers|select("odd") }}
853aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich
854049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    .. versionadded:: 2.7
855049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """
856049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return _select_or_reject(args, kwargs, lambda x: x, False)
857049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
858049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
859049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project@contextfilter
860049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Projectdef do_reject(*args, **kwargs):
861049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """Filters a sequence of objects by appying a test to either the object
862049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    or the attribute and rejecting the ones with the test succeeding.
863049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
864049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    Example usage:
865049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
866049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    .. sourcecode:: jinja
867049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
868049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {{ numbers|reject("odd") }}
869049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
870049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    .. versionadded:: 2.7
871049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """
872049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return _select_or_reject(args, kwargs, lambda x: not x, False)
873049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
874049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
875049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project@contextfilter
876049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Projectdef do_selectattr(*args, **kwargs):
877049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """Filters a sequence of objects by appying a test to either the object
878049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    or the attribute and only selecting the ones with the test succeeding.
879049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
880049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    Example usage:
881049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
882295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    .. sourcecode:: jinja
883295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner
884295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        {{ users|selectattr("is_active") }}
885295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner        {{ users|selectattr("email", "none") }}
886aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich
887aacb8e1368a883fcbc9fe64fd0e460cef9c9b20cNick Kralevich    .. versionadded:: 2.7
888049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """
889049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return _select_or_reject(args, kwargs, lambda x: x, True)
890049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
891049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
892049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project@contextfilter
893049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Projectdef do_rejectattr(*args, **kwargs):
894049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """Filters a sequence of objects by appying a test to either the object
895049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    or the attribute and rejecting the ones with the test succeeding.
896049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
897049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    .. sourcecode:: jinja
898049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
899049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {{ users|rejectattr("is_active") }}
900049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        {{ users|rejectattr("email", "none") }}
901049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
902049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    .. versionadded:: 2.7
903049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    """
904049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return _select_or_reject(args, kwargs, lambda x: not x, True)
905049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
906049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
907049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Projectdef _select_or_reject(args, kwargs, modfunc, lookup_attr):
908049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    context = args[0]
909049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    seq = args[1]
910049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if lookup_attr:
911049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        try:
912049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            attr = args[2]
913049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        except LookupError:
914049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            raise FilterArgumentError('Missing parameter for attribute name')
915049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        transfunc = make_attrgetter(context.environment, attr)
916049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        off = 1
917049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else:
918049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        off = 0
919049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        transfunc = lambda x: x
920049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
921049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    try:
922049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        name = args[2 + off]
923049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        args = args[3 + off:]
924049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        func = lambda item: context.environment.call_test(
925049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            name, item, args, kwargs)
926049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    except LookupError:
927049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        func = bool
928049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
929049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if seq:
930049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        for item in seq:
931049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            if modfunc(func(transfunc(item))):
932049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                yield item
933049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
934049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
935049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source ProjectFILTERS = {
936049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    'attr':                 do_attr,
937049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    'replace':              do_replace,
938049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    'upper':                do_upper,
939049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    'lower':                do_lower,
940049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    'escape':               escape,
941049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    'e':                    escape,
942049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    'forceescape':          do_forceescape,
943049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    'capitalize':           do_capitalize,
944049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    'title':                do_title,
945049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    'default':              do_default,
946049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    'd':                    do_default,
947049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    'join':                 do_join,
948049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    'count':                len,
949049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    'dictsort':             do_dictsort,
950049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    'sort':                 do_sort,
951049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    'length':               len,
952049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    'reverse':              do_reverse,
953049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    'center':               do_center,
954049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    'indent':               do_indent,
955049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    'title':                do_title,
956049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    'capitalize':           do_capitalize,
957049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    'first':                do_first,
958049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    'last':                 do_last,
959a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    'map':                  do_map,
960295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    'random':               do_random,
961295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    'reject':               do_reject,
962295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    'rejectattr':           do_rejectattr,
963295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    'filesizeformat':       do_filesizeformat,
964295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    'pprint':               do_pprint,
965a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    'truncate':             do_truncate,
966295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    'wordwrap':             do_wordwrap,
967295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    'wordcount':            do_wordcount,
968295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    'int':                  do_int,
969295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    'float':                do_float,
970295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    'string':               soft_unicode,
971295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    'list':                 do_list,
972295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    'urlize':               do_urlize,
973a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    'format':               do_format,
974a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    'trim':                 do_trim,
975a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    'striptags':            do_striptags,
976295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    'select':               do_select,
977295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    'selectattr':           do_selectattr,
978295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    'slice':                do_slice,
979295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    'batch':                do_batch,
980295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    'sum':                  do_sum,
981295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    'abs':                  abs,
982295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    'round':                do_round,
983295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    'groupby':              do_groupby,
984a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    'safe':                 do_mark_safe,
985295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    'xmlattr':              do_xmlattr,
986295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner    'urlencode':            do_urlencode
987295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner}
988295ffce55e0198e7a9f7d46b33f5c2b4147bf821David 'Digit' Turner