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