1# -*- coding: utf-8 -*-
2# -*- test-case-name: pytils.test.templatetags.test_numeral -*-
3"""
4pytils.numeral templatetags for Django web-framework
5"""
6
7from django import template, conf
8
9from pytils import numeral
10from pytils.templatetags import init_defaults
11from pytils.third import six
12
13try:
14    # Django 1.4+
15    from django.utils.encoding import smart_text
16except ImportError:
17    from django.utils.encoding import smart_unicode
18    smart_text = smart_unicode
19
20register = template.Library()  #: Django template tag/filter registrator
21encoding = conf.settings.DEFAULT_CHARSET  #: Current charset (sets in Django project's settings)
22debug = conf.settings.DEBUG  #: Debug mode (sets in Django project's settings)
23show_value = getattr(conf.settings, 'PYTILS_SHOW_VALUES_ON_ERROR', False)  #: Show values on errors (sets in Django project's settings)
24
25default_value, default_uvalue = init_defaults(debug, show_value)
26
27# -- filters
28
29def choose_plural(amount, variants):
30    """
31    Choose proper form for plural.
32
33    Value is a amount, parameters are forms of noun.
34    Forms are variants for 1, 2, 5 nouns. It may be tuple
35    of elements, or string where variants separates each other
36    by comma.
37
38    Examples::
39        {{ some_int|choose_plural:"пример,примера,примеров" }}
40    """
41    try:
42        if isinstance(variants, six.string_types):
43            uvariants = smart_text(variants, encoding)
44        else:
45            uvariants = [smart_text(v, encoding) for v in variants]
46        res = numeral.choose_plural(amount, uvariants)
47    except Exception as err:
48        # because filter must die silently
49        try:
50            default_variant = variants
51        except Exception:
52            default_variant = ""
53        res = default_value % {'error': err, 'value': default_variant}
54    return res
55
56def get_plural(amount, variants):
57    """
58    Get proper form for plural and it value.
59
60    Value is a amount, parameters are forms of noun.
61    Forms are variants for 1, 2, 5 nouns. It may be tuple
62    of elements, or string where variants separates each other
63    by comma. You can append 'absence variant' after all over variants
64
65    Examples::
66        {{ some_int|get_plural:"пример,примера,примеров,нет примеров" }}
67    """
68    try:
69        if isinstance(variants, six.string_types):
70            uvariants = smart_text(variants, encoding)
71        else:
72            uvariants = [smart_text(v, encoding) for v in variants]
73        res = numeral._get_plural_legacy(amount, uvariants)
74    except Exception as err:
75        # because filter must die silently
76        try:
77            default_variant = variants
78        except Exception:
79            default_variant = ""
80        res = default_value % {'error': err, 'value': default_variant}
81    return res
82
83def rubles(amount, zero_for_kopeck=False):
84    """Converts float value to in-words representation (for money)"""
85    try:
86        res = numeral.rubles(amount, zero_for_kopeck)
87    except Exception as err:
88        # because filter must die silently
89        res = default_value % {'error': err, 'value': str(amount)}
90    return res
91
92def in_words(amount, gender=None):
93    """
94    In-words representation of amount.
95
96    Parameter is a gender: MALE, FEMALE or NEUTER
97
98    Examples::
99        {{ some_int|in_words }}
100        {{ some_other_int|in_words:FEMALE }}
101    """
102    try:
103        res = numeral.in_words(amount, getattr(numeral, str(gender), None))
104    except Exception as err:
105        # because filter must die silently
106        res = default_value % {'error': err, 'value': str(amount)}
107    return res
108
109# -- register filters
110
111register.filter('choose_plural', choose_plural)
112register.filter('get_plural', get_plural)
113register.filter('rubles', rubles)
114register.filter('in_words', in_words)
115
116# -- tags
117
118def sum_string(amount, gender, items):
119    """
120    in_words and choose_plural in a one flask
121    Makes in-words representation of value with
122    choosing correct form of noun.
123
124    First parameter is an amount of objects. Second is a
125    gender (MALE, FEMALE, NEUTER). Third is a variants
126    of forms for object name.
127
128    Examples::
129        {% sum_string some_int MALE "пример,примера,примеров" %}
130        {% sum_string some_other_int FEMALE "задача,задачи,задач" %}
131    """
132    try:
133        if isinstance(items, six.string_types):
134            uitems = smart_text(items, encoding, default_uvalue)
135        else:
136            uitems = [smart_text(i, encoding) for i in items]
137        res = numeral.sum_string(amount, getattr(numeral, str(gender), None), uitems)
138    except Exception as err:
139        # because tag's renderer must die silently
140        res = default_value % {'error': err, 'value': str(amount)}
141    return res
142
143# -- register tags
144
145register.simple_tag(sum_string)
146