Back to index

python3.2  3.2.2
test_decimal.py
Go to the documentation of this file.
00001 # Copyright (c) 2004 Python Software Foundation.
00002 # All rights reserved.
00003 
00004 # Written by Eric Price <eprice at tjhsst.edu>
00005 #    and Facundo Batista <facundo at taniquetil.com.ar>
00006 #    and Raymond Hettinger <python at rcn.com>
00007 #    and Aahz (aahz at pobox.com)
00008 #    and Tim Peters
00009 
00010 """
00011 These are the test cases for the Decimal module.
00012 
00013 There are two groups of tests, Arithmetic and Behaviour. The former test
00014 the Decimal arithmetic using the tests provided by Mike Cowlishaw. The latter
00015 test the pythonic behaviour according to PEP 327.
00016 
00017 Cowlishaw's tests can be downloaded from:
00018 
00019    www2.hursley.ibm.com/decimal/dectest.zip
00020 
00021 This test module can be called from command line with one parameter (Arithmetic
00022 or Behaviour) to test each part, or without parameter to test both parts. If
00023 you're working through IDLE, you can import this test module and call test_main()
00024 with the corresponding argument.
00025 """
00026 
00027 import math
00028 import os, sys
00029 import operator
00030 import warnings
00031 import pickle, copy
00032 import unittest
00033 from decimal import *
00034 import numbers
00035 from test.support import (run_unittest, run_doctest, is_resource_enabled,
00036                           requires_IEEE_754)
00037 from test.support import check_warnings
00038 import random
00039 try:
00040     import threading
00041 except ImportError:
00042     threading = None
00043 
00044 # Useful Test Constant
00045 Signals = tuple(getcontext().flags.keys())
00046 
00047 # Signals ordered with respect to precedence: when an operation
00048 # produces multiple signals, signals occurring later in the list
00049 # should be handled before those occurring earlier in the list.
00050 OrderedSignals = (Clamped, Rounded, Inexact, Subnormal,
00051                   Underflow, Overflow, DivisionByZero, InvalidOperation)
00052 
00053 # Tests are built around these assumed context defaults.
00054 # test_main() restores the original context.
00055 def init():
00056     global ORIGINAL_CONTEXT
00057     ORIGINAL_CONTEXT = getcontext().copy()
00058     DefaultTestContext = Context(
00059         prec = 9,
00060         rounding = ROUND_HALF_EVEN,
00061         traps = dict.fromkeys(Signals, 0)
00062         )
00063     setcontext(DefaultTestContext)
00064 
00065 TESTDATADIR = 'decimaltestdata'
00066 if __name__ == '__main__':
00067     file = sys.argv[0]
00068 else:
00069     file = __file__
00070 testdir = os.path.dirname(file) or os.curdir
00071 directory = testdir + os.sep + TESTDATADIR + os.sep
00072 
00073 skip_expected = not os.path.isdir(directory)
00074 
00075 # list of individual .decTest test ids that correspond to tests that
00076 # we're skipping for one reason or another.
00077 skipped_test_ids = set([
00078     # Skip implementation-specific scaleb tests.
00079     'scbx164',
00080     'scbx165',
00081 
00082     # For some operations (currently exp, ln, log10, power), the decNumber
00083     # reference implementation imposes additional restrictions on the context
00084     # and operands.  These restrictions are not part of the specification;
00085     # however, the effect of these restrictions does show up in some of the
00086     # testcases.  We skip testcases that violate these restrictions, since
00087     # Decimal behaves differently from decNumber for these testcases so these
00088     # testcases would otherwise fail.
00089     'expx901',
00090     'expx902',
00091     'expx903',
00092     'expx905',
00093     'lnx901',
00094     'lnx902',
00095     'lnx903',
00096     'lnx905',
00097     'logx901',
00098     'logx902',
00099     'logx903',
00100     'logx905',
00101     'powx1183',
00102     'powx1184',
00103     'powx4001',
00104     'powx4002',
00105     'powx4003',
00106     'powx4005',
00107     'powx4008',
00108     'powx4010',
00109     'powx4012',
00110     'powx4014',
00111     ])
00112 
00113 # Make sure it actually raises errors when not expected and caught in flags
00114 # Slower, since it runs some things several times.
00115 EXTENDEDERRORTEST = False
00116 
00117 #Map the test cases' error names to the actual errors
00118 ErrorNames = {'clamped' : Clamped,
00119               'conversion_syntax' : InvalidOperation,
00120               'division_by_zero' : DivisionByZero,
00121               'division_impossible' : InvalidOperation,
00122               'division_undefined' : InvalidOperation,
00123               'inexact' : Inexact,
00124               'invalid_context' : InvalidOperation,
00125               'invalid_operation' : InvalidOperation,
00126               'overflow' : Overflow,
00127               'rounded' : Rounded,
00128               'subnormal' : Subnormal,
00129               'underflow' : Underflow}
00130 
00131 
00132 def Nonfunction(*args):
00133     """Doesn't do anything."""
00134     return None
00135 
00136 RoundingDict = {'ceiling' : ROUND_CEILING, #Maps test-case names to roundings.
00137                 'down' : ROUND_DOWN,
00138                 'floor' : ROUND_FLOOR,
00139                 'half_down' : ROUND_HALF_DOWN,
00140                 'half_even' : ROUND_HALF_EVEN,
00141                 'half_up' : ROUND_HALF_UP,
00142                 'up' : ROUND_UP,
00143                 '05up' : ROUND_05UP}
00144 
00145 # Name adapter to be able to change the Decimal and Context
00146 # interface without changing the test files from Cowlishaw
00147 nameAdapter = {'and':'logical_and',
00148                'apply':'_apply',
00149                'class':'number_class',
00150                'comparesig':'compare_signal',
00151                'comparetotal':'compare_total',
00152                'comparetotmag':'compare_total_mag',
00153                'copy':'copy_decimal',
00154                'copyabs':'copy_abs',
00155                'copynegate':'copy_negate',
00156                'copysign':'copy_sign',
00157                'divideint':'divide_int',
00158                'invert':'logical_invert',
00159                'iscanonical':'is_canonical',
00160                'isfinite':'is_finite',
00161                'isinfinite':'is_infinite',
00162                'isnan':'is_nan',
00163                'isnormal':'is_normal',
00164                'isqnan':'is_qnan',
00165                'issigned':'is_signed',
00166                'issnan':'is_snan',
00167                'issubnormal':'is_subnormal',
00168                'iszero':'is_zero',
00169                'maxmag':'max_mag',
00170                'minmag':'min_mag',
00171                'nextminus':'next_minus',
00172                'nextplus':'next_plus',
00173                'nexttoward':'next_toward',
00174                'or':'logical_or',
00175                'reduce':'normalize',
00176                'remaindernear':'remainder_near',
00177                'samequantum':'same_quantum',
00178                'squareroot':'sqrt',
00179                'toeng':'to_eng_string',
00180                'tointegral':'to_integral_value',
00181                'tointegralx':'to_integral_exact',
00182                'tosci':'to_sci_string',
00183                'xor':'logical_xor',
00184               }
00185 
00186 # The following functions return True/False rather than a Decimal instance
00187 
00188 LOGICAL_FUNCTIONS = (
00189     'is_canonical',
00190     'is_finite',
00191     'is_infinite',
00192     'is_nan',
00193     'is_normal',
00194     'is_qnan',
00195     'is_signed',
00196     'is_snan',
00197     'is_subnormal',
00198     'is_zero',
00199     'same_quantum',
00200     )
00201 
00202 class DecimalTest(unittest.TestCase):
00203     """Class which tests the Decimal class against the test cases.
00204 
00205     Changed for unittest.
00206     """
00207     def setUp(self):
00208         self.context = Context()
00209         self.ignore_list = ['#']
00210         # Basically, a # means return NaN InvalidOperation.
00211         # Different from a sNaN in trim
00212 
00213         self.ChangeDict = {'precision' : self.change_precision,
00214                       'rounding' : self.change_rounding_method,
00215                       'maxexponent' : self.change_max_exponent,
00216                       'minexponent' : self.change_min_exponent,
00217                       'clamp' : self.change_clamp}
00218 
00219     def eval_file(self, file):
00220         global skip_expected
00221         if skip_expected:
00222             raise unittest.SkipTest
00223             return
00224         with open(file) as f:
00225             for line in f:
00226                 line = line.replace('\r\n', '').replace('\n', '')
00227                 #print line
00228                 try:
00229                     t = self.eval_line(line)
00230                 except DecimalException as exception:
00231                     #Exception raised where there shouldn't have been one.
00232                     self.fail('Exception "'+exception.__class__.__name__ + '" raised on line '+line)
00233 
00234         return
00235 
00236     def eval_line(self, s):
00237         if s.find(' -> ') >= 0 and s[:2] != '--' and not s.startswith('  --'):
00238             s = (s.split('->')[0] + '->' +
00239                  s.split('->')[1].split('--')[0]).strip()
00240         else:
00241             s = s.split('--')[0].strip()
00242 
00243         for ignore in self.ignore_list:
00244             if s.find(ignore) >= 0:
00245                 #print s.split()[0], 'NotImplemented--', ignore
00246                 return
00247         if not s:
00248             return
00249         elif ':' in s:
00250             return self.eval_directive(s)
00251         else:
00252             return self.eval_equation(s)
00253 
00254     def eval_directive(self, s):
00255         funct, value = (x.strip().lower() for x in s.split(':'))
00256         if funct == 'rounding':
00257             value = RoundingDict[value]
00258         else:
00259             try:
00260                 value = int(value)
00261             except ValueError:
00262                 pass
00263 
00264         funct = self.ChangeDict.get(funct, Nonfunction)
00265         funct(value)
00266 
00267     def eval_equation(self, s):
00268         #global DEFAULT_PRECISION
00269         #print DEFAULT_PRECISION
00270 
00271         if not TEST_ALL and random.random() < 0.90:
00272             return
00273 
00274         try:
00275             Sides = s.split('->')
00276             L = Sides[0].strip().split()
00277             id = L[0]
00278             if DEBUG:
00279                 print("Test ", id, end=" ")
00280             funct = L[1].lower()
00281             valstemp = L[2:]
00282             L = Sides[1].strip().split()
00283             ans = L[0]
00284             exceptions = L[1:]
00285         except (TypeError, AttributeError, IndexError):
00286             raise InvalidOperation
00287         def FixQuotes(val):
00288             val = val.replace("''", 'SingleQuote').replace('""', 'DoubleQuote')
00289             val = val.replace("'", '').replace('"', '')
00290             val = val.replace('SingleQuote', "'").replace('DoubleQuote', '"')
00291             return val
00292 
00293         if id in skipped_test_ids:
00294             return
00295 
00296         fname = nameAdapter.get(funct, funct)
00297         if fname == 'rescale':
00298             return
00299         funct = getattr(self.context, fname)
00300         vals = []
00301         conglomerate = ''
00302         quote = 0
00303         theirexceptions = [ErrorNames[x.lower()] for x in exceptions]
00304 
00305         for exception in Signals:
00306             self.context.traps[exception] = 1 #Catch these bugs...
00307         for exception in theirexceptions:
00308             self.context.traps[exception] = 0
00309         for i, val in enumerate(valstemp):
00310             if val.count("'") % 2 == 1:
00311                 quote = 1 - quote
00312             if quote:
00313                 conglomerate = conglomerate + ' ' + val
00314                 continue
00315             else:
00316                 val = conglomerate + val
00317                 conglomerate = ''
00318             v = FixQuotes(val)
00319             if fname in ('to_sci_string', 'to_eng_string'):
00320                 if EXTENDEDERRORTEST:
00321                     for error in theirexceptions:
00322                         self.context.traps[error] = 1
00323                         try:
00324                             funct(self.context.create_decimal(v))
00325                         except error:
00326                             pass
00327                         except Signals as e:
00328                             self.fail("Raised %s in %s when %s disabled" % \
00329                                       (e, s, error))
00330                         else:
00331                             self.fail("Did not raise %s in %s" % (error, s))
00332                         self.context.traps[error] = 0
00333                 v = self.context.create_decimal(v)
00334             else:
00335                 v = Decimal(v, self.context)
00336             vals.append(v)
00337 
00338         ans = FixQuotes(ans)
00339 
00340         if EXTENDEDERRORTEST and fname not in ('to_sci_string', 'to_eng_string'):
00341             for error in theirexceptions:
00342                 self.context.traps[error] = 1
00343                 try:
00344                     funct(*vals)
00345                 except error:
00346                     pass
00347                 except Signals as e:
00348                     self.fail("Raised %s in %s when %s disabled" % \
00349                               (e, s, error))
00350                 else:
00351                     self.fail("Did not raise %s in %s" % (error, s))
00352                 self.context.traps[error] = 0
00353 
00354             # as above, but add traps cumulatively, to check precedence
00355             ordered_errors = [e for e in OrderedSignals if e in theirexceptions]
00356             for error in ordered_errors:
00357                 self.context.traps[error] = 1
00358                 try:
00359                     funct(*vals)
00360                 except error:
00361                     pass
00362                 except Signals as e:
00363                     self.fail("Raised %s in %s; expected %s" %
00364                               (type(e), s, error))
00365                 else:
00366                     self.fail("Did not raise %s in %s" % (error, s))
00367             # reset traps
00368             for error in ordered_errors:
00369                 self.context.traps[error] = 0
00370 
00371 
00372         if DEBUG:
00373             print("--", self.context)
00374         try:
00375             result = str(funct(*vals))
00376             if fname in LOGICAL_FUNCTIONS:
00377                 result = str(int(eval(result))) # 'True', 'False' -> '1', '0'
00378         except Signals as error:
00379             self.fail("Raised %s in %s" % (error, s))
00380         except: #Catch any error long enough to state the test case.
00381             print("ERROR:", s)
00382             raise
00383 
00384         myexceptions = self.getexceptions()
00385         self.context.clear_flags()
00386 
00387         myexceptions.sort(key=repr)
00388         theirexceptions.sort(key=repr)
00389 
00390         self.assertEqual(result, ans,
00391                          'Incorrect answer for ' + s + ' -- got ' + result)
00392         self.assertEqual(myexceptions, theirexceptions,
00393               'Incorrect flags set in ' + s + ' -- got ' + str(myexceptions))
00394         return
00395 
00396     def getexceptions(self):
00397         return [e for e in Signals if self.context.flags[e]]
00398 
00399     def change_precision(self, prec):
00400         self.context.prec = prec
00401     def change_rounding_method(self, rounding):
00402         self.context.rounding = rounding
00403     def change_min_exponent(self, exp):
00404         self.context.Emin = exp
00405     def change_max_exponent(self, exp):
00406         self.context.Emax = exp
00407     def change_clamp(self, clamp):
00408         self.context.clamp = clamp
00409 
00410 
00411 
00412 # The following classes test the behaviour of Decimal according to PEP 327
00413 
00414 class DecimalExplicitConstructionTest(unittest.TestCase):
00415     '''Unit tests for Explicit Construction cases of Decimal.'''
00416 
00417     def test_explicit_empty(self):
00418         self.assertEqual(Decimal(), Decimal("0"))
00419 
00420     def test_explicit_from_None(self):
00421         self.assertRaises(TypeError, Decimal, None)
00422 
00423     def test_explicit_from_int(self):
00424 
00425         #positive
00426         d = Decimal(45)
00427         self.assertEqual(str(d), '45')
00428 
00429         #very large positive
00430         d = Decimal(500000123)
00431         self.assertEqual(str(d), '500000123')
00432 
00433         #negative
00434         d = Decimal(-45)
00435         self.assertEqual(str(d), '-45')
00436 
00437         #zero
00438         d = Decimal(0)
00439         self.assertEqual(str(d), '0')
00440 
00441     def test_explicit_from_string(self):
00442 
00443         #empty
00444         self.assertEqual(str(Decimal('')), 'NaN')
00445 
00446         #int
00447         self.assertEqual(str(Decimal('45')), '45')
00448 
00449         #float
00450         self.assertEqual(str(Decimal('45.34')), '45.34')
00451 
00452         #engineer notation
00453         self.assertEqual(str(Decimal('45e2')), '4.5E+3')
00454 
00455         #just not a number
00456         self.assertEqual(str(Decimal('ugly')), 'NaN')
00457 
00458         #leading and trailing whitespace permitted
00459         self.assertEqual(str(Decimal('1.3E4 \n')), '1.3E+4')
00460         self.assertEqual(str(Decimal('  -7.89')), '-7.89')
00461 
00462     def test_explicit_from_tuples(self):
00463 
00464         #zero
00465         d = Decimal( (0, (0,), 0) )
00466         self.assertEqual(str(d), '0')
00467 
00468         #int
00469         d = Decimal( (1, (4, 5), 0) )
00470         self.assertEqual(str(d), '-45')
00471 
00472         #float
00473         d = Decimal( (0, (4, 5, 3, 4), -2) )
00474         self.assertEqual(str(d), '45.34')
00475 
00476         #weird
00477         d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
00478         self.assertEqual(str(d), '-4.34913534E-17')
00479 
00480         #wrong number of items
00481         self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1)) )
00482 
00483         #bad sign
00484         self.assertRaises(ValueError, Decimal, (8, (4, 3, 4, 9, 1), 2) )
00485         self.assertRaises(ValueError, Decimal, (0., (4, 3, 4, 9, 1), 2) )
00486         self.assertRaises(ValueError, Decimal, (Decimal(1), (4, 3, 4, 9, 1), 2))
00487 
00488         #bad exp
00489         self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 'wrong!') )
00490         self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 0.) )
00491         self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), '1') )
00492 
00493         #bad coefficients
00494         self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, None, 1), 2) )
00495         self.assertRaises(ValueError, Decimal, (1, (4, -3, 4, 9, 1), 2) )
00496         self.assertRaises(ValueError, Decimal, (1, (4, 10, 4, 9, 1), 2) )
00497         self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 'a', 1), 2) )
00498 
00499     def test_explicit_from_bool(self):
00500         self.assertIs(bool(Decimal(0)), False)
00501         self.assertIs(bool(Decimal(1)), True)
00502         self.assertEqual(Decimal(False), Decimal(0))
00503         self.assertEqual(Decimal(True), Decimal(1))
00504 
00505     def test_explicit_from_Decimal(self):
00506 
00507         #positive
00508         d = Decimal(45)
00509         e = Decimal(d)
00510         self.assertEqual(str(e), '45')
00511         self.assertNotEqual(id(d), id(e))
00512 
00513         #very large positive
00514         d = Decimal(500000123)
00515         e = Decimal(d)
00516         self.assertEqual(str(e), '500000123')
00517         self.assertNotEqual(id(d), id(e))
00518 
00519         #negative
00520         d = Decimal(-45)
00521         e = Decimal(d)
00522         self.assertEqual(str(e), '-45')
00523         self.assertNotEqual(id(d), id(e))
00524 
00525         #zero
00526         d = Decimal(0)
00527         e = Decimal(d)
00528         self.assertEqual(str(e), '0')
00529         self.assertNotEqual(id(d), id(e))
00530 
00531     @requires_IEEE_754
00532     def test_explicit_from_float(self):
00533         r = Decimal(0.1)
00534         self.assertEqual(type(r), Decimal)
00535         self.assertEqual(str(r),
00536                 '0.1000000000000000055511151231257827021181583404541015625')
00537         self.assertTrue(Decimal(float('nan')).is_qnan())
00538         self.assertTrue(Decimal(float('inf')).is_infinite())
00539         self.assertTrue(Decimal(float('-inf')).is_infinite())
00540         self.assertEqual(str(Decimal(float('nan'))),
00541                          str(Decimal('NaN')))
00542         self.assertEqual(str(Decimal(float('inf'))),
00543                          str(Decimal('Infinity')))
00544         self.assertEqual(str(Decimal(float('-inf'))),
00545                          str(Decimal('-Infinity')))
00546         self.assertEqual(str(Decimal(float('-0.0'))),
00547                          str(Decimal('-0')))
00548         for i in range(200):
00549             x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
00550             self.assertEqual(x, float(Decimal(x))) # roundtrip
00551 
00552     def test_explicit_context_create_decimal(self):
00553 
00554         nc = copy.copy(getcontext())
00555         nc.prec = 3
00556 
00557         # empty
00558         d = Decimal()
00559         self.assertEqual(str(d), '0')
00560         d = nc.create_decimal()
00561         self.assertEqual(str(d), '0')
00562 
00563         # from None
00564         self.assertRaises(TypeError, nc.create_decimal, None)
00565 
00566         # from int
00567         d = nc.create_decimal(456)
00568         self.assertIsInstance(d, Decimal)
00569         self.assertEqual(nc.create_decimal(45678),
00570                          nc.create_decimal('457E+2'))
00571 
00572         # from string
00573         d = Decimal('456789')
00574         self.assertEqual(str(d), '456789')
00575         d = nc.create_decimal('456789')
00576         self.assertEqual(str(d), '4.57E+5')
00577         # leading and trailing whitespace should result in a NaN;
00578         # spaces are already checked in Cowlishaw's test-suite, so
00579         # here we just check that a trailing newline results in a NaN
00580         self.assertEqual(str(nc.create_decimal('3.14\n')), 'NaN')
00581 
00582         # from tuples
00583         d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
00584         self.assertEqual(str(d), '-4.34913534E-17')
00585         d = nc.create_decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
00586         self.assertEqual(str(d), '-4.35E-17')
00587 
00588         # from Decimal
00589         prevdec = Decimal(500000123)
00590         d = Decimal(prevdec)
00591         self.assertEqual(str(d), '500000123')
00592         d = nc.create_decimal(prevdec)
00593         self.assertEqual(str(d), '5.00E+8')
00594 
00595     def test_unicode_digits(self):
00596         test_values = {
00597             '\uff11': '1',
00598             '\u0660.\u0660\u0663\u0667\u0662e-\u0663' : '0.0000372',
00599             '-nan\u0c68\u0c6a\u0c66\u0c66' : '-NaN2400',
00600             }
00601         for input, expected in test_values.items():
00602             self.assertEqual(str(Decimal(input)), expected)
00603 
00604 
00605 class DecimalImplicitConstructionTest(unittest.TestCase):
00606     '''Unit tests for Implicit Construction cases of Decimal.'''
00607 
00608     def test_implicit_from_None(self):
00609         self.assertRaises(TypeError, eval, 'Decimal(5) + None', globals())
00610 
00611     def test_implicit_from_int(self):
00612         #normal
00613         self.assertEqual(str(Decimal(5) + 45), '50')
00614         #exceeding precision
00615         self.assertEqual(Decimal(5) + 123456789000, Decimal(123456789000))
00616 
00617     def test_implicit_from_string(self):
00618         self.assertRaises(TypeError, eval, 'Decimal(5) + "3"', globals())
00619 
00620     def test_implicit_from_float(self):
00621         self.assertRaises(TypeError, eval, 'Decimal(5) + 2.2', globals())
00622 
00623     def test_implicit_from_Decimal(self):
00624         self.assertEqual(Decimal(5) + Decimal(45), Decimal(50))
00625 
00626     def test_rop(self):
00627         # Allow other classes to be trained to interact with Decimals
00628         class E:
00629             def __divmod__(self, other):
00630                 return 'divmod ' + str(other)
00631             def __rdivmod__(self, other):
00632                 return str(other) + ' rdivmod'
00633             def __lt__(self, other):
00634                 return 'lt ' + str(other)
00635             def __gt__(self, other):
00636                 return 'gt ' + str(other)
00637             def __le__(self, other):
00638                 return 'le ' + str(other)
00639             def __ge__(self, other):
00640                 return 'ge ' + str(other)
00641             def __eq__(self, other):
00642                 return 'eq ' + str(other)
00643             def __ne__(self, other):
00644                 return 'ne ' + str(other)
00645 
00646         self.assertEqual(divmod(E(), Decimal(10)), 'divmod 10')
00647         self.assertEqual(divmod(Decimal(10), E()), '10 rdivmod')
00648         self.assertEqual(eval('Decimal(10) < E()'), 'gt 10')
00649         self.assertEqual(eval('Decimal(10) > E()'), 'lt 10')
00650         self.assertEqual(eval('Decimal(10) <= E()'), 'ge 10')
00651         self.assertEqual(eval('Decimal(10) >= E()'), 'le 10')
00652         self.assertEqual(eval('Decimal(10) == E()'), 'eq 10')
00653         self.assertEqual(eval('Decimal(10) != E()'), 'ne 10')
00654 
00655         # insert operator methods and then exercise them
00656         oplist = [
00657             ('+', '__add__', '__radd__'),
00658             ('-', '__sub__', '__rsub__'),
00659             ('*', '__mul__', '__rmul__'),
00660             ('/', '__truediv__', '__rtruediv__'),
00661             ('%', '__mod__', '__rmod__'),
00662             ('//', '__floordiv__', '__rfloordiv__'),
00663             ('**', '__pow__', '__rpow__')
00664         ]
00665 
00666         for sym, lop, rop in oplist:
00667             setattr(E, lop, lambda self, other: 'str' + lop + str(other))
00668             setattr(E, rop, lambda self, other: str(other) + rop + 'str')
00669             self.assertEqual(eval('E()' + sym + 'Decimal(10)'),
00670                              'str' + lop + '10')
00671             self.assertEqual(eval('Decimal(10)' + sym + 'E()'),
00672                              '10' + rop + 'str')
00673 
00674 
00675 class DecimalFormatTest(unittest.TestCase):
00676     '''Unit tests for the format function.'''
00677     def test_formatting(self):
00678         # triples giving a format, a Decimal, and the expected result
00679         test_values = [
00680             ('e', '0E-15', '0e-15'),
00681             ('e', '2.3E-15', '2.3e-15'),
00682             ('e', '2.30E+2', '2.30e+2'), # preserve significant zeros
00683             ('e', '2.30000E-15', '2.30000e-15'),
00684             ('e', '1.23456789123456789e40', '1.23456789123456789e+40'),
00685             ('e', '1.5', '1.5e+0'),
00686             ('e', '0.15', '1.5e-1'),
00687             ('e', '0.015', '1.5e-2'),
00688             ('e', '0.0000000000015', '1.5e-12'),
00689             ('e', '15.0', '1.50e+1'),
00690             ('e', '-15', '-1.5e+1'),
00691             ('e', '0', '0e+0'),
00692             ('e', '0E1', '0e+1'),
00693             ('e', '0.0', '0e-1'),
00694             ('e', '0.00', '0e-2'),
00695             ('.6e', '0E-15', '0.000000e-9'),
00696             ('.6e', '0', '0.000000e+6'),
00697             ('.6e', '9.999999', '9.999999e+0'),
00698             ('.6e', '9.9999999', '1.000000e+1'),
00699             ('.6e', '-1.23e5', '-1.230000e+5'),
00700             ('.6e', '1.23456789e-3', '1.234568e-3'),
00701             ('f', '0', '0'),
00702             ('f', '0.0', '0.0'),
00703             ('f', '0E-2', '0.00'),
00704             ('f', '0.00E-8', '0.0000000000'),
00705             ('f', '0E1', '0'), # loses exponent information
00706             ('f', '3.2E1', '32'),
00707             ('f', '3.2E2', '320'),
00708             ('f', '3.20E2', '320'),
00709             ('f', '3.200E2', '320.0'),
00710             ('f', '3.2E-6', '0.0000032'),
00711             ('.6f', '0E-15', '0.000000'), # all zeros treated equally
00712             ('.6f', '0E1', '0.000000'),
00713             ('.6f', '0', '0.000000'),
00714             ('.0f', '0', '0'), # no decimal point
00715             ('.0f', '0e-2', '0'),
00716             ('.0f', '3.14159265', '3'),
00717             ('.1f', '3.14159265', '3.1'),
00718             ('.4f', '3.14159265', '3.1416'),
00719             ('.6f', '3.14159265', '3.141593'),
00720             ('.7f', '3.14159265', '3.1415926'), # round-half-even!
00721             ('.8f', '3.14159265', '3.14159265'),
00722             ('.9f', '3.14159265', '3.141592650'),
00723 
00724             ('g', '0', '0'),
00725             ('g', '0.0', '0.0'),
00726             ('g', '0E1', '0e+1'),
00727             ('G', '0E1', '0E+1'),
00728             ('g', '0E-5', '0.00000'),
00729             ('g', '0E-6', '0.000000'),
00730             ('g', '0E-7', '0e-7'),
00731             ('g', '-0E2', '-0e+2'),
00732             ('.0g', '3.14159265', '3'),  # 0 sig fig -> 1 sig fig
00733             ('.1g', '3.14159265', '3'),
00734             ('.2g', '3.14159265', '3.1'),
00735             ('.5g', '3.14159265', '3.1416'),
00736             ('.7g', '3.14159265', '3.141593'),
00737             ('.8g', '3.14159265', '3.1415926'), # round-half-even!
00738             ('.9g', '3.14159265', '3.14159265'),
00739             ('.10g', '3.14159265', '3.14159265'), # don't pad
00740 
00741             ('%', '0E1', '0%'),
00742             ('%', '0E0', '0%'),
00743             ('%', '0E-1', '0%'),
00744             ('%', '0E-2', '0%'),
00745             ('%', '0E-3', '0.0%'),
00746             ('%', '0E-4', '0.00%'),
00747 
00748             ('.3%', '0', '0.000%'), # all zeros treated equally
00749             ('.3%', '0E10', '0.000%'),
00750             ('.3%', '0E-10', '0.000%'),
00751             ('.3%', '2.34', '234.000%'),
00752             ('.3%', '1.234567', '123.457%'),
00753             ('.0%', '1.23', '123%'),
00754 
00755             ('e', 'NaN', 'NaN'),
00756             ('f', '-NaN123', '-NaN123'),
00757             ('+g', 'NaN456', '+NaN456'),
00758             ('.3e', 'Inf', 'Infinity'),
00759             ('.16f', '-Inf', '-Infinity'),
00760             ('.0g', '-sNaN', '-sNaN'),
00761 
00762             ('', '1.00', '1.00'),
00763 
00764             # test alignment and padding
00765             ('6', '123', '   123'),
00766             ('<6', '123', '123   '),
00767             ('>6', '123', '   123'),
00768             ('^6', '123', ' 123  '),
00769             ('=+6', '123', '+  123'),
00770             ('#<10', 'NaN', 'NaN#######'),
00771             ('#<10', '-4.3', '-4.3######'),
00772             ('#<+10', '0.0130', '+0.0130###'),
00773             ('#< 10', '0.0130', ' 0.0130###'),
00774             ('@>10', '-Inf', '@-Infinity'),
00775             ('#>5', '-Inf', '-Infinity'),
00776             ('?^5', '123', '?123?'),
00777             ('%^6', '123', '%123%%'),
00778             (' ^6', '-45.6', '-45.6 '),
00779             ('/=10', '-45.6', '-/////45.6'),
00780             ('/=+10', '45.6', '+/////45.6'),
00781             ('/= 10', '45.6', ' /////45.6'),
00782 
00783             # thousands separator
00784             (',', '1234567', '1,234,567'),
00785             (',', '123456', '123,456'),
00786             (',', '12345', '12,345'),
00787             (',', '1234', '1,234'),
00788             (',', '123', '123'),
00789             (',', '12', '12'),
00790             (',', '1', '1'),
00791             (',', '0', '0'),
00792             (',', '-1234567', '-1,234,567'),
00793             (',', '-123456', '-123,456'),
00794             ('7,', '123456', '123,456'),
00795             ('8,', '123456', ' 123,456'),
00796             ('08,', '123456', '0,123,456'), # special case: extra 0 needed
00797             ('+08,', '123456', '+123,456'), # but not if there's a sign
00798             (' 08,', '123456', ' 123,456'),
00799             ('08,', '-123456', '-123,456'),
00800             ('+09,', '123456', '+0,123,456'),
00801             # ... with fractional part...
00802             ('07,', '1234.56', '1,234.56'),
00803             ('08,', '1234.56', '1,234.56'),
00804             ('09,', '1234.56', '01,234.56'),
00805             ('010,', '1234.56', '001,234.56'),
00806             ('011,', '1234.56', '0,001,234.56'),
00807             ('012,', '1234.56', '0,001,234.56'),
00808             ('08,.1f', '1234.5', '01,234.5'),
00809             # no thousands separators in fraction part
00810             (',', '1.23456789', '1.23456789'),
00811             (',%', '123.456789', '12,345.6789%'),
00812             (',e', '123456', '1.23456e+5'),
00813             (',E', '123456', '1.23456E+5'),
00814 
00815             # issue 6850
00816             ('a=-7.0', '0.12345', 'aaaa0.1'),
00817 
00818             # Issue 7094: Alternate formatting (specified by #)
00819             ('.0e', '1.0', '1e+0'),
00820             ('#.0e', '1.0', '1.e+0'),
00821             ('.0f', '1.0', '1'),
00822             ('#.0f', '1.0', '1.'),
00823             ('g', '1.1', '1.1'),
00824             ('#g', '1.1', '1.1'),
00825             ('.0g', '1', '1'),
00826             ('#.0g', '1', '1.'),
00827             ('.0%', '1.0', '100%'),
00828             ('#.0%', '1.0', '100.%'),
00829             ]
00830         for fmt, d, result in test_values:
00831             self.assertEqual(format(Decimal(d), fmt), result)
00832 
00833     def test_n_format(self):
00834         try:
00835             from locale import CHAR_MAX
00836         except ImportError:
00837             return
00838 
00839         # Set up some localeconv-like dictionaries
00840         en_US = {
00841             'decimal_point' : '.',
00842             'grouping' : [3, 3, 0],
00843             'thousands_sep': ','
00844             }
00845 
00846         fr_FR = {
00847             'decimal_point' : ',',
00848             'grouping' : [CHAR_MAX],
00849             'thousands_sep' : ''
00850             }
00851 
00852         ru_RU = {
00853             'decimal_point' : ',',
00854             'grouping' : [3, 3, 0],
00855             'thousands_sep' : ' '
00856             }
00857 
00858         crazy = {
00859             'decimal_point' : '&',
00860             'grouping' : [1, 4, 2, CHAR_MAX],
00861             'thousands_sep' : '-'
00862             }
00863 
00864 
00865         def get_fmt(x, locale, fmt='n'):
00866             return Decimal.__format__(Decimal(x), fmt, _localeconv=locale)
00867 
00868         self.assertEqual(get_fmt(Decimal('12.7'), en_US), '12.7')
00869         self.assertEqual(get_fmt(Decimal('12.7'), fr_FR), '12,7')
00870         self.assertEqual(get_fmt(Decimal('12.7'), ru_RU), '12,7')
00871         self.assertEqual(get_fmt(Decimal('12.7'), crazy), '1-2&7')
00872 
00873         self.assertEqual(get_fmt(123456789, en_US), '123,456,789')
00874         self.assertEqual(get_fmt(123456789, fr_FR), '123456789')
00875         self.assertEqual(get_fmt(123456789, ru_RU), '123 456 789')
00876         self.assertEqual(get_fmt(1234567890123, crazy), '123456-78-9012-3')
00877 
00878         self.assertEqual(get_fmt(123456789, en_US, '.6n'), '1.23457e+8')
00879         self.assertEqual(get_fmt(123456789, fr_FR, '.6n'), '1,23457e+8')
00880         self.assertEqual(get_fmt(123456789, ru_RU, '.6n'), '1,23457e+8')
00881         self.assertEqual(get_fmt(123456789, crazy, '.6n'), '1&23457e+8')
00882 
00883         # zero padding
00884         self.assertEqual(get_fmt(1234, fr_FR, '03n'), '1234')
00885         self.assertEqual(get_fmt(1234, fr_FR, '04n'), '1234')
00886         self.assertEqual(get_fmt(1234, fr_FR, '05n'), '01234')
00887         self.assertEqual(get_fmt(1234, fr_FR, '06n'), '001234')
00888 
00889         self.assertEqual(get_fmt(12345, en_US, '05n'), '12,345')
00890         self.assertEqual(get_fmt(12345, en_US, '06n'), '12,345')
00891         self.assertEqual(get_fmt(12345, en_US, '07n'), '012,345')
00892         self.assertEqual(get_fmt(12345, en_US, '08n'), '0,012,345')
00893         self.assertEqual(get_fmt(12345, en_US, '09n'), '0,012,345')
00894         self.assertEqual(get_fmt(12345, en_US, '010n'), '00,012,345')
00895 
00896         self.assertEqual(get_fmt(123456, crazy, '06n'), '1-2345-6')
00897         self.assertEqual(get_fmt(123456, crazy, '07n'), '1-2345-6')
00898         self.assertEqual(get_fmt(123456, crazy, '08n'), '1-2345-6')
00899         self.assertEqual(get_fmt(123456, crazy, '09n'), '01-2345-6')
00900         self.assertEqual(get_fmt(123456, crazy, '010n'), '0-01-2345-6')
00901         self.assertEqual(get_fmt(123456, crazy, '011n'), '0-01-2345-6')
00902         self.assertEqual(get_fmt(123456, crazy, '012n'), '00-01-2345-6')
00903         self.assertEqual(get_fmt(123456, crazy, '013n'), '000-01-2345-6')
00904 
00905 
00906 class DecimalArithmeticOperatorsTest(unittest.TestCase):
00907     '''Unit tests for all arithmetic operators, binary and unary.'''
00908 
00909     def test_addition(self):
00910 
00911         d1 = Decimal('-11.1')
00912         d2 = Decimal('22.2')
00913 
00914         #two Decimals
00915         self.assertEqual(d1+d2, Decimal('11.1'))
00916         self.assertEqual(d2+d1, Decimal('11.1'))
00917 
00918         #with other type, left
00919         c = d1 + 5
00920         self.assertEqual(c, Decimal('-6.1'))
00921         self.assertEqual(type(c), type(d1))
00922 
00923         #with other type, right
00924         c = 5 + d1
00925         self.assertEqual(c, Decimal('-6.1'))
00926         self.assertEqual(type(c), type(d1))
00927 
00928         #inline with decimal
00929         d1 += d2
00930         self.assertEqual(d1, Decimal('11.1'))
00931 
00932         #inline with other type
00933         d1 += 5
00934         self.assertEqual(d1, Decimal('16.1'))
00935 
00936     def test_subtraction(self):
00937 
00938         d1 = Decimal('-11.1')
00939         d2 = Decimal('22.2')
00940 
00941         #two Decimals
00942         self.assertEqual(d1-d2, Decimal('-33.3'))
00943         self.assertEqual(d2-d1, Decimal('33.3'))
00944 
00945         #with other type, left
00946         c = d1 - 5
00947         self.assertEqual(c, Decimal('-16.1'))
00948         self.assertEqual(type(c), type(d1))
00949 
00950         #with other type, right
00951         c = 5 - d1
00952         self.assertEqual(c, Decimal('16.1'))
00953         self.assertEqual(type(c), type(d1))
00954 
00955         #inline with decimal
00956         d1 -= d2
00957         self.assertEqual(d1, Decimal('-33.3'))
00958 
00959         #inline with other type
00960         d1 -= 5
00961         self.assertEqual(d1, Decimal('-38.3'))
00962 
00963     def test_multiplication(self):
00964 
00965         d1 = Decimal('-5')
00966         d2 = Decimal('3')
00967 
00968         #two Decimals
00969         self.assertEqual(d1*d2, Decimal('-15'))
00970         self.assertEqual(d2*d1, Decimal('-15'))
00971 
00972         #with other type, left
00973         c = d1 * 5
00974         self.assertEqual(c, Decimal('-25'))
00975         self.assertEqual(type(c), type(d1))
00976 
00977         #with other type, right
00978         c = 5 * d1
00979         self.assertEqual(c, Decimal('-25'))
00980         self.assertEqual(type(c), type(d1))
00981 
00982         #inline with decimal
00983         d1 *= d2
00984         self.assertEqual(d1, Decimal('-15'))
00985 
00986         #inline with other type
00987         d1 *= 5
00988         self.assertEqual(d1, Decimal('-75'))
00989 
00990     def test_division(self):
00991 
00992         d1 = Decimal('-5')
00993         d2 = Decimal('2')
00994 
00995         #two Decimals
00996         self.assertEqual(d1/d2, Decimal('-2.5'))
00997         self.assertEqual(d2/d1, Decimal('-0.4'))
00998 
00999         #with other type, left
01000         c = d1 / 4
01001         self.assertEqual(c, Decimal('-1.25'))
01002         self.assertEqual(type(c), type(d1))
01003 
01004         #with other type, right
01005         c = 4 / d1
01006         self.assertEqual(c, Decimal('-0.8'))
01007         self.assertEqual(type(c), type(d1))
01008 
01009         #inline with decimal
01010         d1 /= d2
01011         self.assertEqual(d1, Decimal('-2.5'))
01012 
01013         #inline with other type
01014         d1 /= 4
01015         self.assertEqual(d1, Decimal('-0.625'))
01016 
01017     def test_floor_division(self):
01018 
01019         d1 = Decimal('5')
01020         d2 = Decimal('2')
01021 
01022         #two Decimals
01023         self.assertEqual(d1//d2, Decimal('2'))
01024         self.assertEqual(d2//d1, Decimal('0'))
01025 
01026         #with other type, left
01027         c = d1 // 4
01028         self.assertEqual(c, Decimal('1'))
01029         self.assertEqual(type(c), type(d1))
01030 
01031         #with other type, right
01032         c = 7 // d1
01033         self.assertEqual(c, Decimal('1'))
01034         self.assertEqual(type(c), type(d1))
01035 
01036         #inline with decimal
01037         d1 //= d2
01038         self.assertEqual(d1, Decimal('2'))
01039 
01040         #inline with other type
01041         d1 //= 2
01042         self.assertEqual(d1, Decimal('1'))
01043 
01044     def test_powering(self):
01045 
01046         d1 = Decimal('5')
01047         d2 = Decimal('2')
01048 
01049         #two Decimals
01050         self.assertEqual(d1**d2, Decimal('25'))
01051         self.assertEqual(d2**d1, Decimal('32'))
01052 
01053         #with other type, left
01054         c = d1 ** 4
01055         self.assertEqual(c, Decimal('625'))
01056         self.assertEqual(type(c), type(d1))
01057 
01058         #with other type, right
01059         c = 7 ** d1
01060         self.assertEqual(c, Decimal('16807'))
01061         self.assertEqual(type(c), type(d1))
01062 
01063         #inline with decimal
01064         d1 **= d2
01065         self.assertEqual(d1, Decimal('25'))
01066 
01067         #inline with other type
01068         d1 **= 4
01069         self.assertEqual(d1, Decimal('390625'))
01070 
01071     def test_module(self):
01072 
01073         d1 = Decimal('5')
01074         d2 = Decimal('2')
01075 
01076         #two Decimals
01077         self.assertEqual(d1%d2, Decimal('1'))
01078         self.assertEqual(d2%d1, Decimal('2'))
01079 
01080         #with other type, left
01081         c = d1 % 4
01082         self.assertEqual(c, Decimal('1'))
01083         self.assertEqual(type(c), type(d1))
01084 
01085         #with other type, right
01086         c = 7 % d1
01087         self.assertEqual(c, Decimal('2'))
01088         self.assertEqual(type(c), type(d1))
01089 
01090         #inline with decimal
01091         d1 %= d2
01092         self.assertEqual(d1, Decimal('1'))
01093 
01094         #inline with other type
01095         d1 %= 4
01096         self.assertEqual(d1, Decimal('1'))
01097 
01098     def test_floor_div_module(self):
01099 
01100         d1 = Decimal('5')
01101         d2 = Decimal('2')
01102 
01103         #two Decimals
01104         (p, q) = divmod(d1, d2)
01105         self.assertEqual(p, Decimal('2'))
01106         self.assertEqual(q, Decimal('1'))
01107         self.assertEqual(type(p), type(d1))
01108         self.assertEqual(type(q), type(d1))
01109 
01110         #with other type, left
01111         (p, q) = divmod(d1, 4)
01112         self.assertEqual(p, Decimal('1'))
01113         self.assertEqual(q, Decimal('1'))
01114         self.assertEqual(type(p), type(d1))
01115         self.assertEqual(type(q), type(d1))
01116 
01117         #with other type, right
01118         (p, q) = divmod(7, d1)
01119         self.assertEqual(p, Decimal('1'))
01120         self.assertEqual(q, Decimal('2'))
01121         self.assertEqual(type(p), type(d1))
01122         self.assertEqual(type(q), type(d1))
01123 
01124     def test_unary_operators(self):
01125         self.assertEqual(+Decimal(45), Decimal(+45))           #  +
01126         self.assertEqual(-Decimal(45), Decimal(-45))           #  -
01127         self.assertEqual(abs(Decimal(45)), abs(Decimal(-45)))  # abs
01128 
01129     def test_nan_comparisons(self):
01130         # comparisons involving signaling nans signal InvalidOperation
01131 
01132         # order comparisons (<, <=, >, >=) involving only quiet nans
01133         # also signal InvalidOperation
01134 
01135         # equality comparisons (==, !=) involving only quiet nans
01136         # don't signal, but return False or True respectively.
01137 
01138         n = Decimal('NaN')
01139         s = Decimal('sNaN')
01140         i = Decimal('Inf')
01141         f = Decimal('2')
01142 
01143         qnan_pairs = (n, n), (n, i), (i, n), (n, f), (f, n)
01144         snan_pairs = (s, n), (n, s), (s, i), (i, s), (s, f), (f, s), (s, s)
01145         order_ops = operator.lt, operator.le, operator.gt, operator.ge
01146         equality_ops = operator.eq, operator.ne
01147 
01148         # results when InvalidOperation is not trapped
01149         for x, y in qnan_pairs + snan_pairs:
01150             for op in order_ops + equality_ops:
01151                 got = op(x, y)
01152                 expected = True if op is operator.ne else False
01153                 self.assertIs(expected, got,
01154                               "expected {0!r} for operator.{1}({2!r}, {3!r}); "
01155                               "got {4!r}".format(
01156                         expected, op.__name__, x, y, got))
01157 
01158         # repeat the above, but this time trap the InvalidOperation
01159         with localcontext() as ctx:
01160             ctx.traps[InvalidOperation] = 1
01161 
01162             for x, y in qnan_pairs:
01163                 for op in equality_ops:
01164                     got = op(x, y)
01165                     expected = True if op is operator.ne else False
01166                     self.assertIs(expected, got,
01167                                   "expected {0!r} for "
01168                                   "operator.{1}({2!r}, {3!r}); "
01169                                   "got {4!r}".format(
01170                             expected, op.__name__, x, y, got))
01171 
01172             for x, y in snan_pairs:
01173                 for op in equality_ops:
01174                     self.assertRaises(InvalidOperation, operator.eq, x, y)
01175                     self.assertRaises(InvalidOperation, operator.ne, x, y)
01176 
01177             for x, y in qnan_pairs + snan_pairs:
01178                 for op in order_ops:
01179                     self.assertRaises(InvalidOperation, op, x, y)
01180 
01181     def test_copy_sign(self):
01182         d = Decimal(1).copy_sign(Decimal(-2))
01183 
01184         self.assertEqual(Decimal(1).copy_sign(-2), d)
01185         self.assertRaises(TypeError, Decimal(1).copy_sign, '-2')
01186 
01187 # The following are two functions used to test threading in the next class
01188 
01189 def thfunc1(cls):
01190     d1 = Decimal(1)
01191     d3 = Decimal(3)
01192     test1 = d1/d3
01193     cls.synchro.wait()
01194     test2 = d1/d3
01195     cls.finish1.set()
01196 
01197     cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
01198     cls.assertEqual(test2, Decimal('0.3333333333333333333333333333'))
01199     return
01200 
01201 def thfunc2(cls):
01202     d1 = Decimal(1)
01203     d3 = Decimal(3)
01204     test1 = d1/d3
01205     thiscontext = getcontext()
01206     thiscontext.prec = 18
01207     test2 = d1/d3
01208     cls.synchro.set()
01209     cls.finish2.set()
01210 
01211     cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
01212     cls.assertEqual(test2, Decimal('0.333333333333333333'))
01213     return
01214 
01215 
01216 class DecimalUseOfContextTest(unittest.TestCase):
01217     '''Unit tests for Use of Context cases in Decimal.'''
01218 
01219     try:
01220         import threading
01221     except ImportError:
01222         threading = None
01223 
01224     # Take care executing this test from IDLE, there's an issue in threading
01225     # that hangs IDLE and I couldn't find it
01226 
01227     def test_threading(self):
01228         #Test the "threading isolation" of a Context.
01229 
01230         self.synchro = threading.Event()
01231         self.finish1 = threading.Event()
01232         self.finish2 = threading.Event()
01233 
01234         th1 = threading.Thread(target=thfunc1, args=(self,))
01235         th2 = threading.Thread(target=thfunc2, args=(self,))
01236 
01237         th1.start()
01238         th2.start()
01239 
01240         self.finish1.wait()
01241         self.finish2.wait()
01242         return
01243 
01244     if threading is None:
01245         del test_threading
01246 
01247 
01248 class DecimalUsabilityTest(unittest.TestCase):
01249     '''Unit tests for Usability cases of Decimal.'''
01250 
01251     def test_comparison_operators(self):
01252 
01253         da = Decimal('23.42')
01254         db = Decimal('23.42')
01255         dc = Decimal('45')
01256 
01257         #two Decimals
01258         self.assertGreater(dc, da)
01259         self.assertGreaterEqual(dc, da)
01260         self.assertLess(da, dc)
01261         self.assertLessEqual(da, dc)
01262         self.assertEqual(da, db)
01263         self.assertNotEqual(da, dc)
01264         self.assertLessEqual(da, db)
01265         self.assertGreaterEqual(da, db)
01266 
01267         #a Decimal and an int
01268         self.assertGreater(dc, 23)
01269         self.assertLess(23, dc)
01270         self.assertEqual(dc, 45)
01271 
01272         #a Decimal and uncomparable
01273         self.assertNotEqual(da, 'ugly')
01274         self.assertNotEqual(da, 32.7)
01275         self.assertNotEqual(da, object())
01276         self.assertNotEqual(da, object)
01277 
01278         # sortable
01279         a = list(map(Decimal, range(100)))
01280         b =  a[:]
01281         random.shuffle(a)
01282         a.sort()
01283         self.assertEqual(a, b)
01284 
01285     def test_decimal_float_comparison(self):
01286         da = Decimal('0.25')
01287         db = Decimal('3.0')
01288         self.assertLess(da, 3.0)
01289         self.assertLessEqual(da, 3.0)
01290         self.assertGreater(db, 0.25)
01291         self.assertGreaterEqual(db, 0.25)
01292         self.assertNotEqual(da, 1.5)
01293         self.assertEqual(da, 0.25)
01294         self.assertGreater(3.0, da)
01295         self.assertGreaterEqual(3.0, da)
01296         self.assertLess(0.25, db)
01297         self.assertLessEqual(0.25, db)
01298         self.assertNotEqual(0.25, db)
01299         self.assertEqual(3.0, db)
01300         self.assertNotEqual(0.1, Decimal('0.1'))
01301 
01302     def test_copy_and_deepcopy_methods(self):
01303         d = Decimal('43.24')
01304         c = copy.copy(d)
01305         self.assertEqual(id(c), id(d))
01306         dc = copy.deepcopy(d)
01307         self.assertEqual(id(dc), id(d))
01308 
01309     def test_hash_method(self):
01310         def hashit(d):
01311             a = hash(d)
01312             b = d.__hash__()
01313             self.assertEqual(a, b)
01314             return a
01315 
01316         #just that it's hashable
01317         hashit(Decimal(23))
01318         hashit(Decimal('Infinity'))
01319         hashit(Decimal('-Infinity'))
01320         hashit(Decimal('nan123'))
01321         hashit(Decimal('-NaN'))
01322 
01323         test_values = [Decimal(sign*(2**m + n))
01324                        for m in [0, 14, 15, 16, 17, 30, 31,
01325                                  32, 33, 61, 62, 63, 64, 65, 66]
01326                        for n in range(-10, 10)
01327                        for sign in [-1, 1]]
01328         test_values.extend([
01329                 Decimal("-1"), # ==> -2
01330                 Decimal("-0"), # zeros
01331                 Decimal("0.00"),
01332                 Decimal("-0.000"),
01333                 Decimal("0E10"),
01334                 Decimal("-0E12"),
01335                 Decimal("10.0"), # negative exponent
01336                 Decimal("-23.00000"),
01337                 Decimal("1230E100"), # positive exponent
01338                 Decimal("-4.5678E50"),
01339                 # a value for which hash(n) != hash(n % (2**64-1))
01340                 # in Python pre-2.6
01341                 Decimal(2**64 + 2**32 - 1),
01342                 # selection of values which fail with the old (before
01343                 # version 2.6) long.__hash__
01344                 Decimal("1.634E100"),
01345                 Decimal("90.697E100"),
01346                 Decimal("188.83E100"),
01347                 Decimal("1652.9E100"),
01348                 Decimal("56531E100"),
01349                 ])
01350 
01351         # check that hash(d) == hash(int(d)) for integral values
01352         for value in test_values:
01353             self.assertEqual(hashit(value), hashit(int(value)))
01354 
01355         #the same hash that to an int
01356         self.assertEqual(hashit(Decimal(23)), hashit(23))
01357         self.assertRaises(TypeError, hash, Decimal('sNaN'))
01358         self.assertTrue(hashit(Decimal('Inf')))
01359         self.assertTrue(hashit(Decimal('-Inf')))
01360 
01361         # check that the hashes of a Decimal float match when they
01362         # represent exactly the same values
01363         test_strings = ['inf', '-Inf', '0.0', '-.0e1',
01364                         '34.0', '2.5', '112390.625', '-0.515625']
01365         for s in test_strings:
01366             f = float(s)
01367             d = Decimal(s)
01368             self.assertEqual(hashit(f), hashit(d))
01369 
01370         # check that the value of the hash doesn't depend on the
01371         # current context (issue #1757)
01372         c = getcontext()
01373         old_precision = c.prec
01374         x = Decimal("123456789.1")
01375 
01376         c.prec = 6
01377         h1 = hashit(x)
01378         c.prec = 10
01379         h2 = hashit(x)
01380         c.prec = 16
01381         h3 = hashit(x)
01382 
01383         self.assertEqual(h1, h2)
01384         self.assertEqual(h1, h3)
01385         c.prec = old_precision
01386 
01387     def test_min_and_max_methods(self):
01388 
01389         d1 = Decimal('15.32')
01390         d2 = Decimal('28.5')
01391         l1 = 15
01392         l2 = 28
01393 
01394         #between Decimals
01395         self.assertIs(min(d1,d2), d1)
01396         self.assertIs(min(d2,d1), d1)
01397         self.assertIs(max(d1,d2), d2)
01398         self.assertIs(max(d2,d1), d2)
01399 
01400         #between Decimal and long
01401         self.assertIs(min(d1,l2), d1)
01402         self.assertIs(min(l2,d1), d1)
01403         self.assertIs(max(l1,d2), d2)
01404         self.assertIs(max(d2,l1), d2)
01405 
01406     def test_as_nonzero(self):
01407         #as false
01408         self.assertFalse(Decimal(0))
01409         #as true
01410         self.assertTrue(Decimal('0.372'))
01411 
01412     def test_tostring_methods(self):
01413         #Test str and repr methods.
01414 
01415         d = Decimal('15.32')
01416         self.assertEqual(str(d), '15.32')               # str
01417         self.assertEqual(repr(d), "Decimal('15.32')")   # repr
01418 
01419     def test_tonum_methods(self):
01420         #Test float and int methods.
01421 
01422         d1 = Decimal('66')
01423         d2 = Decimal('15.32')
01424 
01425         #int
01426         self.assertEqual(int(d1), 66)
01427         self.assertEqual(int(d2), 15)
01428 
01429         #float
01430         self.assertEqual(float(d1), 66)
01431         self.assertEqual(float(d2), 15.32)
01432 
01433         #floor
01434         test_pairs = [
01435             ('123.00', 123),
01436             ('3.2', 3),
01437             ('3.54', 3),
01438             ('3.899', 3),
01439             ('-2.3', -3),
01440             ('-11.0', -11),
01441             ('0.0', 0),
01442             ('-0E3', 0),
01443             ]
01444         for d, i in test_pairs:
01445             self.assertEqual(math.floor(Decimal(d)), i)
01446         self.assertRaises(ValueError, math.floor, Decimal('-NaN'))
01447         self.assertRaises(ValueError, math.floor, Decimal('sNaN'))
01448         self.assertRaises(ValueError, math.floor, Decimal('NaN123'))
01449         self.assertRaises(OverflowError, math.floor, Decimal('Inf'))
01450         self.assertRaises(OverflowError, math.floor, Decimal('-Inf'))
01451 
01452         #ceiling
01453         test_pairs = [
01454             ('123.00', 123),
01455             ('3.2', 4),
01456             ('3.54', 4),
01457             ('3.899', 4),
01458             ('-2.3', -2),
01459             ('-11.0', -11),
01460             ('0.0', 0),
01461             ('-0E3', 0),
01462             ]
01463         for d, i in test_pairs:
01464             self.assertEqual(math.ceil(Decimal(d)), i)
01465         self.assertRaises(ValueError, math.ceil, Decimal('-NaN'))
01466         self.assertRaises(ValueError, math.ceil, Decimal('sNaN'))
01467         self.assertRaises(ValueError, math.ceil, Decimal('NaN123'))
01468         self.assertRaises(OverflowError, math.ceil, Decimal('Inf'))
01469         self.assertRaises(OverflowError, math.ceil, Decimal('-Inf'))
01470 
01471         #round, single argument
01472         test_pairs = [
01473             ('123.00', 123),
01474             ('3.2', 3),
01475             ('3.54', 4),
01476             ('3.899', 4),
01477             ('-2.3', -2),
01478             ('-11.0', -11),
01479             ('0.0', 0),
01480             ('-0E3', 0),
01481             ('-3.5', -4),
01482             ('-2.5', -2),
01483             ('-1.5', -2),
01484             ('-0.5', 0),
01485             ('0.5', 0),
01486             ('1.5', 2),
01487             ('2.5', 2),
01488             ('3.5', 4),
01489             ]
01490         for d, i in test_pairs:
01491             self.assertEqual(round(Decimal(d)), i)
01492         self.assertRaises(ValueError, round, Decimal('-NaN'))
01493         self.assertRaises(ValueError, round, Decimal('sNaN'))
01494         self.assertRaises(ValueError, round, Decimal('NaN123'))
01495         self.assertRaises(OverflowError, round, Decimal('Inf'))
01496         self.assertRaises(OverflowError, round, Decimal('-Inf'))
01497 
01498         #round, two arguments;  this is essentially equivalent
01499         #to quantize, which is already extensively tested
01500         test_triples = [
01501             ('123.456', -4, '0E+4'),
01502             ('123.456', -3, '0E+3'),
01503             ('123.456', -2, '1E+2'),
01504             ('123.456', -1, '1.2E+2'),
01505             ('123.456', 0, '123'),
01506             ('123.456', 1, '123.5'),
01507             ('123.456', 2, '123.46'),
01508             ('123.456', 3, '123.456'),
01509             ('123.456', 4, '123.4560'),
01510             ('123.455', 2, '123.46'),
01511             ('123.445', 2, '123.44'),
01512             ('Inf', 4, 'NaN'),
01513             ('-Inf', -23, 'NaN'),
01514             ('sNaN314', 3, 'NaN314'),
01515             ]
01516         for d, n, r in test_triples:
01517             self.assertEqual(str(round(Decimal(d), n)), r)
01518 
01519 
01520 
01521     def test_eval_round_trip(self):
01522 
01523         #with zero
01524         d = Decimal( (0, (0,), 0) )
01525         self.assertEqual(d, eval(repr(d)))
01526 
01527         #int
01528         d = Decimal( (1, (4, 5), 0) )
01529         self.assertEqual(d, eval(repr(d)))
01530 
01531         #float
01532         d = Decimal( (0, (4, 5, 3, 4), -2) )
01533         self.assertEqual(d, eval(repr(d)))
01534 
01535         #weird
01536         d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
01537         self.assertEqual(d, eval(repr(d)))
01538 
01539     def test_as_tuple(self):
01540 
01541         #with zero
01542         d = Decimal(0)
01543         self.assertEqual(d.as_tuple(), (0, (0,), 0) )
01544 
01545         #int
01546         d = Decimal(-45)
01547         self.assertEqual(d.as_tuple(), (1, (4, 5), 0) )
01548 
01549         #complicated string
01550         d = Decimal("-4.34913534E-17")
01551         self.assertEqual(d.as_tuple(), (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
01552 
01553         #inf
01554         d = Decimal("Infinity")
01555         self.assertEqual(d.as_tuple(), (0, (0,), 'F') )
01556 
01557         #leading zeros in coefficient should be stripped
01558         d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), -2) )
01559         self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), -2) )
01560         d = Decimal( (1, (0, 0, 0), 37) )
01561         self.assertEqual(d.as_tuple(), (1, (0,), 37))
01562         d = Decimal( (1, (), 37) )
01563         self.assertEqual(d.as_tuple(), (1, (0,), 37))
01564 
01565         #leading zeros in NaN diagnostic info should be stripped
01566         d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), 'n') )
01567         self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), 'n') )
01568         d = Decimal( (1, (0, 0, 0), 'N') )
01569         self.assertEqual(d.as_tuple(), (1, (), 'N') )
01570         d = Decimal( (1, (), 'n') )
01571         self.assertEqual(d.as_tuple(), (1, (), 'n') )
01572 
01573         #coefficient in infinity should be ignored
01574         d = Decimal( (0, (4, 5, 3, 4), 'F') )
01575         self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
01576         d = Decimal( (1, (0, 2, 7, 1), 'F') )
01577         self.assertEqual(d.as_tuple(), (1, (0,), 'F'))
01578 
01579     def test_immutability_operations(self):
01580         # Do operations and check that it didn't change change internal objects.
01581 
01582         d1 = Decimal('-25e55')
01583         b1 = Decimal('-25e55')
01584         d2 = Decimal('33e+33')
01585         b2 = Decimal('33e+33')
01586 
01587         def checkSameDec(operation, useOther=False):
01588             if useOther:
01589                 eval("d1." + operation + "(d2)")
01590                 self.assertEqual(d1._sign, b1._sign)
01591                 self.assertEqual(d1._int, b1._int)
01592                 self.assertEqual(d1._exp, b1._exp)
01593                 self.assertEqual(d2._sign, b2._sign)
01594                 self.assertEqual(d2._int, b2._int)
01595                 self.assertEqual(d2._exp, b2._exp)
01596             else:
01597                 eval("d1." + operation + "()")
01598                 self.assertEqual(d1._sign, b1._sign)
01599                 self.assertEqual(d1._int, b1._int)
01600                 self.assertEqual(d1._exp, b1._exp)
01601             return
01602 
01603         Decimal(d1)
01604         self.assertEqual(d1._sign, b1._sign)
01605         self.assertEqual(d1._int, b1._int)
01606         self.assertEqual(d1._exp, b1._exp)
01607 
01608         checkSameDec("__abs__")
01609         checkSameDec("__add__", True)
01610         checkSameDec("__divmod__", True)
01611         checkSameDec("__eq__", True)
01612         checkSameDec("__ne__", True)
01613         checkSameDec("__le__", True)
01614         checkSameDec("__lt__", True)
01615         checkSameDec("__ge__", True)
01616         checkSameDec("__gt__", True)
01617         checkSameDec("__float__")
01618         checkSameDec("__floordiv__", True)
01619         checkSameDec("__hash__")
01620         checkSameDec("__int__")
01621         checkSameDec("__trunc__")
01622         checkSameDec("__mod__", True)
01623         checkSameDec("__mul__", True)
01624         checkSameDec("__neg__")
01625         checkSameDec("__bool__")
01626         checkSameDec("__pos__")
01627         checkSameDec("__pow__", True)
01628         checkSameDec("__radd__", True)
01629         checkSameDec("__rdivmod__", True)
01630         checkSameDec("__repr__")
01631         checkSameDec("__rfloordiv__", True)
01632         checkSameDec("__rmod__", True)
01633         checkSameDec("__rmul__", True)
01634         checkSameDec("__rpow__", True)
01635         checkSameDec("__rsub__", True)
01636         checkSameDec("__str__")
01637         checkSameDec("__sub__", True)
01638         checkSameDec("__truediv__", True)
01639         checkSameDec("adjusted")
01640         checkSameDec("as_tuple")
01641         checkSameDec("compare", True)
01642         checkSameDec("max", True)
01643         checkSameDec("min", True)
01644         checkSameDec("normalize")
01645         checkSameDec("quantize", True)
01646         checkSameDec("remainder_near", True)
01647         checkSameDec("same_quantum", True)
01648         checkSameDec("sqrt")
01649         checkSameDec("to_eng_string")
01650         checkSameDec("to_integral")
01651 
01652     def test_subclassing(self):
01653         # Different behaviours when subclassing Decimal
01654 
01655         class MyDecimal(Decimal):
01656             pass
01657 
01658         d1 = MyDecimal(1)
01659         d2 = MyDecimal(2)
01660         d = d1 + d2
01661         self.assertIs(type(d), Decimal)
01662 
01663         d = d1.max(d2)
01664         self.assertIs(type(d), Decimal)
01665 
01666     def test_implicit_context(self):
01667         # Check results when context given implicitly.  (Issue 2478)
01668         c = getcontext()
01669         self.assertEqual(str(Decimal(0).sqrt()),
01670                          str(c.sqrt(Decimal(0))))
01671 
01672     def test_conversions_from_int(self):
01673         # Check that methods taking a second Decimal argument will
01674         # always accept an integer in place of a Decimal.
01675         self.assertEqual(Decimal(4).compare(3),
01676                          Decimal(4).compare(Decimal(3)))
01677         self.assertEqual(Decimal(4).compare_signal(3),
01678                          Decimal(4).compare_signal(Decimal(3)))
01679         self.assertEqual(Decimal(4).compare_total(3),
01680                          Decimal(4).compare_total(Decimal(3)))
01681         self.assertEqual(Decimal(4).compare_total_mag(3),
01682                          Decimal(4).compare_total_mag(Decimal(3)))
01683         self.assertEqual(Decimal(10101).logical_and(1001),
01684                          Decimal(10101).logical_and(Decimal(1001)))
01685         self.assertEqual(Decimal(10101).logical_or(1001),
01686                          Decimal(10101).logical_or(Decimal(1001)))
01687         self.assertEqual(Decimal(10101).logical_xor(1001),
01688                          Decimal(10101).logical_xor(Decimal(1001)))
01689         self.assertEqual(Decimal(567).max(123),
01690                          Decimal(567).max(Decimal(123)))
01691         self.assertEqual(Decimal(567).max_mag(123),
01692                          Decimal(567).max_mag(Decimal(123)))
01693         self.assertEqual(Decimal(567).min(123),
01694                          Decimal(567).min(Decimal(123)))
01695         self.assertEqual(Decimal(567).min_mag(123),
01696                          Decimal(567).min_mag(Decimal(123)))
01697         self.assertEqual(Decimal(567).next_toward(123),
01698                          Decimal(567).next_toward(Decimal(123)))
01699         self.assertEqual(Decimal(1234).quantize(100),
01700                          Decimal(1234).quantize(Decimal(100)))
01701         self.assertEqual(Decimal(768).remainder_near(1234),
01702                          Decimal(768).remainder_near(Decimal(1234)))
01703         self.assertEqual(Decimal(123).rotate(1),
01704                          Decimal(123).rotate(Decimal(1)))
01705         self.assertEqual(Decimal(1234).same_quantum(1000),
01706                          Decimal(1234).same_quantum(Decimal(1000)))
01707         self.assertEqual(Decimal('9.123').scaleb(-100),
01708                          Decimal('9.123').scaleb(Decimal(-100)))
01709         self.assertEqual(Decimal(456).shift(-1),
01710                          Decimal(456).shift(Decimal(-1)))
01711 
01712         self.assertEqual(Decimal(-12).fma(Decimal(45), 67),
01713                          Decimal(-12).fma(Decimal(45), Decimal(67)))
01714         self.assertEqual(Decimal(-12).fma(45, 67),
01715                          Decimal(-12).fma(Decimal(45), Decimal(67)))
01716         self.assertEqual(Decimal(-12).fma(45, Decimal(67)),
01717                          Decimal(-12).fma(Decimal(45), Decimal(67)))
01718 
01719 
01720 class DecimalPythonAPItests(unittest.TestCase):
01721 
01722     def test_abc(self):
01723         self.assertTrue(issubclass(Decimal, numbers.Number))
01724         self.assertFalse(issubclass(Decimal, numbers.Real))
01725         self.assertIsInstance(Decimal(0), numbers.Number)
01726         self.assertNotIsInstance(Decimal(0), numbers.Real)
01727 
01728     def test_pickle(self):
01729         d = Decimal('-3.141590000')
01730         p = pickle.dumps(d)
01731         e = pickle.loads(p)
01732         self.assertEqual(d, e)
01733 
01734     def test_int(self):
01735         for x in range(-250, 250):
01736             s = '%0.2f' % (x / 100.0)
01737             # should work the same as for floats
01738             self.assertEqual(int(Decimal(s)), int(float(s)))
01739             # should work the same as to_integral in the ROUND_DOWN mode
01740             d = Decimal(s)
01741             r = d.to_integral(ROUND_DOWN)
01742             self.assertEqual(Decimal(int(d)), r)
01743 
01744         self.assertRaises(ValueError, int, Decimal('-nan'))
01745         self.assertRaises(ValueError, int, Decimal('snan'))
01746         self.assertRaises(OverflowError, int, Decimal('inf'))
01747         self.assertRaises(OverflowError, int, Decimal('-inf'))
01748 
01749     def test_trunc(self):
01750         for x in range(-250, 250):
01751             s = '%0.2f' % (x / 100.0)
01752             # should work the same as for floats
01753             self.assertEqual(int(Decimal(s)), int(float(s)))
01754             # should work the same as to_integral in the ROUND_DOWN mode
01755             d = Decimal(s)
01756             r = d.to_integral(ROUND_DOWN)
01757             self.assertEqual(Decimal(math.trunc(d)), r)
01758 
01759     def test_from_float(self):
01760 
01761         class  MyDecimal(Decimal):
01762             pass
01763 
01764         r = MyDecimal.from_float(0.1)
01765         self.assertEqual(type(r), MyDecimal)
01766         self.assertEqual(str(r),
01767                 '0.1000000000000000055511151231257827021181583404541015625')
01768         bigint = 12345678901234567890123456789
01769         self.assertEqual(MyDecimal.from_float(bigint), MyDecimal(bigint))
01770         self.assertTrue(MyDecimal.from_float(float('nan')).is_qnan())
01771         self.assertTrue(MyDecimal.from_float(float('inf')).is_infinite())
01772         self.assertTrue(MyDecimal.from_float(float('-inf')).is_infinite())
01773         self.assertEqual(str(MyDecimal.from_float(float('nan'))),
01774                          str(Decimal('NaN')))
01775         self.assertEqual(str(MyDecimal.from_float(float('inf'))),
01776                          str(Decimal('Infinity')))
01777         self.assertEqual(str(MyDecimal.from_float(float('-inf'))),
01778                          str(Decimal('-Infinity')))
01779         self.assertRaises(TypeError, MyDecimal.from_float, 'abc')
01780         for i in range(200):
01781             x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
01782             self.assertEqual(x, float(MyDecimal.from_float(x))) # roundtrip
01783 
01784     def test_create_decimal_from_float(self):
01785         context = Context(prec=5, rounding=ROUND_DOWN)
01786         self.assertEqual(
01787             context.create_decimal_from_float(math.pi),
01788             Decimal('3.1415')
01789         )
01790         context = Context(prec=5, rounding=ROUND_UP)
01791         self.assertEqual(
01792             context.create_decimal_from_float(math.pi),
01793             Decimal('3.1416')
01794         )
01795         context = Context(prec=5, traps=[Inexact])
01796         self.assertRaises(
01797             Inexact,
01798             context.create_decimal_from_float,
01799             math.pi
01800         )
01801         self.assertEqual(repr(context.create_decimal_from_float(-0.0)),
01802                          "Decimal('-0')")
01803         self.assertEqual(repr(context.create_decimal_from_float(1.0)),
01804                          "Decimal('1')")
01805         self.assertEqual(repr(context.create_decimal_from_float(10)),
01806                          "Decimal('10')")
01807 
01808 class ContextAPItests(unittest.TestCase):
01809 
01810     def test_pickle(self):
01811         c = Context()
01812         e = pickle.loads(pickle.dumps(c))
01813         for k in vars(c):
01814             v1 = vars(c)[k]
01815             v2 = vars(e)[k]
01816             self.assertEqual(v1, v2)
01817 
01818     def test_equality_with_other_types(self):
01819         self.assertIn(Decimal(10), ['a', 1.0, Decimal(10), (1,2), {}])
01820         self.assertNotIn(Decimal(10), ['a', 1.0, (1,2), {}])
01821 
01822     def test_copy(self):
01823         # All copies should be deep
01824         c = Context()
01825         d = c.copy()
01826         self.assertNotEqual(id(c), id(d))
01827         self.assertNotEqual(id(c.flags), id(d.flags))
01828         self.assertNotEqual(id(c.traps), id(d.traps))
01829 
01830     def test__clamp(self):
01831         # In Python 3.2, the private attribute `_clamp` was made
01832         # public (issue 8540), with the old `_clamp` becoming a
01833         # property wrapping `clamp`.  For the duration of Python 3.2
01834         # only, the attribute should be gettable/settable via both
01835         # `clamp` and `_clamp`; in Python 3.3, `_clamp` should be
01836         # removed.
01837         c = Context(clamp = 0)
01838         self.assertEqual(c.clamp, 0)
01839 
01840         with check_warnings(("", DeprecationWarning)):
01841             c._clamp = 1
01842         self.assertEqual(c.clamp, 1)
01843         with check_warnings(("", DeprecationWarning)):
01844             self.assertEqual(c._clamp, 1)
01845         c.clamp = 0
01846         self.assertEqual(c.clamp, 0)
01847         with check_warnings(("", DeprecationWarning)):
01848             self.assertEqual(c._clamp, 0)
01849 
01850     def test_abs(self):
01851         c = Context()
01852         d = c.abs(Decimal(-1))
01853         self.assertEqual(c.abs(-1), d)
01854         self.assertRaises(TypeError, c.abs, '-1')
01855 
01856     def test_add(self):
01857         c = Context()
01858         d = c.add(Decimal(1), Decimal(1))
01859         self.assertEqual(c.add(1, 1), d)
01860         self.assertEqual(c.add(Decimal(1), 1), d)
01861         self.assertEqual(c.add(1, Decimal(1)), d)
01862         self.assertRaises(TypeError, c.add, '1', 1)
01863         self.assertRaises(TypeError, c.add, 1, '1')
01864 
01865     def test_compare(self):
01866         c = Context()
01867         d = c.compare(Decimal(1), Decimal(1))
01868         self.assertEqual(c.compare(1, 1), d)
01869         self.assertEqual(c.compare(Decimal(1), 1), d)
01870         self.assertEqual(c.compare(1, Decimal(1)), d)
01871         self.assertRaises(TypeError, c.compare, '1', 1)
01872         self.assertRaises(TypeError, c.compare, 1, '1')
01873 
01874     def test_compare_signal(self):
01875         c = Context()
01876         d = c.compare_signal(Decimal(1), Decimal(1))
01877         self.assertEqual(c.compare_signal(1, 1), d)
01878         self.assertEqual(c.compare_signal(Decimal(1), 1), d)
01879         self.assertEqual(c.compare_signal(1, Decimal(1)), d)
01880         self.assertRaises(TypeError, c.compare_signal, '1', 1)
01881         self.assertRaises(TypeError, c.compare_signal, 1, '1')
01882 
01883     def test_compare_total(self):
01884         c = Context()
01885         d = c.compare_total(Decimal(1), Decimal(1))
01886         self.assertEqual(c.compare_total(1, 1), d)
01887         self.assertEqual(c.compare_total(Decimal(1), 1), d)
01888         self.assertEqual(c.compare_total(1, Decimal(1)), d)
01889         self.assertRaises(TypeError, c.compare_total, '1', 1)
01890         self.assertRaises(TypeError, c.compare_total, 1, '1')
01891 
01892     def test_compare_total_mag(self):
01893         c = Context()
01894         d = c.compare_total_mag(Decimal(1), Decimal(1))
01895         self.assertEqual(c.compare_total_mag(1, 1), d)
01896         self.assertEqual(c.compare_total_mag(Decimal(1), 1), d)
01897         self.assertEqual(c.compare_total_mag(1, Decimal(1)), d)
01898         self.assertRaises(TypeError, c.compare_total_mag, '1', 1)
01899         self.assertRaises(TypeError, c.compare_total_mag, 1, '1')
01900 
01901     def test_copy_abs(self):
01902         c = Context()
01903         d = c.copy_abs(Decimal(-1))
01904         self.assertEqual(c.copy_abs(-1), d)
01905         self.assertRaises(TypeError, c.copy_abs, '-1')
01906 
01907     def test_copy_decimal(self):
01908         c = Context()
01909         d = c.copy_decimal(Decimal(-1))
01910         self.assertEqual(c.copy_decimal(-1), d)
01911         self.assertRaises(TypeError, c.copy_decimal, '-1')
01912 
01913     def test_copy_negate(self):
01914         c = Context()
01915         d = c.copy_negate(Decimal(-1))
01916         self.assertEqual(c.copy_negate(-1), d)
01917         self.assertRaises(TypeError, c.copy_negate, '-1')
01918 
01919     def test_copy_sign(self):
01920         c = Context()
01921         d = c.copy_sign(Decimal(1), Decimal(-2))
01922         self.assertEqual(c.copy_sign(1, -2), d)
01923         self.assertEqual(c.copy_sign(Decimal(1), -2), d)
01924         self.assertEqual(c.copy_sign(1, Decimal(-2)), d)
01925         self.assertRaises(TypeError, c.copy_sign, '1', -2)
01926         self.assertRaises(TypeError, c.copy_sign, 1, '-2')
01927 
01928     def test_divide(self):
01929         c = Context()
01930         d = c.divide(Decimal(1), Decimal(2))
01931         self.assertEqual(c.divide(1, 2), d)
01932         self.assertEqual(c.divide(Decimal(1), 2), d)
01933         self.assertEqual(c.divide(1, Decimal(2)), d)
01934         self.assertRaises(TypeError, c.divide, '1', 2)
01935         self.assertRaises(TypeError, c.divide, 1, '2')
01936 
01937     def test_divide_int(self):
01938         c = Context()
01939         d = c.divide_int(Decimal(1), Decimal(2))
01940         self.assertEqual(c.divide_int(1, 2), d)
01941         self.assertEqual(c.divide_int(Decimal(1), 2), d)
01942         self.assertEqual(c.divide_int(1, Decimal(2)), d)
01943         self.assertRaises(TypeError, c.divide_int, '1', 2)
01944         self.assertRaises(TypeError, c.divide_int, 1, '2')
01945 
01946     def test_divmod(self):
01947         c = Context()
01948         d = c.divmod(Decimal(1), Decimal(2))
01949         self.assertEqual(c.divmod(1, 2), d)
01950         self.assertEqual(c.divmod(Decimal(1), 2), d)
01951         self.assertEqual(c.divmod(1, Decimal(2)), d)
01952         self.assertRaises(TypeError, c.divmod, '1', 2)
01953         self.assertRaises(TypeError, c.divmod, 1, '2')
01954 
01955     def test_exp(self):
01956         c = Context()
01957         d = c.exp(Decimal(10))
01958         self.assertEqual(c.exp(10), d)
01959         self.assertRaises(TypeError, c.exp, '10')
01960 
01961     def test_fma(self):
01962         c = Context()
01963         d = c.fma(Decimal(2), Decimal(3), Decimal(4))
01964         self.assertEqual(c.fma(2, 3, 4), d)
01965         self.assertEqual(c.fma(Decimal(2), 3, 4), d)
01966         self.assertEqual(c.fma(2, Decimal(3), 4), d)
01967         self.assertEqual(c.fma(2, 3, Decimal(4)), d)
01968         self.assertEqual(c.fma(Decimal(2), Decimal(3), 4), d)
01969         self.assertRaises(TypeError, c.fma, '2', 3, 4)
01970         self.assertRaises(TypeError, c.fma, 2, '3', 4)
01971         self.assertRaises(TypeError, c.fma, 2, 3, '4')
01972 
01973     def test_is_finite(self):
01974         c = Context()
01975         d = c.is_finite(Decimal(10))
01976         self.assertEqual(c.is_finite(10), d)
01977         self.assertRaises(TypeError, c.is_finite, '10')
01978 
01979     def test_is_infinite(self):
01980         c = Context()
01981         d = c.is_infinite(Decimal(10))
01982         self.assertEqual(c.is_infinite(10), d)
01983         self.assertRaises(TypeError, c.is_infinite, '10')
01984 
01985     def test_is_nan(self):
01986         c = Context()
01987         d = c.is_nan(Decimal(10))
01988         self.assertEqual(c.is_nan(10), d)
01989         self.assertRaises(TypeError, c.is_nan, '10')
01990 
01991     def test_is_normal(self):
01992         c = Context()
01993         d = c.is_normal(Decimal(10))
01994         self.assertEqual(c.is_normal(10), d)
01995         self.assertRaises(TypeError, c.is_normal, '10')
01996 
01997     def test_is_qnan(self):
01998         c = Context()
01999         d = c.is_qnan(Decimal(10))
02000         self.assertEqual(c.is_qnan(10), d)
02001         self.assertRaises(TypeError, c.is_qnan, '10')
02002 
02003     def test_is_signed(self):
02004         c = Context()
02005         d = c.is_signed(Decimal(10))
02006         self.assertEqual(c.is_signed(10), d)
02007         self.assertRaises(TypeError, c.is_signed, '10')
02008 
02009     def test_is_snan(self):
02010         c = Context()
02011         d = c.is_snan(Decimal(10))
02012         self.assertEqual(c.is_snan(10), d)
02013         self.assertRaises(TypeError, c.is_snan, '10')
02014 
02015     def test_is_subnormal(self):
02016         c = Context()
02017         d = c.is_subnormal(Decimal(10))
02018         self.assertEqual(c.is_subnormal(10), d)
02019         self.assertRaises(TypeError, c.is_subnormal, '10')
02020 
02021     def test_is_zero(self):
02022         c = Context()
02023         d = c.is_zero(Decimal(10))
02024         self.assertEqual(c.is_zero(10), d)
02025         self.assertRaises(TypeError, c.is_zero, '10')
02026 
02027     def test_ln(self):
02028         c = Context()
02029         d = c.ln(Decimal(10))
02030         self.assertEqual(c.ln(10), d)
02031         self.assertRaises(TypeError, c.ln, '10')
02032 
02033     def test_log10(self):
02034         c = Context()
02035         d = c.log10(Decimal(10))
02036         self.assertEqual(c.log10(10), d)
02037         self.assertRaises(TypeError, c.log10, '10')
02038 
02039     def test_logb(self):
02040         c = Context()
02041         d = c.logb(Decimal(10))
02042         self.assertEqual(c.logb(10), d)
02043         self.assertRaises(TypeError, c.logb, '10')
02044 
02045     def test_logical_and(self):
02046         c = Context()
02047         d = c.logical_and(Decimal(1), Decimal(1))
02048         self.assertEqual(c.logical_and(1, 1), d)
02049         self.assertEqual(c.logical_and(Decimal(1), 1), d)
02050         self.assertEqual(c.logical_and(1, Decimal(1)), d)
02051         self.assertRaises(TypeError, c.logical_and, '1', 1)
02052         self.assertRaises(TypeError, c.logical_and, 1, '1')
02053 
02054     def test_logical_invert(self):
02055         c = Context()
02056         d = c.logical_invert(Decimal(1000))
02057         self.assertEqual(c.logical_invert(1000), d)
02058         self.assertRaises(TypeError, c.logical_invert, '1000')
02059 
02060     def test_logical_or(self):
02061         c = Context()
02062         d = c.logical_or(Decimal(1), Decimal(1))
02063         self.assertEqual(c.logical_or(1, 1), d)
02064         self.assertEqual(c.logical_or(Decimal(1), 1), d)
02065         self.assertEqual(c.logical_or(1, Decimal(1)), d)
02066         self.assertRaises(TypeError, c.logical_or, '1', 1)
02067         self.assertRaises(TypeError, c.logical_or, 1, '1')
02068 
02069     def test_logical_xor(self):
02070         c = Context()
02071         d = c.logical_xor(Decimal(1), Decimal(1))
02072         self.assertEqual(c.logical_xor(1, 1), d)
02073         self.assertEqual(c.logical_xor(Decimal(1), 1), d)
02074         self.assertEqual(c.logical_xor(1, Decimal(1)), d)
02075         self.assertRaises(TypeError, c.logical_xor, '1', 1)
02076         self.assertRaises(TypeError, c.logical_xor, 1, '1')
02077 
02078     def test_max(self):
02079         c = Context()
02080         d = c.max(Decimal(1), Decimal(2))
02081         self.assertEqual(c.max(1, 2), d)
02082         self.assertEqual(c.max(Decimal(1), 2), d)
02083         self.assertEqual(c.max(1, Decimal(2)), d)
02084         self.assertRaises(TypeError, c.max, '1', 2)
02085         self.assertRaises(TypeError, c.max, 1, '2')
02086 
02087     def test_max_mag(self):
02088         c = Context()
02089         d = c.max_mag(Decimal(1), Decimal(2))
02090         self.assertEqual(c.max_mag(1, 2), d)
02091         self.assertEqual(c.max_mag(Decimal(1), 2), d)
02092         self.assertEqual(c.max_mag(1, Decimal(2)), d)
02093         self.assertRaises(TypeError, c.max_mag, '1', 2)
02094         self.assertRaises(TypeError, c.max_mag, 1, '2')
02095 
02096     def test_min(self):
02097         c = Context()
02098         d = c.min(Decimal(1), Decimal(2))
02099         self.assertEqual(c.min(1, 2), d)
02100         self.assertEqual(c.min(Decimal(1), 2), d)
02101         self.assertEqual(c.min(1, Decimal(2)), d)
02102         self.assertRaises(TypeError, c.min, '1', 2)
02103         self.assertRaises(TypeError, c.min, 1, '2')
02104 
02105     def test_min_mag(self):
02106         c = Context()
02107         d = c.min_mag(Decimal(1), Decimal(2))
02108         self.assertEqual(c.min_mag(1, 2), d)
02109         self.assertEqual(c.min_mag(Decimal(1), 2), d)
02110         self.assertEqual(c.min_mag(1, Decimal(2)), d)
02111         self.assertRaises(TypeError, c.min_mag, '1', 2)
02112         self.assertRaises(TypeError, c.min_mag, 1, '2')
02113 
02114     def test_minus(self):
02115         c = Context()
02116         d = c.minus(Decimal(10))
02117         self.assertEqual(c.minus(10), d)
02118         self.assertRaises(TypeError, c.minus, '10')
02119 
02120     def test_multiply(self):
02121         c = Context()
02122         d = c.multiply(Decimal(1), Decimal(2))
02123         self.assertEqual(c.multiply(1, 2), d)
02124         self.assertEqual(c.multiply(Decimal(1), 2), d)
02125         self.assertEqual(c.multiply(1, Decimal(2)), d)
02126         self.assertRaises(TypeError, c.multiply, '1', 2)
02127         self.assertRaises(TypeError, c.multiply, 1, '2')
02128 
02129     def test_next_minus(self):
02130         c = Context()
02131         d = c.next_minus(Decimal(10))
02132         self.assertEqual(c.next_minus(10), d)
02133         self.assertRaises(TypeError, c.next_minus, '10')
02134 
02135     def test_next_plus(self):
02136         c = Context()
02137         d = c.next_plus(Decimal(10))
02138         self.assertEqual(c.next_plus(10), d)
02139         self.assertRaises(TypeError, c.next_plus, '10')
02140 
02141     def test_next_toward(self):
02142         c = Context()
02143         d = c.next_toward(Decimal(1), Decimal(2))
02144         self.assertEqual(c.next_toward(1, 2), d)
02145         self.assertEqual(c.next_toward(Decimal(1), 2), d)
02146         self.assertEqual(c.next_toward(1, Decimal(2)), d)
02147         self.assertRaises(TypeError, c.next_toward, '1', 2)
02148         self.assertRaises(TypeError, c.next_toward, 1, '2')
02149 
02150     def test_normalize(self):
02151         c = Context()
02152         d = c.normalize(Decimal(10))
02153         self.assertEqual(c.normalize(10), d)
02154         self.assertRaises(TypeError, c.normalize, '10')
02155 
02156     def test_number_class(self):
02157         c = Context()
02158         self.assertEqual(c.number_class(123), c.number_class(Decimal(123)))
02159         self.assertEqual(c.number_class(0), c.number_class(Decimal(0)))
02160         self.assertEqual(c.number_class(-45), c.number_class(Decimal(-45)))
02161 
02162     def test_power(self):
02163         c = Context()
02164         d = c.power(Decimal(1), Decimal(4), Decimal(2))
02165         self.assertEqual(c.power(1, 4, 2), d)
02166         self.assertEqual(c.power(Decimal(1), 4, 2), d)
02167         self.assertEqual(c.power(1, Decimal(4), 2), d)
02168         self.assertEqual(c.power(1, 4, Decimal(2)), d)
02169         self.assertEqual(c.power(Decimal(1), Decimal(4), 2), d)
02170         self.assertRaises(TypeError, c.power, '1', 4, 2)
02171         self.assertRaises(TypeError, c.power, 1, '4', 2)
02172         self.assertRaises(TypeError, c.power, 1, 4, '2')
02173 
02174     def test_plus(self):
02175         c = Context()
02176         d = c.plus(Decimal(10))
02177         self.assertEqual(c.plus(10), d)
02178         self.assertRaises(TypeError, c.plus, '10')
02179 
02180     def test_quantize(self):
02181         c = Context()
02182         d = c.quantize(Decimal(1), Decimal(2))
02183         self.assertEqual(c.quantize(1, 2), d)
02184         self.assertEqual(c.quantize(Decimal(1), 2), d)
02185         self.assertEqual(c.quantize(1, Decimal(2)), d)
02186         self.assertRaises(TypeError, c.quantize, '1', 2)
02187         self.assertRaises(TypeError, c.quantize, 1, '2')
02188 
02189     def test_remainder(self):
02190         c = Context()
02191         d = c.remainder(Decimal(1), Decimal(2))
02192         self.assertEqual(c.remainder(1, 2), d)
02193         self.assertEqual(c.remainder(Decimal(1), 2), d)
02194         self.assertEqual(c.remainder(1, Decimal(2)), d)
02195         self.assertRaises(TypeError, c.remainder, '1', 2)
02196         self.assertRaises(TypeError, c.remainder, 1, '2')
02197 
02198     def test_remainder_near(self):
02199         c = Context()
02200         d = c.remainder_near(Decimal(1), Decimal(2))
02201         self.assertEqual(c.remainder_near(1, 2), d)
02202         self.assertEqual(c.remainder_near(Decimal(1), 2), d)
02203         self.assertEqual(c.remainder_near(1, Decimal(2)), d)
02204         self.assertRaises(TypeError, c.remainder_near, '1', 2)
02205         self.assertRaises(TypeError, c.remainder_near, 1, '2')
02206 
02207     def test_rotate(self):
02208         c = Context()
02209         d = c.rotate(Decimal(1), Decimal(2))
02210         self.assertEqual(c.rotate(1, 2), d)
02211         self.assertEqual(c.rotate(Decimal(1), 2), d)
02212         self.assertEqual(c.rotate(1, Decimal(2)), d)
02213         self.assertRaises(TypeError, c.rotate, '1', 2)
02214         self.assertRaises(TypeError, c.rotate, 1, '2')
02215 
02216     def test_sqrt(self):
02217         c = Context()
02218         d = c.sqrt(Decimal(10))
02219         self.assertEqual(c.sqrt(10), d)
02220         self.assertRaises(TypeError, c.sqrt, '10')
02221 
02222     def test_same_quantum(self):
02223         c = Context()
02224         d = c.same_quantum(Decimal(1), Decimal(2))
02225         self.assertEqual(c.same_quantum(1, 2), d)
02226         self.assertEqual(c.same_quantum(Decimal(1), 2), d)
02227         self.assertEqual(c.same_quantum(1, Decimal(2)), d)
02228         self.assertRaises(TypeError, c.same_quantum, '1', 2)
02229         self.assertRaises(TypeError, c.same_quantum, 1, '2')
02230 
02231     def test_scaleb(self):
02232         c = Context()
02233         d = c.scaleb(Decimal(1), Decimal(2))
02234         self.assertEqual(c.scaleb(1, 2), d)
02235         self.assertEqual(c.scaleb(Decimal(1), 2), d)
02236         self.assertEqual(c.scaleb(1, Decimal(2)), d)
02237         self.assertRaises(TypeError, c.scaleb, '1', 2)
02238         self.assertRaises(TypeError, c.scaleb, 1, '2')
02239 
02240     def test_shift(self):
02241         c = Context()
02242         d = c.shift(Decimal(1), Decimal(2))
02243         self.assertEqual(c.shift(1, 2), d)
02244         self.assertEqual(c.shift(Decimal(1), 2), d)
02245         self.assertEqual(c.shift(1, Decimal(2)), d)
02246         self.assertRaises(TypeError, c.shift, '1', 2)
02247         self.assertRaises(TypeError, c.shift, 1, '2')
02248 
02249     def test_subtract(self):
02250         c = Context()
02251         d = c.subtract(Decimal(1), Decimal(2))
02252         self.assertEqual(c.subtract(1, 2), d)
02253         self.assertEqual(c.subtract(Decimal(1), 2), d)
02254         self.assertEqual(c.subtract(1, Decimal(2)), d)
02255         self.assertRaises(TypeError, c.subtract, '1', 2)
02256         self.assertRaises(TypeError, c.subtract, 1, '2')
02257 
02258     def test_to_eng_string(self):
02259         c = Context()
02260         d = c.to_eng_string(Decimal(10))
02261         self.assertEqual(c.to_eng_string(10), d)
02262         self.assertRaises(TypeError, c.to_eng_string, '10')
02263 
02264     def test_to_sci_string(self):
02265         c = Context()
02266         d = c.to_sci_string(Decimal(10))
02267         self.assertEqual(c.to_sci_string(10), d)
02268         self.assertRaises(TypeError, c.to_sci_string, '10')
02269 
02270     def test_to_integral_exact(self):
02271         c = Context()
02272         d = c.to_integral_exact(Decimal(10))
02273         self.assertEqual(c.to_integral_exact(10), d)
02274         self.assertRaises(TypeError, c.to_integral_exact, '10')
02275 
02276     def test_to_integral_value(self):
02277         c = Context()
02278         d = c.to_integral_value(Decimal(10))
02279         self.assertEqual(c.to_integral_value(10), d)
02280         self.assertRaises(TypeError, c.to_integral_value, '10')
02281 
02282 class WithStatementTest(unittest.TestCase):
02283     # Can't do these as docstrings until Python 2.6
02284     # as doctest can't handle __future__ statements
02285 
02286     def test_localcontext(self):
02287         # Use a copy of the current context in the block
02288         orig_ctx = getcontext()
02289         with localcontext() as enter_ctx:
02290             set_ctx = getcontext()
02291         final_ctx = getcontext()
02292         self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
02293         self.assertIsNot(orig_ctx, set_ctx, 'did not copy the context')
02294         self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
02295 
02296     def test_localcontextarg(self):
02297         # Use a copy of the supplied context in the block
02298         orig_ctx = getcontext()
02299         new_ctx = Context(prec=42)
02300         with localcontext(new_ctx) as enter_ctx:
02301             set_ctx = getcontext()
02302         final_ctx = getcontext()
02303         self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
02304         self.assertEqual(set_ctx.prec, new_ctx.prec, 'did not set correct context')
02305         self.assertIsNot(new_ctx, set_ctx, 'did not copy the context')
02306         self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
02307 
02308 class ContextFlags(unittest.TestCase):
02309     def test_flags_irrelevant(self):
02310         # check that the result (numeric result + flags raised) of an
02311         # arithmetic operation doesn't depend on the current flags
02312 
02313         context = Context(prec=9, Emin = -999999999, Emax = 999999999,
02314                     rounding=ROUND_HALF_EVEN, traps=[], flags=[])
02315 
02316         # operations that raise various flags, in the form (function, arglist)
02317         operations = [
02318             (context._apply, [Decimal("100E-1000000009")]),
02319             (context.sqrt, [Decimal(2)]),
02320             (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]),
02321             (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]),
02322             (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]),
02323             ]
02324 
02325         # try various flags individually, then a whole lot at once
02326         flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal],
02327                     [Inexact, Rounded, Underflow, Clamped, Subnormal]]
02328 
02329         for fn, args in operations:
02330             # find answer and flags raised using a clean context
02331             context.clear_flags()
02332             ans = fn(*args)
02333             flags = [k for k, v in context.flags.items() if v]
02334 
02335             for extra_flags in flagsets:
02336                 # set flags, before calling operation
02337                 context.clear_flags()
02338                 for flag in extra_flags:
02339                     context._raise_error(flag)
02340                 new_ans = fn(*args)
02341 
02342                 # flags that we expect to be set after the operation
02343                 expected_flags = list(flags)
02344                 for flag in extra_flags:
02345                     if flag not in expected_flags:
02346                         expected_flags.append(flag)
02347                 expected_flags.sort(key=id)
02348 
02349                 # flags we actually got
02350                 new_flags = [k for k,v in context.flags.items() if v]
02351                 new_flags.sort(key=id)
02352 
02353                 self.assertEqual(ans, new_ans,
02354                                  "operation produces different answers depending on flags set: " +
02355                                  "expected %s, got %s." % (ans, new_ans))
02356                 self.assertEqual(new_flags, expected_flags,
02357                                   "operation raises different flags depending on flags set: " +
02358                                   "expected %s, got %s" % (expected_flags, new_flags))
02359 
02360 def test_main(arith=False, verbose=None, todo_tests=None, debug=None):
02361     """ Execute the tests.
02362 
02363     Runs all arithmetic tests if arith is True or if the "decimal" resource
02364     is enabled in regrtest.py
02365     """
02366 
02367     init()
02368     global TEST_ALL, DEBUG
02369     TEST_ALL = arith or is_resource_enabled('decimal')
02370     DEBUG = debug
02371 
02372     if todo_tests is None:
02373         test_classes = [
02374             DecimalExplicitConstructionTest,
02375             DecimalImplicitConstructionTest,
02376             DecimalArithmeticOperatorsTest,
02377             DecimalFormatTest,
02378             DecimalUseOfContextTest,
02379             DecimalUsabilityTest,
02380             DecimalPythonAPItests,
02381             ContextAPItests,
02382             DecimalTest,
02383             WithStatementTest,
02384             ContextFlags
02385         ]
02386     else:
02387         test_classes = [DecimalTest]
02388 
02389     # Dynamically build custom test definition for each file in the test
02390     # directory and add the definitions to the DecimalTest class.  This
02391     # procedure insures that new files do not get skipped.
02392     for filename in os.listdir(directory):
02393         if '.decTest' not in filename or filename.startswith("."):
02394             continue
02395         head, tail = filename.split('.')
02396         if todo_tests is not None and head not in todo_tests:
02397             continue
02398         tester = lambda self, f=filename: self.eval_file(directory + f)
02399         setattr(DecimalTest, 'test_' + head, tester)
02400         del filename, head, tail, tester
02401 
02402 
02403     try:
02404         run_unittest(*test_classes)
02405         if todo_tests is None:
02406             import decimal as DecimalModule
02407             run_doctest(DecimalModule, verbose)
02408     finally:
02409         setcontext(ORIGINAL_CONTEXT)
02410 
02411 if __name__ == '__main__':
02412     import optparse
02413     p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]")
02414     p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test')
02415     p.add_option('--skip',  '-s', action='store_true', help='skip over 90% of the arithmetic tests')
02416     (opt, args) = p.parse_args()
02417 
02418     if opt.skip:
02419         test_main(arith=False, verbose=True)
02420     elif args:
02421         test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug)
02422     else:
02423         test_main(arith=True, verbose=True)