コード例 #1
0
ファイル: plural.py プロジェクト: AaronJaramillo/shopDPM
def extract_operands(source):
    """Extract operands from a decimal, a float or an int, according to
    `CLDR rules`_.

    .. _`CLDR rules`: http://www.unicode.org/reports/tr35/tr35-33/tr35-numbers.html#Operands
    """
    n = abs(source)
    i = int(n)
    if isinstance(n, float):
        if i == n:
            n = i
        else:
            # 2.6's Decimal cannot convert from float directly
            if sys.version_info < (2, 7):
                n = str(n)
            n = Decimal(n)

    if isinstance(n, Decimal):
        dec_tuple = n.as_tuple()
        exp = dec_tuple.exponent
        fraction_digits = dec_tuple.digits[exp:] if exp < 0 else ()
        trailing = ''.join(str(d) for d in fraction_digits)
        no_trailing = trailing.rstrip('0')
        v = len(trailing)
        w = len(no_trailing)
        f = int(trailing or 0)
        t = int(no_trailing or 0)
    else:
        v = w = f = t = 0
    return n, i, v, w, f, t
コード例 #2
0
ファイル: plural.py プロジェクト: 571451370/devstack_mitaka
def extract_operands(source):
    """Extract operands from a decimal, a float or an int, according to
    `CLDR rules`_.

    .. _`CLDR rules`: http://www.unicode.org/reports/tr35/tr35-33/tr35-numbers.html#Operands
    """
    n = abs(source)
    i = int(n)
    if isinstance(n, float):
        if i == n:
            n = i
        else:
            # 2.6's Decimal cannot convert from float directly
            if sys.version_info < (2, 7):
                n = str(n)
            n = Decimal(n)

    if isinstance(n, Decimal):
        dec_tuple = n.as_tuple()
        exp = dec_tuple.exponent
        fraction_digits = dec_tuple.digits[exp:] if exp < 0 else ()
        trailing = ''.join(str(d) for d in fraction_digits)
        no_trailing = trailing.rstrip('0')
        v = len(trailing)
        w = len(no_trailing)
        f = int(trailing or 0)
        t = int(no_trailing or 0)
    else:
        v = w = f = t = 0
    return n, i, v, w, f, t
コード例 #3
0
ファイル: test_numbers.py プロジェクト: st4lk/babel
 def test_can_parse_decimals(self):
     self.assertEqual(Decimal('1099.98'),
         numbers.parse_decimal('1,099.98', locale='en_US'))
     self.assertEqual(Decimal('1099.98'),
         numbers.parse_decimal('1.099,98', locale='de'))
     self.assertRaises(numbers.NumberFormatError,
                       lambda: numbers.parse_decimal('2,109,998', locale='de'))
コード例 #4
0
def test_parse_decimal():
    assert (numbers.parse_decimal('1,099.98',
                                  locale='en_US') == Decimal('1099.98'))
    assert numbers.parse_decimal('1.099,98', locale='de') == Decimal('1099.98')

    with pytest.raises(numbers.NumberFormatError) as excinfo:
        numbers.parse_decimal('2,109,998', locale='de')
    assert excinfo.value.args[0] == "'2,109,998' is not a valid decimal number"
コード例 #5
0
def test_smoke_numbers(locale):
    locale = Locale.parse(locale)
    for number in (
            Decimal("-33.76"),  # Negative Decimal
            Decimal("13.37"),  # Positive Decimal
            1.2 - 1.0,  # Inaccurate float
            10,  # Plain old integer
            0,  # Zero
    ):
        assert numbers.format_number(number, locale=locale)
コード例 #6
0
ファイル: numbers.py プロジェクト: marcosptf/fedora
 def apply(self, value, locale, currency=None, force_frac=None):
     frac_prec = force_frac or self.frac_prec
     if not isinstance(value, Decimal):
         value = Decimal(str(value))
     value = value.scaleb(self.scale)
     is_negative = int(value.is_signed())
     if self.exp_prec:  # Scientific notation
         exp = value.adjusted()
         value = abs(value)
         # Minimum number of integer digits
         if self.int_prec[0] == self.int_prec[1]:
             exp -= self.int_prec[0] - 1
         # Exponent grouping
         elif self.int_prec[1]:
             exp = int(exp / self.int_prec[1]) * self.int_prec[1]
         if exp < 0:
             value = value * 10**(-exp)
         else:
             value = value / 10**exp
         exp_sign = ''
         if exp < 0:
             exp_sign = get_minus_sign_symbol(locale)
         elif self.exp_plus:
             exp_sign = get_plus_sign_symbol(locale)
         exp = abs(exp)
         number = u'%s%s%s%s' % \
             (self._format_significant(value, frac_prec[0], frac_prec[1]),
              get_exponential_symbol(locale), exp_sign,
              self._format_int(str(exp), self.exp_prec[0],
                               self.exp_prec[1], locale))
     elif '@' in self.pattern:  # Is it a siginificant digits pattern?
         text = self._format_significant(abs(value),
                                         self.int_prec[0],
                                         self.int_prec[1])
         a, sep, b = text.partition(".")
         number = self._format_int(a, 0, 1000, locale)
         if sep:
             number += get_decimal_symbol(locale) + b
     else:  # A normal number pattern
         precision = Decimal('1.' + '1' * frac_prec[1])
         rounded = value.quantize(precision, ROUND_HALF_EVEN)
         a, sep, b = str(abs(rounded)).partition(".")
         number = (self._format_int(a, self.int_prec[0],
                                    self.int_prec[1], locale) +
                   self._format_frac(b or '0', locale, force_frac))
     retval = u'%s%s%s' % (self.prefix[is_negative], number,
                           self.suffix[is_negative])
     if u'¤' in retval:
         retval = retval.replace(u'¤¤¤',
                                 get_currency_name(currency, value, locale))
         retval = retval.replace(u'¤¤', currency.upper())
         retval = retval.replace(u'¤', get_currency_symbol(currency, locale))
     return retval
