c170f510f2a9fcda735af577b7a34b89706e4154
[jinja2.git] / jinja2 / filters.py
1 # -*- coding: utf-8 -*-
2 """
3     jinja2.filters
4     ~~~~~~~~~~~~~~
5
6     Bundled jinja filters.
7
8     :copyright: (c) 2010 by the Jinja Team.
9     :license: BSD, see LICENSE for more details.
10 """
11 import re
12 import math
13 import urllib
14 from random import choice
15 from operator import itemgetter
16 from itertools import imap, groupby
17 from jinja2.utils import Markup, escape, pformat, urlize, soft_unicode
18 from jinja2.runtime import Undefined
19 from jinja2.exceptions import FilterArgumentError
20
21
22 _word_re = re.compile(r'\w+(?u)')
23
24
25 def contextfilter(f):
26     """Decorator for marking context dependent filters. The current
27     :class:`Context` will be passed as first argument.
28     """
29     f.contextfilter = True
30     return f
31
32
33 def evalcontextfilter(f):
34     """Decorator for marking eval-context dependent filters.  An eval
35     context object is passed as first argument.  For more information
36     about the eval context, see :ref:`eval-context`.
37
38     .. versionadded:: 2.4
39     """
40     f.evalcontextfilter = True
41     return f
42
43
44 def environmentfilter(f):
45     """Decorator for marking evironment dependent filters.  The current
46     :class:`Environment` is passed to the filter as first argument.
47     """
48     f.environmentfilter = True
49     return f
50
51
52 def make_attrgetter(environment, attribute):
53     """Returns a callable that looks up the given attribute from a
54     passed object with the rules of the environment.  Dots are allowed
55     to access attributes of attributes.
56     """
57     if not isinstance(attribute, basestring) or '.' not in attribute:
58         return lambda x: environment.getitem(x, attribute)
59     attribute = attribute.split('.')
60     def attrgetter(item):
61         for part in attribute:
62             item = environment.getitem(item, part)
63         return item
64     return attrgetter
65
66
67 def do_forceescape(value):
68     """Enforce HTML escaping.  This will probably double escape variables."""
69     if hasattr(value, '__html__'):
70         value = value.__html__()
71     return escape(unicode(value))
72
73 def do_urlescape(value):
74     """Escape for use in URLs."""
75     return urllib.quote(value.encode('utf8'))
76
77 @evalcontextfilter
78 def do_replace(eval_ctx, s, old, new, count=None):
79     """Return a copy of the value with all occurrences of a substring
80     replaced with a new one. The first argument is the substring
81     that should be replaced, the second is the replacement string.
82     If the optional third argument ``count`` is given, only the first
83     ``count`` occurrences are replaced:
84
85     .. sourcecode:: jinja
86
87         {{ "Hello World"|replace("Hello", "Goodbye") }}
88             -> Goodbye World
89
90         {{ "aaaaargh"|replace("a", "d'oh, ", 2) }}
91             -> d'oh, d'oh, aaargh
92     """
93     if count is None:
94         count = -1
95     if not eval_ctx.autoescape:
96         return unicode(s).replace(unicode(old), unicode(new), count)
97     if hasattr(old, '__html__') or hasattr(new, '__html__') and \
98        not hasattr(s, '__html__'):
99         s = escape(s)
100     else:
101         s = soft_unicode(s)
102     return s.replace(soft_unicode(old), soft_unicode(new), count)
103
104
105 def do_upper(s):
106     """Convert a value to uppercase."""
107     return soft_unicode(s).upper()
108
109
110 def do_lower(s):
111     """Convert a value to lowercase."""
112     return soft_unicode(s).lower()
113
114
115 @evalcontextfilter
116 def do_xmlattr(_eval_ctx, d, autospace=True):
117     """Create an SGML/XML attribute string based on the items in a dict.
118     All values that are neither `none` nor `undefined` are automatically
119     escaped:
120
121     .. sourcecode:: html+jinja
122
123         <ul{{ {'class': 'my_list', 'missing': none,
124                 'id': 'list-%d'|format(variable)}|xmlattr }}>
125         ...
126         </ul>
127
128     Results in something like this:
129
130     .. sourcecode:: html
131
132         <ul class="my_list" id="list-42">
133         ...
134         </ul>
135
136     As you can see it automatically prepends a space in front of the item
137     if the filter returned something unless the second parameter is false.
138     """
139     rv = u' '.join(
140         u'%s="%s"' % (escape(key), escape(value))
141         for key, value in d.iteritems()
142         if value is not None and not isinstance(value, Undefined)
143     )
144     if autospace and rv:
145         rv = u' ' + rv
146     if _eval_ctx.autoescape:
147         rv = Markup(rv)
148     return rv
149
150
151 def do_capitalize(s):
152     """Capitalize a value. The first character will be uppercase, all others
153     lowercase.
154     """
155     return soft_unicode(s).capitalize()
156
157
158 def do_title(s):
159     """Return a titlecased version of the value. I.e. words will start with
160     uppercase letters, all remaining characters are lowercase.
161     """
162     return soft_unicode(s).title()
163
164
165 def do_dictsort(value, case_sensitive=False, by='key'):
166     """Sort a dict and yield (key, value) pairs. Because python dicts are
167     unsorted you may want to use this function to order them by either
168     key or value:
169
170     .. sourcecode:: jinja
171
172         {% for item in mydict|dictsort %}
173             sort the dict by key, case insensitive
174
175         {% for item in mydict|dicsort(true) %}
176             sort the dict by key, case sensitive
177
178         {% for item in mydict|dictsort(false, 'value') %}
179             sort the dict by key, case insensitive, sorted
180             normally and ordered by value.
181     """
182     if by == 'key':
183         pos = 0
184     elif by == 'value':
185         pos = 1
186     else:
187         raise FilterArgumentError('You can only sort by either '
188                                   '"key" or "value"')
189     def sort_func(item):
190         value = item[pos]
191         if isinstance(value, basestring) and not case_sensitive:
192             value = value.lower()
193         return value
194
195     return sorted(value.items(), key=sort_func)
196
197
198 @environmentfilter
199 def do_sort(environment, value, reverse=False, case_sensitive=False,
200             attribute=None):
201     """Sort an iterable.  Per default it sorts ascending, if you pass it
202     true as first argument it will reverse the sorting.
203
204     If the iterable is made of strings the third parameter can be used to
205     control the case sensitiveness of the comparison which is disabled by
206     default.
207
208     .. sourcecode:: jinja
209
210         {% for item in iterable|sort %}
211             ...
212         {% endfor %}
213
214     It is also possible to sort by an attribute (for example to sort
215     by the date of an object) by specifying the `attribute` parameter:
216
217     .. sourcecode:: jinja
218
219         {% for item in iterable|sort(attribute='date') %}
220             ...
221         {% endfor %}
222
223     .. versionchanged:: 2.6
224        The `attribute` parameter was added.
225     """
226     if not case_sensitive:
227         def sort_func(item):
228             if isinstance(item, basestring):
229                 item = item.lower()
230             return item
231     else:
232         sort_func = None
233     if attribute is not None:
234         getter = make_attrgetter(environment, attribute)
235         def sort_func(item, processor=sort_func or (lambda x: x)):
236             return processor(getter(item))
237     return sorted(value, key=sort_func, reverse=reverse)
238
239
240 def do_default(value, default_value=u'', boolean=False):
241     """If the value is undefined it will return the passed default value,
242     otherwise the value of the variable:
243
244     .. sourcecode:: jinja
245
246         {{ my_variable|default('my_variable is not defined') }}
247
248     This will output the value of ``my_variable`` if the variable was
249     defined, otherwise ``'my_variable is not defined'``. If you want
250     to use default with variables that evaluate to false you have to
251     set the second parameter to `true`:
252
253     .. sourcecode:: jinja
254
255         {{ ''|default('the string was empty', true) }}
256     """
257     if (boolean and not value) or isinstance(value, Undefined):
258         return default_value
259     return value
260
261
262 @evalcontextfilter
263 def do_join(eval_ctx, value, d=u'', attribute=None):
264     """Return a string which is the concatenation of the strings in the
265     sequence. The separator between elements is an empty string per
266     default, you can define it with the optional parameter:
267
268     .. sourcecode:: jinja
269
270         {{ [1, 2, 3]|join('|') }}
271             -> 1|2|3
272
273         {{ [1, 2, 3]|join }}
274             -> 123
275
276     It is also possible to join certain attributes of an object:
277
278     .. sourcecode:: jinja
279
280         {{ users|join(', ', attribute='username') }}
281
282     .. versionadded:: 2.6
283        The `attribute` parameter was added.
284     """
285     if attribute is not None:
286         value = imap(make_attrgetter(eval_ctx.environment, attribute), value)
287
288     # no automatic escaping?  joining is a lot eaiser then
289     if not eval_ctx.autoescape:
290         return unicode(d).join(imap(unicode, value))
291
292     # if the delimiter doesn't have an html representation we check
293     # if any of the items has.  If yes we do a coercion to Markup
294     if not hasattr(d, '__html__'):
295         value = list(value)
296         do_escape = False
297         for idx, item in enumerate(value):
298             if hasattr(item, '__html__'):
299                 do_escape = True
300             else:
301                 value[idx] = unicode(item)
302         if do_escape:
303             d = escape(d)
304         else:
305             d = unicode(d)
306         return d.join(value)
307
308     # no html involved, to normal joining
309     return soft_unicode(d).join(imap(soft_unicode, value))
310
311
312 def do_center(value, width=80):
313     """Centers the value in a field of a given width."""
314     return unicode(value).center(width)
315
316
317 @environmentfilter
318 def do_first(environment, seq):
319     """Return the first item of a sequence."""
320     try:
321         return iter(seq).next()
322     except StopIteration:
323         return environment.undefined('No first item, sequence was empty.')
324
325
326 @environmentfilter
327 def do_last(environment, seq):
328     """Return the last item of a sequence."""
329     try:
330         return iter(reversed(seq)).next()
331     except StopIteration:
332         return environment.undefined('No last item, sequence was empty.')
333
334
335 @environmentfilter
336 def do_random(environment, seq):
337     """Return a random item from the sequence."""
338     try:
339         return choice(seq)
340     except IndexError:
341         return environment.undefined('No random item, sequence was empty.')
342
343
344 def do_filesizeformat(value, binary=False):
345     """Format the value like a 'human-readable' file size (i.e. 13 kB,
346     4.1 MB, 102 Bytes, etc).  Per default decimal prefixes are used (Mega,
347     Giga, etc.), if the second parameter is set to `True` the binary
348     prefixes are used (Mebi, Gibi).
349     """
350     bytes = float(value)
351     base = binary and 1024 or 1000
352     prefixes = [
353         (binary and 'KiB' or 'kB'),
354         (binary and 'MiB' or 'MB'),
355         (binary and 'GiB' or 'GB'),
356         (binary and 'TiB' or 'TB'),
357         (binary and 'PiB' or 'PB'),
358         (binary and 'EiB' or 'EB'),
359         (binary and 'ZiB' or 'ZB'),
360         (binary and 'YiB' or 'YB')
361     ]
362     if bytes == 1:
363         return '1 Byte'
364     elif bytes < base:
365         return '%d Bytes' % bytes
366     else:
367         for i, prefix in enumerate(prefixes):
368             unit = base ** (i + 2)
369             if bytes < unit:
370                 return '%.1f %s' % ((base * bytes / unit), prefix)
371         return '%.1f %s' % ((base * bytes / unit), prefix)
372
373
374 def do_pprint(value, verbose=False):
375     """Pretty print a variable. Useful for debugging.
376
377     With Jinja 1.2 onwards you can pass it a parameter.  If this parameter
378     is truthy the output will be more verbose (this requires `pretty`)
379     """
380     return pformat(value, verbose=verbose)
381
382
383 @evalcontextfilter
384 def do_urlize(eval_ctx, value, trim_url_limit=None, nofollow=False):
385     """Converts URLs in plain text into clickable links.
386
387     If you pass the filter an additional integer it will shorten the urls
388     to that number. Also a third argument exists that makes the urls
389     "nofollow":
390
391     .. sourcecode:: jinja
392
393         {{ mytext|urlize(40, true) }}
394             links are shortened to 40 chars and defined with rel="nofollow"
395     """
396     rv = urlize(value, trim_url_limit, nofollow)
397     if eval_ctx.autoescape:
398         rv = Markup(rv)
399     return rv
400
401
402 def do_indent(s, width=4, indentfirst=False):
403     """Return a copy of the passed string, each line indented by
404     4 spaces. The first line is not indented. If you want to
405     change the number of spaces or indent the first line too
406     you can pass additional parameters to the filter:
407
408     .. sourcecode:: jinja
409
410         {{ mytext|indent(2, true) }}
411             indent by two spaces and indent the first line too.
412     """
413     indention = u' ' * width
414     rv = (u'\n' + indention).join(s.splitlines())
415     if indentfirst:
416         rv = indention + rv
417     return rv
418
419
420 def do_truncate(s, length=255, killwords=False, end='...'):
421     """Return a truncated copy of the string. The length is specified
422     with the first parameter which defaults to ``255``. If the second
423     parameter is ``true`` the filter will cut the text at length. Otherwise
424     it will try to save the last word. If the text was in fact
425     truncated it will append an ellipsis sign (``"..."``). If you want a
426     different ellipsis sign than ``"..."`` you can specify it using the
427     third parameter.
428
429     .. sourcecode jinja::
430
431         {{ mytext|truncate(300, false, '&raquo;') }}
432             truncate mytext to 300 chars, don't split up words, use a
433             right pointing double arrow as ellipsis sign.
434     """
435     if len(s) <= length:
436         return s
437     elif killwords:
438         return s[:length] + end
439     words = s.split(' ')
440     result = []
441     m = 0
442     for word in words:
443         m += len(word) + 1
444         if m > length:
445             break
446         result.append(word)
447     result.append(end)
448     return u' '.join(result)
449
450 @environmentfilter
451 def do_wordwrap(environment, s, width=79, break_long_words=True):
452     """
453     Return a copy of the string passed to the filter wrapped after
454     ``79`` characters.  You can override this default using the first
455     parameter.  If you set the second parameter to `false` Jinja will not
456     split words apart if they are longer than `width`.
457     """
458     import textwrap
459     return environment.newline_sequence.join(textwrap.wrap(s, width=width, expand_tabs=False,
460                                    replace_whitespace=False,
461                                    break_long_words=break_long_words))
462
463
464 def do_wordcount(s):
465     """Count the words in that string."""
466     return len(_word_re.findall(s))
467
468
469 def do_int(value, default=0):
470     """Convert the value into an integer. If the
471     conversion doesn't work it will return ``0``. You can
472     override this default using the first parameter.
473     """
474     try:
475         return int(value)
476     except (TypeError, ValueError):
477         # this quirk is necessary so that "42.23"|int gives 42.
478         try:
479             return int(float(value))
480         except (TypeError, ValueError):
481             return default
482
483
484 def do_float(value, default=0.0):
485     """Convert the value into a floating point number. If the
486     conversion doesn't work it will return ``0.0``. You can
487     override this default using the first parameter.
488     """
489     try:
490         return float(value)
491     except (TypeError, ValueError):
492         return default
493
494
495 def do_format(value, *args, **kwargs):
496     """
497     Apply python string formatting on an object:
498
499     .. sourcecode:: jinja
500
501         {{ "%s - %s"|format("Hello?", "Foo!") }}
502             -> Hello? - Foo!
503     """
504     if args and kwargs:
505         raise FilterArgumentError('can\'t handle positional and keyword '
506                                   'arguments at the same time')
507     return soft_unicode(value) % (kwargs or args)
508
509
510 def do_trim(value):
511     """Strip leading and trailing whitespace."""
512     return soft_unicode(value).strip()
513
514
515 def do_striptags(value):
516     """Strip SGML/XML tags and replace adjacent whitespace by one space.
517     """
518     if hasattr(value, '__html__'):
519         value = value.__html__()
520     return Markup(unicode(value)).striptags()
521
522
523 def do_slice(value, slices, fill_with=None):
524     """Slice an iterator and return a list of lists containing
525     those items. Useful if you want to create a div containing
526     three ul tags that represent columns:
527
528     .. sourcecode:: html+jinja
529
530         <div class="columwrapper">
531           {%- for column in items|slice(3) %}
532             <ul class="column-{{ loop.index }}">
533             {%- for item in column %}
534               <li>{{ item }}</li>
535             {%- endfor %}
536             </ul>
537           {%- endfor %}
538         </div>
539
540     If you pass it a second argument it's used to fill missing
541     values on the last iteration.
542     """
543     seq = list(value)
544     length = len(seq)
545     items_per_slice = length // slices
546     slices_with_extra = length % slices
547     offset = 0
548     for slice_number in xrange(slices):
549         start = offset + slice_number * items_per_slice
550         if slice_number < slices_with_extra:
551             offset += 1
552         end = offset + (slice_number + 1) * items_per_slice
553         tmp = seq[start:end]
554         if fill_with is not None and slice_number >= slices_with_extra:
555             tmp.append(fill_with)
556         yield tmp
557
558
559 def do_batch(value, linecount, fill_with=None):
560     """
561     A filter that batches items. It works pretty much like `slice`
562     just the other way round. It returns a list of lists with the
563     given number of items. If you provide a second parameter this
564     is used to fill missing items. See this example:
565
566     .. sourcecode:: html+jinja
567
568         <table>
569         {%- for row in items|batch(3, '&nbsp;') %}
570           <tr>
571           {%- for column in row %}
572             <td>{{ column }}</td>
573           {%- endfor %}
574           </tr>
575         {%- endfor %}
576         </table>
577     """
578     result = []
579     tmp = []
580     for item in value:
581         if len(tmp) == linecount:
582             yield tmp
583             tmp = []
584         tmp.append(item)
585     if tmp:
586         if fill_with is not None and len(tmp) < linecount:
587             tmp += [fill_with] * (linecount - len(tmp))
588         yield tmp
589
590
591 def do_round(value, precision=0, method='common'):
592     """Round the number to a given precision. The first
593     parameter specifies the precision (default is ``0``), the
594     second the rounding method:
595
596     - ``'common'`` rounds either up or down
597     - ``'ceil'`` always rounds up
598     - ``'floor'`` always rounds down
599
600     If you don't specify a method ``'common'`` is used.
601
602     .. sourcecode:: jinja
603
604         {{ 42.55|round }}
605             -> 43.0
606         {{ 42.55|round(1, 'floor') }}
607             -> 42.5
608
609     Note that even if rounded to 0 precision, a float is returned.  If
610     you need a real integer, pipe it through `int`:
611
612     .. sourcecode:: jinja
613
614         {{ 42.55|round|int }}
615             -> 43
616     """
617     if not method in ('common', 'ceil', 'floor'):
618         raise FilterArgumentError('method must be common, ceil or floor')
619     if method == 'common':
620         return round(value, precision)
621     func = getattr(math, method)
622     return func(value * (10 ** precision)) / (10 ** precision)
623
624
625 @environmentfilter
626 def do_groupby(environment, value, attribute):
627     """Group a sequence of objects by a common attribute.
628
629     If you for example have a list of dicts or objects that represent persons
630     with `gender`, `first_name` and `last_name` attributes and you want to
631     group all users by genders you can do something like the following
632     snippet:
633
634     .. sourcecode:: html+jinja
635
636         <ul>
637         {% for group in persons|groupby('gender') %}
638             <li>{{ group.grouper }}<ul>
639             {% for person in group.list %}
640                 <li>{{ person.first_name }} {{ person.last_name }}</li>
641             {% endfor %}</ul></li>
642         {% endfor %}
643         </ul>
644
645     Additionally it's possible to use tuple unpacking for the grouper and
646     list:
647
648     .. sourcecode:: html+jinja
649
650         <ul>
651         {% for grouper, list in persons|groupby('gender') %}
652             ...
653         {% endfor %}
654         </ul>
655
656     As you can see the item we're grouping by is stored in the `grouper`
657     attribute and the `list` contains all the objects that have this grouper
658     in common.
659
660     .. versionchanged:: 2.6
661        It's now possible to use dotted notation to group by the child
662        attribute of another attribute.
663     """
664     expr = make_attrgetter(environment, attribute)
665     return sorted(map(_GroupTuple, groupby(sorted(value, key=expr), expr)))
666
667
668 class _GroupTuple(tuple):
669     __slots__ = ()
670     grouper = property(itemgetter(0))
671     list = property(itemgetter(1))
672
673     def __new__(cls, (key, value)):
674         return tuple.__new__(cls, (key, list(value)))
675
676
677 @environmentfilter
678 def do_sum(environment, iterable, attribute=None, start=0):
679     """Returns the sum of a sequence of numbers plus the value of parameter
680     'start' (which defaults to 0).  When the sequence is empty it returns
681     start.
682
683     It is also possible to sum up only certain attributes:
684
685     .. sourcecode:: jinja
686
687         Total: {{ items|sum(attribute='price') }}
688
689     .. versionchanged:: 2.6
690        The `attribute` parameter was added to allow suming up over
691        attributes.  Also the `start` parameter was moved on to the right.
692     """
693     if attribute is not None:
694         iterable = imap(make_attrgetter(environment, attribute), iterable)
695     return sum(iterable, start)
696
697
698 def do_list(value):
699     """Convert the value into a list.  If it was a string the returned list
700     will be a list of characters.
701     """
702     return list(value)
703
704
705 def do_mark_safe(value):
706     """Mark the value as safe which means that in an environment with automatic
707     escaping enabled this variable will not be escaped.
708     """
709     return Markup(value)
710
711
712 def do_mark_unsafe(value):
713     """Mark a value as unsafe.  This is the reverse operation for :func:`safe`."""
714     return unicode(value)
715
716
717 def do_reverse(value):
718     """Reverse the object or return an iterator the iterates over it the other
719     way round.
720     """
721     if isinstance(value, basestring):
722         return value[::-1]
723     try:
724         return reversed(value)
725     except TypeError:
726         try:
727             rv = list(value)
728             rv.reverse()
729             return rv
730         except TypeError:
731             raise FilterArgumentError('argument must be iterable')
732
733
734 @environmentfilter
735 def do_attr(environment, obj, name):
736     """Get an attribute of an object.  ``foo|attr("bar")`` works like
737     ``foo["bar"]`` just that always an attribute is returned and items are not
738     looked up.
739
740     See :ref:`Notes on subscriptions <notes-on-subscriptions>` for more details.
741     """
742     try:
743         name = str(name)
744     except UnicodeError:
745         pass
746     else:
747         try:
748             value = getattr(obj, name)
749         except AttributeError:
750             pass
751         else:
752             if environment.sandboxed and not \
753                environment.is_safe_attribute(obj, name, value):
754                 return environment.unsafe_undefined(obj, name)
755             return value
756     return environment.undefined(obj=obj, name=name)
757
758
759 FILTERS = {
760     'attr':                 do_attr,
761     'replace':              do_replace,
762     'upper':                do_upper,
763     'lower':                do_lower,
764     'escape':               escape,
765     'e':                    escape,
766     'forceescape':          do_forceescape,
767     'capitalize':           do_capitalize,
768     'title':                do_title,
769     'default':              do_default,
770     'd':                    do_default,
771     'join':                 do_join,
772     'count':                len,
773     'dictsort':             do_dictsort,
774     'sort':                 do_sort,
775     'length':               len,
776     'reverse':              do_reverse,
777     'center':               do_center,
778     'indent':               do_indent,
779     'title':                do_title,
780     'capitalize':           do_capitalize,
781     'first':                do_first,
782     'last':                 do_last,
783     'random':               do_random,
784     'filesizeformat':       do_filesizeformat,
785     'pprint':               do_pprint,
786     'truncate':             do_truncate,
787     'wordwrap':             do_wordwrap,
788     'wordcount':            do_wordcount,
789     'int':                  do_int,
790     'float':                do_float,
791     'string':               soft_unicode,
792     'list':                 do_list,
793     'urlize':               do_urlize,
794     'format':               do_format,
795     'trim':                 do_trim,
796     'striptags':            do_striptags,
797     'slice':                do_slice,
798     'batch':                do_batch,
799     'sum':                  do_sum,
800     'abs':                  abs,
801     'round':                do_round,
802     'groupby':              do_groupby,
803     'safe':                 do_mark_safe,
804     'xmlattr':              do_xmlattr,
805     'urlescape':            do_urlescape,
806     'urle':                 do_urlescape,
807     'urlencode':            do_urlescape,
808     'urlquote':             do_urlescape
809 }