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