コード例 #7
0
ファイル: test_numbers.py プロジェクト: st4lk/babel
 def test_decimals(self):
     """Test significant digits patterns"""
     self.assertEqual(numbers.format_decimal(Decimal('1.2345'),
                                             '#.00', locale='en_US'),
                      '1.23')
     self.assertEqual(numbers.format_decimal(Decimal('1.2345000'),
                                             '#.00', locale='en_US'),
                      '1.23')
     self.assertEqual(numbers.format_decimal(Decimal('1.2345000'),
                                             '@@', locale='en_US'),
                      '1.2')
     self.assertEqual(numbers.format_decimal(Decimal('12345678901234567890.12345'),
                                             '#.00', locale='en_US'),
                      '12345678901234567890.12')
コード例 #8
0
def parse_decimal(string, locale=LC_NUMERIC):
    """Parse localized decimal string into a decimal.

    >>> parse_decimal('1,099.98', locale='en_US')
    Decimal('1099.98')
    >>> parse_decimal('1.099,98', locale='de')
    Decimal('1099.98')

    When the given string cannot be parsed, an exception is raised:

    >>> parse_decimal('2,109,998', locale='de')
    Traceback (most recent call last):
        ...
    NumberFormatError: '2,109,998' is not a valid decimal number

    :param string: the string to parse
    :param locale: the `Locale` object or locale identifier
    :raise NumberFormatError: if the string can not be converted to a
                              decimal number
    """
    locale = Locale.parse(locale)
    try:
        return Decimal(string.replace(get_group_symbol(locale), '')
                           .replace(get_decimal_symbol(locale), '.'))
    except InvalidOperation:
        raise NumberFormatError('%r is not a valid decimal number' % string)
コード例 #9
0
ファイル: test_numbers.py プロジェクト: st4lk/babel
 def test_scientific_notation(self):
     fmt = numbers.format_scientific(0.1, '#E0', locale='en_US')
     self.assertEqual(fmt, '1E-1')
     fmt = numbers.format_scientific(0.01, '#E0', locale='en_US')
     self.assertEqual(fmt, '1E-2')
     fmt = numbers.format_scientific(10, '#E0', locale='en_US')
     self.assertEqual(fmt, '1E1')
     fmt = numbers.format_scientific(1234, '0.###E0', locale='en_US')
     self.assertEqual(fmt, '1.234E3')
     fmt = numbers.format_scientific(1234, '0.#E0', locale='en_US')
     self.assertEqual(fmt, '1.2E3')
     # Exponent grouping
     fmt = numbers.format_scientific(12345, '##0.####E0', locale='en_US')
     self.assertEqual(fmt, '12.345E3')
     # Minimum number of int digits
     fmt = numbers.format_scientific(12345, '00.###E0', locale='en_US')
     self.assertEqual(fmt, '12.345E3')
     fmt = numbers.format_scientific(-12345.6, '00.###E0', locale='en_US')
     self.assertEqual(fmt, '-12.346E3')
     fmt = numbers.format_scientific(-0.01234, '00.###E0', locale='en_US')
     self.assertEqual(fmt, '-12.34E-3')
     # Custom pattern suffic
     fmt = numbers.format_scientific(123.45, '#.##E0 m/s', locale='en_US')
     self.assertEqual(fmt, '1.23E2 m/s')
     # Exponent patterns
     fmt = numbers.format_scientific(123.45, '#.##E00 m/s', locale='en_US')
     self.assertEqual(fmt, '1.23E02 m/s')
     fmt = numbers.format_scientific(0.012345, '#.##E00 m/s', locale='en_US')
     self.assertEqual(fmt, '1.23E-02 m/s')
     fmt = numbers.format_scientific(Decimal('12345'), '#.##E+00 m/s',
     locale='en_US')
     self.assertEqual(fmt, '1.23E+04 m/s')
     # 0 (see ticket #99)
     fmt = numbers.format_scientific(0, '#E0', locale='en_US')
     self.assertEqual(fmt, '0E0')
