mirror of
				https://github.com/python/cpython.git
				synced 2025-11-03 23:21:29 +00:00 
			
		
		
		
	Merged revisions 74279 via svnmerge from
svn+ssh://pythondev@www.python.org/python/branches/py3k ........ r74279 | mark.dickinson | 2009-08-02 11:14:23 +0100 (Sun, 02 Aug 2009) | 1 line Issue #6595: Allow Decimal constructor to accept non-European decimal digits, as recommended by the specification. ........
This commit is contained in:
		
							parent
							
								
									e634d87315
								
							
						
					
					
						commit
						8d238293cd
					
				
					 4 changed files with 28 additions and 20 deletions
				
			
		| 
						 | 
				
			
			@ -324,6 +324,11 @@ Decimal objects
 | 
			
		|||
      numeric-value  ::=  decimal-part [exponent-part] | infinity
 | 
			
		||||
      numeric-string ::=  [sign] numeric-value | [sign] nan
 | 
			
		||||
 | 
			
		||||
   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 ``'\uff10'`` through ``'\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))``
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -554,20 +554,16 @@ def __new__(cls, value="0", context=None):
 | 
			
		|||
            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 = (intpart+fracpart).lstrip('0') or '0'
 | 
			
		||||
                self._int = str(int(intpart+fracpart))
 | 
			
		||||
                self._exp = exp - len(fracpart)
 | 
			
		||||
                else:
 | 
			
		||||
                    self._int = intpart.lstrip('0') or '0'
 | 
			
		||||
                    self._exp = exp
 | 
			
		||||
                self._is_special = False
 | 
			
		||||
            else:
 | 
			
		||||
                diag = m.group('diag')
 | 
			
		||||
                if diag is not None:
 | 
			
		||||
                    # NaN
 | 
			
		||||
                    self._int = diag.lstrip('0')
 | 
			
		||||
                    self._int = str(int(diag or '0')).lstrip('0')
 | 
			
		||||
                    if m.group('signal'):
 | 
			
		||||
                        self._exp = 'N'
 | 
			
		||||
                    else:
 | 
			
		||||
| 
						 | 
				
			
			@ -5482,26 +5478,23 @@ def _convert_other(other, raiseit=False):
 | 
			
		|||
# 2. For finite numbers (not infinities and NaNs) the body of the
 | 
			
		||||
# number between the optional sign and the optional exponent must have
 | 
			
		||||
# at least one decimal digit, possibly after the decimal point.  The
 | 
			
		||||
# lookahead expression '(?=[0-9]|\.[0-9])' checks this.
 | 
			
		||||
#
 | 
			
		||||
# As the flag UNICODE is not enabled here, we're explicitly avoiding any
 | 
			
		||||
# other meaning for \d than the numbers [0-9].
 | 
			
		||||
# lookahead expression '(?=\d|\.\d)' checks this.
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -425,9 +425,6 @@ def test_explicit_from_string(self):
 | 
			
		|||
        self.assertEqual(str(Decimal('1.3E4 \n')), '1.3E+4')
 | 
			
		||||
        self.assertEqual(str(Decimal('  -7.89')), '-7.89')
 | 
			
		||||
 | 
			
		||||
        #but alternate unicode digits should not
 | 
			
		||||
        self.assertEqual(str(Decimal('\uff11')), 'NaN')
 | 
			
		||||
 | 
			
		||||
    def test_explicit_from_tuples(self):
 | 
			
		||||
 | 
			
		||||
        #zero
 | 
			
		||||
| 
						 | 
				
			
			@ -534,6 +531,15 @@ def test_explicit_context_create_decimal(self):
 | 
			
		|||
        d = nc.create_decimal(prevdec)
 | 
			
		||||
        self.assertEqual(str(d), '5.00E+8')
 | 
			
		||||
 | 
			
		||||
    def test_unicode_digits(self):
 | 
			
		||||
        test_values = {
 | 
			
		||||
            '\uff11': '1',
 | 
			
		||||
            '\u0660.\u0660\u0663\u0667\u0662e-\u0663' : '0.0000372',
 | 
			
		||||
            '-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.'''
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -42,6 +42,10 @@ C-API
 | 
			
		|||
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].
 | 
			
		||||
 | 
			
		||||
- Issues #5155, #5313, #5331: multiprocessing.Process._bootstrap was
 | 
			
		||||
  unconditionally calling "os.close(sys.stdin.fileno())" resulting in file
 | 
			
		||||
  descriptor errors
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue