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