• 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
2449class PythonAPItests(unittest.TestCase):
2450
2451    def test_abc(self):
2452        Decimal = self.decimal.Decimal
2453
2454        self.assertTrue(issubclass(Decimal, numbers.Number))
2455        self.assertFalse(issubclass(Decimal, numbers.Real))
2456        self.assertIsInstance(Decimal(0), numbers.Number)
2457        self.assertNotIsInstance(Decimal(0), numbers.Real)
2458
2459    def test_pickle(self):
2460        for proto in range(pickle.HIGHEST_PROTOCOL + 1):
2461            Decimal = self.decimal.Decimal
2462
2463            savedecimal = sys.modules['decimal']
2464
2465            # Round trip
2466            sys.modules['decimal'] = self.decimal
2467            d = Decimal('-3.141590000')
2468            p = pickle.dumps(d, proto)
2469            e = pickle.loads(p)
2470            self.assertEqual(d, e)
2471
2472            if C:
2473                # Test interchangeability
2474                x = C.Decimal('-3.123e81723')
2475                y = P.Decimal('-3.123e81723')
2476
2477                sys.modules['decimal'] = C
2478                sx = pickle.dumps(x, proto)
2479                sys.modules['decimal'] = P
2480                r = pickle.loads(sx)
2481                self.assertIsInstance(r, P.Decimal)
2482                self.assertEqual(r, y)
2483
2484                sys.modules['decimal'] = P
2485                sy = pickle.dumps(y, proto)
2486                sys.modules['decimal'] = C
2487                r = pickle.loads(sy)
2488                self.assertIsInstance(r, C.Decimal)
2489                self.assertEqual(r, x)
2490
2491                x = C.Decimal('-3.123e81723').as_tuple()
2492                y = P.Decimal('-3.123e81723').as_tuple()
2493
2494                sys.modules['decimal'] = C
2495                sx = pickle.dumps(x, proto)
2496                sys.modules['decimal'] = P
2497                r = pickle.loads(sx)
2498                self.assertIsInstance(r, P.DecimalTuple)
2499                self.assertEqual(r, y)
2500
2501                sys.modules['decimal'] = P
2502                sy = pickle.dumps(y, proto)
2503                sys.modules['decimal'] = C
2504                r = pickle.loads(sy)
2505                self.assertIsInstance(r, C.DecimalTuple)
2506                self.assertEqual(r, x)
2507
2508            sys.modules['decimal'] = savedecimal
2509
2510    def test_int(self):
2511        Decimal = self.decimal.Decimal
2512
2513        for x in range(-250, 250):
2514            s = '%0.2f' % (x / 100.0)
2515            # should work the same as for floats
2516            self.assertEqual(int(Decimal(s)), int(float(s)))
2517            # should work the same as to_integral in the ROUND_DOWN mode
2518            d = Decimal(s)
2519            r = d.to_integral(ROUND_DOWN)
2520            self.assertEqual(Decimal(int(d)), r)
2521
2522        self.assertRaises(ValueError, int, Decimal('-nan'))
2523        self.assertRaises(ValueError, int, Decimal('snan'))
2524        self.assertRaises(OverflowError, int, Decimal('inf'))
2525        self.assertRaises(OverflowError, int, Decimal('-inf'))
2526
2527    def test_trunc(self):
2528        Decimal = self.decimal.Decimal
2529
2530        for x in range(-250, 250):
2531            s = '%0.2f' % (x / 100.0)
2532            # should work the same as for floats
2533            self.assertEqual(int(Decimal(s)), int(float(s)))
2534            # should work the same as to_integral in the ROUND_DOWN mode
2535            d = Decimal(s)
2536            r = d.to_integral(ROUND_DOWN)
2537            self.assertEqual(Decimal(math.trunc(d)), r)
2538
2539    def test_from_float(self):
2540
2541        Decimal = self.decimal.Decimal
2542
2543        class MyDecimal(Decimal):
2544            def __init__(self, _):
2545                self.x = 'y'
2546
2547        self.assertTrue(issubclass(MyDecimal, Decimal))
2548
2549        r = MyDecimal.from_float(0.1)
2550        self.assertEqual(type(r), MyDecimal)
2551        self.assertEqual(str(r),
2552                '0.1000000000000000055511151231257827021181583404541015625')
2553        self.assertEqual(r.x, 'y')
2554
2555        bigint = 12345678901234567890123456789
2556        self.assertEqual(MyDecimal.from_float(bigint), MyDecimal(bigint))
2557        self.assertTrue(MyDecimal.from_float(float('nan')).is_qnan())
2558        self.assertTrue(MyDecimal.from_float(float('inf')).is_infinite())
2559        self.assertTrue(MyDecimal.from_float(float('-inf')).is_infinite())
2560        self.assertEqual(str(MyDecimal.from_float(float('nan'))),
2561                         str(Decimal('NaN')))
2562        self.assertEqual(str(MyDecimal.from_float(float('inf'))),
2563                         str(Decimal('Infinity')))
2564        self.assertEqual(str(MyDecimal.from_float(float('-inf'))),
2565                         str(Decimal('-Infinity')))
2566        self.assertRaises(TypeError, MyDecimal.from_float, 'abc')
2567        for i in range(200):
2568            x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
2569            self.assertEqual(x, float(MyDecimal.from_float(x))) # roundtrip
2570
2571    def test_create_decimal_from_float(self):
2572        Decimal = self.decimal.Decimal
2573        Context = self.decimal.Context
2574        Inexact = self.decimal.Inexact
2575
2576        context = Context(prec=5, rounding=ROUND_DOWN)
2577        self.assertEqual(
2578            context.create_decimal_from_float(math.pi),
2579            Decimal('3.1415')
2580        )
2581        context = Context(prec=5, rounding=ROUND_UP)
2582        self.assertEqual(
2583            context.create_decimal_from_float(math.pi),
2584            Decimal('3.1416')
2585        )
2586        context = Context(prec=5, traps=[Inexact])
2587        self.assertRaises(
2588            Inexact,
2589            context.create_decimal_from_float,
2590            math.pi
2591        )
2592        self.assertEqual(repr(context.create_decimal_from_float(-0.0)),
2593                         "Decimal('-0')")
2594        self.assertEqual(repr(context.create_decimal_from_float(1.0)),
2595                         "Decimal('1')")
2596        self.assertEqual(repr(context.create_decimal_from_float(10)),
2597                         "Decimal('10')")
2598
2599    def test_quantize(self):
2600        Decimal = self.decimal.Decimal
2601        Context = self.decimal.Context
2602        InvalidOperation = self.decimal.InvalidOperation
2603
2604        c = Context(Emax=99999, Emin=-99999)
2605        self.assertEqual(
2606            Decimal('7.335').quantize(Decimal('.01')),
2607            Decimal('7.34')
2608        )
2609        self.assertEqual(
2610            Decimal('7.335').quantize(Decimal('.01'), rounding=ROUND_DOWN),
2611            Decimal('7.33')
2612        )
2613        self.assertRaises(
2614            InvalidOperation,
2615            Decimal("10e99999").quantize, Decimal('1e100000'), context=c
2616        )
2617
2618        c = Context()
2619        d = Decimal("0.871831e800")
2620        x = d.quantize(context=c, exp=Decimal("1e797"), rounding=ROUND_DOWN)
2621        self.assertEqual(x, Decimal('8.71E+799'))
2622
2623    def test_complex(self):
2624        Decimal = self.decimal.Decimal
2625
2626        x = Decimal("9.8182731e181273")
2627        self.assertEqual(x.real, x)
2628        self.assertEqual(x.imag, 0)
2629        self.assertEqual(x.conjugate(), x)
2630
2631        x = Decimal("1")
2632        self.assertEqual(complex(x), complex(float(1)))
2633
2634        self.assertRaises(AttributeError, setattr, x, 'real', 100)
2635        self.assertRaises(AttributeError, setattr, x, 'imag', 100)
2636        self.assertRaises(AttributeError, setattr, x, 'conjugate', 100)
2637        self.assertRaises(AttributeError, setattr, x, '__complex__', 100)
2638
2639    def test_named_parameters(self):
2640        D = self.decimal.Decimal
2641        Context = self.decimal.Context
2642        localcontext = self.decimal.localcontext
2643        InvalidOperation = self.decimal.InvalidOperation
2644        Overflow = self.decimal.Overflow
2645
2646        xc = Context()
2647        xc.prec = 1
2648        xc.Emax = 1
2649        xc.Emin = -1
2650
2651        with localcontext() as c:
2652            c.clear_flags()
2653
2654            self.assertEqual(D(9, xc), 9)
2655            self.assertEqual(D(9, context=xc), 9)
2656            self.assertEqual(D(context=xc, value=9), 9)
2657            self.assertEqual(D(context=xc), 0)
2658            xc.clear_flags()
2659            self.assertRaises(InvalidOperation, D, "xyz", context=xc)
2660            self.assertTrue(xc.flags[InvalidOperation])
2661            self.assertFalse(c.flags[InvalidOperation])
2662
2663            xc.clear_flags()
2664            self.assertEqual(D(2).exp(context=xc), 7)
2665            self.assertRaises(Overflow, D(8).exp, context=xc)
2666            self.assertTrue(xc.flags[Overflow])
2667            self.assertFalse(c.flags[Overflow])
2668
2669            xc.clear_flags()
2670            self.assertEqual(D(2).ln(context=xc), D('0.7'))
2671            self.assertRaises(InvalidOperation, D(-1).ln, context=xc)
2672            self.assertTrue(xc.flags[InvalidOperation])
2673            self.assertFalse(c.flags[InvalidOperation])
2674
2675            self.assertEqual(D(0).log10(context=xc), D('-inf'))
2676            self.assertEqual(D(-1).next_minus(context=xc), -2)
2677            self.assertEqual(D(-1).next_plus(context=xc), D('-0.9'))
2678            self.assertEqual(D("9.73").normalize(context=xc), D('1E+1'))
2679            self.assertEqual(D("9999").to_integral(context=xc), 9999)
2680            self.assertEqual(D("-2000").to_integral_exact(context=xc), -2000)
2681            self.assertEqual(D("123").to_integral_value(context=xc), 123)
2682            self.assertEqual(D("0.0625").sqrt(context=xc), D('0.2'))
2683
2684            self.assertEqual(D("0.0625").compare(context=xc, other=3), -1)
2685            xc.clear_flags()
2686            self.assertRaises(InvalidOperation,
2687                              D("0").compare_signal, D('nan'), context=xc)
2688            self.assertTrue(xc.flags[InvalidOperation])
2689            self.assertFalse(c.flags[InvalidOperation])
2690            self.assertEqual(D("0.01").max(D('0.0101'), context=xc), D('0.0'))
2691            self.assertEqual(D("0.01").max(D('0.0101'), context=xc), D('0.0'))
2692            self.assertEqual(D("0.2").max_mag(D('-0.3'), context=xc),
2693                             D('-0.3'))
2694            self.assertEqual(D("0.02").min(D('-0.03'), context=xc), D('-0.0'))
2695            self.assertEqual(D("0.02").min_mag(D('-0.03'), context=xc),
2696                             D('0.0'))
2697            self.assertEqual(D("0.2").next_toward(D('-1'), context=xc), D('0.1'))
2698            xc.clear_flags()
2699            self.assertRaises(InvalidOperation,
2700                              D("0.2").quantize, D('1e10'), context=xc)
2701            self.assertTrue(xc.flags[InvalidOperation])
2702            self.assertFalse(c.flags[InvalidOperation])
2703            self.assertEqual(D("9.99").remainder_near(D('1.5'), context=xc),
2704                             D('-0.5'))
2705
2706            self.assertEqual(D("9.9").fma(third=D('0.9'), context=xc, other=7),
2707                             D('7E+1'))
2708
2709            self.assertRaises(TypeError, D(1).is_canonical, context=xc)
2710            self.assertRaises(TypeError, D(1).is_finite, context=xc)
2711            self.assertRaises(TypeError, D(1).is_infinite, context=xc)
2712            self.assertRaises(TypeError, D(1).is_nan, context=xc)
2713            self.assertRaises(TypeError, D(1).is_qnan, context=xc)
2714            self.assertRaises(TypeError, D(1).is_snan, context=xc)
2715            self.assertRaises(TypeError, D(1).is_signed, context=xc)
2716            self.assertRaises(TypeError, D(1).is_zero, context=xc)
2717
2718            self.assertFalse(D("0.01").is_normal(context=xc))
2719            self.assertTrue(D("0.01").is_subnormal(context=xc))
2720
2721            self.assertRaises(TypeError, D(1).adjusted, context=xc)
2722            self.assertRaises(TypeError, D(1).conjugate, context=xc)
2723            self.assertRaises(TypeError, D(1).radix, context=xc)
2724
2725            self.assertEqual(D(-111).logb(context=xc), 2)
2726            self.assertEqual(D(0).logical_invert(context=xc), 1)
2727            self.assertEqual(D('0.01').number_class(context=xc), '+Subnormal')
2728            self.assertEqual(D('0.21').to_eng_string(context=xc), '0.21')
2729
2730            self.assertEqual(D('11').logical_and(D('10'), context=xc), 0)
2731            self.assertEqual(D('11').logical_or(D('10'), context=xc), 1)
2732            self.assertEqual(D('01').logical_xor(D('10'), context=xc), 1)
2733            self.assertEqual(D('23').rotate(1, context=xc), 3)
2734            self.assertEqual(D('23').rotate(1, context=xc), 3)
2735            xc.clear_flags()
2736            self.assertRaises(Overflow,
2737                              D('23').scaleb, 1, context=xc)
2738            self.assertTrue(xc.flags[Overflow])
2739            self.assertFalse(c.flags[Overflow])
2740            self.assertEqual(D('23').shift(-1, context=xc), 0)
2741
2742            self.assertRaises(TypeError, D.from_float, 1.1, context=xc)
2743            self.assertRaises(TypeError, D(0).as_tuple, context=xc)
2744
2745            self.assertEqual(D(1).canonical(), 1)
2746            self.assertRaises(TypeError, D("-1").copy_abs, context=xc)
2747            self.assertRaises(TypeError, D("-1").copy_negate, context=xc)
2748            self.assertRaises(TypeError, D(1).canonical, context="x")
2749            self.assertRaises(TypeError, D(1).canonical, xyz="x")
2750
2751    def test_exception_hierarchy(self):
2752
2753        decimal = self.decimal
2754        DecimalException = decimal.DecimalException
2755        InvalidOperation = decimal.InvalidOperation
2756        FloatOperation = decimal.FloatOperation
2757        DivisionByZero = decimal.DivisionByZero
2758        Overflow = decimal.Overflow
2759        Underflow = decimal.Underflow
2760        Subnormal = decimal.Subnormal
2761        Inexact = decimal.Inexact
2762        Rounded = decimal.Rounded
2763        Clamped = decimal.Clamped
2764
2765        self.assertTrue(issubclass(DecimalException, ArithmeticError))
2766
2767        self.assertTrue(issubclass(InvalidOperation, DecimalException))
2768        self.assertTrue(issubclass(FloatOperation, DecimalException))
2769        self.assertTrue(issubclass(FloatOperation, TypeError))
2770        self.assertTrue(issubclass(DivisionByZero, DecimalException))
2771        self.assertTrue(issubclass(DivisionByZero, ZeroDivisionError))
2772        self.assertTrue(issubclass(Overflow, Rounded))
2773        self.assertTrue(issubclass(Overflow, Inexact))
2774        self.assertTrue(issubclass(Overflow, DecimalException))
2775        self.assertTrue(issubclass(Underflow, Inexact))
2776        self.assertTrue(issubclass(Underflow, Rounded))
2777        self.assertTrue(issubclass(Underflow, Subnormal))
2778        self.assertTrue(issubclass(Underflow, DecimalException))
2779
2780        self.assertTrue(issubclass(Subnormal, DecimalException))
2781        self.assertTrue(issubclass(Inexact, DecimalException))
2782        self.assertTrue(issubclass(Rounded, DecimalException))
2783        self.assertTrue(issubclass(Clamped, DecimalException))
2784
2785        self.assertTrue(issubclass(decimal.ConversionSyntax, InvalidOperation))
2786        self.assertTrue(issubclass(decimal.DivisionImpossible, InvalidOperation))
2787        self.assertTrue(issubclass(decimal.DivisionUndefined, InvalidOperation))
2788        self.assertTrue(issubclass(decimal.DivisionUndefined, ZeroDivisionError))
2789        self.assertTrue(issubclass(decimal.InvalidContext, InvalidOperation))
2790
2791class CPythonAPItests(PythonAPItests):
2792    decimal = C
2793class PyPythonAPItests(PythonAPItests):
2794    decimal = P
2795
2796class ContextAPItests(unittest.TestCase):
2797
2798    def test_none_args(self):
2799        Context = self.decimal.Context
2800        InvalidOperation = self.decimal.InvalidOperation
2801        DivisionByZero = self.decimal.DivisionByZero
2802        Overflow = self.decimal.Overflow
2803
2804        c1 = Context()
2805        c2 = Context(prec=None, rounding=None, Emax=None, Emin=None,
2806                     capitals=None, clamp=None, flags=None, traps=None)
2807        for c in [c1, c2]:
2808            self.assertEqual(c.prec, 28)
2809            self.assertEqual(c.rounding, ROUND_HALF_EVEN)
2810            self.assertEqual(c.Emax, 999999)
2811            self.assertEqual(c.Emin, -999999)
2812            self.assertEqual(c.capitals, 1)
2813            self.assertEqual(c.clamp, 0)
2814            assert_signals(self, c, 'flags', [])
2815            assert_signals(self, c, 'traps', [InvalidOperation, DivisionByZero,
2816                                              Overflow])
2817
2818    @cpython_only
2819    def test_from_legacy_strings(self):
2820        import _testcapi
2821        c = self.decimal.Context()
2822
2823        for rnd in RoundingModes:
2824            c.rounding = _testcapi.unicode_legacy_string(rnd)
2825            self.assertEqual(c.rounding, rnd)
2826
2827        s = _testcapi.unicode_legacy_string('')
2828        self.assertRaises(TypeError, setattr, c, 'rounding', s)
2829
2830        s = _testcapi.unicode_legacy_string('ROUND_\x00UP')
2831        self.assertRaises(TypeError, setattr, c, 'rounding', s)
2832
2833    def test_pickle(self):
2834
2835        for proto in range(pickle.HIGHEST_PROTOCOL + 1):
2836            Context = self.decimal.Context
2837
2838            savedecimal = sys.modules['decimal']
2839
2840            # Round trip
2841            sys.modules['decimal'] = self.decimal
2842            c = Context()
2843            e = pickle.loads(pickle.dumps(c, proto))
2844
2845            self.assertEqual(c.prec, e.prec)
2846            self.assertEqual(c.Emin, e.Emin)
2847            self.assertEqual(c.Emax, e.Emax)
2848            self.assertEqual(c.rounding, e.rounding)
2849            self.assertEqual(c.capitals, e.capitals)
2850            self.assertEqual(c.clamp, e.clamp)
2851            self.assertEqual(c.flags, e.flags)
2852            self.assertEqual(c.traps, e.traps)
2853
2854            # Test interchangeability
2855            combinations = [(C, P), (P, C)] if C else [(P, P)]
2856            for dumper, loader in combinations:
2857                for ri, _ in enumerate(RoundingModes):
2858                    for fi, _ in enumerate(OrderedSignals[dumper]):
2859                        for ti, _ in enumerate(OrderedSignals[dumper]):
2860
2861                            prec = random.randrange(1, 100)
2862                            emin = random.randrange(-100, 0)
2863                            emax = random.randrange(1, 100)
2864                            caps = random.randrange(2)
2865                            clamp = random.randrange(2)
2866
2867                            # One module dumps
2868                            sys.modules['decimal'] = dumper
2869                            c = dumper.Context(
2870                                  prec=prec, Emin=emin, Emax=emax,
2871                                  rounding=RoundingModes[ri],
2872                                  capitals=caps, clamp=clamp,
2873                                  flags=OrderedSignals[dumper][:fi],
2874                                  traps=OrderedSignals[dumper][:ti]
2875                            )
2876                            s = pickle.dumps(c, proto)
2877
2878                            # The other module loads
2879                            sys.modules['decimal'] = loader
2880                            d = pickle.loads(s)
2881                            self.assertIsInstance(d, loader.Context)
2882
2883                            self.assertEqual(d.prec, prec)
2884                            self.assertEqual(d.Emin, emin)
2885                            self.assertEqual(d.Emax, emax)
2886                            self.assertEqual(d.rounding, RoundingModes[ri])
2887                            self.assertEqual(d.capitals, caps)
2888                            self.assertEqual(d.clamp, clamp)
2889                            assert_signals(self, d, 'flags', OrderedSignals[loader][:fi])
2890                            assert_signals(self, d, 'traps', OrderedSignals[loader][:ti])
2891
2892            sys.modules['decimal'] = savedecimal
2893
2894    def test_equality_with_other_types(self):
2895        Decimal = self.decimal.Decimal
2896
2897        self.assertIn(Decimal(10), ['a', 1.0, Decimal(10), (1,2), {}])
2898        self.assertNotIn(Decimal(10), ['a', 1.0, (1,2), {}])
2899
2900    def test_copy(self):
2901        # All copies should be deep
2902        Decimal = self.decimal.Decimal
2903        Context = self.decimal.Context
2904
2905        c = Context()
2906        d = c.copy()
2907        self.assertNotEqual(id(c), id(d))
2908        self.assertNotEqual(id(c.flags), id(d.flags))
2909        self.assertNotEqual(id(c.traps), id(d.traps))
2910        k1 = set(c.flags.keys())
2911        k2 = set(d.flags.keys())
2912        self.assertEqual(k1, k2)
2913        self.assertEqual(c.flags, d.flags)
2914
2915    def test__clamp(self):
2916        # In Python 3.2, the private attribute `_clamp` was made
2917        # public (issue 8540), with the old `_clamp` becoming a
2918        # property wrapping `clamp`.  For the duration of Python 3.2
2919        # only, the attribute should be gettable/settable via both
2920        # `clamp` and `_clamp`; in Python 3.3, `_clamp` should be
2921        # removed.
2922        Context = self.decimal.Context
2923        c = Context()
2924        self.assertRaises(AttributeError, getattr, c, '_clamp')
2925
2926    def test_abs(self):
2927        Decimal = self.decimal.Decimal
2928        Context = self.decimal.Context
2929
2930        c = Context()
2931        d = c.abs(Decimal(-1))
2932        self.assertEqual(c.abs(-1), d)
2933        self.assertRaises(TypeError, c.abs, '-1')
2934
2935    def test_add(self):
2936        Decimal = self.decimal.Decimal
2937        Context = self.decimal.Context
2938
2939        c = Context()
2940        d = c.add(Decimal(1), Decimal(1))
2941        self.assertEqual(c.add(1, 1), d)
2942        self.assertEqual(c.add(Decimal(1), 1), d)
2943        self.assertEqual(c.add(1, Decimal(1)), d)
2944        self.assertRaises(TypeError, c.add, '1', 1)
2945        self.assertRaises(TypeError, c.add, 1, '1')
2946
2947    def test_compare(self):
2948        Decimal = self.decimal.Decimal
2949        Context = self.decimal.Context
2950
2951        c = Context()
2952        d = c.compare(Decimal(1), Decimal(1))
2953        self.assertEqual(c.compare(1, 1), d)
2954        self.assertEqual(c.compare(Decimal(1), 1), d)
2955        self.assertEqual(c.compare(1, Decimal(1)), d)
2956        self.assertRaises(TypeError, c.compare, '1', 1)
2957        self.assertRaises(TypeError, c.compare, 1, '1')
2958
2959    def test_compare_signal(self):
2960        Decimal = self.decimal.Decimal
2961        Context = self.decimal.Context
2962
2963        c = Context()
2964        d = c.compare_signal(Decimal(1), Decimal(1))
2965        self.assertEqual(c.compare_signal(1, 1), d)
2966        self.assertEqual(c.compare_signal(Decimal(1), 1), d)
2967        self.assertEqual(c.compare_signal(1, Decimal(1)), d)
2968        self.assertRaises(TypeError, c.compare_signal, '1', 1)
2969        self.assertRaises(TypeError, c.compare_signal, 1, '1')
2970
2971    def test_compare_total(self):
2972        Decimal = self.decimal.Decimal
2973        Context = self.decimal.Context
2974
2975        c = Context()
2976        d = c.compare_total(Decimal(1), Decimal(1))
2977        self.assertEqual(c.compare_total(1, 1), d)
2978        self.assertEqual(c.compare_total(Decimal(1), 1), d)
2979        self.assertEqual(c.compare_total(1, Decimal(1)), d)
2980        self.assertRaises(TypeError, c.compare_total, '1', 1)
2981        self.assertRaises(TypeError, c.compare_total, 1, '1')
2982
2983    def test_compare_total_mag(self):
2984        Decimal = self.decimal.Decimal
2985        Context = self.decimal.Context
2986
2987        c = Context()
2988        d = c.compare_total_mag(Decimal(1), Decimal(1))
2989        self.assertEqual(c.compare_total_mag(1, 1), d)
2990        self.assertEqual(c.compare_total_mag(Decimal(1), 1), d)
2991        self.assertEqual(c.compare_total_mag(1, Decimal(1)), d)
2992        self.assertRaises(TypeError, c.compare_total_mag, '1', 1)
2993        self.assertRaises(TypeError, c.compare_total_mag, 1, '1')
2994
2995    def test_copy_abs(self):
2996        Decimal = self.decimal.Decimal
2997        Context = self.decimal.Context
2998
2999        c = Context()
3000        d = c.copy_abs(Decimal(-1))
3001        self.assertEqual(c.copy_abs(-1), d)
3002        self.assertRaises(TypeError, c.copy_abs, '-1')
3003
3004    def test_copy_decimal(self):
3005        Decimal = self.decimal.Decimal
3006        Context = self.decimal.Context
3007
3008        c = Context()
3009        d = c.copy_decimal(Decimal(-1))
3010        self.assertEqual(c.copy_decimal(-1), d)
3011        self.assertRaises(TypeError, c.copy_decimal, '-1')
3012
3013    def test_copy_negate(self):
3014        Decimal = self.decimal.Decimal
3015        Context = self.decimal.Context
3016
3017        c = Context()
3018        d = c.copy_negate(Decimal(-1))
3019        self.assertEqual(c.copy_negate(-1), d)
3020        self.assertRaises(TypeError, c.copy_negate, '-1')
3021
3022    def test_copy_sign(self):
3023        Decimal = self.decimal.Decimal
3024        Context = self.decimal.Context
3025
3026        c = Context()
3027        d = c.copy_sign(Decimal(1), Decimal(-2))
3028        self.assertEqual(c.copy_sign(1, -2), d)
3029        self.assertEqual(c.copy_sign(Decimal(1), -2), d)
3030        self.assertEqual(c.copy_sign(1, Decimal(-2)), d)
3031        self.assertRaises(TypeError, c.copy_sign, '1', -2)
3032        self.assertRaises(TypeError, c.copy_sign, 1, '-2')
3033
3034    def test_divide(self):
3035        Decimal = self.decimal.Decimal
3036        Context = self.decimal.Context
3037
3038        c = Context()
3039        d = c.divide(Decimal(1), Decimal(2))
3040        self.assertEqual(c.divide(1, 2), d)
3041        self.assertEqual(c.divide(Decimal(1), 2), d)
3042        self.assertEqual(c.divide(1, Decimal(2)), d)
3043        self.assertRaises(TypeError, c.divide, '1', 2)
3044        self.assertRaises(TypeError, c.divide, 1, '2')
3045
3046    def test_divide_int(self):
3047        Decimal = self.decimal.Decimal
3048        Context = self.decimal.Context
3049
3050        c = Context()
3051        d = c.divide_int(Decimal(1), Decimal(2))
3052        self.assertEqual(c.divide_int(1, 2), d)
3053        self.assertEqual(c.divide_int(Decimal(1), 2), d)
3054        self.assertEqual(c.divide_int(1, Decimal(2)), d)
3055        self.assertRaises(TypeError, c.divide_int, '1', 2)
3056        self.assertRaises(TypeError, c.divide_int, 1, '2')
3057
3058    def test_divmod(self):
3059        Decimal = self.decimal.Decimal
3060        Context = self.decimal.Context
3061
3062        c = Context()
3063        d = c.divmod(Decimal(1), Decimal(2))
3064        self.assertEqual(c.divmod(1, 2), d)
3065        self.assertEqual(c.divmod(Decimal(1), 2), d)
3066        self.assertEqual(c.divmod(1, Decimal(2)), d)
3067        self.assertRaises(TypeError, c.divmod, '1', 2)
3068        self.assertRaises(TypeError, c.divmod, 1, '2')
3069
3070    def test_exp(self):
3071        Decimal = self.decimal.Decimal
3072        Context = self.decimal.Context
3073
3074        c = Context()
3075        d = c.exp(Decimal(10))
3076        self.assertEqual(c.exp(10), d)
3077        self.assertRaises(TypeError, c.exp, '10')
3078
3079    def test_fma(self):
3080        Decimal = self.decimal.Decimal
3081        Context = self.decimal.Context
3082
3083        c = Context()
3084        d = c.fma(Decimal(2), Decimal(3), Decimal(4))
3085        self.assertEqual(c.fma(2, 3, 4), d)
3086        self.assertEqual(c.fma(Decimal(2), 3, 4), d)
3087        self.assertEqual(c.fma(2, Decimal(3), 4), d)
3088        self.assertEqual(c.fma(2, 3, Decimal(4)), d)
3089        self.assertEqual(c.fma(Decimal(2), Decimal(3), 4), d)
3090        self.assertRaises(TypeError, c.fma, '2', 3, 4)
3091        self.assertRaises(TypeError, c.fma, 2, '3', 4)
3092        self.assertRaises(TypeError, c.fma, 2, 3, '4')
3093
3094        # Issue 12079 for Context.fma ...
3095        self.assertRaises(TypeError, c.fma,
3096                          Decimal('Infinity'), Decimal(0), "not a decimal")
3097        self.assertRaises(TypeError, c.fma,
3098                          Decimal(1), Decimal('snan'), 1.222)
3099        # ... and for Decimal.fma.
3100        self.assertRaises(TypeError, Decimal('Infinity').fma,
3101                          Decimal(0), "not a decimal")
3102        self.assertRaises(TypeError, Decimal(1).fma,
3103                          Decimal('snan'), 1.222)
3104
3105    def test_is_finite(self):
3106        Decimal = self.decimal.Decimal
3107        Context = self.decimal.Context
3108
3109        c = Context()
3110        d = c.is_finite(Decimal(10))
3111        self.assertEqual(c.is_finite(10), d)
3112        self.assertRaises(TypeError, c.is_finite, '10')
3113
3114    def test_is_infinite(self):
3115        Decimal = self.decimal.Decimal
3116        Context = self.decimal.Context
3117
3118        c = Context()
3119        d = c.is_infinite(Decimal(10))
3120        self.assertEqual(c.is_infinite(10), d)
3121        self.assertRaises(TypeError, c.is_infinite, '10')
3122
3123    def test_is_nan(self):
3124        Decimal = self.decimal.Decimal
3125        Context = self.decimal.Context
3126
3127        c = Context()
3128        d = c.is_nan(Decimal(10))
3129        self.assertEqual(c.is_nan(10), d)
3130        self.assertRaises(TypeError, c.is_nan, '10')
3131
3132    def test_is_normal(self):
3133        Decimal = self.decimal.Decimal
3134        Context = self.decimal.Context
3135
3136        c = Context()
3137        d = c.is_normal(Decimal(10))
3138        self.assertEqual(c.is_normal(10), d)
3139        self.assertRaises(TypeError, c.is_normal, '10')
3140
3141    def test_is_qnan(self):
3142        Decimal = self.decimal.Decimal
3143        Context = self.decimal.Context
3144
3145        c = Context()
3146        d = c.is_qnan(Decimal(10))
3147        self.assertEqual(c.is_qnan(10), d)
3148        self.assertRaises(TypeError, c.is_qnan, '10')
3149
3150    def test_is_signed(self):
3151        Decimal = self.decimal.Decimal
3152        Context = self.decimal.Context
3153
3154        c = Context()
3155        d = c.is_signed(Decimal(10))
3156        self.assertEqual(c.is_signed(10), d)
3157        self.assertRaises(TypeError, c.is_signed, '10')
3158
3159    def test_is_snan(self):
3160        Decimal = self.decimal.Decimal
3161        Context = self.decimal.Context
3162
3163        c = Context()
3164        d = c.is_snan(Decimal(10))
3165        self.assertEqual(c.is_snan(10), d)
3166        self.assertRaises(TypeError, c.is_snan, '10')
3167
3168    def test_is_subnormal(self):
3169        Decimal = self.decimal.Decimal
3170        Context = self.decimal.Context
3171
3172        c = Context()
3173        d = c.is_subnormal(Decimal(10))
3174        self.assertEqual(c.is_subnormal(10), d)
3175        self.assertRaises(TypeError, c.is_subnormal, '10')
3176
3177    def test_is_zero(self):
3178        Decimal = self.decimal.Decimal
3179        Context = self.decimal.Context
3180
3181        c = Context()
3182        d = c.is_zero(Decimal(10))
3183        self.assertEqual(c.is_zero(10), d)
3184        self.assertRaises(TypeError, c.is_zero, '10')
3185
3186    def test_ln(self):
3187        Decimal = self.decimal.Decimal
3188        Context = self.decimal.Context
3189
3190        c = Context()
3191        d = c.ln(Decimal(10))
3192        self.assertEqual(c.ln(10), d)
3193        self.assertRaises(TypeError, c.ln, '10')
3194
3195    def test_log10(self):
3196        Decimal = self.decimal.Decimal
3197        Context = self.decimal.Context
3198
3199        c = Context()
3200        d = c.log10(Decimal(10))
3201        self.assertEqual(c.log10(10), d)
3202        self.assertRaises(TypeError, c.log10, '10')
3203
3204    def test_logb(self):
3205        Decimal = self.decimal.Decimal
3206        Context = self.decimal.Context
3207
3208        c = Context()
3209        d = c.logb(Decimal(10))
3210        self.assertEqual(c.logb(10), d)
3211        self.assertRaises(TypeError, c.logb, '10')
3212
3213    def test_logical_and(self):
3214        Decimal = self.decimal.Decimal
3215        Context = self.decimal.Context
3216
3217        c = Context()
3218        d = c.logical_and(Decimal(1), Decimal(1))
3219        self.assertEqual(c.logical_and(1, 1), d)
3220        self.assertEqual(c.logical_and(Decimal(1), 1), d)
3221        self.assertEqual(c.logical_and(1, Decimal(1)), d)
3222        self.assertRaises(TypeError, c.logical_and, '1', 1)
3223        self.assertRaises(TypeError, c.logical_and, 1, '1')
3224
3225    def test_logical_invert(self):
3226        Decimal = self.decimal.Decimal
3227        Context = self.decimal.Context
3228
3229        c = Context()
3230        d = c.logical_invert(Decimal(1000))
3231        self.assertEqual(c.logical_invert(1000), d)
3232        self.assertRaises(TypeError, c.logical_invert, '1000')
3233
3234    def test_logical_or(self):
3235        Decimal = self.decimal.Decimal
3236        Context = self.decimal.Context
3237
3238        c = Context()
3239        d = c.logical_or(Decimal(1), Decimal(1))
3240        self.assertEqual(c.logical_or(1, 1), d)
3241        self.assertEqual(c.logical_or(Decimal(1), 1), d)
3242        self.assertEqual(c.logical_or(1, Decimal(1)), d)
3243        self.assertRaises(TypeError, c.logical_or, '1', 1)
3244        self.assertRaises(TypeError, c.logical_or, 1, '1')
3245
3246    def test_logical_xor(self):
3247        Decimal = self.decimal.Decimal
3248        Context = self.decimal.Context
3249
3250        c = Context()
3251        d = c.logical_xor(Decimal(1), Decimal(1))
3252        self.assertEqual(c.logical_xor(1, 1), d)
3253        self.assertEqual(c.logical_xor(Decimal(1), 1), d)
3254        self.assertEqual(c.logical_xor(1, Decimal(1)), d)
3255        self.assertRaises(TypeError, c.logical_xor, '1', 1)
3256        self.assertRaises(TypeError, c.logical_xor, 1, '1')
3257
3258    def test_max(self):
3259        Decimal = self.decimal.Decimal
3260        Context = self.decimal.Context
3261
3262        c = Context()
3263        d = c.max(Decimal(1), Decimal(2))
3264        self.assertEqual(c.max(1, 2), d)
3265        self.assertEqual(c.max(Decimal(1), 2), d)
3266        self.assertEqual(c.max(1, Decimal(2)), d)
3267        self.assertRaises(TypeError, c.max, '1', 2)
3268        self.assertRaises(TypeError, c.max, 1, '2')
3269
3270    def test_max_mag(self):
3271        Decimal = self.decimal.Decimal
3272        Context = self.decimal.Context
3273
3274        c = Context()
3275        d = c.max_mag(Decimal(1), Decimal(2))
3276        self.assertEqual(c.max_mag(1, 2), d)
3277        self.assertEqual(c.max_mag(Decimal(1), 2), d)
3278        self.assertEqual(c.max_mag(1, Decimal(2)), d)
3279        self.assertRaises(TypeError, c.max_mag, '1', 2)
3280        self.assertRaises(TypeError, c.max_mag, 1, '2')
3281
3282    def test_min(self):
3283        Decimal = self.decimal.Decimal
3284        Context = self.decimal.Context
3285
3286        c = Context()
3287        d = c.min(Decimal(1), Decimal(2))
3288        self.assertEqual(c.min(1, 2), d)
3289        self.assertEqual(c.min(Decimal(1), 2), d)
3290        self.assertEqual(c.min(1, Decimal(2)), d)
3291        self.assertRaises(TypeError, c.min, '1', 2)
3292        self.assertRaises(TypeError, c.min, 1, '2')
3293
3294    def test_min_mag(self):
3295        Decimal = self.decimal.Decimal
3296        Context = self.decimal.Context
3297
3298        c = Context()
3299        d = c.min_mag(Decimal(1), Decimal(2))
3300        self.assertEqual(c.min_mag(1, 2), d)
3301        self.assertEqual(c.min_mag(Decimal(1), 2), d)
3302        self.assertEqual(c.min_mag(1, Decimal(2)), d)
3303        self.assertRaises(TypeError, c.min_mag, '1', 2)
3304        self.assertRaises(TypeError, c.min_mag, 1, '2')
3305
3306    def test_minus(self):
3307        Decimal = self.decimal.Decimal
3308        Context = self.decimal.Context
3309
3310        c = Context()
3311        d = c.minus(Decimal(10))
3312        self.assertEqual(c.minus(10), d)
3313        self.assertRaises(TypeError, c.minus, '10')
3314
3315    def test_multiply(self):
3316        Decimal = self.decimal.Decimal
3317        Context = self.decimal.Context
3318
3319        c = Context()
3320        d = c.multiply(Decimal(1), Decimal(2))
3321        self.assertEqual(c.multiply(1, 2), d)
3322        self.assertEqual(c.multiply(Decimal(1), 2), d)
3323        self.assertEqual(c.multiply(1, Decimal(2)), d)
3324        self.assertRaises(TypeError, c.multiply, '1', 2)
3325        self.assertRaises(TypeError, c.multiply, 1, '2')
3326
3327    def test_next_minus(self):
3328        Decimal = self.decimal.Decimal
3329        Context = self.decimal.Context
3330
3331        c = Context()
3332        d = c.next_minus(Decimal(10))
3333        self.assertEqual(c.next_minus(10), d)
3334        self.assertRaises(TypeError, c.next_minus, '10')
3335
3336    def test_next_plus(self):
3337        Decimal = self.decimal.Decimal
3338        Context = self.decimal.Context
3339
3340        c = Context()
3341        d = c.next_plus(Decimal(10))
3342        self.assertEqual(c.next_plus(10), d)
3343        self.assertRaises(TypeError, c.next_plus, '10')
3344
3345    def test_next_toward(self):
3346        Decimal = self.decimal.Decimal
3347        Context = self.decimal.Context
3348
3349        c = Context()
3350        d = c.next_toward(Decimal(1), Decimal(2))
3351        self.assertEqual(c.next_toward(1, 2), d)
3352        self.assertEqual(c.next_toward(Decimal(1), 2), d)
3353        self.assertEqual(c.next_toward(1, Decimal(2)), d)
3354        self.assertRaises(TypeError, c.next_toward, '1', 2)
3355        self.assertRaises(TypeError, c.next_toward, 1, '2')
3356
3357    def test_normalize(self):
3358        Decimal = self.decimal.Decimal
3359        Context = self.decimal.Context
3360
3361        c = Context()
3362        d = c.normalize(Decimal(10))
3363        self.assertEqual(c.normalize(10), d)
3364        self.assertRaises(TypeError, c.normalize, '10')
3365
3366    def test_number_class(self):
3367        Decimal = self.decimal.Decimal
3368        Context = self.decimal.Context
3369
3370        c = Context()
3371        self.assertEqual(c.number_class(123), c.number_class(Decimal(123)))
3372        self.assertEqual(c.number_class(0), c.number_class(Decimal(0)))
3373        self.assertEqual(c.number_class(-45), c.number_class(Decimal(-45)))
3374
3375    def test_plus(self):
3376        Decimal = self.decimal.Decimal
3377        Context = self.decimal.Context
3378
3379        c = Context()
3380        d = c.plus(Decimal(10))
3381        self.assertEqual(c.plus(10), d)
3382        self.assertRaises(TypeError, c.plus, '10')
3383
3384    def test_power(self):
3385        Decimal = self.decimal.Decimal
3386        Context = self.decimal.Context
3387
3388        c = Context()
3389        d = c.power(Decimal(1), Decimal(4))
3390        self.assertEqual(c.power(1, 4), d)
3391        self.assertEqual(c.power(Decimal(1), 4), d)
3392        self.assertEqual(c.power(1, Decimal(4)), d)
3393        self.assertEqual(c.power(Decimal(1), Decimal(4)), d)
3394        self.assertRaises(TypeError, c.power, '1', 4)
3395        self.assertRaises(TypeError, c.power, 1, '4')
3396        self.assertEqual(c.power(modulo=5, b=8, a=2), 1)
3397
3398    def test_quantize(self):
3399        Decimal = self.decimal.Decimal
3400        Context = self.decimal.Context
3401
3402        c = Context()
3403        d = c.quantize(Decimal(1), Decimal(2))
3404        self.assertEqual(c.quantize(1, 2), d)
3405        self.assertEqual(c.quantize(Decimal(1), 2), d)
3406        self.assertEqual(c.quantize(1, Decimal(2)), d)
3407        self.assertRaises(TypeError, c.quantize, '1', 2)
3408        self.assertRaises(TypeError, c.quantize, 1, '2')
3409
3410    def test_remainder(self):
3411        Decimal = self.decimal.Decimal
3412        Context = self.decimal.Context
3413
3414        c = Context()
3415        d = c.remainder(Decimal(1), Decimal(2))
3416        self.assertEqual(c.remainder(1, 2), d)
3417        self.assertEqual(c.remainder(Decimal(1), 2), d)
3418        self.assertEqual(c.remainder(1, Decimal(2)), d)
3419        self.assertRaises(TypeError, c.remainder, '1', 2)
3420        self.assertRaises(TypeError, c.remainder, 1, '2')
3421
3422    def test_remainder_near(self):
3423        Decimal = self.decimal.Decimal
3424        Context = self.decimal.Context
3425
3426        c = Context()
3427        d = c.remainder_near(Decimal(1), Decimal(2))
3428        self.assertEqual(c.remainder_near(1, 2), d)
3429        self.assertEqual(c.remainder_near(Decimal(1), 2), d)
3430        self.assertEqual(c.remainder_near(1, Decimal(2)), d)
3431        self.assertRaises(TypeError, c.remainder_near, '1', 2)
3432        self.assertRaises(TypeError, c.remainder_near, 1, '2')
3433
3434    def test_rotate(self):
3435        Decimal = self.decimal.Decimal
3436        Context = self.decimal.Context
3437
3438        c = Context()
3439        d = c.rotate(Decimal(1), Decimal(2))
3440        self.assertEqual(c.rotate(1, 2), d)
3441        self.assertEqual(c.rotate(Decimal(1), 2), d)
3442        self.assertEqual(c.rotate(1, Decimal(2)), d)
3443        self.assertRaises(TypeError, c.rotate, '1', 2)
3444        self.assertRaises(TypeError, c.rotate, 1, '2')
3445
3446    def test_sqrt(self):
3447        Decimal = self.decimal.Decimal
3448        Context = self.decimal.Context
3449
3450        c = Context()
3451        d = c.sqrt(Decimal(10))
3452        self.assertEqual(c.sqrt(10), d)
3453        self.assertRaises(TypeError, c.sqrt, '10')
3454
3455    def test_same_quantum(self):
3456        Decimal = self.decimal.Decimal
3457        Context = self.decimal.Context
3458
3459        c = Context()
3460        d = c.same_quantum(Decimal(1), Decimal(2))
3461        self.assertEqual(c.same_quantum(1, 2), d)
3462        self.assertEqual(c.same_quantum(Decimal(1), 2), d)
3463        self.assertEqual(c.same_quantum(1, Decimal(2)), d)
3464        self.assertRaises(TypeError, c.same_quantum, '1', 2)
3465        self.assertRaises(TypeError, c.same_quantum, 1, '2')
3466
3467    def test_scaleb(self):
3468        Decimal = self.decimal.Decimal
3469        Context = self.decimal.Context
3470
3471        c = Context()
3472        d = c.scaleb(Decimal(1), Decimal(2))
3473        self.assertEqual(c.scaleb(1, 2), d)
3474        self.assertEqual(c.scaleb(Decimal(1), 2), d)
3475        self.assertEqual(c.scaleb(1, Decimal(2)), d)
3476        self.assertRaises(TypeError, c.scaleb, '1', 2)
3477        self.assertRaises(TypeError, c.scaleb, 1, '2')
3478
3479    def test_shift(self):
3480        Decimal = self.decimal.Decimal
3481        Context = self.decimal.Context
3482
3483        c = Context()
3484        d = c.shift(Decimal(1), Decimal(2))
3485        self.assertEqual(c.shift(1, 2), d)
3486        self.assertEqual(c.shift(Decimal(1), 2), d)
3487        self.assertEqual(c.shift(1, Decimal(2)), d)
3488        self.assertRaises(TypeError, c.shift, '1', 2)
3489        self.assertRaises(TypeError, c.shift, 1, '2')
3490
3491    def test_subtract(self):
3492        Decimal = self.decimal.Decimal
3493        Context = self.decimal.Context
3494
3495        c = Context()
3496        d = c.subtract(Decimal(1), Decimal(2))
3497        self.assertEqual(c.subtract(1, 2), d)
3498        self.assertEqual(c.subtract(Decimal(1), 2), d)
3499        self.assertEqual(c.subtract(1, Decimal(2)), d)
3500        self.assertRaises(TypeError, c.subtract, '1', 2)
3501        self.assertRaises(TypeError, c.subtract, 1, '2')
3502
3503    def test_to_eng_string(self):
3504        Decimal = self.decimal.Decimal
3505        Context = self.decimal.Context
3506
3507        c = Context()
3508        d = c.to_eng_string(Decimal(10))
3509        self.assertEqual(c.to_eng_string(10), d)
3510        self.assertRaises(TypeError, c.to_eng_string, '10')
3511
3512    def test_to_sci_string(self):
3513        Decimal = self.decimal.Decimal
3514        Context = self.decimal.Context
3515
3516        c = Context()
3517        d = c.to_sci_string(Decimal(10))
3518        self.assertEqual(c.to_sci_string(10), d)
3519        self.assertRaises(TypeError, c.to_sci_string, '10')
3520
3521    def test_to_integral_exact(self):
3522        Decimal = self.decimal.Decimal
3523        Context = self.decimal.Context
3524
3525        c = Context()
3526        d = c.to_integral_exact(Decimal(10))
3527        self.assertEqual(c.to_integral_exact(10), d)
3528        self.assertRaises(TypeError, c.to_integral_exact, '10')
3529
3530    def test_to_integral_value(self):
3531        Decimal = self.decimal.Decimal
3532        Context = self.decimal.Context
3533
3534        c = Context()
3535        d = c.to_integral_value(Decimal(10))
3536        self.assertEqual(c.to_integral_value(10), d)
3537        self.assertRaises(TypeError, c.to_integral_value, '10')
3538        self.assertRaises(TypeError, c.to_integral_value, 10, 'x')
3539
3540class CContextAPItests(ContextAPItests):
3541    decimal = C
3542class PyContextAPItests(ContextAPItests):
3543    decimal = P
3544
3545class ContextWithStatement(unittest.TestCase):
3546    # Can't do these as docstrings until Python 2.6
3547    # as doctest can't handle __future__ statements
3548
3549    def test_localcontext(self):
3550        # Use a copy of the current context in the block
3551        getcontext = self.decimal.getcontext
3552        localcontext = self.decimal.localcontext
3553
3554        orig_ctx = getcontext()
3555        with localcontext() as enter_ctx:
3556            set_ctx = getcontext()
3557        final_ctx = getcontext()
3558        self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
3559        self.assertIsNot(orig_ctx, set_ctx, 'did not copy the context')
3560        self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
3561
3562    def test_localcontextarg(self):
3563        # Use a copy of the supplied context in the block
3564        Context = self.decimal.Context
3565        getcontext = self.decimal.getcontext
3566        localcontext = self.decimal.localcontext
3567
3568        localcontext = self.decimal.localcontext
3569        orig_ctx = getcontext()
3570        new_ctx = Context(prec=42)
3571        with localcontext(new_ctx) as enter_ctx:
3572            set_ctx = getcontext()
3573        final_ctx = getcontext()
3574        self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
3575        self.assertEqual(set_ctx.prec, new_ctx.prec, 'did not set correct context')
3576        self.assertIsNot(new_ctx, set_ctx, 'did not copy the context')
3577        self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
3578
3579    def test_nested_with_statements(self):
3580        # Use a copy of the supplied context in the block
3581        Decimal = self.decimal.Decimal
3582        Context = self.decimal.Context
3583        getcontext = self.decimal.getcontext
3584        localcontext = self.decimal.localcontext
3585        Clamped = self.decimal.Clamped
3586        Overflow = self.decimal.Overflow
3587
3588        orig_ctx = getcontext()
3589        orig_ctx.clear_flags()
3590        new_ctx = Context(Emax=384)
3591        with localcontext() as c1:
3592            self.assertEqual(c1.flags, orig_ctx.flags)
3593            self.assertEqual(c1.traps, orig_ctx.traps)
3594            c1.traps[Clamped] = True
3595            c1.Emin = -383
3596            self.assertNotEqual(orig_ctx.Emin, -383)
3597            self.assertRaises(Clamped, c1.create_decimal, '0e-999')
3598            self.assertTrue(c1.flags[Clamped])
3599            with localcontext(new_ctx) as c2:
3600                self.assertEqual(c2.flags, new_ctx.flags)
3601                self.assertEqual(c2.traps, new_ctx.traps)
3602                self.assertRaises(Overflow, c2.power, Decimal('3.4e200'), 2)
3603                self.assertFalse(c2.flags[Clamped])
3604                self.assertTrue(c2.flags[Overflow])
3605                del c2
3606            self.assertFalse(c1.flags[Overflow])
3607            del c1
3608        self.assertNotEqual(orig_ctx.Emin, -383)
3609        self.assertFalse(orig_ctx.flags[Clamped])
3610        self.assertFalse(orig_ctx.flags[Overflow])
3611        self.assertFalse(new_ctx.flags[Clamped])
3612        self.assertFalse(new_ctx.flags[Overflow])
3613
3614    def test_with_statements_gc1(self):
3615        localcontext = self.decimal.localcontext
3616
3617        with localcontext() as c1:
3618            del c1
3619            with localcontext() as c2:
3620                del c2
3621                with localcontext() as c3:
3622                    del c3
3623                    with localcontext() as c4:
3624                        del c4
3625
3626    def test_with_statements_gc2(self):
3627        localcontext = self.decimal.localcontext
3628
3629        with localcontext() as c1:
3630            with localcontext(c1) as c2:
3631                del c1
3632                with localcontext(c2) as c3:
3633                    del c2
3634                    with localcontext(c3) as c4:
3635                        del c3
3636                        del c4
3637
3638    def test_with_statements_gc3(self):
3639        Context = self.decimal.Context
3640        localcontext = self.decimal.localcontext
3641        getcontext = self.decimal.getcontext
3642        setcontext = self.decimal.setcontext
3643
3644        with localcontext() as c1:
3645            del c1
3646            n1 = Context(prec=1)
3647            setcontext(n1)
3648            with localcontext(n1) as c2:
3649                del n1
3650                self.assertEqual(c2.prec, 1)
3651                del c2
3652                n2 = Context(prec=2)
3653                setcontext(n2)
3654                del n2
3655                self.assertEqual(getcontext().prec, 2)
3656                n3 = Context(prec=3)
3657                setcontext(n3)
3658                self.assertEqual(getcontext().prec, 3)
3659                with localcontext(n3) as c3:
3660                    del n3
3661                    self.assertEqual(c3.prec, 3)
3662                    del c3
3663                    n4 = Context(prec=4)
3664                    setcontext(n4)
3665                    del n4
3666                    self.assertEqual(getcontext().prec, 4)
3667                    with localcontext() as c4:
3668                        self.assertEqual(c4.prec, 4)
3669                        del c4
3670
3671class CContextWithStatement(ContextWithStatement):
3672    decimal = C
3673class PyContextWithStatement(ContextWithStatement):
3674    decimal = P
3675
3676class ContextFlags(unittest.TestCase):
3677
3678    def test_flags_irrelevant(self):
3679        # check that the result (numeric result + flags raised) of an
3680        # arithmetic operation doesn't depend on the current flags
3681        Decimal = self.decimal.Decimal
3682        Context = self.decimal.Context
3683        Inexact = self.decimal.Inexact
3684        Rounded = self.decimal.Rounded
3685        Underflow = self.decimal.Underflow
3686        Clamped = self.decimal.Clamped
3687        Subnormal = self.decimal.Subnormal
3688
3689        def raise_error(context, flag):
3690            if self.decimal == C:
3691                context.flags[flag] = True
3692                if context.traps[flag]:
3693                    raise flag
3694            else:
3695                context._raise_error(flag)
3696
3697        context = Context(prec=9, Emin = -425000000, Emax = 425000000,
3698                          rounding=ROUND_HALF_EVEN, traps=[], flags=[])
3699
3700        # operations that raise various flags, in the form (function, arglist)
3701        operations = [
3702            (context._apply, [Decimal("100E-425000010")]),
3703            (context.sqrt, [Decimal(2)]),
3704            (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]),
3705            (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]),
3706            (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]),
3707            ]
3708
3709        # try various flags individually, then a whole lot at once
3710        flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal],
3711                    [Inexact, Rounded, Underflow, Clamped, Subnormal]]
3712
3713        for fn, args in operations:
3714            # find answer and flags raised using a clean context
3715            context.clear_flags()
3716            ans = fn(*args)
3717            flags = [k for k, v in context.flags.items() if v]
3718
3719            for extra_flags in flagsets:
3720                # set flags, before calling operation
3721                context.clear_flags()
3722                for flag in extra_flags:
3723                    raise_error(context, flag)
3724                new_ans = fn(*args)
3725
3726                # flags that we expect to be set after the operation
3727                expected_flags = list(flags)
3728                for flag in extra_flags:
3729                    if flag not in expected_flags:
3730                        expected_flags.append(flag)
3731                expected_flags.sort(key=id)
3732
3733                # flags we actually got
3734                new_flags = [k for k,v in context.flags.items() if v]
3735                new_flags.sort(key=id)
3736
3737                self.assertEqual(ans, new_ans,
3738                                 "operation produces different answers depending on flags set: " +
3739                                 "expected %s, got %s." % (ans, new_ans))
3740                self.assertEqual(new_flags, expected_flags,
3741                                  "operation raises different flags depending on flags set: " +
3742                                  "expected %s, got %s" % (expected_flags, new_flags))
3743
3744    def test_flag_comparisons(self):
3745        Context = self.decimal.Context
3746        Inexact = self.decimal.Inexact
3747        Rounded = self.decimal.Rounded
3748
3749        c = Context()
3750
3751        # Valid SignalDict
3752        self.assertNotEqual(c.flags, c.traps)
3753        self.assertNotEqual(c.traps, c.flags)
3754
3755        c.flags = c.traps
3756        self.assertEqual(c.flags, c.traps)
3757        self.assertEqual(c.traps, c.flags)
3758
3759        c.flags[Rounded] = True
3760        c.traps = c.flags
3761        self.assertEqual(c.flags, c.traps)
3762        self.assertEqual(c.traps, c.flags)
3763
3764        d = {}
3765        d.update(c.flags)
3766        self.assertEqual(d, c.flags)
3767        self.assertEqual(c.flags, d)
3768
3769        d[Inexact] = True
3770        self.assertNotEqual(d, c.flags)
3771        self.assertNotEqual(c.flags, d)
3772
3773        # Invalid SignalDict
3774        d = {Inexact:False}
3775        self.assertNotEqual(d, c.flags)
3776        self.assertNotEqual(c.flags, d)
3777
3778        d = ["xyz"]
3779        self.assertNotEqual(d, c.flags)
3780        self.assertNotEqual(c.flags, d)
3781
3782    @requires_IEEE_754
3783    def test_float_operation(self):
3784        Decimal = self.decimal.Decimal
3785        FloatOperation = self.decimal.FloatOperation
3786        localcontext = self.decimal.localcontext
3787
3788        with localcontext() as c:
3789            ##### trap is off by default
3790            self.assertFalse(c.traps[FloatOperation])
3791
3792            # implicit conversion sets the flag
3793            c.clear_flags()
3794            self.assertEqual(Decimal(7.5), 7.5)
3795            self.assertTrue(c.flags[FloatOperation])
3796
3797            c.clear_flags()
3798            self.assertEqual(c.create_decimal(7.5), 7.5)
3799            self.assertTrue(c.flags[FloatOperation])
3800
3801            # explicit conversion does not set the flag
3802            c.clear_flags()
3803            x = Decimal.from_float(7.5)
3804            self.assertFalse(c.flags[FloatOperation])
3805            # comparison sets the flag
3806            self.assertEqual(x, 7.5)
3807            self.assertTrue(c.flags[FloatOperation])
3808
3809            c.clear_flags()
3810            x = c.create_decimal_from_float(7.5)
3811            self.assertFalse(c.flags[FloatOperation])
3812            self.assertEqual(x, 7.5)
3813            self.assertTrue(c.flags[FloatOperation])
3814
3815            ##### set the trap
3816            c.traps[FloatOperation] = True
3817
3818            # implicit conversion raises
3819            c.clear_flags()
3820            self.assertRaises(FloatOperation, Decimal, 7.5)
3821            self.assertTrue(c.flags[FloatOperation])
3822
3823            c.clear_flags()
3824            self.assertRaises(FloatOperation, c.create_decimal, 7.5)
3825            self.assertTrue(c.flags[FloatOperation])
3826
3827            # explicit conversion is silent
3828            c.clear_flags()
3829            x = Decimal.from_float(7.5)
3830            self.assertFalse(c.flags[FloatOperation])
3831
3832            c.clear_flags()
3833            x = c.create_decimal_from_float(7.5)
3834            self.assertFalse(c.flags[FloatOperation])
3835
3836    def test_float_comparison(self):
3837        Decimal = self.decimal.Decimal
3838        Context = self.decimal.Context
3839        FloatOperation = self.decimal.FloatOperation
3840        localcontext = self.decimal.localcontext
3841
3842        def assert_attr(a, b, attr, context, signal=None):
3843            context.clear_flags()
3844            f = getattr(a, attr)
3845            if signal == FloatOperation:
3846                self.assertRaises(signal, f, b)
3847            else:
3848                self.assertIs(f(b), True)
3849            self.assertTrue(context.flags[FloatOperation])
3850
3851        small_d = Decimal('0.25')
3852        big_d = Decimal('3.0')
3853        small_f = 0.25
3854        big_f = 3.0
3855
3856        zero_d = Decimal('0.0')
3857        neg_zero_d = Decimal('-0.0')
3858        zero_f = 0.0
3859        neg_zero_f = -0.0
3860
3861        inf_d = Decimal('Infinity')
3862        neg_inf_d = Decimal('-Infinity')
3863        inf_f = float('inf')
3864        neg_inf_f = float('-inf')
3865
3866        def doit(c, signal=None):
3867            # Order
3868            for attr in '__lt__', '__le__':
3869                assert_attr(small_d, big_f, attr, c, signal)
3870
3871            for attr in '__gt__', '__ge__':
3872                assert_attr(big_d, small_f, attr, c, signal)
3873
3874            # Equality
3875            assert_attr(small_d, small_f, '__eq__', c, None)
3876
3877            assert_attr(neg_zero_d, neg_zero_f, '__eq__', c, None)
3878            assert_attr(neg_zero_d, zero_f, '__eq__', c, None)
3879
3880            assert_attr(zero_d, neg_zero_f, '__eq__', c, None)
3881            assert_attr(zero_d, zero_f, '__eq__', c, None)
3882
3883            assert_attr(neg_inf_d, neg_inf_f, '__eq__', c, None)
3884            assert_attr(inf_d, inf_f, '__eq__', c, None)
3885
3886            # Inequality
3887            assert_attr(small_d, big_f, '__ne__', c, None)
3888
3889            assert_attr(Decimal('0.1'), 0.1, '__ne__', c, None)
3890
3891            assert_attr(neg_inf_d, inf_f, '__ne__', c, None)
3892            assert_attr(inf_d, neg_inf_f, '__ne__', c, None)
3893
3894            assert_attr(Decimal('NaN'), float('nan'), '__ne__', c, None)
3895
3896        def test_containers(c, signal=None):
3897            c.clear_flags()
3898            s = set([100.0, Decimal('100.0')])
3899            self.assertEqual(len(s), 1)
3900            self.assertTrue(c.flags[FloatOperation])
3901
3902            c.clear_flags()
3903            if signal:
3904                self.assertRaises(signal, sorted, [1.0, Decimal('10.0')])
3905            else:
3906                s = sorted([10.0, Decimal('10.0')])
3907            self.assertTrue(c.flags[FloatOperation])
3908
3909            c.clear_flags()
3910            b = 10.0 in [Decimal('10.0'), 1.0]
3911            self.assertTrue(c.flags[FloatOperation])
3912
3913            c.clear_flags()
3914            b = 10.0 in {Decimal('10.0'):'a', 1.0:'b'}
3915            self.assertTrue(c.flags[FloatOperation])
3916
3917        nc = Context()
3918        with localcontext(nc) as c:
3919            self.assertFalse(c.traps[FloatOperation])
3920            doit(c, signal=None)
3921            test_containers(c, signal=None)
3922
3923            c.traps[FloatOperation] = True
3924            doit(c, signal=FloatOperation)
3925            test_containers(c, signal=FloatOperation)
3926
3927    def test_float_operation_default(self):
3928        Decimal = self.decimal.Decimal
3929        Context = self.decimal.Context
3930        Inexact = self.decimal.Inexact
3931        FloatOperation= self.decimal.FloatOperation
3932
3933        context = Context()
3934        self.assertFalse(context.flags[FloatOperation])
3935        self.assertFalse(context.traps[FloatOperation])
3936
3937        context.clear_traps()
3938        context.traps[Inexact] = True
3939        context.traps[FloatOperation] = True
3940        self.assertTrue(context.traps[FloatOperation])
3941        self.assertTrue(context.traps[Inexact])
3942
3943class CContextFlags(ContextFlags):
3944    decimal = C
3945class PyContextFlags(ContextFlags):
3946    decimal = P
3947
3948class SpecialContexts(unittest.TestCase):
3949    """Test the context templates."""
3950
3951    def test_context_templates(self):
3952        BasicContext = self.decimal.BasicContext
3953        ExtendedContext = self.decimal.ExtendedContext
3954        getcontext = self.decimal.getcontext
3955        setcontext = self.decimal.setcontext
3956        InvalidOperation = self.decimal.InvalidOperation
3957        DivisionByZero = self.decimal.DivisionByZero
3958        Overflow = self.decimal.Overflow
3959        Underflow = self.decimal.Underflow
3960        Clamped = self.decimal.Clamped
3961
3962        assert_signals(self, BasicContext, 'traps',
3963            [InvalidOperation, DivisionByZero, Overflow, Underflow, Clamped]
3964        )
3965
3966        savecontext = getcontext().copy()
3967        basic_context_prec = BasicContext.prec
3968        extended_context_prec = ExtendedContext.prec
3969
3970        ex = None
3971        try:
3972            BasicContext.prec = ExtendedContext.prec = 441
3973            for template in BasicContext, ExtendedContext:
3974                setcontext(template)
3975                c = getcontext()
3976                self.assertIsNot(c, template)
3977                self.assertEqual(c.prec, 441)
3978        except Exception as e:
3979            ex = e.__class__
3980        finally:
3981            BasicContext.prec = basic_context_prec
3982            ExtendedContext.prec = extended_context_prec
3983            setcontext(savecontext)
3984            if ex:
3985                raise ex
3986
3987    def test_default_context(self):
3988        DefaultContext = self.decimal.DefaultContext
3989        BasicContext = self.decimal.BasicContext
3990        ExtendedContext = self.decimal.ExtendedContext
3991        getcontext = self.decimal.getcontext
3992        setcontext = self.decimal.setcontext
3993        InvalidOperation = self.decimal.InvalidOperation
3994        DivisionByZero = self.decimal.DivisionByZero
3995        Overflow = self.decimal.Overflow
3996
3997        self.assertEqual(BasicContext.prec, 9)
3998        self.assertEqual(ExtendedContext.prec, 9)
3999
4000        assert_signals(self, DefaultContext, 'traps',
4001            [InvalidOperation, DivisionByZero, Overflow]
4002        )
4003
4004        savecontext = getcontext().copy()
4005        default_context_prec = DefaultContext.prec
4006
4007        ex = None
4008        try:
4009            c = getcontext()
4010            saveprec = c.prec
4011
4012            DefaultContext.prec = 961
4013            c = getcontext()
4014            self.assertEqual(c.prec, saveprec)
4015
4016            setcontext(DefaultContext)
4017            c = getcontext()
4018            self.assertIsNot(c, DefaultContext)
4019            self.assertEqual(c.prec, 961)
4020        except Exception as e:
4021            ex = e.__class__
4022        finally:
4023            DefaultContext.prec = default_context_prec
4024            setcontext(savecontext)
4025            if ex:
4026                raise ex
4027
4028class CSpecialContexts(SpecialContexts):
4029    decimal = C
4030class PySpecialContexts(SpecialContexts):
4031    decimal = P
4032
4033class ContextInputValidation(unittest.TestCase):
4034
4035    def test_invalid_context(self):
4036        Context = self.decimal.Context
4037        DefaultContext = self.decimal.DefaultContext
4038
4039        c = DefaultContext.copy()
4040
4041        # prec, Emax
4042        for attr in ['prec', 'Emax']:
4043            setattr(c, attr, 999999)
4044            self.assertEqual(getattr(c, attr), 999999)
4045            self.assertRaises(ValueError, setattr, c, attr, -1)
4046            self.assertRaises(TypeError, setattr, c, attr, 'xyz')
4047
4048        # Emin
4049        setattr(c, 'Emin', -999999)
4050        self.assertEqual(getattr(c, 'Emin'), -999999)
4051        self.assertRaises(ValueError, setattr, c, 'Emin', 1)
4052        self.assertRaises(TypeError, setattr, c, 'Emin', (1,2,3))
4053
4054        self.assertRaises(TypeError, setattr, c, 'rounding', -1)
4055        self.assertRaises(TypeError, setattr, c, 'rounding', 9)
4056        self.assertRaises(TypeError, setattr, c, 'rounding', 1.0)
4057        self.assertRaises(TypeError, setattr, c, 'rounding', 'xyz')
4058
4059        # capitals, clamp
4060        for attr in ['capitals', 'clamp']:
4061            self.assertRaises(ValueError, setattr, c, attr, -1)
4062            self.assertRaises(ValueError, setattr, c, attr, 2)
4063            self.assertRaises(TypeError, setattr, c, attr, [1,2,3])
4064
4065        # Invalid attribute
4066        self.assertRaises(AttributeError, setattr, c, 'emax', 100)
4067
4068        # Invalid signal dict
4069        self.assertRaises(TypeError, setattr, c, 'flags', [])
4070        self.assertRaises(KeyError, setattr, c, 'flags', {})
4071        self.assertRaises(KeyError, setattr, c, 'traps',
4072                          {'InvalidOperation':0})
4073
4074        # Attributes cannot be deleted
4075        for attr in ['prec', 'Emax', 'Emin', 'rounding', 'capitals', 'clamp',
4076                     'flags', 'traps']:
4077            self.assertRaises(AttributeError, c.__delattr__, attr)
4078
4079        # Invalid attributes
4080        self.assertRaises(TypeError, getattr, c, 9)
4081        self.assertRaises(TypeError, setattr, c, 9)
4082
4083        # Invalid values in constructor
4084        self.assertRaises(TypeError, Context, rounding=999999)
4085        self.assertRaises(TypeError, Context, rounding='xyz')
4086        self.assertRaises(ValueError, Context, clamp=2)
4087        self.assertRaises(ValueError, Context, capitals=-1)
4088        self.assertRaises(KeyError, Context, flags=["P"])
4089        self.assertRaises(KeyError, Context, traps=["Q"])
4090
4091        # Type error in conversion
4092        self.assertRaises(TypeError, Context, flags=(0,1))
4093        self.assertRaises(TypeError, Context, traps=(1,0))
4094
4095class CContextInputValidation(ContextInputValidation):
4096    decimal = C
4097class PyContextInputValidation(ContextInputValidation):
4098    decimal = P
4099
4100class ContextSubclassing(unittest.TestCase):
4101
4102    def test_context_subclassing(self):
4103        decimal = self.decimal
4104        Decimal = decimal.Decimal
4105        Context = decimal.Context
4106        Clamped = decimal.Clamped
4107        DivisionByZero = decimal.DivisionByZero
4108        Inexact = decimal.Inexact
4109        Overflow = decimal.Overflow
4110        Rounded = decimal.Rounded
4111        Subnormal = decimal.Subnormal
4112        Underflow = decimal.Underflow
4113        InvalidOperation = decimal.InvalidOperation
4114
4115        class MyContext(Context):
4116            def __init__(self, prec=None, rounding=None, Emin=None, Emax=None,
4117                               capitals=None, clamp=None, flags=None,
4118                               traps=None):
4119                Context.__init__(self)
4120                if prec is not None:
4121                    self.prec = prec
4122                if rounding is not None:
4123                    self.rounding = rounding
4124                if Emin is not None:
4125                    self.Emin = Emin
4126                if Emax is not None:
4127                    self.Emax = Emax
4128                if capitals is not None:
4129                    self.capitals = capitals
4130                if clamp is not None:
4131                    self.clamp = clamp
4132                if flags is not None:
4133                    if isinstance(flags, list):
4134                        flags = {v:(v in flags) for v in OrderedSignals[decimal] + flags}
4135                    self.flags = flags
4136                if traps is not None:
4137                    if isinstance(traps, list):
4138                        traps = {v:(v in traps) for v in OrderedSignals[decimal] + traps}
4139                    self.traps = traps
4140
4141        c = Context()
4142        d = MyContext()
4143        for attr in ('prec', 'rounding', 'Emin', 'Emax', 'capitals', 'clamp',
4144                     'flags', 'traps'):
4145            self.assertEqual(getattr(c, attr), getattr(d, attr))
4146
4147        # prec
4148        self.assertRaises(ValueError, MyContext, **{'prec':-1})
4149        c = MyContext(prec=1)
4150        self.assertEqual(c.prec, 1)
4151        self.assertRaises(InvalidOperation, c.quantize, Decimal('9e2'), 0)
4152
4153        # rounding
4154        self.assertRaises(TypeError, MyContext, **{'rounding':'XYZ'})
4155        c = MyContext(rounding=ROUND_DOWN, prec=1)
4156        self.assertEqual(c.rounding, ROUND_DOWN)
4157        self.assertEqual(c.plus(Decimal('9.9')), 9)
4158
4159        # Emin
4160        self.assertRaises(ValueError, MyContext, **{'Emin':5})
4161        c = MyContext(Emin=-1, prec=1)
4162        self.assertEqual(c.Emin, -1)
4163        x = c.add(Decimal('1e-99'), Decimal('2.234e-2000'))
4164        self.assertEqual(x, Decimal('0.0'))
4165        for signal in (Inexact, Underflow, Subnormal, Rounded, Clamped):
4166            self.assertTrue(c.flags[signal])
4167
4168        # Emax
4169        self.assertRaises(ValueError, MyContext, **{'Emax':-1})
4170        c = MyContext(Emax=1, prec=1)
4171        self.assertEqual(c.Emax, 1)
4172        self.assertRaises(Overflow, c.add, Decimal('1e99'), Decimal('2.234e2000'))
4173        if self.decimal == C:
4174            for signal in (Inexact, Overflow, Rounded):
4175                self.assertTrue(c.flags[signal])
4176
4177        # capitals
4178        self.assertRaises(ValueError, MyContext, **{'capitals':-1})
4179        c = MyContext(capitals=0)
4180        self.assertEqual(c.capitals, 0)
4181        x = c.create_decimal('1E222')
4182        self.assertEqual(c.to_sci_string(x), '1e+222')
4183
4184        # clamp
4185        self.assertRaises(ValueError, MyContext, **{'clamp':2})
4186        c = MyContext(clamp=1, Emax=99)
4187        self.assertEqual(c.clamp, 1)
4188        x = c.plus(Decimal('1e99'))
4189        self.assertEqual(str(x), '1.000000000000000000000000000E+99')
4190
4191        # flags
4192        self.assertRaises(TypeError, MyContext, **{'flags':'XYZ'})
4193        c = MyContext(flags=[Rounded, DivisionByZero])
4194        for signal in (Rounded, DivisionByZero):
4195            self.assertTrue(c.flags[signal])
4196        c.clear_flags()
4197        for signal in OrderedSignals[decimal]:
4198            self.assertFalse(c.flags[signal])
4199
4200        # traps
4201        self.assertRaises(TypeError, MyContext, **{'traps':'XYZ'})
4202        c = MyContext(traps=[Rounded, DivisionByZero])
4203        for signal in (Rounded, DivisionByZero):
4204            self.assertTrue(c.traps[signal])
4205        c.clear_traps()
4206        for signal in OrderedSignals[decimal]:
4207            self.assertFalse(c.traps[signal])
4208
4209class CContextSubclassing(ContextSubclassing):
4210    decimal = C
4211class PyContextSubclassing(ContextSubclassing):
4212    decimal = P
4213
4214@skip_if_extra_functionality
4215class CheckAttributes(unittest.TestCase):
4216
4217    def test_module_attributes(self):
4218
4219        # Architecture dependent context limits
4220        self.assertEqual(C.MAX_PREC, P.MAX_PREC)
4221        self.assertEqual(C.MAX_EMAX, P.MAX_EMAX)
4222        self.assertEqual(C.MIN_EMIN, P.MIN_EMIN)
4223        self.assertEqual(C.MIN_ETINY, P.MIN_ETINY)
4224
4225        self.assertTrue(C.HAVE_THREADS is True or C.HAVE_THREADS is False)
4226        self.assertTrue(P.HAVE_THREADS is True or P.HAVE_THREADS is False)
4227
4228        self.assertEqual(C.__version__, P.__version__)
4229
4230        self.assertEqual(dir(C), dir(P))
4231
4232    def test_context_attributes(self):
4233
4234        x = [s for s in dir(C.Context()) if '__' in s or not s.startswith('_')]
4235        y = [s for s in dir(P.Context()) if '__' in s or not s.startswith('_')]
4236        self.assertEqual(set(x) - set(y), set())
4237
4238    def test_decimal_attributes(self):
4239
4240        x = [s for s in dir(C.Decimal(9)) if '__' in s or not s.startswith('_')]
4241        y = [s for s in dir(C.Decimal(9)) if '__' in s or not s.startswith('_')]
4242        self.assertEqual(set(x) - set(y), set())
4243
4244class Coverage(unittest.TestCase):
4245
4246    def test_adjusted(self):
4247        Decimal = self.decimal.Decimal
4248
4249        self.assertEqual(Decimal('1234e9999').adjusted(), 10002)
4250        # XXX raise?
4251        self.assertEqual(Decimal('nan').adjusted(), 0)
4252        self.assertEqual(Decimal('inf').adjusted(), 0)
4253
4254    def test_canonical(self):
4255        Decimal = self.decimal.Decimal
4256        getcontext = self.decimal.getcontext
4257
4258        x = Decimal(9).canonical()
4259        self.assertEqual(x, 9)
4260
4261        c = getcontext()
4262        x = c.canonical(Decimal(9))
4263        self.assertEqual(x, 9)
4264
4265    def test_context_repr(self):
4266        c = self.decimal.DefaultContext.copy()
4267
4268        c.prec = 425000000
4269        c.Emax = 425000000
4270        c.Emin = -425000000
4271        c.rounding = ROUND_HALF_DOWN
4272        c.capitals = 0
4273        c.clamp = 1
4274        for sig in OrderedSignals[self.decimal]:
4275            c.flags[sig] = False
4276            c.traps[sig] = False
4277
4278        s = c.__repr__()
4279        t = "Context(prec=425000000, rounding=ROUND_HALF_DOWN, " \
4280            "Emin=-425000000, Emax=425000000, capitals=0, clamp=1, " \
4281            "flags=[], traps=[])"
4282        self.assertEqual(s, t)
4283
4284    def test_implicit_context(self):
4285        Decimal = self.decimal.Decimal
4286        localcontext = self.decimal.localcontext
4287
4288        with localcontext() as c:
4289            c.prec = 1
4290            c.Emax = 1
4291            c.Emin = -1
4292
4293            # abs
4294            self.assertEqual(abs(Decimal("-10")), 10)
4295            # add
4296            self.assertEqual(Decimal("7") + 1, 8)
4297            # divide
4298            self.assertEqual(Decimal("10") / 5, 2)
4299            # divide_int
4300            self.assertEqual(Decimal("10") // 7, 1)
4301            # fma
4302            self.assertEqual(Decimal("1.2").fma(Decimal("0.01"), 1), 1)
4303            self.assertIs(Decimal("NaN").fma(7, 1).is_nan(), True)
4304            # three arg power
4305            self.assertEqual(pow(Decimal(10), 2, 7), 2)
4306            # exp
4307            self.assertEqual(Decimal("1.01").exp(), 3)
4308            # is_normal
4309            self.assertIs(Decimal("0.01").is_normal(), False)
4310            # is_subnormal
4311            self.assertIs(Decimal("0.01").is_subnormal(), True)
4312            # ln
4313            self.assertEqual(Decimal("20").ln(), 3)
4314            # log10
4315            self.assertEqual(Decimal("20").log10(), 1)
4316            # logb
4317            self.assertEqual(Decimal("580").logb(), 2)
4318            # logical_invert
4319            self.assertEqual(Decimal("10").logical_invert(), 1)
4320            # minus
4321            self.assertEqual(-Decimal("-10"), 10)
4322            # multiply
4323            self.assertEqual(Decimal("2") * 4, 8)
4324            # next_minus
4325            self.assertEqual(Decimal("10").next_minus(), 9)
4326            # next_plus
4327            self.assertEqual(Decimal("10").next_plus(), Decimal('2E+1'))
4328            # normalize
4329            self.assertEqual(Decimal("-10").normalize(), Decimal('-1E+1'))
4330            # number_class
4331            self.assertEqual(Decimal("10").number_class(), '+Normal')
4332            # plus
4333            self.assertEqual(+Decimal("-1"), -1)
4334            # remainder
4335            self.assertEqual(Decimal("10") % 7, 3)
4336            # subtract
4337            self.assertEqual(Decimal("10") - 7, 3)
4338            # to_integral_exact
4339            self.assertEqual(Decimal("1.12345").to_integral_exact(), 1)
4340
4341            # Boolean functions
4342            self.assertTrue(Decimal("1").is_canonical())
4343            self.assertTrue(Decimal("1").is_finite())
4344            self.assertTrue(Decimal("1").is_finite())
4345            self.assertTrue(Decimal("snan").is_snan())
4346            self.assertTrue(Decimal("-1").is_signed())
4347            self.assertTrue(Decimal("0").is_zero())
4348            self.assertTrue(Decimal("0").is_zero())
4349
4350        # Copy
4351        with localcontext() as c:
4352            c.prec = 10000
4353            x = 1228 ** 1523
4354            y = -Decimal(x)
4355
4356            z = y.copy_abs()
4357            self.assertEqual(z, x)
4358
4359            z = y.copy_negate()
4360            self.assertEqual(z, x)
4361
4362            z = y.copy_sign(Decimal(1))
4363            self.assertEqual(z, x)
4364
4365    def test_divmod(self):
4366        Decimal = self.decimal.Decimal
4367        localcontext = self.decimal.localcontext
4368        InvalidOperation = self.decimal.InvalidOperation
4369        DivisionByZero = self.decimal.DivisionByZero
4370
4371        with localcontext() as c:
4372            q, r = divmod(Decimal("10912837129"), 1001)
4373            self.assertEqual(q, Decimal('10901935'))
4374            self.assertEqual(r, Decimal('194'))
4375
4376            q, r = divmod(Decimal("NaN"), 7)
4377            self.assertTrue(q.is_nan() and r.is_nan())
4378
4379            c.traps[InvalidOperation] = False
4380            q, r = divmod(Decimal("NaN"), 7)
4381            self.assertTrue(q.is_nan() and r.is_nan())
4382
4383            c.traps[InvalidOperation] = False
4384            c.clear_flags()
4385            q, r = divmod(Decimal("inf"), Decimal("inf"))
4386            self.assertTrue(q.is_nan() and r.is_nan())
4387            self.assertTrue(c.flags[InvalidOperation])
4388
4389            c.clear_flags()
4390            q, r = divmod(Decimal("inf"), 101)
4391            self.assertTrue(q.is_infinite() and r.is_nan())
4392            self.assertTrue(c.flags[InvalidOperation])
4393
4394            c.clear_flags()
4395            q, r = divmod(Decimal(0), 0)
4396            self.assertTrue(q.is_nan() and r.is_nan())
4397            self.assertTrue(c.flags[InvalidOperation])
4398
4399            c.traps[DivisionByZero] = False
4400            c.clear_flags()
4401            q, r = divmod(Decimal(11), 0)
4402            self.assertTrue(q.is_infinite() and r.is_nan())
4403            self.assertTrue(c.flags[InvalidOperation] and
4404                            c.flags[DivisionByZero])
4405
4406    def test_power(self):
4407        Decimal = self.decimal.Decimal
4408        localcontext = self.decimal.localcontext
4409        Overflow = self.decimal.Overflow
4410        Rounded = self.decimal.Rounded
4411
4412        with localcontext() as c:
4413            c.prec = 3
4414            c.clear_flags()
4415            self.assertEqual(Decimal("1.0") ** 100, Decimal('1.00'))
4416            self.assertTrue(c.flags[Rounded])
4417
4418            c.prec = 1
4419            c.Emax = 1
4420            c.Emin = -1
4421            c.clear_flags()
4422            c.traps[Overflow] = False
4423            self.assertEqual(Decimal(10000) ** Decimal("0.5"), Decimal('inf'))
4424            self.assertTrue(c.flags[Overflow])
4425
4426    def test_quantize(self):
4427        Decimal = self.decimal.Decimal
4428        localcontext = self.decimal.localcontext
4429        InvalidOperation = self.decimal.InvalidOperation
4430
4431        with localcontext() as c:
4432            c.prec = 1
4433            c.Emax = 1
4434            c.Emin = -1
4435            c.traps[InvalidOperation] = False
4436            x = Decimal(99).quantize(Decimal("1e1"))
4437            self.assertTrue(x.is_nan())
4438
4439    def test_radix(self):
4440        Decimal = self.decimal.Decimal
4441        getcontext = self.decimal.getcontext
4442
4443        c = getcontext()
4444        self.assertEqual(Decimal("1").radix(), 10)
4445        self.assertEqual(c.radix(), 10)
4446
4447    def test_rop(self):
4448        Decimal = self.decimal.Decimal
4449
4450        for attr in ('__radd__', '__rsub__', '__rmul__', '__rtruediv__',
4451                     '__rdivmod__', '__rmod__', '__rfloordiv__', '__rpow__'):
4452            self.assertIs(getattr(Decimal("1"), attr)("xyz"), NotImplemented)
4453
4454    def test_round(self):
4455        # Python3 behavior: round() returns Decimal
4456        Decimal = self.decimal.Decimal
4457        localcontext = self.decimal.localcontext
4458
4459        with localcontext() as c:
4460            c.prec = 28
4461
4462            self.assertEqual(str(Decimal("9.99").__round__()), "10")
4463            self.assertEqual(str(Decimal("9.99e-5").__round__()), "0")
4464            self.assertEqual(str(Decimal("1.23456789").__round__(5)), "1.23457")
4465            self.assertEqual(str(Decimal("1.2345").__round__(10)), "1.2345000000")
4466            self.assertEqual(str(Decimal("1.2345").__round__(-10)), "0E+10")
4467
4468            self.assertRaises(TypeError, Decimal("1.23").__round__, "5")
4469            self.assertRaises(TypeError, Decimal("1.23").__round__, 5, 8)
4470
4471    def test_create_decimal(self):
4472        c = self.decimal.Context()
4473        self.assertRaises(ValueError, c.create_decimal, ["%"])
4474
4475    def test_int(self):
4476        Decimal = self.decimal.Decimal
4477        localcontext = self.decimal.localcontext
4478
4479        with localcontext() as c:
4480            c.prec = 9999
4481            x = Decimal(1221**1271) / 10**3923
4482            self.assertEqual(int(x), 1)
4483            self.assertEqual(x.to_integral(), 2)
4484
4485    def test_copy(self):
4486        Context = self.decimal.Context
4487
4488        c = Context()
4489        c.prec = 10000
4490        x = -(1172 ** 1712)
4491
4492        y = c.copy_abs(x)
4493        self.assertEqual(y, -x)
4494
4495        y = c.copy_negate(x)
4496        self.assertEqual(y, -x)
4497
4498        y = c.copy_sign(x, 1)
4499        self.assertEqual(y, -x)
4500
4501class CCoverage(Coverage):
4502    decimal = C
4503class PyCoverage(Coverage):
4504    decimal = P
4505
4506class PyFunctionality(unittest.TestCase):
4507    """Extra functionality in decimal.py"""
4508
4509    def test_py_alternate_formatting(self):
4510        # triples giving a format, a Decimal, and the expected result
4511        Decimal = P.Decimal
4512        localcontext = P.localcontext
4513
4514        test_values = [
4515            # Issue 7094: Alternate formatting (specified by #)
4516            ('.0e', '1.0', '1e+0'),
4517            ('#.0e', '1.0', '1.e+0'),
4518            ('.0f', '1.0', '1'),
4519            ('#.0f', '1.0', '1.'),
4520            ('g', '1.1', '1.1'),
4521            ('#g', '1.1', '1.1'),
4522            ('.0g', '1', '1'),
4523            ('#.0g', '1', '1.'),
4524            ('.0%', '1.0', '100%'),
4525            ('#.0%', '1.0', '100.%'),
4526            ]
4527        for fmt, d, result in test_values:
4528            self.assertEqual(format(Decimal(d), fmt), result)
4529
4530class PyWhitebox(unittest.TestCase):
4531    """White box testing for decimal.py"""
4532
4533    def test_py_exact_power(self):
4534        # Rarely exercised lines in _power_exact.
4535        Decimal = P.Decimal
4536        localcontext = P.localcontext
4537
4538        with localcontext() as c:
4539            c.prec = 8
4540            x = Decimal(2**16) ** Decimal("-0.5")
4541            self.assertEqual(x, Decimal('0.00390625'))
4542
4543            x = Decimal(2**16) ** Decimal("-0.6")
4544            self.assertEqual(x, Decimal('0.0012885819'))
4545
4546            x = Decimal("256e7") ** Decimal("-0.5")
4547
4548            x = Decimal(152587890625) ** Decimal('-0.0625')
4549            self.assertEqual(x, Decimal("0.2"))
4550
4551            x = Decimal("152587890625e7") ** Decimal('-0.0625')
4552
4553            x = Decimal(5**2659) ** Decimal('-0.0625')
4554
4555            c.prec = 1
4556            x = Decimal("152587890625") ** Decimal('-0.5')
4557            c.prec = 201
4558            x = Decimal(2**578) ** Decimal("-0.5")
4559
4560    def test_py_immutability_operations(self):
4561        # Do operations and check that it didn't change internal objects.
4562        Decimal = P.Decimal
4563        DefaultContext = P.DefaultContext
4564        setcontext = P.setcontext
4565
4566        c = DefaultContext.copy()
4567        c.traps = dict((s, 0) for s in OrderedSignals[P])
4568        setcontext(c)
4569
4570        d1 = Decimal('-25e55')
4571        b1 = Decimal('-25e55')
4572        d2 = Decimal('33e+33')
4573        b2 = Decimal('33e+33')
4574
4575        def checkSameDec(operation, useOther=False):
4576            if useOther:
4577                eval("d1." + operation + "(d2)")
4578                self.assertEqual(d1._sign, b1._sign)
4579                self.assertEqual(d1._int, b1._int)
4580                self.assertEqual(d1._exp, b1._exp)
4581                self.assertEqual(d2._sign, b2._sign)
4582                self.assertEqual(d2._int, b2._int)
4583                self.assertEqual(d2._exp, b2._exp)
4584            else:
4585                eval("d1." + operation + "()")
4586                self.assertEqual(d1._sign, b1._sign)
4587                self.assertEqual(d1._int, b1._int)
4588                self.assertEqual(d1._exp, b1._exp)
4589
4590        Decimal(d1)
4591        self.assertEqual(d1._sign, b1._sign)
4592        self.assertEqual(d1._int, b1._int)
4593        self.assertEqual(d1._exp, b1._exp)
4594
4595        checkSameDec("__abs__")
4596        checkSameDec("__add__", True)
4597        checkSameDec("__divmod__", True)
4598        checkSameDec("__eq__", True)
4599        checkSameDec("__ne__", True)
4600        checkSameDec("__le__", True)
4601        checkSameDec("__lt__", True)
4602        checkSameDec("__ge__", True)
4603        checkSameDec("__gt__", True)
4604        checkSameDec("__float__")
4605        checkSameDec("__floordiv__", True)
4606        checkSameDec("__hash__")
4607        checkSameDec("__int__")
4608        checkSameDec("__trunc__")
4609        checkSameDec("__mod__", True)
4610        checkSameDec("__mul__", True)
4611        checkSameDec("__neg__")
4612        checkSameDec("__bool__")
4613        checkSameDec("__pos__")
4614        checkSameDec("__pow__", True)
4615        checkSameDec("__radd__", True)
4616        checkSameDec("__rdivmod__", True)
4617        checkSameDec("__repr__")
4618        checkSameDec("__rfloordiv__", True)
4619        checkSameDec("__rmod__", True)
4620        checkSameDec("__rmul__", True)
4621        checkSameDec("__rpow__", True)
4622        checkSameDec("__rsub__", True)
4623        checkSameDec("__str__")
4624        checkSameDec("__sub__", True)
4625        checkSameDec("__truediv__", True)
4626        checkSameDec("adjusted")
4627        checkSameDec("as_tuple")
4628        checkSameDec("compare", True)
4629        checkSameDec("max", True)
4630        checkSameDec("min", True)
4631        checkSameDec("normalize")
4632        checkSameDec("quantize", True)
4633        checkSameDec("remainder_near", True)
4634        checkSameDec("same_quantum", True)
4635        checkSameDec("sqrt")
4636        checkSameDec("to_eng_string")
4637        checkSameDec("to_integral")
4638
4639    def test_py_decimal_id(self):
4640        Decimal = P.Decimal
4641
4642        d = Decimal(45)
4643        e = Decimal(d)
4644        self.assertEqual(str(e), '45')
4645        self.assertNotEqual(id(d), id(e))
4646
4647    def test_py_rescale(self):
4648        # Coverage
4649        Decimal = P.Decimal
4650        localcontext = P.localcontext
4651
4652        with localcontext() as c:
4653            x = Decimal("NaN")._rescale(3, ROUND_UP)
4654            self.assertTrue(x.is_nan())
4655
4656    def test_py__round(self):
4657        # Coverage
4658        Decimal = P.Decimal
4659
4660        self.assertRaises(ValueError, Decimal("3.1234")._round, 0, ROUND_UP)
4661
4662class CFunctionality(unittest.TestCase):
4663    """Extra functionality in _decimal"""
4664
4665    @requires_extra_functionality
4666    def test_c_ieee_context(self):
4667        # issue 8786: Add support for IEEE 754 contexts to decimal module.
4668        IEEEContext = C.IEEEContext
4669        DECIMAL32 = C.DECIMAL32
4670        DECIMAL64 = C.DECIMAL64
4671        DECIMAL128 = C.DECIMAL128
4672
4673        def assert_rest(self, context):
4674            self.assertEqual(context.clamp, 1)
4675            assert_signals(self, context, 'traps', [])
4676            assert_signals(self, context, 'flags', [])
4677
4678        c = IEEEContext(DECIMAL32)
4679        self.assertEqual(c.prec, 7)
4680        self.assertEqual(c.Emax, 96)
4681        self.assertEqual(c.Emin, -95)
4682        assert_rest(self, c)
4683
4684        c = IEEEContext(DECIMAL64)
4685        self.assertEqual(c.prec, 16)
4686        self.assertEqual(c.Emax, 384)
4687        self.assertEqual(c.Emin, -383)
4688        assert_rest(self, c)
4689
4690        c = IEEEContext(DECIMAL128)
4691        self.assertEqual(c.prec, 34)
4692        self.assertEqual(c.Emax, 6144)
4693        self.assertEqual(c.Emin, -6143)
4694        assert_rest(self, c)
4695
4696        # Invalid values
4697        self.assertRaises(OverflowError, IEEEContext, 2**63)
4698        self.assertRaises(ValueError, IEEEContext, -1)
4699        self.assertRaises(ValueError, IEEEContext, 1024)
4700
4701    @requires_extra_functionality
4702    def test_c_context(self):
4703        Context = C.Context
4704
4705        c = Context(flags=C.DecClamped, traps=C.DecRounded)
4706        self.assertEqual(c._flags, C.DecClamped)
4707        self.assertEqual(c._traps, C.DecRounded)
4708
4709    @requires_extra_functionality
4710    def test_constants(self):
4711        # Condition flags
4712        cond = (
4713            C.DecClamped, C.DecConversionSyntax, C.DecDivisionByZero,
4714            C.DecDivisionImpossible, C.DecDivisionUndefined,
4715            C.DecFpuError, C.DecInexact, C.DecInvalidContext,
4716            C.DecInvalidOperation, C.DecMallocError,
4717            C.DecFloatOperation, C.DecOverflow, C.DecRounded,
4718            C.DecSubnormal, C.DecUnderflow
4719        )
4720
4721        # IEEEContext
4722        self.assertEqual(C.DECIMAL32, 32)
4723        self.assertEqual(C.DECIMAL64, 64)
4724        self.assertEqual(C.DECIMAL128, 128)
4725        self.assertEqual(C.IEEE_CONTEXT_MAX_BITS, 512)
4726
4727        # Conditions
4728        for i, v in enumerate(cond):
4729            self.assertEqual(v, 1<<i)
4730
4731        self.assertEqual(C.DecIEEEInvalidOperation,
4732                         C.DecConversionSyntax|
4733                         C.DecDivisionImpossible|
4734                         C.DecDivisionUndefined|
4735                         C.DecFpuError|
4736                         C.DecInvalidContext|
4737                         C.DecInvalidOperation|
4738                         C.DecMallocError)
4739
4740        self.assertEqual(C.DecErrors,
4741                         C.DecIEEEInvalidOperation|
4742                         C.DecDivisionByZero)
4743
4744        self.assertEqual(C.DecTraps,
4745                         C.DecErrors|C.DecOverflow|C.DecUnderflow)
4746
4747class CWhitebox(unittest.TestCase):
4748    """Whitebox testing for _decimal"""
4749
4750    def test_bignum(self):
4751        # Not exactly whitebox, but too slow with pydecimal.
4752
4753        Decimal = C.Decimal
4754        localcontext = C.localcontext
4755
4756        b1 = 10**35
4757        b2 = 10**36
4758        with localcontext() as c:
4759            c.prec = 1000000
4760            for i in range(5):
4761                a = random.randrange(b1, b2)
4762                b = random.randrange(1000, 1200)
4763                x = a ** b
4764                y = Decimal(a) ** Decimal(b)
4765                self.assertEqual(x, y)
4766
4767    def test_invalid_construction(self):
4768        self.assertRaises(TypeError, C.Decimal, 9, "xyz")
4769
4770    def test_c_input_restriction(self):
4771        # Too large for _decimal to be converted exactly
4772        Decimal = C.Decimal
4773        InvalidOperation = C.InvalidOperation
4774        Context = C.Context
4775        localcontext = C.localcontext
4776
4777        with localcontext(Context()):
4778            self.assertRaises(InvalidOperation, Decimal,
4779                              "1e9999999999999999999")
4780
4781    def test_c_context_repr(self):
4782        # This test is _decimal-only because flags are not printed
4783        # in the same order.
4784        DefaultContext = C.DefaultContext
4785        FloatOperation = C.FloatOperation
4786
4787        c = DefaultContext.copy()
4788
4789        c.prec = 425000000
4790        c.Emax = 425000000
4791        c.Emin = -425000000
4792        c.rounding = ROUND_HALF_DOWN
4793        c.capitals = 0
4794        c.clamp = 1
4795        for sig in OrderedSignals[C]:
4796            c.flags[sig] = True
4797            c.traps[sig] = True
4798        c.flags[FloatOperation] = True
4799        c.traps[FloatOperation] = True
4800
4801        s = c.__repr__()
4802        t = "Context(prec=425000000, rounding=ROUND_HALF_DOWN, " \
4803            "Emin=-425000000, Emax=425000000, capitals=0, clamp=1, " \
4804            "flags=[Clamped, InvalidOperation, DivisionByZero, Inexact, " \
4805                   "FloatOperation, Overflow, Rounded, Subnormal, Underflow], " \
4806            "traps=[Clamped, InvalidOperation, DivisionByZero, Inexact, " \
4807                   "FloatOperation, Overflow, Rounded, Subnormal, Underflow])"
4808        self.assertEqual(s, t)
4809
4810    def test_c_context_errors(self):
4811        Context = C.Context
4812        InvalidOperation = C.InvalidOperation
4813        Overflow = C.Overflow
4814        FloatOperation = C.FloatOperation
4815        localcontext = C.localcontext
4816        getcontext = C.getcontext
4817        setcontext = C.setcontext
4818        HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
4819
4820        c = Context()
4821
4822        # SignalDict: input validation
4823        self.assertRaises(KeyError, c.flags.__setitem__, 801, 0)
4824        self.assertRaises(KeyError, c.traps.__setitem__, 801, 0)
4825        self.assertRaises(ValueError, c.flags.__delitem__, Overflow)
4826        self.assertRaises(ValueError, c.traps.__delitem__, InvalidOperation)
4827        self.assertRaises(TypeError, setattr, c, 'flags', ['x'])
4828        self.assertRaises(TypeError, setattr, c,'traps', ['y'])
4829        self.assertRaises(KeyError, setattr, c, 'flags', {0:1})
4830        self.assertRaises(KeyError, setattr, c, 'traps', {0:1})
4831
4832        # Test assignment from a signal dict with the correct length but
4833        # one invalid key.
4834        d = c.flags.copy()
4835        del d[FloatOperation]
4836        d["XYZ"] = 91283719
4837        self.assertRaises(KeyError, setattr, c, 'flags', d)
4838        self.assertRaises(KeyError, setattr, c, 'traps', d)
4839
4840        # Input corner cases
4841        int_max = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
4842        gt_max_emax = 10**18 if HAVE_CONFIG_64 else 10**9
4843
4844        # prec, Emax, Emin
4845        for attr in ['prec', 'Emax']:
4846            self.assertRaises(ValueError, setattr, c, attr, gt_max_emax)
4847        self.assertRaises(ValueError, setattr, c, 'Emin', -gt_max_emax)
4848
4849        # prec, Emax, Emin in context constructor
4850        self.assertRaises(ValueError, Context, prec=gt_max_emax)
4851        self.assertRaises(ValueError, Context, Emax=gt_max_emax)
4852        self.assertRaises(ValueError, Context, Emin=-gt_max_emax)
4853
4854        # Overflow in conversion
4855        self.assertRaises(OverflowError, Context, prec=int_max+1)
4856        self.assertRaises(OverflowError, Context, Emax=int_max+1)
4857        self.assertRaises(OverflowError, Context, Emin=-int_max-2)
4858        self.assertRaises(OverflowError, Context, clamp=int_max+1)
4859        self.assertRaises(OverflowError, Context, capitals=int_max+1)
4860
4861        # OverflowError, general ValueError
4862        for attr in ('prec', 'Emin', 'Emax', 'capitals', 'clamp'):
4863            self.assertRaises(OverflowError, setattr, c, attr, int_max+1)
4864            self.assertRaises(OverflowError, setattr, c, attr, -int_max-2)
4865            if sys.platform != 'win32':
4866                self.assertRaises(ValueError, setattr, c, attr, int_max)
4867                self.assertRaises(ValueError, setattr, c, attr, -int_max-1)
4868
4869        # OverflowError: _unsafe_setprec, _unsafe_setemin, _unsafe_setemax
4870        if C.MAX_PREC == 425000000:
4871            self.assertRaises(OverflowError, getattr(c, '_unsafe_setprec'),
4872                              int_max+1)
4873            self.assertRaises(OverflowError, getattr(c, '_unsafe_setemax'),
4874                              int_max+1)
4875            self.assertRaises(OverflowError, getattr(c, '_unsafe_setemin'),
4876                              -int_max-2)
4877
4878        # ValueError: _unsafe_setprec, _unsafe_setemin, _unsafe_setemax
4879        if C.MAX_PREC == 425000000:
4880            self.assertRaises(ValueError, getattr(c, '_unsafe_setprec'), 0)
4881            self.assertRaises(ValueError, getattr(c, '_unsafe_setprec'),
4882                              1070000001)
4883            self.assertRaises(ValueError, getattr(c, '_unsafe_setemax'), -1)
4884            self.assertRaises(ValueError, getattr(c, '_unsafe_setemax'),
4885                              1070000001)
4886            self.assertRaises(ValueError, getattr(c, '_unsafe_setemin'),
4887                              -1070000001)
4888            self.assertRaises(ValueError, getattr(c, '_unsafe_setemin'), 1)
4889
4890        # capitals, clamp
4891        for attr in ['capitals', 'clamp']:
4892            self.assertRaises(ValueError, setattr, c, attr, -1)
4893            self.assertRaises(ValueError, setattr, c, attr, 2)
4894            self.assertRaises(TypeError, setattr, c, attr, [1,2,3])
4895            if HAVE_CONFIG_64:
4896                self.assertRaises(ValueError, setattr, c, attr, 2**32)
4897                self.assertRaises(ValueError, setattr, c, attr, 2**32+1)
4898
4899        # Invalid local context
4900        self.assertRaises(TypeError, exec, 'with localcontext("xyz"): pass',
4901                          locals())
4902        self.assertRaises(TypeError, exec,
4903                          'with localcontext(context=getcontext()): pass',
4904                          locals())
4905
4906        # setcontext
4907        saved_context = getcontext()
4908        self.assertRaises(TypeError, setcontext, "xyz")
4909        setcontext(saved_context)
4910
4911    def test_rounding_strings_interned(self):
4912
4913        self.assertIs(C.ROUND_UP, P.ROUND_UP)
4914        self.assertIs(C.ROUND_DOWN, P.ROUND_DOWN)
4915        self.assertIs(C.ROUND_CEILING, P.ROUND_CEILING)
4916        self.assertIs(C.ROUND_FLOOR, P.ROUND_FLOOR)
4917        self.assertIs(C.ROUND_HALF_UP, P.ROUND_HALF_UP)
4918        self.assertIs(C.ROUND_HALF_DOWN, P.ROUND_HALF_DOWN)
4919        self.assertIs(C.ROUND_HALF_EVEN, P.ROUND_HALF_EVEN)
4920        self.assertIs(C.ROUND_05UP, P.ROUND_05UP)
4921
4922    @requires_extra_functionality
4923    def test_c_context_errors_extra(self):
4924        Context = C.Context
4925        InvalidOperation = C.InvalidOperation
4926        Overflow = C.Overflow
4927        localcontext = C.localcontext
4928        getcontext = C.getcontext
4929        setcontext = C.setcontext
4930        HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
4931
4932        c = Context()
4933
4934        # Input corner cases
4935        int_max = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
4936
4937        # OverflowError, general ValueError
4938        self.assertRaises(OverflowError, setattr, c, '_allcr', int_max+1)
4939        self.assertRaises(OverflowError, setattr, c, '_allcr', -int_max-2)
4940        if sys.platform != 'win32':
4941            self.assertRaises(ValueError, setattr, c, '_allcr', int_max)
4942            self.assertRaises(ValueError, setattr, c, '_allcr', -int_max-1)
4943
4944        # OverflowError, general TypeError
4945        for attr in ('_flags', '_traps'):
4946            self.assertRaises(OverflowError, setattr, c, attr, int_max+1)
4947            self.assertRaises(OverflowError, setattr, c, attr, -int_max-2)
4948            if sys.platform != 'win32':
4949                self.assertRaises(TypeError, setattr, c, attr, int_max)
4950                self.assertRaises(TypeError, setattr, c, attr, -int_max-1)
4951
4952        # _allcr
4953        self.assertRaises(ValueError, setattr, c, '_allcr', -1)
4954        self.assertRaises(ValueError, setattr, c, '_allcr', 2)
4955        self.assertRaises(TypeError, setattr, c, '_allcr', [1,2,3])
4956        if HAVE_CONFIG_64:
4957            self.assertRaises(ValueError, setattr, c, '_allcr', 2**32)
4958            self.assertRaises(ValueError, setattr, c, '_allcr', 2**32+1)
4959
4960        # _flags, _traps
4961        for attr in ['_flags', '_traps']:
4962            self.assertRaises(TypeError, setattr, c, attr, 999999)
4963            self.assertRaises(TypeError, setattr, c, attr, 'x')
4964
4965    def test_c_valid_context(self):
4966        # These tests are for code coverage in _decimal.
4967        DefaultContext = C.DefaultContext
4968        Clamped = C.Clamped
4969        Underflow = C.Underflow
4970        Inexact = C.Inexact
4971        Rounded = C.Rounded
4972        Subnormal = C.Subnormal
4973
4974        c = DefaultContext.copy()
4975
4976        # Exercise all getters and setters
4977        c.prec = 34
4978        c.rounding = ROUND_HALF_UP
4979        c.Emax = 3000
4980        c.Emin = -3000
4981        c.capitals = 1
4982        c.clamp = 0
4983
4984        self.assertEqual(c.prec, 34)
4985        self.assertEqual(c.rounding, ROUND_HALF_UP)
4986        self.assertEqual(c.Emin, -3000)
4987        self.assertEqual(c.Emax, 3000)
4988        self.assertEqual(c.capitals, 1)
4989        self.assertEqual(c.clamp, 0)
4990
4991        self.assertEqual(c.Etiny(), -3033)
4992        self.assertEqual(c.Etop(), 2967)
4993
4994        # Exercise all unsafe setters
4995        if C.MAX_PREC == 425000000:
4996            c._unsafe_setprec(999999999)
4997            c._unsafe_setemax(999999999)
4998            c._unsafe_setemin(-999999999)
4999            self.assertEqual(c.prec, 999999999)
5000            self.assertEqual(c.Emax, 999999999)
5001            self.assertEqual(c.Emin, -999999999)
5002
5003    @requires_extra_functionality
5004    def test_c_valid_context_extra(self):
5005        DefaultContext = C.DefaultContext
5006
5007        c = DefaultContext.copy()
5008        self.assertEqual(c._allcr, 1)
5009        c._allcr = 0
5010        self.assertEqual(c._allcr, 0)
5011
5012    def test_c_round(self):
5013        # Restricted input.
5014        Decimal = C.Decimal
5015        InvalidOperation = C.InvalidOperation
5016        localcontext = C.localcontext
5017        MAX_EMAX = C.MAX_EMAX
5018        MIN_ETINY = C.MIN_ETINY
5019        int_max = 2**63-1 if C.MAX_PREC > 425000000 else 2**31-1
5020
5021        with localcontext() as c:
5022            c.traps[InvalidOperation] = True
5023            self.assertRaises(InvalidOperation, Decimal("1.23").__round__,
5024                              -int_max-1)
5025            self.assertRaises(InvalidOperation, Decimal("1.23").__round__,
5026                              int_max)
5027            self.assertRaises(InvalidOperation, Decimal("1").__round__,
5028                              int(MAX_EMAX+1))
5029            self.assertRaises(C.InvalidOperation, Decimal("1").__round__,
5030                              -int(MIN_ETINY-1))
5031            self.assertRaises(OverflowError, Decimal("1.23").__round__,
5032                              -int_max-2)
5033            self.assertRaises(OverflowError, Decimal("1.23").__round__,
5034                              int_max+1)
5035
5036    def test_c_format(self):
5037        # Restricted input
5038        Decimal = C.Decimal
5039        HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
5040
5041        self.assertRaises(TypeError, Decimal(1).__format__, "=10.10", [], 9)
5042        self.assertRaises(TypeError, Decimal(1).__format__, "=10.10", 9)
5043        self.assertRaises(TypeError, Decimal(1).__format__, [])
5044
5045        self.assertRaises(ValueError, Decimal(1).__format__, "<>=10.10")
5046        maxsize = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
5047        self.assertRaises(ValueError, Decimal("1.23456789").__format__,
5048                          "=%d.1" % maxsize)
5049
5050    def test_c_integral(self):
5051        Decimal = C.Decimal
5052        Inexact = C.Inexact
5053        localcontext = C.localcontext
5054
5055        x = Decimal(10)
5056        self.assertEqual(x.to_integral(), 10)
5057        self.assertRaises(TypeError, x.to_integral, '10')
5058        self.assertRaises(TypeError, x.to_integral, 10, 'x')
5059        self.assertRaises(TypeError, x.to_integral, 10)
5060
5061        self.assertEqual(x.to_integral_value(), 10)
5062        self.assertRaises(TypeError, x.to_integral_value, '10')
5063        self.assertRaises(TypeError, x.to_integral_value, 10, 'x')
5064        self.assertRaises(TypeError, x.to_integral_value, 10)
5065
5066        self.assertEqual(x.to_integral_exact(), 10)
5067        self.assertRaises(TypeError, x.to_integral_exact, '10')
5068        self.assertRaises(TypeError, x.to_integral_exact, 10, 'x')
5069        self.assertRaises(TypeError, x.to_integral_exact, 10)
5070
5071        with localcontext() as c:
5072            x = Decimal("99999999999999999999999999.9").to_integral_value(ROUND_UP)
5073            self.assertEqual(x, Decimal('100000000000000000000000000'))
5074
5075            x = Decimal("99999999999999999999999999.9").to_integral_exact(ROUND_UP)
5076            self.assertEqual(x, Decimal('100000000000000000000000000'))
5077
5078            c.traps[Inexact] = True
5079            self.assertRaises(Inexact, Decimal("999.9").to_integral_exact, ROUND_UP)
5080
5081    def test_c_funcs(self):
5082        # Invalid arguments
5083        Decimal = C.Decimal
5084        InvalidOperation = C.InvalidOperation
5085        DivisionByZero = C.DivisionByZero
5086        getcontext = C.getcontext
5087        localcontext = C.localcontext
5088
5089        self.assertEqual(Decimal('9.99e10').to_eng_string(), '99.9E+9')
5090
5091        self.assertRaises(TypeError, pow, Decimal(1), 2, "3")
5092        self.assertRaises(TypeError, Decimal(9).number_class, "x", "y")
5093        self.assertRaises(TypeError, Decimal(9).same_quantum, 3, "x", "y")
5094
5095        self.assertRaises(
5096            TypeError,
5097            Decimal("1.23456789").quantize, Decimal('1e-100000'), []
5098        )
5099        self.assertRaises(
5100            TypeError,
5101            Decimal("1.23456789").quantize, Decimal('1e-100000'), getcontext()
5102        )
5103        self.assertRaises(
5104            TypeError,
5105            Decimal("1.23456789").quantize, Decimal('1e-100000'), 10
5106        )
5107        self.assertRaises(
5108            TypeError,
5109            Decimal("1.23456789").quantize, Decimal('1e-100000'), ROUND_UP, 1000
5110        )
5111
5112        with localcontext() as c:
5113            c.clear_traps()
5114
5115            # Invalid arguments
5116            self.assertRaises(TypeError, c.copy_sign, Decimal(1), "x", "y")
5117            self.assertRaises(TypeError, c.canonical, 200)
5118            self.assertRaises(TypeError, c.is_canonical, 200)
5119            self.assertRaises(TypeError, c.divmod, 9, 8, "x", "y")
5120            self.assertRaises(TypeError, c.same_quantum, 9, 3, "x", "y")
5121
5122            self.assertEqual(str(c.canonical(Decimal(200))), '200')
5123            self.assertEqual(c.radix(), 10)
5124
5125            c.traps[DivisionByZero] = True
5126            self.assertRaises(DivisionByZero, Decimal(9).__divmod__, 0)
5127            self.assertRaises(DivisionByZero, c.divmod, 9, 0)
5128            self.assertTrue(c.flags[InvalidOperation])
5129
5130            c.clear_flags()
5131            c.traps[InvalidOperation] = True
5132            self.assertRaises(InvalidOperation, Decimal(9).__divmod__, 0)
5133            self.assertRaises(InvalidOperation, c.divmod, 9, 0)
5134            self.assertTrue(c.flags[DivisionByZero])
5135
5136            c.traps[InvalidOperation] = True
5137            c.prec = 2
5138            self.assertRaises(InvalidOperation, pow, Decimal(1000), 1, 501)
5139
5140    def test_va_args_exceptions(self):
5141        Decimal = C.Decimal
5142        Context = C.Context
5143
5144        x = Decimal("10001111111")
5145
5146        for attr in ['exp', 'is_normal', 'is_subnormal', 'ln', 'log10',
5147                     'logb', 'logical_invert', 'next_minus', 'next_plus',
5148                     'normalize', 'number_class', 'sqrt', 'to_eng_string']:
5149            func = getattr(x, attr)
5150            self.assertRaises(TypeError, func, context="x")
5151            self.assertRaises(TypeError, func, "x", context=None)
5152
5153        for attr in ['compare', 'compare_signal', 'logical_and',
5154                     'logical_or', 'max', 'max_mag', 'min', 'min_mag',
5155                     'remainder_near', 'rotate', 'scaleb', 'shift']:
5156            func = getattr(x, attr)
5157            self.assertRaises(TypeError, func, context="x")
5158            self.assertRaises(TypeError, func, "x", context=None)
5159
5160        self.assertRaises(TypeError, x.to_integral, rounding=None, context=[])
5161        self.assertRaises(TypeError, x.to_integral, rounding={}, context=[])
5162        self.assertRaises(TypeError, x.to_integral, [], [])
5163
5164        self.assertRaises(TypeError, x.to_integral_value, rounding=None, context=[])
5165        self.assertRaises(TypeError, x.to_integral_value, rounding={}, context=[])
5166        self.assertRaises(TypeError, x.to_integral_value, [], [])
5167
5168        self.assertRaises(TypeError, x.to_integral_exact, rounding=None, context=[])
5169        self.assertRaises(TypeError, x.to_integral_exact, rounding={}, context=[])
5170        self.assertRaises(TypeError, x.to_integral_exact, [], [])
5171
5172        self.assertRaises(TypeError, x.fma, 1, 2, context="x")
5173        self.assertRaises(TypeError, x.fma, 1, 2, "x", context=None)
5174
5175        self.assertRaises(TypeError, x.quantize, 1, [], context=None)
5176        self.assertRaises(TypeError, x.quantize, 1, [], rounding=None)
5177        self.assertRaises(TypeError, x.quantize, 1, [], [])
5178
5179        c = Context()
5180        self.assertRaises(TypeError, c.power, 1, 2, mod="x")
5181        self.assertRaises(TypeError, c.power, 1, "x", mod=None)
5182        self.assertRaises(TypeError, c.power, "x", 2, mod=None)
5183
5184    @requires_extra_functionality
5185    def test_c_context_templates(self):
5186        self.assertEqual(
5187            C.BasicContext._traps,
5188            C.DecIEEEInvalidOperation|C.DecDivisionByZero|C.DecOverflow|
5189            C.DecUnderflow|C.DecClamped
5190        )
5191        self.assertEqual(
5192            C.DefaultContext._traps,
5193            C.DecIEEEInvalidOperation|C.DecDivisionByZero|C.DecOverflow
5194        )
5195
5196    @requires_extra_functionality
5197    def test_c_signal_dict(self):
5198
5199        # SignalDict coverage
5200        Context = C.Context
5201        DefaultContext = C.DefaultContext
5202
5203        InvalidOperation = C.InvalidOperation
5204        DivisionByZero = C.DivisionByZero
5205        Overflow = C.Overflow
5206        Subnormal = C.Subnormal
5207        Underflow = C.Underflow
5208        Rounded = C.Rounded
5209        Inexact = C.Inexact
5210        Clamped = C.Clamped
5211
5212        DecClamped = C.DecClamped
5213        DecInvalidOperation = C.DecInvalidOperation
5214        DecIEEEInvalidOperation = C.DecIEEEInvalidOperation
5215
5216        def assertIsExclusivelySet(signal, signal_dict):
5217            for sig in signal_dict:
5218                if sig == signal:
5219                    self.assertTrue(signal_dict[sig])
5220                else:
5221                    self.assertFalse(signal_dict[sig])
5222
5223        c = DefaultContext.copy()
5224
5225        # Signal dict methods
5226        self.assertTrue(Overflow in c.traps)
5227        c.clear_traps()
5228        for k in c.traps.keys():
5229            c.traps[k] = True
5230        for v in c.traps.values():
5231            self.assertTrue(v)
5232        c.clear_traps()
5233        for k, v in c.traps.items():
5234            self.assertFalse(v)
5235
5236        self.assertFalse(c.flags.get(Overflow))
5237        self.assertIs(c.flags.get("x"), None)
5238        self.assertEqual(c.flags.get("x", "y"), "y")
5239        self.assertRaises(TypeError, c.flags.get, "x", "y", "z")
5240
5241        self.assertEqual(len(c.flags), len(c.traps))
5242        s = sys.getsizeof(c.flags)
5243        s = sys.getsizeof(c.traps)
5244        s = c.flags.__repr__()
5245
5246        # Set flags/traps.
5247        c.clear_flags()
5248        c._flags = DecClamped
5249        self.assertTrue(c.flags[Clamped])
5250
5251        c.clear_traps()
5252        c._traps = DecInvalidOperation
5253        self.assertTrue(c.traps[InvalidOperation])
5254
5255        # Set flags/traps from dictionary.
5256        c.clear_flags()
5257        d = c.flags.copy()
5258        d[DivisionByZero] = True
5259        c.flags = d
5260        assertIsExclusivelySet(DivisionByZero, c.flags)
5261
5262        c.clear_traps()
5263        d = c.traps.copy()
5264        d[Underflow] = True
5265        c.traps = d
5266        assertIsExclusivelySet(Underflow, c.traps)
5267
5268        # Random constructors
5269        IntSignals = {
5270          Clamped: C.DecClamped,
5271          Rounded: C.DecRounded,
5272          Inexact: C.DecInexact,
5273          Subnormal: C.DecSubnormal,
5274          Underflow: C.DecUnderflow,
5275          Overflow: C.DecOverflow,
5276          DivisionByZero: C.DecDivisionByZero,
5277          InvalidOperation: C.DecIEEEInvalidOperation
5278        }
5279        IntCond = [
5280          C.DecDivisionImpossible, C.DecDivisionUndefined, C.DecFpuError,
5281          C.DecInvalidContext, C.DecInvalidOperation, C.DecMallocError,
5282          C.DecConversionSyntax,
5283        ]
5284
5285        lim = len(OrderedSignals[C])
5286        for r in range(lim):
5287            for t in range(lim):
5288                for round in RoundingModes:
5289                    flags = random.sample(OrderedSignals[C], r)
5290                    traps = random.sample(OrderedSignals[C], t)
5291                    prec = random.randrange(1, 10000)
5292                    emin = random.randrange(-10000, 0)
5293                    emax = random.randrange(0, 10000)
5294                    clamp = random.randrange(0, 2)
5295                    caps = random.randrange(0, 2)
5296                    cr = random.randrange(0, 2)
5297                    c = Context(prec=prec, rounding=round, Emin=emin, Emax=emax,
5298                                capitals=caps, clamp=clamp, flags=list(flags),
5299                                traps=list(traps))
5300
5301                    self.assertEqual(c.prec, prec)
5302                    self.assertEqual(c.rounding, round)
5303                    self.assertEqual(c.Emin, emin)
5304                    self.assertEqual(c.Emax, emax)
5305                    self.assertEqual(c.capitals, caps)
5306                    self.assertEqual(c.clamp, clamp)
5307
5308                    f = 0
5309                    for x in flags:
5310                        f |= IntSignals[x]
5311                    self.assertEqual(c._flags, f)
5312
5313                    f = 0
5314                    for x in traps:
5315                        f |= IntSignals[x]
5316                    self.assertEqual(c._traps, f)
5317
5318        for cond in IntCond:
5319            c._flags = cond
5320            self.assertTrue(c._flags&DecIEEEInvalidOperation)
5321            assertIsExclusivelySet(InvalidOperation, c.flags)
5322
5323        for cond in IntCond:
5324            c._traps = cond
5325            self.assertTrue(c._traps&DecIEEEInvalidOperation)
5326            assertIsExclusivelySet(InvalidOperation, c.traps)
5327
5328    def test_invalid_override(self):
5329        Decimal = C.Decimal
5330
5331        try:
5332            from locale import CHAR_MAX
5333        except ImportError:
5334            self.skipTest('locale.CHAR_MAX not available')
5335
5336        def make_grouping(lst):
5337            return ''.join([chr(x) for x in lst])
5338
5339        def get_fmt(x, override=None, fmt='n'):
5340            return Decimal(x).__format__(fmt, override)
5341
5342        invalid_grouping = {
5343            'decimal_point' : ',',
5344            'grouping' : make_grouping([255, 255, 0]),
5345            'thousands_sep' : ','
5346        }
5347        invalid_dot = {
5348            'decimal_point' : 'xxxxx',
5349            'grouping' : make_grouping([3, 3, 0]),
5350            'thousands_sep' : ','
5351        }
5352        invalid_sep = {
5353            'decimal_point' : '.',
5354            'grouping' : make_grouping([3, 3, 0]),
5355            'thousands_sep' : 'yyyyy'
5356        }
5357
5358        if CHAR_MAX == 127: # negative grouping in override
5359            self.assertRaises(ValueError, get_fmt, 12345,
5360                              invalid_grouping, 'g')
5361
5362        self.assertRaises(ValueError, get_fmt, 12345, invalid_dot, 'g')
5363        self.assertRaises(ValueError, get_fmt, 12345, invalid_sep, 'g')
5364
5365    def test_exact_conversion(self):
5366        Decimal = C.Decimal
5367        localcontext = C.localcontext
5368        InvalidOperation = C.InvalidOperation
5369
5370        with localcontext() as c:
5371
5372            c.traps[InvalidOperation] = True
5373
5374            # Clamped
5375            x = "0e%d" % sys.maxsize
5376            self.assertRaises(InvalidOperation, Decimal, x)
5377
5378            x = "0e%d" % (-sys.maxsize-1)
5379            self.assertRaises(InvalidOperation, Decimal, x)
5380
5381            # Overflow
5382            x = "1e%d" % sys.maxsize
5383            self.assertRaises(InvalidOperation, Decimal, x)
5384
5385            # Underflow
5386            x = "1e%d" % (-sys.maxsize-1)
5387            self.assertRaises(InvalidOperation, Decimal, x)
5388
5389    def test_from_tuple(self):
5390        Decimal = C.Decimal
5391        localcontext = C.localcontext
5392        InvalidOperation = C.InvalidOperation
5393        Overflow = C.Overflow
5394        Underflow = C.Underflow
5395
5396        with localcontext() as c:
5397
5398            c.traps[InvalidOperation] = True
5399            c.traps[Overflow] = True
5400            c.traps[Underflow] = True
5401
5402            # SSIZE_MAX
5403            x = (1, (), sys.maxsize)
5404            self.assertEqual(str(c.create_decimal(x)), '-0E+999999')
5405            self.assertRaises(InvalidOperation, Decimal, x)
5406
5407            x = (1, (0, 1, 2), sys.maxsize)
5408            self.assertRaises(Overflow, c.create_decimal, x)
5409            self.assertRaises(InvalidOperation, Decimal, x)
5410
5411            # SSIZE_MIN
5412            x = (1, (), -sys.maxsize-1)
5413            self.assertEqual(str(c.create_decimal(x)), '-0E-1000007')
5414            self.assertRaises(InvalidOperation, Decimal, x)
5415
5416            x = (1, (0, 1, 2), -sys.maxsize-1)
5417            self.assertRaises(Underflow, c.create_decimal, x)
5418            self.assertRaises(InvalidOperation, Decimal, x)
5419
5420            # OverflowError
5421            x = (1, (), sys.maxsize+1)
5422            self.assertRaises(OverflowError, c.create_decimal, x)
5423            self.assertRaises(OverflowError, Decimal, x)
5424
5425            x = (1, (), -sys.maxsize-2)
5426            self.assertRaises(OverflowError, c.create_decimal, x)
5427            self.assertRaises(OverflowError, Decimal, x)
5428
5429            # Specials
5430            x = (1, (), "N")
5431            self.assertEqual(str(Decimal(x)), '-sNaN')
5432            x = (1, (0,), "N")
5433            self.assertEqual(str(Decimal(x)), '-sNaN')
5434            x = (1, (0, 1), "N")
5435            self.assertEqual(str(Decimal(x)), '-sNaN1')
5436
5437    def test_sizeof(self):
5438        Decimal = C.Decimal
5439        HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
5440
5441        self.assertGreater(Decimal(0).__sizeof__(), 0)
5442        if HAVE_CONFIG_64:
5443            x = Decimal(10**(19*24)).__sizeof__()
5444            y = Decimal(10**(19*25)).__sizeof__()
5445            self.assertEqual(y, x+8)
5446        else:
5447            x = Decimal(10**(9*24)).__sizeof__()
5448            y = Decimal(10**(9*25)).__sizeof__()
5449            self.assertEqual(y, x+4)
5450
5451    def test_internal_use_of_overridden_methods(self):
5452        Decimal = C.Decimal
5453
5454        # Unsound subtyping
5455        class X(float):
5456            def as_integer_ratio(self):
5457                return 1
5458            def __abs__(self):
5459                return self
5460
5461        class Y(float):
5462            def __abs__(self):
5463                return [1]*200
5464
5465        class I(int):
5466            def bit_length(self):
5467                return [1]*200
5468
5469        class Z(float):
5470            def as_integer_ratio(self):
5471                return (I(1), I(1))
5472            def __abs__(self):
5473                return self
5474
5475        for cls in X, Y, Z:
5476            self.assertEqual(Decimal.from_float(cls(101.1)),
5477                             Decimal.from_float(101.1))
5478
5479@requires_docstrings
5480@unittest.skipUnless(C, "test requires C version")
5481class SignatureTest(unittest.TestCase):
5482    """Function signatures"""
5483
5484    def test_inspect_module(self):
5485        for attr in dir(P):
5486            if attr.startswith('_'):
5487                continue
5488            p_func = getattr(P, attr)
5489            c_func = getattr(C, attr)
5490            if (attr == 'Decimal' or attr == 'Context' or
5491                inspect.isfunction(p_func)):
5492                p_sig = inspect.signature(p_func)
5493                c_sig = inspect.signature(c_func)
5494
5495                # parameter names:
5496                c_names = list(c_sig.parameters.keys())
5497                p_names = [x for x in p_sig.parameters.keys() if not
5498                           x.startswith('_')]
5499
5500                self.assertEqual(c_names, p_names,
5501                                 msg="parameter name mismatch in %s" % p_func)
5502
5503                c_kind = [x.kind for x in c_sig.parameters.values()]
5504                p_kind = [x[1].kind for x in p_sig.parameters.items() if not
5505                          x[0].startswith('_')]
5506
5507                # parameters:
5508                if attr != 'setcontext':
5509                    self.assertEqual(c_kind, p_kind,
5510                                     msg="parameter kind mismatch in %s" % p_func)
5511
5512    def test_inspect_types(self):
5513
5514        POS = inspect._ParameterKind.POSITIONAL_ONLY
5515        POS_KWD = inspect._ParameterKind.POSITIONAL_OR_KEYWORD
5516
5517        # Type heuristic (type annotations would help!):
5518        pdict = {C: {'other': C.Decimal(1),
5519                     'third': C.Decimal(1),
5520                     'x': C.Decimal(1),
5521                     'y': C.Decimal(1),
5522                     'z': C.Decimal(1),
5523                     'a': C.Decimal(1),
5524                     'b': C.Decimal(1),
5525                     'c': C.Decimal(1),
5526                     'exp': C.Decimal(1),
5527                     'modulo': C.Decimal(1),
5528                     'num': "1",
5529                     'f': 1.0,
5530                     'rounding': C.ROUND_HALF_UP,
5531                     'context': C.getcontext()},
5532                 P: {'other': P.Decimal(1),
5533                     'third': P.Decimal(1),
5534                     'a': P.Decimal(1),
5535                     'b': P.Decimal(1),
5536                     'c': P.Decimal(1),
5537                     'exp': P.Decimal(1),
5538                     'modulo': P.Decimal(1),
5539                     'num': "1",
5540                     'f': 1.0,
5541                     'rounding': P.ROUND_HALF_UP,
5542                     'context': P.getcontext()}}
5543
5544        def mkargs(module, sig):
5545            args = []
5546            kwargs = {}
5547            for name, param in sig.parameters.items():
5548                if name == 'self': continue
5549                if param.kind == POS:
5550                    args.append(pdict[module][name])
5551                elif param.kind == POS_KWD:
5552                    kwargs[name] = pdict[module][name]
5553                else:
5554                    raise TestFailed("unexpected parameter kind")
5555            return args, kwargs
5556
5557        def tr(s):
5558            """The C Context docstrings use 'x' in order to prevent confusion
5559               with the article 'a' in the descriptions."""
5560            if s == 'x': return 'a'
5561            if s == 'y': return 'b'
5562            if s == 'z': return 'c'
5563            return s
5564
5565        def doit(ty):
5566            p_type = getattr(P, ty)
5567            c_type = getattr(C, ty)
5568            for attr in dir(p_type):
5569                if attr.startswith('_'):
5570                    continue
5571                p_func = getattr(p_type, attr)
5572                c_func = getattr(c_type, attr)
5573                if inspect.isfunction(p_func):
5574                    p_sig = inspect.signature(p_func)
5575                    c_sig = inspect.signature(c_func)
5576
5577                    # parameter names:
5578                    p_names = list(p_sig.parameters.keys())
5579                    c_names = [tr(x) for x in c_sig.parameters.keys()]
5580
5581                    self.assertEqual(c_names, p_names,
5582                                     msg="parameter name mismatch in %s" % p_func)
5583
5584                    p_kind = [x.kind for x in p_sig.parameters.values()]
5585                    c_kind = [x.kind for x in c_sig.parameters.values()]
5586
5587                    # 'self' parameter:
5588                    self.assertIs(p_kind[0], POS_KWD)
5589                    self.assertIs(c_kind[0], POS)
5590
5591                    # remaining parameters:
5592                    if ty == 'Decimal':
5593                        self.assertEqual(c_kind[1:], p_kind[1:],
5594                                         msg="parameter kind mismatch in %s" % p_func)
5595                    else: # Context methods are positional only in the C version.
5596                        self.assertEqual(len(c_kind), len(p_kind),
5597                                         msg="parameter kind mismatch in %s" % p_func)
5598
5599                    # Run the function:
5600                    args, kwds = mkargs(C, c_sig)
5601                    try:
5602                        getattr(c_type(9), attr)(*args, **kwds)
5603                    except Exception as err:
5604                        raise TestFailed("invalid signature for %s: %s %s" % (c_func, args, kwds))
5605
5606                    args, kwds = mkargs(P, p_sig)
5607                    try:
5608                        getattr(p_type(9), attr)(*args, **kwds)
5609                    except Exception as err:
5610                        raise TestFailed("invalid signature for %s: %s %s" % (p_func, args, kwds))
5611
5612        doit('Decimal')
5613        doit('Context')
5614
5615
5616all_tests = [
5617  CExplicitConstructionTest, PyExplicitConstructionTest,
5618  CImplicitConstructionTest, PyImplicitConstructionTest,
5619  CFormatTest,               PyFormatTest,
5620  CArithmeticOperatorsTest,  PyArithmeticOperatorsTest,
5621  CThreadingTest,            PyThreadingTest,
5622  CUsabilityTest,            PyUsabilityTest,
5623  CPythonAPItests,           PyPythonAPItests,
5624  CContextAPItests,          PyContextAPItests,
5625  CContextWithStatement,     PyContextWithStatement,
5626  CContextFlags,             PyContextFlags,
5627  CSpecialContexts,          PySpecialContexts,
5628  CContextInputValidation,   PyContextInputValidation,
5629  CContextSubclassing,       PyContextSubclassing,
5630  CCoverage,                 PyCoverage,
5631  CFunctionality,            PyFunctionality,
5632  CWhitebox,                 PyWhitebox,
5633  CIBMTestCases,             PyIBMTestCases,
5634]
5635
5636# Delete C tests if _decimal.so is not present.
5637if not C:
5638    all_tests = all_tests[1::2]
5639else:
5640    all_tests.insert(0, CheckAttributes)
5641    all_tests.insert(1, SignatureTest)
5642
5643
5644def test_main(arith=None, verbose=None, todo_tests=None, debug=None):
5645    """ Execute the tests.
5646
5647    Runs all arithmetic tests if arith is True or if the "decimal" resource
5648    is enabled in regrtest.py
5649    """
5650
5651    init(C)
5652    init(P)
5653    global TEST_ALL, DEBUG
5654    TEST_ALL = arith if arith is not None else is_resource_enabled('decimal')
5655    DEBUG = debug
5656
5657    if todo_tests is None:
5658        test_classes = all_tests
5659    else:
5660        test_classes = [CIBMTestCases, PyIBMTestCases]
5661
5662    # Dynamically build custom test definition for each file in the test
5663    # directory and add the definitions to the DecimalTest class.  This
5664    # procedure insures that new files do not get skipped.
5665    for filename in os.listdir(directory):
5666        if '.decTest' not in filename or filename.startswith("."):
5667            continue
5668        head, tail = filename.split('.')
5669        if todo_tests is not None and head not in todo_tests:
5670            continue
5671        tester = lambda self, f=filename: self.eval_file(directory + f)
5672        setattr(CIBMTestCases, 'test_' + head, tester)
5673        setattr(PyIBMTestCases, 'test_' + head, tester)
5674        del filename, head, tail, tester
5675
5676
5677    try:
5678        run_unittest(*test_classes)
5679        if todo_tests is None:
5680            from doctest import IGNORE_EXCEPTION_DETAIL
5681            savedecimal = sys.modules['decimal']
5682            if C:
5683                sys.modules['decimal'] = C
5684                run_doctest(C, verbose, optionflags=IGNORE_EXCEPTION_DETAIL)
5685            sys.modules['decimal'] = P
5686            run_doctest(P, verbose)
5687            sys.modules['decimal'] = savedecimal
5688    finally:
5689        if C: C.setcontext(ORIGINAL_CONTEXT[C])
5690        P.setcontext(ORIGINAL_CONTEXT[P])
5691        if not C:
5692            warnings.warn('C tests skipped: no module named _decimal.',
5693                          UserWarning)
5694        if not orig_sys_decimal is sys.modules['decimal']:
5695            raise TestFailed("Internal error: unbalanced number of changes to "
5696                             "sys.modules['decimal'].")
5697
5698
5699if __name__ == '__main__':
5700    import optparse
5701    p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]")
5702    p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test')
5703    p.add_option('--skip',  '-s', action='store_true', help='skip over 90% of the arithmetic tests')
5704    (opt, args) = p.parse_args()
5705
5706    if opt.skip:
5707        test_main(arith=False, verbose=True)
5708    elif args:
5709        test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug)
5710    else:
5711        test_main(arith=True, verbose=True)
5712