Home | History | Annotate | Download | only in test
      1 # Copyright (c) 2004 Python Software Foundation.
      2 # All rights reserved.
      3 
      4 # Written by Eric Price <eprice at tjhsst.edu>
      5 #    and Facundo Batista <facundo at taniquetil.com.ar>
      6 #    and Raymond Hettinger <python at rcn.com>
      7 #    and Aahz (aahz at pobox.com)
      8 #    and Tim Peters
      9 
     10 """
     11 These are the test cases for the Decimal module.
     12 
     13 There are two groups of tests, Arithmetic and Behaviour. The former test
     14 the Decimal arithmetic using the tests provided by Mike Cowlishaw. The latter
     15 test the pythonic behaviour according to PEP 327.
     16 
     17 Cowlishaw's tests can be downloaded from:
     18 
     19    http://speleotrove.com/decimal/dectest.zip
     20 
     21 This test module can be called from command line with one parameter (Arithmetic
     22 or Behaviour) to test each part, or without parameter to test both parts. If
     23 you're working through IDLE, you can import this test module and call test_main()
     24 with the corresponding argument.
     25 """
     26 
     27 import math
     28 import os, sys
     29 import operator
     30 import warnings
     31 import pickle, copy
     32 import unittest
     33 import numbers
     34 import locale
     35 from test.support import (run_unittest, run_doctest, is_resource_enabled,
     36                           requires_IEEE_754, requires_docstrings)
     37 from test.support import (import_fresh_module, TestFailed,
     38                           run_with_locale, cpython_only)
     39 import random
     40 import inspect
     41 import threading
     42 
     43 
     44 C = import_fresh_module('decimal', fresh=['_decimal'])
     45 P = import_fresh_module('decimal', blocked=['_decimal'])
     46 orig_sys_decimal = sys.modules['decimal']
     47 
     48 # fractions module must import the correct decimal module.
     49 cfractions = import_fresh_module('fractions', fresh=['fractions'])
     50 sys.modules['decimal'] = P
     51 pfractions = import_fresh_module('fractions', fresh=['fractions'])
     52 sys.modules['decimal'] = C
     53 fractions = {C:cfractions, P:pfractions}
     54 sys.modules['decimal'] = orig_sys_decimal
     55 
     56 
     57 # Useful Test Constant
     58 Signals = {
     59   C: tuple(C.getcontext().flags.keys()) if C else None,
     60   P: tuple(P.getcontext().flags.keys())
     61 }
     62 # Signals ordered with respect to precedence: when an operation
     63 # produces multiple signals, signals occurring later in the list
     64 # should be handled before those occurring earlier in the list.
     65 OrderedSignals = {
     66   C: [C.Clamped, C.Rounded, C.Inexact, C.Subnormal, C.Underflow,
     67       C.Overflow, C.DivisionByZero, C.InvalidOperation,
     68       C.FloatOperation] if C else None,
     69   P: [P.Clamped, P.Rounded, P.Inexact, P.Subnormal, P.Underflow,
     70       P.Overflow, P.DivisionByZero, P.InvalidOperation,
     71       P.FloatOperation]
     72 }
     73 def assert_signals(cls, context, attr, expected):
     74     d = getattr(context, attr)
     75     cls.assertTrue(all(d[s] if s in expected else not d[s] for s in d))
     76 
     77 ROUND_UP = P.ROUND_UP
     78 ROUND_DOWN = P.ROUND_DOWN
     79 ROUND_CEILING = P.ROUND_CEILING
     80 ROUND_FLOOR = P.ROUND_FLOOR
     81 ROUND_HALF_UP = P.ROUND_HALF_UP
     82 ROUND_HALF_DOWN = P.ROUND_HALF_DOWN
     83 ROUND_HALF_EVEN = P.ROUND_HALF_EVEN
     84 ROUND_05UP = P.ROUND_05UP
     85 
     86 RoundingModes = [
     87   ROUND_UP, ROUND_DOWN, ROUND_CEILING, ROUND_FLOOR,
     88   ROUND_HALF_UP, ROUND_HALF_DOWN, ROUND_HALF_EVEN,
     89   ROUND_05UP
     90 ]
     91 
     92 # Tests are built around these assumed context defaults.
     93 # test_main() restores the original context.
     94 ORIGINAL_CONTEXT = {
     95   C: C.getcontext().copy() if C else None,
     96   P: P.getcontext().copy()
     97 }
     98 def init(m):
     99     if not m: return
    100     DefaultTestContext = m.Context(
    101        prec=9, rounding=ROUND_HALF_EVEN, traps=dict.fromkeys(Signals[m], 0)
    102     )
    103     m.setcontext(DefaultTestContext)
    104 
    105 TESTDATADIR = 'decimaltestdata'
    106 if __name__ == '__main__':
    107     file = sys.argv[0]
    108 else:
    109     file = __file__
    110 testdir = os.path.dirname(file) or os.curdir
    111 directory = testdir + os.sep + TESTDATADIR + os.sep
    112 
    113 skip_expected = not os.path.isdir(directory)
    114 
    115 # Make sure it actually raises errors when not expected and caught in flags
    116 # Slower, since it runs some things several times.
    117 EXTENDEDERRORTEST = False
    118 
    119 # Test extra functionality in the C version (-DEXTRA_FUNCTIONALITY).
    120 EXTRA_FUNCTIONALITY = True if hasattr(C, 'DecClamped') else False
    121 requires_extra_functionality = unittest.skipUnless(
    122   EXTRA_FUNCTIONALITY, "test requires build with -DEXTRA_FUNCTIONALITY")
    123 skip_if_extra_functionality = unittest.skipIf(
    124   EXTRA_FUNCTIONALITY, "test requires regular build")
    125 
    126 
    127 class IBMTestCases(unittest.TestCase):
    128     """Class which tests the Decimal class against the IBM test cases."""
    129 
    130     def setUp(self):
    131         self.context = self.decimal.Context()
    132         self.readcontext = self.decimal.Context()
    133         self.ignore_list = ['#']
    134 
    135         # List of individual .decTest test ids that correspond to tests that
    136         # we're skipping for one reason or another.
    137         self.skipped_test_ids = set([
    138             # Skip implementation-specific scaleb tests.
    139             'scbx164',
    140             'scbx165',
    141 
    142             # For some operations (currently exp, ln, log10, power), the decNumber
    143             # reference implementation imposes additional restrictions on the context
    144             # and operands.  These restrictions are not part of the specification;
    145             # however, the effect of these restrictions does show up in some of the
    146             # testcases.  We skip testcases that violate these restrictions, since
    147             # Decimal behaves differently from decNumber for these testcases so these
    148             # testcases would otherwise fail.
    149             'expx901',
    150             'expx902',
    151             'expx903',
    152             'expx905',
    153             'lnx901',
    154             'lnx902',
    155             'lnx903',
    156             'lnx905',
    157             'logx901',
    158             'logx902',
    159             'logx903',
    160             'logx905',
    161             'powx1183',
    162             'powx1184',
    163             'powx4001',
    164             'powx4002',
    165             'powx4003',
    166             'powx4005',
    167             'powx4008',
    168             'powx4010',
    169             'powx4012',
    170             'powx4014',
    171             ])
    172 
    173         if self.decimal == C:
    174             # status has additional Subnormal, Underflow
    175             self.skipped_test_ids.add('pwsx803')
    176             self.skipped_test_ids.add('pwsx805')
    177             # Correct rounding (skipped for decNumber, too)
    178             self.skipped_test_ids.add('powx4302')
    179             self.skipped_test_ids.add('powx4303')
    180             self.skipped_test_ids.add('powx4342')
    181             self.skipped_test_ids.add('powx4343')
    182             # http://bugs.python.org/issue7049
    183             self.skipped_test_ids.add('pwmx325')
    184             self.skipped_test_ids.add('pwmx326')
    185 
    186         # Map test directives to setter functions.
    187         self.ChangeDict = {'precision' : self.change_precision,
    188                            'rounding' : self.change_rounding_method,
    189                            'maxexponent' : self.change_max_exponent,
    190                            'minexponent' : self.change_min_exponent,
    191                            'clamp' : self.change_clamp}
    192 
    193         # Name adapter to be able to change the Decimal and Context
    194         # interface without changing the test files from Cowlishaw.
    195         self.NameAdapter = {'and':'logical_and',
    196                             'apply':'_apply',
    197                             'class':'number_class',
    198                             'comparesig':'compare_signal',
    199                             'comparetotal':'compare_total',
    200                             'comparetotmag':'compare_total_mag',
    201                             'copy':'copy_decimal',
    202                             'copyabs':'copy_abs',
    203                             'copynegate':'copy_negate',
    204                             'copysign':'copy_sign',
    205                             'divideint':'divide_int',
    206                             'invert':'logical_invert',
    207                             'iscanonical':'is_canonical',
    208                             'isfinite':'is_finite',
    209                             'isinfinite':'is_infinite',
    210                             'isnan':'is_nan',
    211                             'isnormal':'is_normal',
    212                             'isqnan':'is_qnan',
    213                             'issigned':'is_signed',
    214                             'issnan':'is_snan',
    215                             'issubnormal':'is_subnormal',
    216                             'iszero':'is_zero',
    217                             'maxmag':'max_mag',
    218                             'minmag':'min_mag',
    219                             'nextminus':'next_minus',
    220                             'nextplus':'next_plus',
    221                             'nexttoward':'next_toward',
    222                             'or':'logical_or',
    223                             'reduce':'normalize',
    224                             'remaindernear':'remainder_near',
    225                             'samequantum':'same_quantum',
    226                             'squareroot':'sqrt',
    227                             'toeng':'to_eng_string',
    228                             'tointegral':'to_integral_value',
    229                             'tointegralx':'to_integral_exact',
    230                             'tosci':'to_sci_string',
    231                             'xor':'logical_xor'}
    232 
    233         # Map test-case names to roundings.
    234         self.RoundingDict = {'ceiling' : ROUND_CEILING,
    235                              'down' : ROUND_DOWN,
    236                              'floor' : ROUND_FLOOR,
    237                              'half_down' : ROUND_HALF_DOWN,
    238                              'half_even' : ROUND_HALF_EVEN,
    239                              'half_up' : ROUND_HALF_UP,
    240                              'up' : ROUND_UP,
    241                              '05up' : ROUND_05UP}
    242 
    243         # Map the test cases' error names to the actual errors.
    244         self.ErrorNames = {'clamped' : self.decimal.Clamped,
    245                            'conversion_syntax' : self.decimal.InvalidOperation,
    246                            'division_by_zero' : self.decimal.DivisionByZero,
    247                            'division_impossible' : self.decimal.InvalidOperation,
    248                            'division_undefined' : self.decimal.InvalidOperation,
    249                            'inexact' : self.decimal.Inexact,
    250                            'invalid_context' : self.decimal.InvalidOperation,
    251                            'invalid_operation' : self.decimal.InvalidOperation,
    252                            'overflow' : self.decimal.Overflow,
    253                            'rounded' : self.decimal.Rounded,
    254                            'subnormal' : self.decimal.Subnormal,
    255                            'underflow' : self.decimal.Underflow}
    256 
    257         # The following functions return True/False rather than a
    258         # Decimal instance.
    259         self.LogicalFunctions = ('is_canonical',
    260                                  'is_finite',
    261                                  'is_infinite',
    262                                  'is_nan',
    263                                  'is_normal',
    264                                  'is_qnan',
    265                                  'is_signed',
    266                                  'is_snan',
    267                                  'is_subnormal',
    268                                  'is_zero',
    269                                  'same_quantum')
    270 
    271     def read_unlimited(self, v, context):
    272         """Work around the limitations of the 32-bit _decimal version. The
    273            guaranteed maximum values for prec, Emax etc. are 425000000,
    274            but higher values usually work, except for rare corner cases.
    275            In particular, all of the IBM tests pass with maximum values
    276            of 1070000000."""
    277         if self.decimal == C and self.decimal.MAX_EMAX == 425000000:
    278             self.readcontext._unsafe_setprec(1070000000)
    279             self.readcontext._unsafe_setemax(1070000000)
    280             self.readcontext._unsafe_setemin(-1070000000)
    281             return self.readcontext.create_decimal(v)
    282         else:
    283             return self.decimal.Decimal(v, context)
    284 
    285     def eval_file(self, file):
    286         global skip_expected
    287         if skip_expected:
    288             raise unittest.SkipTest
    289         with open(file) as f:
    290             for line in f:
    291                 line = line.replace('\r\n', '').replace('\n', '')
    292                 #print line
    293                 try:
    294                     t = self.eval_line(line)
    295                 except self.decimal.DecimalException as exception:
    296                     #Exception raised where there shouldn't have been one.
    297                     self.fail('Exception "'+exception.__class__.__name__ + '" raised on line '+line)
    298 
    299 
    300     def eval_line(self, s):
    301         if s.find(' -> ') >= 0 and s[:2] != '--' and not s.startswith('  --'):
    302             s = (s.split('->')[0] + '->' +
    303                  s.split('->')[1].split('--')[0]).strip()
    304         else:
    305             s = s.split('--')[0].strip()
    306 
    307         for ignore in self.ignore_list:
    308             if s.find(ignore) >= 0:
    309                 #print s.split()[0], 'NotImplemented--', ignore
    310                 return
    311         if not s:
    312             return
    313         elif ':' in s:
    314             return self.eval_directive(s)
    315         else:
    316             return self.eval_equation(s)
    317 
    318     def eval_directive(self, s):
    319         funct, value = (x.strip().lower() for x in s.split(':'))
    320         if funct == 'rounding':
    321             value = self.RoundingDict[value]
    322         else:
    323             try:
    324                 value = int(value)
    325             except ValueError:
    326                 pass
    327 
    328         funct = self.ChangeDict.get(funct, (lambda *args: None))
    329         funct(value)
    330 
    331     def eval_equation(self, s):
    332 
    333         if not TEST_ALL and random.random() < 0.90:
    334             return
    335 
    336         self.context.clear_flags()
    337 
    338         try:
    339             Sides = s.split('->')
    340             L = Sides[0].strip().split()
    341             id = L[0]
    342             if DEBUG:
    343                 print("Test ", id, end=" ")
    344             funct = L[1].lower()
    345             valstemp = L[2:]
    346             L = Sides[1].strip().split()
    347             ans = L[0]
    348             exceptions = L[1:]
    349         except (TypeError, AttributeError, IndexError):
    350             raise self.decimal.InvalidOperation
    351         def FixQuotes(val):
    352             val = val.replace("''", 'SingleQuote').replace('""', 'DoubleQuote')
    353             val = val.replace("'", '').replace('"', '')
    354             val = val.replace('SingleQuote', "'").replace('DoubleQuote', '"')
    355             return val
    356 
    357         if id in self.skipped_test_ids:
    358             return
    359 
    360         fname = self.NameAdapter.get(funct, funct)
    361         if fname == 'rescale':
    362             return
    363         funct = getattr(self.context, fname)
    364         vals = []
    365         conglomerate = ''
    366         quote = 0
    367         theirexceptions = [self.ErrorNames[x.lower()] for x in exceptions]
    368 
    369         for exception in Signals[self.decimal]:
    370             self.context.traps[exception] = 1 #Catch these bugs...
    371         for exception in theirexceptions:
    372             self.context.traps[exception] = 0
    373         for i, val in enumerate(valstemp):
    374             if val.count("'") % 2 == 1:
    375                 quote = 1 - quote
    376             if quote:
    377                 conglomerate = conglomerate + ' ' + val
    378                 continue
    379             else:
    380                 val = conglomerate + val
    381                 conglomerate = ''
    382             v = FixQuotes(val)
    383             if fname in ('to_sci_string', 'to_eng_string'):
    384                 if EXTENDEDERRORTEST:
    385                     for error in theirexceptions:
    386                         self.context.traps[error] = 1
    387                         try:
    388                             funct(self.context.create_decimal(v))
    389                         except error:
    390                             pass
    391                         except Signals[self.decimal] as e:
    392                             self.fail("Raised %s in %s when %s disabled" % \
    393                                       (e, s, error))
    394                         else:
    395                             self.fail("Did not raise %s in %s" % (error, s))
    396                         self.context.traps[error] = 0
    397                 v = self.context.create_decimal(v)
    398             else:
    399                 v = self.read_unlimited(v, self.context)
    400             vals.append(v)
    401 
    402         ans = FixQuotes(ans)
    403 
    404         if EXTENDEDERRORTEST and fname not in ('to_sci_string', 'to_eng_string'):
    405             for error in theirexceptions:
    406                 self.context.traps[error] = 1
    407                 try:
    408                     funct(*vals)
    409                 except error:
    410                     pass
    411                 except Signals[self.decimal] as e:
    412                     self.fail("Raised %s in %s when %s disabled" % \
    413                               (e, s, error))
    414                 else:
    415                     self.fail("Did not raise %s in %s" % (error, s))
    416                 self.context.traps[error] = 0
    417 
    418             # as above, but add traps cumulatively, to check precedence
    419             ordered_errors = [e for e in OrderedSignals[self.decimal] if e in theirexceptions]
    420             for error in ordered_errors:
    421                 self.context.traps[error] = 1
    422                 try:
    423                     funct(*vals)
    424                 except error:
    425                     pass
    426                 except Signals[self.decimal] as e:
    427                     self.fail("Raised %s in %s; expected %s" %
    428                               (type(e), s, error))
    429                 else:
    430                     self.fail("Did not raise %s in %s" % (error, s))
    431             # reset traps
    432             for error in ordered_errors:
    433                 self.context.traps[error] = 0
    434 
    435 
    436         if DEBUG:
    437             print("--", self.context)
    438         try:
    439             result = str(funct(*vals))
    440             if fname in self.LogicalFunctions:
    441                 result = str(int(eval(result))) # 'True', 'False' -> '1', '0'
    442         except Signals[self.decimal] as error:
    443             self.fail("Raised %s in %s" % (error, s))
    444         except: #Catch any error long enough to state the test case.
    445             print("ERROR:", s)
    446             raise
    447 
    448         myexceptions = self.getexceptions()
    449 
    450         myexceptions.sort(key=repr)
    451         theirexceptions.sort(key=repr)
    452 
    453         self.assertEqual(result, ans,
    454                          'Incorrect answer for ' + s + ' -- got ' + result)
    455 
    456         self.assertEqual(myexceptions, theirexceptions,
    457               'Incorrect flags set in ' + s + ' -- got ' + str(myexceptions))
    458 
    459     def getexceptions(self):
    460         return [e for e in Signals[self.decimal] if self.context.flags[e]]
    461 
    462     def change_precision(self, prec):
    463         if self.decimal == C and self.decimal.MAX_PREC == 425000000:
    464             self.context._unsafe_setprec(prec)
    465         else:
    466             self.context.prec = prec
    467     def change_rounding_method(self, rounding):
    468         self.context.rounding = rounding
    469     def change_min_exponent(self, exp):
    470         if self.decimal == C and self.decimal.MAX_PREC == 425000000:
    471             self.context._unsafe_setemin(exp)
    472         else:
    473             self.context.Emin = exp
    474     def change_max_exponent(self, exp):
    475         if self.decimal == C and self.decimal.MAX_PREC == 425000000:
    476             self.context._unsafe_setemax(exp)
    477         else:
    478             self.context.Emax = exp
    479     def change_clamp(self, clamp):
    480         self.context.clamp = clamp
    481 
    482 class CIBMTestCases(IBMTestCases):
    483     decimal = C
    484 class PyIBMTestCases(IBMTestCases):
    485     decimal = P
    486 
    487 # The following classes test the behaviour of Decimal according to PEP 327
    488 
    489 class ExplicitConstructionTest(unittest.TestCase):
    490     '''Unit tests for Explicit Construction cases of Decimal.'''
    491 
    492     def test_explicit_empty(self):
    493         Decimal = self.decimal.Decimal
    494         self.assertEqual(Decimal(), Decimal("0"))
    495 
    496     def test_explicit_from_None(self):
    497         Decimal = self.decimal.Decimal
    498         self.assertRaises(TypeError, Decimal, None)
    499 
    500     def test_explicit_from_int(self):
    501         Decimal = self.decimal.Decimal
    502 
    503         #positive
    504         d = Decimal(45)
    505         self.assertEqual(str(d), '45')
    506 
    507         #very large positive
    508         d = Decimal(500000123)
    509         self.assertEqual(str(d), '500000123')
    510 
    511         #negative
    512         d = Decimal(-45)
    513         self.assertEqual(str(d), '-45')
    514 
    515         #zero
    516         d = Decimal(0)
    517         self.assertEqual(str(d), '0')
    518 
    519         # single word longs
    520         for n in range(0, 32):
    521             for sign in (-1, 1):
    522                 for x in range(-5, 5):
    523                     i = sign * (2**n + x)
    524                     d = Decimal(i)
    525                     self.assertEqual(str(d), str(i))
    526 
    527     def test_explicit_from_string(self):
    528         Decimal = self.decimal.Decimal
    529         InvalidOperation = self.decimal.InvalidOperation
    530         localcontext = self.decimal.localcontext
    531 
    532         #empty
    533         self.assertEqual(str(Decimal('')), 'NaN')
    534 
    535         #int
    536         self.assertEqual(str(Decimal('45')), '45')
    537 
    538         #float
    539         self.assertEqual(str(Decimal('45.34')), '45.34')
    540 
    541         #engineer notation
    542         self.assertEqual(str(Decimal('45e2')), '4.5E+3')
    543 
    544         #just not a number
    545         self.assertEqual(str(Decimal('ugly')), 'NaN')
    546 
    547         #leading and trailing whitespace permitted
    548         self.assertEqual(str(Decimal('1.3E4 \n')), '1.3E+4')
    549         self.assertEqual(str(Decimal('  -7.89')), '-7.89')
    550         self.assertEqual(str(Decimal("  3.45679  ")), '3.45679')
    551 
    552         # underscores
    553         self.assertEqual(str(Decimal('1_3.3e4_0')), '1.33E+41')
    554         self.assertEqual(str(Decimal('1_0_0_0')), '1000')
    555 
    556         # unicode whitespace
    557         for lead in ["", ' ', '\u00a0', '\u205f']:
    558             for trail in ["", ' ', '\u00a0', '\u205f']:
    559                 self.assertEqual(str(Decimal(lead + '9.311E+28' + trail)),
    560                                  '9.311E+28')
    561 
    562         with localcontext() as c:
    563             c.traps[InvalidOperation] = True
    564             # Invalid string
    565             self.assertRaises(InvalidOperation, Decimal, "xyz")
    566             # Two arguments max
    567             self.assertRaises(TypeError, Decimal, "1234", "x", "y")
    568 
    569             # space within the numeric part
    570             self.assertRaises(InvalidOperation, Decimal, "1\u00a02\u00a03")
    571             self.assertRaises(InvalidOperation, Decimal, "\u00a01\u00a02\u00a0")
    572 
    573             # unicode whitespace
    574             self.assertRaises(InvalidOperation, Decimal, "\u00a0")
    575             self.assertRaises(InvalidOperation, Decimal, "\u00a0\u00a0")
    576 
    577             # embedded NUL
    578             self.assertRaises(InvalidOperation, Decimal, "12\u00003")
    579 
    580             # underscores don't prevent errors
    581             self.assertRaises(InvalidOperation, Decimal, "1_2_\u00003")
    582 
    583     @cpython_only
    584     def test_from_legacy_strings(self):
    585         import _testcapi
    586         Decimal = self.decimal.Decimal
    587         context = self.decimal.Context()
    588 
    589         s = _testcapi.unicode_legacy_string('9.999999')
    590         self.assertEqual(str(Decimal(s)), '9.999999')
    591         self.assertEqual(str(context.create_decimal(s)), '9.999999')
    592 
    593     def test_explicit_from_tuples(self):
    594         Decimal = self.decimal.Decimal
    595 
    596         #zero
    597         d = Decimal( (0, (0,), 0) )
    598         self.assertEqual(str(d), '0')
    599 
    600         #int
    601         d = Decimal( (1, (4, 5), 0) )
    602         self.assertEqual(str(d), '-45')
    603 
    604         #float
    605         d = Decimal( (0, (4, 5, 3, 4), -2) )
    606         self.assertEqual(str(d), '45.34')
    607 
    608         #weird
    609         d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
    610         self.assertEqual(str(d), '-4.34913534E-17')
    611 
    612         #inf
    613         d = Decimal( (0, (), "F") )
    614         self.assertEqual(str(d), 'Infinity')
    615 
    616         #wrong number of items
    617         self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1)) )
    618 
    619         #bad sign
    620         self.assertRaises(ValueError, Decimal, (8, (4, 3, 4, 9, 1), 2) )
    621         self.assertRaises(ValueError, Decimal, (0., (4, 3, 4, 9, 1), 2) )
    622         self.assertRaises(ValueError, Decimal, (Decimal(1), (4, 3, 4, 9, 1), 2))
    623 
    624         #bad exp
    625         self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 'wrong!') )
    626         self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 0.) )
    627         self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), '1') )
    628 
    629         #bad coefficients
    630         self.assertRaises(ValueError, Decimal, (1, "xyz", 2) )
    631         self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, None, 1), 2) )
    632         self.assertRaises(ValueError, Decimal, (1, (4, -3, 4, 9, 1), 2) )
    633         self.assertRaises(ValueError, Decimal, (1, (4, 10, 4, 9, 1), 2) )
    634         self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 'a', 1), 2) )
    635 
    636     def test_explicit_from_list(self):
    637         Decimal = self.decimal.Decimal
    638 
    639         d = Decimal([0, [0], 0])
    640         self.assertEqual(str(d), '0')
    641 
    642         d = Decimal([1, [4, 3, 4, 9, 1, 3, 5, 3, 4], -25])
    643         self.assertEqual(str(d), '-4.34913534E-17')
    644 
    645         d = Decimal([1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25])
    646         self.assertEqual(str(d), '-4.34913534E-17')
    647 
    648         d = Decimal((1, [4, 3, 4, 9, 1, 3, 5, 3, 4], -25))
    649         self.assertEqual(str(d), '-4.34913534E-17')
    650 
    651     def test_explicit_from_bool(self):
    652         Decimal = self.decimal.Decimal
    653 
    654         self.assertIs(bool(Decimal(0)), False)
    655         self.assertIs(bool(Decimal(1)), True)
    656         self.assertEqual(Decimal(False), Decimal(0))
    657         self.assertEqual(Decimal(True), Decimal(1))
    658 
    659     def test_explicit_from_Decimal(self):
    660         Decimal = self.decimal.Decimal
    661 
    662         #positive
    663         d = Decimal(45)
    664         e = Decimal(d)
    665         self.assertEqual(str(e), '45')
    666 
    667         #very large positive
    668         d = Decimal(500000123)
    669         e = Decimal(d)
    670         self.assertEqual(str(e), '500000123')
    671 
    672         #negative
    673         d = Decimal(-45)
    674         e = Decimal(d)
    675         self.assertEqual(str(e), '-45')
    676 
    677         #zero
    678         d = Decimal(0)
    679         e = Decimal(d)
    680         self.assertEqual(str(e), '0')
    681 
    682     @requires_IEEE_754
    683     def test_explicit_from_float(self):
    684 
    685         Decimal = self.decimal.Decimal
    686 
    687         r = Decimal(0.1)
    688         self.assertEqual(type(r), Decimal)
    689         self.assertEqual(str(r),
    690                 '0.1000000000000000055511151231257827021181583404541015625')
    691         self.assertTrue(Decimal(float('nan')).is_qnan())
    692         self.assertTrue(Decimal(float('inf')).is_infinite())
    693         self.assertTrue(Decimal(float('-inf')).is_infinite())
    694         self.assertEqual(str(Decimal(float('nan'))),
    695                          str(Decimal('NaN')))
    696         self.assertEqual(str(Decimal(float('inf'))),
    697                          str(Decimal('Infinity')))
    698         self.assertEqual(str(Decimal(float('-inf'))),
    699                          str(Decimal('-Infinity')))
    700         self.assertEqual(str(Decimal(float('-0.0'))),
    701                          str(Decimal('-0')))
    702         for i in range(200):
    703             x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
    704             self.assertEqual(x, float(Decimal(x))) # roundtrip
    705 
    706     def test_explicit_context_create_decimal(self):
    707         Decimal = self.decimal.Decimal
    708         InvalidOperation = self.decimal.InvalidOperation
    709         Rounded = self.decimal.Rounded
    710 
    711         nc = copy.copy(self.decimal.getcontext())
    712         nc.prec = 3
    713 
    714         # empty
    715         d = Decimal()
    716         self.assertEqual(str(d), '0')
    717         d = nc.create_decimal()
    718         self.assertEqual(str(d), '0')
    719 
    720         # from None
    721         self.assertRaises(TypeError, nc.create_decimal, None)
    722 
    723         # from int
    724         d = nc.create_decimal(456)
    725         self.assertIsInstance(d, Decimal)
    726         self.assertEqual(nc.create_decimal(45678),
    727                          nc.create_decimal('457E+2'))
    728 
    729         # from string
    730         d = Decimal('456789')
    731         self.assertEqual(str(d), '456789')
    732         d = nc.create_decimal('456789')
    733         self.assertEqual(str(d), '4.57E+5')
    734         # leading and trailing whitespace should result in a NaN;
    735         # spaces are already checked in Cowlishaw's test-suite, so
    736         # here we just check that a trailing newline results in a NaN
    737         self.assertEqual(str(nc.create_decimal('3.14\n')), 'NaN')
    738 
    739         # from tuples
    740         d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
    741         self.assertEqual(str(d), '-4.34913534E-17')
    742         d = nc.create_decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
    743         self.assertEqual(str(d), '-4.35E-17')
    744 
    745         # from Decimal
    746         prevdec = Decimal(500000123)
    747         d = Decimal(prevdec)
    748         self.assertEqual(str(d), '500000123')
    749         d = nc.create_decimal(prevdec)
    750         self.assertEqual(str(d), '5.00E+8')
    751 
    752         # more integers
    753         nc.prec = 28
    754         nc.traps[InvalidOperation] = True
    755 
    756         for v in [-2**63-1, -2**63, -2**31-1, -2**31, 0,
    757                    2**31-1, 2**31, 2**63-1, 2**63]:
    758             d = nc.create_decimal(v)
    759             self.assertTrue(isinstance(d, Decimal))
    760             self.assertEqual(int(d), v)
    761 
    762         nc.prec = 3
    763         nc.traps[Rounded] = True
    764         self.assertRaises(Rounded, nc.create_decimal, 1234)
    765 
    766         # from string
    767         nc.prec = 28
    768         self.assertEqual(str(nc.create_decimal('0E-017')), '0E-17')
    769         self.assertEqual(str(nc.create_decimal('45')), '45')
    770         self.assertEqual(str(nc.create_decimal('-Inf')), '-Infinity')
    771         self.assertEqual(str(nc.create_decimal('NaN123')), 'NaN123')
    772 
    773         # invalid arguments
    774         self.assertRaises(InvalidOperation, nc.create_decimal, "xyz")
    775         self.assertRaises(ValueError, nc.create_decimal, (1, "xyz", -25))
    776         self.assertRaises(TypeError, nc.create_decimal, "1234", "5678")
    777         # no whitespace and underscore stripping is done with this method
    778         self.assertRaises(InvalidOperation, nc.create_decimal, " 1234")
    779         self.assertRaises(InvalidOperation, nc.create_decimal, "12_34")
    780 
    781         # too many NaN payload digits
    782         nc.prec = 3
    783         self.assertRaises(InvalidOperation, nc.create_decimal, 'NaN12345')
    784         self.assertRaises(InvalidOperation, nc.create_decimal,
    785                           Decimal('NaN12345'))
    786 
    787         nc.traps[InvalidOperation] = False
    788         self.assertEqual(str(nc.create_decimal('NaN12345')), 'NaN')
    789         self.assertTrue(nc.flags[InvalidOperation])
    790 
    791         nc.flags[InvalidOperation] = False
    792         self.assertEqual(str(nc.create_decimal(Decimal('NaN12345'))), 'NaN')
    793         self.assertTrue(nc.flags[InvalidOperation])
    794 
    795     def test_explicit_context_create_from_float(self):
    796 
    797         Decimal = self.decimal.Decimal
    798 
    799         nc = self.decimal.Context()
    800         r = nc.create_decimal(0.1)
    801         self.assertEqual(type(r), Decimal)
    802         self.assertEqual(str(r), '0.1000000000000000055511151231')
    803         self.assertTrue(nc.create_decimal(float('nan')).is_qnan())
    804         self.assertTrue(nc.create_decimal(float('inf')).is_infinite())
    805         self.assertTrue(nc.create_decimal(float('-inf')).is_infinite())
    806         self.assertEqual(str(nc.create_decimal(float('nan'))),
    807                          str(nc.create_decimal('NaN')))
    808         self.assertEqual(str(nc.create_decimal(float('inf'))),
    809                          str(nc.create_decimal('Infinity')))
    810         self.assertEqual(str(nc.create_decimal(float('-inf'))),
    811                          str(nc.create_decimal('-Infinity')))
    812         self.assertEqual(str(nc.create_decimal(float('-0.0'))),
    813                          str(nc.create_decimal('-0')))
    814         nc.prec = 100
    815         for i in range(200):
    816             x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
    817             self.assertEqual(x, float(nc.create_decimal(x))) # roundtrip
    818 
    819     def test_unicode_digits(self):
    820         Decimal = self.decimal.Decimal
    821 
    822         test_values = {
    823             '\uff11': '1',
    824             '\u0660.\u0660\u0663\u0667\u0662e-\u0663' : '0.0000372',
    825             '-nan\u0c68\u0c6a\u0c66\u0c66' : '-NaN2400',
    826             }
    827         for input, expected in test_values.items():
    828             self.assertEqual(str(Decimal(input)), expected)
    829 
    830 class CExplicitConstructionTest(ExplicitConstructionTest):
    831     decimal = C
    832 class PyExplicitConstructionTest(ExplicitConstructionTest):
    833     decimal = P
    834 
    835 class ImplicitConstructionTest(unittest.TestCase):
    836     '''Unit tests for Implicit Construction cases of Decimal.'''
    837 
    838     def test_implicit_from_None(self):
    839         Decimal = self.decimal.Decimal
    840         self.assertRaises(TypeError, eval, 'Decimal(5) + None', locals())
    841 
    842     def test_implicit_from_int(self):
    843         Decimal = self.decimal.Decimal
    844 
    845         #normal
    846         self.assertEqual(str(Decimal(5) + 45), '50')
    847         #exceeding precision
    848         self.assertEqual(Decimal(5) + 123456789000, Decimal(123456789000))
    849 
    850     def test_implicit_from_string(self):
    851         Decimal = self.decimal.Decimal
    852         self.assertRaises(TypeError, eval, 'Decimal(5) + "3"', locals())
    853 
    854     def test_implicit_from_float(self):
    855         Decimal = self.decimal.Decimal
    856         self.assertRaises(TypeError, eval, 'Decimal(5) + 2.2', locals())
    857 
    858     def test_implicit_from_Decimal(self):
    859         Decimal = self.decimal.Decimal
    860         self.assertEqual(Decimal(5) + Decimal(45), Decimal(50))
    861 
    862     def test_rop(self):
    863         Decimal = self.decimal.Decimal
    864 
    865         # Allow other classes to be trained to interact with Decimals
    866         class E:
    867             def __divmod__(self, other):
    868                 return 'divmod ' + str(other)
    869             def __rdivmod__(self, other):
    870                 return str(other) + ' rdivmod'
    871             def __lt__(self, other):
    872                 return 'lt ' + str(other)
    873             def __gt__(self, other):
    874                 return 'gt ' + str(other)
    875             def __le__(self, other):
    876                 return 'le ' + str(other)
    877             def __ge__(self, other):
    878                 return 'ge ' + str(other)
    879             def __eq__(self, other):
    880                 return 'eq ' + str(other)
    881             def __ne__(self, other):
    882                 return 'ne ' + str(other)
    883 
    884         self.assertEqual(divmod(E(), Decimal(10)), 'divmod 10')
    885         self.assertEqual(divmod(Decimal(10), E()), '10 rdivmod')
    886         self.assertEqual(eval('Decimal(10) < E()'), 'gt 10')
    887         self.assertEqual(eval('Decimal(10) > E()'), 'lt 10')
    888         self.assertEqual(eval('Decimal(10) <= E()'), 'ge 10')
    889         self.assertEqual(eval('Decimal(10) >= E()'), 'le 10')
    890         self.assertEqual(eval('Decimal(10) == E()'), 'eq 10')
    891         self.assertEqual(eval('Decimal(10) != E()'), 'ne 10')
    892 
    893         # insert operator methods and then exercise them
    894         oplist = [
    895             ('+', '__add__', '__radd__'),
    896             ('-', '__sub__', '__rsub__'),
    897             ('*', '__mul__', '__rmul__'),
    898             ('/', '__truediv__', '__rtruediv__'),
    899             ('%', '__mod__', '__rmod__'),
    900             ('//', '__floordiv__', '__rfloordiv__'),
    901             ('**', '__pow__', '__rpow__')
    902         ]
    903 
    904         for sym, lop, rop in oplist:
    905             setattr(E, lop, lambda self, other: 'str' + lop + str(other))
    906             setattr(E, rop, lambda self, other: str(other) + rop + 'str')
    907             self.assertEqual(eval('E()' + sym + 'Decimal(10)'),
    908                              'str' + lop + '10')
    909             self.assertEqual(eval('Decimal(10)' + sym + 'E()'),
    910                              '10' + rop + 'str')
    911 
    912 class CImplicitConstructionTest(ImplicitConstructionTest):
    913     decimal = C
    914 class PyImplicitConstructionTest(ImplicitConstructionTest):
    915     decimal = P
    916 
    917 class FormatTest(unittest.TestCase):
    918     '''Unit tests for the format function.'''
    919     def test_formatting(self):
    920         Decimal = self.decimal.Decimal
    921 
    922         # triples giving a format, a Decimal, and the expected result
    923         test_values = [
    924             ('e', '0E-15', '0e-15'),
    925             ('e', '2.3E-15', '2.3e-15'),
    926             ('e', '2.30E+2', '2.30e+2'), # preserve significant zeros
    927             ('e', '2.30000E-15', '2.30000e-15'),
    928             ('e', '1.23456789123456789e40', '1.23456789123456789e+40'),
    929             ('e', '1.5', '1.5e+0'),
    930             ('e', '0.15', '1.5e-1'),
    931             ('e', '0.015', '1.5e-2'),
    932             ('e', '0.0000000000015', '1.5e-12'),
    933             ('e', '15.0', '1.50e+1'),
    934             ('e', '-15', '-1.5e+1'),
    935             ('e', '0', '0e+0'),
    936             ('e', '0E1', '0e+1'),
    937             ('e', '0.0', '0e-1'),
    938             ('e', '0.00', '0e-2'),
    939             ('.6e', '0E-15', '0.000000e-9'),
    940             ('.6e', '0', '0.000000e+6'),
    941             ('.6e', '9.999999', '9.999999e+0'),
    942             ('.6e', '9.9999999', '1.000000e+1'),
    943             ('.6e', '-1.23e5', '-1.230000e+5'),
    944             ('.6e', '1.23456789e-3', '1.234568e-3'),
    945             ('f', '0', '0'),
    946             ('f', '0.0', '0.0'),
    947             ('f', '0E-2', '0.00'),
    948             ('f', '0.00E-8', '0.0000000000'),
    949             ('f', '0E1', '0'), # loses exponent information
    950             ('f', '3.2E1', '32'),
    951             ('f', '3.2E2', '320'),
    952             ('f', '3.20E2', '320'),
    953             ('f', '3.200E2', '320.0'),
    954             ('f', '3.2E-6', '0.0000032'),
    955             ('.6f', '0E-15', '0.000000'), # all zeros treated equally
    956             ('.6f', '0E1', '0.000000'),
    957             ('.6f', '0', '0.000000'),
    958             ('.0f', '0', '0'), # no decimal point
    959             ('.0f', '0e-2', '0'),
    960             ('.0f', '3.14159265', '3'),
    961             ('.1f', '3.14159265', '3.1'),
    962             ('.4f', '3.14159265', '3.1416'),
    963             ('.6f', '3.14159265', '3.141593'),
    964             ('.7f', '3.14159265', '3.1415926'), # round-half-even!
    965             ('.8f', '3.14159265', '3.14159265'),
    966             ('.9f', '3.14159265', '3.141592650'),
    967 
    968             ('g', '0', '0'),
    969             ('g', '0.0', '0.0'),
    970             ('g', '0E1', '0e+1'),
    971             ('G', '0E1', '0E+1'),
    972             ('g', '0E-5', '0.00000'),
    973             ('g', '0E-6', '0.000000'),
    974             ('g', '0E-7', '0e-7'),
    975             ('g', '-0E2', '-0e+2'),
    976             ('.0g', '3.14159265', '3'),  # 0 sig fig -> 1 sig fig
    977             ('.0n', '3.14159265', '3'),  # same for 'n'
    978             ('.1g', '3.14159265', '3'),
    979             ('.2g', '3.14159265', '3.1'),
    980             ('.5g', '3.14159265', '3.1416'),
    981             ('.7g', '3.14159265', '3.141593'),
    982             ('.8g', '3.14159265', '3.1415926'), # round-half-even!
    983             ('.9g', '3.14159265', '3.14159265'),
    984             ('.10g', '3.14159265', '3.14159265'), # don't pad
    985 
    986             ('%', '0E1', '0%'),
    987             ('%', '0E0', '0%'),
    988             ('%', '0E-1', '0%'),
    989             ('%', '0E-2', '0%'),
    990             ('%', '0E-3', '0.0%'),
    991             ('%', '0E-4', '0.00%'),
    992 
    993             ('.3%', '0', '0.000%'), # all zeros treated equally
    994             ('.3%', '0E10', '0.000%'),
    995             ('.3%', '0E-10', '0.000%'),
    996             ('.3%', '2.34', '234.000%'),
    997             ('.3%', '1.234567', '123.457%'),
    998             ('.0%', '1.23', '123%'),
    999 
   1000             ('e', 'NaN', 'NaN'),
   1001             ('f', '-NaN123', '-NaN123'),
   1002             ('+g', 'NaN456', '+NaN456'),
   1003             ('.3e', 'Inf', 'Infinity'),
   1004             ('.16f', '-Inf', '-Infinity'),
   1005             ('.0g', '-sNaN', '-sNaN'),
   1006 
   1007             ('', '1.00', '1.00'),
   1008 
   1009             # test alignment and padding
   1010             ('6', '123', '   123'),
   1011             ('<6', '123', '123   '),
   1012             ('>6', '123', '   123'),
   1013             ('^6', '123', ' 123  '),
   1014             ('=+6', '123', '+  123'),
   1015             ('#<10', 'NaN', 'NaN#######'),
   1016             ('#<10', '-4.3', '-4.3######'),
   1017             ('#<+10', '0.0130', '+0.0130###'),
   1018             ('#< 10', '0.0130', ' 0.0130###'),
   1019             ('@>10', '-Inf', '@-Infinity'),
   1020             ('#>5', '-Inf', '-Infinity'),
   1021             ('?^5', '123', '?123?'),
   1022             ('%^6', '123', '%123%%'),
   1023             (' ^6', '-45.6', '-45.6 '),
   1024             ('/=10', '-45.6', '-/////45.6'),
   1025             ('/=+10', '45.6', '+/////45.6'),
   1026             ('/= 10', '45.6', ' /////45.6'),
   1027             ('\x00=10', '-inf', '-\x00Infinity'),
   1028             ('\x00^16', '-inf', '\x00\x00\x00-Infinity\x00\x00\x00\x00'),
   1029             ('\x00>10', '1.2345', '\x00\x00\x00\x001.2345'),
   1030             ('\x00<10', '1.2345', '1.2345\x00\x00\x00\x00'),
   1031 
   1032             # thousands separator
   1033             (',', '1234567', '1,234,567'),
   1034             (',', '123456', '123,456'),
   1035             (',', '12345', '12,345'),
   1036             (',', '1234', '1,234'),
   1037             (',', '123', '123'),
   1038             (',', '12', '12'),
   1039             (',', '1', '1'),
   1040             (',', '0', '0'),
   1041             (',', '-1234567', '-1,234,567'),
   1042             (',', '-123456', '-123,456'),
   1043             ('7,', '123456', '123,456'),
   1044             ('8,', '123456', ' 123,456'),
   1045             ('08,', '123456', '0,123,456'), # special case: extra 0 needed
   1046             ('+08,', '123456', '+123,456'), # but not if there's a sign
   1047             (' 08,', '123456', ' 123,456'),
   1048             ('08,', '-123456', '-123,456'),
   1049             ('+09,', '123456', '+0,123,456'),
   1050             # ... with fractional part...
   1051             ('07,', '1234.56', '1,234.56'),
   1052             ('08,', '1234.56', '1,234.56'),
   1053             ('09,', '1234.56', '01,234.56'),
   1054             ('010,', '1234.56', '001,234.56'),
   1055             ('011,', '1234.56', '0,001,234.56'),
   1056             ('012,', '1234.56', '0,001,234.56'),
   1057             ('08,.1f', '1234.5', '01,234.5'),
   1058             # no thousands separators in fraction part
   1059             (',', '1.23456789', '1.23456789'),
   1060             (',%', '123.456789', '12,345.6789%'),
   1061             (',e', '123456', '1.23456e+5'),
   1062             (',E', '123456', '1.23456E+5'),
   1063 
   1064             # issue 6850
   1065             ('a=-7.0', '0.12345', 'aaaa0.1'),
   1066 
   1067             # issue 22090
   1068             ('<^+15.20%', 'inf', '<<+Infinity%<<<'),
   1069             ('\x07>,%', 'sNaN1234567', 'sNaN1234567%'),
   1070             ('=10.10%', 'NaN123', '   NaN123%'),
   1071             ]
   1072         for fmt, d, result in test_values:
   1073             self.assertEqual(format(Decimal(d), fmt), result)
   1074 
   1075         # bytes format argument
   1076         self.assertRaises(TypeError, Decimal(1).__format__, b'-020')
   1077 
   1078     def test_n_format(self):
   1079         Decimal = self.decimal.Decimal
   1080 
   1081         try:
   1082             from locale import CHAR_MAX
   1083         except ImportError:
   1084             self.skipTest('locale.CHAR_MAX not available')
   1085 
   1086         def make_grouping(lst):
   1087             return ''.join([chr(x) for x in lst]) if self.decimal == C else lst
   1088 
   1089         def get_fmt(x, override=None, fmt='n'):
   1090             if self.decimal == C:
   1091                 return Decimal(x).__format__(fmt, override)
   1092             else:
   1093                 return Decimal(x).__format__(fmt, _localeconv=override)
   1094 
   1095         # Set up some localeconv-like dictionaries
   1096         en_US = {
   1097             'decimal_point' : '.',
   1098             'grouping' : make_grouping([3, 3, 0]),
   1099             'thousands_sep' : ','
   1100             }
   1101 
   1102         fr_FR = {
   1103             'decimal_point' : ',',
   1104             'grouping' : make_grouping([CHAR_MAX]),
   1105             'thousands_sep' : ''
   1106             }
   1107 
   1108         ru_RU = {
   1109             'decimal_point' : ',',
   1110             'grouping': make_grouping([3, 3, 0]),
   1111             'thousands_sep' : ' '
   1112             }
   1113 
   1114         crazy = {
   1115             'decimal_point' : '&',
   1116             'grouping': make_grouping([1, 4, 2, CHAR_MAX]),
   1117             'thousands_sep' : '-'
   1118             }
   1119 
   1120         dotsep_wide = {
   1121             'decimal_point' : b'\xc2\xbf'.decode('utf-8'),
   1122             'grouping': make_grouping([3, 3, 0]),
   1123             'thousands_sep' : b'\xc2\xb4'.decode('utf-8')
   1124             }
   1125 
   1126         self.assertEqual(get_fmt(Decimal('12.7'), en_US), '12.7')
   1127         self.assertEqual(get_fmt(Decimal('12.7'), fr_FR), '12,7')
   1128         self.assertEqual(get_fmt(Decimal('12.7'), ru_RU), '12,7')
   1129         self.assertEqual(get_fmt(Decimal('12.7'), crazy), '1-2&7')
   1130 
   1131         self.assertEqual(get_fmt(123456789, en_US), '123,456,789')
   1132         self.assertEqual(get_fmt(123456789, fr_FR), '123456789')
   1133         self.assertEqual(get_fmt(123456789, ru_RU), '123 456 789')
   1134         self.assertEqual(get_fmt(1234567890123, crazy), '123456-78-9012-3')
   1135 
   1136         self.assertEqual(get_fmt(123456789, en_US, '.6n'), '1.23457e+8')
   1137         self.assertEqual(get_fmt(123456789, fr_FR, '.6n'), '1,23457e+8')
   1138         self.assertEqual(get_fmt(123456789, ru_RU, '.6n'), '1,23457e+8')
   1139         self.assertEqual(get_fmt(123456789, crazy, '.6n'), '1&23457e+8')
   1140 
   1141         # zero padding
   1142         self.assertEqual(get_fmt(1234, fr_FR, '03n'), '1234')
   1143         self.assertEqual(get_fmt(1234, fr_FR, '04n'), '1234')
   1144         self.assertEqual(get_fmt(1234, fr_FR, '05n'), '01234')
   1145         self.assertEqual(get_fmt(1234, fr_FR, '06n'), '001234')
   1146 
   1147         self.assertEqual(get_fmt(12345, en_US, '05n'), '12,345')
   1148         self.assertEqual(get_fmt(12345, en_US, '06n'), '12,345')
   1149         self.assertEqual(get_fmt(12345, en_US, '07n'), '012,345')
   1150         self.assertEqual(get_fmt(12345, en_US, '08n'), '0,012,345')
   1151         self.assertEqual(get_fmt(12345, en_US, '09n'), '0,012,345')
   1152         self.assertEqual(get_fmt(12345, en_US, '010n'), '00,012,345')
   1153 
   1154         self.assertEqual(get_fmt(123456, crazy, '06n'), '1-2345-6')
   1155         self.assertEqual(get_fmt(123456, crazy, '07n'), '1-2345-6')
   1156         self.assertEqual(get_fmt(123456, crazy, '08n'), '1-2345-6')
   1157         self.assertEqual(get_fmt(123456, crazy, '09n'), '01-2345-6')
   1158         self.assertEqual(get_fmt(123456, crazy, '010n'), '0-01-2345-6')
   1159         self.assertEqual(get_fmt(123456, crazy, '011n'), '0-01-2345-6')
   1160         self.assertEqual(get_fmt(123456, crazy, '012n'), '00-01-2345-6')
   1161         self.assertEqual(get_fmt(123456, crazy, '013n'), '000-01-2345-6')
   1162 
   1163         # wide char separator and decimal point
   1164         self.assertEqual(get_fmt(Decimal('-1.5'), dotsep_wide, '020n'),
   1165                          '-0\u00b4000\u00b4000\u00b4000\u00b4001\u00bf5')
   1166 
   1167     @run_with_locale('LC_ALL', 'ps_AF')
   1168     def test_wide_char_separator_decimal_point(self):
   1169         # locale with wide char separator and decimal point
   1170         Decimal = self.decimal.Decimal
   1171 
   1172         decimal_point = locale.localeconv()['decimal_point']
   1173         thousands_sep = locale.localeconv()['thousands_sep']
   1174         if decimal_point != '\u066b':
   1175             self.skipTest('inappropriate decimal point separator '
   1176                           '({!a} not {!a})'.format(decimal_point, '\u066b'))
   1177         if thousands_sep != '\u066c':
   1178             self.skipTest('inappropriate thousands separator '
   1179                           '({!a} not {!a})'.format(thousands_sep, '\u066c'))
   1180 
   1181         self.assertEqual(format(Decimal('100000000.123'), 'n'),
   1182                          '100\u066c000\u066c000\u066b123')
   1183 
   1184     def test_decimal_from_float_argument_type(self):
   1185         class A(self.decimal.Decimal):
   1186             def __init__(self, a):
   1187                 self.a_type = type(a)
   1188         a = A.from_float(42.5)
   1189         self.assertEqual(self.decimal.Decimal, a.a_type)
   1190 
   1191         a = A.from_float(42)
   1192         self.assertEqual(self.decimal.Decimal, a.a_type)
   1193 
   1194 class CFormatTest(FormatTest):
   1195     decimal = C
   1196 class PyFormatTest(FormatTest):
   1197     decimal = P
   1198 
   1199 class ArithmeticOperatorsTest(unittest.TestCase):
   1200     '''Unit tests for all arithmetic operators, binary and unary.'''
   1201 
   1202     def test_addition(self):
   1203         Decimal = self.decimal.Decimal
   1204 
   1205         d1 = Decimal('-11.1')
   1206         d2 = Decimal('22.2')
   1207 
   1208         #two Decimals
   1209         self.assertEqual(d1+d2, Decimal('11.1'))
   1210         self.assertEqual(d2+d1, Decimal('11.1'))
   1211 
   1212         #with other type, left
   1213         c = d1 + 5
   1214         self.assertEqual(c, Decimal('-6.1'))
   1215         self.assertEqual(type(c), type(d1))
   1216 
   1217         #with other type, right
   1218         c = 5 + d1
   1219         self.assertEqual(c, Decimal('-6.1'))
   1220         self.assertEqual(type(c), type(d1))
   1221 
   1222         #inline with decimal
   1223         d1 += d2
   1224         self.assertEqual(d1, Decimal('11.1'))
   1225 
   1226         #inline with other type
   1227         d1 += 5
   1228         self.assertEqual(d1, Decimal('16.1'))
   1229 
   1230     def test_subtraction(self):
   1231         Decimal = self.decimal.Decimal
   1232 
   1233         d1 = Decimal('-11.1')
   1234         d2 = Decimal('22.2')
   1235 
   1236         #two Decimals
   1237         self.assertEqual(d1-d2, Decimal('-33.3'))
   1238         self.assertEqual(d2-d1, Decimal('33.3'))
   1239 
   1240         #with other type, left
   1241         c = d1 - 5
   1242         self.assertEqual(c, Decimal('-16.1'))
   1243         self.assertEqual(type(c), type(d1))
   1244 
   1245         #with other type, right
   1246         c = 5 - d1
   1247         self.assertEqual(c, Decimal('16.1'))
   1248         self.assertEqual(type(c), type(d1))
   1249 
   1250         #inline with decimal
   1251         d1 -= d2
   1252         self.assertEqual(d1, Decimal('-33.3'))
   1253 
   1254         #inline with other type
   1255         d1 -= 5
   1256         self.assertEqual(d1, Decimal('-38.3'))
   1257 
   1258     def test_multiplication(self):
   1259         Decimal = self.decimal.Decimal
   1260 
   1261         d1 = Decimal('-5')
   1262         d2 = Decimal('3')
   1263 
   1264         #two Decimals
   1265         self.assertEqual(d1*d2, Decimal('-15'))
   1266         self.assertEqual(d2*d1, Decimal('-15'))
   1267 
   1268         #with other type, left
   1269         c = d1 * 5
   1270         self.assertEqual(c, Decimal('-25'))
   1271         self.assertEqual(type(c), type(d1))
   1272 
   1273         #with other type, right
   1274         c = 5 * d1
   1275         self.assertEqual(c, Decimal('-25'))
   1276         self.assertEqual(type(c), type(d1))
   1277 
   1278         #inline with decimal
   1279         d1 *= d2
   1280         self.assertEqual(d1, Decimal('-15'))
   1281 
   1282         #inline with other type
   1283         d1 *= 5
   1284         self.assertEqual(d1, Decimal('-75'))
   1285 
   1286     def test_division(self):
   1287         Decimal = self.decimal.Decimal
   1288 
   1289         d1 = Decimal('-5')
   1290         d2 = Decimal('2')
   1291 
   1292         #two Decimals
   1293         self.assertEqual(d1/d2, Decimal('-2.5'))
   1294         self.assertEqual(d2/d1, Decimal('-0.4'))
   1295 
   1296         #with other type, left
   1297         c = d1 / 4
   1298         self.assertEqual(c, Decimal('-1.25'))
   1299         self.assertEqual(type(c), type(d1))
   1300 
   1301         #with other type, right
   1302         c = 4 / d1
   1303         self.assertEqual(c, Decimal('-0.8'))
   1304         self.assertEqual(type(c), type(d1))
   1305 
   1306         #inline with decimal
   1307         d1 /= d2
   1308         self.assertEqual(d1, Decimal('-2.5'))
   1309 
   1310         #inline with other type
   1311         d1 /= 4
   1312         self.assertEqual(d1, Decimal('-0.625'))
   1313 
   1314     def test_floor_division(self):
   1315         Decimal = self.decimal.Decimal
   1316 
   1317         d1 = Decimal('5')
   1318         d2 = Decimal('2')
   1319 
   1320         #two Decimals
   1321         self.assertEqual(d1//d2, Decimal('2'))
   1322         self.assertEqual(d2//d1, Decimal('0'))
   1323 
   1324         #with other type, left
   1325         c = d1 // 4
   1326         self.assertEqual(c, Decimal('1'))
   1327         self.assertEqual(type(c), type(d1))
   1328 
   1329         #with other type, right
   1330         c = 7 // d1
   1331         self.assertEqual(c, Decimal('1'))
   1332         self.assertEqual(type(c), type(d1))
   1333 
   1334         #inline with decimal
   1335         d1 //= d2
   1336         self.assertEqual(d1, Decimal('2'))
   1337 
   1338         #inline with other type
   1339         d1 //= 2
   1340         self.assertEqual(d1, Decimal('1'))
   1341 
   1342     def test_powering(self):
   1343         Decimal = self.decimal.Decimal
   1344 
   1345         d1 = Decimal('5')
   1346         d2 = Decimal('2')
   1347 
   1348         #two Decimals
   1349         self.assertEqual(d1**d2, Decimal('25'))
   1350         self.assertEqual(d2**d1, Decimal('32'))
   1351 
   1352         #with other type, left
   1353         c = d1 ** 4
   1354         self.assertEqual(c, Decimal('625'))
   1355         self.assertEqual(type(c), type(d1))
   1356 
   1357         #with other type, right
   1358         c = 7 ** d1
   1359         self.assertEqual(c, Decimal('16807'))
   1360         self.assertEqual(type(c), type(d1))
   1361 
   1362         #inline with decimal
   1363         d1 **= d2
   1364         self.assertEqual(d1, Decimal('25'))
   1365 
   1366         #inline with other type
   1367         d1 **= 4
   1368         self.assertEqual(d1, Decimal('390625'))
   1369 
   1370     def test_module(self):
   1371         Decimal = self.decimal.Decimal
   1372 
   1373         d1 = Decimal('5')
   1374         d2 = Decimal('2')
   1375 
   1376         #two Decimals
   1377         self.assertEqual(d1%d2, Decimal('1'))
   1378         self.assertEqual(d2%d1, Decimal('2'))
   1379 
   1380         #with other type, left
   1381         c = d1 % 4
   1382         self.assertEqual(c, Decimal('1'))
   1383         self.assertEqual(type(c), type(d1))
   1384 
   1385         #with other type, right
   1386         c = 7 % d1
   1387         self.assertEqual(c, Decimal('2'))
   1388         self.assertEqual(type(c), type(d1))
   1389 
   1390         #inline with decimal
   1391         d1 %= d2
   1392         self.assertEqual(d1, Decimal('1'))
   1393 
   1394         #inline with other type
   1395         d1 %= 4
   1396         self.assertEqual(d1, Decimal('1'))
   1397 
   1398     def test_floor_div_module(self):
   1399         Decimal = self.decimal.Decimal
   1400 
   1401         d1 = Decimal('5')
   1402         d2 = Decimal('2')
   1403 
   1404         #two Decimals
   1405         (p, q) = divmod(d1, d2)
   1406         self.assertEqual(p, Decimal('2'))
   1407         self.assertEqual(q, Decimal('1'))
   1408         self.assertEqual(type(p), type(d1))
   1409         self.assertEqual(type(q), type(d1))
   1410 
   1411         #with other type, left
   1412         (p, q) = divmod(d1, 4)
   1413         self.assertEqual(p, Decimal('1'))
   1414         self.assertEqual(q, Decimal('1'))
   1415         self.assertEqual(type(p), type(d1))
   1416         self.assertEqual(type(q), type(d1))
   1417 
   1418         #with other type, right
   1419         (p, q) = divmod(7, d1)
   1420         self.assertEqual(p, Decimal('1'))
   1421         self.assertEqual(q, Decimal('2'))
   1422         self.assertEqual(type(p), type(d1))
   1423         self.assertEqual(type(q), type(d1))
   1424 
   1425     def test_unary_operators(self):
   1426         Decimal = self.decimal.Decimal
   1427 
   1428         self.assertEqual(+Decimal(45), Decimal(+45))           #  +
   1429         self.assertEqual(-Decimal(45), Decimal(-45))           #  -
   1430         self.assertEqual(abs(Decimal(45)), abs(Decimal(-45)))  # abs
   1431 
   1432     def test_nan_comparisons(self):
   1433         # comparisons involving signaling nans signal InvalidOperation
   1434 
   1435         # order comparisons (<, <=, >, >=) involving only quiet nans
   1436         # also signal InvalidOperation
   1437 
   1438         # equality comparisons (==, !=) involving only quiet nans
   1439         # don't signal, but return False or True respectively.
   1440         Decimal = self.decimal.Decimal
   1441         InvalidOperation = self.decimal.InvalidOperation
   1442         localcontext = self.decimal.localcontext
   1443 
   1444         n = Decimal('NaN')
   1445         s = Decimal('sNaN')
   1446         i = Decimal('Inf')
   1447         f = Decimal('2')
   1448 
   1449         qnan_pairs = (n, n), (n, i), (i, n), (n, f), (f, n)
   1450         snan_pairs = (s, n), (n, s), (s, i), (i, s), (s, f), (f, s), (s, s)
   1451         order_ops = operator.lt, operator.le, operator.gt, operator.ge
   1452         equality_ops = operator.eq, operator.ne
   1453 
   1454         # results when InvalidOperation is not trapped
   1455         for x, y in qnan_pairs + snan_pairs:
   1456             for op in order_ops + equality_ops:
   1457                 got = op(x, y)
   1458                 expected = True if op is operator.ne else False
   1459                 self.assertIs(expected, got,
   1460                               "expected {0!r} for operator.{1}({2!r}, {3!r}); "
   1461                               "got {4!r}".format(
   1462                         expected, op.__name__, x, y, got))
   1463 
   1464         # repeat the above, but this time trap the InvalidOperation
   1465         with localcontext() as ctx:
   1466             ctx.traps[InvalidOperation] = 1
   1467 
   1468             for x, y in qnan_pairs:
   1469                 for op in equality_ops:
   1470                     got = op(x, y)
   1471                     expected = True if op is operator.ne else False
   1472                     self.assertIs(expected, got,
   1473                                   "expected {0!r} for "
   1474                                   "operator.{1}({2!r}, {3!r}); "
   1475                                   "got {4!r}".format(
   1476                             expected, op.__name__, x, y, got))
   1477 
   1478             for x, y in snan_pairs:
   1479                 for op in equality_ops:
   1480                     self.assertRaises(InvalidOperation, operator.eq, x, y)
   1481                     self.assertRaises(InvalidOperation, operator.ne, x, y)
   1482 
   1483             for x, y in qnan_pairs + snan_pairs:
   1484                 for op in order_ops:
   1485                     self.assertRaises(InvalidOperation, op, x, y)
   1486 
   1487     def test_copy_sign(self):
   1488         Decimal = self.decimal.Decimal
   1489 
   1490         d = Decimal(1).copy_sign(Decimal(-2))
   1491         self.assertEqual(Decimal(1).copy_sign(-2), d)
   1492         self.assertRaises(TypeError, Decimal(1).copy_sign, '-2')
   1493 
   1494 class CArithmeticOperatorsTest(ArithmeticOperatorsTest):
   1495     decimal = C
   1496 class PyArithmeticOperatorsTest(ArithmeticOperatorsTest):
   1497     decimal = P
   1498 
   1499 # The following are two functions used to test threading in the next class
   1500 
   1501 def thfunc1(cls):
   1502     Decimal = cls.decimal.Decimal
   1503     InvalidOperation = cls.decimal.InvalidOperation
   1504     DivisionByZero = cls.decimal.DivisionByZero
   1505     Overflow = cls.decimal.Overflow
   1506     Underflow = cls.decimal.Underflow
   1507     Inexact = cls.decimal.Inexact
   1508     getcontext = cls.decimal.getcontext
   1509     localcontext = cls.decimal.localcontext
   1510 
   1511     d1 = Decimal(1)
   1512     d3 = Decimal(3)
   1513     test1 = d1/d3
   1514 
   1515     cls.finish1.set()
   1516     cls.synchro.wait()
   1517 
   1518     test2 = d1/d3
   1519     with localcontext() as c2:
   1520         cls.assertTrue(c2.flags[Inexact])
   1521         cls.assertRaises(DivisionByZero, c2.divide, d1, 0)
   1522         cls.assertTrue(c2.flags[DivisionByZero])
   1523         with localcontext() as c3:
   1524             cls.assertTrue(c3.flags[Inexact])
   1525             cls.assertTrue(c3.flags[DivisionByZero])
   1526             cls.assertRaises(InvalidOperation, c3.compare, d1, Decimal('sNaN'))
   1527             cls.assertTrue(c3.flags[InvalidOperation])
   1528             del c3
   1529         cls.assertFalse(c2.flags[InvalidOperation])
   1530         del c2
   1531 
   1532     cls.assertEqual(test1, Decimal('0.333333333333333333333333'))
   1533     cls.assertEqual(test2, Decimal('0.333333333333333333333333'))
   1534 
   1535     c1 = getcontext()
   1536     cls.assertTrue(c1.flags[Inexact])
   1537     for sig in Overflow, Underflow, DivisionByZero, InvalidOperation:
   1538         cls.assertFalse(c1.flags[sig])
   1539 
   1540 def thfunc2(cls):
   1541     Decimal = cls.decimal.Decimal
   1542     InvalidOperation = cls.decimal.InvalidOperation
   1543     DivisionByZero = cls.decimal.DivisionByZero
   1544     Overflow = cls.decimal.Overflow
   1545     Underflow = cls.decimal.Underflow
   1546     Inexact = cls.decimal.Inexact
   1547     getcontext = cls.decimal.getcontext
   1548     localcontext = cls.decimal.localcontext
   1549 
   1550     d1 = Decimal(1)
   1551     d3 = Decimal(3)
   1552     test1 = d1/d3
   1553 
   1554     thiscontext = getcontext()
   1555     thiscontext.prec = 18
   1556     test2 = d1/d3
   1557 
   1558     with localcontext() as c2:
   1559         cls.assertTrue(c2.flags[Inexact])
   1560         cls.assertRaises(Overflow, c2.multiply, Decimal('1e425000000'), 999)
   1561         cls.assertTrue(c2.flags[Overflow])
   1562         with localcontext(thiscontext) as c3:
   1563             cls.assertTrue(c3.flags[Inexact])
   1564             cls.assertFalse(c3.flags[Overflow])
   1565             c3.traps[Underflow] = True
   1566             cls.assertRaises(Underflow, c3.divide, Decimal('1e-425000000'), 999)
   1567             cls.assertTrue(c3.flags[Underflow])
   1568             del c3
   1569         cls.assertFalse(c2.flags[Underflow])
   1570         cls.assertFalse(c2.traps[Underflow])
   1571         del c2
   1572 
   1573     cls.synchro.set()
   1574     cls.finish2.set()
   1575 
   1576     cls.assertEqual(test1, Decimal('0.333333333333333333333333'))
   1577     cls.assertEqual(test2, Decimal('0.333333333333333333'))
   1578 
   1579     cls.assertFalse(thiscontext.traps[Underflow])
   1580     cls.assertTrue(thiscontext.flags[Inexact])
   1581     for sig in Overflow, Underflow, DivisionByZero, InvalidOperation:
   1582         cls.assertFalse(thiscontext.flags[sig])
   1583 
   1584 class ThreadingTest(unittest.TestCase):
   1585     '''Unit tests for thread local contexts in Decimal.'''
   1586 
   1587     # Take care executing this test from IDLE, there's an issue in threading
   1588     # that hangs IDLE and I couldn't find it
   1589 
   1590     def test_threading(self):
   1591         DefaultContext = self.decimal.DefaultContext
   1592 
   1593         if self.decimal == C and not self.decimal.HAVE_THREADS:
   1594             self.skipTest("compiled without threading")
   1595         # Test the "threading isolation" of a Context. Also test changing
   1596         # the DefaultContext, which acts as a template for the thread-local
   1597         # contexts.
   1598         save_prec = DefaultContext.prec
   1599         save_emax = DefaultContext.Emax
   1600         save_emin = DefaultContext.Emin
   1601         DefaultContext.prec = 24
   1602         DefaultContext.Emax = 425000000
   1603         DefaultContext.Emin = -425000000
   1604 
   1605         self.synchro = threading.Event()
   1606         self.finish1 = threading.Event()
   1607         self.finish2 = threading.Event()
   1608 
   1609         th1 = threading.Thread(target=thfunc1, args=(self,))
   1610         th2 = threading.Thread(target=thfunc2, args=(self,))
   1611 
   1612         th1.start()
   1613         th2.start()
   1614 
   1615         self.finish1.wait()
   1616         self.finish2.wait()
   1617 
   1618         for sig in Signals[self.decimal]:
   1619             self.assertFalse(DefaultContext.flags[sig])
   1620 
   1621         th1.join()
   1622         th2.join()
   1623 
   1624         DefaultContext.prec = save_prec
   1625         DefaultContext.Emax = save_emax
   1626         DefaultContext.Emin = save_emin
   1627 
   1628 
   1629 class CThreadingTest(ThreadingTest):
   1630     decimal = C
   1631 
   1632 class PyThreadingTest(ThreadingTest):
   1633     decimal = P
   1634 
   1635 class UsabilityTest(unittest.TestCase):
   1636     '''Unit tests for Usability cases of Decimal.'''
   1637 
   1638     def test_comparison_operators(self):
   1639 
   1640         Decimal = self.decimal.Decimal
   1641 
   1642         da = Decimal('23.42')
   1643         db = Decimal('23.42')
   1644         dc = Decimal('45')
   1645 
   1646         #two Decimals
   1647         self.assertGreater(dc, da)
   1648         self.assertGreaterEqual(dc, da)
   1649         self.assertLess(da, dc)
   1650         self.assertLessEqual(da, dc)
   1651         self.assertEqual(da, db)
   1652         self.assertNotEqual(da, dc)
   1653         self.assertLessEqual(da, db)
   1654         self.assertGreaterEqual(da, db)
   1655 
   1656         #a Decimal and an int
   1657         self.assertGreater(dc, 23)
   1658         self.assertLess(23, dc)
   1659         self.assertEqual(dc, 45)
   1660 
   1661         #a Decimal and uncomparable
   1662         self.assertNotEqual(da, 'ugly')
   1663         self.assertNotEqual(da, 32.7)
   1664         self.assertNotEqual(da, object())
   1665         self.assertNotEqual(da, object)
   1666 
   1667         # sortable
   1668         a = list(map(Decimal, range(100)))
   1669         b =  a[:]
   1670         random.shuffle(a)
   1671         a.sort()
   1672         self.assertEqual(a, b)
   1673 
   1674     def test_decimal_float_comparison(self):
   1675         Decimal = self.decimal.Decimal
   1676 
   1677         da = Decimal('0.25')
   1678         db = Decimal('3.0')
   1679         self.assertLess(da, 3.0)
   1680         self.assertLessEqual(da, 3.0)
   1681         self.assertGreater(db, 0.25)
   1682         self.assertGreaterEqual(db, 0.25)
   1683         self.assertNotEqual(da, 1.5)
   1684         self.assertEqual(da, 0.25)
   1685         self.assertGreater(3.0, da)
   1686         self.assertGreaterEqual(3.0, da)
   1687         self.assertLess(0.25, db)
   1688         self.assertLessEqual(0.25, db)
   1689         self.assertNotEqual(0.25, db)
   1690         self.assertEqual(3.0, db)
   1691         self.assertNotEqual(0.1, Decimal('0.1'))
   1692 
   1693     def test_decimal_complex_comparison(self):
   1694         Decimal = self.decimal.Decimal
   1695 
   1696         da = Decimal('0.25')
   1697         db = Decimal('3.0')
   1698         self.assertNotEqual(da, (1.5+0j))
   1699         self.assertNotEqual((1.5+0j), da)
   1700         self.assertEqual(da, (0.25+0j))
   1701         self.assertEqual((0.25+0j), da)
   1702         self.assertEqual((3.0+0j), db)
   1703         self.assertEqual(db, (3.0+0j))
   1704 
   1705         self.assertNotEqual(db, (3.0+1j))
   1706         self.assertNotEqual((3.0+1j), db)
   1707 
   1708         self.assertIs(db.__lt__(3.0+0j), NotImplemented)
   1709         self.assertIs(db.__le__(3.0+0j), NotImplemented)
   1710         self.assertIs(db.__gt__(3.0+0j), NotImplemented)
   1711         self.assertIs(db.__le__(3.0+0j), NotImplemented)
   1712 
   1713     def test_decimal_fraction_comparison(self):
   1714         D = self.decimal.Decimal
   1715         F = fractions[self.decimal].Fraction
   1716         Context = self.decimal.Context
   1717         localcontext = self.decimal.localcontext
   1718         InvalidOperation = self.decimal.InvalidOperation
   1719 
   1720 
   1721         emax = C.MAX_EMAX if C else 999999999
   1722         emin = C.MIN_EMIN if C else -999999999
   1723         etiny = C.MIN_ETINY if C else -1999999997
   1724         c = Context(Emax=emax, Emin=emin)
   1725 
   1726         with localcontext(c):
   1727             c.prec = emax
   1728             self.assertLess(D(0), F(1,9999999999999999999999999999999999999))
   1729             self.assertLess(F(-1,9999999999999999999999999999999999999), D(0))
   1730             self.assertLess(F(0,1), D("1e" + str(etiny)))
   1731             self.assertLess(D("-1e" + str(etiny)), F(0,1))
   1732             self.assertLess(F(0,9999999999999999999999999), D("1e" + str(etiny)))
   1733             self.assertLess(D("-1e" + str(etiny)), F(0,9999999999999999999999999))
   1734 
   1735             self.assertEqual(D("0.1"), F(1,10))
   1736             self.assertEqual(F(1,10), D("0.1"))
   1737 
   1738             c.prec = 300
   1739             self.assertNotEqual(D(1)/3, F(1,3))
   1740             self.assertNotEqual(F(1,3), D(1)/3)
   1741 
   1742             self.assertLessEqual(F(120984237, 9999999999), D("9e" + str(emax)))
   1743             self.assertGreaterEqual(D("9e" + str(emax)), F(120984237, 9999999999))
   1744 
   1745             self.assertGreater(D('inf'), F(99999999999,123))
   1746             self.assertGreater(D('inf'), F(-99999999999,123))
   1747             self.assertLess(D('-inf'), F(99999999999,123))
   1748             self.assertLess(D('-inf'), F(-99999999999,123))
   1749 
   1750             self.assertRaises(InvalidOperation, D('nan').__gt__, F(-9,123))
   1751             self.assertIs(NotImplemented, F(-9,123).__lt__(D('nan')))
   1752             self.assertNotEqual(D('nan'), F(-9,123))
   1753             self.assertNotEqual(F(-9,123), D('nan'))
   1754 
   1755     def test_copy_and_deepcopy_methods(self):
   1756         Decimal = self.decimal.Decimal
   1757 
   1758         d = Decimal('43.24')
   1759         c = copy.copy(d)
   1760         self.assertEqual(id(c), id(d))
   1761         dc = copy.deepcopy(d)
   1762         self.assertEqual(id(dc), id(d))
   1763 
   1764     def test_hash_method(self):
   1765 
   1766         Decimal = self.decimal.Decimal
   1767         localcontext = self.decimal.localcontext
   1768 
   1769         def hashit(d):
   1770             a = hash(d)
   1771             b = d.__hash__()
   1772             self.assertEqual(a, b)
   1773             return a
   1774 
   1775         #just that it's hashable
   1776         hashit(Decimal(23))
   1777         hashit(Decimal('Infinity'))
   1778         hashit(Decimal('-Infinity'))
   1779         hashit(Decimal('nan123'))
   1780         hashit(Decimal('-NaN'))
   1781 
   1782         test_values = [Decimal(sign*(2**m + n))
   1783                        for m in [0, 14, 15, 16, 17, 30, 31,
   1784                                  32, 33, 61, 62, 63, 64, 65, 66]
   1785                        for n in range(-10, 10)
   1786                        for sign in [-1, 1]]
   1787         test_values.extend([
   1788                 Decimal("-1"), # ==> -2
   1789                 Decimal("-0"), # zeros
   1790                 Decimal("0.00"),
   1791                 Decimal("-0.000"),
   1792                 Decimal("0E10"),
   1793                 Decimal("-0E12"),
   1794                 Decimal("10.0"), # negative exponent
   1795                 Decimal("-23.00000"),
   1796                 Decimal("1230E100"), # positive exponent
   1797                 Decimal("-4.5678E50"),
   1798                 # a value for which hash(n) != hash(n % (2**64-1))
   1799                 # in Python pre-2.6
   1800                 Decimal(2**64 + 2**32 - 1),
   1801                 # selection of values which fail with the old (before
   1802                 # version 2.6) long.__hash__
   1803                 Decimal("1.634E100"),
   1804                 Decimal("90.697E100"),
   1805                 Decimal("188.83E100"),
   1806                 Decimal("1652.9E100"),
   1807                 Decimal("56531E100"),
   1808                 ])
   1809 
   1810         # check that hash(d) == hash(int(d)) for integral values
   1811         for value in test_values:
   1812             self.assertEqual(hashit(value), hashit(int(value)))
   1813 
   1814         #the same hash that to an int
   1815         self.assertEqual(hashit(Decimal(23)), hashit(23))
   1816         self.assertRaises(TypeError, hash, Decimal('sNaN'))
   1817         self.assertTrue(hashit(Decimal('Inf')))
   1818         self.assertTrue(hashit(Decimal('-Inf')))
   1819 
   1820         # check that the hashes of a Decimal float match when they
   1821         # represent exactly the same values
   1822         test_strings = ['inf', '-Inf', '0.0', '-.0e1',
   1823                         '34.0', '2.5', '112390.625', '-0.515625']
   1824         for s in test_strings:
   1825             f = float(s)
   1826             d = Decimal(s)
   1827             self.assertEqual(hashit(f), hashit(d))
   1828 
   1829         with localcontext() as c:
   1830             # check that the value of the hash doesn't depend on the
   1831             # current context (issue #1757)
   1832             x = Decimal("123456789.1")
   1833 
   1834             c.prec = 6
   1835             h1 = hashit(x)
   1836             c.prec = 10
   1837             h2 = hashit(x)
   1838             c.prec = 16
   1839             h3 = hashit(x)
   1840 
   1841             self.assertEqual(h1, h2)
   1842             self.assertEqual(h1, h3)
   1843 
   1844             c.prec = 10000
   1845             x = 1100 ** 1248
   1846             self.assertEqual(hashit(Decimal(x)), hashit(x))
   1847 
   1848     def test_min_and_max_methods(self):
   1849         Decimal = self.decimal.Decimal
   1850 
   1851         d1 = Decimal('15.32')
   1852         d2 = Decimal('28.5')
   1853         l1 = 15
   1854         l2 = 28
   1855 
   1856         #between Decimals
   1857         self.assertIs(min(d1,d2), d1)
   1858         self.assertIs(min(d2,d1), d1)
   1859         self.assertIs(max(d1,d2), d2)
   1860         self.assertIs(max(d2,d1), d2)
   1861 
   1862         #between Decimal and int
   1863         self.assertIs(min(d1,l2), d1)
   1864         self.assertIs(min(l2,d1), d1)
   1865         self.assertIs(max(l1,d2), d2)
   1866         self.assertIs(max(d2,l1), d2)
   1867 
   1868     def test_as_nonzero(self):
   1869         Decimal = self.decimal.Decimal
   1870 
   1871         #as false
   1872         self.assertFalse(Decimal(0))
   1873         #as true
   1874         self.assertTrue(Decimal('0.372'))
   1875 
   1876     def test_tostring_methods(self):
   1877         #Test str and repr methods.
   1878         Decimal = self.decimal.Decimal
   1879 
   1880         d = Decimal('15.32')
   1881         self.assertEqual(str(d), '15.32')               # str
   1882         self.assertEqual(repr(d), "Decimal('15.32')")   # repr
   1883 
   1884     def test_tonum_methods(self):
   1885         #Test float and int methods.
   1886         Decimal = self.decimal.Decimal
   1887 
   1888         d1 = Decimal('66')
   1889         d2 = Decimal('15.32')
   1890 
   1891         #int
   1892         self.assertEqual(int(d1), 66)
   1893         self.assertEqual(int(d2), 15)
   1894 
   1895         #float
   1896         self.assertEqual(float(d1), 66)
   1897         self.assertEqual(float(d2), 15.32)
   1898 
   1899         #floor
   1900         test_pairs = [
   1901             ('123.00', 123),
   1902             ('3.2', 3),
   1903             ('3.54', 3),
   1904             ('3.899', 3),
   1905             ('-2.3', -3),
   1906             ('-11.0', -11),
   1907             ('0.0', 0),
   1908             ('-0E3', 0),
   1909             ('89891211712379812736.1', 89891211712379812736),
   1910             ]
   1911         for d, i in test_pairs:
   1912             self.assertEqual(math.floor(Decimal(d)), i)
   1913         self.assertRaises(ValueError, math.floor, Decimal('-NaN'))
   1914         self.assertRaises(ValueError, math.floor, Decimal('sNaN'))
   1915         self.assertRaises(ValueError, math.floor, Decimal('NaN123'))
   1916         self.assertRaises(OverflowError, math.floor, Decimal('Inf'))
   1917         self.assertRaises(OverflowError, math.floor, Decimal('-Inf'))
   1918 
   1919         #ceiling
   1920         test_pairs = [
   1921             ('123.00', 123),
   1922             ('3.2', 4),
   1923             ('3.54', 4),
   1924             ('3.899', 4),
   1925             ('-2.3', -2),
   1926             ('-11.0', -11),
   1927             ('0.0', 0),
   1928             ('-0E3', 0),
   1929             ('89891211712379812736.1', 89891211712379812737),
   1930             ]
   1931         for d, i in test_pairs:
   1932             self.assertEqual(math.ceil(Decimal(d)), i)
   1933         self.assertRaises(ValueError, math.ceil, Decimal('-NaN'))
   1934         self.assertRaises(ValueError, math.ceil, Decimal('sNaN'))
   1935         self.assertRaises(ValueError, math.ceil, Decimal('NaN123'))
   1936         self.assertRaises(OverflowError, math.ceil, Decimal('Inf'))
   1937         self.assertRaises(OverflowError, math.ceil, Decimal('-Inf'))
   1938 
   1939         #round, single argument
   1940         test_pairs = [
   1941             ('123.00', 123),
   1942             ('3.2', 3),
   1943             ('3.54', 4),
   1944             ('3.899', 4),
   1945             ('-2.3', -2),
   1946             ('-11.0', -11),
   1947             ('0.0', 0),
   1948             ('-0E3', 0),
   1949             ('-3.5', -4),
   1950             ('-2.5', -2),
   1951             ('-1.5', -2),
   1952             ('-0.5', 0),
   1953             ('0.5', 0),
   1954             ('1.5', 2),
   1955             ('2.5', 2),
   1956             ('3.5', 4),
   1957             ]
   1958         for d, i in test_pairs:
   1959             self.assertEqual(round(Decimal(d)), i)
   1960         self.assertRaises(ValueError, round, Decimal('-NaN'))
   1961         self.assertRaises(ValueError, round, Decimal('sNaN'))
   1962         self.assertRaises(ValueError, round, Decimal('NaN123'))
   1963         self.assertRaises(OverflowError, round, Decimal('Inf'))
   1964         self.assertRaises(OverflowError, round, Decimal('-Inf'))
   1965 
   1966         #round, two arguments;  this is essentially equivalent
   1967         #to quantize, which is already extensively tested
   1968         test_triples = [
   1969             ('123.456', -4, '0E+4'),
   1970             ('123.456', -3, '0E+3'),
   1971             ('123.456', -2, '1E+2'),
   1972             ('123.456', -1, '1.2E+2'),
   1973             ('123.456', 0, '123'),
   1974             ('123.456', 1, '123.5'),
   1975             ('123.456', 2, '123.46'),
   1976             ('123.456', 3, '123.456'),
   1977             ('123.456', 4, '123.4560'),
   1978             ('123.455', 2, '123.46'),
   1979             ('123.445', 2, '123.44'),
   1980             ('Inf', 4, 'NaN'),
   1981             ('-Inf', -23, 'NaN'),
   1982             ('sNaN314', 3, 'NaN314'),
   1983             ]
   1984         for d, n, r in test_triples:
   1985             self.assertEqual(str(round(Decimal(d), n)), r)
   1986 
   1987     def test_nan_to_float(self):
   1988         # Test conversions of decimal NANs to float.
   1989         # See http://bugs.python.org/issue15544
   1990         Decimal = self.decimal.Decimal
   1991         for s in ('nan', 'nan1234', '-nan', '-nan2468'):
   1992             f = float(Decimal(s))
   1993             self.assertTrue(math.isnan(f))
   1994             sign = math.copysign(1.0, f)
   1995             self.assertEqual(sign, -1.0 if s.startswith('-') else 1.0)
   1996 
   1997     def test_snan_to_float(self):
   1998         Decimal = self.decimal.Decimal
   1999         for s in ('snan', '-snan', 'snan1357', '-snan1234'):
   2000             d = Decimal(s)
   2001             self.assertRaises(ValueError, float, d)
   2002 
   2003     def test_eval_round_trip(self):
   2004         Decimal = self.decimal.Decimal
   2005 
   2006         #with zero
   2007         d = Decimal( (0, (0,), 0) )
   2008         self.assertEqual(d, eval(repr(d)))
   2009 
   2010         #int
   2011         d = Decimal( (1, (4, 5), 0) )
   2012         self.assertEqual(d, eval(repr(d)))
   2013 
   2014         #float
   2015         d = Decimal( (0, (4, 5, 3, 4), -2) )
   2016         self.assertEqual(d, eval(repr(d)))
   2017 
   2018         #weird
   2019         d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
   2020         self.assertEqual(d, eval(repr(d)))
   2021 
   2022     def test_as_tuple(self):
   2023         Decimal = self.decimal.Decimal
   2024 
   2025         #with zero
   2026         d = Decimal(0)
   2027         self.assertEqual(d.as_tuple(), (0, (0,), 0) )
   2028 
   2029         #int
   2030         d = Decimal(-45)
   2031         self.assertEqual(d.as_tuple(), (1, (4, 5), 0) )
   2032 
   2033         #complicated string
   2034         d = Decimal("-4.34913534E-17")
   2035         self.assertEqual(d.as_tuple(), (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
   2036 
   2037         # The '0' coefficient is implementation specific to decimal.py.
   2038         # It has no meaning in the C-version and is ignored there.
   2039         d = Decimal("Infinity")
   2040         self.assertEqual(d.as_tuple(), (0, (0,), 'F') )
   2041 
   2042         #leading zeros in coefficient should be stripped
   2043         d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), -2) )
   2044         self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), -2) )
   2045         d = Decimal( (1, (0, 0, 0), 37) )
   2046         self.assertEqual(d.as_tuple(), (1, (0,), 37))
   2047         d = Decimal( (1, (), 37) )
   2048         self.assertEqual(d.as_tuple(), (1, (0,), 37))
   2049 
   2050         #leading zeros in NaN diagnostic info should be stripped
   2051         d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), 'n') )
   2052         self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), 'n') )
   2053         d = Decimal( (1, (0, 0, 0), 'N') )
   2054         self.assertEqual(d.as_tuple(), (1, (), 'N') )
   2055         d = Decimal( (1, (), 'n') )
   2056         self.assertEqual(d.as_tuple(), (1, (), 'n') )
   2057 
   2058         # For infinities, decimal.py has always silently accepted any
   2059         # coefficient tuple.
   2060         d = Decimal( (0, (0,), 'F') )
   2061         self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
   2062         d = Decimal( (0, (4, 5, 3, 4), 'F') )
   2063         self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
   2064         d = Decimal( (1, (0, 2, 7, 1), 'F') )
   2065         self.assertEqual(d.as_tuple(), (1, (0,), 'F'))
   2066 
   2067     def test_as_integer_ratio(self):
   2068         Decimal = self.decimal.Decimal
   2069 
   2070         # exceptional cases
   2071         self.assertRaises(OverflowError,
   2072                           Decimal.as_integer_ratio, Decimal('inf'))
   2073         self.assertRaises(OverflowError,
   2074                           Decimal.as_integer_ratio, Decimal('-inf'))
   2075         self.assertRaises(ValueError,
   2076                           Decimal.as_integer_ratio, Decimal('-nan'))
   2077         self.assertRaises(ValueError,
   2078                           Decimal.as_integer_ratio, Decimal('snan123'))
   2079 
   2080         for exp in range(-4, 2):
   2081             for coeff in range(1000):
   2082                 for sign in '+', '-':
   2083                     d = Decimal('%s%dE%d' % (sign, coeff, exp))
   2084                     pq = d.as_integer_ratio()
   2085                     p, q = pq
   2086 
   2087                     # check return type
   2088                     self.assertIsInstance(pq, tuple)
   2089                     self.assertIsInstance(p, int)
   2090                     self.assertIsInstance(q, int)
   2091 
   2092                     # check normalization:  q should be positive;
   2093                     # p should be relatively prime to q.
   2094                     self.assertGreater(q, 0)
   2095                     self.assertEqual(math.gcd(p, q), 1)
   2096 
   2097                     # check that p/q actually gives the correct value
   2098                     self.assertEqual(Decimal(p) / Decimal(q), d)
   2099 
   2100     def test_subclassing(self):
   2101         # Different behaviours when subclassing Decimal
   2102         Decimal = self.decimal.Decimal
   2103 
   2104         class MyDecimal(Decimal):
   2105             y = None
   2106 
   2107         d1 = MyDecimal(1)
   2108         d2 = MyDecimal(2)
   2109         d = d1 + d2
   2110         self.assertIs(type(d), Decimal)
   2111 
   2112         d = d1.max(d2)
   2113         self.assertIs(type(d), Decimal)
   2114 
   2115         d = copy.copy(d1)
   2116         self.assertIs(type(d), MyDecimal)
   2117         self.assertEqual(d, d1)
   2118 
   2119         d = copy.deepcopy(d1)
   2120         self.assertIs(type(d), MyDecimal)
   2121         self.assertEqual(d, d1)
   2122 
   2123         # Decimal(Decimal)
   2124         d = Decimal('1.0')
   2125         x = Decimal(d)
   2126         self.assertIs(type(x), Decimal)
   2127         self.assertEqual(x, d)
   2128 
   2129         # MyDecimal(Decimal)
   2130         m = MyDecimal(d)
   2131         self.assertIs(type(m), MyDecimal)
   2132         self.assertEqual(m, d)
   2133         self.assertIs(m.y, None)
   2134 
   2135         # Decimal(MyDecimal)
   2136         x = Decimal(m)
   2137         self.assertIs(type(x), Decimal)
   2138         self.assertEqual(x, d)
   2139 
   2140         # MyDecimal(MyDecimal)
   2141         m.y = 9
   2142         x = MyDecimal(m)
   2143         self.assertIs(type(x), MyDecimal)
   2144         self.assertEqual(x, d)
   2145         self.assertIs(x.y, None)
   2146 
   2147     def test_implicit_context(self):
   2148         Decimal = self.decimal.Decimal
   2149         getcontext = self.decimal.getcontext
   2150 
   2151         # Check results when context given implicitly.  (Issue 2478)
   2152         c = getcontext()
   2153         self.assertEqual(str(Decimal(0).sqrt()),
   2154                          str(c.sqrt(Decimal(0))))
   2155 
   2156     def test_none_args(self):
   2157         Decimal = self.decimal.Decimal
   2158         Context = self.decimal.Context
   2159         localcontext = self.decimal.localcontext
   2160         InvalidOperation = self.decimal.InvalidOperation
   2161         DivisionByZero = self.decimal.DivisionByZero
   2162         Overflow = self.decimal.Overflow
   2163         Underflow = self.decimal.Underflow
   2164         Subnormal = self.decimal.Subnormal
   2165         Inexact = self.decimal.Inexact
   2166         Rounded = self.decimal.Rounded
   2167         Clamped = self.decimal.Clamped
   2168 
   2169         with localcontext(Context()) as c:
   2170             c.prec = 7
   2171             c.Emax = 999
   2172             c.Emin = -999
   2173 
   2174             x = Decimal("111")
   2175             y = Decimal("1e9999")
   2176             z = Decimal("1e-9999")
   2177 
   2178             ##### Unary functions
   2179             c.clear_flags()
   2180             self.assertEqual(str(x.exp(context=None)), '1.609487E+48')
   2181             self.assertTrue(c.flags[Inexact])
   2182             self.assertTrue(c.flags[Rounded])
   2183             c.clear_flags()
   2184             self.assertRaises(Overflow, y.exp, context=None)
   2185             self.assertTrue(c.flags[Overflow])
   2186 
   2187             self.assertIs(z.is_normal(context=None), False)
   2188             self.assertIs(z.is_subnormal(context=None), True)
   2189 
   2190             c.clear_flags()
   2191             self.assertEqual(str(x.ln(context=None)), '4.709530')
   2192             self.assertTrue(c.flags[Inexact])
   2193             self.assertTrue(c.flags[Rounded])
   2194             c.clear_flags()
   2195             self.assertRaises(InvalidOperation, Decimal(-1).ln, context=None)
   2196             self.assertTrue(c.flags[InvalidOperation])
   2197 
   2198             c.clear_flags()
   2199             self.assertEqual(str(x.log10(context=None)), '2.045323')
   2200             self.assertTrue(c.flags[Inexact])
   2201             self.assertTrue(c.flags[Rounded])
   2202             c.clear_flags()
   2203             self.assertRaises(InvalidOperation, Decimal(-1).log10, context=None)
   2204             self.assertTrue(c.flags[InvalidOperation])
   2205 
   2206             c.clear_flags()
   2207             self.assertEqual(str(x.logb(context=None)), '2')
   2208             self.assertRaises(DivisionByZero, Decimal(0).logb, context=None)
   2209             self.assertTrue(c.flags[DivisionByZero])
   2210 
   2211             c.clear_flags()
   2212             self.assertEqual(str(x.logical_invert(context=None)), '1111000')
   2213             self.assertRaises(InvalidOperation, y.logical_invert, context=None)
   2214             self.assertTrue(c.flags[InvalidOperation])
   2215 
   2216             c.clear_flags()
   2217             self.assertEqual(str(y.next_minus(context=None)), '9.999999E+999')
   2218             self.assertRaises(InvalidOperation, Decimal('sNaN').next_minus, context=None)
   2219             self.assertTrue(c.flags[InvalidOperation])
   2220 
   2221             c.clear_flags()
   2222             self.assertEqual(str(y.next_plus(context=None)), 'Infinity')
   2223             self.assertRaises(InvalidOperation, Decimal('sNaN').next_plus, context=None)
   2224             self.assertTrue(c.flags[InvalidOperation])
   2225 
   2226             c.clear_flags()
   2227             self.assertEqual(str(z.normalize(context=None)), '0')
   2228             self.assertRaises(Overflow, y.normalize, context=None)
   2229             self.assertTrue(c.flags[Overflow])
   2230 
   2231             self.assertEqual(str(z.number_class(context=None)), '+Subnormal')
   2232 
   2233             c.clear_flags()
   2234             self.assertEqual(str(z.sqrt(context=None)), '0E-1005')
   2235             self.assertTrue(c.flags[Clamped])
   2236             self.assertTrue(c.flags[Inexact])
   2237             self.assertTrue(c.flags[Rounded])
   2238             self.assertTrue(c.flags[Subnormal])
   2239             self.assertTrue(c.flags[Underflow])
   2240             c.clear_flags()
   2241             self.assertRaises(Overflow, y.sqrt, context=None)
   2242             self.assertTrue(c.flags[Overflow])
   2243 
   2244             c.capitals = 0
   2245             self.assertEqual(str(z.to_eng_string(context=None)), '1e-9999')
   2246             c.capitals = 1
   2247 
   2248 
   2249             ##### Binary functions
   2250             c.clear_flags()
   2251             ans = str(x.compare(Decimal('Nan891287828'), context=None))
   2252             self.assertEqual(ans, 'NaN1287828')
   2253             self.assertRaises(InvalidOperation, x.compare, Decimal('sNaN'), context=None)
   2254             self.assertTrue(c.flags[InvalidOperation])
   2255 
   2256             c.clear_flags()
   2257             ans = str(x.compare_signal(8224, context=None))
   2258             self.assertEqual(ans, '-1')
   2259             self.assertRaises(InvalidOperation, x.compare_signal, Decimal('NaN'), context=None)
   2260             self.assertTrue(c.flags[InvalidOperation])
   2261 
   2262             c.clear_flags()
   2263             ans = str(x.logical_and(101, context=None))
   2264             self.assertEqual(ans, '101')
   2265             self.assertRaises(InvalidOperation, x.logical_and, 123, context=None)
   2266             self.assertTrue(c.flags[InvalidOperation])
   2267 
   2268             c.clear_flags()
   2269             ans = str(x.logical_or(101, context=None))
   2270             self.assertEqual(ans, '111')
   2271             self.assertRaises(InvalidOperation, x.logical_or, 123, context=None)
   2272             self.assertTrue(c.flags[InvalidOperation])
   2273 
   2274             c.clear_flags()
   2275             ans = str(x.logical_xor(101, context=None))
   2276             self.assertEqual(ans, '10')
   2277             self.assertRaises(InvalidOperation, x.logical_xor, 123, context=None)
   2278             self.assertTrue(c.flags[InvalidOperation])
   2279 
   2280             c.clear_flags()
   2281             ans = str(x.max(101, context=None))
   2282             self.assertEqual(ans, '111')
   2283             self.assertRaises(InvalidOperation, x.max, Decimal('sNaN'), context=None)
   2284             self.assertTrue(c.flags[InvalidOperation])
   2285 
   2286             c.clear_flags()
   2287             ans = str(x.max_mag(101, context=None))
   2288             self.assertEqual(ans, '111')
   2289             self.assertRaises(InvalidOperation, x.max_mag, Decimal('sNaN'), context=None)
   2290             self.assertTrue(c.flags[InvalidOperation])
   2291 
   2292             c.clear_flags()
   2293             ans = str(x.min(101, context=None))
   2294             self.assertEqual(ans, '101')
   2295             self.assertRaises(InvalidOperation, x.min, Decimal('sNaN'), context=None)
   2296             self.assertTrue(c.flags[InvalidOperation])
   2297 
   2298             c.clear_flags()
   2299             ans = str(x.min_mag(101, context=None))
   2300             self.assertEqual(ans, '101')
   2301             self.assertRaises(InvalidOperation, x.min_mag, Decimal('sNaN'), context=None)
   2302             self.assertTrue(c.flags[InvalidOperation])
   2303 
   2304             c.clear_flags()
   2305             ans = str(x.remainder_near(101, context=None))
   2306             self.assertEqual(ans, '10')
   2307             self.assertRaises(InvalidOperation, y.remainder_near, 101, context=None)
   2308             self.assertTrue(c.flags[InvalidOperation])
   2309 
   2310             c.clear_flags()
   2311             ans = str(x.rotate(2, context=None))
   2312             self.assertEqual(ans, '11100')
   2313             self.assertRaises(InvalidOperation, x.rotate, 101, context=None)
   2314             self.assertTrue(c.flags[InvalidOperation])
   2315 
   2316             c.clear_flags()
   2317             ans = str(x.scaleb(7, context=None))
   2318             self.assertEqual(ans, '1.11E+9')
   2319             self.assertRaises(InvalidOperation, x.scaleb, 10000, context=None)
   2320             self.assertTrue(c.flags[InvalidOperation])
   2321 
   2322             c.clear_flags()
   2323             ans = str(x.shift(2, context=None))
   2324             self.assertEqual(ans, '11100')
   2325             self.assertRaises(InvalidOperation, x.shift, 10000, context=None)
   2326             self.assertTrue(c.flags[InvalidOperation])
   2327 
   2328 
   2329             ##### Ternary functions
   2330             c.clear_flags()
   2331             ans = str(x.fma(2, 3, context=None))
   2332             self.assertEqual(ans, '225')
   2333             self.assertRaises(Overflow, x.fma, Decimal('1e9999'), 3, context=None)
   2334             self.assertTrue(c.flags[Overflow])
   2335 
   2336 
   2337             ##### Special cases
   2338             c.rounding = ROUND_HALF_EVEN
   2339             ans = str(Decimal('1.5').to_integral(rounding=None, context=None))
   2340             self.assertEqual(ans, '2')
   2341             c.rounding = ROUND_DOWN
   2342             ans = str(Decimal('1.5').to_integral(rounding=None, context=None))
   2343             self.assertEqual(ans, '1')
   2344             ans = str(Decimal('1.5').to_integral(rounding=ROUND_UP, context=None))
   2345             self.assertEqual(ans, '2')
   2346             c.clear_flags()
   2347             self.assertRaises(InvalidOperation, Decimal('sNaN').to_integral, context=None)
   2348             self.assertTrue(c.flags[InvalidOperation])
   2349 
   2350             c.rounding = ROUND_HALF_EVEN
   2351             ans = str(Decimal('1.5').to_integral_value(rounding=None, context=None))
   2352             self.assertEqual(ans, '2')
   2353             c.rounding = ROUND_DOWN
   2354             ans = str(Decimal('1.5').to_integral_value(rounding=None, context=None))
   2355             self.assertEqual(ans, '1')
   2356             ans = str(Decimal('1.5').to_integral_value(rounding=ROUND_UP, context=None))
   2357             self.assertEqual(ans, '2')
   2358             c.clear_flags()
   2359             self.assertRaises(InvalidOperation, Decimal('sNaN').to_integral_value, context=None)
   2360             self.assertTrue(c.flags[InvalidOperation])
   2361 
   2362             c.rounding = ROUND_HALF_EVEN
   2363             ans = str(Decimal('1.5').to_integral_exact(rounding=None, context=None))
   2364             self.assertEqual(ans, '2')
   2365             c.rounding = ROUND_DOWN
   2366             ans = str(Decimal('1.5').to_integral_exact(rounding=None, context=None))
   2367             self.assertEqual(ans, '1')
   2368             ans = str(Decimal('1.5').to_integral_exact(rounding=ROUND_UP, context=None))
   2369             self.assertEqual(ans, '2')
   2370             c.clear_flags()
   2371             self.assertRaises(InvalidOperation, Decimal('sNaN').to_integral_exact, context=None)
   2372             self.assertTrue(c.flags[InvalidOperation])
   2373 
   2374             c.rounding = ROUND_UP
   2375             ans = str(Decimal('1.50001').quantize(exp=Decimal('1e-3'), rounding=None, context=None))
   2376             self.assertEqual(ans, '1.501')
   2377             c.rounding = ROUND_DOWN
   2378             ans = str(Decimal('1.50001').quantize(exp=Decimal('1e-3'), rounding=None, context=None))
   2379             self.assertEqual(ans, '1.500')
   2380             ans = str(Decimal('1.50001').quantize(exp=Decimal('1e-3'), rounding=ROUND_UP, context=None))
   2381             self.assertEqual(ans, '1.501')
   2382             c.clear_flags()
   2383             self.assertRaises(InvalidOperation, y.quantize, Decimal('1e-10'), rounding=ROUND_UP, context=None)
   2384             self.assertTrue(c.flags[InvalidOperation])
   2385 
   2386         with localcontext(Context()) as context:
   2387             context.prec = 7
   2388             context.Emax = 999
   2389             context.Emin = -999
   2390             with localcontext(ctx=None) as c:
   2391                 self.assertEqual(c.prec, 7)
   2392                 self.assertEqual(c.Emax, 999)
   2393                 self.assertEqual(c.Emin, -999)
   2394 
   2395     def test_conversions_from_int(self):
   2396         # Check that methods taking a second Decimal argument will
   2397         # always accept an integer in place of a Decimal.
   2398         Decimal = self.decimal.Decimal
   2399 
   2400         self.assertEqual(Decimal(4).compare(3),
   2401                          Decimal(4).compare(Decimal(3)))
   2402         self.assertEqual(Decimal(4).compare_signal(3),
   2403                          Decimal(4).compare_signal(Decimal(3)))
   2404         self.assertEqual(Decimal(4).compare_total(3),
   2405                          Decimal(4).compare_total(Decimal(3)))
   2406         self.assertEqual(Decimal(4).compare_total_mag(3),
   2407                          Decimal(4).compare_total_mag(Decimal(3)))
   2408         self.assertEqual(Decimal(10101).logical_and(1001),
   2409                          Decimal(10101).logical_and(Decimal(1001)))
   2410         self.assertEqual(Decimal(10101).logical_or(1001),
   2411                          Decimal(10101).logical_or(Decimal(1001)))
   2412         self.assertEqual(Decimal(10101).logical_xor(1001),
   2413                          Decimal(10101).logical_xor(Decimal(1001)))
   2414         self.assertEqual(Decimal(567).max(123),
   2415                          Decimal(567).max(Decimal(123)))
   2416         self.assertEqual(Decimal(567).max_mag(123),
   2417                          Decimal(567).max_mag(Decimal(123)))
   2418         self.assertEqual(Decimal(567).min(123),
   2419                          Decimal(567).min(Decimal(123)))
   2420         self.assertEqual(Decimal(567).min_mag(123),
   2421                          Decimal(567).min_mag(Decimal(123)))
   2422         self.assertEqual(Decimal(567).next_toward(123),
   2423                          Decimal(567).next_toward(Decimal(123)))
   2424         self.assertEqual(Decimal(1234).quantize(100),
   2425                          Decimal(1234).quantize(Decimal(100)))
   2426         self.assertEqual(Decimal(768).remainder_near(1234),
   2427                          Decimal(768).remainder_near(Decimal(1234)))
   2428         self.assertEqual(Decimal(123).rotate(1),
   2429                          Decimal(123).rotate(Decimal(1)))
   2430         self.assertEqual(Decimal(1234).same_quantum(1000),
   2431                          Decimal(1234).same_quantum(Decimal(1000)))
   2432         self.assertEqual(Decimal('9.123').scaleb(-100),
   2433                          Decimal('9.123').scaleb(Decimal(-100)))
   2434         self.assertEqual(Decimal(456).shift(-1),
   2435                          Decimal(456).shift(Decimal(-1)))
   2436 
   2437         self.assertEqual(Decimal(-12).fma(Decimal(45), 67),
   2438                          Decimal(-12).fma(Decimal(45), Decimal(67)))
   2439         self.assertEqual(Decimal(-12).fma(45, 67),
   2440                          Decimal(-12).fma(Decimal(45), Decimal(67)))
   2441         self.assertEqual(Decimal(-12).fma(45, Decimal(67)),
   2442                          Decimal(-12).fma(Decimal(45), Decimal(67)))
   2443 
   2444 class CUsabilityTest(UsabilityTest):
   2445     decimal = C
   2446 class PyUsabilityTest(UsabilityTest):
   2447     decimal = P
   2448 
   2449 class PythonAPItests(unittest.TestCase):
   2450 
   2451     def test_abc(self):
   2452         Decimal = self.decimal.Decimal
   2453 
   2454         self.assertTrue(issubclass(Decimal, numbers.Number))
   2455         self.assertFalse(issubclass(Decimal, numbers.Real))
   2456         self.assertIsInstance(Decimal(0), numbers.Number)
   2457         self.assertNotIsInstance(Decimal(0), numbers.Real)
   2458 
   2459     def test_pickle(self):
   2460         for proto in range(pickle.HIGHEST_PROTOCOL + 1):
   2461             Decimal = self.decimal.Decimal
   2462 
   2463             savedecimal = sys.modules['decimal']
   2464 
   2465             # Round trip
   2466             sys.modules['decimal'] = self.decimal
   2467             d = Decimal('-3.141590000')
   2468             p = pickle.dumps(d, proto)
   2469             e = pickle.loads(p)
   2470             self.assertEqual(d, e)
   2471 
   2472             if C:
   2473                 # Test interchangeability
   2474                 x = C.Decimal('-3.123e81723')
   2475                 y = P.Decimal('-3.123e81723')
   2476 
   2477                 sys.modules['decimal'] = C
   2478                 sx = pickle.dumps(x, proto)
   2479                 sys.modules['decimal'] = P
   2480                 r = pickle.loads(sx)
   2481                 self.assertIsInstance(r, P.Decimal)
   2482                 self.assertEqual(r, y)
   2483 
   2484                 sys.modules['decimal'] = P
   2485                 sy = pickle.dumps(y, proto)
   2486                 sys.modules['decimal'] = C
   2487                 r = pickle.loads(sy)
   2488                 self.assertIsInstance(r, C.Decimal)
   2489                 self.assertEqual(r, x)
   2490 
   2491                 x = C.Decimal('-3.123e81723').as_tuple()
   2492                 y = P.Decimal('-3.123e81723').as_tuple()
   2493 
   2494                 sys.modules['decimal'] = C
   2495                 sx = pickle.dumps(x, proto)
   2496                 sys.modules['decimal'] = P
   2497                 r = pickle.loads(sx)
   2498                 self.assertIsInstance(r, P.DecimalTuple)
   2499                 self.assertEqual(r, y)
   2500 
   2501                 sys.modules['decimal'] = P
   2502                 sy = pickle.dumps(y, proto)
   2503                 sys.modules['decimal'] = C
   2504                 r = pickle.loads(sy)
   2505                 self.assertIsInstance(r, C.DecimalTuple)
   2506                 self.assertEqual(r, x)
   2507 
   2508             sys.modules['decimal'] = savedecimal
   2509 
   2510     def test_int(self):
   2511         Decimal = self.decimal.Decimal
   2512 
   2513         for x in range(-250, 250):
   2514             s = '%0.2f' % (x / 100.0)
   2515             # should work the same as for floats
   2516             self.assertEqual(int(Decimal(s)), int(float(s)))
   2517             # should work the same as to_integral in the ROUND_DOWN mode
   2518             d = Decimal(s)
   2519             r = d.to_integral(ROUND_DOWN)
   2520             self.assertEqual(Decimal(int(d)), r)
   2521 
   2522         self.assertRaises(ValueError, int, Decimal('-nan'))
   2523         self.assertRaises(ValueError, int, Decimal('snan'))
   2524         self.assertRaises(OverflowError, int, Decimal('inf'))
   2525         self.assertRaises(OverflowError, int, Decimal('-inf'))
   2526 
   2527     def test_trunc(self):
   2528         Decimal = self.decimal.Decimal
   2529 
   2530         for x in range(-250, 250):
   2531             s = '%0.2f' % (x / 100.0)
   2532             # should work the same as for floats
   2533             self.assertEqual(int(Decimal(s)), int(float(s)))
   2534             # should work the same as to_integral in the ROUND_DOWN mode
   2535             d = Decimal(s)
   2536             r = d.to_integral(ROUND_DOWN)
   2537             self.assertEqual(Decimal(math.trunc(d)), r)
   2538 
   2539     def test_from_float(self):
   2540 
   2541         Decimal = self.decimal.Decimal
   2542 
   2543         class MyDecimal(Decimal):
   2544             def __init__(self, _):
   2545                 self.x = 'y'
   2546 
   2547         self.assertTrue(issubclass(MyDecimal, Decimal))
   2548 
   2549         r = MyDecimal.from_float(0.1)
   2550         self.assertEqual(type(r), MyDecimal)
   2551         self.assertEqual(str(r),
   2552                 '0.1000000000000000055511151231257827021181583404541015625')
   2553         self.assertEqual(r.x, 'y')
   2554 
   2555         bigint = 12345678901234567890123456789
   2556         self.assertEqual(MyDecimal.from_float(bigint), MyDecimal(bigint))
   2557         self.assertTrue(MyDecimal.from_float(float('nan')).is_qnan())
   2558         self.assertTrue(MyDecimal.from_float(float('inf')).is_infinite())
   2559         self.assertTrue(MyDecimal.from_float(float('-inf')).is_infinite())
   2560         self.assertEqual(str(MyDecimal.from_float(float('nan'))),
   2561                          str(Decimal('NaN')))
   2562         self.assertEqual(str(MyDecimal.from_float(float('inf'))),
   2563                          str(Decimal('Infinity')))
   2564         self.assertEqual(str(MyDecimal.from_float(float('-inf'))),
   2565                          str(Decimal('-Infinity')))
   2566         self.assertRaises(TypeError, MyDecimal.from_float, 'abc')
   2567         for i in range(200):
   2568             x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
   2569             self.assertEqual(x, float(MyDecimal.from_float(x))) # roundtrip
   2570 
   2571     def test_create_decimal_from_float(self):
   2572         Decimal = self.decimal.Decimal
   2573         Context = self.decimal.Context
   2574         Inexact = self.decimal.Inexact
   2575 
   2576         context = Context(prec=5, rounding=ROUND_DOWN)
   2577         self.assertEqual(
   2578             context.create_decimal_from_float(math.pi),
   2579             Decimal('3.1415')
   2580         )
   2581         context = Context(prec=5, rounding=ROUND_UP)
   2582         self.assertEqual(
   2583             context.create_decimal_from_float(math.pi),
   2584             Decimal('3.1416')
   2585         )
   2586         context = Context(prec=5, traps=[Inexact])
   2587         self.assertRaises(
   2588             Inexact,
   2589             context.create_decimal_from_float,
   2590             math.pi
   2591         )
   2592         self.assertEqual(repr(context.create_decimal_from_float(-0.0)),
   2593                          "Decimal('-0')")
   2594         self.assertEqual(repr(context.create_decimal_from_float(1.0)),
   2595                          "Decimal('1')")
   2596         self.assertEqual(repr(context.create_decimal_from_float(10)),
   2597                          "Decimal('10')")
   2598 
   2599     def test_quantize(self):
   2600         Decimal = self.decimal.Decimal
   2601         Context = self.decimal.Context
   2602         InvalidOperation = self.decimal.InvalidOperation
   2603 
   2604         c = Context(Emax=99999, Emin=-99999)
   2605         self.assertEqual(
   2606             Decimal('7.335').quantize(Decimal('.01')),
   2607             Decimal('7.34')
   2608         )
   2609         self.assertEqual(
   2610             Decimal('7.335').quantize(Decimal('.01'), rounding=ROUND_DOWN),
   2611             Decimal('7.33')
   2612         )
   2613         self.assertRaises(
   2614             InvalidOperation,
   2615             Decimal("10e99999").quantize, Decimal('1e100000'), context=c
   2616         )
   2617 
   2618         c = Context()
   2619         d = Decimal("0.871831e800")
   2620         x = d.quantize(context=c, exp=Decimal("1e797"), rounding=ROUND_DOWN)
   2621         self.assertEqual(x, Decimal('8.71E+799'))
   2622 
   2623     def test_complex(self):
   2624         Decimal = self.decimal.Decimal
   2625 
   2626         x = Decimal("9.8182731e181273")
   2627         self.assertEqual(x.real, x)
   2628         self.assertEqual(x.imag, 0)
   2629         self.assertEqual(x.conjugate(), x)
   2630 
   2631         x = Decimal("1")
   2632         self.assertEqual(complex(x), complex(float(1)))
   2633 
   2634         self.assertRaises(AttributeError, setattr, x, 'real', 100)
   2635         self.assertRaises(AttributeError, setattr, x, 'imag', 100)
   2636         self.assertRaises(AttributeError, setattr, x, 'conjugate', 100)
   2637         self.assertRaises(AttributeError, setattr, x, '__complex__', 100)
   2638 
   2639     def test_named_parameters(self):
   2640         D = self.decimal.Decimal
   2641         Context = self.decimal.Context
   2642         localcontext = self.decimal.localcontext
   2643         InvalidOperation = self.decimal.InvalidOperation
   2644         Overflow = self.decimal.Overflow
   2645 
   2646         xc = Context()
   2647         xc.prec = 1
   2648         xc.Emax = 1
   2649         xc.Emin = -1
   2650 
   2651         with localcontext() as c:
   2652             c.clear_flags()
   2653 
   2654             self.assertEqual(D(9, xc), 9)
   2655             self.assertEqual(D(9, context=xc), 9)
   2656             self.assertEqual(D(context=xc, value=9), 9)
   2657             self.assertEqual(D(context=xc), 0)
   2658             xc.clear_flags()
   2659             self.assertRaises(InvalidOperation, D, "xyz", context=xc)
   2660             self.assertTrue(xc.flags[InvalidOperation])
   2661             self.assertFalse(c.flags[InvalidOperation])
   2662 
   2663             xc.clear_flags()
   2664             self.assertEqual(D(2).exp(context=xc), 7)
   2665             self.assertRaises(Overflow, D(8).exp, context=xc)
   2666             self.assertTrue(xc.flags[Overflow])
   2667             self.assertFalse(c.flags[Overflow])
   2668 
   2669             xc.clear_flags()
   2670             self.assertEqual(D(2).ln(context=xc), D('0.7'))
   2671             self.assertRaises(InvalidOperation, D(-1).ln, context=xc)
   2672             self.assertTrue(xc.flags[InvalidOperation])
   2673             self.assertFalse(c.flags[InvalidOperation])
   2674 
   2675             self.assertEqual(D(0).log10(context=xc), D('-inf'))
   2676             self.assertEqual(D(-1).next_minus(context=xc), -2)
   2677             self.assertEqual(D(-1).next_plus(context=xc), D('-0.9'))
   2678             self.assertEqual(D("9.73").normalize(context=xc), D('1E+1'))
   2679             self.assertEqual(D("9999").to_integral(context=xc), 9999)
   2680             self.assertEqual(D("-2000").to_integral_exact(context=xc), -2000)
   2681             self.assertEqual(D("123").to_integral_value(context=xc), 123)
   2682             self.assertEqual(D("0.0625").sqrt(context=xc), D('0.2'))
   2683 
   2684             self.assertEqual(D("0.0625").compare(context=xc, other=3), -1)
   2685             xc.clear_flags()
   2686             self.assertRaises(InvalidOperation,
   2687                               D("0").compare_signal, D('nan'), context=xc)
   2688             self.assertTrue(xc.flags[InvalidOperation])
   2689             self.assertFalse(c.flags[InvalidOperation])
   2690             self.assertEqual(D("0.01").max(D('0.0101'), context=xc), D('0.0'))
   2691             self.assertEqual(D("0.01").max(D('0.0101'), context=xc), D('0.0'))
   2692             self.assertEqual(D("0.2").max_mag(D('-0.3'), context=xc),
   2693                              D('-0.3'))
   2694             self.assertEqual(D("0.02").min(D('-0.03'), context=xc), D('-0.0'))
   2695             self.assertEqual(D("0.02").min_mag(D('-0.03'), context=xc),
   2696                              D('0.0'))
   2697             self.assertEqual(D("0.2").next_toward(D('-1'), context=xc), D('0.1'))
   2698             xc.clear_flags()
   2699             self.assertRaises(InvalidOperation,
   2700                               D("0.2").quantize, D('1e10'), context=xc)
   2701             self.assertTrue(xc.flags[InvalidOperation])
   2702             self.assertFalse(c.flags[InvalidOperation])
   2703             self.assertEqual(D("9.99").remainder_near(D('1.5'), context=xc),
   2704                              D('-0.5'))
   2705 
   2706             self.assertEqual(D("9.9").fma(third=D('0.9'), context=xc, other=7),
   2707                              D('7E+1'))
   2708 
   2709             self.assertRaises(TypeError, D(1).is_canonical, context=xc)
   2710             self.assertRaises(TypeError, D(1).is_finite, context=xc)
   2711             self.assertRaises(TypeError, D(1).is_infinite, context=xc)
   2712             self.assertRaises(TypeError, D(1).is_nan, context=xc)
   2713             self.assertRaises(TypeError, D(1).is_qnan, context=xc)
   2714             self.assertRaises(TypeError, D(1).is_snan, context=xc)
   2715             self.assertRaises(TypeError, D(1).is_signed, context=xc)
   2716             self.assertRaises(TypeError, D(1).is_zero, context=xc)
   2717 
   2718             self.assertFalse(D("0.01").is_normal(context=xc))
   2719             self.assertTrue(D("0.01").is_subnormal(context=xc))
   2720 
   2721             self.assertRaises(TypeError, D(1).adjusted, context=xc)
   2722             self.assertRaises(TypeError, D(1).conjugate, context=xc)
   2723             self.assertRaises(TypeError, D(1).radix, context=xc)
   2724 
   2725             self.assertEqual(D(-111).logb(context=xc), 2)
   2726             self.assertEqual(D(0).logical_invert(context=xc), 1)
   2727             self.assertEqual(D('0.01').number_class(context=xc), '+Subnormal')
   2728             self.assertEqual(D('0.21').to_eng_string(context=xc), '0.21')
   2729 
   2730             self.assertEqual(D('11').logical_and(D('10'), context=xc), 0)
   2731             self.assertEqual(D('11').logical_or(D('10'), context=xc), 1)
   2732             self.assertEqual(D('01').logical_xor(D('10'), context=xc), 1)
   2733             self.assertEqual(D('23').rotate(1, context=xc), 3)
   2734             self.assertEqual(D('23').rotate(1, context=xc), 3)
   2735             xc.clear_flags()
   2736             self.assertRaises(Overflow,
   2737                               D('23').scaleb, 1, context=xc)
   2738             self.assertTrue(xc.flags[Overflow])
   2739             self.assertFalse(c.flags[Overflow])
   2740             self.assertEqual(D('23').shift(-1, context=xc), 0)
   2741 
   2742             self.assertRaises(TypeError, D.from_float, 1.1, context=xc)
   2743             self.assertRaises(TypeError, D(0).as_tuple, context=xc)
   2744 
   2745             self.assertEqual(D(1).canonical(), 1)
   2746             self.assertRaises(TypeError, D("-1").copy_abs, context=xc)
   2747             self.assertRaises(TypeError, D("-1").copy_negate, context=xc)
   2748             self.assertRaises(TypeError, D(1).canonical, context="x")
   2749             self.assertRaises(TypeError, D(1).canonical, xyz="x")
   2750 
   2751     def test_exception_hierarchy(self):
   2752 
   2753         decimal = self.decimal
   2754         DecimalException = decimal.DecimalException
   2755         InvalidOperation = decimal.InvalidOperation
   2756         FloatOperation = decimal.FloatOperation
   2757         DivisionByZero = decimal.DivisionByZero
   2758         Overflow = decimal.Overflow
   2759         Underflow = decimal.Underflow
   2760         Subnormal = decimal.Subnormal
   2761         Inexact = decimal.Inexact
   2762         Rounded = decimal.Rounded
   2763         Clamped = decimal.Clamped
   2764 
   2765         self.assertTrue(issubclass(DecimalException, ArithmeticError))
   2766 
   2767         self.assertTrue(issubclass(InvalidOperation, DecimalException))
   2768         self.assertTrue(issubclass(FloatOperation, DecimalException))
   2769         self.assertTrue(issubclass(FloatOperation, TypeError))
   2770         self.assertTrue(issubclass(DivisionByZero, DecimalException))
   2771         self.assertTrue(issubclass(DivisionByZero, ZeroDivisionError))
   2772         self.assertTrue(issubclass(Overflow, Rounded))
   2773         self.assertTrue(issubclass(Overflow, Inexact))
   2774         self.assertTrue(issubclass(Overflow, DecimalException))
   2775         self.assertTrue(issubclass(Underflow, Inexact))
   2776         self.assertTrue(issubclass(Underflow, Rounded))
   2777         self.assertTrue(issubclass(Underflow, Subnormal))
   2778         self.assertTrue(issubclass(Underflow, DecimalException))
   2779 
   2780         self.assertTrue(issubclass(Subnormal, DecimalException))
   2781         self.assertTrue(issubclass(Inexact, DecimalException))
   2782         self.assertTrue(issubclass(Rounded, DecimalException))
   2783         self.assertTrue(issubclass(Clamped, DecimalException))
   2784 
   2785         self.assertTrue(issubclass(decimal.ConversionSyntax, InvalidOperation))
   2786         self.assertTrue(issubclass(decimal.DivisionImpossible, InvalidOperation))
   2787         self.assertTrue(issubclass(decimal.DivisionUndefined, InvalidOperation))
   2788         self.assertTrue(issubclass(decimal.DivisionUndefined, ZeroDivisionError))
   2789         self.assertTrue(issubclass(decimal.InvalidContext, InvalidOperation))
   2790 
   2791 class CPythonAPItests(PythonAPItests):
   2792     decimal = C
   2793 class PyPythonAPItests(PythonAPItests):
   2794     decimal = P
   2795 
   2796 class ContextAPItests(unittest.TestCase):
   2797 
   2798     def test_none_args(self):
   2799         Context = self.decimal.Context
   2800         InvalidOperation = self.decimal.InvalidOperation
   2801         DivisionByZero = self.decimal.DivisionByZero
   2802         Overflow = self.decimal.Overflow
   2803 
   2804         c1 = Context()
   2805         c2 = Context(prec=None, rounding=None, Emax=None, Emin=None,
   2806                      capitals=None, clamp=None, flags=None, traps=None)
   2807         for c in [c1, c2]:
   2808             self.assertEqual(c.prec, 28)
   2809             self.assertEqual(c.rounding, ROUND_HALF_EVEN)
   2810             self.assertEqual(c.Emax, 999999)
   2811             self.assertEqual(c.Emin, -999999)
   2812             self.assertEqual(c.capitals, 1)
   2813             self.assertEqual(c.clamp, 0)
   2814             assert_signals(self, c, 'flags', [])
   2815             assert_signals(self, c, 'traps', [InvalidOperation, DivisionByZero,
   2816                                               Overflow])
   2817 
   2818     @cpython_only
   2819     def test_from_legacy_strings(self):
   2820         import _testcapi
   2821         c = self.decimal.Context()
   2822 
   2823         for rnd in RoundingModes:
   2824             c.rounding = _testcapi.unicode_legacy_string(rnd)
   2825             self.assertEqual(c.rounding, rnd)
   2826 
   2827         s = _testcapi.unicode_legacy_string('')
   2828         self.assertRaises(TypeError, setattr, c, 'rounding', s)
   2829 
   2830         s = _testcapi.unicode_legacy_string('ROUND_\x00UP')
   2831         self.assertRaises(TypeError, setattr, c, 'rounding', s)
   2832 
   2833     def test_pickle(self):
   2834 
   2835         for proto in range(pickle.HIGHEST_PROTOCOL + 1):
   2836             Context = self.decimal.Context
   2837 
   2838             savedecimal = sys.modules['decimal']
   2839 
   2840             # Round trip
   2841             sys.modules['decimal'] = self.decimal
   2842             c = Context()
   2843             e = pickle.loads(pickle.dumps(c, proto))
   2844 
   2845             self.assertEqual(c.prec, e.prec)
   2846             self.assertEqual(c.Emin, e.Emin)
   2847             self.assertEqual(c.Emax, e.Emax)
   2848             self.assertEqual(c.rounding, e.rounding)
   2849             self.assertEqual(c.capitals, e.capitals)
   2850             self.assertEqual(c.clamp, e.clamp)
   2851             self.assertEqual(c.flags, e.flags)
   2852             self.assertEqual(c.traps, e.traps)
   2853 
   2854             # Test interchangeability
   2855             combinations = [(C, P), (P, C)] if C else [(P, P)]
   2856             for dumper, loader in combinations:
   2857                 for ri, _ in enumerate(RoundingModes):
   2858                     for fi, _ in enumerate(OrderedSignals[dumper]):
   2859                         for ti, _ in enumerate(OrderedSignals[dumper]):
   2860 
   2861                             prec = random.randrange(1, 100)
   2862                             emin = random.randrange(-100, 0)
   2863                             emax = random.randrange(1, 100)
   2864                             caps = random.randrange(2)
   2865                             clamp = random.randrange(2)
   2866 
   2867                             # One module dumps
   2868                             sys.modules['decimal'] = dumper
   2869                             c = dumper.Context(
   2870                                   prec=prec, Emin=emin, Emax=emax,
   2871                                   rounding=RoundingModes[ri],
   2872                                   capitals=caps, clamp=clamp,
   2873                                   flags=OrderedSignals[dumper][:fi],
   2874                                   traps=OrderedSignals[dumper][:ti]
   2875                             )
   2876                             s = pickle.dumps(c, proto)
   2877 
   2878                             # The other module loads
   2879                             sys.modules['decimal'] = loader
   2880                             d = pickle.loads(s)
   2881                             self.assertIsInstance(d, loader.Context)
   2882 
   2883                             self.assertEqual(d.prec, prec)
   2884                             self.assertEqual(d.Emin, emin)
   2885                             self.assertEqual(d.Emax, emax)
   2886                             self.assertEqual(d.rounding, RoundingModes[ri])
   2887                             self.assertEqual(d.capitals, caps)
   2888                             self.assertEqual(d.clamp, clamp)
   2889                             assert_signals(self, d, 'flags', OrderedSignals[loader][:fi])
   2890                             assert_signals(self, d, 'traps', OrderedSignals[loader][:ti])
   2891 
   2892             sys.modules['decimal'] = savedecimal
   2893 
   2894     def test_equality_with_other_types(self):
   2895         Decimal = self.decimal.Decimal
   2896 
   2897         self.assertIn(Decimal(10), ['a', 1.0, Decimal(10), (1,2), {}])
   2898         self.assertNotIn(Decimal(10), ['a', 1.0, (1,2), {}])
   2899 
   2900     def test_copy(self):
   2901         # All copies should be deep
   2902         Decimal = self.decimal.Decimal
   2903         Context = self.decimal.Context
   2904 
   2905         c = Context()
   2906         d = c.copy()
   2907         self.assertNotEqual(id(c), id(d))
   2908         self.assertNotEqual(id(c.flags), id(d.flags))
   2909         self.assertNotEqual(id(c.traps), id(d.traps))
   2910         k1 = set(c.flags.keys())
   2911         k2 = set(d.flags.keys())
   2912         self.assertEqual(k1, k2)
   2913         self.assertEqual(c.flags, d.flags)
   2914 
   2915     def test__clamp(self):
   2916         # In Python 3.2, the private attribute `_clamp` was made
   2917         # public (issue 8540), with the old `_clamp` becoming a
   2918         # property wrapping `clamp`.  For the duration of Python 3.2
   2919         # only, the attribute should be gettable/settable via both
   2920         # `clamp` and `_clamp`; in Python 3.3, `_clamp` should be
   2921         # removed.
   2922         Context = self.decimal.Context
   2923         c = Context()
   2924         self.assertRaises(AttributeError, getattr, c, '_clamp')
   2925 
   2926     def test_abs(self):
   2927         Decimal = self.decimal.Decimal
   2928         Context = self.decimal.Context
   2929 
   2930         c = Context()
   2931         d = c.abs(Decimal(-1))
   2932         self.assertEqual(c.abs(-1), d)
   2933         self.assertRaises(TypeError, c.abs, '-1')
   2934 
   2935     def test_add(self):
   2936         Decimal = self.decimal.Decimal
   2937         Context = self.decimal.Context
   2938 
   2939         c = Context()
   2940         d = c.add(Decimal(1), Decimal(1))
   2941         self.assertEqual(c.add(1, 1), d)
   2942         self.assertEqual(c.add(Decimal(1), 1), d)
   2943         self.assertEqual(c.add(1, Decimal(1)), d)
   2944         self.assertRaises(TypeError, c.add, '1', 1)
   2945         self.assertRaises(TypeError, c.add, 1, '1')
   2946 
   2947     def test_compare(self):
   2948         Decimal = self.decimal.Decimal
   2949         Context = self.decimal.Context
   2950 
   2951         c = Context()
   2952         d = c.compare(Decimal(1), Decimal(1))
   2953         self.assertEqual(c.compare(1, 1), d)
   2954         self.assertEqual(c.compare(Decimal(1), 1), d)
   2955         self.assertEqual(c.compare(1, Decimal(1)), d)
   2956         self.assertRaises(TypeError, c.compare, '1', 1)
   2957         self.assertRaises(TypeError, c.compare, 1, '1')
   2958 
   2959     def test_compare_signal(self):
   2960         Decimal = self.decimal.Decimal
   2961         Context = self.decimal.Context
   2962 
   2963         c = Context()
   2964         d = c.compare_signal(Decimal(1), Decimal(1))
   2965         self.assertEqual(c.compare_signal(1, 1), d)
   2966         self.assertEqual(c.compare_signal(Decimal(1), 1), d)
   2967         self.assertEqual(c.compare_signal(1, Decimal(1)), d)
   2968         self.assertRaises(TypeError, c.compare_signal, '1', 1)
   2969         self.assertRaises(TypeError, c.compare_signal, 1, '1')
   2970 
   2971     def test_compare_total(self):
   2972         Decimal = self.decimal.Decimal
   2973         Context = self.decimal.Context
   2974 
   2975         c = Context()
   2976         d = c.compare_total(Decimal(1), Decimal(1))
   2977         self.assertEqual(c.compare_total(1, 1), d)
   2978         self.assertEqual(c.compare_total(Decimal(1), 1), d)
   2979         self.assertEqual(c.compare_total(1, Decimal(1)), d)
   2980         self.assertRaises(TypeError, c.compare_total, '1', 1)
   2981         self.assertRaises(TypeError, c.compare_total, 1, '1')
   2982 
   2983     def test_compare_total_mag(self):
   2984         Decimal = self.decimal.Decimal
   2985         Context = self.decimal.Context
   2986 
   2987         c = Context()
   2988         d = c.compare_total_mag(Decimal(1), Decimal(1))
   2989         self.assertEqual(c.compare_total_mag(1, 1), d)
   2990         self.assertEqual(c.compare_total_mag(Decimal(1), 1), d)
   2991         self.assertEqual(c.compare_total_mag(1, Decimal(1)), d)
   2992         self.assertRaises(TypeError, c.compare_total_mag, '1', 1)
   2993         self.assertRaises(TypeError, c.compare_total_mag, 1, '1')
   2994 
   2995     def test_copy_abs(self):
   2996         Decimal = self.decimal.Decimal
   2997         Context = self.decimal.Context
   2998 
   2999         c = Context()
   3000         d = c.copy_abs(Decimal(-1))
   3001         self.assertEqual(c.copy_abs(-1), d)
   3002         self.assertRaises(TypeError, c.copy_abs, '-1')
   3003 
   3004     def test_copy_decimal(self):
   3005         Decimal = self.decimal.Decimal
   3006         Context = self.decimal.Context
   3007 
   3008         c = Context()
   3009         d = c.copy_decimal(Decimal(-1))
   3010         self.assertEqual(c.copy_decimal(-1), d)
   3011         self.assertRaises(TypeError, c.copy_decimal, '-1')
   3012 
   3013     def test_copy_negate(self):
   3014         Decimal = self.decimal.Decimal
   3015         Context = self.decimal.Context
   3016 
   3017         c = Context()
   3018         d = c.copy_negate(Decimal(-1))
   3019         self.assertEqual(c.copy_negate(-1), d)
   3020         self.assertRaises(TypeError, c.copy_negate, '-1')
   3021 
   3022     def test_copy_sign(self):
   3023         Decimal = self.decimal.Decimal
   3024         Context = self.decimal.Context
   3025 
   3026         c = Context()
   3027         d = c.copy_sign(Decimal(1), Decimal(-2))
   3028         self.assertEqual(c.copy_sign(1, -2), d)
   3029         self.assertEqual(c.copy_sign(Decimal(1), -2), d)
   3030         self.assertEqual(c.copy_sign(1, Decimal(-2)), d)
   3031         self.assertRaises(TypeError, c.copy_sign, '1', -2)
   3032         self.assertRaises(TypeError, c.copy_sign, 1, '-2')
   3033 
   3034     def test_divide(self):
   3035         Decimal = self.decimal.Decimal
   3036         Context = self.decimal.Context
   3037 
   3038         c = Context()
   3039         d = c.divide(Decimal(1), Decimal(2))
   3040         self.assertEqual(c.divide(1, 2), d)
   3041         self.assertEqual(c.divide(Decimal(1), 2), d)
   3042         self.assertEqual(c.divide(1, Decimal(2)), d)
   3043         self.assertRaises(TypeError, c.divide, '1', 2)
   3044         self.assertRaises(TypeError, c.divide, 1, '2')
   3045 
   3046     def test_divide_int(self):
   3047         Decimal = self.decimal.Decimal
   3048         Context = self.decimal.Context
   3049 
   3050         c = Context()
   3051         d = c.divide_int(Decimal(1), Decimal(2))
   3052         self.assertEqual(c.divide_int(1, 2), d)
   3053         self.assertEqual(c.divide_int(Decimal(1), 2), d)
   3054         self.assertEqual(c.divide_int(1, Decimal(2)), d)
   3055         self.assertRaises(TypeError, c.divide_int, '1', 2)
   3056         self.assertRaises(TypeError, c.divide_int, 1, '2')
   3057 
   3058     def test_divmod(self):
   3059         Decimal = self.decimal.Decimal
   3060         Context = self.decimal.Context
   3061 
   3062         c = Context()
   3063         d = c.divmod(Decimal(1), Decimal(2))
   3064         self.assertEqual(c.divmod(1, 2), d)
   3065         self.assertEqual(c.divmod(Decimal(1), 2), d)
   3066         self.assertEqual(c.divmod(1, Decimal(2)), d)
   3067         self.assertRaises(TypeError, c.divmod, '1', 2)
   3068         self.assertRaises(TypeError, c.divmod, 1, '2')
   3069 
   3070     def test_exp(self):
   3071         Decimal = self.decimal.Decimal
   3072         Context = self.decimal.Context
   3073 
   3074         c = Context()
   3075         d = c.exp(Decimal(10))
   3076         self.assertEqual(c.exp(10), d)
   3077         self.assertRaises(TypeError, c.exp, '10')
   3078 
   3079     def test_fma(self):
   3080         Decimal = self.decimal.Decimal
   3081         Context = self.decimal.Context
   3082 
   3083         c = Context()
   3084         d = c.fma(Decimal(2), Decimal(3), Decimal(4))
   3085         self.assertEqual(c.fma(2, 3, 4), d)
   3086         self.assertEqual(c.fma(Decimal(2), 3, 4), d)
   3087         self.assertEqual(c.fma(2, Decimal(3), 4), d)
   3088         self.assertEqual(c.fma(2, 3, Decimal(4)), d)
   3089         self.assertEqual(c.fma(Decimal(2), Decimal(3), 4), d)
   3090         self.assertRaises(TypeError, c.fma, '2', 3, 4)
   3091         self.assertRaises(TypeError, c.fma, 2, '3', 4)
   3092         self.assertRaises(TypeError, c.fma, 2, 3, '4')
   3093 
   3094         # Issue 12079 for Context.fma ...
   3095         self.assertRaises(TypeError, c.fma,
   3096                           Decimal('Infinity'), Decimal(0), "not a decimal")
   3097         self.assertRaises(TypeError, c.fma,
   3098                           Decimal(1), Decimal('snan'), 1.222)
   3099         # ... and for Decimal.fma.
   3100         self.assertRaises(TypeError, Decimal('Infinity').fma,
   3101                           Decimal(0), "not a decimal")
   3102         self.assertRaises(TypeError, Decimal(1).fma,
   3103                           Decimal('snan'), 1.222)
   3104 
   3105     def test_is_finite(self):
   3106         Decimal = self.decimal.Decimal
   3107         Context = self.decimal.Context
   3108 
   3109         c = Context()
   3110         d = c.is_finite(Decimal(10))
   3111         self.assertEqual(c.is_finite(10), d)
   3112         self.assertRaises(TypeError, c.is_finite, '10')
   3113 
   3114     def test_is_infinite(self):
   3115         Decimal = self.decimal.Decimal
   3116         Context = self.decimal.Context
   3117 
   3118         c = Context()
   3119         d = c.is_infinite(Decimal(10))
   3120         self.assertEqual(c.is_infinite(10), d)
   3121         self.assertRaises(TypeError, c.is_infinite, '10')
   3122 
   3123     def test_is_nan(self):
   3124         Decimal = self.decimal.Decimal
   3125         Context = self.decimal.Context
   3126 
   3127         c = Context()
   3128         d = c.is_nan(Decimal(10))
   3129         self.assertEqual(c.is_nan(10), d)
   3130         self.assertRaises(TypeError, c.is_nan, '10')
   3131 
   3132     def test_is_normal(self):
   3133         Decimal = self.decimal.Decimal
   3134         Context = self.decimal.Context
   3135 
   3136         c = Context()
   3137         d = c.is_normal(Decimal(10))
   3138         self.assertEqual(c.is_normal(10), d)
   3139         self.assertRaises(TypeError, c.is_normal, '10')
   3140 
   3141     def test_is_qnan(self):
   3142         Decimal = self.decimal.Decimal
   3143         Context = self.decimal.Context
   3144 
   3145         c = Context()
   3146         d = c.is_qnan(Decimal(10))
   3147         self.assertEqual(c.is_qnan(10), d)
   3148         self.assertRaises(TypeError, c.is_qnan, '10')
   3149 
   3150     def test_is_signed(self):
   3151         Decimal = self.decimal.Decimal
   3152         Context = self.decimal.Context
   3153 
   3154         c = Context()
   3155         d = c.is_signed(Decimal(10))
   3156         self.assertEqual(c.is_signed(10), d)
   3157         self.assertRaises(TypeError, c.is_signed, '10')
   3158 
   3159     def test_is_snan(self):
   3160         Decimal = self.decimal.Decimal
   3161         Context = self.decimal.Context
   3162 
   3163         c = Context()
   3164         d = c.is_snan(Decimal(10))
   3165         self.assertEqual(c.is_snan(10), d)
   3166         self.assertRaises(TypeError, c.is_snan, '10')
   3167 
   3168     def test_is_subnormal(self):
   3169         Decimal = self.decimal.Decimal
   3170         Context = self.decimal.Context
   3171 
   3172         c = Context()
   3173         d = c.is_subnormal(Decimal(10))
   3174         self.assertEqual(c.is_subnormal(10), d)
   3175         self.assertRaises(TypeError, c.is_subnormal, '10')
   3176 
   3177     def test_is_zero(self):
   3178         Decimal = self.decimal.Decimal
   3179         Context = self.decimal.Context
   3180 
   3181         c = Context()
   3182         d = c.is_zero(Decimal(10))
   3183         self.assertEqual(c.is_zero(10), d)
   3184         self.assertRaises(TypeError, c.is_zero, '10')
   3185 
   3186     def test_ln(self):
   3187         Decimal = self.decimal.Decimal
   3188         Context = self.decimal.Context
   3189 
   3190         c = Context()
   3191         d = c.ln(Decimal(10))
   3192         self.assertEqual(c.ln(10), d)
   3193         self.assertRaises(TypeError, c.ln, '10')
   3194 
   3195     def test_log10(self):
   3196         Decimal = self.decimal.Decimal
   3197         Context = self.decimal.Context
   3198 
   3199         c = Context()
   3200         d = c.log10(Decimal(10))
   3201         self.assertEqual(c.log10(10), d)
   3202         self.assertRaises(TypeError, c.log10, '10')
   3203 
   3204     def test_logb(self):
   3205         Decimal = self.decimal.Decimal
   3206         Context = self.decimal.Context
   3207 
   3208         c = Context()
   3209         d = c.logb(Decimal(10))
   3210         self.assertEqual(c.logb(10), d)
   3211         self.assertRaises(TypeError, c.logb, '10')
   3212 
   3213     def test_logical_and(self):
   3214         Decimal = self.decimal.Decimal
   3215         Context = self.decimal.Context
   3216 
   3217         c = Context()
   3218         d = c.logical_and(Decimal(1), Decimal(1))
   3219         self.assertEqual(c.logical_and(1, 1), d)
   3220         self.assertEqual(c.logical_and(Decimal(1), 1), d)
   3221         self.assertEqual(c.logical_and(1, Decimal(1)), d)
   3222         self.assertRaises(TypeError, c.logical_and, '1', 1)
   3223         self.assertRaises(TypeError, c.logical_and, 1, '1')
   3224 
   3225     def test_logical_invert(self):
   3226         Decimal = self.decimal.Decimal
   3227         Context = self.decimal.Context
   3228 
   3229         c = Context()
   3230         d = c.logical_invert(Decimal(1000))
   3231         self.assertEqual(c.logical_invert(1000), d)
   3232         self.assertRaises(TypeError, c.logical_invert, '1000')
   3233 
   3234     def test_logical_or(self):
   3235         Decimal = self.decimal.Decimal
   3236         Context = self.decimal.Context
   3237 
   3238         c = Context()
   3239         d = c.logical_or(Decimal(1), Decimal(1))
   3240         self.assertEqual(c.logical_or(1, 1), d)
   3241         self.assertEqual(c.logical_or(Decimal(1), 1), d)
   3242         self.assertEqual(c.logical_or(1, Decimal(1)), d)
   3243         self.assertRaises(TypeError, c.logical_or, '1', 1)
   3244         self.assertRaises(TypeError, c.logical_or, 1, '1')
   3245 
   3246     def test_logical_xor(self):
   3247         Decimal = self.decimal.Decimal
   3248         Context = self.decimal.Context
   3249 
   3250         c = Context()
   3251         d = c.logical_xor(Decimal(1), Decimal(1))
   3252         self.assertEqual(c.logical_xor(1, 1), d)
   3253         self.assertEqual(c.logical_xor(Decimal(1), 1), d)
   3254         self.assertEqual(c.logical_xor(1, Decimal(1)), d)
   3255         self.assertRaises(TypeError, c.logical_xor, '1', 1)
   3256         self.assertRaises(TypeError, c.logical_xor, 1, '1')
   3257 
   3258     def test_max(self):
   3259         Decimal = self.decimal.Decimal
   3260         Context = self.decimal.Context
   3261 
   3262         c = Context()
   3263         d = c.max(Decimal(1), Decimal(2))
   3264         self.assertEqual(c.max(1, 2), d)
   3265         self.assertEqual(c.max(Decimal(1), 2), d)
   3266         self.assertEqual(c.max(1, Decimal(2)), d)
   3267         self.assertRaises(TypeError, c.max, '1', 2)
   3268         self.assertRaises(TypeError, c.max, 1, '2')
   3269 
   3270     def test_max_mag(self):
   3271         Decimal = self.decimal.Decimal
   3272         Context = self.decimal.Context
   3273 
   3274         c = Context()
   3275         d = c.max_mag(Decimal(1), Decimal(2))
   3276         self.assertEqual(c.max_mag(1, 2), d)
   3277         self.assertEqual(c.max_mag(Decimal(1), 2), d)
   3278         self.assertEqual(c.max_mag(1, Decimal(2)), d)
   3279         self.assertRaises(TypeError, c.max_mag, '1', 2)
   3280         self.assertRaises(TypeError, c.max_mag, 1, '2')
   3281 
   3282     def test_min(self):
   3283         Decimal = self.decimal.Decimal
   3284         Context = self.decimal.Context
   3285 
   3286         c = Context()
   3287         d = c.min(Decimal(1), Decimal(2))
   3288         self.assertEqual(c.min(1, 2), d)
   3289         self.assertEqual(c.min(Decimal(1), 2), d)
   3290         self.assertEqual(c.min(1, Decimal(2)), d)
   3291         self.assertRaises(TypeError, c.min, '1', 2)
   3292         self.assertRaises(TypeError, c.min, 1, '2')
   3293 
   3294     def test_min_mag(self):
   3295         Decimal = self.decimal.Decimal
   3296         Context = self.decimal.Context
   3297 
   3298         c = Context()
   3299         d = c.min_mag(Decimal(1), Decimal(2))
   3300         self.assertEqual(c.min_mag(1, 2), d)
   3301         self.assertEqual(c.min_mag(Decimal(1), 2), d)
   3302         self.assertEqual(c.min_mag(1, Decimal(2)), d)
   3303         self.assertRaises(TypeError, c.min_mag, '1', 2)
   3304         self.assertRaises(TypeError, c.min_mag, 1, '2')
   3305 
   3306     def test_minus(self):
   3307         Decimal = self.decimal.Decimal
   3308         Context = self.decimal.Context
   3309 
   3310         c = Context()
   3311         d = c.minus(Decimal(10))
   3312         self.assertEqual(c.minus(10), d)
   3313         self.assertRaises(TypeError, c.minus, '10')
   3314 
   3315     def test_multiply(self):
   3316         Decimal = self.decimal.Decimal
   3317         Context = self.decimal.Context
   3318 
   3319         c = Context()
   3320         d = c.multiply(Decimal(1), Decimal(2))
   3321         self.assertEqual(c.multiply(1, 2), d)
   3322         self.assertEqual(c.multiply(Decimal(1), 2), d)
   3323         self.assertEqual(c.multiply(1, Decimal(2)), d)
   3324         self.assertRaises(TypeError, c.multiply, '1', 2)
   3325         self.assertRaises(TypeError, c.multiply, 1, '2')
   3326 
   3327     def test_next_minus(self):
   3328         Decimal = self.decimal.Decimal
   3329         Context = self.decimal.Context
   3330 
   3331         c = Context()
   3332         d = c.next_minus(Decimal(10))
   3333         self.assertEqual(c.next_minus(10), d)
   3334         self.assertRaises(TypeError, c.next_minus, '10')
   3335 
   3336     def test_next_plus(self):
   3337         Decimal = self.decimal.Decimal
   3338         Context = self.decimal.Context
   3339 
   3340         c = Context()
   3341         d = c.next_plus(Decimal(10))
   3342         self.assertEqual(c.next_plus(10), d)
   3343         self.assertRaises(TypeError, c.next_plus, '10')
   3344 
   3345     def test_next_toward(self):
   3346         Decimal = self.decimal.Decimal
   3347         Context = self.decimal.Context
   3348 
   3349         c = Context()
   3350         d = c.next_toward(Decimal(1), Decimal(2))
   3351         self.assertEqual(c.next_toward(1, 2), d)
   3352         self.assertEqual(c.next_toward(Decimal(1), 2), d)
   3353         self.assertEqual(c.next_toward(1, Decimal(2)), d)
   3354         self.assertRaises(TypeError, c.next_toward, '1', 2)
   3355         self.assertRaises(TypeError, c.next_toward, 1, '2')
   3356 
   3357     def test_normalize(self):
   3358         Decimal = self.decimal.Decimal
   3359         Context = self.decimal.Context
   3360 
   3361         c = Context()
   3362         d = c.normalize(Decimal(10))
   3363         self.assertEqual(c.normalize(10), d)
   3364         self.assertRaises(TypeError, c.normalize, '10')
   3365 
   3366     def test_number_class(self):
   3367         Decimal = self.decimal.Decimal
   3368         Context = self.decimal.Context
   3369 
   3370         c = Context()
   3371         self.assertEqual(c.number_class(123), c.number_class(Decimal(123)))
   3372         self.assertEqual(c.number_class(0), c.number_class(Decimal(0)))
   3373         self.assertEqual(c.number_class(-45), c.number_class(Decimal(-45)))
   3374 
   3375     def test_plus(self):
   3376         Decimal = self.decimal.Decimal
   3377         Context = self.decimal.Context
   3378 
   3379         c = Context()
   3380         d = c.plus(Decimal(10))
   3381         self.assertEqual(c.plus(10), d)
   3382         self.assertRaises(TypeError, c.plus, '10')
   3383 
   3384     def test_power(self):
   3385         Decimal = self.decimal.Decimal
   3386         Context = self.decimal.Context
   3387 
   3388         c = Context()
   3389         d = c.power(Decimal(1), Decimal(4))
   3390         self.assertEqual(c.power(1, 4), d)
   3391         self.assertEqual(c.power(Decimal(1), 4), d)
   3392         self.assertEqual(c.power(1, Decimal(4)), d)
   3393         self.assertEqual(c.power(Decimal(1), Decimal(4)), d)
   3394         self.assertRaises(TypeError, c.power, '1', 4)
   3395         self.assertRaises(TypeError, c.power, 1, '4')
   3396         self.assertEqual(c.power(modulo=5, b=8, a=2), 1)
   3397 
   3398     def test_quantize(self):
   3399         Decimal = self.decimal.Decimal
   3400         Context = self.decimal.Context
   3401 
   3402         c = Context()
   3403         d = c.quantize(Decimal(1), Decimal(2))
   3404         self.assertEqual(c.quantize(1, 2), d)
   3405         self.assertEqual(c.quantize(Decimal(1), 2), d)
   3406         self.assertEqual(c.quantize(1, Decimal(2)), d)
   3407         self.assertRaises(TypeError, c.quantize, '1', 2)
   3408         self.assertRaises(TypeError, c.quantize, 1, '2')
   3409 
   3410     def test_remainder(self):
   3411         Decimal = self.decimal.Decimal
   3412         Context = self.decimal.Context
   3413 
   3414         c = Context()
   3415         d = c.remainder(Decimal(1), Decimal(2))
   3416         self.assertEqual(c.remainder(1, 2), d)
   3417         self.assertEqual(c.remainder(Decimal(1), 2), d)
   3418         self.assertEqual(c.remainder(1, Decimal(2)), d)
   3419         self.assertRaises(TypeError, c.remainder, '1', 2)
   3420         self.assertRaises(TypeError, c.remainder, 1, '2')
   3421 
   3422     def test_remainder_near(self):
   3423         Decimal = self.decimal.Decimal
   3424         Context = self.decimal.Context
   3425 
   3426         c = Context()
   3427         d = c.remainder_near(Decimal(1), Decimal(2))
   3428         self.assertEqual(c.remainder_near(1, 2), d)
   3429         self.assertEqual(c.remainder_near(Decimal(1), 2), d)
   3430         self.assertEqual(c.remainder_near(1, Decimal(2)), d)
   3431         self.assertRaises(TypeError, c.remainder_near, '1', 2)
   3432         self.assertRaises(TypeError, c.remainder_near, 1, '2')
   3433 
   3434     def test_rotate(self):
   3435         Decimal = self.decimal.Decimal
   3436         Context = self.decimal.Context
   3437 
   3438         c = Context()
   3439         d = c.rotate(Decimal(1), Decimal(2))
   3440         self.assertEqual(c.rotate(1, 2), d)
   3441         self.assertEqual(c.rotate(Decimal(1), 2), d)
   3442         self.assertEqual(c.rotate(1, Decimal(2)), d)
   3443         self.assertRaises(TypeError, c.rotate, '1', 2)
   3444         self.assertRaises(TypeError, c.rotate, 1, '2')
   3445 
   3446     def test_sqrt(self):
   3447         Decimal = self.decimal.Decimal
   3448         Context = self.decimal.Context
   3449 
   3450         c = Context()
   3451         d = c.sqrt(Decimal(10))
   3452         self.assertEqual(c.sqrt(10), d)
   3453         self.assertRaises(TypeError, c.sqrt, '10')
   3454 
   3455     def test_same_quantum(self):
   3456         Decimal = self.decimal.Decimal
   3457         Context = self.decimal.Context
   3458 
   3459         c = Context()
   3460         d = c.same_quantum(Decimal(1), Decimal(2))
   3461         self.assertEqual(c.same_quantum(1, 2), d)
   3462         self.assertEqual(c.same_quantum(Decimal(1), 2), d)
   3463         self.assertEqual(c.same_quantum(1, Decimal(2)), d)
   3464         self.assertRaises(TypeError, c.same_quantum, '1', 2)
   3465         self.assertRaises(TypeError, c.same_quantum, 1, '2')
   3466 
   3467     def test_scaleb(self):
   3468         Decimal = self.decimal.Decimal
   3469         Context = self.decimal.Context
   3470 
   3471         c = Context()
   3472         d = c.scaleb(Decimal(1), Decimal(2))
   3473         self.assertEqual(c.scaleb(1, 2), d)
   3474         self.assertEqual(c.scaleb(Decimal(1), 2), d)
   3475         self.assertEqual(c.scaleb(1, Decimal(2)), d)
   3476         self.assertRaises(TypeError, c.scaleb, '1', 2)
   3477         self.assertRaises(TypeError, c.scaleb, 1, '2')
   3478 
   3479     def test_shift(self):
   3480         Decimal = self.decimal.Decimal
   3481         Context = self.decimal.Context
   3482 
   3483         c = Context()
   3484         d = c.shift(Decimal(1), Decimal(2))
   3485         self.assertEqual(c.shift(1, 2), d)
   3486         self.assertEqual(c.shift(Decimal(1), 2), d)
   3487         self.assertEqual(c.shift(1, Decimal(2)), d)
   3488         self.assertRaises(TypeError, c.shift, '1', 2)
   3489         self.assertRaises(TypeError, c.shift, 1, '2')
   3490 
   3491     def test_subtract(self):
   3492         Decimal = self.decimal.Decimal
   3493         Context = self.decimal.Context
   3494 
   3495         c = Context()
   3496         d = c.subtract(Decimal(1), Decimal(2))
   3497         self.assertEqual(c.subtract(1, 2), d)
   3498         self.assertEqual(c.subtract(Decimal(1), 2), d)
   3499         self.assertEqual(c.subtract(1, Decimal(2)), d)
   3500         self.assertRaises(TypeError, c.subtract, '1', 2)
   3501         self.assertRaises(TypeError, c.subtract, 1, '2')
   3502 
   3503     def test_to_eng_string(self):
   3504         Decimal = self.decimal.Decimal
   3505         Context = self.decimal.Context
   3506 
   3507         c = Context()
   3508         d = c.to_eng_string(Decimal(10))
   3509         self.assertEqual(c.to_eng_string(10), d)
   3510         self.assertRaises(TypeError, c.to_eng_string, '10')
   3511 
   3512     def test_to_sci_string(self):
   3513         Decimal = self.decimal.Decimal
   3514         Context = self.decimal.Context
   3515 
   3516         c = Context()
   3517         d = c.to_sci_string(Decimal(10))
   3518         self.assertEqual(c.to_sci_string(10), d)
   3519         self.assertRaises(TypeError, c.to_sci_string, '10')
   3520 
   3521     def test_to_integral_exact(self):
   3522         Decimal = self.decimal.Decimal
   3523         Context = self.decimal.Context
   3524 
   3525         c = Context()
   3526         d = c.to_integral_exact(Decimal(10))
   3527         self.assertEqual(c.to_integral_exact(10), d)
   3528         self.assertRaises(TypeError, c.to_integral_exact, '10')
   3529 
   3530     def test_to_integral_value(self):
   3531         Decimal = self.decimal.Decimal
   3532         Context = self.decimal.Context
   3533 
   3534         c = Context()
   3535         d = c.to_integral_value(Decimal(10))
   3536         self.assertEqual(c.to_integral_value(10), d)
   3537         self.assertRaises(TypeError, c.to_integral_value, '10')
   3538         self.assertRaises(TypeError, c.to_integral_value, 10, 'x')
   3539 
   3540 class CContextAPItests(ContextAPItests):
   3541     decimal = C
   3542 class PyContextAPItests(ContextAPItests):
   3543     decimal = P
   3544 
   3545 class ContextWithStatement(unittest.TestCase):
   3546     # Can't do these as docstrings until Python 2.6
   3547     # as doctest can't handle __future__ statements
   3548 
   3549     def test_localcontext(self):
   3550         # Use a copy of the current context in the block
   3551         getcontext = self.decimal.getcontext
   3552         localcontext = self.decimal.localcontext
   3553 
   3554         orig_ctx = getcontext()
   3555         with localcontext() as enter_ctx:
   3556             set_ctx = getcontext()
   3557         final_ctx = getcontext()
   3558         self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
   3559         self.assertIsNot(orig_ctx, set_ctx, 'did not copy the context')
   3560         self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
   3561 
   3562     def test_localcontextarg(self):
   3563         # Use a copy of the supplied context in the block
   3564         Context = self.decimal.Context
   3565         getcontext = self.decimal.getcontext
   3566         localcontext = self.decimal.localcontext
   3567 
   3568         localcontext = self.decimal.localcontext
   3569         orig_ctx = getcontext()
   3570         new_ctx = Context(prec=42)
   3571         with localcontext(new_ctx) as enter_ctx:
   3572             set_ctx = getcontext()
   3573         final_ctx = getcontext()
   3574         self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
   3575         self.assertEqual(set_ctx.prec, new_ctx.prec, 'did not set correct context')
   3576         self.assertIsNot(new_ctx, set_ctx, 'did not copy the context')
   3577         self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
   3578 
   3579     def test_nested_with_statements(self):
   3580         # Use a copy of the supplied context in the block
   3581         Decimal = self.decimal.Decimal
   3582         Context = self.decimal.Context
   3583         getcontext = self.decimal.getcontext
   3584         localcontext = self.decimal.localcontext
   3585         Clamped = self.decimal.Clamped
   3586         Overflow = self.decimal.Overflow
   3587 
   3588         orig_ctx = getcontext()
   3589         orig_ctx.clear_flags()
   3590         new_ctx = Context(Emax=384)
   3591         with localcontext() as c1:
   3592             self.assertEqual(c1.flags, orig_ctx.flags)
   3593             self.assertEqual(c1.traps, orig_ctx.traps)
   3594             c1.traps[Clamped] = True
   3595             c1.Emin = -383
   3596             self.assertNotEqual(orig_ctx.Emin, -383)
   3597             self.assertRaises(Clamped, c1.create_decimal, '0e-999')
   3598             self.assertTrue(c1.flags[Clamped])
   3599             with localcontext(new_ctx) as c2:
   3600                 self.assertEqual(c2.flags, new_ctx.flags)
   3601                 self.assertEqual(c2.traps, new_ctx.traps)
   3602                 self.assertRaises(Overflow, c2.power, Decimal('3.4e200'), 2)
   3603                 self.assertFalse(c2.flags[Clamped])
   3604                 self.assertTrue(c2.flags[Overflow])
   3605                 del c2
   3606             self.assertFalse(c1.flags[Overflow])
   3607             del c1
   3608         self.assertNotEqual(orig_ctx.Emin, -383)
   3609         self.assertFalse(orig_ctx.flags[Clamped])
   3610         self.assertFalse(orig_ctx.flags[Overflow])
   3611         self.assertFalse(new_ctx.flags[Clamped])
   3612         self.assertFalse(new_ctx.flags[Overflow])
   3613 
   3614     def test_with_statements_gc1(self):
   3615         localcontext = self.decimal.localcontext
   3616 
   3617         with localcontext() as c1:
   3618             del c1
   3619             with localcontext() as c2:
   3620                 del c2
   3621                 with localcontext() as c3:
   3622                     del c3
   3623                     with localcontext() as c4:
   3624                         del c4
   3625 
   3626     def test_with_statements_gc2(self):
   3627         localcontext = self.decimal.localcontext
   3628 
   3629         with localcontext() as c1:
   3630             with localcontext(c1) as c2:
   3631                 del c1
   3632                 with localcontext(c2) as c3:
   3633                     del c2
   3634                     with localcontext(c3) as c4:
   3635                         del c3
   3636                         del c4
   3637 
   3638     def test_with_statements_gc3(self):
   3639         Context = self.decimal.Context
   3640         localcontext = self.decimal.localcontext
   3641         getcontext = self.decimal.getcontext
   3642         setcontext = self.decimal.setcontext
   3643 
   3644         with localcontext() as c1:
   3645             del c1
   3646             n1 = Context(prec=1)
   3647             setcontext(n1)
   3648             with localcontext(n1) as c2:
   3649                 del n1
   3650                 self.assertEqual(c2.prec, 1)
   3651                 del c2
   3652                 n2 = Context(prec=2)
   3653                 setcontext(n2)
   3654                 del n2
   3655                 self.assertEqual(getcontext().prec, 2)
   3656                 n3 = Context(prec=3)
   3657                 setcontext(n3)
   3658                 self.assertEqual(getcontext().prec, 3)
   3659                 with localcontext(n3) as c3:
   3660                     del n3
   3661                     self.assertEqual(c3.prec, 3)
   3662                     del c3
   3663                     n4 = Context(prec=4)
   3664                     setcontext(n4)
   3665                     del n4
   3666                     self.assertEqual(getcontext().prec, 4)
   3667                     with localcontext() as c4:
   3668                         self.assertEqual(c4.prec, 4)
   3669                         del c4
   3670 
   3671 class CContextWithStatement(ContextWithStatement):
   3672     decimal = C
   3673 class PyContextWithStatement(ContextWithStatement):
   3674     decimal = P
   3675 
   3676 class ContextFlags(unittest.TestCase):
   3677 
   3678     def test_flags_irrelevant(self):
   3679         # check that the result (numeric result + flags raised) of an
   3680         # arithmetic operation doesn't depend on the current flags
   3681         Decimal = self.decimal.Decimal
   3682         Context = self.decimal.Context
   3683         Inexact = self.decimal.Inexact
   3684         Rounded = self.decimal.Rounded
   3685         Underflow = self.decimal.Underflow
   3686         Clamped = self.decimal.Clamped
   3687         Subnormal = self.decimal.Subnormal
   3688 
   3689         def raise_error(context, flag):
   3690             if self.decimal == C:
   3691                 context.flags[flag] = True
   3692                 if context.traps[flag]:
   3693                     raise flag
   3694             else:
   3695                 context._raise_error(flag)
   3696 
   3697         context = Context(prec=9, Emin = -425000000, Emax = 425000000,
   3698                           rounding=ROUND_HALF_EVEN, traps=[], flags=[])
   3699 
   3700         # operations that raise various flags, in the form (function, arglist)
   3701         operations = [
   3702             (context._apply, [Decimal("100E-425000010")]),
   3703             (context.sqrt, [Decimal(2)]),
   3704             (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]),
   3705             (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]),
   3706             (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]),
   3707             ]
   3708 
   3709         # try various flags individually, then a whole lot at once
   3710         flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal],
   3711                     [Inexact, Rounded, Underflow, Clamped, Subnormal]]
   3712 
   3713         for fn, args in operations:
   3714             # find answer and flags raised using a clean context
   3715             context.clear_flags()
   3716             ans = fn(*args)
   3717             flags = [k for k, v in context.flags.items() if v]
   3718 
   3719             for extra_flags in flagsets:
   3720                 # set flags, before calling operation
   3721                 context.clear_flags()
   3722                 for flag in extra_flags:
   3723                     raise_error(context, flag)
   3724                 new_ans = fn(*args)
   3725 
   3726                 # flags that we expect to be set after the operation
   3727                 expected_flags = list(flags)
   3728                 for flag in extra_flags:
   3729                     if flag not in expected_flags:
   3730                         expected_flags.append(flag)
   3731                 expected_flags.sort(key=id)
   3732 
   3733                 # flags we actually got
   3734                 new_flags = [k for k,v in context.flags.items() if v]
   3735                 new_flags.sort(key=id)
   3736 
   3737                 self.assertEqual(ans, new_ans,
   3738                                  "operation produces different answers depending on flags set: " +
   3739                                  "expected %s, got %s." % (ans, new_ans))
   3740                 self.assertEqual(new_flags, expected_flags,
   3741                                   "operation raises different flags depending on flags set: " +
   3742                                   "expected %s, got %s" % (expected_flags, new_flags))
   3743 
   3744     def test_flag_comparisons(self):
   3745         Context = self.decimal.Context
   3746         Inexact = self.decimal.Inexact
   3747         Rounded = self.decimal.Rounded
   3748 
   3749         c = Context()
   3750 
   3751         # Valid SignalDict
   3752         self.assertNotEqual(c.flags, c.traps)
   3753         self.assertNotEqual(c.traps, c.flags)
   3754 
   3755         c.flags = c.traps
   3756         self.assertEqual(c.flags, c.traps)
   3757         self.assertEqual(c.traps, c.flags)
   3758 
   3759         c.flags[Rounded] = True
   3760         c.traps = c.flags
   3761         self.assertEqual(c.flags, c.traps)
   3762         self.assertEqual(c.traps, c.flags)
   3763 
   3764         d = {}
   3765         d.update(c.flags)
   3766         self.assertEqual(d, c.flags)
   3767         self.assertEqual(c.flags, d)
   3768 
   3769         d[Inexact] = True
   3770         self.assertNotEqual(d, c.flags)
   3771         self.assertNotEqual(c.flags, d)
   3772 
   3773         # Invalid SignalDict
   3774         d = {Inexact:False}
   3775         self.assertNotEqual(d, c.flags)
   3776         self.assertNotEqual(c.flags, d)
   3777 
   3778         d = ["xyz"]
   3779         self.assertNotEqual(d, c.flags)
   3780         self.assertNotEqual(c.flags, d)
   3781 
   3782     @requires_IEEE_754
   3783     def test_float_operation(self):
   3784         Decimal = self.decimal.Decimal
   3785         FloatOperation = self.decimal.FloatOperation
   3786         localcontext = self.decimal.localcontext
   3787 
   3788         with localcontext() as c:
   3789             ##### trap is off by default
   3790             self.assertFalse(c.traps[FloatOperation])
   3791 
   3792             # implicit conversion sets the flag
   3793             c.clear_flags()
   3794             self.assertEqual(Decimal(7.5), 7.5)
   3795             self.assertTrue(c.flags[FloatOperation])
   3796 
   3797             c.clear_flags()
   3798             self.assertEqual(c.create_decimal(7.5), 7.5)
   3799             self.assertTrue(c.flags[FloatOperation])
   3800 
   3801             # explicit conversion does not set the flag
   3802             c.clear_flags()
   3803             x = Decimal.from_float(7.5)
   3804             self.assertFalse(c.flags[FloatOperation])
   3805             # comparison sets the flag
   3806             self.assertEqual(x, 7.5)
   3807             self.assertTrue(c.flags[FloatOperation])
   3808 
   3809             c.clear_flags()
   3810             x = c.create_decimal_from_float(7.5)
   3811             self.assertFalse(c.flags[FloatOperation])
   3812             self.assertEqual(x, 7.5)
   3813             self.assertTrue(c.flags[FloatOperation])
   3814 
   3815             ##### set the trap
   3816             c.traps[FloatOperation] = True
   3817 
   3818             # implicit conversion raises
   3819             c.clear_flags()
   3820             self.assertRaises(FloatOperation, Decimal, 7.5)
   3821             self.assertTrue(c.flags[FloatOperation])
   3822 
   3823             c.clear_flags()
   3824             self.assertRaises(FloatOperation, c.create_decimal, 7.5)
   3825             self.assertTrue(c.flags[FloatOperation])
   3826 
   3827             # explicit conversion is silent
   3828             c.clear_flags()
   3829             x = Decimal.from_float(7.5)
   3830             self.assertFalse(c.flags[FloatOperation])
   3831 
   3832             c.clear_flags()
   3833             x = c.create_decimal_from_float(7.5)
   3834             self.assertFalse(c.flags[FloatOperation])
   3835 
   3836     def test_float_comparison(self):
   3837         Decimal = self.decimal.Decimal
   3838         Context = self.decimal.Context
   3839         FloatOperation = self.decimal.FloatOperation
   3840         localcontext = self.decimal.localcontext
   3841 
   3842         def assert_attr(a, b, attr, context, signal=None):
   3843             context.clear_flags()
   3844             f = getattr(a, attr)
   3845             if signal == FloatOperation:
   3846                 self.assertRaises(signal, f, b)
   3847             else:
   3848                 self.assertIs(f(b), True)
   3849             self.assertTrue(context.flags[FloatOperation])
   3850 
   3851         small_d = Decimal('0.25')
   3852         big_d = Decimal('3.0')
   3853         small_f = 0.25
   3854         big_f = 3.0
   3855 
   3856         zero_d = Decimal('0.0')
   3857         neg_zero_d = Decimal('-0.0')
   3858         zero_f = 0.0
   3859         neg_zero_f = -0.0
   3860 
   3861         inf_d = Decimal('Infinity')
   3862         neg_inf_d = Decimal('-Infinity')
   3863         inf_f = float('inf')
   3864         neg_inf_f = float('-inf')
   3865 
   3866         def doit(c, signal=None):
   3867             # Order
   3868             for attr in '__lt__', '__le__':
   3869                 assert_attr(small_d, big_f, attr, c, signal)
   3870 
   3871             for attr in '__gt__', '__ge__':
   3872                 assert_attr(big_d, small_f, attr, c, signal)
   3873 
   3874             # Equality
   3875             assert_attr(small_d, small_f, '__eq__', c, None)
   3876 
   3877             assert_attr(neg_zero_d, neg_zero_f, '__eq__', c, None)
   3878             assert_attr(neg_zero_d, zero_f, '__eq__', c, None)
   3879 
   3880             assert_attr(zero_d, neg_zero_f, '__eq__', c, None)
   3881             assert_attr(zero_d, zero_f, '__eq__', c, None)
   3882 
   3883             assert_attr(neg_inf_d, neg_inf_f, '__eq__', c, None)
   3884             assert_attr(inf_d, inf_f, '__eq__', c, None)
   3885 
   3886             # Inequality
   3887             assert_attr(small_d, big_f, '__ne__', c, None)
   3888 
   3889             assert_attr(Decimal('0.1'), 0.1, '__ne__', c, None)
   3890 
   3891             assert_attr(neg_inf_d, inf_f, '__ne__', c, None)
   3892             assert_attr(inf_d, neg_inf_f, '__ne__', c, None)
   3893 
   3894             assert_attr(Decimal('NaN'), float('nan'), '__ne__', c, None)
   3895 
   3896         def test_containers(c, signal=None):
   3897             c.clear_flags()
   3898             s = set([100.0, Decimal('100.0')])
   3899             self.assertEqual(len(s), 1)
   3900             self.assertTrue(c.flags[FloatOperation])
   3901 
   3902             c.clear_flags()
   3903             if signal:
   3904                 self.assertRaises(signal, sorted, [1.0, Decimal('10.0')])
   3905             else:
   3906                 s = sorted([10.0, Decimal('10.0')])
   3907             self.assertTrue(c.flags[FloatOperation])
   3908 
   3909             c.clear_flags()
   3910             b = 10.0 in [Decimal('10.0'), 1.0]
   3911             self.assertTrue(c.flags[FloatOperation])
   3912 
   3913             c.clear_flags()
   3914             b = 10.0 in {Decimal('10.0'):'a', 1.0:'b'}
   3915             self.assertTrue(c.flags[FloatOperation])
   3916 
   3917         nc = Context()
   3918         with localcontext(nc) as c:
   3919             self.assertFalse(c.traps[FloatOperation])
   3920             doit(c, signal=None)
   3921             test_containers(c, signal=None)
   3922 
   3923             c.traps[FloatOperation] = True
   3924             doit(c, signal=FloatOperation)
   3925             test_containers(c, signal=FloatOperation)
   3926 
   3927     def test_float_operation_default(self):
   3928         Decimal = self.decimal.Decimal
   3929         Context = self.decimal.Context
   3930         Inexact = self.decimal.Inexact
   3931         FloatOperation= self.decimal.FloatOperation
   3932 
   3933         context = Context()
   3934         self.assertFalse(context.flags[FloatOperation])
   3935         self.assertFalse(context.traps[FloatOperation])
   3936 
   3937         context.clear_traps()
   3938         context.traps[Inexact] = True
   3939         context.traps[FloatOperation] = True
   3940         self.assertTrue(context.traps[FloatOperation])
   3941         self.assertTrue(context.traps[Inexact])
   3942 
   3943 class CContextFlags(ContextFlags):
   3944     decimal = C
   3945 class PyContextFlags(ContextFlags):
   3946     decimal = P
   3947 
   3948 class SpecialContexts(unittest.TestCase):
   3949     """Test the context templates."""
   3950 
   3951     def test_context_templates(self):
   3952         BasicContext = self.decimal.BasicContext
   3953         ExtendedContext = self.decimal.ExtendedContext
   3954         getcontext = self.decimal.getcontext
   3955         setcontext = self.decimal.setcontext
   3956         InvalidOperation = self.decimal.InvalidOperation
   3957         DivisionByZero = self.decimal.DivisionByZero
   3958         Overflow = self.decimal.Overflow
   3959         Underflow = self.decimal.Underflow
   3960         Clamped = self.decimal.Clamped
   3961 
   3962         assert_signals(self, BasicContext, 'traps',
   3963             [InvalidOperation, DivisionByZero, Overflow, Underflow, Clamped]
   3964         )
   3965 
   3966         savecontext = getcontext().copy()
   3967         basic_context_prec = BasicContext.prec
   3968         extended_context_prec = ExtendedContext.prec
   3969 
   3970         ex = None
   3971         try:
   3972             BasicContext.prec = ExtendedContext.prec = 441
   3973             for template in BasicContext, ExtendedContext:
   3974                 setcontext(template)
   3975                 c = getcontext()
   3976                 self.assertIsNot(c, template)
   3977                 self.assertEqual(c.prec, 441)
   3978         except Exception as e:
   3979             ex = e.__class__
   3980         finally:
   3981             BasicContext.prec = basic_context_prec
   3982             ExtendedContext.prec = extended_context_prec
   3983             setcontext(savecontext)
   3984             if ex:
   3985                 raise ex
   3986 
   3987     def test_default_context(self):
   3988         DefaultContext = self.decimal.DefaultContext
   3989         BasicContext = self.decimal.BasicContext
   3990         ExtendedContext = self.decimal.ExtendedContext
   3991         getcontext = self.decimal.getcontext
   3992         setcontext = self.decimal.setcontext
   3993         InvalidOperation = self.decimal.InvalidOperation
   3994         DivisionByZero = self.decimal.DivisionByZero
   3995         Overflow = self.decimal.Overflow
   3996 
   3997         self.assertEqual(BasicContext.prec, 9)
   3998         self.assertEqual(ExtendedContext.prec, 9)
   3999 
   4000         assert_signals(self, DefaultContext, 'traps',
   4001             [InvalidOperation, DivisionByZero, Overflow]
   4002         )
   4003 
   4004         savecontext = getcontext().copy()
   4005         default_context_prec = DefaultContext.prec
   4006 
   4007         ex = None
   4008         try:
   4009             c = getcontext()
   4010             saveprec = c.prec
   4011 
   4012             DefaultContext.prec = 961
   4013             c = getcontext()
   4014             self.assertEqual(c.prec, saveprec)
   4015 
   4016             setcontext(DefaultContext)
   4017             c = getcontext()
   4018             self.assertIsNot(c, DefaultContext)
   4019             self.assertEqual(c.prec, 961)
   4020         except Exception as e:
   4021             ex = e.__class__
   4022         finally:
   4023             DefaultContext.prec = default_context_prec
   4024             setcontext(savecontext)
   4025             if ex:
   4026                 raise ex
   4027 
   4028 class CSpecialContexts(SpecialContexts):
   4029     decimal = C
   4030 class PySpecialContexts(SpecialContexts):
   4031     decimal = P
   4032 
   4033 class ContextInputValidation(unittest.TestCase):
   4034 
   4035     def test_invalid_context(self):
   4036         Context = self.decimal.Context
   4037         DefaultContext = self.decimal.DefaultContext
   4038 
   4039         c = DefaultContext.copy()
   4040 
   4041         # prec, Emax
   4042         for attr in ['prec', 'Emax']:
   4043             setattr(c, attr, 999999)
   4044             self.assertEqual(getattr(c, attr), 999999)
   4045             self.assertRaises(ValueError, setattr, c, attr, -1)
   4046             self.assertRaises(TypeError, setattr, c, attr, 'xyz')
   4047 
   4048         # Emin
   4049         setattr(c, 'Emin', -999999)
   4050         self.assertEqual(getattr(c, 'Emin'), -999999)
   4051         self.assertRaises(ValueError, setattr, c, 'Emin', 1)
   4052         self.assertRaises(TypeError, setattr, c, 'Emin', (1,2,3))
   4053 
   4054         self.assertRaises(TypeError, setattr, c, 'rounding', -1)
   4055         self.assertRaises(TypeError, setattr, c, 'rounding', 9)
   4056         self.assertRaises(TypeError, setattr, c, 'rounding', 1.0)
   4057         self.assertRaises(TypeError, setattr, c, 'rounding', 'xyz')
   4058 
   4059         # capitals, clamp
   4060         for attr in ['capitals', 'clamp']:
   4061             self.assertRaises(ValueError, setattr, c, attr, -1)
   4062             self.assertRaises(ValueError, setattr, c, attr, 2)
   4063             self.assertRaises(TypeError, setattr, c, attr, [1,2,3])
   4064 
   4065         # Invalid attribute
   4066         self.assertRaises(AttributeError, setattr, c, 'emax', 100)
   4067 
   4068         # Invalid signal dict
   4069         self.assertRaises(TypeError, setattr, c, 'flags', [])
   4070         self.assertRaises(KeyError, setattr, c, 'flags', {})
   4071         self.assertRaises(KeyError, setattr, c, 'traps',
   4072                           {'InvalidOperation':0})
   4073 
   4074         # Attributes cannot be deleted
   4075         for attr in ['prec', 'Emax', 'Emin', 'rounding', 'capitals', 'clamp',
   4076                      'flags', 'traps']:
   4077             self.assertRaises(AttributeError, c.__delattr__, attr)
   4078 
   4079         # Invalid attributes
   4080         self.assertRaises(TypeError, getattr, c, 9)
   4081         self.assertRaises(TypeError, setattr, c, 9)
   4082 
   4083         # Invalid values in constructor
   4084         self.assertRaises(TypeError, Context, rounding=999999)
   4085         self.assertRaises(TypeError, Context, rounding='xyz')
   4086         self.assertRaises(ValueError, Context, clamp=2)
   4087         self.assertRaises(ValueError, Context, capitals=-1)
   4088         self.assertRaises(KeyError, Context, flags=["P"])
   4089         self.assertRaises(KeyError, Context, traps=["Q"])
   4090 
   4091         # Type error in conversion
   4092         self.assertRaises(TypeError, Context, flags=(0,1))
   4093         self.assertRaises(TypeError, Context, traps=(1,0))
   4094 
   4095 class CContextInputValidation(ContextInputValidation):
   4096     decimal = C
   4097 class PyContextInputValidation(ContextInputValidation):
   4098     decimal = P
   4099 
   4100 class ContextSubclassing(unittest.TestCase):
   4101 
   4102     def test_context_subclassing(self):
   4103         decimal = self.decimal
   4104         Decimal = decimal.Decimal
   4105         Context = decimal.Context
   4106         Clamped = decimal.Clamped
   4107         DivisionByZero = decimal.DivisionByZero
   4108         Inexact = decimal.Inexact
   4109         Overflow = decimal.Overflow
   4110         Rounded = decimal.Rounded
   4111         Subnormal = decimal.Subnormal
   4112         Underflow = decimal.Underflow
   4113         InvalidOperation = decimal.InvalidOperation
   4114 
   4115         class MyContext(Context):
   4116             def __init__(self, prec=None, rounding=None, Emin=None, Emax=None,
   4117                                capitals=None, clamp=None, flags=None,
   4118                                traps=None):
   4119                 Context.__init__(self)
   4120                 if prec is not None:
   4121                     self.prec = prec
   4122                 if rounding is not None:
   4123                     self.rounding = rounding
   4124                 if Emin is not None:
   4125                     self.Emin = Emin
   4126                 if Emax is not None:
   4127                     self.Emax = Emax
   4128                 if capitals is not None:
   4129                     self.capitals = capitals
   4130                 if clamp is not None:
   4131                     self.clamp = clamp
   4132                 if flags is not None:
   4133                     if isinstance(flags, list):
   4134                         flags = {v:(v in flags) for v in OrderedSignals[decimal] + flags}
   4135                     self.flags = flags
   4136                 if traps is not None:
   4137                     if isinstance(traps, list):
   4138                         traps = {v:(v in traps) for v in OrderedSignals[decimal] + traps}
   4139                     self.traps = traps
   4140 
   4141         c = Context()
   4142         d = MyContext()
   4143         for attr in ('prec', 'rounding', 'Emin', 'Emax', 'capitals', 'clamp',
   4144                      'flags', 'traps'):
   4145             self.assertEqual(getattr(c, attr), getattr(d, attr))
   4146 
   4147         # prec
   4148         self.assertRaises(ValueError, MyContext, **{'prec':-1})
   4149         c = MyContext(prec=1)
   4150         self.assertEqual(c.prec, 1)
   4151         self.assertRaises(InvalidOperation, c.quantize, Decimal('9e2'), 0)
   4152 
   4153         # rounding
   4154         self.assertRaises(TypeError, MyContext, **{'rounding':'XYZ'})
   4155         c = MyContext(rounding=ROUND_DOWN, prec=1)
   4156         self.assertEqual(c.rounding, ROUND_DOWN)
   4157         self.assertEqual(c.plus(Decimal('9.9')), 9)
   4158 
   4159         # Emin
   4160         self.assertRaises(ValueError, MyContext, **{'Emin':5})
   4161         c = MyContext(Emin=-1, prec=1)
   4162         self.assertEqual(c.Emin, -1)
   4163         x = c.add(Decimal('1e-99'), Decimal('2.234e-2000'))
   4164         self.assertEqual(x, Decimal('0.0'))
   4165         for signal in (Inexact, Underflow, Subnormal, Rounded, Clamped):
   4166             self.assertTrue(c.flags[signal])
   4167 
   4168         # Emax
   4169         self.assertRaises(ValueError, MyContext, **{'Emax':-1})
   4170         c = MyContext(Emax=1, prec=1)
   4171         self.assertEqual(c.Emax, 1)
   4172         self.assertRaises(Overflow, c.add, Decimal('1e99'), Decimal('2.234e2000'))
   4173         if self.decimal == C:
   4174             for signal in (Inexact, Overflow, Rounded):
   4175                 self.assertTrue(c.flags[signal])
   4176 
   4177         # capitals
   4178         self.assertRaises(ValueError, MyContext, **{'capitals':-1})
   4179         c = MyContext(capitals=0)
   4180         self.assertEqual(c.capitals, 0)
   4181         x = c.create_decimal('1E222')
   4182         self.assertEqual(c.to_sci_string(x), '1e+222')
   4183 
   4184         # clamp
   4185         self.assertRaises(ValueError, MyContext, **{'clamp':2})
   4186         c = MyContext(clamp=1, Emax=99)
   4187         self.assertEqual(c.clamp, 1)
   4188         x = c.plus(Decimal('1e99'))
   4189         self.assertEqual(str(x), '1.000000000000000000000000000E+99')
   4190 
   4191         # flags
   4192         self.assertRaises(TypeError, MyContext, **{'flags':'XYZ'})
   4193         c = MyContext(flags=[Rounded, DivisionByZero])
   4194         for signal in (Rounded, DivisionByZero):
   4195             self.assertTrue(c.flags[signal])
   4196         c.clear_flags()
   4197         for signal in OrderedSignals[decimal]:
   4198             self.assertFalse(c.flags[signal])
   4199 
   4200         # traps
   4201         self.assertRaises(TypeError, MyContext, **{'traps':'XYZ'})
   4202         c = MyContext(traps=[Rounded, DivisionByZero])
   4203         for signal in (Rounded, DivisionByZero):
   4204             self.assertTrue(c.traps[signal])
   4205         c.clear_traps()
   4206         for signal in OrderedSignals[decimal]:
   4207             self.assertFalse(c.traps[signal])
   4208 
   4209 class CContextSubclassing(ContextSubclassing):
   4210     decimal = C
   4211 class PyContextSubclassing(ContextSubclassing):
   4212     decimal = P
   4213 
   4214 @skip_if_extra_functionality
   4215 class CheckAttributes(unittest.TestCase):
   4216 
   4217     def test_module_attributes(self):
   4218 
   4219         # Architecture dependent context limits
   4220         self.assertEqual(C.MAX_PREC, P.MAX_PREC)
   4221         self.assertEqual(C.MAX_EMAX, P.MAX_EMAX)
   4222         self.assertEqual(C.MIN_EMIN, P.MIN_EMIN)
   4223         self.assertEqual(C.MIN_ETINY, P.MIN_ETINY)
   4224 
   4225         self.assertTrue(C.HAVE_THREADS is True or C.HAVE_THREADS is False)
   4226         self.assertTrue(P.HAVE_THREADS is True or P.HAVE_THREADS is False)
   4227 
   4228         self.assertEqual(C.__version__, P.__version__)
   4229 
   4230         self.assertEqual(dir(C), dir(P))
   4231 
   4232     def test_context_attributes(self):
   4233 
   4234         x = [s for s in dir(C.Context()) if '__' in s or not s.startswith('_')]
   4235         y = [s for s in dir(P.Context()) if '__' in s or not s.startswith('_')]
   4236         self.assertEqual(set(x) - set(y), set())
   4237 
   4238     def test_decimal_attributes(self):
   4239 
   4240         x = [s for s in dir(C.Decimal(9)) if '__' in s or not s.startswith('_')]
   4241         y = [s for s in dir(C.Decimal(9)) if '__' in s or not s.startswith('_')]
   4242         self.assertEqual(set(x) - set(y), set())
   4243 
   4244 class Coverage(unittest.TestCase):
   4245 
   4246     def test_adjusted(self):
   4247         Decimal = self.decimal.Decimal
   4248 
   4249         self.assertEqual(Decimal('1234e9999').adjusted(), 10002)
   4250         # XXX raise?
   4251         self.assertEqual(Decimal('nan').adjusted(), 0)
   4252         self.assertEqual(Decimal('inf').adjusted(), 0)
   4253 
   4254     def test_canonical(self):
   4255         Decimal = self.decimal.Decimal
   4256         getcontext = self.decimal.getcontext
   4257 
   4258         x = Decimal(9).canonical()
   4259         self.assertEqual(x, 9)
   4260 
   4261         c = getcontext()
   4262         x = c.canonical(Decimal(9))
   4263         self.assertEqual(x, 9)
   4264 
   4265     def test_context_repr(self):
   4266         c = self.decimal.DefaultContext.copy()
   4267 
   4268         c.prec = 425000000
   4269         c.Emax = 425000000
   4270         c.Emin = -425000000
   4271         c.rounding = ROUND_HALF_DOWN
   4272         c.capitals = 0
   4273         c.clamp = 1
   4274         for sig in OrderedSignals[self.decimal]:
   4275             c.flags[sig] = False
   4276             c.traps[sig] = False
   4277 
   4278         s = c.__repr__()
   4279         t = "Context(prec=425000000, rounding=ROUND_HALF_DOWN, " \
   4280             "Emin=-425000000, Emax=425000000, capitals=0, clamp=1, " \
   4281             "flags=[], traps=[])"
   4282         self.assertEqual(s, t)
   4283 
   4284     def test_implicit_context(self):
   4285         Decimal = self.decimal.Decimal
   4286         localcontext = self.decimal.localcontext
   4287 
   4288         with localcontext() as c:
   4289             c.prec = 1
   4290             c.Emax = 1
   4291             c.Emin = -1
   4292 
   4293             # abs
   4294             self.assertEqual(abs(Decimal("-10")), 10)
   4295             # add
   4296             self.assertEqual(Decimal("7") + 1, 8)
   4297             # divide
   4298             self.assertEqual(Decimal("10") / 5, 2)
   4299             # divide_int
   4300             self.assertEqual(Decimal("10") // 7, 1)
   4301             # fma
   4302             self.assertEqual(Decimal("1.2").fma(Decimal("0.01"), 1), 1)
   4303             self.assertIs(Decimal("NaN").fma(7, 1).is_nan(), True)
   4304             # three arg power
   4305             self.assertEqual(pow(Decimal(10), 2, 7), 2)
   4306             # exp
   4307             self.assertEqual(Decimal("1.01").exp(), 3)
   4308             # is_normal
   4309             self.assertIs(Decimal("0.01").is_normal(), False)
   4310             # is_subnormal
   4311             self.assertIs(Decimal("0.01").is_subnormal(), True)
   4312             # ln
   4313             self.assertEqual(Decimal("20").ln(), 3)
   4314             # log10
   4315             self.assertEqual(Decimal("20").log10(), 1)
   4316             # logb
   4317             self.assertEqual(Decimal("580").logb(), 2)
   4318             # logical_invert
   4319             self.assertEqual(Decimal("10").logical_invert(), 1)
   4320             # minus
   4321             self.assertEqual(-Decimal("-10"), 10)
   4322             # multiply
   4323             self.assertEqual(Decimal("2") * 4, 8)
   4324             # next_minus
   4325             self.assertEqual(Decimal("10").next_minus(), 9)
   4326             # next_plus
   4327             self.assertEqual(Decimal("10").next_plus(), Decimal('2E+1'))
   4328             # normalize
   4329             self.assertEqual(Decimal("-10").normalize(), Decimal('-1E+1'))
   4330             # number_class
   4331             self.assertEqual(Decimal("10").number_class(), '+Normal')
   4332             # plus
   4333             self.assertEqual(+Decimal("-1"), -1)
   4334             # remainder
   4335             self.assertEqual(Decimal("10") % 7, 3)
   4336             # subtract
   4337             self.assertEqual(Decimal("10") - 7, 3)
   4338             # to_integral_exact
   4339             self.assertEqual(Decimal("1.12345").to_integral_exact(), 1)
   4340 
   4341             # Boolean functions
   4342             self.assertTrue(Decimal("1").is_canonical())
   4343             self.assertTrue(Decimal("1").is_finite())
   4344             self.assertTrue(Decimal("1").is_finite())
   4345             self.assertTrue(Decimal("snan").is_snan())
   4346             self.assertTrue(Decimal("-1").is_signed())
   4347             self.assertTrue(Decimal("0").is_zero())
   4348             self.assertTrue(Decimal("0").is_zero())
   4349 
   4350         # Copy
   4351         with localcontext() as c:
   4352             c.prec = 10000
   4353             x = 1228 ** 1523
   4354             y = -Decimal(x)
   4355 
   4356             z = y.copy_abs()
   4357             self.assertEqual(z, x)
   4358 
   4359             z = y.copy_negate()
   4360             self.assertEqual(z, x)
   4361 
   4362             z = y.copy_sign(Decimal(1))
   4363             self.assertEqual(z, x)
   4364 
   4365     def test_divmod(self):
   4366         Decimal = self.decimal.Decimal
   4367         localcontext = self.decimal.localcontext
   4368         InvalidOperation = self.decimal.InvalidOperation
   4369         DivisionByZero = self.decimal.DivisionByZero
   4370 
   4371         with localcontext() as c:
   4372             q, r = divmod(Decimal("10912837129"), 1001)
   4373             self.assertEqual(q, Decimal('10901935'))
   4374             self.assertEqual(r, Decimal('194'))
   4375 
   4376             q, r = divmod(Decimal("NaN"), 7)
   4377             self.assertTrue(q.is_nan() and r.is_nan())
   4378 
   4379             c.traps[InvalidOperation] = False
   4380             q, r = divmod(Decimal("NaN"), 7)
   4381             self.assertTrue(q.is_nan() and r.is_nan())
   4382 
   4383             c.traps[InvalidOperation] = False
   4384             c.clear_flags()
   4385             q, r = divmod(Decimal("inf"), Decimal("inf"))
   4386             self.assertTrue(q.is_nan() and r.is_nan())
   4387             self.assertTrue(c.flags[InvalidOperation])
   4388 
   4389             c.clear_flags()
   4390             q, r = divmod(Decimal("inf"), 101)
   4391             self.assertTrue(q.is_infinite() and r.is_nan())
   4392             self.assertTrue(c.flags[InvalidOperation])
   4393 
   4394             c.clear_flags()
   4395             q, r = divmod(Decimal(0), 0)
   4396             self.assertTrue(q.is_nan() and r.is_nan())
   4397             self.assertTrue(c.flags[InvalidOperation])
   4398 
   4399             c.traps[DivisionByZero] = False
   4400             c.clear_flags()
   4401             q, r = divmod(Decimal(11), 0)
   4402             self.assertTrue(q.is_infinite() and r.is_nan())
   4403             self.assertTrue(c.flags[InvalidOperation] and
   4404                             c.flags[DivisionByZero])
   4405 
   4406     def test_power(self):
   4407         Decimal = self.decimal.Decimal
   4408         localcontext = self.decimal.localcontext
   4409         Overflow = self.decimal.Overflow
   4410         Rounded = self.decimal.Rounded
   4411 
   4412         with localcontext() as c:
   4413             c.prec = 3
   4414             c.clear_flags()
   4415             self.assertEqual(Decimal("1.0") ** 100, Decimal('1.00'))
   4416             self.assertTrue(c.flags[Rounded])
   4417 
   4418             c.prec = 1
   4419             c.Emax = 1
   4420             c.Emin = -1
   4421             c.clear_flags()
   4422             c.traps[Overflow] = False
   4423             self.assertEqual(Decimal(10000) ** Decimal("0.5"), Decimal('inf'))
   4424             self.assertTrue(c.flags[Overflow])
   4425 
   4426     def test_quantize(self):
   4427         Decimal = self.decimal.Decimal
   4428         localcontext = self.decimal.localcontext
   4429         InvalidOperation = self.decimal.InvalidOperation
   4430 
   4431         with localcontext() as c:
   4432             c.prec = 1
   4433             c.Emax = 1
   4434             c.Emin = -1
   4435             c.traps[InvalidOperation] = False
   4436             x = Decimal(99).quantize(Decimal("1e1"))
   4437             self.assertTrue(x.is_nan())
   4438 
   4439     def test_radix(self):
   4440         Decimal = self.decimal.Decimal
   4441         getcontext = self.decimal.getcontext
   4442 
   4443         c = getcontext()
   4444         self.assertEqual(Decimal("1").radix(), 10)
   4445         self.assertEqual(c.radix(), 10)
   4446 
   4447     def test_rop(self):
   4448         Decimal = self.decimal.Decimal
   4449 
   4450         for attr in ('__radd__', '__rsub__', '__rmul__', '__rtruediv__',
   4451                      '__rdivmod__', '__rmod__', '__rfloordiv__', '__rpow__'):
   4452             self.assertIs(getattr(Decimal("1"), attr)("xyz"), NotImplemented)
   4453 
   4454     def test_round(self):
   4455         # Python3 behavior: round() returns Decimal
   4456         Decimal = self.decimal.Decimal
   4457         localcontext = self.decimal.localcontext
   4458 
   4459         with localcontext() as c:
   4460             c.prec = 28
   4461 
   4462             self.assertEqual(str(Decimal("9.99").__round__()), "10")
   4463             self.assertEqual(str(Decimal("9.99e-5").__round__()), "0")
   4464             self.assertEqual(str(Decimal("1.23456789").__round__(5)), "1.23457")
   4465             self.assertEqual(str(Decimal("1.2345").__round__(10)), "1.2345000000")
   4466             self.assertEqual(str(Decimal("1.2345").__round__(-10)), "0E+10")
   4467 
   4468             self.assertRaises(TypeError, Decimal("1.23").__round__, "5")
   4469             self.assertRaises(TypeError, Decimal("1.23").__round__, 5, 8)
   4470 
   4471     def test_create_decimal(self):
   4472         c = self.decimal.Context()
   4473         self.assertRaises(ValueError, c.create_decimal, ["%"])
   4474 
   4475     def test_int(self):
   4476         Decimal = self.decimal.Decimal
   4477         localcontext = self.decimal.localcontext
   4478 
   4479         with localcontext() as c:
   4480             c.prec = 9999
   4481             x = Decimal(1221**1271) / 10**3923
   4482             self.assertEqual(int(x), 1)
   4483             self.assertEqual(x.to_integral(), 2)
   4484 
   4485     def test_copy(self):
   4486         Context = self.decimal.Context
   4487 
   4488         c = Context()
   4489         c.prec = 10000
   4490         x = -(1172 ** 1712)
   4491 
   4492         y = c.copy_abs(x)
   4493         self.assertEqual(y, -x)
   4494 
   4495         y = c.copy_negate(x)
   4496         self.assertEqual(y, -x)
   4497 
   4498         y = c.copy_sign(x, 1)
   4499         self.assertEqual(y, -x)
   4500 
   4501 class CCoverage(Coverage):
   4502     decimal = C
   4503 class PyCoverage(Coverage):
   4504     decimal = P
   4505 
   4506 class PyFunctionality(unittest.TestCase):
   4507     """Extra functionality in decimal.py"""
   4508 
   4509     def test_py_alternate_formatting(self):
   4510         # triples giving a format, a Decimal, and the expected result
   4511         Decimal = P.Decimal
   4512         localcontext = P.localcontext
   4513 
   4514         test_values = [
   4515             # Issue 7094: Alternate formatting (specified by #)
   4516             ('.0e', '1.0', '1e+0'),
   4517             ('#.0e', '1.0', '1.e+0'),
   4518             ('.0f', '1.0', '1'),
   4519             ('#.0f', '1.0', '1.'),
   4520             ('g', '1.1', '1.1'),
   4521             ('#g', '1.1', '1.1'),
   4522             ('.0g', '1', '1'),
   4523             ('#.0g', '1', '1.'),
   4524             ('.0%', '1.0', '100%'),
   4525             ('#.0%', '1.0', '100.%'),
   4526             ]
   4527         for fmt, d, result in test_values:
   4528             self.assertEqual(format(Decimal(d), fmt), result)
   4529 
   4530 class PyWhitebox(unittest.TestCase):
   4531     """White box testing for decimal.py"""
   4532 
   4533     def test_py_exact_power(self):
   4534         # Rarely exercised lines in _power_exact.
   4535         Decimal = P.Decimal
   4536         localcontext = P.localcontext
   4537 
   4538         with localcontext() as c:
   4539             c.prec = 8
   4540             x = Decimal(2**16) ** Decimal("-0.5")
   4541             self.assertEqual(x, Decimal('0.00390625'))
   4542 
   4543             x = Decimal(2**16) ** Decimal("-0.6")
   4544             self.assertEqual(x, Decimal('0.0012885819'))
   4545 
   4546             x = Decimal("256e7") ** Decimal("-0.5")
   4547 
   4548             x = Decimal(152587890625) ** Decimal('-0.0625')
   4549             self.assertEqual(x, Decimal("0.2"))
   4550 
   4551             x = Decimal("152587890625e7") ** Decimal('-0.0625')
   4552 
   4553             x = Decimal(5**2659) ** Decimal('-0.0625')
   4554 
   4555             c.prec = 1
   4556             x = Decimal("152587890625") ** Decimal('-0.5')
   4557             c.prec = 201
   4558             x = Decimal(2**578) ** Decimal("-0.5")
   4559 
   4560     def test_py_immutability_operations(self):
   4561         # Do operations and check that it didn't change internal objects.
   4562         Decimal = P.Decimal
   4563         DefaultContext = P.DefaultContext
   4564         setcontext = P.setcontext
   4565 
   4566         c = DefaultContext.copy()
   4567         c.traps = dict((s, 0) for s in OrderedSignals[P])
   4568         setcontext(c)
   4569 
   4570         d1 = Decimal('-25e55')
   4571         b1 = Decimal('-25e55')
   4572         d2 = Decimal('33e+33')
   4573         b2 = Decimal('33e+33')
   4574 
   4575         def checkSameDec(operation, useOther=False):
   4576             if useOther:
   4577                 eval("d1." + operation + "(d2)")
   4578                 self.assertEqual(d1._sign, b1._sign)
   4579                 self.assertEqual(d1._int, b1._int)
   4580                 self.assertEqual(d1._exp, b1._exp)
   4581                 self.assertEqual(d2._sign, b2._sign)
   4582                 self.assertEqual(d2._int, b2._int)
   4583                 self.assertEqual(d2._exp, b2._exp)
   4584             else:
   4585                 eval("d1." + operation + "()")
   4586                 self.assertEqual(d1._sign, b1._sign)
   4587                 self.assertEqual(d1._int, b1._int)
   4588                 self.assertEqual(d1._exp, b1._exp)
   4589 
   4590         Decimal(d1)
   4591         self.assertEqual(d1._sign, b1._sign)
   4592         self.assertEqual(d1._int, b1._int)
   4593         self.assertEqual(d1._exp, b1._exp)
   4594 
   4595         checkSameDec("__abs__")
   4596         checkSameDec("__add__", True)
   4597         checkSameDec("__divmod__", True)
   4598         checkSameDec("__eq__", True)
   4599         checkSameDec("__ne__", True)
   4600         checkSameDec("__le__", True)
   4601         checkSameDec("__lt__", True)
   4602         checkSameDec("__ge__", True)
   4603         checkSameDec("__gt__", True)
   4604         checkSameDec("__float__")
   4605         checkSameDec("__floordiv__", True)
   4606         checkSameDec("__hash__")
   4607         checkSameDec("__int__")
   4608         checkSameDec("__trunc__")
   4609         checkSameDec("__mod__", True)
   4610         checkSameDec("__mul__", True)
   4611         checkSameDec("__neg__")
   4612         checkSameDec("__bool__")
   4613         checkSameDec("__pos__")
   4614         checkSameDec("__pow__", True)
   4615         checkSameDec("__radd__", True)
   4616         checkSameDec("__rdivmod__", True)
   4617         checkSameDec("__repr__")
   4618         checkSameDec("__rfloordiv__", True)
   4619         checkSameDec("__rmod__", True)
   4620         checkSameDec("__rmul__", True)
   4621         checkSameDec("__rpow__", True)
   4622         checkSameDec("__rsub__", True)
   4623         checkSameDec("__str__")
   4624         checkSameDec("__sub__", True)
   4625         checkSameDec("__truediv__", True)
   4626         checkSameDec("adjusted")
   4627         checkSameDec("as_tuple")
   4628         checkSameDec("compare", True)
   4629         checkSameDec("max", True)
   4630         checkSameDec("min", True)
   4631         checkSameDec("normalize")
   4632         checkSameDec("quantize", True)
   4633         checkSameDec("remainder_near", True)
   4634         checkSameDec("same_quantum", True)
   4635         checkSameDec("sqrt")
   4636         checkSameDec("to_eng_string")
   4637         checkSameDec("to_integral")
   4638 
   4639     def test_py_decimal_id(self):
   4640         Decimal = P.Decimal
   4641 
   4642         d = Decimal(45)
   4643         e = Decimal(d)
   4644         self.assertEqual(str(e), '45')
   4645         self.assertNotEqual(id(d), id(e))
   4646 
   4647     def test_py_rescale(self):
   4648         # Coverage
   4649         Decimal = P.Decimal
   4650         localcontext = P.localcontext
   4651 
   4652         with localcontext() as c:
   4653             x = Decimal("NaN")._rescale(3, ROUND_UP)
   4654             self.assertTrue(x.is_nan())
   4655 
   4656     def test_py__round(self):
   4657         # Coverage
   4658         Decimal = P.Decimal
   4659 
   4660         self.assertRaises(ValueError, Decimal("3.1234")._round, 0, ROUND_UP)
   4661 
   4662 class CFunctionality(unittest.TestCase):
   4663     """Extra functionality in _decimal"""
   4664 
   4665     @requires_extra_functionality
   4666     def test_c_ieee_context(self):
   4667         # issue 8786: Add support for IEEE 754 contexts to decimal module.
   4668         IEEEContext = C.IEEEContext
   4669         DECIMAL32 = C.DECIMAL32
   4670         DECIMAL64 = C.DECIMAL64
   4671         DECIMAL128 = C.DECIMAL128
   4672 
   4673         def assert_rest(self, context):
   4674             self.assertEqual(context.clamp, 1)
   4675             assert_signals(self, context, 'traps', [])
   4676             assert_signals(self, context, 'flags', [])
   4677 
   4678         c = IEEEContext(DECIMAL32)
   4679         self.assertEqual(c.prec, 7)
   4680         self.assertEqual(c.Emax, 96)
   4681         self.assertEqual(c.Emin, -95)
   4682         assert_rest(self, c)
   4683 
   4684         c = IEEEContext(DECIMAL64)
   4685         self.assertEqual(c.prec, 16)
   4686         self.assertEqual(c.Emax, 384)
   4687         self.assertEqual(c.Emin, -383)
   4688         assert_rest(self, c)
   4689 
   4690         c = IEEEContext(DECIMAL128)
   4691         self.assertEqual(c.prec, 34)
   4692         self.assertEqual(c.Emax, 6144)
   4693         self.assertEqual(c.Emin, -6143)
   4694         assert_rest(self, c)
   4695 
   4696         # Invalid values
   4697         self.assertRaises(OverflowError, IEEEContext, 2**63)
   4698         self.assertRaises(ValueError, IEEEContext, -1)
   4699         self.assertRaises(ValueError, IEEEContext, 1024)
   4700 
   4701     @requires_extra_functionality
   4702     def test_c_context(self):
   4703         Context = C.Context
   4704 
   4705         c = Context(flags=C.DecClamped, traps=C.DecRounded)
   4706         self.assertEqual(c._flags, C.DecClamped)
   4707         self.assertEqual(c._traps, C.DecRounded)
   4708 
   4709     @requires_extra_functionality
   4710     def test_constants(self):
   4711         # Condition flags
   4712         cond = (
   4713             C.DecClamped, C.DecConversionSyntax, C.DecDivisionByZero,
   4714             C.DecDivisionImpossible, C.DecDivisionUndefined,
   4715             C.DecFpuError, C.DecInexact, C.DecInvalidContext,
   4716             C.DecInvalidOperation, C.DecMallocError,
   4717             C.DecFloatOperation, C.DecOverflow, C.DecRounded,
   4718             C.DecSubnormal, C.DecUnderflow
   4719         )
   4720 
   4721         # IEEEContext
   4722         self.assertEqual(C.DECIMAL32, 32)
   4723         self.assertEqual(C.DECIMAL64, 64)
   4724         self.assertEqual(C.DECIMAL128, 128)
   4725         self.assertEqual(C.IEEE_CONTEXT_MAX_BITS, 512)
   4726 
   4727         # Conditions
   4728         for i, v in enumerate(cond):
   4729             self.assertEqual(v, 1<<i)
   4730 
   4731         self.assertEqual(C.DecIEEEInvalidOperation,
   4732                          C.DecConversionSyntax|
   4733                          C.DecDivisionImpossible|
   4734                          C.DecDivisionUndefined|
   4735                          C.DecFpuError|
   4736                          C.DecInvalidContext|
   4737                          C.DecInvalidOperation|
   4738                          C.DecMallocError)
   4739 
   4740         self.assertEqual(C.DecErrors,
   4741                          C.DecIEEEInvalidOperation|
   4742                          C.DecDivisionByZero)
   4743 
   4744         self.assertEqual(C.DecTraps,
   4745                          C.DecErrors|C.DecOverflow|C.DecUnderflow)
   4746 
   4747 class CWhitebox(unittest.TestCase):
   4748     """Whitebox testing for _decimal"""
   4749 
   4750     def test_bignum(self):
   4751         # Not exactly whitebox, but too slow with pydecimal.
   4752 
   4753         Decimal = C.Decimal
   4754         localcontext = C.localcontext
   4755 
   4756         b1 = 10**35
   4757         b2 = 10**36
   4758         with localcontext() as c:
   4759             c.prec = 1000000
   4760             for i in range(5):
   4761                 a = random.randrange(b1, b2)
   4762                 b = random.randrange(1000, 1200)
   4763                 x = a ** b
   4764                 y = Decimal(a) ** Decimal(b)
   4765                 self.assertEqual(x, y)
   4766 
   4767     def test_invalid_construction(self):
   4768         self.assertRaises(TypeError, C.Decimal, 9, "xyz")
   4769 
   4770     def test_c_input_restriction(self):
   4771         # Too large for _decimal to be converted exactly
   4772         Decimal = C.Decimal
   4773         InvalidOperation = C.InvalidOperation
   4774         Context = C.Context
   4775         localcontext = C.localcontext
   4776 
   4777         with localcontext(Context()):
   4778             self.assertRaises(InvalidOperation, Decimal,
   4779                               "1e9999999999999999999")
   4780 
   4781     def test_c_context_repr(self):
   4782         # This test is _decimal-only because flags are not printed
   4783         # in the same order.
   4784         DefaultContext = C.DefaultContext
   4785         FloatOperation = C.FloatOperation
   4786 
   4787         c = DefaultContext.copy()
   4788 
   4789         c.prec = 425000000
   4790         c.Emax = 425000000
   4791         c.Emin = -425000000
   4792         c.rounding = ROUND_HALF_DOWN
   4793         c.capitals = 0
   4794         c.clamp = 1
   4795         for sig in OrderedSignals[C]:
   4796             c.flags[sig] = True
   4797             c.traps[sig] = True
   4798         c.flags[FloatOperation] = True
   4799         c.traps[FloatOperation] = True
   4800 
   4801         s = c.__repr__()
   4802         t = "Context(prec=425000000, rounding=ROUND_HALF_DOWN, " \
   4803             "Emin=-425000000, Emax=425000000, capitals=0, clamp=1, " \
   4804             "flags=[Clamped, InvalidOperation, DivisionByZero, Inexact, " \
   4805                    "FloatOperation, Overflow, Rounded, Subnormal, Underflow], " \
   4806             "traps=[Clamped, InvalidOperation, DivisionByZero, Inexact, " \
   4807                    "FloatOperation, Overflow, Rounded, Subnormal, Underflow])"
   4808         self.assertEqual(s, t)
   4809 
   4810     def test_c_context_errors(self):
   4811         Context = C.Context
   4812         InvalidOperation = C.InvalidOperation
   4813         Overflow = C.Overflow
   4814         FloatOperation = C.FloatOperation
   4815         localcontext = C.localcontext
   4816         getcontext = C.getcontext
   4817         setcontext = C.setcontext
   4818         HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
   4819 
   4820         c = Context()
   4821 
   4822         # SignalDict: input validation
   4823         self.assertRaises(KeyError, c.flags.__setitem__, 801, 0)
   4824         self.assertRaises(KeyError, c.traps.__setitem__, 801, 0)
   4825         self.assertRaises(ValueError, c.flags.__delitem__, Overflow)
   4826         self.assertRaises(ValueError, c.traps.__delitem__, InvalidOperation)
   4827         self.assertRaises(TypeError, setattr, c, 'flags', ['x'])
   4828         self.assertRaises(TypeError, setattr, c,'traps', ['y'])
   4829         self.assertRaises(KeyError, setattr, c, 'flags', {0:1})
   4830         self.assertRaises(KeyError, setattr, c, 'traps', {0:1})
   4831 
   4832         # Test assignment from a signal dict with the correct length but
   4833         # one invalid key.
   4834         d = c.flags.copy()
   4835         del d[FloatOperation]
   4836         d["XYZ"] = 91283719
   4837         self.assertRaises(KeyError, setattr, c, 'flags', d)
   4838         self.assertRaises(KeyError, setattr, c, 'traps', d)
   4839 
   4840         # Input corner cases
   4841         int_max = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
   4842         gt_max_emax = 10**18 if HAVE_CONFIG_64 else 10**9
   4843 
   4844         # prec, Emax, Emin
   4845         for attr in ['prec', 'Emax']:
   4846             self.assertRaises(ValueError, setattr, c, attr, gt_max_emax)
   4847         self.assertRaises(ValueError, setattr, c, 'Emin', -gt_max_emax)
   4848 
   4849         # prec, Emax, Emin in context constructor
   4850         self.assertRaises(ValueError, Context, prec=gt_max_emax)
   4851         self.assertRaises(ValueError, Context, Emax=gt_max_emax)
   4852         self.assertRaises(ValueError, Context, Emin=-gt_max_emax)
   4853 
   4854         # Overflow in conversion
   4855         self.assertRaises(OverflowError, Context, prec=int_max+1)
   4856         self.assertRaises(OverflowError, Context, Emax=int_max+1)
   4857         self.assertRaises(OverflowError, Context, Emin=-int_max-2)
   4858         self.assertRaises(OverflowError, Context, clamp=int_max+1)
   4859         self.assertRaises(OverflowError, Context, capitals=int_max+1)
   4860 
   4861         # OverflowError, general ValueError
   4862         for attr in ('prec', 'Emin', 'Emax', 'capitals', 'clamp'):
   4863             self.assertRaises(OverflowError, setattr, c, attr, int_max+1)
   4864             self.assertRaises(OverflowError, setattr, c, attr, -int_max-2)
   4865             if sys.platform != 'win32':
   4866                 self.assertRaises(ValueError, setattr, c, attr, int_max)
   4867                 self.assertRaises(ValueError, setattr, c, attr, -int_max-1)
   4868 
   4869         # OverflowError: _unsafe_setprec, _unsafe_setemin, _unsafe_setemax
   4870         if C.MAX_PREC == 425000000:
   4871             self.assertRaises(OverflowError, getattr(c, '_unsafe_setprec'),
   4872                               int_max+1)
   4873             self.assertRaises(OverflowError, getattr(c, '_unsafe_setemax'),
   4874                               int_max+1)
   4875             self.assertRaises(OverflowError, getattr(c, '_unsafe_setemin'),
   4876                               -int_max-2)
   4877 
   4878         # ValueError: _unsafe_setprec, _unsafe_setemin, _unsafe_setemax
   4879         if C.MAX_PREC == 425000000:
   4880             self.assertRaises(ValueError, getattr(c, '_unsafe_setprec'), 0)
   4881             self.assertRaises(ValueError, getattr(c, '_unsafe_setprec'),
   4882                               1070000001)
   4883             self.assertRaises(ValueError, getattr(c, '_unsafe_setemax'), -1)
   4884             self.assertRaises(ValueError, getattr(c, '_unsafe_setemax'),
   4885                               1070000001)
   4886             self.assertRaises(ValueError, getattr(c, '_unsafe_setemin'),
   4887                               -1070000001)
   4888             self.assertRaises(ValueError, getattr(c, '_unsafe_setemin'), 1)
   4889 
   4890         # capitals, clamp
   4891         for attr in ['capitals', 'clamp']:
   4892             self.assertRaises(ValueError, setattr, c, attr, -1)
   4893             self.assertRaises(ValueError, setattr, c, attr, 2)
   4894             self.assertRaises(TypeError, setattr, c, attr, [1,2,3])
   4895             if HAVE_CONFIG_64:
   4896                 self.assertRaises(ValueError, setattr, c, attr, 2**32)
   4897                 self.assertRaises(ValueError, setattr, c, attr, 2**32+1)
   4898 
   4899         # Invalid local context
   4900         self.assertRaises(TypeError, exec, 'with localcontext("xyz"): pass',
   4901                           locals())
   4902         self.assertRaises(TypeError, exec,
   4903                           'with localcontext(context=getcontext()): pass',
   4904                           locals())
   4905 
   4906         # setcontext
   4907         saved_context = getcontext()
   4908         self.assertRaises(TypeError, setcontext, "xyz")
   4909         setcontext(saved_context)
   4910 
   4911     def test_rounding_strings_interned(self):
   4912 
   4913         self.assertIs(C.ROUND_UP, P.ROUND_UP)
   4914         self.assertIs(C.ROUND_DOWN, P.ROUND_DOWN)
   4915         self.assertIs(C.ROUND_CEILING, P.ROUND_CEILING)
   4916         self.assertIs(C.ROUND_FLOOR, P.ROUND_FLOOR)
   4917         self.assertIs(C.ROUND_HALF_UP, P.ROUND_HALF_UP)
   4918         self.assertIs(C.ROUND_HALF_DOWN, P.ROUND_HALF_DOWN)
   4919         self.assertIs(C.ROUND_HALF_EVEN, P.ROUND_HALF_EVEN)
   4920         self.assertIs(C.ROUND_05UP, P.ROUND_05UP)
   4921 
   4922     @requires_extra_functionality
   4923     def test_c_context_errors_extra(self):
   4924         Context = C.Context
   4925         InvalidOperation = C.InvalidOperation
   4926         Overflow = C.Overflow
   4927         localcontext = C.localcontext
   4928         getcontext = C.getcontext
   4929         setcontext = C.setcontext
   4930         HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
   4931 
   4932         c = Context()
   4933 
   4934         # Input corner cases
   4935         int_max = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
   4936 
   4937         # OverflowError, general ValueError
   4938         self.assertRaises(OverflowError, setattr, c, '_allcr', int_max+1)
   4939         self.assertRaises(OverflowError, setattr, c, '_allcr', -int_max-2)
   4940         if sys.platform != 'win32':
   4941             self.assertRaises(ValueError, setattr, c, '_allcr', int_max)
   4942             self.assertRaises(ValueError, setattr, c, '_allcr', -int_max-1)
   4943 
   4944         # OverflowError, general TypeError
   4945         for attr in ('_flags', '_traps'):
   4946             self.assertRaises(OverflowError, setattr, c, attr, int_max+1)
   4947             self.assertRaises(OverflowError, setattr, c, attr, -int_max-2)
   4948             if sys.platform != 'win32':
   4949                 self.assertRaises(TypeError, setattr, c, attr, int_max)
   4950                 self.assertRaises(TypeError, setattr, c, attr, -int_max-1)
   4951 
   4952         # _allcr
   4953         self.assertRaises(ValueError, setattr, c, '_allcr', -1)
   4954         self.assertRaises(ValueError, setattr, c, '_allcr', 2)
   4955         self.assertRaises(TypeError, setattr, c, '_allcr', [1,2,3])
   4956         if HAVE_CONFIG_64:
   4957             self.assertRaises(ValueError, setattr, c, '_allcr', 2**32)
   4958             self.assertRaises(ValueError, setattr, c, '_allcr', 2**32+1)
   4959 
   4960         # _flags, _traps
   4961         for attr in ['_flags', '_traps']:
   4962             self.assertRaises(TypeError, setattr, c, attr, 999999)
   4963             self.assertRaises(TypeError, setattr, c, attr, 'x')
   4964 
   4965     def test_c_valid_context(self):
   4966         # These tests are for code coverage in _decimal.
   4967         DefaultContext = C.DefaultContext
   4968         Clamped = C.Clamped
   4969         Underflow = C.Underflow
   4970         Inexact = C.Inexact
   4971         Rounded = C.Rounded
   4972         Subnormal = C.Subnormal
   4973 
   4974         c = DefaultContext.copy()
   4975 
   4976         # Exercise all getters and setters
   4977         c.prec = 34
   4978         c.rounding = ROUND_HALF_UP
   4979         c.Emax = 3000
   4980         c.Emin = -3000
   4981         c.capitals = 1
   4982         c.clamp = 0
   4983 
   4984         self.assertEqual(c.prec, 34)
   4985         self.assertEqual(c.rounding, ROUND_HALF_UP)
   4986         self.assertEqual(c.Emin, -3000)
   4987         self.assertEqual(c.Emax, 3000)
   4988         self.assertEqual(c.capitals, 1)
   4989         self.assertEqual(c.clamp, 0)
   4990 
   4991         self.assertEqual(c.Etiny(), -3033)
   4992         self.assertEqual(c.Etop(), 2967)
   4993 
   4994         # Exercise all unsafe setters
   4995         if C.MAX_PREC == 425000000:
   4996             c._unsafe_setprec(999999999)
   4997             c._unsafe_setemax(999999999)
   4998             c._unsafe_setemin(-999999999)
   4999             self.assertEqual(c.prec, 999999999)
   5000             self.assertEqual(c.Emax, 999999999)
   5001             self.assertEqual(c.Emin, -999999999)
   5002 
   5003     @requires_extra_functionality
   5004     def test_c_valid_context_extra(self):
   5005         DefaultContext = C.DefaultContext
   5006 
   5007         c = DefaultContext.copy()
   5008         self.assertEqual(c._allcr, 1)
   5009         c._allcr = 0
   5010         self.assertEqual(c._allcr, 0)
   5011 
   5012     def test_c_round(self):
   5013         # Restricted input.
   5014         Decimal = C.Decimal
   5015         InvalidOperation = C.InvalidOperation
   5016         localcontext = C.localcontext
   5017         MAX_EMAX = C.MAX_EMAX
   5018         MIN_ETINY = C.MIN_ETINY
   5019         int_max = 2**63-1 if C.MAX_PREC > 425000000 else 2**31-1
   5020 
   5021         with localcontext() as c:
   5022             c.traps[InvalidOperation] = True
   5023             self.assertRaises(InvalidOperation, Decimal("1.23").__round__,
   5024                               -int_max-1)
   5025             self.assertRaises(InvalidOperation, Decimal("1.23").__round__,
   5026                               int_max)
   5027             self.assertRaises(InvalidOperation, Decimal("1").__round__,
   5028                               int(MAX_EMAX+1))
   5029             self.assertRaises(C.InvalidOperation, Decimal("1").__round__,
   5030                               -int(MIN_ETINY-1))
   5031             self.assertRaises(OverflowError, Decimal("1.23").__round__,
   5032                               -int_max-2)
   5033             self.assertRaises(OverflowError, Decimal("1.23").__round__,
   5034                               int_max+1)
   5035 
   5036     def test_c_format(self):
   5037         # Restricted input
   5038         Decimal = C.Decimal
   5039         HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
   5040 
   5041         self.assertRaises(TypeError, Decimal(1).__format__, "=10.10", [], 9)
   5042         self.assertRaises(TypeError, Decimal(1).__format__, "=10.10", 9)
   5043         self.assertRaises(TypeError, Decimal(1).__format__, [])
   5044 
   5045         self.assertRaises(ValueError, Decimal(1).__format__, "<>=10.10")
   5046         maxsize = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
   5047         self.assertRaises(ValueError, Decimal("1.23456789").__format__,
   5048                           "=%d.1" % maxsize)
   5049 
   5050     def test_c_integral(self):
   5051         Decimal = C.Decimal
   5052         Inexact = C.Inexact
   5053         localcontext = C.localcontext
   5054 
   5055         x = Decimal(10)
   5056         self.assertEqual(x.to_integral(), 10)
   5057         self.assertRaises(TypeError, x.to_integral, '10')
   5058         self.assertRaises(TypeError, x.to_integral, 10, 'x')
   5059         self.assertRaises(TypeError, x.to_integral, 10)
   5060 
   5061         self.assertEqual(x.to_integral_value(), 10)
   5062         self.assertRaises(TypeError, x.to_integral_value, '10')
   5063         self.assertRaises(TypeError, x.to_integral_value, 10, 'x')
   5064         self.assertRaises(TypeError, x.to_integral_value, 10)
   5065 
   5066         self.assertEqual(x.to_integral_exact(), 10)
   5067         self.assertRaises(TypeError, x.to_integral_exact, '10')
   5068         self.assertRaises(TypeError, x.to_integral_exact, 10, 'x')
   5069         self.assertRaises(TypeError, x.to_integral_exact, 10)
   5070 
   5071         with localcontext() as c:
   5072             x = Decimal("99999999999999999999999999.9").to_integral_value(ROUND_UP)
   5073             self.assertEqual(x, Decimal('100000000000000000000000000'))
   5074 
   5075             x = Decimal("99999999999999999999999999.9").to_integral_exact(ROUND_UP)
   5076             self.assertEqual(x, Decimal('100000000000000000000000000'))
   5077 
   5078             c.traps[Inexact] = True
   5079             self.assertRaises(Inexact, Decimal("999.9").to_integral_exact, ROUND_UP)
   5080 
   5081     def test_c_funcs(self):
   5082         # Invalid arguments
   5083         Decimal = C.Decimal
   5084         InvalidOperation = C.InvalidOperation
   5085         DivisionByZero = C.DivisionByZero
   5086         getcontext = C.getcontext
   5087         localcontext = C.localcontext
   5088 
   5089         self.assertEqual(Decimal('9.99e10').to_eng_string(), '99.9E+9')
   5090 
   5091         self.assertRaises(TypeError, pow, Decimal(1), 2, "3")
   5092         self.assertRaises(TypeError, Decimal(9).number_class, "x", "y")
   5093         self.assertRaises(TypeError, Decimal(9).same_quantum, 3, "x", "y")
   5094 
   5095         self.assertRaises(
   5096             TypeError,
   5097             Decimal("1.23456789").quantize, Decimal('1e-100000'), []
   5098         )
   5099         self.assertRaises(
   5100             TypeError,
   5101             Decimal("1.23456789").quantize, Decimal('1e-100000'), getcontext()
   5102         )
   5103         self.assertRaises(
   5104             TypeError,
   5105             Decimal("1.23456789").quantize, Decimal('1e-100000'), 10
   5106         )
   5107         self.assertRaises(
   5108             TypeError,
   5109             Decimal("1.23456789").quantize, Decimal('1e-100000'), ROUND_UP, 1000
   5110         )
   5111 
   5112         with localcontext() as c:
   5113             c.clear_traps()
   5114 
   5115             # Invalid arguments
   5116             self.assertRaises(TypeError, c.copy_sign, Decimal(1), "x", "y")
   5117             self.assertRaises(TypeError, c.canonical, 200)
   5118             self.assertRaises(TypeError, c.is_canonical, 200)
   5119             self.assertRaises(TypeError, c.divmod, 9, 8, "x", "y")
   5120             self.assertRaises(TypeError, c.same_quantum, 9, 3, "x", "y")
   5121 
   5122             self.assertEqual(str(c.canonical(Decimal(200))), '200')
   5123             self.assertEqual(c.radix(), 10)
   5124 
   5125             c.traps[DivisionByZero] = True
   5126             self.assertRaises(DivisionByZero, Decimal(9).__divmod__, 0)
   5127             self.assertRaises(DivisionByZero, c.divmod, 9, 0)
   5128             self.assertTrue(c.flags[InvalidOperation])
   5129 
   5130             c.clear_flags()
   5131             c.traps[InvalidOperation] = True
   5132             self.assertRaises(InvalidOperation, Decimal(9).__divmod__, 0)
   5133             self.assertRaises(InvalidOperation, c.divmod, 9, 0)
   5134             self.assertTrue(c.flags[DivisionByZero])
   5135 
   5136             c.traps[InvalidOperation] = True
   5137             c.prec = 2
   5138             self.assertRaises(InvalidOperation, pow, Decimal(1000), 1, 501)
   5139 
   5140     def test_va_args_exceptions(self):
   5141         Decimal = C.Decimal
   5142         Context = C.Context
   5143 
   5144         x = Decimal("10001111111")
   5145 
   5146         for attr in ['exp', 'is_normal', 'is_subnormal', 'ln', 'log10',
   5147                      'logb', 'logical_invert', 'next_minus', 'next_plus',
   5148                      'normalize', 'number_class', 'sqrt', 'to_eng_string']:
   5149             func = getattr(x, attr)
   5150             self.assertRaises(TypeError, func, context="x")
   5151             self.assertRaises(TypeError, func, "x", context=None)
   5152 
   5153         for attr in ['compare', 'compare_signal', 'logical_and',
   5154                      'logical_or', 'max', 'max_mag', 'min', 'min_mag',
   5155                      'remainder_near', 'rotate', 'scaleb', 'shift']:
   5156             func = getattr(x, attr)
   5157             self.assertRaises(TypeError, func, context="x")
   5158             self.assertRaises(TypeError, func, "x", context=None)
   5159 
   5160         self.assertRaises(TypeError, x.to_integral, rounding=None, context=[])
   5161         self.assertRaises(TypeError, x.to_integral, rounding={}, context=[])
   5162         self.assertRaises(TypeError, x.to_integral, [], [])
   5163 
   5164         self.assertRaises(TypeError, x.to_integral_value, rounding=None, context=[])
   5165         self.assertRaises(TypeError, x.to_integral_value, rounding={}, context=[])
   5166         self.assertRaises(TypeError, x.to_integral_value, [], [])
   5167 
   5168         self.assertRaises(TypeError, x.to_integral_exact, rounding=None, context=[])
   5169         self.assertRaises(TypeError, x.to_integral_exact, rounding={}, context=[])
   5170         self.assertRaises(TypeError, x.to_integral_exact, [], [])
   5171 
   5172         self.assertRaises(TypeError, x.fma, 1, 2, context="x")
   5173         self.assertRaises(TypeError, x.fma, 1, 2, "x", context=None)
   5174 
   5175         self.assertRaises(TypeError, x.quantize, 1, [], context=None)
   5176         self.assertRaises(TypeError, x.quantize, 1, [], rounding=None)
   5177         self.assertRaises(TypeError, x.quantize, 1, [], [])
   5178 
   5179         c = Context()
   5180         self.assertRaises(TypeError, c.power, 1, 2, mod="x")
   5181         self.assertRaises(TypeError, c.power, 1, "x", mod=None)
   5182         self.assertRaises(TypeError, c.power, "x", 2, mod=None)
   5183 
   5184     @requires_extra_functionality
   5185     def test_c_context_templates(self):
   5186         self.assertEqual(
   5187             C.BasicContext._traps,
   5188             C.DecIEEEInvalidOperation|C.DecDivisionByZero|C.DecOverflow|
   5189             C.DecUnderflow|C.DecClamped
   5190         )
   5191         self.assertEqual(
   5192             C.DefaultContext._traps,
   5193             C.DecIEEEInvalidOperation|C.DecDivisionByZero|C.DecOverflow
   5194         )
   5195 
   5196     @requires_extra_functionality
   5197     def test_c_signal_dict(self):
   5198 
   5199         # SignalDict coverage
   5200         Context = C.Context
   5201         DefaultContext = C.DefaultContext
   5202 
   5203         InvalidOperation = C.InvalidOperation
   5204         DivisionByZero = C.DivisionByZero
   5205         Overflow = C.Overflow
   5206         Subnormal = C.Subnormal
   5207         Underflow = C.Underflow
   5208         Rounded = C.Rounded
   5209         Inexact = C.Inexact
   5210         Clamped = C.Clamped
   5211 
   5212         DecClamped = C.DecClamped
   5213         DecInvalidOperation = C.DecInvalidOperation
   5214         DecIEEEInvalidOperation = C.DecIEEEInvalidOperation
   5215 
   5216         def assertIsExclusivelySet(signal, signal_dict):
   5217             for sig in signal_dict:
   5218                 if sig == signal:
   5219                     self.assertTrue(signal_dict[sig])
   5220                 else:
   5221                     self.assertFalse(signal_dict[sig])
   5222 
   5223         c = DefaultContext.copy()
   5224 
   5225         # Signal dict methods
   5226         self.assertTrue(Overflow in c.traps)
   5227         c.clear_traps()
   5228         for k in c.traps.keys():
   5229             c.traps[k] = True
   5230         for v in c.traps.values():
   5231             self.assertTrue(v)
   5232         c.clear_traps()
   5233         for k, v in c.traps.items():
   5234             self.assertFalse(v)
   5235 
   5236         self.assertFalse(c.flags.get(Overflow))
   5237         self.assertIs(c.flags.get("x"), None)
   5238         self.assertEqual(c.flags.get("x", "y"), "y")
   5239         self.assertRaises(TypeError, c.flags.get, "x", "y", "z")
   5240 
   5241         self.assertEqual(len(c.flags), len(c.traps))
   5242         s = sys.getsizeof(c.flags)
   5243         s = sys.getsizeof(c.traps)
   5244         s = c.flags.__repr__()
   5245 
   5246         # Set flags/traps.
   5247         c.clear_flags()
   5248         c._flags = DecClamped
   5249         self.assertTrue(c.flags[Clamped])
   5250 
   5251         c.clear_traps()
   5252         c._traps = DecInvalidOperation
   5253         self.assertTrue(c.traps[InvalidOperation])
   5254 
   5255         # Set flags/traps from dictionary.
   5256         c.clear_flags()
   5257         d = c.flags.copy()
   5258         d[DivisionByZero] = True
   5259         c.flags = d
   5260         assertIsExclusivelySet(DivisionByZero, c.flags)
   5261 
   5262         c.clear_traps()
   5263         d = c.traps.copy()
   5264         d[Underflow] = True
   5265         c.traps = d
   5266         assertIsExclusivelySet(Underflow, c.traps)
   5267 
   5268         # Random constructors
   5269         IntSignals = {
   5270           Clamped: C.DecClamped,
   5271           Rounded: C.DecRounded,
   5272           Inexact: C.DecInexact,
   5273           Subnormal: C.DecSubnormal,
   5274           Underflow: C.DecUnderflow,
   5275           Overflow: C.DecOverflow,
   5276           DivisionByZero: C.DecDivisionByZero,
   5277           InvalidOperation: C.DecIEEEInvalidOperation
   5278         }
   5279         IntCond = [
   5280           C.DecDivisionImpossible, C.DecDivisionUndefined, C.DecFpuError,
   5281           C.DecInvalidContext, C.DecInvalidOperation, C.DecMallocError,
   5282           C.DecConversionSyntax,
   5283         ]
   5284 
   5285         lim = len(OrderedSignals[C])
   5286         for r in range(lim):
   5287             for t in range(lim):
   5288                 for round in RoundingModes:
   5289                     flags = random.sample(OrderedSignals[C], r)
   5290                     traps = random.sample(OrderedSignals[C], t)
   5291                     prec = random.randrange(1, 10000)
   5292                     emin = random.randrange(-10000, 0)
   5293                     emax = random.randrange(0, 10000)
   5294                     clamp = random.randrange(0, 2)
   5295                     caps = random.randrange(0, 2)
   5296                     cr = random.randrange(0, 2)
   5297                     c = Context(prec=prec, rounding=round, Emin=emin, Emax=emax,
   5298                                 capitals=caps, clamp=clamp, flags=list(flags),
   5299                                 traps=list(traps))
   5300 
   5301                     self.assertEqual(c.prec, prec)
   5302                     self.assertEqual(c.rounding, round)
   5303                     self.assertEqual(c.Emin, emin)
   5304                     self.assertEqual(c.Emax, emax)
   5305                     self.assertEqual(c.capitals, caps)
   5306                     self.assertEqual(c.clamp, clamp)
   5307 
   5308                     f = 0
   5309                     for x in flags:
   5310                         f |= IntSignals[x]
   5311                     self.assertEqual(c._flags, f)
   5312 
   5313                     f = 0
   5314                     for x in traps:
   5315                         f |= IntSignals[x]
   5316                     self.assertEqual(c._traps, f)
   5317 
   5318         for cond in IntCond:
   5319             c._flags = cond
   5320             self.assertTrue(c._flags&DecIEEEInvalidOperation)
   5321             assertIsExclusivelySet(InvalidOperation, c.flags)
   5322 
   5323         for cond in IntCond:
   5324             c._traps = cond
   5325             self.assertTrue(c._traps&DecIEEEInvalidOperation)
   5326             assertIsExclusivelySet(InvalidOperation, c.traps)
   5327 
   5328     def test_invalid_override(self):
   5329         Decimal = C.Decimal
   5330 
   5331         try:
   5332             from locale import CHAR_MAX
   5333         except ImportError:
   5334             self.skipTest('locale.CHAR_MAX not available')
   5335 
   5336         def make_grouping(lst):
   5337             return ''.join([chr(x) for x in lst])
   5338 
   5339         def get_fmt(x, override=None, fmt='n'):
   5340             return Decimal(x).__format__(fmt, override)
   5341 
   5342         invalid_grouping = {
   5343             'decimal_point' : ',',
   5344             'grouping' : make_grouping([255, 255, 0]),
   5345             'thousands_sep' : ','
   5346         }
   5347         invalid_dot = {
   5348             'decimal_point' : 'xxxxx',
   5349             'grouping' : make_grouping([3, 3, 0]),
   5350             'thousands_sep' : ','
   5351         }
   5352         invalid_sep = {
   5353             'decimal_point' : '.',
   5354             'grouping' : make_grouping([3, 3, 0]),
   5355             'thousands_sep' : 'yyyyy'
   5356         }
   5357 
   5358         if CHAR_MAX == 127: # negative grouping in override
   5359             self.assertRaises(ValueError, get_fmt, 12345,
   5360                               invalid_grouping, 'g')
   5361 
   5362         self.assertRaises(ValueError, get_fmt, 12345, invalid_dot, 'g')
   5363         self.assertRaises(ValueError, get_fmt, 12345, invalid_sep, 'g')
   5364 
   5365     def test_exact_conversion(self):
   5366         Decimal = C.Decimal
   5367         localcontext = C.localcontext
   5368         InvalidOperation = C.InvalidOperation
   5369 
   5370         with localcontext() as c:
   5371 
   5372             c.traps[InvalidOperation] = True
   5373 
   5374             # Clamped
   5375             x = "0e%d" % sys.maxsize
   5376             self.assertRaises(InvalidOperation, Decimal, x)
   5377 
   5378             x = "0e%d" % (-sys.maxsize-1)
   5379             self.assertRaises(InvalidOperation, Decimal, x)
   5380 
   5381             # Overflow
   5382             x = "1e%d" % sys.maxsize
   5383             self.assertRaises(InvalidOperation, Decimal, x)
   5384 
   5385             # Underflow
   5386             x = "1e%d" % (-sys.maxsize-1)
   5387             self.assertRaises(InvalidOperation, Decimal, x)
   5388 
   5389     def test_from_tuple(self):
   5390         Decimal = C.Decimal
   5391         localcontext = C.localcontext
   5392         InvalidOperation = C.InvalidOperation
   5393         Overflow = C.Overflow
   5394         Underflow = C.Underflow
   5395 
   5396         with localcontext() as c:
   5397 
   5398             c.traps[InvalidOperation] = True
   5399             c.traps[Overflow] = True
   5400             c.traps[Underflow] = True
   5401 
   5402             # SSIZE_MAX
   5403             x = (1, (), sys.maxsize)
   5404             self.assertEqual(str(c.create_decimal(x)), '-0E+999999')
   5405             self.assertRaises(InvalidOperation, Decimal, x)
   5406 
   5407             x = (1, (0, 1, 2), sys.maxsize)
   5408             self.assertRaises(Overflow, c.create_decimal, x)
   5409             self.assertRaises(InvalidOperation, Decimal, x)
   5410 
   5411             # SSIZE_MIN
   5412             x = (1, (), -sys.maxsize-1)
   5413             self.assertEqual(str(c.create_decimal(x)), '-0E-1000007')
   5414             self.assertRaises(InvalidOperation, Decimal, x)
   5415 
   5416             x = (1, (0, 1, 2), -sys.maxsize-1)
   5417             self.assertRaises(Underflow, c.create_decimal, x)
   5418             self.assertRaises(InvalidOperation, Decimal, x)
   5419 
   5420             # OverflowError
   5421             x = (1, (), sys.maxsize+1)
   5422             self.assertRaises(OverflowError, c.create_decimal, x)
   5423             self.assertRaises(OverflowError, Decimal, x)
   5424 
   5425             x = (1, (), -sys.maxsize-2)
   5426             self.assertRaises(OverflowError, c.create_decimal, x)
   5427             self.assertRaises(OverflowError, Decimal, x)
   5428 
   5429             # Specials
   5430             x = (1, (), "N")
   5431             self.assertEqual(str(Decimal(x)), '-sNaN')
   5432             x = (1, (0,), "N")
   5433             self.assertEqual(str(Decimal(x)), '-sNaN')
   5434             x = (1, (0, 1), "N")
   5435             self.assertEqual(str(Decimal(x)), '-sNaN1')
   5436 
   5437     def test_sizeof(self):
   5438         Decimal = C.Decimal
   5439         HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
   5440 
   5441         self.assertGreater(Decimal(0).__sizeof__(), 0)
   5442         if HAVE_CONFIG_64:
   5443             x = Decimal(10**(19*24)).__sizeof__()
   5444             y = Decimal(10**(19*25)).__sizeof__()
   5445             self.assertEqual(y, x+8)
   5446         else:
   5447             x = Decimal(10**(9*24)).__sizeof__()
   5448             y = Decimal(10**(9*25)).__sizeof__()
   5449             self.assertEqual(y, x+4)
   5450 
   5451     def test_internal_use_of_overridden_methods(self):
   5452         Decimal = C.Decimal
   5453 
   5454         # Unsound subtyping
   5455         class X(float):
   5456             def as_integer_ratio(self):
   5457                 return 1
   5458             def __abs__(self):
   5459                 return self
   5460 
   5461         class Y(float):
   5462             def __abs__(self):
   5463                 return [1]*200
   5464 
   5465         class I(int):
   5466             def bit_length(self):
   5467                 return [1]*200
   5468 
   5469         class Z(float):
   5470             def as_integer_ratio(self):
   5471                 return (I(1), I(1))
   5472             def __abs__(self):
   5473                 return self
   5474 
   5475         for cls in X, Y, Z:
   5476             self.assertEqual(Decimal.from_float(cls(101.1)),
   5477                              Decimal.from_float(101.1))
   5478 
   5479 @requires_docstrings
   5480 @unittest.skipUnless(C, "test requires C version")
   5481 class SignatureTest(unittest.TestCase):
   5482     """Function signatures"""
   5483 
   5484     def test_inspect_module(self):
   5485         for attr in dir(P):
   5486             if attr.startswith('_'):
   5487                 continue
   5488             p_func = getattr(P, attr)
   5489             c_func = getattr(C, attr)
   5490             if (attr == 'Decimal' or attr == 'Context' or
   5491                 inspect.isfunction(p_func)):
   5492                 p_sig = inspect.signature(p_func)
   5493                 c_sig = inspect.signature(c_func)
   5494 
   5495                 # parameter names:
   5496                 c_names = list(c_sig.parameters.keys())
   5497                 p_names = [x for x in p_sig.parameters.keys() if not
   5498                            x.startswith('_')]
   5499 
   5500                 self.assertEqual(c_names, p_names,
   5501                                  msg="parameter name mismatch in %s" % p_func)
   5502 
   5503                 c_kind = [x.kind for x in c_sig.parameters.values()]
   5504                 p_kind = [x[1].kind for x in p_sig.parameters.items() if not
   5505                           x[0].startswith('_')]
   5506 
   5507                 # parameters:
   5508                 if attr != 'setcontext':
   5509                     self.assertEqual(c_kind, p_kind,
   5510                                      msg="parameter kind mismatch in %s" % p_func)
   5511 
   5512     def test_inspect_types(self):
   5513 
   5514         POS = inspect._ParameterKind.POSITIONAL_ONLY
   5515         POS_KWD = inspect._ParameterKind.POSITIONAL_OR_KEYWORD
   5516 
   5517         # Type heuristic (type annotations would help!):
   5518         pdict = {C: {'other': C.Decimal(1),
   5519                      'third': C.Decimal(1),
   5520                      'x': C.Decimal(1),
   5521                      'y': C.Decimal(1),
   5522                      'z': C.Decimal(1),
   5523                      'a': C.Decimal(1),
   5524                      'b': C.Decimal(1),
   5525                      'c': C.Decimal(1),
   5526                      'exp': C.Decimal(1),
   5527                      'modulo': C.Decimal(1),
   5528                      'num': "1",
   5529                      'f': 1.0,
   5530                      'rounding': C.ROUND_HALF_UP,
   5531                      'context': C.getcontext()},
   5532                  P: {'other': P.Decimal(1),
   5533                      'third': P.Decimal(1),
   5534                      'a': P.Decimal(1),
   5535                      'b': P.Decimal(1),
   5536                      'c': P.Decimal(1),
   5537                      'exp': P.Decimal(1),
   5538                      'modulo': P.Decimal(1),
   5539                      'num': "1",
   5540                      'f': 1.0,
   5541                      'rounding': P.ROUND_HALF_UP,
   5542                      'context': P.getcontext()}}
   5543 
   5544         def mkargs(module, sig):
   5545             args = []
   5546             kwargs = {}
   5547             for name, param in sig.parameters.items():
   5548                 if name == 'self': continue
   5549                 if param.kind == POS:
   5550                     args.append(pdict[module][name])
   5551                 elif param.kind == POS_KWD:
   5552                     kwargs[name] = pdict[module][name]
   5553                 else:
   5554                     raise TestFailed("unexpected parameter kind")
   5555             return args, kwargs
   5556 
   5557         def tr(s):
   5558             """The C Context docstrings use 'x' in order to prevent confusion
   5559                with the article 'a' in the descriptions."""
   5560             if s == 'x': return 'a'
   5561             if s == 'y': return 'b'
   5562             if s == 'z': return 'c'
   5563             return s
   5564 
   5565         def doit(ty):
   5566             p_type = getattr(P, ty)
   5567             c_type = getattr(C, ty)
   5568             for attr in dir(p_type):
   5569                 if attr.startswith('_'):
   5570                     continue
   5571                 p_func = getattr(p_type, attr)
   5572                 c_func = getattr(c_type, attr)
   5573                 if inspect.isfunction(p_func):
   5574                     p_sig = inspect.signature(p_func)
   5575                     c_sig = inspect.signature(c_func)
   5576 
   5577                     # parameter names:
   5578                     p_names = list(p_sig.parameters.keys())
   5579                     c_names = [tr(x) for x in c_sig.parameters.keys()]
   5580 
   5581                     self.assertEqual(c_names, p_names,
   5582                                      msg="parameter name mismatch in %s" % p_func)
   5583 
   5584                     p_kind = [x.kind for x in p_sig.parameters.values()]
   5585                     c_kind = [x.kind for x in c_sig.parameters.values()]
   5586 
   5587                     # 'self' parameter:
   5588                     self.assertIs(p_kind[0], POS_KWD)
   5589                     self.assertIs(c_kind[0], POS)
   5590 
   5591                     # remaining parameters:
   5592                     if ty == 'Decimal':
   5593                         self.assertEqual(c_kind[1:], p_kind[1:],
   5594                                          msg="parameter kind mismatch in %s" % p_func)
   5595                     else: # Context methods are positional only in the C version.
   5596                         self.assertEqual(len(c_kind), len(p_kind),
   5597                                          msg="parameter kind mismatch in %s" % p_func)
   5598 
   5599                     # Run the function:
   5600                     args, kwds = mkargs(C, c_sig)
   5601                     try:
   5602                         getattr(c_type(9), attr)(*args, **kwds)
   5603                     except Exception as err:
   5604                         raise TestFailed("invalid signature for %s: %s %s" % (c_func, args, kwds))
   5605 
   5606                     args, kwds = mkargs(P, p_sig)
   5607                     try:
   5608                         getattr(p_type(9), attr)(*args, **kwds)
   5609                     except Exception as err:
   5610                         raise TestFailed("invalid signature for %s: %s %s" % (p_func, args, kwds))
   5611 
   5612         doit('Decimal')
   5613         doit('Context')
   5614 
   5615 
   5616 all_tests = [
   5617   CExplicitConstructionTest, PyExplicitConstructionTest,
   5618   CImplicitConstructionTest, PyImplicitConstructionTest,
   5619   CFormatTest,               PyFormatTest,
   5620   CArithmeticOperatorsTest,  PyArithmeticOperatorsTest,
   5621   CThreadingTest,            PyThreadingTest,
   5622   CUsabilityTest,            PyUsabilityTest,
   5623   CPythonAPItests,           PyPythonAPItests,
   5624   CContextAPItests,          PyContextAPItests,
   5625   CContextWithStatement,     PyContextWithStatement,
   5626   CContextFlags,             PyContextFlags,
   5627   CSpecialContexts,          PySpecialContexts,
   5628   CContextInputValidation,   PyContextInputValidation,
   5629   CContextSubclassing,       PyContextSubclassing,
   5630   CCoverage,                 PyCoverage,
   5631   CFunctionality,            PyFunctionality,
   5632   CWhitebox,                 PyWhitebox,
   5633   CIBMTestCases,             PyIBMTestCases,
   5634 ]
   5635 
   5636 # Delete C tests if _decimal.so is not present.
   5637 if not C:
   5638     all_tests = all_tests[1::2]
   5639 else:
   5640     all_tests.insert(0, CheckAttributes)
   5641     all_tests.insert(1, SignatureTest)
   5642 
   5643 
   5644 def test_main(arith=None, verbose=None, todo_tests=None, debug=None):
   5645     """ Execute the tests.
   5646 
   5647     Runs all arithmetic tests if arith is True or if the "decimal" resource
   5648     is enabled in regrtest.py
   5649     """
   5650 
   5651     init(C)
   5652     init(P)
   5653     global TEST_ALL, DEBUG
   5654     TEST_ALL = arith if arith is not None else is_resource_enabled('decimal')
   5655     DEBUG = debug
   5656 
   5657     if todo_tests is None:
   5658         test_classes = all_tests
   5659     else:
   5660         test_classes = [CIBMTestCases, PyIBMTestCases]
   5661 
   5662     # Dynamically build custom test definition for each file in the test
   5663     # directory and add the definitions to the DecimalTest class.  This
   5664     # procedure insures that new files do not get skipped.
   5665     for filename in os.listdir(directory):
   5666         if '.decTest' not in filename or filename.startswith("."):
   5667             continue
   5668         head, tail = filename.split('.')
   5669         if todo_tests is not None and head not in todo_tests:
   5670             continue
   5671         tester = lambda self, f=filename: self.eval_file(directory + f)
   5672         setattr(CIBMTestCases, 'test_' + head, tester)
   5673         setattr(PyIBMTestCases, 'test_' + head, tester)
   5674         del filename, head, tail, tester
   5675 
   5676 
   5677     try:
   5678         run_unittest(*test_classes)
   5679         if todo_tests is None:
   5680             from doctest import IGNORE_EXCEPTION_DETAIL
   5681             savedecimal = sys.modules['decimal']
   5682             if C:
   5683                 sys.modules['decimal'] = C
   5684                 run_doctest(C, verbose, optionflags=IGNORE_EXCEPTION_DETAIL)
   5685             sys.modules['decimal'] = P
   5686             run_doctest(P, verbose)
   5687             sys.modules['decimal'] = savedecimal
   5688     finally:
   5689         if C: C.setcontext(ORIGINAL_CONTEXT[C])
   5690         P.setcontext(ORIGINAL_CONTEXT[P])
   5691         if not C:
   5692             warnings.warn('C tests skipped: no module named _decimal.',
   5693                           UserWarning)
   5694         if not orig_sys_decimal is sys.modules['decimal']:
   5695             raise TestFailed("Internal error: unbalanced number of changes to "
   5696                              "sys.modules['decimal'].")
   5697 
   5698 
   5699 if __name__ == '__main__':
   5700     import optparse
   5701     p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]")
   5702     p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test')
   5703     p.add_option('--skip',  '-s', action='store_true', help='skip over 90% of the arithmetic tests')
   5704     (opt, args) = p.parse_args()
   5705 
   5706     if opt.skip:
   5707         test_main(arith=False, verbose=True)
   5708     elif args:
   5709         test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug)
   5710     else:
   5711         test_main(arith=True, verbose=True)
   5712