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