[Python-checkins] r74281 - in python/trunk: Doc/library/decimal.rst Lib/decimal.py Lib/test/test_decimal.py Misc/NEWS

mark.dickinson python-checkins at python.org
Sun Aug 2 12:59:36 CEST 2009


Author: mark.dickinson
Date: Sun Aug 2 12:59:36 2009
New Revision: 74281
Log:
Issue #6595: Allow Decimal constructor to accept non-European decimal
digits, as recommended by the specification. (Backport of r74279 from
py3k.)
Modified:
 python/trunk/Doc/library/decimal.rst
 python/trunk/Lib/decimal.py
 python/trunk/Lib/test/test_decimal.py
 python/trunk/Misc/NEWS
Modified: python/trunk/Doc/library/decimal.rst
==============================================================================
--- python/trunk/Doc/library/decimal.rst	(original)
+++ python/trunk/Doc/library/decimal.rst	Sun Aug 2 12:59:36 2009
@@ -330,6 +330,12 @@
 numeric-value ::= decimal-part [exponent-part] | infinity
 numeric-string ::= [sign] numeric-value | [sign] nan
 
+ If *value* is a unicode string then other Unicode decimal digits
+ are also permitted where ``digit`` appears above. These include
+ decimal digits from various other alphabets (for example,
+ Arabic-Indic and Devanāgarī digits) along with the fullwidth digits
+ ``u'\uff10'`` through ``u'\uff19'``.
+
 If *value* is a :class:`tuple`, it should have three components, a sign
 (:const:`0` for positive or :const:`1` for negative), a :class:`tuple` of
 digits, and an integer exponent. For example, ``Decimal((0, (1, 4, 1, 4), -3))``
Modified: python/trunk/Lib/decimal.py
==============================================================================
--- python/trunk/Lib/decimal.py	(original)
+++ python/trunk/Lib/decimal.py	Sun Aug 2 12:59:36 2009
@@ -554,20 +554,16 @@
 intpart = m.group('int')
 if intpart is not None:
 # finite number
- fracpart = m.group('frac')
+ fracpart = m.group('frac') or ''
 exp = int(m.group('exp') or '0')
- if fracpart is not None:
- self._int = str((intpart+fracpart).lstrip('0') or '0')
- self._exp = exp - len(fracpart)
- else:
- self._int = str(intpart.lstrip('0') or '0')
- self._exp = exp
+ self._int = str(int(intpart+fracpart))
+ self._exp = exp - len(fracpart)
 self._is_special = False
 else:
 diag = m.group('diag')
 if diag is not None:
 # NaN
- self._int = str(diag.lstrip('0'))
+ self._int = str(int(diag or '0')).lstrip('0')
 if m.group('signal'):
 self._exp = 'N'
 else:
@@ -5402,29 +5398,26 @@
 # number between the optional sign and the optional exponent must have
 # at least one decimal digit, possibly after the decimal point. The
 # lookahead expression '(?=\d|\.\d)' checks this.
-#
-# As the flag UNICODE is not enabled here, we're explicitly avoiding any
-# other meaning for \d than the numbers [0-9].
 
 import re
 _parser = re.compile(r""" # A numeric string consists of:
 # \s*
 (?P<sign>[-+])? # an optional sign, followed by either...
 (
- (?=[0-9]|\.[0-9]) # ...a number (with at least one digit)
- (?P<int>[0-9]*) # having a (possibly empty) integer part
- (\.(?P<frac>[0-9]*))? # followed by an optional fractional part
- (E(?P<exp>[-+]?[0-9]+))? # followed by an optional exponent, or...
+ (?=\d|\.\d) # ...a number (with at least one digit)
+ (?P<int>\d*) # having a (possibly empty) integer part
+ (\.(?P<frac>\d*))? # followed by an optional fractional part
+ (E(?P<exp>[-+]?\d+))? # followed by an optional exponent, or...
 |
 Inf(inity)? # ...an infinity, or...
 |
 (?P<signal>s)? # ...an (optionally signaling)
 NaN # NaN
- (?P<diag>[0-9]*) # with (possibly empty) diagnostic info.
+ (?P<diag>\d*) # with (possibly empty) diagnostic info.
 )
 # \s*
 \Z
-""", re.VERBOSE | re.IGNORECASE).match
+""", re.VERBOSE | re.IGNORECASE | re.UNICODE).match
 
 _all_zeros = re.compile('0*$').match
 _exact_half = re.compile('50*$').match
Modified: python/trunk/Lib/test/test_decimal.py
==============================================================================
--- python/trunk/Lib/test/test_decimal.py	(original)
+++ python/trunk/Lib/test/test_decimal.py	Sun Aug 2 12:59:36 2009
@@ -431,9 +431,6 @@
 self.assertEqual(str(Decimal(u'-Inf')), '-Infinity')
 self.assertEqual(str(Decimal(u'NaN123')), 'NaN123')
 
- #but alternate unicode digits should not
- self.assertEqual(str(Decimal(u'\uff11')), 'NaN')
-
 def test_explicit_from_tuples(self):
 
 #zero
@@ -540,6 +537,15 @@
 d = nc.create_decimal(prevdec)
 self.assertEqual(str(d), '5.00E+8')
 
+ def test_unicode_digits(self):
+ test_values = {
+ u'\uff11': '1',
+ u'\u0660.\u0660\u0663\u0667\u0662e-\u0663' : '0.0000372',
+ u'-nan\u0c68\u0c6a\u0c66\u0c66' : '-NaN2400',
+ }
+ for input, expected in test_values.items():
+ self.assertEqual(str(Decimal(input)), expected)
+
 
 class DecimalImplicitConstructionTest(unittest.TestCase):
 '''Unit tests for Implicit Construction cases of Decimal.'''
Modified: python/trunk/Misc/NEWS
==============================================================================
--- python/trunk/Misc/NEWS	(original)
+++ python/trunk/Misc/NEWS	Sun Aug 2 12:59:36 2009
@@ -354,6 +354,10 @@
 Library
 -------
 
+- Issue #6595: The Decimal constructor now allows arbitrary Unicode
+ decimal digits in input, as recommended by the standard. Previously
+ it was restricted to accepting [0-9].
+
 - Issue #6511: ZipFile now raises BadZipfile (instead of an IOError) when
 opening an empty or very small file.
 


More information about the Python-checkins mailing list

AltStyle によって変換されたページ (->オリジナル) /