1645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez# -*- coding: utf-8 -*-
2645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez"""
3645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    jinja2.filters
4645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    ~~~~~~~~~~~~~~
5645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
6645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    Bundled jinja filters.
7645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
8645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    :copyright: (c) 2010 by the Jinja Team.
9645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    :license: BSD, see LICENSE for more details.
10645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez"""
11645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezimport re
12645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezimport math
13645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
14645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezfrom random import choice
15645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezfrom operator import itemgetter
16645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezfrom itertools import groupby
17645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezfrom jinja2.utils import Markup, escape, pformat, urlize, soft_unicode, \
18645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez     unicode_urlencode
19645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezfrom jinja2.runtime import Undefined
20645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezfrom jinja2.exceptions import FilterArgumentError
21645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezfrom jinja2._compat import next, imap, string_types, text_type, iteritems
22645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
23645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
24645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez_word_re = re.compile(r'\w+(?u)')
25645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
26645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
27645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezdef contextfilter(f):
28645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """Decorator for marking context dependent filters. The current
29645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    :class:`Context` will be passed as first argument.
30645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """
31645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    f.contextfilter = True
32645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    return f
33645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
34645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
35645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezdef evalcontextfilter(f):
36645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """Decorator for marking eval-context dependent filters.  An eval
37645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    context object is passed as first argument.  For more information
38645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    about the eval context, see :ref:`eval-context`.
39645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
40645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    .. versionadded:: 2.4
41645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """
42645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    f.evalcontextfilter = True
43645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    return f
44645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
45645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
46645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezdef environmentfilter(f):
47645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """Decorator for marking evironment dependent filters.  The current
48645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    :class:`Environment` is passed to the filter as first argument.
49645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """
50645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    f.environmentfilter = True
51645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    return f
52645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
53645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
54645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezdef make_attrgetter(environment, attribute):
55645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """Returns a callable that looks up the given attribute from a
56645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    passed object with the rules of the environment.  Dots are allowed
57645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    to access attributes of attributes.  Integer parts in paths are
58645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    looked up as integers.
59645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """
60645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    if not isinstance(attribute, string_types) \
61645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez       or ('.' not in attribute and not attribute.isdigit()):
62645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        return lambda x: environment.getitem(x, attribute)
63645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    attribute = attribute.split('.')
64645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    def attrgetter(item):
65645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        for part in attribute:
66645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            if part.isdigit():
67645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                part = int(part)
68645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            item = environment.getitem(item, part)
69645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        return item
70645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    return attrgetter
71645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
72645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
73645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezdef do_forceescape(value):
74645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """Enforce HTML escaping.  This will probably double escape variables."""
75645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    if hasattr(value, '__html__'):
76645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        value = value.__html__()
77645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    return escape(text_type(value))
78645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
79645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
80645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezdef do_urlencode(value):
81645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """Escape strings for use in URLs (uses UTF-8 encoding).  It accepts both
82645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    dictionaries and regular strings as well as pairwise iterables.
83645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
84645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    .. versionadded:: 2.7
85645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """
86645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    itemiter = None
87645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    if isinstance(value, dict):
88645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        itemiter = iteritems(value)
89645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    elif not isinstance(value, string_types):
90645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        try:
91645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            itemiter = iter(value)
92645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        except TypeError:
93645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            pass
94645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    if itemiter is None:
95645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        return unicode_urlencode(value)
96645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    return u'&'.join(unicode_urlencode(k) + '=' +
97645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                     unicode_urlencode(v) for k, v in itemiter)
98645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
99645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
100645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez@evalcontextfilter
101645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezdef do_replace(eval_ctx, s, old, new, count=None):
102645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """Return a copy of the value with all occurrences of a substring
103645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    replaced with a new one. The first argument is the substring
104645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    that should be replaced, the second is the replacement string.
105645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    If the optional third argument ``count`` is given, only the first
106645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    ``count`` occurrences are replaced:
107645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
108645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    .. sourcecode:: jinja
109645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
110645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        {{ "Hello World"|replace("Hello", "Goodbye") }}
111645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            -> Goodbye World
112645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
113645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        {{ "aaaaargh"|replace("a", "d'oh, ", 2) }}
114645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            -> d'oh, d'oh, aaargh
115645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """
116645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    if count is None:
117645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        count = -1
118645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    if not eval_ctx.autoescape:
119645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        return text_type(s).replace(text_type(old), text_type(new), count)
120645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    if hasattr(old, '__html__') or hasattr(new, '__html__') and \
121645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez       not hasattr(s, '__html__'):
122645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        s = escape(s)
123645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    else:
124645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        s = soft_unicode(s)
125645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    return s.replace(soft_unicode(old), soft_unicode(new), count)
126645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
127645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
128645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezdef do_upper(s):
129645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """Convert a value to uppercase."""
130645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    return soft_unicode(s).upper()
131645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
132645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
133645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezdef do_lower(s):
134645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """Convert a value to lowercase."""
135645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    return soft_unicode(s).lower()
136645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
137645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
138645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez@evalcontextfilter
139645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezdef do_xmlattr(_eval_ctx, d, autospace=True):
140645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """Create an SGML/XML attribute string based on the items in a dict.
141645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    All values that are neither `none` nor `undefined` are automatically
142645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    escaped:
143645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
144645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    .. sourcecode:: html+jinja
145645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
146645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        <ul{{ {'class': 'my_list', 'missing': none,
147645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                'id': 'list-%d'|format(variable)}|xmlattr }}>
148645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        ...
149645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        </ul>
150645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
151645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    Results in something like this:
152645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
153645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    .. sourcecode:: html
154645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
155645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        <ul class="my_list" id="list-42">
156645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        ...
157645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        </ul>
158645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
159645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    As you can see it automatically prepends a space in front of the item
160645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    if the filter returned something unless the second parameter is false.
161645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """
162645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    rv = u' '.join(
163645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        u'%s="%s"' % (escape(key), escape(value))
164645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        for key, value in iteritems(d)
165645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        if value is not None and not isinstance(value, Undefined)
166645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    )
167645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    if autospace and rv:
168645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        rv = u' ' + rv
169645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    if _eval_ctx.autoescape:
170645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        rv = Markup(rv)
171645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    return rv
172645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
173645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
174645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezdef do_capitalize(s):
175645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """Capitalize a value. The first character will be uppercase, all others
176645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    lowercase.
177645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """
178645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    return soft_unicode(s).capitalize()
179645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
180645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
181645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezdef do_title(s):
182645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """Return a titlecased version of the value. I.e. words will start with
183645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    uppercase letters, all remaining characters are lowercase.
184645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """
185645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    rv = []
186645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    for item in re.compile(r'([-\s]+)(?u)').split(s):
187645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        if not item:
188645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            continue
189645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        rv.append(item[0].upper() + item[1:].lower())
190645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    return ''.join(rv)
191645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
192645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
193645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezdef do_dictsort(value, case_sensitive=False, by='key'):
194645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """Sort a dict and yield (key, value) pairs. Because python dicts are
195645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    unsorted you may want to use this function to order them by either
196645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    key or value:
197645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
198645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    .. sourcecode:: jinja
199645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
200645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        {% for item in mydict|dictsort %}
201645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            sort the dict by key, case insensitive
202645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
203645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        {% for item in mydict|dictsort(true) %}
204645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            sort the dict by key, case sensitive
205645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
206645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        {% for item in mydict|dictsort(false, 'value') %}
207645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            sort the dict by key, case insensitive, sorted
208645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            normally and ordered by value.
209645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """
210645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    if by == 'key':
211645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        pos = 0
212645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    elif by == 'value':
213645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        pos = 1
214645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    else:
215645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        raise FilterArgumentError('You can only sort by either '
216645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                                  '"key" or "value"')
217645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    def sort_func(item):
218645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        value = item[pos]
219645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        if isinstance(value, string_types) and not case_sensitive:
220645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            value = value.lower()
221645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        return value
222645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
223645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    return sorted(value.items(), key=sort_func)
224645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
225645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
226645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez@environmentfilter
227645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezdef do_sort(environment, value, reverse=False, case_sensitive=False,
228645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            attribute=None):
229645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """Sort an iterable.  Per default it sorts ascending, if you pass it
230645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    true as first argument it will reverse the sorting.
231645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
232645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    If the iterable is made of strings the third parameter can be used to
233645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    control the case sensitiveness of the comparison which is disabled by
234645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    default.
235645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
236645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    .. sourcecode:: jinja
237645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
238645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        {% for item in iterable|sort %}
239645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            ...
240645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        {% endfor %}
241645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
242645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    It is also possible to sort by an attribute (for example to sort
243645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    by the date of an object) by specifying the `attribute` parameter:
244645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
245645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    .. sourcecode:: jinja
246645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
247645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        {% for item in iterable|sort(attribute='date') %}
248645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            ...
249645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        {% endfor %}
250645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
251645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    .. versionchanged:: 2.6
252645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez       The `attribute` parameter was added.
253645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """
254645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    if not case_sensitive:
255645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        def sort_func(item):
256645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            if isinstance(item, string_types):
257645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                item = item.lower()
258645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            return item
259645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    else:
260645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        sort_func = None
261645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    if attribute is not None:
262645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        getter = make_attrgetter(environment, attribute)
263645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        def sort_func(item, processor=sort_func or (lambda x: x)):
264645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            return processor(getter(item))
265645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    return sorted(value, key=sort_func, reverse=reverse)
266645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
267645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
268645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezdef do_default(value, default_value=u'', boolean=False):
269645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """If the value is undefined it will return the passed default value,
270645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    otherwise the value of the variable:
271645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
272645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    .. sourcecode:: jinja
273645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
274645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        {{ my_variable|default('my_variable is not defined') }}
275645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
276645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    This will output the value of ``my_variable`` if the variable was
277645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    defined, otherwise ``'my_variable is not defined'``. If you want
278645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    to use default with variables that evaluate to false you have to
279645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    set the second parameter to `true`:
280645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
281645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    .. sourcecode:: jinja
282645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
283645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        {{ ''|default('the string was empty', true) }}
284645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """
285645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    if isinstance(value, Undefined) or (boolean and not value):
286645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        return default_value
287645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    return value
288645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
289645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
290645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez@evalcontextfilter
291645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezdef do_join(eval_ctx, value, d=u'', attribute=None):
292645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """Return a string which is the concatenation of the strings in the
293645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    sequence. The separator between elements is an empty string per
294645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    default, you can define it with the optional parameter:
295645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
296645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    .. sourcecode:: jinja
297645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
298645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        {{ [1, 2, 3]|join('|') }}
299645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            -> 1|2|3
300645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
301645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        {{ [1, 2, 3]|join }}
302645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            -> 123
303645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
304645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    It is also possible to join certain attributes of an object:
305645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
306645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    .. sourcecode:: jinja
307645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
308645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        {{ users|join(', ', attribute='username') }}
309645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
310645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    .. versionadded:: 2.6
311645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez       The `attribute` parameter was added.
312645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """
313645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    if attribute is not None:
314645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        value = imap(make_attrgetter(eval_ctx.environment, attribute), value)
315645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
316645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    # no automatic escaping?  joining is a lot eaiser then
317645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    if not eval_ctx.autoescape:
318645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        return text_type(d).join(imap(text_type, value))
319645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
320645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    # if the delimiter doesn't have an html representation we check
321645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    # if any of the items has.  If yes we do a coercion to Markup
322645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    if not hasattr(d, '__html__'):
323645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        value = list(value)
324645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        do_escape = False
325645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        for idx, item in enumerate(value):
326645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            if hasattr(item, '__html__'):
327645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                do_escape = True
328645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            else:
329645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                value[idx] = text_type(item)
330645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        if do_escape:
331645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            d = escape(d)
332645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        else:
333645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            d = text_type(d)
334645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        return d.join(value)
335645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
336645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    # no html involved, to normal joining
337645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    return soft_unicode(d).join(imap(soft_unicode, value))
338645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
339645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
340645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezdef do_center(value, width=80):
341645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """Centers the value in a field of a given width."""
342645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    return text_type(value).center(width)
343645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
344645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
345645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez@environmentfilter
346645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezdef do_first(environment, seq):
347645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """Return the first item of a sequence."""
348645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    try:
349645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        return next(iter(seq))
350645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    except StopIteration:
351645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        return environment.undefined('No first item, sequence was empty.')
352645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
353645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
354645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez@environmentfilter
355645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezdef do_last(environment, seq):
356645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """Return the last item of a sequence."""
357645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    try:
358645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        return next(iter(reversed(seq)))
359645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    except StopIteration:
360645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        return environment.undefined('No last item, sequence was empty.')
361645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
362645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
363645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez@environmentfilter
364645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezdef do_random(environment, seq):
365645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """Return a random item from the sequence."""
366645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    try:
367645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        return choice(seq)
368645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    except IndexError:
369645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        return environment.undefined('No random item, sequence was empty.')
370645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
371645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
372645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezdef do_filesizeformat(value, binary=False):
373645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """Format the value like a 'human-readable' file size (i.e. 13 kB,
374645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    4.1 MB, 102 Bytes, etc).  Per default decimal prefixes are used (Mega,
375645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    Giga, etc.), if the second parameter is set to `True` the binary
376645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    prefixes are used (Mebi, Gibi).
377645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """
378645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    bytes = float(value)
379645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    base = binary and 1024 or 1000
380645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    prefixes = [
381645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        (binary and 'KiB' or 'kB'),
382645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        (binary and 'MiB' or 'MB'),
383645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        (binary and 'GiB' or 'GB'),
384645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        (binary and 'TiB' or 'TB'),
385645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        (binary and 'PiB' or 'PB'),
386645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        (binary and 'EiB' or 'EB'),
387645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        (binary and 'ZiB' or 'ZB'),
388645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        (binary and 'YiB' or 'YB')
389645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    ]
390645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    if bytes == 1:
391645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        return '1 Byte'
392645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    elif bytes < base:
393645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        return '%d Bytes' % bytes
394645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    else:
395645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        for i, prefix in enumerate(prefixes):
396645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            unit = base ** (i + 2)
397645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            if bytes < unit:
398645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                return '%.1f %s' % ((base * bytes / unit), prefix)
399645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        return '%.1f %s' % ((base * bytes / unit), prefix)
400645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
401645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
402645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezdef do_pprint(value, verbose=False):
403645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """Pretty print a variable. Useful for debugging.
404645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
405645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    With Jinja 1.2 onwards you can pass it a parameter.  If this parameter
406645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    is truthy the output will be more verbose (this requires `pretty`)
407645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """
408645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    return pformat(value, verbose=verbose)
409645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
410645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
411645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez@evalcontextfilter
412645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezdef do_urlize(eval_ctx, value, trim_url_limit=None, nofollow=False):
413645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """Converts URLs in plain text into clickable links.
414645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
415645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    If you pass the filter an additional integer it will shorten the urls
416645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    to that number. Also a third argument exists that makes the urls
417645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    "nofollow":
418645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
419645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    .. sourcecode:: jinja
420645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
421645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        {{ mytext|urlize(40, true) }}
422645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            links are shortened to 40 chars and defined with rel="nofollow"
423645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """
424645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    rv = urlize(value, trim_url_limit, nofollow)
425645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    if eval_ctx.autoescape:
426645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        rv = Markup(rv)
427645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    return rv
428645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
429645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
430645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezdef do_indent(s, width=4, indentfirst=False):
431645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """Return a copy of the passed string, each line indented by
432645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    4 spaces. The first line is not indented. If you want to
433645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    change the number of spaces or indent the first line too
434645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    you can pass additional parameters to the filter:
435645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
436645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    .. sourcecode:: jinja
437645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
438645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        {{ mytext|indent(2, true) }}
439645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            indent by two spaces and indent the first line too.
440645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """
441645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    indention = u' ' * width
442645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    rv = (u'\n' + indention).join(s.splitlines())
443645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    if indentfirst:
444645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        rv = indention + rv
445645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    return rv
446645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
447645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
448645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezdef do_truncate(s, length=255, killwords=False, end='...'):
449645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """Return a truncated copy of the string. The length is specified
450645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    with the first parameter which defaults to ``255``. If the second
451645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    parameter is ``true`` the filter will cut the text at length. Otherwise
452645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    it will discard the last word. If the text was in fact
453645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    truncated it will append an ellipsis sign (``"..."``). If you want a
454645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    different ellipsis sign than ``"..."`` you can specify it using the
455645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    third parameter.
456645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
457645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    .. sourcecode:: jinja
458645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
459645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        {{ "foo bar"|truncate(5) }}
460645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            -> "foo ..."
461645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        {{ "foo bar"|truncate(5, True) }}
462645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            -> "foo b..."
463645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """
464645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    if len(s) <= length:
465645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        return s
466645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    elif killwords:
467645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        return s[:length] + end
468645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    words = s.split(' ')
469645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    result = []
470645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    m = 0
471645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    for word in words:
472645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        m += len(word) + 1
473645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        if m > length:
474645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            break
475645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        result.append(word)
476645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    result.append(end)
477645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    return u' '.join(result)
478645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
479645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez@environmentfilter
480645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezdef do_wordwrap(environment, s, width=79, break_long_words=True,
481645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                wrapstring=None):
482645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """
483645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    Return a copy of the string passed to the filter wrapped after
484645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    ``79`` characters.  You can override this default using the first
485645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    parameter.  If you set the second parameter to `false` Jinja will not
486645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    split words apart if they are longer than `width`. By default, the newlines
487645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    will be the default newlines for the environment, but this can be changed
488645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    using the wrapstring keyword argument.
489645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
490645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    .. versionadded:: 2.7
491645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez       Added support for the `wrapstring` parameter.
492645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """
493645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    if not wrapstring:
494645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        wrapstring = environment.newline_sequence
495645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    import textwrap
496645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    return wrapstring.join(textwrap.wrap(s, width=width, expand_tabs=False,
497645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                                   replace_whitespace=False,
498645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                                   break_long_words=break_long_words))
499645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
500645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
501645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezdef do_wordcount(s):
502645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """Count the words in that string."""
503645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    return len(_word_re.findall(s))
504645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
505645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
506645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezdef do_int(value, default=0):
507645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """Convert the value into an integer. If the
508645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    conversion doesn't work it will return ``0``. You can
509645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    override this default using the first parameter.
510645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """
511645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    try:
512645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        return int(value)
513645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    except (TypeError, ValueError):
514645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        # this quirk is necessary so that "42.23"|int gives 42.
515645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        try:
516645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            return int(float(value))
517645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        except (TypeError, ValueError):
518645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            return default
519645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
520645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
521645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezdef do_float(value, default=0.0):
522645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """Convert the value into a floating point number. If the
523645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    conversion doesn't work it will return ``0.0``. You can
524645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    override this default using the first parameter.
525645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """
526645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    try:
527645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        return float(value)
528645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    except (TypeError, ValueError):
529645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        return default
530645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
531645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
532645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezdef do_format(value, *args, **kwargs):
533645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """
534645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    Apply python string formatting on an object:
535645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
536645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    .. sourcecode:: jinja
537645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
538645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        {{ "%s - %s"|format("Hello?", "Foo!") }}
539645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            -> Hello? - Foo!
540645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """
541645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    if args and kwargs:
542645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        raise FilterArgumentError('can\'t handle positional and keyword '
543645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                                  'arguments at the same time')
544645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    return soft_unicode(value) % (kwargs or args)
545645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
546645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
547645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezdef do_trim(value):
548645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """Strip leading and trailing whitespace."""
549645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    return soft_unicode(value).strip()
550645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
551645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
552645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezdef do_striptags(value):
553645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """Strip SGML/XML tags and replace adjacent whitespace by one space.
554645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """
555645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    if hasattr(value, '__html__'):
556645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        value = value.__html__()
557645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    return Markup(text_type(value)).striptags()
558645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
559645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
560645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezdef do_slice(value, slices, fill_with=None):
561645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """Slice an iterator and return a list of lists containing
562645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    those items. Useful if you want to create a div containing
563645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    three ul tags that represent columns:
564645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
565645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    .. sourcecode:: html+jinja
566645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
567645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        <div class="columwrapper">
568645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez          {%- for column in items|slice(3) %}
569645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            <ul class="column-{{ loop.index }}">
570645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            {%- for item in column %}
571645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez              <li>{{ item }}</li>
572645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            {%- endfor %}
573645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            </ul>
574645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez          {%- endfor %}
575645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        </div>
576645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
577645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    If you pass it a second argument it's used to fill missing
578645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    values on the last iteration.
579645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """
580645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    seq = list(value)
581645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    length = len(seq)
582645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    items_per_slice = length // slices
583645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    slices_with_extra = length % slices
584645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    offset = 0
585645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    for slice_number in range(slices):
586645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        start = offset + slice_number * items_per_slice
587645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        if slice_number < slices_with_extra:
588645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            offset += 1
589645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        end = offset + (slice_number + 1) * items_per_slice
590645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        tmp = seq[start:end]
591645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        if fill_with is not None and slice_number >= slices_with_extra:
592645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            tmp.append(fill_with)
593645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        yield tmp
594645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
595645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
596645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezdef do_batch(value, linecount, fill_with=None):
597645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """
598645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    A filter that batches items. It works pretty much like `slice`
599645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    just the other way round. It returns a list of lists with the
600645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    given number of items. If you provide a second parameter this
601645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    is used to fill up missing items. See this example:
602645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
603645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    .. sourcecode:: html+jinja
604645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
605645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        <table>
606645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        {%- for row in items|batch(3, '&nbsp;') %}
607645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez          <tr>
608645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez          {%- for column in row %}
609645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            <td>{{ column }}</td>
610645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez          {%- endfor %}
611645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez          </tr>
612645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        {%- endfor %}
613645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        </table>
614645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """
615645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    result = []
616645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    tmp = []
617645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    for item in value:
618645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        if len(tmp) == linecount:
619645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            yield tmp
620645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            tmp = []
621645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        tmp.append(item)
622645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    if tmp:
623645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        if fill_with is not None and len(tmp) < linecount:
624645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            tmp += [fill_with] * (linecount - len(tmp))
625645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        yield tmp
626645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
627645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
628645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezdef do_round(value, precision=0, method='common'):
629645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """Round the number to a given precision. The first
630645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    parameter specifies the precision (default is ``0``), the
631645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    second the rounding method:
632645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
633645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    - ``'common'`` rounds either up or down
634645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    - ``'ceil'`` always rounds up
635645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    - ``'floor'`` always rounds down
636645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
637645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    If you don't specify a method ``'common'`` is used.
638645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
639645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    .. sourcecode:: jinja
640645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
641645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        {{ 42.55|round }}
642645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            -> 43.0
643645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        {{ 42.55|round(1, 'floor') }}
644645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            -> 42.5
645645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
646645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    Note that even if rounded to 0 precision, a float is returned.  If
647645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    you need a real integer, pipe it through `int`:
648645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
649645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    .. sourcecode:: jinja
650645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
651645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        {{ 42.55|round|int }}
652645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            -> 43
653645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """
654645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    if not method in ('common', 'ceil', 'floor'):
655645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        raise FilterArgumentError('method must be common, ceil or floor')
656645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    if method == 'common':
657645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        return round(value, precision)
658645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    func = getattr(math, method)
659645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    return func(value * (10 ** precision)) / (10 ** precision)
660645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
661645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
662645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez@environmentfilter
663645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezdef do_groupby(environment, value, attribute):
664645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """Group a sequence of objects by a common attribute.
665645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
666645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    If you for example have a list of dicts or objects that represent persons
667645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    with `gender`, `first_name` and `last_name` attributes and you want to
668645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    group all users by genders you can do something like the following
669645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    snippet:
670645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
671645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    .. sourcecode:: html+jinja
672645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
673645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        <ul>
674645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        {% for group in persons|groupby('gender') %}
675645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            <li>{{ group.grouper }}<ul>
676645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            {% for person in group.list %}
677645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                <li>{{ person.first_name }} {{ person.last_name }}</li>
678645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            {% endfor %}</ul></li>
679645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        {% endfor %}
680645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        </ul>
681645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
682645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    Additionally it's possible to use tuple unpacking for the grouper and
683645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    list:
684645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
685645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    .. sourcecode:: html+jinja
686645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
687645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        <ul>
688645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        {% for grouper, list in persons|groupby('gender') %}
689645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            ...
690645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        {% endfor %}
691645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        </ul>
692645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
693645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    As you can see the item we're grouping by is stored in the `grouper`
694645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    attribute and the `list` contains all the objects that have this grouper
695645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    in common.
696645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
697645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    .. versionchanged:: 2.6
698645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez       It's now possible to use dotted notation to group by the child
699645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez       attribute of another attribute.
700645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """
701645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    expr = make_attrgetter(environment, attribute)
702645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    return sorted(map(_GroupTuple, groupby(sorted(value, key=expr), expr)))
703645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
704645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
705645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezclass _GroupTuple(tuple):
706645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    __slots__ = ()
707645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    grouper = property(itemgetter(0))
708645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    list = property(itemgetter(1))
709645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
710645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    def __new__(cls, xxx_todo_changeme):
711645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        (key, value) = xxx_todo_changeme
712645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        return tuple.__new__(cls, (key, list(value)))
713645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
714645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
715645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez@environmentfilter
716645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezdef do_sum(environment, iterable, attribute=None, start=0):
717645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """Returns the sum of a sequence of numbers plus the value of parameter
718645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    'start' (which defaults to 0).  When the sequence is empty it returns
719645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    start.
720645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
721645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    It is also possible to sum up only certain attributes:
722645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
723645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    .. sourcecode:: jinja
724645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
725645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        Total: {{ items|sum(attribute='price') }}
726645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
727645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    .. versionchanged:: 2.6
728645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez       The `attribute` parameter was added to allow suming up over
729645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez       attributes.  Also the `start` parameter was moved on to the right.
730645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """
731645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    if attribute is not None:
732645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        iterable = imap(make_attrgetter(environment, attribute), iterable)
733645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    return sum(iterable, start)
734645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
735645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
736645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezdef do_list(value):
737645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """Convert the value into a list.  If it was a string the returned list
738645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    will be a list of characters.
739645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """
740645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    return list(value)
741645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
742645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
743645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezdef do_mark_safe(value):
744645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """Mark the value as safe which means that in an environment with automatic
745645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    escaping enabled this variable will not be escaped.
746645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """
747645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    return Markup(value)
748645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
749645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
750645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezdef do_mark_unsafe(value):
751645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """Mark a value as unsafe.  This is the reverse operation for :func:`safe`."""
752645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    return text_type(value)
753645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
754645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
755645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezdef do_reverse(value):
756645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """Reverse the object or return an iterator the iterates over it the other
757645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    way round.
758645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """
759645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    if isinstance(value, string_types):
760645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        return value[::-1]
761645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    try:
762645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        return reversed(value)
763645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    except TypeError:
764645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        try:
765645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            rv = list(value)
766645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            rv.reverse()
767645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            return rv
768645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        except TypeError:
769645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            raise FilterArgumentError('argument must be iterable')
770645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
771645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
772645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez@environmentfilter
773645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezdef do_attr(environment, obj, name):
774645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """Get an attribute of an object.  ``foo|attr("bar")`` works like
775645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    ``foo["bar"]`` just that always an attribute is returned and items are not
776645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    looked up.
777645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
778645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    See :ref:`Notes on subscriptions <notes-on-subscriptions>` for more details.
779645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """
780645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    try:
781645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        name = str(name)
782645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    except UnicodeError:
783645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        pass
784645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    else:
785645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        try:
786645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            value = getattr(obj, name)
787645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        except AttributeError:
788645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            pass
789645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        else:
790645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            if environment.sandboxed and not \
791645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez               environment.is_safe_attribute(obj, name, value):
792645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                return environment.unsafe_undefined(obj, name)
793645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            return value
794645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    return environment.undefined(obj=obj, name=name)
795645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
796645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
797645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez@contextfilter
798645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezdef do_map(*args, **kwargs):
799645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """Applies a filter on a sequence of objects or looks up an attribute.
800645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    This is useful when dealing with lists of objects but you are really
801645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    only interested in a certain value of it.
802645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
803645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    The basic usage is mapping on an attribute.  Imagine you have a list
804645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    of users but you are only interested in a list of usernames:
805645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
806645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    .. sourcecode:: jinja
807645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
808645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        Users on this page: {{ users|map(attribute='username')|join(', ') }}
809645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
810645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    Alternatively you can let it invoke a filter by passing the name of the
811645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    filter and the arguments afterwards.  A good example would be applying a
812645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    text conversion filter on a sequence:
813645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
814645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    .. sourcecode:: jinja
815645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
816645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        Users on this page: {{ titles|map('lower')|join(', ') }}
817645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
818645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    .. versionadded:: 2.7
819645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """
820645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    context = args[0]
821645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    seq = args[1]
822645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
823645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    if len(args) == 2 and 'attribute' in kwargs:
824645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        attribute = kwargs.pop('attribute')
825645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        if kwargs:
826645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            raise FilterArgumentError('Unexpected keyword argument %r' %
827645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                next(iter(kwargs)))
828645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        func = make_attrgetter(context.environment, attribute)
829645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    else:
830645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        try:
831645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            name = args[2]
832645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            args = args[3:]
833645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        except LookupError:
834645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            raise FilterArgumentError('map requires a filter argument')
835645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        func = lambda item: context.environment.call_filter(
836645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            name, item, args, kwargs, context=context)
837645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
838645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    if seq:
839645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        for item in seq:
840645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            yield func(item)
841645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
842645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
843645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez@contextfilter
844645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezdef do_select(*args, **kwargs):
845645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """Filters a sequence of objects by appying a test to either the object
846645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    or the attribute and only selecting the ones with the test succeeding.
847645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
848645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    Example usage:
849645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
850645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    .. sourcecode:: jinja
851645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
852645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        {{ numbers|select("odd") }}
853645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
854645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    .. versionadded:: 2.7
855645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """
856645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    return _select_or_reject(args, kwargs, lambda x: x, False)
857645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
858645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
859645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez@contextfilter
860645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezdef do_reject(*args, **kwargs):
861645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """Filters a sequence of objects by appying a test to either the object
862645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    or the attribute and rejecting the ones with the test succeeding.
863645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
864645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    Example usage:
865645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
866645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    .. sourcecode:: jinja
867645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
868645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        {{ numbers|reject("odd") }}
869645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
870645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    .. versionadded:: 2.7
871645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """
872645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    return _select_or_reject(args, kwargs, lambda x: not x, False)
873645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
874645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
875645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez@contextfilter
876645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezdef do_selectattr(*args, **kwargs):
877645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """Filters a sequence of objects by appying a test to either the object
878645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    or the attribute and only selecting the ones with the test succeeding.
879645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
880645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    Example usage:
881645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
882645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    .. sourcecode:: jinja
883645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
884645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        {{ users|selectattr("is_active") }}
885645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        {{ users|selectattr("email", "none") }}
886645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
887645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    .. versionadded:: 2.7
888645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """
889645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    return _select_or_reject(args, kwargs, lambda x: x, True)
890645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
891645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
892645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez@contextfilter
893645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezdef do_rejectattr(*args, **kwargs):
894645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """Filters a sequence of objects by appying a test to either the object
895645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    or the attribute and rejecting the ones with the test succeeding.
896645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
897645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    .. sourcecode:: jinja
898645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
899645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        {{ users|rejectattr("is_active") }}
900645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        {{ users|rejectattr("email", "none") }}
901645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
902645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    .. versionadded:: 2.7
903645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    """
904645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    return _select_or_reject(args, kwargs, lambda x: not x, True)
905645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
906645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
907645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezdef _select_or_reject(args, kwargs, modfunc, lookup_attr):
908645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    context = args[0]
909645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    seq = args[1]
910645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    if lookup_attr:
911645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        try:
912645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            attr = args[2]
913645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        except LookupError:
914645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            raise FilterArgumentError('Missing parameter for attribute name')
915645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        transfunc = make_attrgetter(context.environment, attr)
916645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        off = 1
917645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    else:
918645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        off = 0
919645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        transfunc = lambda x: x
920645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
921645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    try:
922645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        name = args[2 + off]
923645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        args = args[3 + off:]
924645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        func = lambda item: context.environment.call_test(
925645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            name, item, args, kwargs)
926645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    except LookupError:
927645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        func = bool
928645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
929645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    if seq:
930645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez        for item in seq:
931645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez            if modfunc(func(transfunc(item))):
932645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez                yield item
933645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
934645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez
935645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector ChavezFILTERS = {
936645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    'attr':                 do_attr,
937645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    'replace':              do_replace,
938645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    'upper':                do_upper,
939645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    'lower':                do_lower,
940645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    'escape':               escape,
941645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    'e':                    escape,
942645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    'forceescape':          do_forceescape,
943645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    'capitalize':           do_capitalize,
944645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    'title':                do_title,
945645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    'default':              do_default,
946645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    'd':                    do_default,
947645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    'join':                 do_join,
948645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    'count':                len,
949645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    'dictsort':             do_dictsort,
950645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    'sort':                 do_sort,
951645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    'length':               len,
952645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    'reverse':              do_reverse,
953645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    'center':               do_center,
954645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    'indent':               do_indent,
955645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    'title':                do_title,
956645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    'capitalize':           do_capitalize,
957645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    'first':                do_first,
958645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    'last':                 do_last,
959645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    'map':                  do_map,
960645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    'random':               do_random,
961645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    'reject':               do_reject,
962645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    'rejectattr':           do_rejectattr,
963645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    'filesizeformat':       do_filesizeformat,
964645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    'pprint':               do_pprint,
965645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    'truncate':             do_truncate,
966645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    'wordwrap':             do_wordwrap,
967645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    'wordcount':            do_wordcount,
968645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    'int':                  do_int,
969645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    'float':                do_float,
970645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    'string':               soft_unicode,
971645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    'list':                 do_list,
972645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    'urlize':               do_urlize,
973645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    'format':               do_format,
974645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    'trim':                 do_trim,
975645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    'striptags':            do_striptags,
976645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    'select':               do_select,
977645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    'selectattr':           do_selectattr,
978645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    'slice':                do_slice,
979645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    'batch':                do_batch,
980645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    'sum':                  do_sum,
981645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    'abs':                  abs,
982645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    'round':                do_round,
983645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    'groupby':              do_groupby,
984645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    'safe':                 do_mark_safe,
985645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    'xmlattr':              do_xmlattr,
986645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez    'urlencode':            do_urlencode
987645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez}
988