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