コード例 #10
0
 def apply(self, value, locale, currency=None, force_frac=None):
     frac_prec = force_frac or self.frac_prec
     if not isinstance(value, Decimal):
         value = Decimal(str(value))
     value = value.scaleb(self.scale)
     is_negative = int(value.is_signed())
     if self.exp_prec: # Scientific notation
         exp = value.adjusted()
         value = abs(value)
         # Minimum number of integer digits
         if self.int_prec[0] == self.int_prec[1]:
             exp -= self.int_prec[0] - 1
         # Exponent grouping
         elif self.int_prec[1]:
             exp = int(exp / self.int_prec[1]) * self.int_prec[1]
         if exp < 0:
             value = value * 10**(-exp)
         else:
             value = value / 10**exp
         exp_sign = ''
         if exp < 0:
             exp_sign = get_minus_sign_symbol(locale)
         elif self.exp_plus:
             exp_sign = get_plus_sign_symbol(locale)
         exp = abs(exp)
         number = u'%s%s%s%s' % \
              (self._format_significant(value, frac_prec[0], frac_prec[1]),
               get_exponential_symbol(locale),  exp_sign,
               self._format_int(str(exp), self.exp_prec[0],
                                self.exp_prec[1], locale))
     elif '@' in self.pattern: # Is it a siginificant digits pattern?
         text = self._format_significant(abs(value),
                                         self.int_prec[0],
                                         self.int_prec[1])
         a, sep, b = text.partition(".")
         number = self._format_int(a, 0, 1000, locale)
         if sep:
             number += get_decimal_symbol(locale) + b
     else: # A normal number pattern
         precision = Decimal('1.' + '1' * frac_prec[1])
         rounded = value.quantize(precision, ROUND_HALF_EVEN)
         a, sep, b = str(abs(rounded)).partition(".")
         number = (self._format_int(a, self.int_prec[0],
                                    self.int_prec[1], locale) +
                   self._format_frac(b or '0', locale, force_frac))
     retval = u'%s%s%s' % (self.prefix[is_negative], number,
                             self.suffix[is_negative])
     if u'¤' in retval:
         retval = retval.replace(u'¤¤¤',
             get_currency_name(currency, value, locale))
         retval = retval.replace(u'¤¤', currency.upper())
         retval = retval.replace(u'¤', get_currency_symbol(currency, locale))
     return retval
コード例 #11
0
 def _format_significant(self, value, minimum, maximum):
     exp = value.adjusted()
     scale = maximum - 1 - exp
     digits = str(value.scaleb(scale).quantize(Decimal(1), ROUND_HALF_EVEN))
     if scale <= 0:
         result = digits + '0' * -scale
     else:
         intpart = digits[:-scale]
         i = len(intpart)
         j = i + max(minimum - i, 0)
         result = "{intpart}.{pad:0<{fill}}{fracpart}{fracextra}".format(
                 intpart=intpart or '0',
                 pad='',
                 fill=-min(exp + 1, 0),
                 fracpart=digits[i:j],
                 fracextra=digits[j:].rstrip('0'),
         ).rstrip('.')
     return result
コード例 #12
0
 def test_formatting_of_very_small_decimals(self):
     # previously formatting very small decimals could lead to a type error
     # because the Decimal->string conversion was too simple (see #214)
     number = Decimal("7E-7")
     fmt = numbers.format_decimal(number, format="@@@", locale='en_US')
     self.assertEqual('0.000000700', fmt)
コード例 #13
0
def test_plural_rule_operands_t():
    rule = plural.PluralRule({'one': 't = 5'})
    assert rule(Decimal('1.53')) == 'other'
    assert rule(Decimal('1.50')) == 'one'
    assert rule(1.5) == 'one'
コード例 #14
0
def test_plural_rule_operands_f():
    rule = plural.PluralRule({'one': 'f is 20'})
    assert rule(Decimal('1.23')) == 'other'
    assert rule(Decimal('1.20')) == 'one'
    assert rule(1.2) == 'other'
コード例 #15
0
def test_plural_rule_operands_v():
    rule = plural.PluralRule({'one': 'v is 2'})
    assert rule(Decimal('1.20')) == 'one'
    assert rule(Decimal('1.2')) == 'other'
    assert rule(2) == 'other'
コード例 #16
0
def test_extract_operands(source, n, i, v, w, f, t):
    source = Decimal(source) if isinstance(source, str) else source
    assert (plural.extract_operands(source) ==
            Decimal(n), i, v, w, f, t)