Coverage for /var/srv/projects/api.amasfac.comuna18.com/tmp/venv/lib/python3.9/site-packages/django/template/defaultfilters.py: 28%
507 statements
« prev ^ index » next coverage.py v6.4.4, created at 2023-07-17 14:22 -0600
« prev ^ index » next coverage.py v6.4.4, created at 2023-07-17 14:22 -0600
1"""Default variable filters."""
2import random as random_module
3import re
4import types
5from decimal import ROUND_HALF_UP, Context, Decimal, InvalidOperation
6from functools import wraps
7from operator import itemgetter
8from pprint import pformat
9from urllib.parse import quote
11from django.utils import formats
12from django.utils.dateformat import format, time_format
13from django.utils.encoding import iri_to_uri
14from django.utils.html import avoid_wrapping, conditional_escape, escape, escapejs
15from django.utils.html import json_script as _json_script
16from django.utils.html import linebreaks, strip_tags
17from django.utils.html import urlize as _urlize
18from django.utils.safestring import SafeData, mark_safe
19from django.utils.text import Truncator, normalize_newlines, phone2numeric
20from django.utils.text import slugify as _slugify
21from django.utils.text import wrap
22from django.utils.timesince import timesince, timeuntil
23from django.utils.translation import gettext, ngettext
25from .base import VARIABLE_ATTRIBUTE_SEPARATOR
26from .library import Library
28register = Library()
31#######################
32# STRING DECORATOR #
33#######################
36def stringfilter(func):
37 """
38 Decorator for filters which should only receive strings. The object
39 passed as the first positional argument will be converted to a string.
40 """
42 def _dec(*args, **kwargs):
43 args = list(args)
44 args[0] = str(args[0])
45 if isinstance(args[0], SafeData) and getattr(
46 _dec._decorated_function, "is_safe", False
47 ):
48 return mark_safe(func(*args, **kwargs))
49 return func(*args, **kwargs)
51 # Include a reference to the real function (used to check original
52 # arguments by the template parser, and to bear the 'is_safe' attribute
53 # when multiple decorators are applied).
54 _dec._decorated_function = getattr(func, "_decorated_function", func)
56 return wraps(func)(_dec)
59###################
60# STRINGS #
61###################
64@register.filter(is_safe=True)
65@stringfilter
66def addslashes(value):
67 """
68 Add slashes before quotes. Useful for escaping strings in CSV, for
69 example. Less useful for escaping JavaScript; use the ``escapejs``
70 filter instead.
71 """
72 return value.replace("\\", "\\\\").replace('"', '\\"').replace("'", "\\'")
75@register.filter(is_safe=True)
76@stringfilter
77def capfirst(value):
78 """Capitalize the first character of the value."""
79 return value and value[0].upper() + value[1:]
82@register.filter("escapejs")
83@stringfilter
84def escapejs_filter(value):
85 """Hex encode characters for use in JavaScript strings."""
86 return escapejs(value)
89@register.filter(is_safe=True)
90def json_script(value, element_id):
91 """
92 Output value JSON-encoded, wrapped in a <script type="application/json">
93 tag.
94 """
95 return _json_script(value, element_id)
98@register.filter(is_safe=True)
99def floatformat(text, arg=-1):
100 """
101 Display a float to a specified number of decimal places.
103 If called without an argument, display the floating point number with one
104 decimal place -- but only if there's a decimal place to be displayed:
106 * num1 = 34.23234
107 * num2 = 34.00000
108 * num3 = 34.26000
109 * {{ num1|floatformat }} displays "34.2"
110 * {{ num2|floatformat }} displays "34"
111 * {{ num3|floatformat }} displays "34.3"
113 If arg is positive, always display exactly arg number of decimal places:
115 * {{ num1|floatformat:3 }} displays "34.232"
116 * {{ num2|floatformat:3 }} displays "34.000"
117 * {{ num3|floatformat:3 }} displays "34.260"
119 If arg is negative, display arg number of decimal places -- but only if
120 there are places to be displayed:
122 * {{ num1|floatformat:"-3" }} displays "34.232"
123 * {{ num2|floatformat:"-3" }} displays "34"
124 * {{ num3|floatformat:"-3" }} displays "34.260"
126 If arg has the 'g' suffix, force the result to be grouped by the
127 THOUSAND_SEPARATOR for the active locale. When the active locale is
128 en (English):
130 * {{ 6666.6666|floatformat:"2g" }} displays "6,666.67"
131 * {{ 10000|floatformat:"g" }} displays "10,000"
133 If arg has the 'u' suffix, force the result to be unlocalized. When the
134 active locale is pl (Polish):
136 * {{ 66666.6666|floatformat:"2" }} displays "66666,67"
137 * {{ 66666.6666|floatformat:"2u" }} displays "66666.67"
139 If the input float is infinity or NaN, display the string representation
140 of that value.
141 """
142 force_grouping = False
143 use_l10n = True
144 if isinstance(arg, str):
145 last_char = arg[-1]
146 if arg[-2:] in {"gu", "ug"}:
147 force_grouping = True
148 use_l10n = False
149 arg = arg[:-2] or -1
150 elif last_char == "g":
151 force_grouping = True
152 arg = arg[:-1] or -1
153 elif last_char == "u":
154 use_l10n = False
155 arg = arg[:-1] or -1
156 try:
157 input_val = repr(text)
158 d = Decimal(input_val)
159 except InvalidOperation:
160 try:
161 d = Decimal(str(float(text)))
162 except (ValueError, InvalidOperation, TypeError):
163 return ""
164 try:
165 p = int(arg)
166 except ValueError:
167 return input_val
169 try:
170 m = int(d) - d
171 except (ValueError, OverflowError, InvalidOperation):
172 return input_val
174 if not m and p < 0:
175 return mark_safe(
176 formats.number_format(
177 "%d" % (int(d)),
178 0,
179 use_l10n=use_l10n,
180 force_grouping=force_grouping,
181 )
182 )
184 exp = Decimal(1).scaleb(-abs(p))
185 # Set the precision high enough to avoid an exception (#15789).
186 tupl = d.as_tuple()
187 units = len(tupl[1])
188 units += -tupl[2] if m else tupl[2]
189 prec = abs(p) + units + 1
191 # Avoid conversion to scientific notation by accessing `sign`, `digits`,
192 # and `exponent` from Decimal.as_tuple() directly.
193 rounded_d = d.quantize(exp, ROUND_HALF_UP, Context(prec=prec))
194 sign, digits, exponent = rounded_d.as_tuple()
195 digits = [str(digit) for digit in reversed(digits)]
196 while len(digits) <= abs(exponent):
197 digits.append("0")
198 digits.insert(-exponent, ".")
199 if sign and rounded_d:
200 digits.append("-")
201 number = "".join(reversed(digits))
202 return mark_safe(
203 formats.number_format(
204 number,
205 abs(p),
206 use_l10n=use_l10n,
207 force_grouping=force_grouping,
208 )
209 )
212@register.filter(is_safe=True)
213@stringfilter
214def iriencode(value):
215 """Escape an IRI value for use in a URL."""
216 return iri_to_uri(value)
219@register.filter(is_safe=True, needs_autoescape=True)
220@stringfilter
221def linenumbers(value, autoescape=True):
222 """Display text with line numbers."""
223 lines = value.split("\n")
224 # Find the maximum width of the line count, for use with zero padding
225 # string format command
226 width = str(len(str(len(lines))))
227 if not autoescape or isinstance(value, SafeData):
228 for i, line in enumerate(lines):
229 lines[i] = ("%0" + width + "d. %s") % (i + 1, line)
230 else:
231 for i, line in enumerate(lines):
232 lines[i] = ("%0" + width + "d. %s") % (i + 1, escape(line))
233 return mark_safe("\n".join(lines))
236@register.filter(is_safe=True)
237@stringfilter
238def lower(value):
239 """Convert a string into all lowercase."""
240 return value.lower()
243@register.filter(is_safe=False)
244@stringfilter
245def make_list(value):
246 """
247 Return the value turned into a list.
249 For an integer, it's a list of digits.
250 For a string, it's a list of characters.
251 """
252 return list(value)
255@register.filter(is_safe=True)
256@stringfilter
257def slugify(value):
258 """
259 Convert to ASCII. Convert spaces to hyphens. Remove characters that aren't
260 alphanumerics, underscores, or hyphens. Convert to lowercase. Also strip
261 leading and trailing whitespace.
262 """
263 return _slugify(value)
266@register.filter(is_safe=True)
267def stringformat(value, arg):
268 """
269 Format the variable according to the arg, a string formatting specifier.
271 This specifier uses Python string formatting syntax, with the exception
272 that the leading "%" is dropped.
274 See https://docs.python.org/library/stdtypes.html#printf-style-string-formatting
275 for documentation of Python string formatting.
276 """
277 if isinstance(value, tuple):
278 value = str(value)
279 try:
280 return ("%" + str(arg)) % value
281 except (ValueError, TypeError):
282 return ""
285@register.filter(is_safe=True)
286@stringfilter
287def title(value):
288 """Convert a string into titlecase."""
289 t = re.sub("([a-z])'([A-Z])", lambda m: m[0].lower(), value.title())
290 return re.sub(r"\d([A-Z])", lambda m: m[0].lower(), t)
293@register.filter(is_safe=True)
294@stringfilter
295def truncatechars(value, arg):
296 """Truncate a string after `arg` number of characters."""
297 try:
298 length = int(arg)
299 except ValueError: # Invalid literal for int().
300 return value # Fail silently.
301 return Truncator(value).chars(length)
304@register.filter(is_safe=True)
305@stringfilter
306def truncatechars_html(value, arg):
307 """
308 Truncate HTML after `arg` number of chars.
309 Preserve newlines in the HTML.
310 """
311 try:
312 length = int(arg)
313 except ValueError: # invalid literal for int()
314 return value # Fail silently.
315 return Truncator(value).chars(length, html=True)
318@register.filter(is_safe=True)
319@stringfilter
320def truncatewords(value, arg):
321 """
322 Truncate a string after `arg` number of words.
323 Remove newlines within the string.
324 """
325 try:
326 length = int(arg)
327 except ValueError: # Invalid literal for int().
328 return value # Fail silently.
329 return Truncator(value).words(length, truncate=" …")
332@register.filter(is_safe=True)
333@stringfilter
334def truncatewords_html(value, arg):
335 """
336 Truncate HTML after `arg` number of words.
337 Preserve newlines in the HTML.
338 """
339 try:
340 length = int(arg)
341 except ValueError: # invalid literal for int()
342 return value # Fail silently.
343 return Truncator(value).words(length, html=True, truncate=" …")
346@register.filter(is_safe=False)
347@stringfilter
348def upper(value):
349 """Convert a string into all uppercase."""
350 return value.upper()
353@register.filter(is_safe=False)
354@stringfilter
355def urlencode(value, safe=None):
356 """
357 Escape a value for use in a URL.
359 The ``safe`` parameter determines the characters which should not be
360 escaped by Python's quote() function. If not provided, use the default safe
361 characters (but an empty string can be provided when *all* characters
362 should be escaped).
363 """
364 kwargs = {}
365 if safe is not None:
366 kwargs["safe"] = safe
367 return quote(value, **kwargs)
370@register.filter(is_safe=True, needs_autoescape=True)
371@stringfilter
372def urlize(value, autoescape=True):
373 """Convert URLs in plain text into clickable links."""
374 return mark_safe(_urlize(value, nofollow=True, autoescape=autoescape))
377@register.filter(is_safe=True, needs_autoescape=True)
378@stringfilter
379def urlizetrunc(value, limit, autoescape=True):
380 """
381 Convert URLs into clickable links, truncating URLs to the given character
382 limit, and adding 'rel=nofollow' attribute to discourage spamming.
384 Argument: Length to truncate URLs to.
385 """
386 return mark_safe(
387 _urlize(value, trim_url_limit=int(limit), nofollow=True, autoescape=autoescape)
388 )
391@register.filter(is_safe=False)
392@stringfilter
393def wordcount(value):
394 """Return the number of words."""
395 return len(value.split())
398@register.filter(is_safe=True)
399@stringfilter
400def wordwrap(value, arg):
401 """Wrap words at `arg` line length."""
402 return wrap(value, int(arg))
405@register.filter(is_safe=True)
406@stringfilter
407def ljust(value, arg):
408 """Left-align the value in a field of a given width."""
409 return value.ljust(int(arg))
412@register.filter(is_safe=True)
413@stringfilter
414def rjust(value, arg):
415 """Right-align the value in a field of a given width."""
416 return value.rjust(int(arg))
419@register.filter(is_safe=True)
420@stringfilter
421def center(value, arg):
422 """Center the value in a field of a given width."""
423 return value.center(int(arg))
426@register.filter
427@stringfilter
428def cut(value, arg):
429 """Remove all values of arg from the given string."""
430 safe = isinstance(value, SafeData)
431 value = value.replace(arg, "")
432 if safe and arg != ";":
433 return mark_safe(value)
434 return value
437###################
438# HTML STRINGS #
439###################
442@register.filter("escape", is_safe=True)
443@stringfilter
444def escape_filter(value):
445 """Mark the value as a string that should be auto-escaped."""
446 return conditional_escape(value)
449@register.filter(is_safe=True)
450@stringfilter
451def force_escape(value):
452 """
453 Escape a string's HTML. Return a new string containing the escaped
454 characters (as opposed to "escape", which marks the content for later
455 possible escaping).
456 """
457 return escape(value)
460@register.filter("linebreaks", is_safe=True, needs_autoescape=True)
461@stringfilter
462def linebreaks_filter(value, autoescape=True):
463 """
464 Replace line breaks in plain text with appropriate HTML; a single
465 newline becomes an HTML line break (``<br>``) and a new line
466 followed by a blank line becomes a paragraph break (``</p>``).
467 """
468 autoescape = autoescape and not isinstance(value, SafeData)
469 return mark_safe(linebreaks(value, autoescape))
472@register.filter(is_safe=True, needs_autoescape=True)
473@stringfilter
474def linebreaksbr(value, autoescape=True):
475 """
476 Convert all newlines in a piece of plain text to HTML line breaks
477 (``<br>``).
478 """
479 autoescape = autoescape and not isinstance(value, SafeData)
480 value = normalize_newlines(value)
481 if autoescape:
482 value = escape(value)
483 return mark_safe(value.replace("\n", "<br>"))
486@register.filter(is_safe=True)
487@stringfilter
488def safe(value):
489 """Mark the value as a string that should not be auto-escaped."""
490 return mark_safe(value)
493@register.filter(is_safe=True)
494def safeseq(value):
495 """
496 A "safe" filter for sequences. Mark each element in the sequence,
497 individually, as safe, after converting them to strings. Return a list
498 with the results.
499 """
500 return [mark_safe(obj) for obj in value]
503@register.filter(is_safe=True)
504@stringfilter
505def striptags(value):
506 """Strip all [X]HTML tags."""
507 return strip_tags(value)
510###################
511# LISTS #
512###################
515def _property_resolver(arg):
516 """
517 When arg is convertible to float, behave like operator.itemgetter(arg)
518 Otherwise, chain __getitem__() and getattr().
520 >>> _property_resolver(1)('abc')
521 'b'
522 >>> _property_resolver('1')('abc')
523 Traceback (most recent call last):
524 ...
525 TypeError: string indices must be integers
526 >>> class Foo:
527 ... a = 42
528 ... b = 3.14
529 ... c = 'Hey!'
530 >>> _property_resolver('b')(Foo())
531 3.14
532 """
533 try:
534 float(arg)
535 except ValueError:
536 if VARIABLE_ATTRIBUTE_SEPARATOR + "_" in arg or arg[0] == "_":
537 raise AttributeError("Access to private variables is forbidden.")
538 parts = arg.split(VARIABLE_ATTRIBUTE_SEPARATOR)
540 def resolve(value):
541 for part in parts:
542 try:
543 value = value[part]
544 except (AttributeError, IndexError, KeyError, TypeError, ValueError):
545 value = getattr(value, part)
546 return value
548 return resolve
549 else:
550 return itemgetter(arg)
553@register.filter(is_safe=False)
554def dictsort(value, arg):
555 """
556 Given a list of dicts, return that list sorted by the property given in
557 the argument.
558 """
559 try:
560 return sorted(value, key=_property_resolver(arg))
561 except (AttributeError, TypeError):
562 return ""
565@register.filter(is_safe=False)
566def dictsortreversed(value, arg):
567 """
568 Given a list of dicts, return that list sorted in reverse order by the
569 property given in the argument.
570 """
571 try:
572 return sorted(value, key=_property_resolver(arg), reverse=True)
573 except (AttributeError, TypeError):
574 return ""
577@register.filter(is_safe=False)
578def first(value):
579 """Return the first item in a list."""
580 try:
581 return value[0]
582 except IndexError:
583 return ""
586@register.filter(is_safe=True, needs_autoescape=True)
587def join(value, arg, autoescape=True):
588 """Join a list with a string, like Python's ``str.join(list)``."""
589 try:
590 if autoescape:
591 value = [conditional_escape(v) for v in value]
592 data = conditional_escape(arg).join(value)
593 except TypeError: # Fail silently if arg isn't iterable.
594 return value
595 return mark_safe(data)
598@register.filter(is_safe=True)
599def last(value):
600 """Return the last item in a list."""
601 try:
602 return value[-1]
603 except IndexError:
604 return ""
607@register.filter(is_safe=False)
608def length(value):
609 """Return the length of the value - useful for lists."""
610 try:
611 return len(value)
612 except (ValueError, TypeError):
613 return 0
616@register.filter(is_safe=False)
617def length_is(value, arg):
618 """Return a boolean of whether the value's length is the argument."""
619 try:
620 return len(value) == int(arg)
621 except (ValueError, TypeError):
622 return ""
625@register.filter(is_safe=True)
626def random(value):
627 """Return a random item from the list."""
628 return random_module.choice(value)
631@register.filter("slice", is_safe=True)
632def slice_filter(value, arg):
633 """
634 Return a slice of the list using the same syntax as Python's list slicing.
635 """
636 try:
637 bits = []
638 for x in str(arg).split(":"):
639 if not x:
640 bits.append(None)
641 else:
642 bits.append(int(x))
643 return value[slice(*bits)]
645 except (ValueError, TypeError):
646 return value # Fail silently.
649@register.filter(is_safe=True, needs_autoescape=True)
650def unordered_list(value, autoescape=True):
651 """
652 Recursively take a self-nested list and return an HTML unordered list --
653 WITHOUT opening and closing <ul> tags.
655 Assume the list is in the proper format. For example, if ``var`` contains:
656 ``['States', ['Kansas', ['Lawrence', 'Topeka'], 'Illinois']]``, then
657 ``{{ var|unordered_list }}`` returns::
659 <li>States
660 <ul>
661 <li>Kansas
662 <ul>
663 <li>Lawrence</li>
664 <li>Topeka</li>
665 </ul>
666 </li>
667 <li>Illinois</li>
668 </ul>
669 </li>
670 """
671 if autoescape:
672 escaper = conditional_escape
673 else:
675 def escaper(x):
676 return x
678 def walk_items(item_list):
679 item_iterator = iter(item_list)
680 try:
681 item = next(item_iterator)
682 while True:
683 try:
684 next_item = next(item_iterator)
685 except StopIteration:
686 yield item, None
687 break
688 if isinstance(next_item, (list, tuple, types.GeneratorType)):
689 try:
690 iter(next_item)
691 except TypeError:
692 pass
693 else:
694 yield item, next_item
695 item = next(item_iterator)
696 continue
697 yield item, None
698 item = next_item
699 except StopIteration:
700 pass
702 def list_formatter(item_list, tabs=1):
703 indent = "\t" * tabs
704 output = []
705 for item, children in walk_items(item_list):
706 sublist = ""
707 if children:
708 sublist = "\n%s<ul>\n%s\n%s</ul>\n%s" % (
709 indent,
710 list_formatter(children, tabs + 1),
711 indent,
712 indent,
713 )
714 output.append("%s<li>%s%s</li>" % (indent, escaper(item), sublist))
715 return "\n".join(output)
717 return mark_safe(list_formatter(value))
720###################
721# INTEGERS #
722###################
725@register.filter(is_safe=False)
726def add(value, arg):
727 """Add the arg to the value."""
728 try:
729 return int(value) + int(arg)
730 except (ValueError, TypeError):
731 try:
732 return value + arg
733 except Exception:
734 return ""
737@register.filter(is_safe=False)
738def get_digit(value, arg):
739 """
740 Given a whole number, return the requested digit of it, where 1 is the
741 right-most digit, 2 is the second-right-most digit, etc. Return the
742 original value for invalid input (if input or argument is not an integer,
743 or if argument is less than 1). Otherwise, output is always an integer.
744 """
745 try:
746 arg = int(arg)
747 value = int(value)
748 except ValueError:
749 return value # Fail silently for an invalid argument
750 if arg < 1:
751 return value
752 try:
753 return int(str(value)[-arg])
754 except IndexError:
755 return 0
758###################
759# DATES #
760###################
763@register.filter(expects_localtime=True, is_safe=False)
764def date(value, arg=None):
765 """Format a date according to the given format."""
766 if value in (None, ""):
767 return ""
768 try:
769 return formats.date_format(value, arg)
770 except AttributeError:
771 try:
772 return format(value, arg)
773 except AttributeError:
774 return ""
777@register.filter(expects_localtime=True, is_safe=False)
778def time(value, arg=None):
779 """Format a time according to the given format."""
780 if value in (None, ""):
781 return ""
782 try:
783 return formats.time_format(value, arg)
784 except (AttributeError, TypeError):
785 try:
786 return time_format(value, arg)
787 except (AttributeError, TypeError):
788 return ""
791@register.filter("timesince", is_safe=False)
792def timesince_filter(value, arg=None):
793 """Format a date as the time since that date (i.e. "4 days, 6 hours")."""
794 if not value:
795 return ""
796 try:
797 if arg:
798 return timesince(value, arg)
799 return timesince(value)
800 except (ValueError, TypeError):
801 return ""
804@register.filter("timeuntil", is_safe=False)
805def timeuntil_filter(value, arg=None):
806 """Format a date as the time until that date (i.e. "4 days, 6 hours")."""
807 if not value:
808 return ""
809 try:
810 return timeuntil(value, arg)
811 except (ValueError, TypeError):
812 return ""
815###################
816# LOGIC #
817###################
820@register.filter(is_safe=False)
821def default(value, arg):
822 """If value is unavailable, use given default."""
823 return value or arg
826@register.filter(is_safe=False)
827def default_if_none(value, arg):
828 """If value is None, use given default."""
829 if value is None:
830 return arg
831 return value
834@register.filter(is_safe=False)
835def divisibleby(value, arg):
836 """Return True if the value is divisible by the argument."""
837 return int(value) % int(arg) == 0
840@register.filter(is_safe=False)
841def yesno(value, arg=None):
842 """
843 Given a string mapping values for true, false, and (optionally) None,
844 return one of those strings according to the value:
846 ========== ====================== ==================================
847 Value Argument Outputs
848 ========== ====================== ==================================
849 ``True`` ``"yeah,no,maybe"`` ``yeah``
850 ``False`` ``"yeah,no,maybe"`` ``no``
851 ``None`` ``"yeah,no,maybe"`` ``maybe``
852 ``None`` ``"yeah,no"`` ``"no"`` (converts None to False
853 if no mapping for None is given.
854 ========== ====================== ==================================
855 """
856 if arg is None:
857 # Translators: Please do not add spaces around commas.
858 arg = gettext("yes,no,maybe")
859 bits = arg.split(",")
860 if len(bits) < 2:
861 return value # Invalid arg.
862 try:
863 yes, no, maybe = bits
864 except ValueError:
865 # Unpack list of wrong size (no "maybe" value provided).
866 yes, no, maybe = bits[0], bits[1], bits[1]
867 if value is None:
868 return maybe
869 if value:
870 return yes
871 return no
874###################
875# MISC #
876###################
879@register.filter(is_safe=True)
880def filesizeformat(bytes_):
881 """
882 Format the value like a 'human-readable' file size (i.e. 13 KB, 4.1 MB,
883 102 bytes, etc.).
884 """
885 try:
886 bytes_ = int(bytes_)
887 except (TypeError, ValueError, UnicodeDecodeError):
888 value = ngettext("%(size)d byte", "%(size)d bytes", 0) % {"size": 0}
889 return avoid_wrapping(value)
891 def filesize_number_format(value):
892 return formats.number_format(round(value, 1), 1)
894 KB = 1 << 10
895 MB = 1 << 20
896 GB = 1 << 30
897 TB = 1 << 40
898 PB = 1 << 50
900 negative = bytes_ < 0
901 if negative:
902 bytes_ = -bytes_ # Allow formatting of negative numbers.
904 if bytes_ < KB:
905 value = ngettext("%(size)d byte", "%(size)d bytes", bytes_) % {"size": bytes_}
906 elif bytes_ < MB:
907 value = gettext("%s KB") % filesize_number_format(bytes_ / KB)
908 elif bytes_ < GB:
909 value = gettext("%s MB") % filesize_number_format(bytes_ / MB)
910 elif bytes_ < TB:
911 value = gettext("%s GB") % filesize_number_format(bytes_ / GB)
912 elif bytes_ < PB:
913 value = gettext("%s TB") % filesize_number_format(bytes_ / TB)
914 else:
915 value = gettext("%s PB") % filesize_number_format(bytes_ / PB)
917 if negative:
918 value = "-%s" % value
919 return avoid_wrapping(value)
922@register.filter(is_safe=False)
923def pluralize(value, arg="s"):
924 """
925 Return a plural suffix if the value is not 1, '1', or an object of
926 length 1. By default, use 's' as the suffix:
928 * If value is 0, vote{{ value|pluralize }} display "votes".
929 * If value is 1, vote{{ value|pluralize }} display "vote".
930 * If value is 2, vote{{ value|pluralize }} display "votes".
932 If an argument is provided, use that string instead:
934 * If value is 0, class{{ value|pluralize:"es" }} display "classes".
935 * If value is 1, class{{ value|pluralize:"es" }} display "class".
936 * If value is 2, class{{ value|pluralize:"es" }} display "classes".
938 If the provided argument contains a comma, use the text before the comma
939 for the singular case and the text after the comma for the plural case:
941 * If value is 0, cand{{ value|pluralize:"y,ies" }} display "candies".
942 * If value is 1, cand{{ value|pluralize:"y,ies" }} display "candy".
943 * If value is 2, cand{{ value|pluralize:"y,ies" }} display "candies".
944 """
945 if "," not in arg:
946 arg = "," + arg
947 bits = arg.split(",")
948 if len(bits) > 2:
949 return ""
950 singular_suffix, plural_suffix = bits[:2]
952 try:
953 return singular_suffix if float(value) == 1 else plural_suffix
954 except ValueError: # Invalid string that's not a number.
955 pass
956 except TypeError: # Value isn't a string or a number; maybe it's a list?
957 try:
958 return singular_suffix if len(value) == 1 else plural_suffix
959 except TypeError: # len() of unsized object.
960 pass
961 return ""
964@register.filter("phone2numeric", is_safe=True)
965def phone2numeric_filter(value):
966 """Take a phone number and converts it in to its numerical equivalent."""
967 return phone2numeric(value)
970@register.filter(is_safe=True)
971def pprint(value):
972 """A wrapper around pprint.pprint -- for debugging, really."""
973 try:
974 return pformat(value)
975 except Exception as e:
976 return "Error in formatting: %s: %s" % (e.__class__.__name__, e)