* fix format_decimal() with small Decimal values (#214, patch from George Lund)
* fix handling of messages containing '\\n' (#198)
* handle irregular multi-line msgstr (no "" as first line) gracefully (#171)
+ * parse_decimal() now returns Decimals not floats, API change (#178)
Version 0.9.6
# TODO:
# Padding and rounding increments in pattern:
# - http://www.unicode.org/reports/tr35/ (Appendix G.6)
-from decimal import Decimal
+from decimal import Decimal, InvalidOperation
import math
import re
raise NumberFormatError('%r is not a valid number' % string)
def parse_decimal(string, locale=LC_NUMERIC):
- """Parse localized decimal string into a float.
+ """Parse localized decimal string into a decimal.
>>> parse_decimal('1,099.98', locale='en_US')
- 1099.98
+ Decimal('1099.98')
>>> parse_decimal('1.099,98', locale='de')
- 1099.98
+ Decimal('1099.98')
When the given string cannot be parsed, an exception is raised:
:param string: the string to parse
:param locale: the `Locale` object or locale identifier
:return: the parsed decimal number
- :rtype: `float`
+ :rtype: `Decimal`
:raise `NumberFormatError`: if the string can not be converted to a
decimal number
"""
locale = Locale.parse(locale)
try:
- return float(string.replace(get_group_symbol(locale), '')
+ return Decimal(string.replace(get_group_symbol(locale), '')
.replace(get_decimal_symbol(locale), '.'))
- except ValueError:
+ except InvalidOperation:
raise NumberFormatError('%r is not a valid decimal number' % string)
self.assertEqual(Decimal('0.2'), numbers.bankersround(Decimal('0.15'), ndigits=1))
+class NumberParsingTestCase(unittest.TestCase):
+ 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'))
+
+
def suite():
suite = unittest.TestSuite()
suite.addTest(doctest.DocTestSuite(numbers))
suite.addTest(unittest.makeSuite(FormatDecimalTestCase))
suite.addTest(unittest.makeSuite(BankersRoundTestCase))
+ suite.addTest(unittest.makeSuite(NumberParsingTestCase))
return suite
if __name__ == '__main__':