def extract_operands(source):
"""Extract operands from a decimal, a float or an int, according to `CLDR rules`_.
- The result is a 6-tuple (n, i, v, w, f, t), where those symbols are as follows:
+ The result is a 8-tuple (n, i, v, w, f, t, c, e), where those symbols are as follows:
====== ===============================================================
Symbol Value
w number of visible fraction digits in n, without trailing zeros.
f visible fractional digits in n, with trailing zeros.
t visible fractional digits in n, without trailing zeros.
+ c compact decimal exponent value: exponent of the power of 10 used in compact decimal formatting.
+ e currently, synonym for ācā. however, may be redefined in the future.
====== ===============================================================
- .. _`CLDR rules`: https://www.unicode.org/reports/tr35/tr35-33/tr35-numbers.html#Operands
+ .. _`CLDR rules`: https://www.unicode.org/reports/tr35/tr35-61/tr35-numbers.html#Operands
:param source: A real number
:type source: int|float|decimal.Decimal
- :return: A n-i-v-w-f-t tuple
- :rtype: tuple[decimal.Decimal, int, int, int, int, int]
+ :return: A n-i-v-w-f-t-c-e tuple
+ :rtype: tuple[decimal.Decimal, int, int, int, int, int, int, int]
"""
n = abs(source)
i = int(n)
t = int(no_trailing or 0)
else:
v = w = f = t = 0
- return n, i, v, w, f, t
+ c = e = 0 # TODO: c and e are not supported
+ return n, i, v, w, f, t, c, e
class PluralRule(object):
to_python_func = _PythonCompiler().compile
result = [
'def evaluate(n):',
- ' n, i, v, w, f, t = extract_operands(n)',
+ ' n, i, v, w, f, t, c, e = extract_operands(n)',
]
for tag, ast in PluralRule.parse(rule).abstract:
# the str() call is to coerce the tag to the native string. It's
class RuleError(Exception):
"""Raised if a rule is malformed."""
-_VARS = 'nivwft'
+_VARS = {
+ 'n', # absolute value of the source number.
+ 'i', # integer digits of n.
+ 'v', # number of visible fraction digits in n, with trailing zeros.*
+ 'w', # number of visible fraction digits in n, without trailing zeros.*
+ 'f', # visible fraction digits in n, with trailing zeros.*
+ 't', # visible fraction digits in n, without trailing zeros.*
+ 'c', # compact decimal exponent value: exponent of the power of 10 used in compact decimal formatting.
+ 'e', # currently, synonym for ācā. however, may be redefined in the future.
+}
_RULES = [
(None, re.compile(r'\s+', re.UNICODE)),
- ('word', re.compile(r'\b(and|or|is|(?:with)?in|not|mod|[{0}])\b'
- .format(_VARS))),
+ ('word', re.compile(fr'\b(and|or|is|(?:with)?in|not|mod|[{"".join(_VARS)}])\b')),
('value', re.compile(r'\d+')),
('symbol', re.compile(r'%|,|!=|=')),
('ellipsis', re.compile(r'\.{2,3}|\u2026', re.UNICODE)) # U+2026: ELLIPSIS
compile_w = lambda x: 'w'
compile_f = lambda x: 'f'
compile_t = lambda x: 't'
+ compile_c = lambda x: 'c'
+ compile_e = lambda x: 'e'
compile_value = lambda x, v: str(v)
compile_and = _binary_compiler('(%s && %s)')
compile_or = _binary_compiler('(%s || %s)')
@pytest.mark.parametrize('source,n,i,v,w,f,t', EXTRACT_OPERANDS_TESTS)
def test_extract_operands(source, n, i, v, w, f, t):
- e_n, e_i, e_v, e_w, e_f, e_t = plural.extract_operands(source)
+ e_n, e_i, e_v, e_w, e_f, e_t, e_c, e_e = plural.extract_operands(source)
assert abs(e_n - decimal.Decimal(n)) <= EPSILON # float-decimal conversion inaccuracy
assert e_i == i
assert e_v == v
assert e_w == w
assert e_f == f
assert e_t == t
+ assert not e_c # Not supported at present
+ assert not e_e # Not supported at present
@pytest.mark.parametrize('locale', ('ru', 'pl'))