symbian-qemu-0.9.1-12/python-2.6.1/Lib/test/test_decimal.py
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 # Copyright (c) 2004 Python Software Foundation.
       
     2 # All rights reserved.
       
     3 
       
     4 # Written by Eric Price <eprice at tjhsst.edu>
       
     5 #    and Facundo Batista <facundo at taniquetil.com.ar>
       
     6 #    and Raymond Hettinger <python at rcn.com>
       
     7 #    and Aahz (aahz at pobox.com)
       
     8 #    and Tim Peters
       
     9 
       
    10 """
       
    11 These are the test cases for the Decimal module.
       
    12 
       
    13 There are two groups of tests, Arithmetic and Behaviour. The former test
       
    14 the Decimal arithmetic using the tests provided by Mike Cowlishaw. The latter
       
    15 test the pythonic behaviour according to PEP 327.
       
    16 
       
    17 Cowlishaw's tests can be downloaded from:
       
    18 
       
    19    www2.hursley.ibm.com/decimal/dectest.zip
       
    20 
       
    21 This test module can be called from command line with one parameter (Arithmetic
       
    22 or Behaviour) to test each part, or without parameter to test both parts. If
       
    23 you're working through IDLE, you can import this test module and call test_main()
       
    24 with the corresponding argument.
       
    25 """
       
    26 
       
    27 import glob
       
    28 import math
       
    29 import os, sys
       
    30 import pickle, copy
       
    31 import unittest
       
    32 from decimal import *
       
    33 from test.test_support import (TestSkipped, run_unittest, run_doctest,
       
    34                                is_resource_enabled)
       
    35 import random
       
    36 try:
       
    37     import threading
       
    38 except ImportError:
       
    39     threading = None
       
    40 
       
    41 # Useful Test Constant
       
    42 Signals = getcontext().flags.keys()
       
    43 
       
    44 # Tests are built around these assumed context defaults.
       
    45 # test_main() restores the original context.
       
    46 def init():
       
    47     global ORIGINAL_CONTEXT
       
    48     ORIGINAL_CONTEXT = getcontext().copy()
       
    49     DefaultTestContext = Context(
       
    50         prec = 9,
       
    51         rounding = ROUND_HALF_EVEN,
       
    52         traps = dict.fromkeys(Signals, 0)
       
    53         )
       
    54     setcontext(DefaultTestContext)
       
    55 
       
    56 TESTDATADIR = 'decimaltestdata'
       
    57 if __name__ == '__main__':
       
    58     file = sys.argv[0]
       
    59 else:
       
    60     file = __file__
       
    61 testdir = os.path.dirname(file) or os.curdir
       
    62 directory = testdir + os.sep + TESTDATADIR + os.sep
       
    63 
       
    64 skip_expected = not os.path.isdir(directory)
       
    65 
       
    66 # Make sure it actually raises errors when not expected and caught in flags
       
    67 # Slower, since it runs some things several times.
       
    68 EXTENDEDERRORTEST = False
       
    69 
       
    70 #Map the test cases' error names to the actual errors
       
    71 ErrorNames = {'clamped' : Clamped,
       
    72               'conversion_syntax' : InvalidOperation,
       
    73               'division_by_zero' : DivisionByZero,
       
    74               'division_impossible' : InvalidOperation,
       
    75               'division_undefined' : InvalidOperation,
       
    76               'inexact' : Inexact,
       
    77               'invalid_context' : InvalidOperation,
       
    78               'invalid_operation' : InvalidOperation,
       
    79               'overflow' : Overflow,
       
    80               'rounded' : Rounded,
       
    81               'subnormal' : Subnormal,
       
    82               'underflow' : Underflow}
       
    83 
       
    84 
       
    85 def Nonfunction(*args):
       
    86     """Doesn't do anything."""
       
    87     return None
       
    88 
       
    89 RoundingDict = {'ceiling' : ROUND_CEILING, #Maps test-case names to roundings.
       
    90                 'down' : ROUND_DOWN,
       
    91                 'floor' : ROUND_FLOOR,
       
    92                 'half_down' : ROUND_HALF_DOWN,
       
    93                 'half_even' : ROUND_HALF_EVEN,
       
    94                 'half_up' : ROUND_HALF_UP,
       
    95                 'up' : ROUND_UP,
       
    96                 '05up' : ROUND_05UP}
       
    97 
       
    98 # Name adapter to be able to change the Decimal and Context
       
    99 # interface without changing the test files from Cowlishaw
       
   100 nameAdapter = {'and':'logical_and',
       
   101                'apply':'_apply',
       
   102                'class':'number_class',
       
   103                'comparesig':'compare_signal',
       
   104                'comparetotal':'compare_total',
       
   105                'comparetotmag':'compare_total_mag',
       
   106                'copy':'copy_decimal',
       
   107                'copyabs':'copy_abs',
       
   108                'copynegate':'copy_negate',
       
   109                'copysign':'copy_sign',
       
   110                'divideint':'divide_int',
       
   111                'invert':'logical_invert',
       
   112                'iscanonical':'is_canonical',
       
   113                'isfinite':'is_finite',
       
   114                'isinfinite':'is_infinite',
       
   115                'isnan':'is_nan',
       
   116                'isnormal':'is_normal',
       
   117                'isqnan':'is_qnan',
       
   118                'issigned':'is_signed',
       
   119                'issnan':'is_snan',
       
   120                'issubnormal':'is_subnormal',
       
   121                'iszero':'is_zero',
       
   122                'maxmag':'max_mag',
       
   123                'minmag':'min_mag',
       
   124                'nextminus':'next_minus',
       
   125                'nextplus':'next_plus',
       
   126                'nexttoward':'next_toward',
       
   127                'or':'logical_or',
       
   128                'reduce':'normalize',
       
   129                'remaindernear':'remainder_near',
       
   130                'samequantum':'same_quantum',
       
   131                'squareroot':'sqrt',
       
   132                'toeng':'to_eng_string',
       
   133                'tointegral':'to_integral_value',
       
   134                'tointegralx':'to_integral_exact',
       
   135                'tosci':'to_sci_string',
       
   136                'xor':'logical_xor',
       
   137               }
       
   138 
       
   139 # The following functions return True/False rather than a Decimal instance
       
   140 
       
   141 LOGICAL_FUNCTIONS = (
       
   142     'is_canonical',
       
   143     'is_finite',
       
   144     'is_infinite',
       
   145     'is_nan',
       
   146     'is_normal',
       
   147     'is_qnan',
       
   148     'is_signed',
       
   149     'is_snan',
       
   150     'is_subnormal',
       
   151     'is_zero',
       
   152     'same_quantum',
       
   153     )
       
   154 
       
   155 # For some operations (currently exp, ln, log10, power), the decNumber
       
   156 # reference implementation imposes additional restrictions on the
       
   157 # context and operands.  These restrictions are not part of the
       
   158 # specification; however, the effect of these restrictions does show
       
   159 # up in some of the testcases.  We skip testcases that violate these
       
   160 # restrictions, since Decimal behaves differently from decNumber for
       
   161 # these testcases so these testcases would otherwise fail.
       
   162 
       
   163 decNumberRestricted = ('power', 'ln', 'log10', 'exp')
       
   164 DEC_MAX_MATH = 999999
       
   165 def outside_decNumber_bounds(v, context):
       
   166     if (context.prec > DEC_MAX_MATH or
       
   167         context.Emax > DEC_MAX_MATH or
       
   168         -context.Emin > DEC_MAX_MATH):
       
   169         return True
       
   170     if not v._is_special and v and (
       
   171         len(v._int) > DEC_MAX_MATH or
       
   172         v.adjusted() > DEC_MAX_MATH or
       
   173         v.adjusted() < 1-2*DEC_MAX_MATH):
       
   174         return True
       
   175     return False
       
   176 
       
   177 class DecimalTest(unittest.TestCase):
       
   178     """Class which tests the Decimal class against the test cases.
       
   179 
       
   180     Changed for unittest.
       
   181     """
       
   182     def setUp(self):
       
   183         self.context = Context()
       
   184         self.ignore_list = ['#']
       
   185         # Basically, a # means return NaN InvalidOperation.
       
   186         # Different from a sNaN in trim
       
   187 
       
   188         self.ChangeDict = {'precision' : self.change_precision,
       
   189                       'rounding' : self.change_rounding_method,
       
   190                       'maxexponent' : self.change_max_exponent,
       
   191                       'minexponent' : self.change_min_exponent,
       
   192                       'clamp' : self.change_clamp}
       
   193 
       
   194     def eval_file(self, file):
       
   195         global skip_expected
       
   196         if skip_expected:
       
   197             raise TestSkipped
       
   198             return
       
   199         for line in open(file).xreadlines():
       
   200             line = line.replace('\r\n', '').replace('\n', '')
       
   201             #print line
       
   202             try:
       
   203                 t = self.eval_line(line)
       
   204             except DecimalException, exception:
       
   205                 #Exception raised where there shoudn't have been one.
       
   206                 self.fail('Exception "'+exception.__class__.__name__ + '" raised on line '+line)
       
   207 
       
   208         return
       
   209 
       
   210     def eval_line(self, s):
       
   211         if s.find(' -> ') >= 0 and s[:2] != '--' and not s.startswith('  --'):
       
   212             s = (s.split('->')[0] + '->' +
       
   213                  s.split('->')[1].split('--')[0]).strip()
       
   214         else:
       
   215             s = s.split('--')[0].strip()
       
   216 
       
   217         for ignore in self.ignore_list:
       
   218             if s.find(ignore) >= 0:
       
   219                 #print s.split()[0], 'NotImplemented--', ignore
       
   220                 return
       
   221         if not s:
       
   222             return
       
   223         elif ':' in s:
       
   224             return self.eval_directive(s)
       
   225         else:
       
   226             return self.eval_equation(s)
       
   227 
       
   228     def eval_directive(self, s):
       
   229         funct, value = map(lambda x: x.strip().lower(), s.split(':'))
       
   230         if funct == 'rounding':
       
   231             value = RoundingDict[value]
       
   232         else:
       
   233             try:
       
   234                 value = int(value)
       
   235             except ValueError:
       
   236                 pass
       
   237 
       
   238         funct = self.ChangeDict.get(funct, Nonfunction)
       
   239         funct(value)
       
   240 
       
   241     def eval_equation(self, s):
       
   242         #global DEFAULT_PRECISION
       
   243         #print DEFAULT_PRECISION
       
   244 
       
   245         if not TEST_ALL and random.random() < 0.90:
       
   246             return
       
   247 
       
   248         try:
       
   249             Sides = s.split('->')
       
   250             L = Sides[0].strip().split()
       
   251             id = L[0]
       
   252             if DEBUG:
       
   253                 print "Test ", id,
       
   254             funct = L[1].lower()
       
   255             valstemp = L[2:]
       
   256             L = Sides[1].strip().split()
       
   257             ans = L[0]
       
   258             exceptions = L[1:]
       
   259         except (TypeError, AttributeError, IndexError):
       
   260             raise InvalidOperation
       
   261         def FixQuotes(val):
       
   262             val = val.replace("''", 'SingleQuote').replace('""', 'DoubleQuote')
       
   263             val = val.replace("'", '').replace('"', '')
       
   264             val = val.replace('SingleQuote', "'").replace('DoubleQuote', '"')
       
   265             return val
       
   266         fname = nameAdapter.get(funct, funct)
       
   267         if fname == 'rescale':
       
   268             return
       
   269         funct = getattr(self.context, fname)
       
   270         vals = []
       
   271         conglomerate = ''
       
   272         quote = 0
       
   273         theirexceptions = [ErrorNames[x.lower()] for x in exceptions]
       
   274 
       
   275         for exception in Signals:
       
   276             self.context.traps[exception] = 1 #Catch these bugs...
       
   277         for exception in theirexceptions:
       
   278             self.context.traps[exception] = 0
       
   279         for i, val in enumerate(valstemp):
       
   280             if val.count("'") % 2 == 1:
       
   281                 quote = 1 - quote
       
   282             if quote:
       
   283                 conglomerate = conglomerate + ' ' + val
       
   284                 continue
       
   285             else:
       
   286                 val = conglomerate + val
       
   287                 conglomerate = ''
       
   288             v = FixQuotes(val)
       
   289             if fname in ('to_sci_string', 'to_eng_string'):
       
   290                 if EXTENDEDERRORTEST:
       
   291                     for error in theirexceptions:
       
   292                         self.context.traps[error] = 1
       
   293                         try:
       
   294                             funct(self.context.create_decimal(v))
       
   295                         except error:
       
   296                             pass
       
   297                         except Signals, e:
       
   298                             self.fail("Raised %s in %s when %s disabled" % \
       
   299                                       (e, s, error))
       
   300                         else:
       
   301                             self.fail("Did not raise %s in %s" % (error, s))
       
   302                         self.context.traps[error] = 0
       
   303                 v = self.context.create_decimal(v)
       
   304             else:
       
   305                 v = Decimal(v, self.context)
       
   306             vals.append(v)
       
   307 
       
   308         ans = FixQuotes(ans)
       
   309 
       
   310         # skip tests that are related to bounds imposed in the decNumber
       
   311         # reference implementation
       
   312         if fname in decNumberRestricted:
       
   313             if fname == 'power':
       
   314                 if not (vals[1]._isinteger() and
       
   315                         -1999999997 <= vals[1] <= 999999999):
       
   316                     if outside_decNumber_bounds(vals[0], self.context) or \
       
   317                             outside_decNumber_bounds(vals[1], self.context):
       
   318                         #print "Skipping test %s" % s
       
   319                         return
       
   320             else:
       
   321                 if outside_decNumber_bounds(vals[0], self.context):
       
   322                     #print "Skipping test %s" % s
       
   323                     return
       
   324 
       
   325 
       
   326         if EXTENDEDERRORTEST and fname not in ('to_sci_string', 'to_eng_string'):
       
   327             for error in theirexceptions:
       
   328                 self.context.traps[error] = 1
       
   329                 try:
       
   330                     funct(*vals)
       
   331                 except error:
       
   332                     pass
       
   333                 except Signals, e:
       
   334                     self.fail("Raised %s in %s when %s disabled" % \
       
   335                               (e, s, error))
       
   336                 else:
       
   337                     self.fail("Did not raise %s in %s" % (error, s))
       
   338                 self.context.traps[error] = 0
       
   339         if DEBUG:
       
   340             print "--", self.context
       
   341         try:
       
   342             result = str(funct(*vals))
       
   343             if fname in LOGICAL_FUNCTIONS:
       
   344                 result = str(int(eval(result))) # 'True', 'False' -> '1', '0'
       
   345         except Signals, error:
       
   346             self.fail("Raised %s in %s" % (error, s))
       
   347         except: #Catch any error long enough to state the test case.
       
   348             print "ERROR:", s
       
   349             raise
       
   350 
       
   351         myexceptions = self.getexceptions()
       
   352         self.context.clear_flags()
       
   353 
       
   354         myexceptions.sort()
       
   355         theirexceptions.sort()
       
   356 
       
   357         self.assertEqual(result, ans,
       
   358                          'Incorrect answer for ' + s + ' -- got ' + result)
       
   359         self.assertEqual(myexceptions, theirexceptions,
       
   360               'Incorrect flags set in ' + s + ' -- got ' + str(myexceptions))
       
   361         return
       
   362 
       
   363     def getexceptions(self):
       
   364         return [e for e in Signals if self.context.flags[e]]
       
   365 
       
   366     def change_precision(self, prec):
       
   367         self.context.prec = prec
       
   368     def change_rounding_method(self, rounding):
       
   369         self.context.rounding = rounding
       
   370     def change_min_exponent(self, exp):
       
   371         self.context.Emin = exp
       
   372     def change_max_exponent(self, exp):
       
   373         self.context.Emax = exp
       
   374     def change_clamp(self, clamp):
       
   375         self.context._clamp = clamp
       
   376 
       
   377 
       
   378 
       
   379 # The following classes test the behaviour of Decimal according to PEP 327
       
   380 
       
   381 class DecimalExplicitConstructionTest(unittest.TestCase):
       
   382     '''Unit tests for Explicit Construction cases of Decimal.'''
       
   383 
       
   384     def test_explicit_empty(self):
       
   385         self.assertEqual(Decimal(), Decimal("0"))
       
   386 
       
   387     def test_explicit_from_None(self):
       
   388         self.assertRaises(TypeError, Decimal, None)
       
   389 
       
   390     def test_explicit_from_int(self):
       
   391 
       
   392         #positive
       
   393         d = Decimal(45)
       
   394         self.assertEqual(str(d), '45')
       
   395 
       
   396         #very large positive
       
   397         d = Decimal(500000123)
       
   398         self.assertEqual(str(d), '500000123')
       
   399 
       
   400         #negative
       
   401         d = Decimal(-45)
       
   402         self.assertEqual(str(d), '-45')
       
   403 
       
   404         #zero
       
   405         d = Decimal(0)
       
   406         self.assertEqual(str(d), '0')
       
   407 
       
   408     def test_explicit_from_string(self):
       
   409 
       
   410         #empty
       
   411         self.assertEqual(str(Decimal('')), 'NaN')
       
   412 
       
   413         #int
       
   414         self.assertEqual(str(Decimal('45')), '45')
       
   415 
       
   416         #float
       
   417         self.assertEqual(str(Decimal('45.34')), '45.34')
       
   418 
       
   419         #engineer notation
       
   420         self.assertEqual(str(Decimal('45e2')), '4.5E+3')
       
   421 
       
   422         #just not a number
       
   423         self.assertEqual(str(Decimal('ugly')), 'NaN')
       
   424 
       
   425         #leading and trailing whitespace permitted
       
   426         self.assertEqual(str(Decimal('1.3E4 \n')), '1.3E+4')
       
   427         self.assertEqual(str(Decimal('  -7.89')), '-7.89')
       
   428 
       
   429         #unicode strings should be permitted
       
   430         self.assertEqual(str(Decimal(u'0E-017')), '0E-17')
       
   431         self.assertEqual(str(Decimal(u'45')), '45')
       
   432         self.assertEqual(str(Decimal(u'-Inf')), '-Infinity')
       
   433         self.assertEqual(str(Decimal(u'NaN123')), 'NaN123')
       
   434 
       
   435         #but alternate unicode digits should not
       
   436         self.assertEqual(str(Decimal(u'\uff11')), 'NaN')
       
   437 
       
   438     def test_explicit_from_tuples(self):
       
   439 
       
   440         #zero
       
   441         d = Decimal( (0, (0,), 0) )
       
   442         self.assertEqual(str(d), '0')
       
   443 
       
   444         #int
       
   445         d = Decimal( (1, (4, 5), 0) )
       
   446         self.assertEqual(str(d), '-45')
       
   447 
       
   448         #float
       
   449         d = Decimal( (0, (4, 5, 3, 4), -2) )
       
   450         self.assertEqual(str(d), '45.34')
       
   451 
       
   452         #weird
       
   453         d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
       
   454         self.assertEqual(str(d), '-4.34913534E-17')
       
   455 
       
   456         #wrong number of items
       
   457         self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1)) )
       
   458 
       
   459         #bad sign
       
   460         self.assertRaises(ValueError, Decimal, (8, (4, 3, 4, 9, 1), 2) )
       
   461         self.assertRaises(ValueError, Decimal, (0., (4, 3, 4, 9, 1), 2) )
       
   462         self.assertRaises(ValueError, Decimal, (Decimal(1), (4, 3, 4, 9, 1), 2))
       
   463 
       
   464         #bad exp
       
   465         self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 'wrong!') )
       
   466         self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 0.) )
       
   467         self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), '1') )
       
   468 
       
   469         #bad coefficients
       
   470         self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, None, 1), 2) )
       
   471         self.assertRaises(ValueError, Decimal, (1, (4, -3, 4, 9, 1), 2) )
       
   472         self.assertRaises(ValueError, Decimal, (1, (4, 10, 4, 9, 1), 2) )
       
   473         self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 'a', 1), 2) )
       
   474 
       
   475     def test_explicit_from_Decimal(self):
       
   476 
       
   477         #positive
       
   478         d = Decimal(45)
       
   479         e = Decimal(d)
       
   480         self.assertEqual(str(e), '45')
       
   481         self.assertNotEqual(id(d), id(e))
       
   482 
       
   483         #very large positive
       
   484         d = Decimal(500000123)
       
   485         e = Decimal(d)
       
   486         self.assertEqual(str(e), '500000123')
       
   487         self.assertNotEqual(id(d), id(e))
       
   488 
       
   489         #negative
       
   490         d = Decimal(-45)
       
   491         e = Decimal(d)
       
   492         self.assertEqual(str(e), '-45')
       
   493         self.assertNotEqual(id(d), id(e))
       
   494 
       
   495         #zero
       
   496         d = Decimal(0)
       
   497         e = Decimal(d)
       
   498         self.assertEqual(str(e), '0')
       
   499         self.assertNotEqual(id(d), id(e))
       
   500 
       
   501     def test_explicit_context_create_decimal(self):
       
   502 
       
   503         nc = copy.copy(getcontext())
       
   504         nc.prec = 3
       
   505 
       
   506         # empty
       
   507         d = Decimal()
       
   508         self.assertEqual(str(d), '0')
       
   509         d = nc.create_decimal()
       
   510         self.assertEqual(str(d), '0')
       
   511 
       
   512         # from None
       
   513         self.assertRaises(TypeError, nc.create_decimal, None)
       
   514 
       
   515         # from int
       
   516         d = nc.create_decimal(456)
       
   517         self.failUnless(isinstance(d, Decimal))
       
   518         self.assertEqual(nc.create_decimal(45678),
       
   519                          nc.create_decimal('457E+2'))
       
   520 
       
   521         # from string
       
   522         d = Decimal('456789')
       
   523         self.assertEqual(str(d), '456789')
       
   524         d = nc.create_decimal('456789')
       
   525         self.assertEqual(str(d), '4.57E+5')
       
   526         # leading and trailing whitespace should result in a NaN;
       
   527         # spaces are already checked in Cowlishaw's test-suite, so
       
   528         # here we just check that a trailing newline results in a NaN
       
   529         self.assertEqual(str(nc.create_decimal('3.14\n')), 'NaN')
       
   530 
       
   531         # from tuples
       
   532         d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
       
   533         self.assertEqual(str(d), '-4.34913534E-17')
       
   534         d = nc.create_decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
       
   535         self.assertEqual(str(d), '-4.35E-17')
       
   536 
       
   537         # from Decimal
       
   538         prevdec = Decimal(500000123)
       
   539         d = Decimal(prevdec)
       
   540         self.assertEqual(str(d), '500000123')
       
   541         d = nc.create_decimal(prevdec)
       
   542         self.assertEqual(str(d), '5.00E+8')
       
   543 
       
   544 
       
   545 class DecimalImplicitConstructionTest(unittest.TestCase):
       
   546     '''Unit tests for Implicit Construction cases of Decimal.'''
       
   547 
       
   548     def test_implicit_from_None(self):
       
   549         self.assertRaises(TypeError, eval, 'Decimal(5) + None', globals())
       
   550 
       
   551     def test_implicit_from_int(self):
       
   552         #normal
       
   553         self.assertEqual(str(Decimal(5) + 45), '50')
       
   554         #exceeding precision
       
   555         self.assertEqual(Decimal(5) + 123456789000, Decimal(123456789000))
       
   556 
       
   557     def test_implicit_from_string(self):
       
   558         self.assertRaises(TypeError, eval, 'Decimal(5) + "3"', globals())
       
   559 
       
   560     def test_implicit_from_float(self):
       
   561         self.assertRaises(TypeError, eval, 'Decimal(5) + 2.2', globals())
       
   562 
       
   563     def test_implicit_from_Decimal(self):
       
   564         self.assertEqual(Decimal(5) + Decimal(45), Decimal(50))
       
   565 
       
   566     def test_rop(self):
       
   567         # Allow other classes to be trained to interact with Decimals
       
   568         class E:
       
   569             def __divmod__(self, other):
       
   570                 return 'divmod ' + str(other)
       
   571             def __rdivmod__(self, other):
       
   572                 return str(other) + ' rdivmod'
       
   573             def __lt__(self, other):
       
   574                 return 'lt ' + str(other)
       
   575             def __gt__(self, other):
       
   576                 return 'gt ' + str(other)
       
   577             def __le__(self, other):
       
   578                 return 'le ' + str(other)
       
   579             def __ge__(self, other):
       
   580                 return 'ge ' + str(other)
       
   581             def __eq__(self, other):
       
   582                 return 'eq ' + str(other)
       
   583             def __ne__(self, other):
       
   584                 return 'ne ' + str(other)
       
   585 
       
   586         self.assertEqual(divmod(E(), Decimal(10)), 'divmod 10')
       
   587         self.assertEqual(divmod(Decimal(10), E()), '10 rdivmod')
       
   588         self.assertEqual(eval('Decimal(10) < E()'), 'gt 10')
       
   589         self.assertEqual(eval('Decimal(10) > E()'), 'lt 10')
       
   590         self.assertEqual(eval('Decimal(10) <= E()'), 'ge 10')
       
   591         self.assertEqual(eval('Decimal(10) >= E()'), 'le 10')
       
   592         self.assertEqual(eval('Decimal(10) == E()'), 'eq 10')
       
   593         self.assertEqual(eval('Decimal(10) != E()'), 'ne 10')
       
   594 
       
   595         # insert operator methods and then exercise them
       
   596         oplist = [
       
   597             ('+', '__add__', '__radd__'),
       
   598             ('-', '__sub__', '__rsub__'),
       
   599             ('*', '__mul__', '__rmul__'),
       
   600             ('%', '__mod__', '__rmod__'),
       
   601             ('//', '__floordiv__', '__rfloordiv__'),
       
   602             ('**', '__pow__', '__rpow__')
       
   603         ]
       
   604         if 1/2 == 0:
       
   605             # testing with classic division, so add __div__
       
   606             oplist.append(('/', '__div__', '__rdiv__'))
       
   607         else:
       
   608             # testing with -Qnew, so add __truediv__
       
   609             oplist.append(('/', '__truediv__', '__rtruediv__'))
       
   610 
       
   611         for sym, lop, rop in oplist:
       
   612             setattr(E, lop, lambda self, other: 'str' + lop + str(other))
       
   613             setattr(E, rop, lambda self, other: str(other) + rop + 'str')
       
   614             self.assertEqual(eval('E()' + sym + 'Decimal(10)'),
       
   615                              'str' + lop + '10')
       
   616             self.assertEqual(eval('Decimal(10)' + sym + 'E()'),
       
   617                              '10' + rop + 'str')
       
   618 
       
   619 class DecimalFormatTest(unittest.TestCase):
       
   620     '''Unit tests for the format function.'''
       
   621     def test_formatting(self):
       
   622         # triples giving a format, a Decimal, and the expected result
       
   623         test_values = [
       
   624             ('e', '0E-15', '0e-15'),
       
   625             ('e', '2.3E-15', '2.3e-15'),
       
   626             ('e', '2.30E+2', '2.30e+2'), # preserve significant zeros
       
   627             ('e', '2.30000E-15', '2.30000e-15'),
       
   628             ('e', '1.23456789123456789e40', '1.23456789123456789e+40'),
       
   629             ('e', '1.5', '1.5e+0'),
       
   630             ('e', '0.15', '1.5e-1'),
       
   631             ('e', '0.015', '1.5e-2'),
       
   632             ('e', '0.0000000000015', '1.5e-12'),
       
   633             ('e', '15.0', '1.50e+1'),
       
   634             ('e', '-15', '-1.5e+1'),
       
   635             ('e', '0', '0e+0'),
       
   636             ('e', '0E1', '0e+1'),
       
   637             ('e', '0.0', '0e-1'),
       
   638             ('e', '0.00', '0e-2'),
       
   639             ('.6e', '0E-15', '0.000000e-9'),
       
   640             ('.6e', '0', '0.000000e+6'),
       
   641             ('.6e', '9.999999', '9.999999e+0'),
       
   642             ('.6e', '9.9999999', '1.000000e+1'),
       
   643             ('.6e', '-1.23e5', '-1.230000e+5'),
       
   644             ('.6e', '1.23456789e-3', '1.234568e-3'),
       
   645             ('f', '0', '0'),
       
   646             ('f', '0.0', '0.0'),
       
   647             ('f', '0E-2', '0.00'),
       
   648             ('f', '0.00E-8', '0.0000000000'),
       
   649             ('f', '0E1', '0'), # loses exponent information
       
   650             ('f', '3.2E1', '32'),
       
   651             ('f', '3.2E2', '320'),
       
   652             ('f', '3.20E2', '320'),
       
   653             ('f', '3.200E2', '320.0'),
       
   654             ('f', '3.2E-6', '0.0000032'),
       
   655             ('.6f', '0E-15', '0.000000'), # all zeros treated equally
       
   656             ('.6f', '0E1', '0.000000'),
       
   657             ('.6f', '0', '0.000000'),
       
   658             ('.0f', '0', '0'), # no decimal point
       
   659             ('.0f', '0e-2', '0'),
       
   660             ('.0f', '3.14159265', '3'),
       
   661             ('.1f', '3.14159265', '3.1'),
       
   662             ('.4f', '3.14159265', '3.1416'),
       
   663             ('.6f', '3.14159265', '3.141593'),
       
   664             ('.7f', '3.14159265', '3.1415926'), # round-half-even!
       
   665             ('.8f', '3.14159265', '3.14159265'),
       
   666             ('.9f', '3.14159265', '3.141592650'),
       
   667 
       
   668             ('g', '0', '0'),
       
   669             ('g', '0.0', '0.0'),
       
   670             ('g', '0E1', '0e+1'),
       
   671             ('G', '0E1', '0E+1'),
       
   672             ('g', '0E-5', '0.00000'),
       
   673             ('g', '0E-6', '0.000000'),
       
   674             ('g', '0E-7', '0e-7'),
       
   675             ('g', '-0E2', '-0e+2'),
       
   676             ('.0g', '3.14159265', '3'),  # 0 sig fig -> 1 sig fig
       
   677             ('.1g', '3.14159265', '3'),
       
   678             ('.2g', '3.14159265', '3.1'),
       
   679             ('.5g', '3.14159265', '3.1416'),
       
   680             ('.7g', '3.14159265', '3.141593'),
       
   681             ('.8g', '3.14159265', '3.1415926'), # round-half-even!
       
   682             ('.9g', '3.14159265', '3.14159265'),
       
   683             ('.10g', '3.14159265', '3.14159265'), # don't pad
       
   684 
       
   685             ('%', '0E1', '0%'),
       
   686             ('%', '0E0', '0%'),
       
   687             ('%', '0E-1', '0%'),
       
   688             ('%', '0E-2', '0%'),
       
   689             ('%', '0E-3', '0.0%'),
       
   690             ('%', '0E-4', '0.00%'),
       
   691 
       
   692             ('.3%', '0', '0.000%'), # all zeros treated equally
       
   693             ('.3%', '0E10', '0.000%'),
       
   694             ('.3%', '0E-10', '0.000%'),
       
   695             ('.3%', '2.34', '234.000%'),
       
   696             ('.3%', '1.234567', '123.457%'),
       
   697             ('.0%', '1.23', '123%'),
       
   698 
       
   699             ('e', 'NaN', 'NaN'),
       
   700             ('f', '-NaN123', '-NaN123'),
       
   701             ('+g', 'NaN456', '+NaN456'),
       
   702             ('.3e', 'Inf', 'Infinity'),
       
   703             ('.16f', '-Inf', '-Infinity'),
       
   704             ('.0g', '-sNaN', '-sNaN'),
       
   705 
       
   706             ('', '1.00', '1.00'),
       
   707             ]
       
   708         for fmt, d, result in test_values:
       
   709             self.assertEqual(format(Decimal(d), fmt), result)
       
   710 
       
   711 class DecimalArithmeticOperatorsTest(unittest.TestCase):
       
   712     '''Unit tests for all arithmetic operators, binary and unary.'''
       
   713 
       
   714     def test_addition(self):
       
   715 
       
   716         d1 = Decimal('-11.1')
       
   717         d2 = Decimal('22.2')
       
   718 
       
   719         #two Decimals
       
   720         self.assertEqual(d1+d2, Decimal('11.1'))
       
   721         self.assertEqual(d2+d1, Decimal('11.1'))
       
   722 
       
   723         #with other type, left
       
   724         c = d1 + 5
       
   725         self.assertEqual(c, Decimal('-6.1'))
       
   726         self.assertEqual(type(c), type(d1))
       
   727 
       
   728         #with other type, right
       
   729         c = 5 + d1
       
   730         self.assertEqual(c, Decimal('-6.1'))
       
   731         self.assertEqual(type(c), type(d1))
       
   732 
       
   733         #inline with decimal
       
   734         d1 += d2
       
   735         self.assertEqual(d1, Decimal('11.1'))
       
   736 
       
   737         #inline with other type
       
   738         d1 += 5
       
   739         self.assertEqual(d1, Decimal('16.1'))
       
   740 
       
   741     def test_subtraction(self):
       
   742 
       
   743         d1 = Decimal('-11.1')
       
   744         d2 = Decimal('22.2')
       
   745 
       
   746         #two Decimals
       
   747         self.assertEqual(d1-d2, Decimal('-33.3'))
       
   748         self.assertEqual(d2-d1, Decimal('33.3'))
       
   749 
       
   750         #with other type, left
       
   751         c = d1 - 5
       
   752         self.assertEqual(c, Decimal('-16.1'))
       
   753         self.assertEqual(type(c), type(d1))
       
   754 
       
   755         #with other type, right
       
   756         c = 5 - d1
       
   757         self.assertEqual(c, Decimal('16.1'))
       
   758         self.assertEqual(type(c), type(d1))
       
   759 
       
   760         #inline with decimal
       
   761         d1 -= d2
       
   762         self.assertEqual(d1, Decimal('-33.3'))
       
   763 
       
   764         #inline with other type
       
   765         d1 -= 5
       
   766         self.assertEqual(d1, Decimal('-38.3'))
       
   767 
       
   768     def test_multiplication(self):
       
   769 
       
   770         d1 = Decimal('-5')
       
   771         d2 = Decimal('3')
       
   772 
       
   773         #two Decimals
       
   774         self.assertEqual(d1*d2, Decimal('-15'))
       
   775         self.assertEqual(d2*d1, Decimal('-15'))
       
   776 
       
   777         #with other type, left
       
   778         c = d1 * 5
       
   779         self.assertEqual(c, Decimal('-25'))
       
   780         self.assertEqual(type(c), type(d1))
       
   781 
       
   782         #with other type, right
       
   783         c = 5 * d1
       
   784         self.assertEqual(c, Decimal('-25'))
       
   785         self.assertEqual(type(c), type(d1))
       
   786 
       
   787         #inline with decimal
       
   788         d1 *= d2
       
   789         self.assertEqual(d1, Decimal('-15'))
       
   790 
       
   791         #inline with other type
       
   792         d1 *= 5
       
   793         self.assertEqual(d1, Decimal('-75'))
       
   794 
       
   795     def test_division(self):
       
   796 
       
   797         d1 = Decimal('-5')
       
   798         d2 = Decimal('2')
       
   799 
       
   800         #two Decimals
       
   801         self.assertEqual(d1/d2, Decimal('-2.5'))
       
   802         self.assertEqual(d2/d1, Decimal('-0.4'))
       
   803 
       
   804         #with other type, left
       
   805         c = d1 / 4
       
   806         self.assertEqual(c, Decimal('-1.25'))
       
   807         self.assertEqual(type(c), type(d1))
       
   808 
       
   809         #with other type, right
       
   810         c = 4 / d1
       
   811         self.assertEqual(c, Decimal('-0.8'))
       
   812         self.assertEqual(type(c), type(d1))
       
   813 
       
   814         #inline with decimal
       
   815         d1 /= d2
       
   816         self.assertEqual(d1, Decimal('-2.5'))
       
   817 
       
   818         #inline with other type
       
   819         d1 /= 4
       
   820         self.assertEqual(d1, Decimal('-0.625'))
       
   821 
       
   822     def test_floor_division(self):
       
   823 
       
   824         d1 = Decimal('5')
       
   825         d2 = Decimal('2')
       
   826 
       
   827         #two Decimals
       
   828         self.assertEqual(d1//d2, Decimal('2'))
       
   829         self.assertEqual(d2//d1, Decimal('0'))
       
   830 
       
   831         #with other type, left
       
   832         c = d1 // 4
       
   833         self.assertEqual(c, Decimal('1'))
       
   834         self.assertEqual(type(c), type(d1))
       
   835 
       
   836         #with other type, right
       
   837         c = 7 // d1
       
   838         self.assertEqual(c, Decimal('1'))
       
   839         self.assertEqual(type(c), type(d1))
       
   840 
       
   841         #inline with decimal
       
   842         d1 //= d2
       
   843         self.assertEqual(d1, Decimal('2'))
       
   844 
       
   845         #inline with other type
       
   846         d1 //= 2
       
   847         self.assertEqual(d1, Decimal('1'))
       
   848 
       
   849     def test_powering(self):
       
   850 
       
   851         d1 = Decimal('5')
       
   852         d2 = Decimal('2')
       
   853 
       
   854         #two Decimals
       
   855         self.assertEqual(d1**d2, Decimal('25'))
       
   856         self.assertEqual(d2**d1, Decimal('32'))
       
   857 
       
   858         #with other type, left
       
   859         c = d1 ** 4
       
   860         self.assertEqual(c, Decimal('625'))
       
   861         self.assertEqual(type(c), type(d1))
       
   862 
       
   863         #with other type, right
       
   864         c = 7 ** d1
       
   865         self.assertEqual(c, Decimal('16807'))
       
   866         self.assertEqual(type(c), type(d1))
       
   867 
       
   868         #inline with decimal
       
   869         d1 **= d2
       
   870         self.assertEqual(d1, Decimal('25'))
       
   871 
       
   872         #inline with other type
       
   873         d1 **= 4
       
   874         self.assertEqual(d1, Decimal('390625'))
       
   875 
       
   876     def test_module(self):
       
   877 
       
   878         d1 = Decimal('5')
       
   879         d2 = Decimal('2')
       
   880 
       
   881         #two Decimals
       
   882         self.assertEqual(d1%d2, Decimal('1'))
       
   883         self.assertEqual(d2%d1, Decimal('2'))
       
   884 
       
   885         #with other type, left
       
   886         c = d1 % 4
       
   887         self.assertEqual(c, Decimal('1'))
       
   888         self.assertEqual(type(c), type(d1))
       
   889 
       
   890         #with other type, right
       
   891         c = 7 % d1
       
   892         self.assertEqual(c, Decimal('2'))
       
   893         self.assertEqual(type(c), type(d1))
       
   894 
       
   895         #inline with decimal
       
   896         d1 %= d2
       
   897         self.assertEqual(d1, Decimal('1'))
       
   898 
       
   899         #inline with other type
       
   900         d1 %= 4
       
   901         self.assertEqual(d1, Decimal('1'))
       
   902 
       
   903     def test_floor_div_module(self):
       
   904 
       
   905         d1 = Decimal('5')
       
   906         d2 = Decimal('2')
       
   907 
       
   908         #two Decimals
       
   909         (p, q) = divmod(d1, d2)
       
   910         self.assertEqual(p, Decimal('2'))
       
   911         self.assertEqual(q, Decimal('1'))
       
   912         self.assertEqual(type(p), type(d1))
       
   913         self.assertEqual(type(q), type(d1))
       
   914 
       
   915         #with other type, left
       
   916         (p, q) = divmod(d1, 4)
       
   917         self.assertEqual(p, Decimal('1'))
       
   918         self.assertEqual(q, Decimal('1'))
       
   919         self.assertEqual(type(p), type(d1))
       
   920         self.assertEqual(type(q), type(d1))
       
   921 
       
   922         #with other type, right
       
   923         (p, q) = divmod(7, d1)
       
   924         self.assertEqual(p, Decimal('1'))
       
   925         self.assertEqual(q, Decimal('2'))
       
   926         self.assertEqual(type(p), type(d1))
       
   927         self.assertEqual(type(q), type(d1))
       
   928 
       
   929     def test_unary_operators(self):
       
   930         self.assertEqual(+Decimal(45), Decimal(+45))           #  +
       
   931         self.assertEqual(-Decimal(45), Decimal(-45))           #  -
       
   932         self.assertEqual(abs(Decimal(45)), abs(Decimal(-45)))  # abs
       
   933 
       
   934     def test_nan_comparisons(self):
       
   935         n = Decimal('NaN')
       
   936         s = Decimal('sNaN')
       
   937         i = Decimal('Inf')
       
   938         f = Decimal('2')
       
   939         for x, y in [(n, n), (n, i), (i, n), (n, f), (f, n),
       
   940                      (s, n), (n, s), (s, i), (i, s), (s, f), (f, s), (s, s)]:
       
   941             self.assert_(x != y)
       
   942             self.assert_(not (x == y))
       
   943             self.assert_(not (x < y))
       
   944             self.assert_(not (x <= y))
       
   945             self.assert_(not (x > y))
       
   946             self.assert_(not (x >= y))
       
   947 
       
   948 # The following are two functions used to test threading in the next class
       
   949 
       
   950 def thfunc1(cls):
       
   951     d1 = Decimal(1)
       
   952     d3 = Decimal(3)
       
   953     test1 = d1/d3
       
   954     cls.synchro.wait()
       
   955     test2 = d1/d3
       
   956     cls.finish1.set()
       
   957 
       
   958     cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
       
   959     cls.assertEqual(test2, Decimal('0.3333333333333333333333333333'))
       
   960     return
       
   961 
       
   962 def thfunc2(cls):
       
   963     d1 = Decimal(1)
       
   964     d3 = Decimal(3)
       
   965     test1 = d1/d3
       
   966     thiscontext = getcontext()
       
   967     thiscontext.prec = 18
       
   968     test2 = d1/d3
       
   969     cls.synchro.set()
       
   970     cls.finish2.set()
       
   971 
       
   972     cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
       
   973     cls.assertEqual(test2, Decimal('0.333333333333333333'))
       
   974     return
       
   975 
       
   976 
       
   977 class DecimalUseOfContextTest(unittest.TestCase):
       
   978     '''Unit tests for Use of Context cases in Decimal.'''
       
   979 
       
   980     try:
       
   981         import threading
       
   982     except ImportError:
       
   983         threading = None
       
   984 
       
   985     # Take care executing this test from IDLE, there's an issue in threading
       
   986     # that hangs IDLE and I couldn't find it
       
   987 
       
   988     def test_threading(self):
       
   989         #Test the "threading isolation" of a Context.
       
   990 
       
   991         self.synchro = threading.Event()
       
   992         self.finish1 = threading.Event()
       
   993         self.finish2 = threading.Event()
       
   994 
       
   995         th1 = threading.Thread(target=thfunc1, args=(self,))
       
   996         th2 = threading.Thread(target=thfunc2, args=(self,))
       
   997 
       
   998         th1.start()
       
   999         th2.start()
       
  1000 
       
  1001         self.finish1.wait()
       
  1002         self.finish2.wait()
       
  1003         return
       
  1004 
       
  1005     if threading is None:
       
  1006         del test_threading
       
  1007 
       
  1008 
       
  1009 class DecimalUsabilityTest(unittest.TestCase):
       
  1010     '''Unit tests for Usability cases of Decimal.'''
       
  1011 
       
  1012     def test_comparison_operators(self):
       
  1013 
       
  1014         da = Decimal('23.42')
       
  1015         db = Decimal('23.42')
       
  1016         dc = Decimal('45')
       
  1017 
       
  1018         #two Decimals
       
  1019         self.failUnless(dc > da)
       
  1020         self.failUnless(dc >= da)
       
  1021         self.failUnless(da < dc)
       
  1022         self.failUnless(da <= dc)
       
  1023         self.failUnless(da == db)
       
  1024         self.failUnless(da != dc)
       
  1025         self.failUnless(da <= db)
       
  1026         self.failUnless(da >= db)
       
  1027         self.assertEqual(cmp(dc,da), 1)
       
  1028         self.assertEqual(cmp(da,dc), -1)
       
  1029         self.assertEqual(cmp(da,db), 0)
       
  1030 
       
  1031         #a Decimal and an int
       
  1032         self.failUnless(dc > 23)
       
  1033         self.failUnless(23 < dc)
       
  1034         self.failUnless(dc == 45)
       
  1035         self.assertEqual(cmp(dc,23), 1)
       
  1036         self.assertEqual(cmp(23,dc), -1)
       
  1037         self.assertEqual(cmp(dc,45), 0)
       
  1038 
       
  1039         #a Decimal and uncomparable
       
  1040         self.assertNotEqual(da, 'ugly')
       
  1041         self.assertNotEqual(da, 32.7)
       
  1042         self.assertNotEqual(da, object())
       
  1043         self.assertNotEqual(da, object)
       
  1044 
       
  1045         # sortable
       
  1046         a = map(Decimal, xrange(100))
       
  1047         b =  a[:]
       
  1048         random.shuffle(a)
       
  1049         a.sort()
       
  1050         self.assertEqual(a, b)
       
  1051 
       
  1052         # with None
       
  1053         self.assertFalse(Decimal(1) < None)
       
  1054         self.assertTrue(Decimal(1) > None)
       
  1055 
       
  1056     def test_copy_and_deepcopy_methods(self):
       
  1057         d = Decimal('43.24')
       
  1058         c = copy.copy(d)
       
  1059         self.assertEqual(id(c), id(d))
       
  1060         dc = copy.deepcopy(d)
       
  1061         self.assertEqual(id(dc), id(d))
       
  1062 
       
  1063     def test_hash_method(self):
       
  1064         #just that it's hashable
       
  1065         hash(Decimal(23))
       
  1066 
       
  1067         test_values = [Decimal(sign*(2**m + n))
       
  1068                        for m in [0, 14, 15, 16, 17, 30, 31,
       
  1069                                  32, 33, 62, 63, 64, 65, 66]
       
  1070                        for n in range(-10, 10)
       
  1071                        for sign in [-1, 1]]
       
  1072         test_values.extend([
       
  1073                 Decimal("-0"), # zeros
       
  1074                 Decimal("0.00"),
       
  1075                 Decimal("-0.000"),
       
  1076                 Decimal("0E10"),
       
  1077                 Decimal("-0E12"),
       
  1078                 Decimal("10.0"), # negative exponent
       
  1079                 Decimal("-23.00000"),
       
  1080                 Decimal("1230E100"), # positive exponent
       
  1081                 Decimal("-4.5678E50"),
       
  1082                 # a value for which hash(n) != hash(n % (2**64-1))
       
  1083                 # in Python pre-2.6
       
  1084                 Decimal(2**64 + 2**32 - 1),
       
  1085                 # selection of values which fail with the old (before
       
  1086                 # version 2.6) long.__hash__
       
  1087                 Decimal("1.634E100"),
       
  1088                 Decimal("90.697E100"),
       
  1089                 Decimal("188.83E100"),
       
  1090                 Decimal("1652.9E100"),
       
  1091                 Decimal("56531E100"),
       
  1092                 ])
       
  1093 
       
  1094         # check that hash(d) == hash(int(d)) for integral values
       
  1095         for value in test_values:
       
  1096             self.assertEqual(hash(value), hash(int(value)))
       
  1097 
       
  1098         #the same hash that to an int
       
  1099         self.assertEqual(hash(Decimal(23)), hash(23))
       
  1100         self.assertRaises(TypeError, hash, Decimal('NaN'))
       
  1101         self.assert_(hash(Decimal('Inf')))
       
  1102         self.assert_(hash(Decimal('-Inf')))
       
  1103 
       
  1104         # check that the value of the hash doesn't depend on the
       
  1105         # current context (issue #1757)
       
  1106         c = getcontext()
       
  1107         old_precision = c.prec
       
  1108         x = Decimal("123456789.1")
       
  1109 
       
  1110         c.prec = 6
       
  1111         h1 = hash(x)
       
  1112         c.prec = 10
       
  1113         h2 = hash(x)
       
  1114         c.prec = 16
       
  1115         h3 = hash(x)
       
  1116 
       
  1117         self.assertEqual(h1, h2)
       
  1118         self.assertEqual(h1, h3)
       
  1119         c.prec = old_precision
       
  1120 
       
  1121     def test_min_and_max_methods(self):
       
  1122 
       
  1123         d1 = Decimal('15.32')
       
  1124         d2 = Decimal('28.5')
       
  1125         l1 = 15
       
  1126         l2 = 28
       
  1127 
       
  1128         #between Decimals
       
  1129         self.failUnless(min(d1,d2) is d1)
       
  1130         self.failUnless(min(d2,d1) is d1)
       
  1131         self.failUnless(max(d1,d2) is d2)
       
  1132         self.failUnless(max(d2,d1) is d2)
       
  1133 
       
  1134         #between Decimal and long
       
  1135         self.failUnless(min(d1,l2) is d1)
       
  1136         self.failUnless(min(l2,d1) is d1)
       
  1137         self.failUnless(max(l1,d2) is d2)
       
  1138         self.failUnless(max(d2,l1) is d2)
       
  1139 
       
  1140     def test_as_nonzero(self):
       
  1141         #as false
       
  1142         self.failIf(Decimal(0))
       
  1143         #as true
       
  1144         self.failUnless(Decimal('0.372'))
       
  1145 
       
  1146     def test_tostring_methods(self):
       
  1147         #Test str and repr methods.
       
  1148 
       
  1149         d = Decimal('15.32')
       
  1150         self.assertEqual(str(d), '15.32')               # str
       
  1151         self.assertEqual(repr(d), "Decimal('15.32')")   # repr
       
  1152 
       
  1153         # result type of string methods should be str, not unicode
       
  1154         unicode_inputs = [u'123.4', u'0.5E2', u'Infinity', u'sNaN',
       
  1155                           u'-0.0E100', u'-NaN001', u'-Inf']
       
  1156 
       
  1157         for u in unicode_inputs:
       
  1158             d = Decimal(u)
       
  1159             self.assertEqual(type(str(d)), str)
       
  1160             self.assertEqual(type(repr(d)), str)
       
  1161             self.assertEqual(type(d.to_eng_string()), str)
       
  1162 
       
  1163     def test_tonum_methods(self):
       
  1164         #Test float, int and long methods.
       
  1165 
       
  1166         d1 = Decimal('66')
       
  1167         d2 = Decimal('15.32')
       
  1168 
       
  1169         #int
       
  1170         self.assertEqual(int(d1), 66)
       
  1171         self.assertEqual(int(d2), 15)
       
  1172 
       
  1173         #long
       
  1174         self.assertEqual(long(d1), 66)
       
  1175         self.assertEqual(long(d2), 15)
       
  1176 
       
  1177         #float
       
  1178         self.assertEqual(float(d1), 66)
       
  1179         self.assertEqual(float(d2), 15.32)
       
  1180 
       
  1181     def test_eval_round_trip(self):
       
  1182 
       
  1183         #with zero
       
  1184         d = Decimal( (0, (0,), 0) )
       
  1185         self.assertEqual(d, eval(repr(d)))
       
  1186 
       
  1187         #int
       
  1188         d = Decimal( (1, (4, 5), 0) )
       
  1189         self.assertEqual(d, eval(repr(d)))
       
  1190 
       
  1191         #float
       
  1192         d = Decimal( (0, (4, 5, 3, 4), -2) )
       
  1193         self.assertEqual(d, eval(repr(d)))
       
  1194 
       
  1195         #weird
       
  1196         d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
       
  1197         self.assertEqual(d, eval(repr(d)))
       
  1198 
       
  1199     def test_as_tuple(self):
       
  1200 
       
  1201         #with zero
       
  1202         d = Decimal(0)
       
  1203         self.assertEqual(d.as_tuple(), (0, (0,), 0) )
       
  1204 
       
  1205         #int
       
  1206         d = Decimal(-45)
       
  1207         self.assertEqual(d.as_tuple(), (1, (4, 5), 0) )
       
  1208 
       
  1209         #complicated string
       
  1210         d = Decimal("-4.34913534E-17")
       
  1211         self.assertEqual(d.as_tuple(), (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
       
  1212 
       
  1213         #inf
       
  1214         d = Decimal("Infinity")
       
  1215         self.assertEqual(d.as_tuple(), (0, (0,), 'F') )
       
  1216 
       
  1217         #leading zeros in coefficient should be stripped
       
  1218         d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), -2) )
       
  1219         self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), -2) )
       
  1220         d = Decimal( (1, (0, 0, 0), 37) )
       
  1221         self.assertEqual(d.as_tuple(), (1, (0,), 37))
       
  1222         d = Decimal( (1, (), 37) )
       
  1223         self.assertEqual(d.as_tuple(), (1, (0,), 37))
       
  1224 
       
  1225         #leading zeros in NaN diagnostic info should be stripped
       
  1226         d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), 'n') )
       
  1227         self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), 'n') )
       
  1228         d = Decimal( (1, (0, 0, 0), 'N') )
       
  1229         self.assertEqual(d.as_tuple(), (1, (), 'N') )
       
  1230         d = Decimal( (1, (), 'n') )
       
  1231         self.assertEqual(d.as_tuple(), (1, (), 'n') )
       
  1232 
       
  1233         #coefficient in infinity should be ignored
       
  1234         d = Decimal( (0, (4, 5, 3, 4), 'F') )
       
  1235         self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
       
  1236         d = Decimal( (1, (0, 2, 7, 1), 'F') )
       
  1237         self.assertEqual(d.as_tuple(), (1, (0,), 'F'))
       
  1238 
       
  1239     def test_immutability_operations(self):
       
  1240         # Do operations and check that it didn't change change internal objects.
       
  1241 
       
  1242         d1 = Decimal('-25e55')
       
  1243         b1 = Decimal('-25e55')
       
  1244         d2 = Decimal('33e+33')
       
  1245         b2 = Decimal('33e+33')
       
  1246 
       
  1247         def checkSameDec(operation, useOther=False):
       
  1248             if useOther:
       
  1249                 eval("d1." + operation + "(d2)")
       
  1250                 self.assertEqual(d1._sign, b1._sign)
       
  1251                 self.assertEqual(d1._int, b1._int)
       
  1252                 self.assertEqual(d1._exp, b1._exp)
       
  1253                 self.assertEqual(d2._sign, b2._sign)
       
  1254                 self.assertEqual(d2._int, b2._int)
       
  1255                 self.assertEqual(d2._exp, b2._exp)
       
  1256             else:
       
  1257                 eval("d1." + operation + "()")
       
  1258                 self.assertEqual(d1._sign, b1._sign)
       
  1259                 self.assertEqual(d1._int, b1._int)
       
  1260                 self.assertEqual(d1._exp, b1._exp)
       
  1261             return
       
  1262 
       
  1263         Decimal(d1)
       
  1264         self.assertEqual(d1._sign, b1._sign)
       
  1265         self.assertEqual(d1._int, b1._int)
       
  1266         self.assertEqual(d1._exp, b1._exp)
       
  1267 
       
  1268         checkSameDec("__abs__")
       
  1269         checkSameDec("__add__", True)
       
  1270         checkSameDec("__div__", True)
       
  1271         checkSameDec("__divmod__", True)
       
  1272         checkSameDec("__eq__", True)
       
  1273         checkSameDec("__ne__", True)
       
  1274         checkSameDec("__le__", True)
       
  1275         checkSameDec("__lt__", True)
       
  1276         checkSameDec("__ge__", True)
       
  1277         checkSameDec("__gt__", True)
       
  1278         checkSameDec("__float__")
       
  1279         checkSameDec("__floordiv__", True)
       
  1280         checkSameDec("__hash__")
       
  1281         checkSameDec("__int__")
       
  1282         checkSameDec("__trunc__")
       
  1283         checkSameDec("__long__")
       
  1284         checkSameDec("__mod__", True)
       
  1285         checkSameDec("__mul__", True)
       
  1286         checkSameDec("__neg__")
       
  1287         checkSameDec("__nonzero__")
       
  1288         checkSameDec("__pos__")
       
  1289         checkSameDec("__pow__", True)
       
  1290         checkSameDec("__radd__", True)
       
  1291         checkSameDec("__rdiv__", True)
       
  1292         checkSameDec("__rdivmod__", True)
       
  1293         checkSameDec("__repr__")
       
  1294         checkSameDec("__rfloordiv__", True)
       
  1295         checkSameDec("__rmod__", True)
       
  1296         checkSameDec("__rmul__", True)
       
  1297         checkSameDec("__rpow__", True)
       
  1298         checkSameDec("__rsub__", True)
       
  1299         checkSameDec("__str__")
       
  1300         checkSameDec("__sub__", True)
       
  1301         checkSameDec("__truediv__", True)
       
  1302         checkSameDec("adjusted")
       
  1303         checkSameDec("as_tuple")
       
  1304         checkSameDec("compare", True)
       
  1305         checkSameDec("max", True)
       
  1306         checkSameDec("min", True)
       
  1307         checkSameDec("normalize")
       
  1308         checkSameDec("quantize", True)
       
  1309         checkSameDec("remainder_near", True)
       
  1310         checkSameDec("same_quantum", True)
       
  1311         checkSameDec("sqrt")
       
  1312         checkSameDec("to_eng_string")
       
  1313         checkSameDec("to_integral")
       
  1314 
       
  1315     def test_subclassing(self):
       
  1316         # Different behaviours when subclassing Decimal
       
  1317 
       
  1318         class MyDecimal(Decimal):
       
  1319             pass
       
  1320 
       
  1321         d1 = MyDecimal(1)
       
  1322         d2 = MyDecimal(2)
       
  1323         d = d1 + d2
       
  1324         self.assertTrue(type(d) is Decimal)
       
  1325 
       
  1326         d = d1.max(d2)
       
  1327         self.assertTrue(type(d) is Decimal)
       
  1328 
       
  1329     def test_implicit_context(self):
       
  1330         # Check results when context given implicitly.  (Issue 2478)
       
  1331         c = getcontext()
       
  1332         self.assertEqual(str(Decimal(0).sqrt()),
       
  1333                          str(c.sqrt(Decimal(0))))
       
  1334 
       
  1335 
       
  1336 class DecimalPythonAPItests(unittest.TestCase):
       
  1337 
       
  1338     def test_pickle(self):
       
  1339         d = Decimal('-3.141590000')
       
  1340         p = pickle.dumps(d)
       
  1341         e = pickle.loads(p)
       
  1342         self.assertEqual(d, e)
       
  1343 
       
  1344     def test_int(self):
       
  1345         for x in range(-250, 250):
       
  1346             s = '%0.2f' % (x / 100.0)
       
  1347             # should work the same as for floats
       
  1348             self.assertEqual(int(Decimal(s)), int(float(s)))
       
  1349             # should work the same as to_integral in the ROUND_DOWN mode
       
  1350             d = Decimal(s)
       
  1351             r = d.to_integral(ROUND_DOWN)
       
  1352             self.assertEqual(Decimal(int(d)), r)
       
  1353 
       
  1354     def test_trunc(self):
       
  1355         for x in range(-250, 250):
       
  1356             s = '%0.2f' % (x / 100.0)
       
  1357             # should work the same as for floats
       
  1358             self.assertEqual(int(Decimal(s)), int(float(s)))
       
  1359             # should work the same as to_integral in the ROUND_DOWN mode
       
  1360             d = Decimal(s)
       
  1361             r = d.to_integral(ROUND_DOWN)
       
  1362             self.assertEqual(Decimal(math.trunc(d)), r)
       
  1363 
       
  1364 class ContextAPItests(unittest.TestCase):
       
  1365 
       
  1366     def test_pickle(self):
       
  1367         c = Context()
       
  1368         e = pickle.loads(pickle.dumps(c))
       
  1369         for k in vars(c):
       
  1370             v1 = vars(c)[k]
       
  1371             v2 = vars(e)[k]
       
  1372             self.assertEqual(v1, v2)
       
  1373 
       
  1374     def test_equality_with_other_types(self):
       
  1375         self.assert_(Decimal(10) in ['a', 1.0, Decimal(10), (1,2), {}])
       
  1376         self.assert_(Decimal(10) not in ['a', 1.0, (1,2), {}])
       
  1377 
       
  1378     def test_copy(self):
       
  1379         # All copies should be deep
       
  1380         c = Context()
       
  1381         d = c.copy()
       
  1382         self.assertNotEqual(id(c), id(d))
       
  1383         self.assertNotEqual(id(c.flags), id(d.flags))
       
  1384         self.assertNotEqual(id(c.traps), id(d.traps))
       
  1385 
       
  1386 class WithStatementTest(unittest.TestCase):
       
  1387     # Can't do these as docstrings until Python 2.6
       
  1388     # as doctest can't handle __future__ statements
       
  1389 
       
  1390     def test_localcontext(self):
       
  1391         # Use a copy of the current context in the block
       
  1392         orig_ctx = getcontext()
       
  1393         with localcontext() as enter_ctx:
       
  1394             set_ctx = getcontext()
       
  1395         final_ctx = getcontext()
       
  1396         self.assert_(orig_ctx is final_ctx, 'did not restore context correctly')
       
  1397         self.assert_(orig_ctx is not set_ctx, 'did not copy the context')
       
  1398         self.assert_(set_ctx is enter_ctx, '__enter__ returned wrong context')
       
  1399 
       
  1400     def test_localcontextarg(self):
       
  1401         # Use a copy of the supplied context in the block
       
  1402         orig_ctx = getcontext()
       
  1403         new_ctx = Context(prec=42)
       
  1404         with localcontext(new_ctx) as enter_ctx:
       
  1405             set_ctx = getcontext()
       
  1406         final_ctx = getcontext()
       
  1407         self.assert_(orig_ctx is final_ctx, 'did not restore context correctly')
       
  1408         self.assert_(set_ctx.prec == new_ctx.prec, 'did not set correct context')
       
  1409         self.assert_(new_ctx is not set_ctx, 'did not copy the context')
       
  1410         self.assert_(set_ctx is enter_ctx, '__enter__ returned wrong context')
       
  1411 
       
  1412 class ContextFlags(unittest.TestCase):
       
  1413     def test_flags_irrelevant(self):
       
  1414         # check that the result (numeric result + flags raised) of an
       
  1415         # arithmetic operation doesn't depend on the current flags
       
  1416 
       
  1417         context = Context(prec=9, Emin = -999999999, Emax = 999999999,
       
  1418                     rounding=ROUND_HALF_EVEN, traps=[], flags=[])
       
  1419 
       
  1420         # operations that raise various flags, in the form (function, arglist)
       
  1421         operations = [
       
  1422             (context._apply, [Decimal("100E-1000000009")]),
       
  1423             (context.sqrt, [Decimal(2)]),
       
  1424             (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]),
       
  1425             (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]),
       
  1426             (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]),
       
  1427             ]
       
  1428 
       
  1429         # try various flags individually, then a whole lot at once
       
  1430         flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal],
       
  1431                     [Inexact, Rounded, Underflow, Clamped, Subnormal]]
       
  1432 
       
  1433         for fn, args in operations:
       
  1434             # find answer and flags raised using a clean context
       
  1435             context.clear_flags()
       
  1436             ans = fn(*args)
       
  1437             flags = [k for k, v in context.flags.items() if v]
       
  1438 
       
  1439             for extra_flags in flagsets:
       
  1440                 # set flags, before calling operation
       
  1441                 context.clear_flags()
       
  1442                 for flag in extra_flags:
       
  1443                     context._raise_error(flag)
       
  1444                 new_ans = fn(*args)
       
  1445 
       
  1446                 # flags that we expect to be set after the operation
       
  1447                 expected_flags = list(flags)
       
  1448                 for flag in extra_flags:
       
  1449                     if flag not in expected_flags:
       
  1450                         expected_flags.append(flag)
       
  1451                 expected_flags.sort()
       
  1452 
       
  1453                 # flags we actually got
       
  1454                 new_flags = [k for k,v in context.flags.items() if v]
       
  1455                 new_flags.sort()
       
  1456 
       
  1457                 self.assertEqual(ans, new_ans,
       
  1458                                  "operation produces different answers depending on flags set: " +
       
  1459                                  "expected %s, got %s." % (ans, new_ans))
       
  1460                 self.assertEqual(new_flags, expected_flags,
       
  1461                                   "operation raises different flags depending on flags set: " +
       
  1462                                   "expected %s, got %s" % (expected_flags, new_flags))
       
  1463 
       
  1464 def test_main(arith=False, verbose=None, todo_tests=None, debug=None):
       
  1465     """ Execute the tests.
       
  1466 
       
  1467     Runs all arithmetic tests if arith is True or if the "decimal" resource
       
  1468     is enabled in regrtest.py
       
  1469     """
       
  1470 
       
  1471     init()
       
  1472     global TEST_ALL, DEBUG
       
  1473     TEST_ALL = arith or is_resource_enabled('decimal')
       
  1474     DEBUG = debug
       
  1475 
       
  1476     if todo_tests is None:
       
  1477         test_classes = [
       
  1478             DecimalExplicitConstructionTest,
       
  1479             DecimalImplicitConstructionTest,
       
  1480             DecimalArithmeticOperatorsTest,
       
  1481             DecimalFormatTest,
       
  1482             DecimalUseOfContextTest,
       
  1483             DecimalUsabilityTest,
       
  1484             DecimalPythonAPItests,
       
  1485             ContextAPItests,
       
  1486             DecimalTest,
       
  1487             WithStatementTest,
       
  1488             ContextFlags
       
  1489         ]
       
  1490     else:
       
  1491         test_classes = [DecimalTest]
       
  1492 
       
  1493     # Dynamically build custom test definition for each file in the test
       
  1494     # directory and add the definitions to the DecimalTest class.  This
       
  1495     # procedure insures that new files do not get skipped.
       
  1496     for filename in os.listdir(directory):
       
  1497         if '.decTest' not in filename or filename.startswith("."):
       
  1498             continue
       
  1499         head, tail = filename.split('.')
       
  1500         if todo_tests is not None and head not in todo_tests:
       
  1501             continue
       
  1502         tester = lambda self, f=filename: self.eval_file(directory + f)
       
  1503         setattr(DecimalTest, 'test_' + head, tester)
       
  1504         del filename, head, tail, tester
       
  1505 
       
  1506 
       
  1507     try:
       
  1508         run_unittest(*test_classes)
       
  1509         if todo_tests is None:
       
  1510             import decimal as DecimalModule
       
  1511             run_doctest(DecimalModule, verbose)
       
  1512     finally:
       
  1513         setcontext(ORIGINAL_CONTEXT)
       
  1514 
       
  1515 if __name__ == '__main__':
       
  1516     import optparse
       
  1517     p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]")
       
  1518     p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test')
       
  1519     p.add_option('--skip',  '-s', action='store_true', help='skip over 90% of the arithmetic tests')
       
  1520     (opt, args) = p.parse_args()
       
  1521 
       
  1522     if opt.skip:
       
  1523         test_main(arith=False, verbose=True)
       
  1524     elif args:
       
  1525         test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug)
       
  1526     else:
       
  1527         test_main(arith=True, verbose=True)