1 # -*- coding: utf-8 -*-
8 :copyright: (c) 2010 by the Jinja Team.
9 :license: BSD, see LICENSE for more details.
13 from random import choice
14 from operator import itemgetter
15 from itertools import imap, groupby
16 from jinja2.utils import Markup, escape, pformat, urlize, soft_unicode
17 from jinja2.runtime import Undefined
18 from jinja2.exceptions import FilterArgumentError, SecurityError
21 _word_re = re.compile(r'\w+(?u)')
25 """Decorator for marking context dependent filters. The current
26 :class:`Context` will be passed as first argument.
28 f.contextfilter = True
32 def evalcontextfilter(f):
33 """Decorator for marking eval-context dependent filters. An eval
34 context object is passed as first argument. For more information
35 about the eval context, see :ref:`eval-context`.
39 f.evalcontextfilter = True
43 def environmentfilter(f):
44 """Decorator for marking evironment dependent filters. The current
45 :class:`Environment` is passed to the filter as first argument.
47 f.environmentfilter = True
51 def make_attrgetter(environment, attribute):
52 """Returns a callable that looks up the given attribute from a
53 passed object with the rules of the environment. Dots are allowed
54 to access attributes of attributes.
56 if '.' not in attribute:
57 return lambda x: environment.getitem(x, attribute)
58 attribute = attribute.split('.')
60 for part in attribute:
61 item = environment.getitem(item, part)
66 def do_forceescape(value):
67 """Enforce HTML escaping. This will probably double escape variables."""
68 if hasattr(value, '__html__'):
69 value = value.__html__()
70 return escape(unicode(value))
74 def do_replace(eval_ctx, s, old, new, count=None):
75 """Return a copy of the value with all occurrences of a substring
76 replaced with a new one. The first argument is the substring
77 that should be replaced, the second is the replacement string.
78 If the optional third argument ``count`` is given, only the first
79 ``count`` occurrences are replaced:
83 {{ "Hello World"|replace("Hello", "Goodbye") }}
86 {{ "aaaaargh"|replace("a", "d'oh, ", 2) }}
91 if not eval_ctx.autoescape:
92 return unicode(s).replace(unicode(old), unicode(new), count)
93 if hasattr(old, '__html__') or hasattr(new, '__html__') and \
94 not hasattr(s, '__html__'):
98 return s.replace(soft_unicode(old), soft_unicode(new), count)
102 """Convert a value to uppercase."""
103 return soft_unicode(s).upper()
107 """Convert a value to lowercase."""
108 return soft_unicode(s).lower()
112 def do_xmlattr(_eval_ctx, d, autospace=True):
113 """Create an SGML/XML attribute string based on the items in a dict.
114 All values that are neither `none` nor `undefined` are automatically
117 .. sourcecode:: html+jinja
119 <ul{{ {'class': 'my_list', 'missing': none,
120 'id': 'list-%d'|format(variable)}|xmlattr }}>
124 Results in something like this:
128 <ul class="my_list" id="list-42">
132 As you can see it automatically prepends a space in front of the item
133 if the filter returned something unless the second parameter is false.
136 u'%s="%s"' % (escape(key), escape(value))
137 for key, value in d.iteritems()
138 if value is not None and not isinstance(value, Undefined)
142 if _eval_ctx.autoescape:
147 def do_capitalize(s):
148 """Capitalize a value. The first character will be uppercase, all others
151 return soft_unicode(s).capitalize()
155 """Return a titlecased version of the value. I.e. words will start with
156 uppercase letters, all remaining characters are lowercase.
158 return soft_unicode(s).title()
161 def do_dictsort(value, case_sensitive=False, by='key'):
162 """Sort a dict and yield (key, value) pairs. Because python dicts are
163 unsorted you may want to use this function to order them by either
166 .. sourcecode:: jinja
168 {% for item in mydict|dictsort %}
169 sort the dict by key, case insensitive
171 {% for item in mydict|dicsort(true) %}
172 sort the dict by key, case sensitive
174 {% for item in mydict|dictsort(false, 'value') %}
175 sort the dict by key, case insensitive, sorted
176 normally and ordered by value.
183 raise FilterArgumentError('You can only sort by either '
187 if isinstance(value, basestring) and not case_sensitive:
188 value = value.lower()
191 return sorted(value.items(), key=sort_func)
195 def do_sort(environment, value, reverse=False, case_sensitive=False,
197 """Sort an iterable. Per default it sorts ascending, if you pass it
198 true as first argument it will reverse the sorting.
200 If the iterable is made of strings the third parameter can be used to
201 control the case sensitiveness of the comparison which is disabled by
204 .. sourcecode:: jinja
206 {% for item in iterable|sort %}
210 It is also possible to sort by an attribute (for example to sort
211 by the date of an object) by specifying the `attribute` parameter:
213 .. sourcecode:: jinja
215 {% for item in iterable|sort(attribute='date') %}
219 .. versionchanged:: 2.6
220 The `attribute` parameter was added.
222 if not case_sensitive:
224 if isinstance(item, basestring):
229 if attribute is not None:
230 getter = make_attrgetter(environment, attribute)
231 def sort_func(item, processor=sort_func or (lambda x: x)):
232 return processor(getter(item))
233 return sorted(value, key=sort_func, reverse=reverse)
236 def do_default(value, default_value=u'', boolean=False):
237 """If the value is undefined it will return the passed default value,
238 otherwise the value of the variable:
240 .. sourcecode:: jinja
242 {{ my_variable|default('my_variable is not defined') }}
244 This will output the value of ``my_variable`` if the variable was
245 defined, otherwise ``'my_variable is not defined'``. If you want
246 to use default with variables that evaluate to false you have to
247 set the second parameter to `true`:
249 .. sourcecode:: jinja
251 {{ ''|default('the string was empty', true) }}
253 if (boolean and not value) or isinstance(value, Undefined):
259 def do_join(eval_ctx, value, d=u''):
260 """Return a string which is the concatenation of the strings in the
261 sequence. The separator between elements is an empty string per
262 default, you can define it with the optional parameter:
264 .. sourcecode:: jinja
266 {{ [1, 2, 3]|join('|') }}
272 # no automatic escaping? joining is a lot eaiser then
273 if not eval_ctx.autoescape:
274 return unicode(d).join(imap(unicode, value))
276 # if the delimiter doesn't have an html representation we check
277 # if any of the items has. If yes we do a coercion to Markup
278 if not hasattr(d, '__html__'):
281 for idx, item in enumerate(value):
282 if hasattr(item, '__html__'):
285 value[idx] = unicode(item)
292 # no html involved, to normal joining
293 return soft_unicode(d).join(imap(soft_unicode, value))
296 def do_center(value, width=80):
297 """Centers the value in a field of a given width."""
298 return unicode(value).center(width)
302 def do_first(environment, seq):
303 """Return the first item of a sequence."""
305 return iter(seq).next()
306 except StopIteration:
307 return environment.undefined('No first item, sequence was empty.')
311 def do_last(environment, seq):
312 """Return the last item of a sequence."""
314 return iter(reversed(seq)).next()
315 except StopIteration:
316 return environment.undefined('No last item, sequence was empty.')
320 def do_random(environment, seq):
321 """Return a random item from the sequence."""
325 return environment.undefined('No random item, sequence was empty.')
328 def do_filesizeformat(value, binary=False):
329 """Format the value like a 'human-readable' file size (i.e. 13 KB,
330 4.1 MB, 102 bytes, etc). Per default decimal prefixes are used (mega,
331 giga, etc.), if the second parameter is set to `True` the binary
332 prefixes are used (mebi, gibi).
335 base = binary and 1024 or 1000
336 middle = binary and 'i' or ''
338 return "%d Byte%s" % (bytes, bytes != 1 and 's' or '')
339 elif bytes < base * base:
340 return "%.1f K%sB" % (bytes / base, middle)
341 elif bytes < base * base * base:
342 return "%.1f M%sB" % (bytes / (base * base), middle)
343 return "%.1f G%sB" % (bytes / (base * base * base), middle)
346 def do_pprint(value, verbose=False):
347 """Pretty print a variable. Useful for debugging.
349 With Jinja 1.2 onwards you can pass it a parameter. If this parameter
350 is truthy the output will be more verbose (this requires `pretty`)
352 return pformat(value, verbose=verbose)
356 def do_urlize(eval_ctx, value, trim_url_limit=None, nofollow=False):
357 """Converts URLs in plain text into clickable links.
359 If you pass the filter an additional integer it will shorten the urls
360 to that number. Also a third argument exists that makes the urls
363 .. sourcecode:: jinja
365 {{ mytext|urlize(40, true) }}
366 links are shortened to 40 chars and defined with rel="nofollow"
368 rv = urlize(value, trim_url_limit, nofollow)
369 if eval_ctx.autoescape:
374 def do_indent(s, width=4, indentfirst=False):
375 """Return a copy of the passed string, each line indented by
376 4 spaces. The first line is not indented. If you want to
377 change the number of spaces or indent the first line too
378 you can pass additional parameters to the filter:
380 .. sourcecode:: jinja
382 {{ mytext|indent(2, true) }}
383 indent by two spaces and indent the first line too.
385 indention = u' ' * width
386 rv = (u'\n' + indention).join(s.splitlines())
392 def do_truncate(s, length=255, killwords=False, end='...'):
393 """Return a truncated copy of the string. The length is specified
394 with the first parameter which defaults to ``255``. If the second
395 parameter is ``true`` the filter will cut the text at length. Otherwise
396 it will try to save the last word. If the text was in fact
397 truncated it will append an ellipsis sign (``"..."``). If you want a
398 different ellipsis sign than ``"..."`` you can specify it using the
401 .. sourcecode jinja::
403 {{ mytext|truncate(300, false, '»') }}
404 truncate mytext to 300 chars, don't split up words, use a
405 right pointing double arrow as ellipsis sign.
410 return s[:length] + end
420 return u' '.join(result)
423 def do_wordwrap(s, width=79, break_long_words=True):
425 Return a copy of the string passed to the filter wrapped after
426 ``79`` characters. You can override this default using the first
427 parameter. If you set the second parameter to `false` Jinja will not
428 split words apart if they are longer than `width`.
431 return u'\n'.join(textwrap.wrap(s, width=width, expand_tabs=False,
432 replace_whitespace=False,
433 break_long_words=break_long_words))
437 """Count the words in that string."""
438 return len(_word_re.findall(s))
441 def do_int(value, default=0):
442 """Convert the value into an integer. If the
443 conversion doesn't work it will return ``0``. You can
444 override this default using the first parameter.
448 except (TypeError, ValueError):
449 # this quirk is necessary so that "42.23"|int gives 42.
451 return int(float(value))
452 except (TypeError, ValueError):
456 def do_float(value, default=0.0):
457 """Convert the value into a floating point number. If the
458 conversion doesn't work it will return ``0.0``. You can
459 override this default using the first parameter.
463 except (TypeError, ValueError):
467 def do_format(value, *args, **kwargs):
469 Apply python string formatting on an object:
471 .. sourcecode:: jinja
473 {{ "%s - %s"|format("Hello?", "Foo!") }}
477 raise FilterArgumentError('can\'t handle positional and keyword '
478 'arguments at the same time')
479 return soft_unicode(value) % (kwargs or args)
483 """Strip leading and trailing whitespace."""
484 return soft_unicode(value).strip()
487 def do_striptags(value):
488 """Strip SGML/XML tags and replace adjacent whitespace by one space.
490 if hasattr(value, '__html__'):
491 value = value.__html__()
492 return Markup(unicode(value)).striptags()
495 def do_slice(value, slices, fill_with=None):
496 """Slice an iterator and return a list of lists containing
497 those items. Useful if you want to create a div containing
498 three ul tags that represent columns:
500 .. sourcecode:: html+jinja
502 <div class="columwrapper">
503 {%- for column in items|slice(3) %}
504 <ul class="column-{{ loop.index }}">
505 {%- for item in column %}
512 If you pass it a second argument it's used to fill missing
513 values on the last iteration.
517 items_per_slice = length // slices
518 slices_with_extra = length % slices
520 for slice_number in xrange(slices):
521 start = offset + slice_number * items_per_slice
522 if slice_number < slices_with_extra:
524 end = offset + (slice_number + 1) * items_per_slice
526 if fill_with is not None and slice_number >= slices_with_extra:
527 tmp.append(fill_with)
531 def do_batch(value, linecount, fill_with=None):
533 A filter that batches items. It works pretty much like `slice`
534 just the other way round. It returns a list of lists with the
535 given number of items. If you provide a second parameter this
536 is used to fill missing items. See this example:
538 .. sourcecode:: html+jinja
541 {%- for row in items|batch(3, ' ') %}
543 {%- for column in row %}
544 <td>{{ column }}</td>
553 if len(tmp) == linecount:
558 if fill_with is not None and len(tmp) < linecount:
559 tmp += [fill_with] * (linecount - len(tmp))
563 def do_round(value, precision=0, method='common'):
564 """Round the number to a given precision. The first
565 parameter specifies the precision (default is ``0``), the
566 second the rounding method:
568 - ``'common'`` rounds either up or down
569 - ``'ceil'`` always rounds up
570 - ``'floor'`` always rounds down
572 If you don't specify a method ``'common'`` is used.
574 .. sourcecode:: jinja
578 {{ 42.55|round(1, 'floor') }}
581 Note that even if rounded to 0 precision, a float is returned. If
582 you need a real integer, pipe it through `int`:
584 .. sourcecode:: jinja
586 {{ 42.55|round|int }}
589 if not method in ('common', 'ceil', 'floor'):
590 raise FilterArgumentError('method must be common, ceil or floor')
591 if method == 'common':
592 return round(value, precision)
593 func = getattr(math, method)
594 return func(value * (10 ** precision)) / (10 ** precision)
598 def do_groupby(environment, value, attribute):
599 """Group a sequence of objects by a common attribute.
601 If you for example have a list of dicts or objects that represent persons
602 with `gender`, `first_name` and `last_name` attributes and you want to
603 group all users by genders you can do something like the following
606 .. sourcecode:: html+jinja
609 {% for group in persons|groupby('gender') %}
610 <li>{{ group.grouper }}<ul>
611 {% for person in group.list %}
612 <li>{{ person.first_name }} {{ person.last_name }}</li>
613 {% endfor %}</ul></li>
617 Additionally it's possible to use tuple unpacking for the grouper and
620 .. sourcecode:: html+jinja
623 {% for grouper, list in persons|groupby('gender') %}
628 As you can see the item we're grouping by is stored in the `grouper`
629 attribute and the `list` contains all the objects that have this grouper
632 .. versionchanged:: 2.6
633 It's now possible to use dotted notation to group by the child
634 attribute of another attribute.
636 expr = make_attrgetter(environment, attribute)
637 return sorted(map(_GroupTuple, groupby(sorted(value, key=expr), expr)))
640 class _GroupTuple(tuple):
642 grouper = property(itemgetter(0))
643 list = property(itemgetter(1))
645 def __new__(cls, (key, value)):
646 return tuple.__new__(cls, (key, list(value)))
650 def do_sum(environment, iterable, attribute=None, start=0):
651 """Sums up an iterable.
653 .. versionchanged:: 2.6
654 The `attribute` parameter was added to allow suming up over
657 if attribute is not None:
658 iterable = imap(make_attrgetter(environment, attribute), iterable)
659 return sum(iterable, start)
663 """Convert the value into a list. If it was a string the returned list
664 will be a list of characters.
669 def do_mark_safe(value):
670 """Mark the value as safe which means that in an environment with automatic
671 escaping enabled this variable will not be escaped.
676 def do_mark_unsafe(value):
677 """Mark a value as unsafe. This is the reverse operation for :func:`safe`."""
678 return unicode(value)
681 def do_reverse(value):
682 """Reverse the object or return an iterator the iterates over it the other
685 if isinstance(value, basestring):
688 return reversed(value)
695 raise FilterArgumentError('argument must be iterable')
699 def do_attr(environment, obj, name):
700 """Get an attribute of an object. ``foo|attr("bar")`` works like
701 ``foo["bar"]`` just that always an attribute is returned and items are not
704 See :ref:`Notes on subscriptions <notes-on-subscriptions>` for more details.
712 value = getattr(obj, name)
713 except AttributeError:
716 if environment.sandboxed and not \
717 environment.is_safe_attribute(obj, name, value):
718 return environment.unsafe_undefined(obj, name)
720 return environment.undefined(obj=obj, name=name)
725 'replace': do_replace,
730 'forceescape': do_forceescape,
731 'capitalize': do_capitalize,
733 'default': do_default,
737 'dictsort': do_dictsort,
740 'reverse': do_reverse,
744 'capitalize': do_capitalize,
748 'filesizeformat': do_filesizeformat,
750 'truncate': do_truncate,
751 'wordwrap': do_wordwrap,
752 'wordcount': do_wordcount,
755 'string': soft_unicode,
760 'striptags': do_striptags,
766 'groupby': do_groupby,
767 'safe': do_mark_safe,
768 'xmlattr': do_xmlattr