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   www2.hursley.ibm.com/decimal/dectest.zip
20
21This test module can be called from command line with one parameter (Arithmetic
22or Behaviour) to test each part, or without parameter to test both parts. If
23you're working through IDLE, you can import this test module and call test_main()
24with the corresponding argument.
25"""
26
27import math
28import os, sys
29import operator
30import pickle, copy
31import unittest
32from decimal import *
33import numbers
34from test.test_support import (run_unittest, run_doctest,
35                               is_resource_enabled, check_py3k_warnings)
36import random
37try:
38    import threading
39except ImportError:
40    threading = None
41
42# Useful Test Constant
43Signals = tuple(getcontext().flags.keys())
44
45# Signals ordered with respect to precedence: when an operation
46# produces multiple signals, signals occurring later in the list
47# should be handled before those occurring earlier in the list.
48OrderedSignals = (Clamped, Rounded, Inexact, Subnormal,
49                  Underflow, Overflow, DivisionByZero, InvalidOperation)
50
51# Tests are built around these assumed context defaults.
52# test_main() restores the original context.
53def init():
54    global ORIGINAL_CONTEXT
55    ORIGINAL_CONTEXT = getcontext().copy()
56    DefaultTestContext = Context(
57        prec = 9,
58        rounding = ROUND_HALF_EVEN,
59        traps = dict.fromkeys(Signals, 0)
60        )
61    setcontext(DefaultTestContext)
62
63# decorator for skipping tests on non-IEEE 754 platforms
64requires_IEEE_754 = unittest.skipUnless(
65    float.__getformat__("double").startswith("IEEE"),
66    "test requires IEEE 754 doubles")
67
68TESTDATADIR = 'decimaltestdata'
69if __name__ == '__main__':
70    file = sys.argv[0]
71else:
72    file = __file__
73testdir = os.path.dirname(file) or os.curdir
74directory = testdir + os.sep + TESTDATADIR + os.sep
75
76skip_expected = not os.path.isdir(directory)
77
78# list of individual .decTest test ids that correspond to tests that
79# we're skipping for one reason or another.
80skipped_test_ids = set([
81    # Skip implementation-specific scaleb tests.
82    'scbx164',
83    'scbx165',
84
85    # For some operations (currently exp, ln, log10, power), the decNumber
86    # reference implementation imposes additional restrictions on the context
87    # and operands.  These restrictions are not part of the specification;
88    # however, the effect of these restrictions does show up in some of the
89    # testcases.  We skip testcases that violate these restrictions, since
90    # Decimal behaves differently from decNumber for these testcases so these
91    # testcases would otherwise fail.
92    'expx901',
93    'expx902',
94    'expx903',
95    'expx905',
96    'lnx901',
97    'lnx902',
98    'lnx903',
99    'lnx905',
100    'logx901',
101    'logx902',
102    'logx903',
103    'logx905',
104    'powx1183',
105    'powx1184',
106    'powx4001',
107    'powx4002',
108    'powx4003',
109    'powx4005',
110    'powx4008',
111    'powx4010',
112    'powx4012',
113    'powx4014',
114    ])
115
116# Make sure it actually raises errors when not expected and caught in flags
117# Slower, since it runs some things several times.
118EXTENDEDERRORTEST = False
119
120#Map the test cases' error names to the actual errors
121ErrorNames = {'clamped' : Clamped,
122              'conversion_syntax' : InvalidOperation,
123              'division_by_zero' : DivisionByZero,
124              'division_impossible' : InvalidOperation,
125              'division_undefined' : InvalidOperation,
126              'inexact' : Inexact,
127              'invalid_context' : InvalidOperation,
128              'invalid_operation' : InvalidOperation,
129              'overflow' : Overflow,
130              'rounded' : Rounded,
131              'subnormal' : Subnormal,
132              'underflow' : Underflow}
133
134
135def Nonfunction(*args):
136    """Doesn't do anything."""
137    return None
138
139RoundingDict = {'ceiling' : ROUND_CEILING, #Maps test-case names to roundings.
140                'down' : ROUND_DOWN,
141                'floor' : ROUND_FLOOR,
142                'half_down' : ROUND_HALF_DOWN,
143                'half_even' : ROUND_HALF_EVEN,
144                'half_up' : ROUND_HALF_UP,
145                'up' : ROUND_UP,
146                '05up' : ROUND_05UP}
147
148# Name adapter to be able to change the Decimal and Context
149# interface without changing the test files from Cowlishaw
150nameAdapter = {'and':'logical_and',
151               'apply':'_apply',
152               'class':'number_class',
153               'comparesig':'compare_signal',
154               'comparetotal':'compare_total',
155               'comparetotmag':'compare_total_mag',
156               'copy':'copy_decimal',
157               'copyabs':'copy_abs',
158               'copynegate':'copy_negate',
159               'copysign':'copy_sign',
160               'divideint':'divide_int',
161               'invert':'logical_invert',
162               'iscanonical':'is_canonical',
163               'isfinite':'is_finite',
164               'isinfinite':'is_infinite',
165               'isnan':'is_nan',
166               'isnormal':'is_normal',
167               'isqnan':'is_qnan',
168               'issigned':'is_signed',
169               'issnan':'is_snan',
170               'issubnormal':'is_subnormal',
171               'iszero':'is_zero',
172               'maxmag':'max_mag',
173               'minmag':'min_mag',
174               'nextminus':'next_minus',
175               'nextplus':'next_plus',
176               'nexttoward':'next_toward',
177               'or':'logical_or',
178               'reduce':'normalize',
179               'remaindernear':'remainder_near',
180               'samequantum':'same_quantum',
181               'squareroot':'sqrt',
182               'toeng':'to_eng_string',
183               'tointegral':'to_integral_value',
184               'tointegralx':'to_integral_exact',
185               'tosci':'to_sci_string',
186               'xor':'logical_xor',
187              }
188
189# The following functions return True/False rather than a Decimal instance
190
191LOGICAL_FUNCTIONS = (
192    'is_canonical',
193    'is_finite',
194    'is_infinite',
195    'is_nan',
196    'is_normal',
197    'is_qnan',
198    'is_signed',
199    'is_snan',
200    'is_subnormal',
201    'is_zero',
202    'same_quantum',
203    )
204
205class DecimalTest(unittest.TestCase):
206    """Class which tests the Decimal class against the test cases.
207
208    Changed for unittest.
209    """
210    def setUp(self):
211        self.context = Context()
212        self.ignore_list = ['#']
213        # Basically, a # means return NaN InvalidOperation.
214        # Different from a sNaN in trim
215
216        self.ChangeDict = {'precision' : self.change_precision,
217                      'rounding' : self.change_rounding_method,
218                      'maxexponent' : self.change_max_exponent,
219                      'minexponent' : self.change_min_exponent,
220                      'clamp' : self.change_clamp}
221
222    def eval_file(self, file):
223        global skip_expected
224        if skip_expected:
225            raise unittest.SkipTest
226            return
227        with open(file) as f:
228            for line in f:
229                line = line.replace('\r\n', '').replace('\n', '')
230                #print line
231                try:
232                    t = self.eval_line(line)
233                except DecimalException as exception:
234                    #Exception raised where there shouldn't have been one.
235                    self.fail('Exception "'+exception.__class__.__name__ + '" raised on line '+line)
236
237        return
238
239    def eval_line(self, s):
240        if s.find(' -> ') >= 0 and s[:2] != '--' and not s.startswith('  --'):
241            s = (s.split('->')[0] + '->' +
242                 s.split('->')[1].split('--')[0]).strip()
243        else:
244            s = s.split('--')[0].strip()
245
246        for ignore in self.ignore_list:
247            if s.find(ignore) >= 0:
248                #print s.split()[0], 'NotImplemented--', ignore
249                return
250        if not s:
251            return
252        elif ':' in s:
253            return self.eval_directive(s)
254        else:
255            return self.eval_equation(s)
256
257    def eval_directive(self, s):
258        funct, value = map(lambda x: x.strip().lower(), s.split(':'))
259        if funct == 'rounding':
260            value = RoundingDict[value]
261        else:
262            try:
263                value = int(value)
264            except ValueError:
265                pass
266
267        funct = self.ChangeDict.get(funct, Nonfunction)
268        funct(value)
269
270    def eval_equation(self, s):
271        #global DEFAULT_PRECISION
272        #print DEFAULT_PRECISION
273
274        if not TEST_ALL and random.random() < 0.90:
275            return
276
277        try:
278            Sides = s.split('->')
279            L = Sides[0].strip().split()
280            id = L[0]
281            if DEBUG:
282                print "Test ", id,
283            funct = L[1].lower()
284            valstemp = L[2:]
285            L = Sides[1].strip().split()
286            ans = L[0]
287            exceptions = L[1:]
288        except (TypeError, AttributeError, IndexError):
289            raise InvalidOperation
290        def FixQuotes(val):
291            val = val.replace("''", 'SingleQuote').replace('""', 'DoubleQuote')
292            val = val.replace("'", '').replace('"', '')
293            val = val.replace('SingleQuote', "'").replace('DoubleQuote', '"')
294            return val
295
296        if id in skipped_test_ids:
297            return
298
299        fname = nameAdapter.get(funct, funct)
300        if fname == 'rescale':
301            return
302        funct = getattr(self.context, fname)
303        vals = []
304        conglomerate = ''
305        quote = 0
306        theirexceptions = [ErrorNames[x.lower()] for x in exceptions]
307
308        for exception in Signals:
309            self.context.traps[exception] = 1 #Catch these bugs...
310        for exception in theirexceptions:
311            self.context.traps[exception] = 0
312        for i, val in enumerate(valstemp):
313            if val.count("'") % 2 == 1:
314                quote = 1 - quote
315            if quote:
316                conglomerate = conglomerate + ' ' + val
317                continue
318            else:
319                val = conglomerate + val
320                conglomerate = ''
321            v = FixQuotes(val)
322            if fname in ('to_sci_string', 'to_eng_string'):
323                if EXTENDEDERRORTEST:
324                    for error in theirexceptions:
325                        self.context.traps[error] = 1
326                        try:
327                            funct(self.context.create_decimal(v))
328                        except error:
329                            pass
330                        except Signals, e:
331                            self.fail("Raised %s in %s when %s disabled" % \
332                                      (e, s, error))
333                        else:
334                            self.fail("Did not raise %s in %s" % (error, s))
335                        self.context.traps[error] = 0
336                v = self.context.create_decimal(v)
337            else:
338                v = Decimal(v, self.context)
339            vals.append(v)
340
341        ans = FixQuotes(ans)
342
343        if EXTENDEDERRORTEST and fname not in ('to_sci_string', 'to_eng_string'):
344            for error in theirexceptions:
345                self.context.traps[error] = 1
346                try:
347                    funct(*vals)
348                except error:
349                    pass
350                except Signals, e:
351                    self.fail("Raised %s in %s when %s disabled" % \
352                              (e, s, error))
353                else:
354                    self.fail("Did not raise %s in %s" % (error, s))
355                self.context.traps[error] = 0
356
357            # as above, but add traps cumulatively, to check precedence
358            ordered_errors = [e for e in OrderedSignals if e in theirexceptions]
359            for error in ordered_errors:
360                self.context.traps[error] = 1
361                try:
362                    funct(*vals)
363                except error:
364                    pass
365                except Signals, e:
366                    self.fail("Raised %s in %s; expected %s" %
367                              (type(e), s, error))
368                else:
369                    self.fail("Did not raise %s in %s" % (error, s))
370            # reset traps
371            for error in ordered_errors:
372                self.context.traps[error] = 0
373
374
375        if DEBUG:
376            print "--", self.context
377        try:
378            result = str(funct(*vals))
379            if fname in LOGICAL_FUNCTIONS:
380                result = str(int(eval(result))) # 'True', 'False' -> '1', '0'
381        except Signals, error:
382            self.fail("Raised %s in %s" % (error, s))
383        except: #Catch any error long enough to state the test case.
384            print "ERROR:", s
385            raise
386
387        myexceptions = self.getexceptions()
388        self.context.clear_flags()
389
390        self.assertEqual(result, ans,
391                         'Incorrect answer for ' + s + ' -- got ' + result)
392        self.assertItemsEqual(myexceptions, theirexceptions,
393              'Incorrect flags set in ' + s + ' -- got ' + str(myexceptions))
394        return
395
396    def getexceptions(self):
397        return [e for e in Signals if self.context.flags[e]]
398
399    def change_precision(self, prec):
400        self.context.prec = prec
401    def change_rounding_method(self, rounding):
402        self.context.rounding = rounding
403    def change_min_exponent(self, exp):
404        self.context.Emin = exp
405    def change_max_exponent(self, exp):
406        self.context.Emax = exp
407    def change_clamp(self, clamp):
408        self.context._clamp = clamp
409
410
411
412# The following classes test the behaviour of Decimal according to PEP 327
413
414class DecimalExplicitConstructionTest(unittest.TestCase):
415    '''Unit tests for Explicit Construction cases of Decimal.'''
416
417    def test_explicit_empty(self):
418        self.assertEqual(Decimal(), Decimal("0"))
419
420    def test_explicit_from_None(self):
421        self.assertRaises(TypeError, Decimal, None)
422
423    def test_explicit_from_int(self):
424
425        #positive
426        d = Decimal(45)
427        self.assertEqual(str(d), '45')
428
429        #very large positive
430        d = Decimal(500000123)
431        self.assertEqual(str(d), '500000123')
432
433        #negative
434        d = Decimal(-45)
435        self.assertEqual(str(d), '-45')
436
437        #zero
438        d = Decimal(0)
439        self.assertEqual(str(d), '0')
440
441    def test_explicit_from_string(self):
442
443        #empty
444        self.assertEqual(str(Decimal('')), 'NaN')
445
446        #int
447        self.assertEqual(str(Decimal('45')), '45')
448
449        #float
450        self.assertEqual(str(Decimal('45.34')), '45.34')
451
452        #engineer notation
453        self.assertEqual(str(Decimal('45e2')), '4.5E+3')
454
455        #just not a number
456        self.assertEqual(str(Decimal('ugly')), 'NaN')
457
458        #leading and trailing whitespace permitted
459        self.assertEqual(str(Decimal('1.3E4 \n')), '1.3E+4')
460        self.assertEqual(str(Decimal('  -7.89')), '-7.89')
461
462        #unicode strings should be permitted
463        self.assertEqual(str(Decimal(u'0E-017')), '0E-17')
464        self.assertEqual(str(Decimal(u'45')), '45')
465        self.assertEqual(str(Decimal(u'-Inf')), '-Infinity')
466        self.assertEqual(str(Decimal(u'NaN123')), 'NaN123')
467
468    def test_explicit_from_tuples(self):
469
470        #zero
471        d = Decimal( (0, (0,), 0) )
472        self.assertEqual(str(d), '0')
473
474        #int
475        d = Decimal( (1, (4, 5), 0) )
476        self.assertEqual(str(d), '-45')
477
478        #float
479        d = Decimal( (0, (4, 5, 3, 4), -2) )
480        self.assertEqual(str(d), '45.34')
481
482        #weird
483        d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
484        self.assertEqual(str(d), '-4.34913534E-17')
485
486        #wrong number of items
487        self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1)) )
488
489        #bad sign
490        self.assertRaises(ValueError, Decimal, (8, (4, 3, 4, 9, 1), 2) )
491        self.assertRaises(ValueError, Decimal, (0., (4, 3, 4, 9, 1), 2) )
492        self.assertRaises(ValueError, Decimal, (Decimal(1), (4, 3, 4, 9, 1), 2))
493
494        #bad exp
495        self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 'wrong!') )
496        self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 0.) )
497        self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), '1') )
498
499        #bad coefficients
500        self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, None, 1), 2) )
501        self.assertRaises(ValueError, Decimal, (1, (4, -3, 4, 9, 1), 2) )
502        self.assertRaises(ValueError, Decimal, (1, (4, 10, 4, 9, 1), 2) )
503        self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 'a', 1), 2) )
504
505    def test_explicit_from_bool(self):
506        self.assertIs(bool(Decimal(0)), False)
507        self.assertIs(bool(Decimal(1)), True)
508        self.assertEqual(Decimal(False), Decimal(0))
509        self.assertEqual(Decimal(True), Decimal(1))
510
511    def test_explicit_from_Decimal(self):
512
513        #positive
514        d = Decimal(45)
515        e = Decimal(d)
516        self.assertEqual(str(e), '45')
517        self.assertNotEqual(id(d), id(e))
518
519        #very large positive
520        d = Decimal(500000123)
521        e = Decimal(d)
522        self.assertEqual(str(e), '500000123')
523        self.assertNotEqual(id(d), id(e))
524
525        #negative
526        d = Decimal(-45)
527        e = Decimal(d)
528        self.assertEqual(str(e), '-45')
529        self.assertNotEqual(id(d), id(e))
530
531        #zero
532        d = Decimal(0)
533        e = Decimal(d)
534        self.assertEqual(str(e), '0')
535        self.assertNotEqual(id(d), id(e))
536
537    @requires_IEEE_754
538    def test_explicit_from_float(self):
539        r = Decimal(0.1)
540        self.assertEqual(type(r), Decimal)
541        self.assertEqual(str(r),
542                '0.1000000000000000055511151231257827021181583404541015625')
543        self.assertTrue(Decimal(float('nan')).is_qnan())
544        self.assertTrue(Decimal(float('inf')).is_infinite())
545        self.assertTrue(Decimal(float('-inf')).is_infinite())
546        self.assertEqual(str(Decimal(float('nan'))),
547                         str(Decimal('NaN')))
548        self.assertEqual(str(Decimal(float('inf'))),
549                         str(Decimal('Infinity')))
550        self.assertEqual(str(Decimal(float('-inf'))),
551                         str(Decimal('-Infinity')))
552        self.assertEqual(str(Decimal(float('-0.0'))),
553                         str(Decimal('-0')))
554        for i in range(200):
555            x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
556            self.assertEqual(x, float(Decimal(x))) # roundtrip
557
558    def test_explicit_context_create_decimal(self):
559
560        nc = copy.copy(getcontext())
561        nc.prec = 3
562
563        # empty
564        d = Decimal()
565        self.assertEqual(str(d), '0')
566        d = nc.create_decimal()
567        self.assertEqual(str(d), '0')
568
569        # from None
570        self.assertRaises(TypeError, nc.create_decimal, None)
571
572        # from int
573        d = nc.create_decimal(456)
574        self.assertIsInstance(d, Decimal)
575        self.assertEqual(nc.create_decimal(45678),
576                         nc.create_decimal('457E+2'))
577
578        # from string
579        d = Decimal('456789')
580        self.assertEqual(str(d), '456789')
581        d = nc.create_decimal('456789')
582        self.assertEqual(str(d), '4.57E+5')
583        # leading and trailing whitespace should result in a NaN;
584        # spaces are already checked in Cowlishaw's test-suite, so
585        # here we just check that a trailing newline results in a NaN
586        self.assertEqual(str(nc.create_decimal('3.14\n')), 'NaN')
587
588        # from tuples
589        d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
590        self.assertEqual(str(d), '-4.34913534E-17')
591        d = nc.create_decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
592        self.assertEqual(str(d), '-4.35E-17')
593
594        # from Decimal
595        prevdec = Decimal(500000123)
596        d = Decimal(prevdec)
597        self.assertEqual(str(d), '500000123')
598        d = nc.create_decimal(prevdec)
599        self.assertEqual(str(d), '5.00E+8')
600
601    def test_unicode_digits(self):
602        test_values = {
603            u'\uff11': '1',
604            u'\u0660.\u0660\u0663\u0667\u0662e-\u0663' : '0.0000372',
605            u'-nan\u0c68\u0c6a\u0c66\u0c66' : '-NaN2400',
606            }
607        for input, expected in test_values.items():
608            self.assertEqual(str(Decimal(input)), expected)
609
610
611class DecimalImplicitConstructionTest(unittest.TestCase):
612    '''Unit tests for Implicit Construction cases of Decimal.'''
613
614    def test_implicit_from_None(self):
615        self.assertRaises(TypeError, eval, 'Decimal(5) + None', globals())
616
617    def test_implicit_from_int(self):
618        #normal
619        self.assertEqual(str(Decimal(5) + 45), '50')
620        #exceeding precision
621        self.assertEqual(Decimal(5) + 123456789000, Decimal(123456789000))
622
623    def test_implicit_from_string(self):
624        self.assertRaises(TypeError, eval, 'Decimal(5) + "3"', globals())
625
626    def test_implicit_from_float(self):
627        self.assertRaises(TypeError, eval, 'Decimal(5) + 2.2', globals())
628
629    def test_implicit_from_Decimal(self):
630        self.assertEqual(Decimal(5) + Decimal(45), Decimal(50))
631
632    def test_rop(self):
633        # Allow other classes to be trained to interact with Decimals
634        class E:
635            def __divmod__(self, other):
636                return 'divmod ' + str(other)
637            def __rdivmod__(self, other):
638                return str(other) + ' rdivmod'
639            def __lt__(self, other):
640                return 'lt ' + str(other)
641            def __gt__(self, other):
642                return 'gt ' + str(other)
643            def __le__(self, other):
644                return 'le ' + str(other)
645            def __ge__(self, other):
646                return 'ge ' + str(other)
647            def __eq__(self, other):
648                return 'eq ' + str(other)
649            def __ne__(self, other):
650                return 'ne ' + str(other)
651
652        self.assertEqual(divmod(E(), Decimal(10)), 'divmod 10')
653        self.assertEqual(divmod(Decimal(10), E()), '10 rdivmod')
654        self.assertEqual(eval('Decimal(10) < E()'), 'gt 10')
655        self.assertEqual(eval('Decimal(10) > E()'), 'lt 10')
656        self.assertEqual(eval('Decimal(10) <= E()'), 'ge 10')
657        self.assertEqual(eval('Decimal(10) >= E()'), 'le 10')
658        self.assertEqual(eval('Decimal(10) == E()'), 'eq 10')
659        self.assertEqual(eval('Decimal(10) != E()'), 'ne 10')
660
661        # insert operator methods and then exercise them
662        oplist = [
663            ('+', '__add__', '__radd__'),
664            ('-', '__sub__', '__rsub__'),
665            ('*', '__mul__', '__rmul__'),
666            ('%', '__mod__', '__rmod__'),
667            ('//', '__floordiv__', '__rfloordiv__'),
668            ('**', '__pow__', '__rpow__')
669        ]
670        with check_py3k_warnings():
671            if 1 / 2 == 0:
672                # testing with classic division, so add __div__
673                oplist.append(('/', '__div__', '__rdiv__'))
674            else:
675                # testing with -Qnew, so add __truediv__
676                oplist.append(('/', '__truediv__', '__rtruediv__'))
677
678        for sym, lop, rop in oplist:
679            setattr(E, lop, lambda self, other: 'str' + lop + str(other))
680            setattr(E, rop, lambda self, other: str(other) + rop + 'str')
681            self.assertEqual(eval('E()' + sym + 'Decimal(10)'),
682                             'str' + lop + '10')
683            self.assertEqual(eval('Decimal(10)' + sym + 'E()'),
684                             '10' + rop + 'str')
685
686
687class DecimalFormatTest(unittest.TestCase):
688    '''Unit tests for the format function.'''
689    def test_formatting(self):
690        # triples giving a format, a Decimal, and the expected result
691        test_values = [
692            ('e', '0E-15', '0e-15'),
693            ('e', '2.3E-15', '2.3e-15'),
694            ('e', '2.30E+2', '2.30e+2'), # preserve significant zeros
695            ('e', '2.30000E-15', '2.30000e-15'),
696            ('e', '1.23456789123456789e40', '1.23456789123456789e+40'),
697            ('e', '1.5', '1.5e+0'),
698            ('e', '0.15', '1.5e-1'),
699            ('e', '0.015', '1.5e-2'),
700            ('e', '0.0000000000015', '1.5e-12'),
701            ('e', '15.0', '1.50e+1'),
702            ('e', '-15', '-1.5e+1'),
703            ('e', '0', '0e+0'),
704            ('e', '0E1', '0e+1'),
705            ('e', '0.0', '0e-1'),
706            ('e', '0.00', '0e-2'),
707            ('.6e', '0E-15', '0.000000e-9'),
708            ('.6e', '0', '0.000000e+6'),
709            ('.6e', '9.999999', '9.999999e+0'),
710            ('.6e', '9.9999999', '1.000000e+1'),
711            ('.6e', '-1.23e5', '-1.230000e+5'),
712            ('.6e', '1.23456789e-3', '1.234568e-3'),
713            ('f', '0', '0'),
714            ('f', '0.0', '0.0'),
715            ('f', '0E-2', '0.00'),
716            ('f', '0.00E-8', '0.0000000000'),
717            ('f', '0E1', '0'), # loses exponent information
718            ('f', '3.2E1', '32'),
719            ('f', '3.2E2', '320'),
720            ('f', '3.20E2', '320'),
721            ('f', '3.200E2', '320.0'),
722            ('f', '3.2E-6', '0.0000032'),
723            ('.6f', '0E-15', '0.000000'), # all zeros treated equally
724            ('.6f', '0E1', '0.000000'),
725            ('.6f', '0', '0.000000'),
726            ('.0f', '0', '0'), # no decimal point
727            ('.0f', '0e-2', '0'),
728            ('.0f', '3.14159265', '3'),
729            ('.1f', '3.14159265', '3.1'),
730            ('.4f', '3.14159265', '3.1416'),
731            ('.6f', '3.14159265', '3.141593'),
732            ('.7f', '3.14159265', '3.1415926'), # round-half-even!
733            ('.8f', '3.14159265', '3.14159265'),
734            ('.9f', '3.14159265', '3.141592650'),
735
736            ('g', '0', '0'),
737            ('g', '0.0', '0.0'),
738            ('g', '0E1', '0e+1'),
739            ('G', '0E1', '0E+1'),
740            ('g', '0E-5', '0.00000'),
741            ('g', '0E-6', '0.000000'),
742            ('g', '0E-7', '0e-7'),
743            ('g', '-0E2', '-0e+2'),
744            ('.0g', '3.14159265', '3'),  # 0 sig fig -> 1 sig fig
745            ('.1g', '3.14159265', '3'),
746            ('.2g', '3.14159265', '3.1'),
747            ('.5g', '3.14159265', '3.1416'),
748            ('.7g', '3.14159265', '3.141593'),
749            ('.8g', '3.14159265', '3.1415926'), # round-half-even!
750            ('.9g', '3.14159265', '3.14159265'),
751            ('.10g', '3.14159265', '3.14159265'), # don't pad
752
753            ('%', '0E1', '0%'),
754            ('%', '0E0', '0%'),
755            ('%', '0E-1', '0%'),
756            ('%', '0E-2', '0%'),
757            ('%', '0E-3', '0.0%'),
758            ('%', '0E-4', '0.00%'),
759
760            ('.3%', '0', '0.000%'), # all zeros treated equally
761            ('.3%', '0E10', '0.000%'),
762            ('.3%', '0E-10', '0.000%'),
763            ('.3%', '2.34', '234.000%'),
764            ('.3%', '1.234567', '123.457%'),
765            ('.0%', '1.23', '123%'),
766
767            ('e', 'NaN', 'NaN'),
768            ('f', '-NaN123', '-NaN123'),
769            ('+g', 'NaN456', '+NaN456'),
770            ('.3e', 'Inf', 'Infinity'),
771            ('.16f', '-Inf', '-Infinity'),
772            ('.0g', '-sNaN', '-sNaN'),
773
774            ('', '1.00', '1.00'),
775
776            # test alignment and padding
777            ('6', '123', '   123'),
778            ('<6', '123', '123   '),
779            ('>6', '123', '   123'),
780            ('^6', '123', ' 123  '),
781            ('=+6', '123', '+  123'),
782            ('#<10', 'NaN', 'NaN#######'),
783            ('#<10', '-4.3', '-4.3######'),
784            ('#<+10', '0.0130', '+0.0130###'),
785            ('#< 10', '0.0130', ' 0.0130###'),
786            ('@>10', '-Inf', '@-Infinity'),
787            ('#>5', '-Inf', '-Infinity'),
788            ('?^5', '123', '?123?'),
789            ('%^6', '123', '%123%%'),
790            (' ^6', '-45.6', '-45.6 '),
791            ('/=10', '-45.6', '-/////45.6'),
792            ('/=+10', '45.6', '+/////45.6'),
793            ('/= 10', '45.6', ' /////45.6'),
794
795            # thousands separator
796            (',', '1234567', '1,234,567'),
797            (',', '123456', '123,456'),
798            (',', '12345', '12,345'),
799            (',', '1234', '1,234'),
800            (',', '123', '123'),
801            (',', '12', '12'),
802            (',', '1', '1'),
803            (',', '0', '0'),
804            (',', '-1234567', '-1,234,567'),
805            (',', '-123456', '-123,456'),
806            ('7,', '123456', '123,456'),
807            ('8,', '123456', ' 123,456'),
808            ('08,', '123456', '0,123,456'), # special case: extra 0 needed
809            ('+08,', '123456', '+123,456'), # but not if there's a sign
810            (' 08,', '123456', ' 123,456'),
811            ('08,', '-123456', '-123,456'),
812            ('+09,', '123456', '+0,123,456'),
813            # ... with fractional part...
814            ('07,', '1234.56', '1,234.56'),
815            ('08,', '1234.56', '1,234.56'),
816            ('09,', '1234.56', '01,234.56'),
817            ('010,', '1234.56', '001,234.56'),
818            ('011,', '1234.56', '0,001,234.56'),
819            ('012,', '1234.56', '0,001,234.56'),
820            ('08,.1f', '1234.5', '01,234.5'),
821            # no thousands separators in fraction part
822            (',', '1.23456789', '1.23456789'),
823            (',%', '123.456789', '12,345.6789%'),
824            (',e', '123456', '1.23456e+5'),
825            (',E', '123456', '1.23456E+5'),
826
827            # issue 6850
828            ('a=-7.0', '0.12345', 'aaaa0.1'),
829            ]
830        for fmt, d, result in test_values:
831            self.assertEqual(format(Decimal(d), fmt), result)
832
833    def test_n_format(self):
834        try:
835            from locale import CHAR_MAX
836        except ImportError:
837            return
838
839        # Set up some localeconv-like dictionaries
840        en_US = {
841            'decimal_point' : '.',
842            'grouping' : [3, 3, 0],
843            'thousands_sep': ','
844            }
845
846        fr_FR = {
847            'decimal_point' : ',',
848            'grouping' : [CHAR_MAX],
849            'thousands_sep' : ''
850            }
851
852        ru_RU = {
853            'decimal_point' : ',',
854            'grouping' : [3, 3, 0],
855            'thousands_sep' : ' '
856            }
857
858        crazy = {
859            'decimal_point' : '&',
860            'grouping' : [1, 4, 2, CHAR_MAX],
861            'thousands_sep' : '-'
862            }
863
864
865        def get_fmt(x, locale, fmt='n'):
866            return Decimal.__format__(Decimal(x), fmt, _localeconv=locale)
867
868        self.assertEqual(get_fmt(Decimal('12.7'), en_US), '12.7')
869        self.assertEqual(get_fmt(Decimal('12.7'), fr_FR), '12,7')
870        self.assertEqual(get_fmt(Decimal('12.7'), ru_RU), '12,7')
871        self.assertEqual(get_fmt(Decimal('12.7'), crazy), '1-2&7')
872
873        self.assertEqual(get_fmt(123456789, en_US), '123,456,789')
874        self.assertEqual(get_fmt(123456789, fr_FR), '123456789')
875        self.assertEqual(get_fmt(123456789, ru_RU), '123 456 789')
876        self.assertEqual(get_fmt(1234567890123, crazy), '123456-78-9012-3')
877
878        self.assertEqual(get_fmt(123456789, en_US, '.6n'), '1.23457e+8')
879        self.assertEqual(get_fmt(123456789, fr_FR, '.6n'), '1,23457e+8')
880        self.assertEqual(get_fmt(123456789, ru_RU, '.6n'), '1,23457e+8')
881        self.assertEqual(get_fmt(123456789, crazy, '.6n'), '1&23457e+8')
882
883        # zero padding
884        self.assertEqual(get_fmt(1234, fr_FR, '03n'), '1234')
885        self.assertEqual(get_fmt(1234, fr_FR, '04n'), '1234')
886        self.assertEqual(get_fmt(1234, fr_FR, '05n'), '01234')
887        self.assertEqual(get_fmt(1234, fr_FR, '06n'), '001234')
888
889        self.assertEqual(get_fmt(12345, en_US, '05n'), '12,345')
890        self.assertEqual(get_fmt(12345, en_US, '06n'), '12,345')
891        self.assertEqual(get_fmt(12345, en_US, '07n'), '012,345')
892        self.assertEqual(get_fmt(12345, en_US, '08n'), '0,012,345')
893        self.assertEqual(get_fmt(12345, en_US, '09n'), '0,012,345')
894        self.assertEqual(get_fmt(12345, en_US, '010n'), '00,012,345')
895
896        self.assertEqual(get_fmt(123456, crazy, '06n'), '1-2345-6')
897        self.assertEqual(get_fmt(123456, crazy, '07n'), '1-2345-6')
898        self.assertEqual(get_fmt(123456, crazy, '08n'), '1-2345-6')
899        self.assertEqual(get_fmt(123456, crazy, '09n'), '01-2345-6')
900        self.assertEqual(get_fmt(123456, crazy, '010n'), '0-01-2345-6')
901        self.assertEqual(get_fmt(123456, crazy, '011n'), '0-01-2345-6')
902        self.assertEqual(get_fmt(123456, crazy, '012n'), '00-01-2345-6')
903        self.assertEqual(get_fmt(123456, crazy, '013n'), '000-01-2345-6')
904
905
906class DecimalArithmeticOperatorsTest(unittest.TestCase):
907    '''Unit tests for all arithmetic operators, binary and unary.'''
908
909    def test_addition(self):
910
911        d1 = Decimal('-11.1')
912        d2 = Decimal('22.2')
913
914        #two Decimals
915        self.assertEqual(d1+d2, Decimal('11.1'))
916        self.assertEqual(d2+d1, Decimal('11.1'))
917
918        #with other type, left
919        c = d1 + 5
920        self.assertEqual(c, Decimal('-6.1'))
921        self.assertEqual(type(c), type(d1))
922
923        #with other type, right
924        c = 5 + d1
925        self.assertEqual(c, Decimal('-6.1'))
926        self.assertEqual(type(c), type(d1))
927
928        #inline with decimal
929        d1 += d2
930        self.assertEqual(d1, Decimal('11.1'))
931
932        #inline with other type
933        d1 += 5
934        self.assertEqual(d1, Decimal('16.1'))
935
936    def test_subtraction(self):
937
938        d1 = Decimal('-11.1')
939        d2 = Decimal('22.2')
940
941        #two Decimals
942        self.assertEqual(d1-d2, Decimal('-33.3'))
943        self.assertEqual(d2-d1, Decimal('33.3'))
944
945        #with other type, left
946        c = d1 - 5
947        self.assertEqual(c, Decimal('-16.1'))
948        self.assertEqual(type(c), type(d1))
949
950        #with other type, right
951        c = 5 - d1
952        self.assertEqual(c, Decimal('16.1'))
953        self.assertEqual(type(c), type(d1))
954
955        #inline with decimal
956        d1 -= d2
957        self.assertEqual(d1, Decimal('-33.3'))
958
959        #inline with other type
960        d1 -= 5
961        self.assertEqual(d1, Decimal('-38.3'))
962
963    def test_multiplication(self):
964
965        d1 = Decimal('-5')
966        d2 = Decimal('3')
967
968        #two Decimals
969        self.assertEqual(d1*d2, Decimal('-15'))
970        self.assertEqual(d2*d1, Decimal('-15'))
971
972        #with other type, left
973        c = d1 * 5
974        self.assertEqual(c, Decimal('-25'))
975        self.assertEqual(type(c), type(d1))
976
977        #with other type, right
978        c = 5 * d1
979        self.assertEqual(c, Decimal('-25'))
980        self.assertEqual(type(c), type(d1))
981
982        #inline with decimal
983        d1 *= d2
984        self.assertEqual(d1, Decimal('-15'))
985
986        #inline with other type
987        d1 *= 5
988        self.assertEqual(d1, Decimal('-75'))
989
990    def test_division(self):
991
992        d1 = Decimal('-5')
993        d2 = Decimal('2')
994
995        #two Decimals
996        self.assertEqual(d1/d2, Decimal('-2.5'))
997        self.assertEqual(d2/d1, Decimal('-0.4'))
998
999        #with other type, left
1000        c = d1 / 4
1001        self.assertEqual(c, Decimal('-1.25'))
1002        self.assertEqual(type(c), type(d1))
1003
1004        #with other type, right
1005        c = 4 / d1
1006        self.assertEqual(c, Decimal('-0.8'))
1007        self.assertEqual(type(c), type(d1))
1008
1009        #inline with decimal
1010        d1 /= d2
1011        self.assertEqual(d1, Decimal('-2.5'))
1012
1013        #inline with other type
1014        d1 /= 4
1015        self.assertEqual(d1, Decimal('-0.625'))
1016
1017    def test_floor_division(self):
1018
1019        d1 = Decimal('5')
1020        d2 = Decimal('2')
1021
1022        #two Decimals
1023        self.assertEqual(d1//d2, Decimal('2'))
1024        self.assertEqual(d2//d1, Decimal('0'))
1025
1026        #with other type, left
1027        c = d1 // 4
1028        self.assertEqual(c, Decimal('1'))
1029        self.assertEqual(type(c), type(d1))
1030
1031        #with other type, right
1032        c = 7 // d1
1033        self.assertEqual(c, Decimal('1'))
1034        self.assertEqual(type(c), type(d1))
1035
1036        #inline with decimal
1037        d1 //= d2
1038        self.assertEqual(d1, Decimal('2'))
1039
1040        #inline with other type
1041        d1 //= 2
1042        self.assertEqual(d1, Decimal('1'))
1043
1044    def test_powering(self):
1045
1046        d1 = Decimal('5')
1047        d2 = Decimal('2')
1048
1049        #two Decimals
1050        self.assertEqual(d1**d2, Decimal('25'))
1051        self.assertEqual(d2**d1, Decimal('32'))
1052
1053        #with other type, left
1054        c = d1 ** 4
1055        self.assertEqual(c, Decimal('625'))
1056        self.assertEqual(type(c), type(d1))
1057
1058        #with other type, right
1059        c = 7 ** d1
1060        self.assertEqual(c, Decimal('16807'))
1061        self.assertEqual(type(c), type(d1))
1062
1063        #inline with decimal
1064        d1 **= d2
1065        self.assertEqual(d1, Decimal('25'))
1066
1067        #inline with other type
1068        d1 **= 4
1069        self.assertEqual(d1, Decimal('390625'))
1070
1071    def test_module(self):
1072
1073        d1 = Decimal('5')
1074        d2 = Decimal('2')
1075
1076        #two Decimals
1077        self.assertEqual(d1%d2, Decimal('1'))
1078        self.assertEqual(d2%d1, Decimal('2'))
1079
1080        #with other type, left
1081        c = d1 % 4
1082        self.assertEqual(c, Decimal('1'))
1083        self.assertEqual(type(c), type(d1))
1084
1085        #with other type, right
1086        c = 7 % d1
1087        self.assertEqual(c, Decimal('2'))
1088        self.assertEqual(type(c), type(d1))
1089
1090        #inline with decimal
1091        d1 %= d2
1092        self.assertEqual(d1, Decimal('1'))
1093
1094        #inline with other type
1095        d1 %= 4
1096        self.assertEqual(d1, Decimal('1'))
1097
1098    def test_floor_div_module(self):
1099
1100        d1 = Decimal('5')
1101        d2 = Decimal('2')
1102
1103        #two Decimals
1104        (p, q) = divmod(d1, d2)
1105        self.assertEqual(p, Decimal('2'))
1106        self.assertEqual(q, Decimal('1'))
1107        self.assertEqual(type(p), type(d1))
1108        self.assertEqual(type(q), type(d1))
1109
1110        #with other type, left
1111        (p, q) = divmod(d1, 4)
1112        self.assertEqual(p, Decimal('1'))
1113        self.assertEqual(q, Decimal('1'))
1114        self.assertEqual(type(p), type(d1))
1115        self.assertEqual(type(q), type(d1))
1116
1117        #with other type, right
1118        (p, q) = divmod(7, d1)
1119        self.assertEqual(p, Decimal('1'))
1120        self.assertEqual(q, Decimal('2'))
1121        self.assertEqual(type(p), type(d1))
1122        self.assertEqual(type(q), type(d1))
1123
1124    def test_unary_operators(self):
1125        self.assertEqual(+Decimal(45), Decimal(+45))           #  +
1126        self.assertEqual(-Decimal(45), Decimal(-45))           #  -
1127        self.assertEqual(abs(Decimal(45)), abs(Decimal(-45)))  # abs
1128
1129    def test_nan_comparisons(self):
1130        # comparisons involving signaling nans signal InvalidOperation
1131
1132        # order comparisons (<, <=, >, >=) involving only quiet nans
1133        # also signal InvalidOperation
1134
1135        # equality comparisons (==, !=) involving only quiet nans
1136        # don't signal, but return False or True respectively.
1137
1138        n = Decimal('NaN')
1139        s = Decimal('sNaN')
1140        i = Decimal('Inf')
1141        f = Decimal('2')
1142
1143        qnan_pairs = (n, n), (n, i), (i, n), (n, f), (f, n)
1144        snan_pairs = (s, n), (n, s), (s, i), (i, s), (s, f), (f, s), (s, s)
1145        order_ops = operator.lt, operator.le, operator.gt, operator.ge
1146        equality_ops = operator.eq, operator.ne
1147
1148        # results when InvalidOperation is not trapped
1149        for x, y in qnan_pairs + snan_pairs:
1150            for op in order_ops + equality_ops:
1151                got = op(x, y)
1152                expected = True if op is operator.ne else False
1153                self.assertIs(expected, got,
1154                              "expected {0!r} for operator.{1}({2!r}, {3!r}); "
1155                              "got {4!r}".format(
1156                        expected, op.__name__, x, y, got))
1157
1158        # repeat the above, but this time trap the InvalidOperation
1159        with localcontext() as ctx:
1160            ctx.traps[InvalidOperation] = 1
1161
1162            for x, y in qnan_pairs:
1163                for op in equality_ops:
1164                    got = op(x, y)
1165                    expected = True if op is operator.ne else False
1166                    self.assertIs(expected, got,
1167                                  "expected {0!r} for "
1168                                  "operator.{1}({2!r}, {3!r}); "
1169                                  "got {4!r}".format(
1170                            expected, op.__name__, x, y, got))
1171
1172            for x, y in snan_pairs:
1173                for op in equality_ops:
1174                    self.assertRaises(InvalidOperation, operator.eq, x, y)
1175                    self.assertRaises(InvalidOperation, operator.ne, x, y)
1176
1177            for x, y in qnan_pairs + snan_pairs:
1178                for op in order_ops:
1179                    self.assertRaises(InvalidOperation, op, x, y)
1180
1181    def test_copy_sign(self):
1182        d = Decimal(1).copy_sign(Decimal(-2))
1183
1184        self.assertEqual(Decimal(1).copy_sign(-2), d)
1185        self.assertRaises(TypeError, Decimal(1).copy_sign, '-2')
1186
1187# The following are two functions used to test threading in the next class
1188
1189def thfunc1(cls):
1190    d1 = Decimal(1)
1191    d3 = Decimal(3)
1192    test1 = d1/d3
1193    cls.synchro.wait()
1194    test2 = d1/d3
1195    cls.finish1.set()
1196
1197    cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
1198    cls.assertEqual(test2, Decimal('0.3333333333333333333333333333'))
1199    return
1200
1201def thfunc2(cls):
1202    d1 = Decimal(1)
1203    d3 = Decimal(3)
1204    test1 = d1/d3
1205    thiscontext = getcontext()
1206    thiscontext.prec = 18
1207    test2 = d1/d3
1208    cls.synchro.set()
1209    cls.finish2.set()
1210
1211    cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
1212    cls.assertEqual(test2, Decimal('0.333333333333333333'))
1213    return
1214
1215
1216class DecimalUseOfContextTest(unittest.TestCase):
1217    '''Unit tests for Use of Context cases in Decimal.'''
1218
1219    try:
1220        import threading
1221    except ImportError:
1222        threading = None
1223
1224    # Take care executing this test from IDLE, there's an issue in threading
1225    # that hangs IDLE and I couldn't find it
1226
1227    def test_threading(self):
1228        #Test the "threading isolation" of a Context.
1229
1230        self.synchro = threading.Event()
1231        self.finish1 = threading.Event()
1232        self.finish2 = threading.Event()
1233
1234        th1 = threading.Thread(target=thfunc1, args=(self,))
1235        th2 = threading.Thread(target=thfunc2, args=(self,))
1236
1237        th1.start()
1238        th2.start()
1239
1240        self.finish1.wait()
1241        self.finish2.wait()
1242        return
1243
1244    if threading is None:
1245        del test_threading
1246
1247
1248class DecimalUsabilityTest(unittest.TestCase):
1249    '''Unit tests for Usability cases of Decimal.'''
1250
1251    def test_comparison_operators(self):
1252
1253        da = Decimal('23.42')
1254        db = Decimal('23.42')
1255        dc = Decimal('45')
1256
1257        #two Decimals
1258        self.assertGreater(dc, da)
1259        self.assertGreaterEqual(dc, da)
1260        self.assertLess(da, dc)
1261        self.assertLessEqual(da, dc)
1262        self.assertEqual(da, db)
1263        self.assertNotEqual(da, dc)
1264        self.assertLessEqual(da, db)
1265        self.assertGreaterEqual(da, db)
1266        self.assertEqual(cmp(dc,da), 1)
1267        self.assertEqual(cmp(da,dc), -1)
1268        self.assertEqual(cmp(da,db), 0)
1269
1270        #a Decimal and an int
1271        self.assertGreater(dc, 23)
1272        self.assertLess(23, dc)
1273        self.assertEqual(dc, 45)
1274        self.assertEqual(cmp(dc,23), 1)
1275        self.assertEqual(cmp(23,dc), -1)
1276        self.assertEqual(cmp(dc,45), 0)
1277
1278        #a Decimal and uncomparable
1279        self.assertNotEqual(da, 'ugly')
1280        self.assertNotEqual(da, 32.7)
1281        self.assertNotEqual(da, object())
1282        self.assertNotEqual(da, object)
1283
1284        # sortable
1285        a = map(Decimal, xrange(100))
1286        b =  a[:]
1287        random.shuffle(a)
1288        a.sort()
1289        self.assertEqual(a, b)
1290
1291        # with None
1292        with check_py3k_warnings():
1293            self.assertFalse(Decimal(1) < None)
1294            self.assertTrue(Decimal(1) > None)
1295
1296    def test_decimal_float_comparison(self):
1297        da = Decimal('0.25')
1298        db = Decimal('3.0')
1299        self.assertLess(da, 3.0)
1300        self.assertLessEqual(da, 3.0)
1301        self.assertGreater(db, 0.25)
1302        self.assertGreaterEqual(db, 0.25)
1303        self.assertNotEqual(da, 1.5)
1304        self.assertEqual(da, 0.25)
1305        self.assertGreater(3.0, da)
1306        self.assertGreaterEqual(3.0, da)
1307        self.assertLess(0.25, db)
1308        self.assertLessEqual(0.25, db)
1309        self.assertNotEqual(0.25, db)
1310        self.assertEqual(3.0, db)
1311        self.assertNotEqual(0.1, Decimal('0.1'))
1312
1313    def test_copy_and_deepcopy_methods(self):
1314        d = Decimal('43.24')
1315        c = copy.copy(d)
1316        self.assertEqual(id(c), id(d))
1317        dc = copy.deepcopy(d)
1318        self.assertEqual(id(dc), id(d))
1319
1320    def test_hash_method(self):
1321        #just that it's hashable
1322        hash(Decimal(23))
1323        hash(Decimal('Infinity'))
1324        hash(Decimal('-Infinity'))
1325        hash(Decimal('nan123'))
1326        hash(Decimal('-NaN'))
1327
1328        test_values = [Decimal(sign*(2**m + n))
1329                       for m in [0, 14, 15, 16, 17, 30, 31,
1330                                 32, 33, 62, 63, 64, 65, 66]
1331                       for n in range(-10, 10)
1332                       for sign in [-1, 1]]
1333        test_values.extend([
1334                Decimal("-0"), # zeros
1335                Decimal("0.00"),
1336                Decimal("-0.000"),
1337                Decimal("0E10"),
1338                Decimal("-0E12"),
1339                Decimal("10.0"), # negative exponent
1340                Decimal("-23.00000"),
1341                Decimal("1230E100"), # positive exponent
1342                Decimal("-4.5678E50"),
1343                # a value for which hash(n) != hash(n % (2**64-1))
1344                # in Python pre-2.6
1345                Decimal(2**64 + 2**32 - 1),
1346                # selection of values which fail with the old (before
1347                # version 2.6) long.__hash__
1348                Decimal("1.634E100"),
1349                Decimal("90.697E100"),
1350                Decimal("188.83E100"),
1351                Decimal("1652.9E100"),
1352                Decimal("56531E100"),
1353                ])
1354
1355        # check that hash(d) == hash(int(d)) for integral values
1356        for value in test_values:
1357            self.assertEqual(hash(value), hash(int(value)))
1358
1359        #the same hash that to an int
1360        self.assertEqual(hash(Decimal(23)), hash(23))
1361        self.assertRaises(TypeError, hash, Decimal('sNaN'))
1362        self.assertTrue(hash(Decimal('Inf')))
1363        self.assertTrue(hash(Decimal('-Inf')))
1364
1365        # check that the hashes of a Decimal float match when they
1366        # represent exactly the same values
1367        test_strings = ['inf', '-Inf', '0.0', '-.0e1',
1368                        '34.0', '2.5', '112390.625', '-0.515625']
1369        for s in test_strings:
1370            f = float(s)
1371            d = Decimal(s)
1372            self.assertEqual(hash(f), hash(d))
1373
1374        # check that the value of the hash doesn't depend on the
1375        # current context (issue #1757)
1376        c = getcontext()
1377        old_precision = c.prec
1378        x = Decimal("123456789.1")
1379
1380        c.prec = 6
1381        h1 = hash(x)
1382        c.prec = 10
1383        h2 = hash(x)
1384        c.prec = 16
1385        h3 = hash(x)
1386
1387        self.assertEqual(h1, h2)
1388        self.assertEqual(h1, h3)
1389        c.prec = old_precision
1390
1391    def test_min_and_max_methods(self):
1392
1393        d1 = Decimal('15.32')
1394        d2 = Decimal('28.5')
1395        l1 = 15
1396        l2 = 28
1397
1398        #between Decimals
1399        self.assertIs(min(d1,d2), d1)
1400        self.assertIs(min(d2,d1), d1)
1401        self.assertIs(max(d1,d2), d2)
1402        self.assertIs(max(d2,d1), d2)
1403
1404        #between Decimal and long
1405        self.assertIs(min(d1,l2), d1)
1406        self.assertIs(min(l2,d1), d1)
1407        self.assertIs(max(l1,d2), d2)
1408        self.assertIs(max(d2,l1), d2)
1409
1410    def test_as_nonzero(self):
1411        #as false
1412        self.assertFalse(Decimal(0))
1413        #as true
1414        self.assertTrue(Decimal('0.372'))
1415
1416    def test_tostring_methods(self):
1417        #Test str and repr methods.
1418
1419        d = Decimal('15.32')
1420        self.assertEqual(str(d), '15.32')               # str
1421        self.assertEqual(repr(d), "Decimal('15.32')")   # repr
1422
1423        # result type of string methods should be str, not unicode
1424        unicode_inputs = [u'123.4', u'0.5E2', u'Infinity', u'sNaN',
1425                          u'-0.0E100', u'-NaN001', u'-Inf']
1426
1427        for u in unicode_inputs:
1428            d = Decimal(u)
1429            self.assertEqual(type(str(d)), str)
1430            self.assertEqual(type(repr(d)), str)
1431            self.assertEqual(type(d.to_eng_string()), str)
1432
1433    def test_tonum_methods(self):
1434        #Test float, int and long methods.
1435
1436        d1 = Decimal('66')
1437        d2 = Decimal('15.32')
1438
1439        #int
1440        self.assertEqual(int(d1), 66)
1441        self.assertEqual(int(d2), 15)
1442
1443        #long
1444        self.assertEqual(long(d1), 66)
1445        self.assertEqual(long(d2), 15)
1446
1447        #float
1448        self.assertEqual(float(d1), 66)
1449        self.assertEqual(float(d2), 15.32)
1450
1451    def test_nan_to_float(self):
1452        # Test conversions of decimal NANs to float.
1453        # See http://bugs.python.org/issue15544
1454        for s in ('nan', 'nan1234', '-nan', '-nan2468'):
1455            f = float(Decimal(s))
1456            self.assertTrue(math.isnan(f))
1457
1458    def test_snan_to_float(self):
1459        for s in ('snan', '-snan', 'snan1357', '-snan1234'):
1460            d = Decimal(s)
1461            self.assertRaises(ValueError, float, d)
1462
1463    def test_eval_round_trip(self):
1464
1465        #with zero
1466        d = Decimal( (0, (0,), 0) )
1467        self.assertEqual(d, eval(repr(d)))
1468
1469        #int
1470        d = Decimal( (1, (4, 5), 0) )
1471        self.assertEqual(d, eval(repr(d)))
1472
1473        #float
1474        d = Decimal( (0, (4, 5, 3, 4), -2) )
1475        self.assertEqual(d, eval(repr(d)))
1476
1477        #weird
1478        d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1479        self.assertEqual(d, eval(repr(d)))
1480
1481    def test_as_tuple(self):
1482
1483        #with zero
1484        d = Decimal(0)
1485        self.assertEqual(d.as_tuple(), (0, (0,), 0) )
1486
1487        #int
1488        d = Decimal(-45)
1489        self.assertEqual(d.as_tuple(), (1, (4, 5), 0) )
1490
1491        #complicated string
1492        d = Decimal("-4.34913534E-17")
1493        self.assertEqual(d.as_tuple(), (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1494
1495        #inf
1496        d = Decimal("Infinity")
1497        self.assertEqual(d.as_tuple(), (0, (0,), 'F') )
1498
1499        #leading zeros in coefficient should be stripped
1500        d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), -2) )
1501        self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), -2) )
1502        d = Decimal( (1, (0, 0, 0), 37) )
1503        self.assertEqual(d.as_tuple(), (1, (0,), 37))
1504        d = Decimal( (1, (), 37) )
1505        self.assertEqual(d.as_tuple(), (1, (0,), 37))
1506
1507        #leading zeros in NaN diagnostic info should be stripped
1508        d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), 'n') )
1509        self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), 'n') )
1510        d = Decimal( (1, (0, 0, 0), 'N') )
1511        self.assertEqual(d.as_tuple(), (1, (), 'N') )
1512        d = Decimal( (1, (), 'n') )
1513        self.assertEqual(d.as_tuple(), (1, (), 'n') )
1514
1515        #coefficient in infinity should be ignored
1516        d = Decimal( (0, (4, 5, 3, 4), 'F') )
1517        self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
1518        d = Decimal( (1, (0, 2, 7, 1), 'F') )
1519        self.assertEqual(d.as_tuple(), (1, (0,), 'F'))
1520
1521    def test_immutability_operations(self):
1522        # Do operations and check that it didn't change change internal objects.
1523
1524        d1 = Decimal('-25e55')
1525        b1 = Decimal('-25e55')
1526        d2 = Decimal('33e+33')
1527        b2 = Decimal('33e+33')
1528
1529        def checkSameDec(operation, useOther=False):
1530            if useOther:
1531                eval("d1." + operation + "(d2)")
1532                self.assertEqual(d1._sign, b1._sign)
1533                self.assertEqual(d1._int, b1._int)
1534                self.assertEqual(d1._exp, b1._exp)
1535                self.assertEqual(d2._sign, b2._sign)
1536                self.assertEqual(d2._int, b2._int)
1537                self.assertEqual(d2._exp, b2._exp)
1538            else:
1539                eval("d1." + operation + "()")
1540                self.assertEqual(d1._sign, b1._sign)
1541                self.assertEqual(d1._int, b1._int)
1542                self.assertEqual(d1._exp, b1._exp)
1543            return
1544
1545        Decimal(d1)
1546        self.assertEqual(d1._sign, b1._sign)
1547        self.assertEqual(d1._int, b1._int)
1548        self.assertEqual(d1._exp, b1._exp)
1549
1550        checkSameDec("__abs__")
1551        checkSameDec("__add__", True)
1552        checkSameDec("__div__", True)
1553        checkSameDec("__divmod__", True)
1554        checkSameDec("__eq__", True)
1555        checkSameDec("__ne__", True)
1556        checkSameDec("__le__", True)
1557        checkSameDec("__lt__", True)
1558        checkSameDec("__ge__", True)
1559        checkSameDec("__gt__", True)
1560        checkSameDec("__float__")
1561        checkSameDec("__floordiv__", True)
1562        checkSameDec("__hash__")
1563        checkSameDec("__int__")
1564        checkSameDec("__trunc__")
1565        checkSameDec("__long__")
1566        checkSameDec("__mod__", True)
1567        checkSameDec("__mul__", True)
1568        checkSameDec("__neg__")
1569        checkSameDec("__nonzero__")
1570        checkSameDec("__pos__")
1571        checkSameDec("__pow__", True)
1572        checkSameDec("__radd__", True)
1573        checkSameDec("__rdiv__", True)
1574        checkSameDec("__rdivmod__", True)
1575        checkSameDec("__repr__")
1576        checkSameDec("__rfloordiv__", True)
1577        checkSameDec("__rmod__", True)
1578        checkSameDec("__rmul__", True)
1579        checkSameDec("__rpow__", True)
1580        checkSameDec("__rsub__", True)
1581        checkSameDec("__str__")
1582        checkSameDec("__sub__", True)
1583        checkSameDec("__truediv__", True)
1584        checkSameDec("adjusted")
1585        checkSameDec("as_tuple")
1586        checkSameDec("compare", True)
1587        checkSameDec("max", True)
1588        checkSameDec("min", True)
1589        checkSameDec("normalize")
1590        checkSameDec("quantize", True)
1591        checkSameDec("remainder_near", True)
1592        checkSameDec("same_quantum", True)
1593        checkSameDec("sqrt")
1594        checkSameDec("to_eng_string")
1595        checkSameDec("to_integral")
1596
1597    def test_subclassing(self):
1598        # Different behaviours when subclassing Decimal
1599
1600        class MyDecimal(Decimal):
1601            pass
1602
1603        d1 = MyDecimal(1)
1604        d2 = MyDecimal(2)
1605        d = d1 + d2
1606        self.assertIs(type(d), Decimal)
1607
1608        d = d1.max(d2)
1609        self.assertIs(type(d), Decimal)
1610
1611    def test_implicit_context(self):
1612        # Check results when context given implicitly.  (Issue 2478)
1613        c = getcontext()
1614        self.assertEqual(str(Decimal(0).sqrt()),
1615                         str(c.sqrt(Decimal(0))))
1616
1617    def test_conversions_from_int(self):
1618        # Check that methods taking a second Decimal argument will
1619        # always accept an integer in place of a Decimal.
1620        self.assertEqual(Decimal(4).compare(3),
1621                         Decimal(4).compare(Decimal(3)))
1622        self.assertEqual(Decimal(4).compare_signal(3),
1623                         Decimal(4).compare_signal(Decimal(3)))
1624        self.assertEqual(Decimal(4).compare_total(3),
1625                         Decimal(4).compare_total(Decimal(3)))
1626        self.assertEqual(Decimal(4).compare_total_mag(3),
1627                         Decimal(4).compare_total_mag(Decimal(3)))
1628        self.assertEqual(Decimal(10101).logical_and(1001),
1629                         Decimal(10101).logical_and(Decimal(1001)))
1630        self.assertEqual(Decimal(10101).logical_or(1001),
1631                         Decimal(10101).logical_or(Decimal(1001)))
1632        self.assertEqual(Decimal(10101).logical_xor(1001),
1633                         Decimal(10101).logical_xor(Decimal(1001)))
1634        self.assertEqual(Decimal(567).max(123),
1635                         Decimal(567).max(Decimal(123)))
1636        self.assertEqual(Decimal(567).max_mag(123),
1637                         Decimal(567).max_mag(Decimal(123)))
1638        self.assertEqual(Decimal(567).min(123),
1639                         Decimal(567).min(Decimal(123)))
1640        self.assertEqual(Decimal(567).min_mag(123),
1641                         Decimal(567).min_mag(Decimal(123)))
1642        self.assertEqual(Decimal(567).next_toward(123),
1643                         Decimal(567).next_toward(Decimal(123)))
1644        self.assertEqual(Decimal(1234).quantize(100),
1645                         Decimal(1234).quantize(Decimal(100)))
1646        self.assertEqual(Decimal(768).remainder_near(1234),
1647                         Decimal(768).remainder_near(Decimal(1234)))
1648        self.assertEqual(Decimal(123).rotate(1),
1649                         Decimal(123).rotate(Decimal(1)))
1650        self.assertEqual(Decimal(1234).same_quantum(1000),
1651                         Decimal(1234).same_quantum(Decimal(1000)))
1652        self.assertEqual(Decimal('9.123').scaleb(-100),
1653                         Decimal('9.123').scaleb(Decimal(-100)))
1654        self.assertEqual(Decimal(456).shift(-1),
1655                         Decimal(456).shift(Decimal(-1)))
1656
1657        self.assertEqual(Decimal(-12).fma(Decimal(45), 67),
1658                         Decimal(-12).fma(Decimal(45), Decimal(67)))
1659        self.assertEqual(Decimal(-12).fma(45, 67),
1660                         Decimal(-12).fma(Decimal(45), Decimal(67)))
1661        self.assertEqual(Decimal(-12).fma(45, Decimal(67)),
1662                         Decimal(-12).fma(Decimal(45), Decimal(67)))
1663
1664
1665class DecimalPythonAPItests(unittest.TestCase):
1666
1667    def test_abc(self):
1668        self.assertTrue(issubclass(Decimal, numbers.Number))
1669        self.assertFalse(issubclass(Decimal, numbers.Real))
1670        self.assertIsInstance(Decimal(0), numbers.Number)
1671        self.assertNotIsInstance(Decimal(0), numbers.Real)
1672
1673    def test_pickle(self):
1674        d = Decimal('-3.141590000')
1675        p = pickle.dumps(d)
1676        e = pickle.loads(p)
1677        self.assertEqual(d, e)
1678
1679    def test_int(self):
1680        for x in range(-250, 250):
1681            s = '%0.2f' % (x / 100.0)
1682            # should work the same as for floats
1683            self.assertEqual(int(Decimal(s)), int(float(s)))
1684            # should work the same as to_integral in the ROUND_DOWN mode
1685            d = Decimal(s)
1686            r = d.to_integral(ROUND_DOWN)
1687            self.assertEqual(Decimal(int(d)), r)
1688
1689        self.assertRaises(ValueError, int, Decimal('-nan'))
1690        self.assertRaises(ValueError, int, Decimal('snan'))
1691        self.assertRaises(OverflowError, int, Decimal('inf'))
1692        self.assertRaises(OverflowError, int, Decimal('-inf'))
1693
1694        self.assertRaises(ValueError, long, Decimal('-nan'))
1695        self.assertRaises(ValueError, long, Decimal('snan'))
1696        self.assertRaises(OverflowError, long, Decimal('inf'))
1697        self.assertRaises(OverflowError, long, Decimal('-inf'))
1698
1699    def test_trunc(self):
1700        for x in range(-250, 250):
1701            s = '%0.2f' % (x / 100.0)
1702            # should work the same as for floats
1703            self.assertEqual(int(Decimal(s)), int(float(s)))
1704            # should work the same as to_integral in the ROUND_DOWN mode
1705            d = Decimal(s)
1706            r = d.to_integral(ROUND_DOWN)
1707            self.assertEqual(Decimal(math.trunc(d)), r)
1708
1709    def test_from_float(self):
1710
1711        class  MyDecimal(Decimal):
1712            pass
1713
1714        r = MyDecimal.from_float(0.1)
1715        self.assertEqual(type(r), MyDecimal)
1716        self.assertEqual(str(r),
1717                '0.1000000000000000055511151231257827021181583404541015625')
1718        bigint = 12345678901234567890123456789
1719        self.assertEqual(MyDecimal.from_float(bigint), MyDecimal(bigint))
1720        self.assertTrue(MyDecimal.from_float(float('nan')).is_qnan())
1721        self.assertTrue(MyDecimal.from_float(float('inf')).is_infinite())
1722        self.assertTrue(MyDecimal.from_float(float('-inf')).is_infinite())
1723        self.assertEqual(str(MyDecimal.from_float(float('nan'))),
1724                         str(Decimal('NaN')))
1725        self.assertEqual(str(MyDecimal.from_float(float('inf'))),
1726                         str(Decimal('Infinity')))
1727        self.assertEqual(str(MyDecimal.from_float(float('-inf'))),
1728                         str(Decimal('-Infinity')))
1729        self.assertRaises(TypeError, MyDecimal.from_float, 'abc')
1730        for i in range(200):
1731            x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
1732            self.assertEqual(x, float(MyDecimal.from_float(x))) # roundtrip
1733
1734    def test_create_decimal_from_float(self):
1735        context = Context(prec=5, rounding=ROUND_DOWN)
1736        self.assertEqual(
1737            context.create_decimal_from_float(math.pi),
1738            Decimal('3.1415')
1739        )
1740        context = Context(prec=5, rounding=ROUND_UP)
1741        self.assertEqual(
1742            context.create_decimal_from_float(math.pi),
1743            Decimal('3.1416')
1744        )
1745        context = Context(prec=5, traps=[Inexact])
1746        self.assertRaises(
1747            Inexact,
1748            context.create_decimal_from_float,
1749            math.pi
1750        )
1751        self.assertEqual(repr(context.create_decimal_from_float(-0.0)),
1752                         "Decimal('-0')")
1753        self.assertEqual(repr(context.create_decimal_from_float(1.0)),
1754                         "Decimal('1')")
1755        self.assertEqual(repr(context.create_decimal_from_float(10)),
1756                         "Decimal('10')")
1757
1758class ContextAPItests(unittest.TestCase):
1759
1760    def test_pickle(self):
1761        c = Context()
1762        e = pickle.loads(pickle.dumps(c))
1763        for k in vars(c):
1764            v1 = vars(c)[k]
1765            v2 = vars(e)[k]
1766            self.assertEqual(v1, v2)
1767
1768    def test_equality_with_other_types(self):
1769        self.assertIn(Decimal(10), ['a', 1.0, Decimal(10), (1,2), {}])
1770        self.assertNotIn(Decimal(10), ['a', 1.0, (1,2), {}])
1771
1772    def test_copy(self):
1773        # All copies should be deep
1774        c = Context()
1775        d = c.copy()
1776        self.assertNotEqual(id(c), id(d))
1777        self.assertNotEqual(id(c.flags), id(d.flags))
1778        self.assertNotEqual(id(c.traps), id(d.traps))
1779
1780    def test_abs(self):
1781        c = Context()
1782        d = c.abs(Decimal(-1))
1783        self.assertEqual(c.abs(-1), d)
1784        self.assertRaises(TypeError, c.abs, '-1')
1785
1786    def test_add(self):
1787        c = Context()
1788        d = c.add(Decimal(1), Decimal(1))
1789        self.assertEqual(c.add(1, 1), d)
1790        self.assertEqual(c.add(Decimal(1), 1), d)
1791        self.assertEqual(c.add(1, Decimal(1)), d)
1792        self.assertRaises(TypeError, c.add, '1', 1)
1793        self.assertRaises(TypeError, c.add, 1, '1')
1794
1795    def test_compare(self):
1796        c = Context()
1797        d = c.compare(Decimal(1), Decimal(1))
1798        self.assertEqual(c.compare(1, 1), d)
1799        self.assertEqual(c.compare(Decimal(1), 1), d)
1800        self.assertEqual(c.compare(1, Decimal(1)), d)
1801        self.assertRaises(TypeError, c.compare, '1', 1)
1802        self.assertRaises(TypeError, c.compare, 1, '1')
1803
1804    def test_compare_signal(self):
1805        c = Context()
1806        d = c.compare_signal(Decimal(1), Decimal(1))
1807        self.assertEqual(c.compare_signal(1, 1), d)
1808        self.assertEqual(c.compare_signal(Decimal(1), 1), d)
1809        self.assertEqual(c.compare_signal(1, Decimal(1)), d)
1810        self.assertRaises(TypeError, c.compare_signal, '1', 1)
1811        self.assertRaises(TypeError, c.compare_signal, 1, '1')
1812
1813    def test_compare_total(self):
1814        c = Context()
1815        d = c.compare_total(Decimal(1), Decimal(1))
1816        self.assertEqual(c.compare_total(1, 1), d)
1817        self.assertEqual(c.compare_total(Decimal(1), 1), d)
1818        self.assertEqual(c.compare_total(1, Decimal(1)), d)
1819        self.assertRaises(TypeError, c.compare_total, '1', 1)
1820        self.assertRaises(TypeError, c.compare_total, 1, '1')
1821
1822    def test_compare_total_mag(self):
1823        c = Context()
1824        d = c.compare_total_mag(Decimal(1), Decimal(1))
1825        self.assertEqual(c.compare_total_mag(1, 1), d)
1826        self.assertEqual(c.compare_total_mag(Decimal(1), 1), d)
1827        self.assertEqual(c.compare_total_mag(1, Decimal(1)), d)
1828        self.assertRaises(TypeError, c.compare_total_mag, '1', 1)
1829        self.assertRaises(TypeError, c.compare_total_mag, 1, '1')
1830
1831    def test_copy_abs(self):
1832        c = Context()
1833        d = c.copy_abs(Decimal(-1))
1834        self.assertEqual(c.copy_abs(-1), d)
1835        self.assertRaises(TypeError, c.copy_abs, '-1')
1836
1837    def test_copy_decimal(self):
1838        c = Context()
1839        d = c.copy_decimal(Decimal(-1))
1840        self.assertEqual(c.copy_decimal(-1), d)
1841        self.assertRaises(TypeError, c.copy_decimal, '-1')
1842
1843    def test_copy_negate(self):
1844        c = Context()
1845        d = c.copy_negate(Decimal(-1))
1846        self.assertEqual(c.copy_negate(-1), d)
1847        self.assertRaises(TypeError, c.copy_negate, '-1')
1848
1849    def test_copy_sign(self):
1850        c = Context()
1851        d = c.copy_sign(Decimal(1), Decimal(-2))
1852        self.assertEqual(c.copy_sign(1, -2), d)
1853        self.assertEqual(c.copy_sign(Decimal(1), -2), d)
1854        self.assertEqual(c.copy_sign(1, Decimal(-2)), d)
1855        self.assertRaises(TypeError, c.copy_sign, '1', -2)
1856        self.assertRaises(TypeError, c.copy_sign, 1, '-2')
1857
1858    def test_divide(self):
1859        c = Context()
1860        d = c.divide(Decimal(1), Decimal(2))
1861        self.assertEqual(c.divide(1, 2), d)
1862        self.assertEqual(c.divide(Decimal(1), 2), d)
1863        self.assertEqual(c.divide(1, Decimal(2)), d)
1864        self.assertRaises(TypeError, c.divide, '1', 2)
1865        self.assertRaises(TypeError, c.divide, 1, '2')
1866
1867    def test_divide_int(self):
1868        c = Context()
1869        d = c.divide_int(Decimal(1), Decimal(2))
1870        self.assertEqual(c.divide_int(1, 2), d)
1871        self.assertEqual(c.divide_int(Decimal(1), 2), d)
1872        self.assertEqual(c.divide_int(1, Decimal(2)), d)
1873        self.assertRaises(TypeError, c.divide_int, '1', 2)
1874        self.assertRaises(TypeError, c.divide_int, 1, '2')
1875
1876    def test_divmod(self):
1877        c = Context()
1878        d = c.divmod(Decimal(1), Decimal(2))
1879        self.assertEqual(c.divmod(1, 2), d)
1880        self.assertEqual(c.divmod(Decimal(1), 2), d)
1881        self.assertEqual(c.divmod(1, Decimal(2)), d)
1882        self.assertRaises(TypeError, c.divmod, '1', 2)
1883        self.assertRaises(TypeError, c.divmod, 1, '2')
1884
1885    def test_exp(self):
1886        c = Context()
1887        d = c.exp(Decimal(10))
1888        self.assertEqual(c.exp(10), d)
1889        self.assertRaises(TypeError, c.exp, '10')
1890
1891    def test_fma(self):
1892        c = Context()
1893        d = c.fma(Decimal(2), Decimal(3), Decimal(4))
1894        self.assertEqual(c.fma(2, 3, 4), d)
1895        self.assertEqual(c.fma(Decimal(2), 3, 4), d)
1896        self.assertEqual(c.fma(2, Decimal(3), 4), d)
1897        self.assertEqual(c.fma(2, 3, Decimal(4)), d)
1898        self.assertEqual(c.fma(Decimal(2), Decimal(3), 4), d)
1899        self.assertRaises(TypeError, c.fma, '2', 3, 4)
1900        self.assertRaises(TypeError, c.fma, 2, '3', 4)
1901        self.assertRaises(TypeError, c.fma, 2, 3, '4')
1902
1903    def test_is_finite(self):
1904        c = Context()
1905        d = c.is_finite(Decimal(10))
1906        self.assertEqual(c.is_finite(10), d)
1907        self.assertRaises(TypeError, c.is_finite, '10')
1908
1909    def test_is_infinite(self):
1910        c = Context()
1911        d = c.is_infinite(Decimal(10))
1912        self.assertEqual(c.is_infinite(10), d)
1913        self.assertRaises(TypeError, c.is_infinite, '10')
1914
1915    def test_is_nan(self):
1916        c = Context()
1917        d = c.is_nan(Decimal(10))
1918        self.assertEqual(c.is_nan(10), d)
1919        self.assertRaises(TypeError, c.is_nan, '10')
1920
1921    def test_is_normal(self):
1922        c = Context()
1923        d = c.is_normal(Decimal(10))
1924        self.assertEqual(c.is_normal(10), d)
1925        self.assertRaises(TypeError, c.is_normal, '10')
1926
1927    def test_is_qnan(self):
1928        c = Context()
1929        d = c.is_qnan(Decimal(10))
1930        self.assertEqual(c.is_qnan(10), d)
1931        self.assertRaises(TypeError, c.is_qnan, '10')
1932
1933    def test_is_signed(self):
1934        c = Context()
1935        d = c.is_signed(Decimal(10))
1936        self.assertEqual(c.is_signed(10), d)
1937        self.assertRaises(TypeError, c.is_signed, '10')
1938
1939    def test_is_snan(self):
1940        c = Context()
1941        d = c.is_snan(Decimal(10))
1942        self.assertEqual(c.is_snan(10), d)
1943        self.assertRaises(TypeError, c.is_snan, '10')
1944
1945    def test_is_subnormal(self):
1946        c = Context()
1947        d = c.is_subnormal(Decimal(10))
1948        self.assertEqual(c.is_subnormal(10), d)
1949        self.assertRaises(TypeError, c.is_subnormal, '10')
1950
1951    def test_is_zero(self):
1952        c = Context()
1953        d = c.is_zero(Decimal(10))
1954        self.assertEqual(c.is_zero(10), d)
1955        self.assertRaises(TypeError, c.is_zero, '10')
1956
1957    def test_ln(self):
1958        c = Context()
1959        d = c.ln(Decimal(10))
1960        self.assertEqual(c.ln(10), d)
1961        self.assertRaises(TypeError, c.ln, '10')
1962
1963    def test_log10(self):
1964        c = Context()
1965        d = c.log10(Decimal(10))
1966        self.assertEqual(c.log10(10), d)
1967        self.assertRaises(TypeError, c.log10, '10')
1968
1969    def test_logb(self):
1970        c = Context()
1971        d = c.logb(Decimal(10))
1972        self.assertEqual(c.logb(10), d)
1973        self.assertRaises(TypeError, c.logb, '10')
1974
1975    def test_logical_and(self):
1976        c = Context()
1977        d = c.logical_and(Decimal(1), Decimal(1))
1978        self.assertEqual(c.logical_and(1, 1), d)
1979        self.assertEqual(c.logical_and(Decimal(1), 1), d)
1980        self.assertEqual(c.logical_and(1, Decimal(1)), d)
1981        self.assertRaises(TypeError, c.logical_and, '1', 1)
1982        self.assertRaises(TypeError, c.logical_and, 1, '1')
1983
1984    def test_logical_invert(self):
1985        c = Context()
1986        d = c.logical_invert(Decimal(1000))
1987        self.assertEqual(c.logical_invert(1000), d)
1988        self.assertRaises(TypeError, c.logical_invert, '1000')
1989
1990    def test_logical_or(self):
1991        c = Context()
1992        d = c.logical_or(Decimal(1), Decimal(1))
1993        self.assertEqual(c.logical_or(1, 1), d)
1994        self.assertEqual(c.logical_or(Decimal(1), 1), d)
1995        self.assertEqual(c.logical_or(1, Decimal(1)), d)
1996        self.assertRaises(TypeError, c.logical_or, '1', 1)
1997        self.assertRaises(TypeError, c.logical_or, 1, '1')
1998
1999    def test_logical_xor(self):
2000        c = Context()
2001        d = c.logical_xor(Decimal(1), Decimal(1))
2002        self.assertEqual(c.logical_xor(1, 1), d)
2003        self.assertEqual(c.logical_xor(Decimal(1), 1), d)
2004        self.assertEqual(c.logical_xor(1, Decimal(1)), d)
2005        self.assertRaises(TypeError, c.logical_xor, '1', 1)
2006        self.assertRaises(TypeError, c.logical_xor, 1, '1')
2007
2008    def test_max(self):
2009        c = Context()
2010        d = c.max(Decimal(1), Decimal(2))
2011        self.assertEqual(c.max(1, 2), d)
2012        self.assertEqual(c.max(Decimal(1), 2), d)
2013        self.assertEqual(c.max(1, Decimal(2)), d)
2014        self.assertRaises(TypeError, c.max, '1', 2)
2015        self.assertRaises(TypeError, c.max, 1, '2')
2016
2017    def test_max_mag(self):
2018        c = Context()
2019        d = c.max_mag(Decimal(1), Decimal(2))
2020        self.assertEqual(c.max_mag(1, 2), d)
2021        self.assertEqual(c.max_mag(Decimal(1), 2), d)
2022        self.assertEqual(c.max_mag(1, Decimal(2)), d)
2023        self.assertRaises(TypeError, c.max_mag, '1', 2)
2024        self.assertRaises(TypeError, c.max_mag, 1, '2')
2025
2026    def test_min(self):
2027        c = Context()
2028        d = c.min(Decimal(1), Decimal(2))
2029        self.assertEqual(c.min(1, 2), d)
2030        self.assertEqual(c.min(Decimal(1), 2), d)
2031        self.assertEqual(c.min(1, Decimal(2)), d)
2032        self.assertRaises(TypeError, c.min, '1', 2)
2033        self.assertRaises(TypeError, c.min, 1, '2')
2034
2035    def test_min_mag(self):
2036        c = Context()
2037        d = c.min_mag(Decimal(1), Decimal(2))
2038        self.assertEqual(c.min_mag(1, 2), d)
2039        self.assertEqual(c.min_mag(Decimal(1), 2), d)
2040        self.assertEqual(c.min_mag(1, Decimal(2)), d)
2041        self.assertRaises(TypeError, c.min_mag, '1', 2)
2042        self.assertRaises(TypeError, c.min_mag, 1, '2')
2043
2044    def test_minus(self):
2045        c = Context()
2046        d = c.minus(Decimal(10))
2047        self.assertEqual(c.minus(10), d)
2048        self.assertRaises(TypeError, c.minus, '10')
2049
2050    def test_multiply(self):
2051        c = Context()
2052        d = c.multiply(Decimal(1), Decimal(2))
2053        self.assertEqual(c.multiply(1, 2), d)
2054        self.assertEqual(c.multiply(Decimal(1), 2), d)
2055        self.assertEqual(c.multiply(1, Decimal(2)), d)
2056        self.assertRaises(TypeError, c.multiply, '1', 2)
2057        self.assertRaises(TypeError, c.multiply, 1, '2')
2058
2059    def test_next_minus(self):
2060        c = Context()
2061        d = c.next_minus(Decimal(10))
2062        self.assertEqual(c.next_minus(10), d)
2063        self.assertRaises(TypeError, c.next_minus, '10')
2064
2065    def test_next_plus(self):
2066        c = Context()
2067        d = c.next_plus(Decimal(10))
2068        self.assertEqual(c.next_plus(10), d)
2069        self.assertRaises(TypeError, c.next_plus, '10')
2070
2071    def test_next_toward(self):
2072        c = Context()
2073        d = c.next_toward(Decimal(1), Decimal(2))
2074        self.assertEqual(c.next_toward(1, 2), d)
2075        self.assertEqual(c.next_toward(Decimal(1), 2), d)
2076        self.assertEqual(c.next_toward(1, Decimal(2)), d)
2077        self.assertRaises(TypeError, c.next_toward, '1', 2)
2078        self.assertRaises(TypeError, c.next_toward, 1, '2')
2079
2080    def test_normalize(self):
2081        c = Context()
2082        d = c.normalize(Decimal(10))
2083        self.assertEqual(c.normalize(10), d)
2084        self.assertRaises(TypeError, c.normalize, '10')
2085
2086    def test_number_class(self):
2087        c = Context()
2088        self.assertEqual(c.number_class(123), c.number_class(Decimal(123)))
2089        self.assertEqual(c.number_class(0), c.number_class(Decimal(0)))
2090        self.assertEqual(c.number_class(-45), c.number_class(Decimal(-45)))
2091
2092    def test_power(self):
2093        c = Context()
2094        d = c.power(Decimal(1), Decimal(4), Decimal(2))
2095        self.assertEqual(c.power(1, 4, 2), d)
2096        self.assertEqual(c.power(Decimal(1), 4, 2), d)
2097        self.assertEqual(c.power(1, Decimal(4), 2), d)
2098        self.assertEqual(c.power(1, 4, Decimal(2)), d)
2099        self.assertEqual(c.power(Decimal(1), Decimal(4), 2), d)
2100        self.assertRaises(TypeError, c.power, '1', 4, 2)
2101        self.assertRaises(TypeError, c.power, 1, '4', 2)
2102        self.assertRaises(TypeError, c.power, 1, 4, '2')
2103
2104    def test_plus(self):
2105        c = Context()
2106        d = c.plus(Decimal(10))
2107        self.assertEqual(c.plus(10), d)
2108        self.assertRaises(TypeError, c.plus, '10')
2109
2110    def test_quantize(self):
2111        c = Context()
2112        d = c.quantize(Decimal(1), Decimal(2))
2113        self.assertEqual(c.quantize(1, 2), d)
2114        self.assertEqual(c.quantize(Decimal(1), 2), d)
2115        self.assertEqual(c.quantize(1, Decimal(2)), d)
2116        self.assertRaises(TypeError, c.quantize, '1', 2)
2117        self.assertRaises(TypeError, c.quantize, 1, '2')
2118
2119    def test_remainder(self):
2120        c = Context()
2121        d = c.remainder(Decimal(1), Decimal(2))
2122        self.assertEqual(c.remainder(1, 2), d)
2123        self.assertEqual(c.remainder(Decimal(1), 2), d)
2124        self.assertEqual(c.remainder(1, Decimal(2)), d)
2125        self.assertRaises(TypeError, c.remainder, '1', 2)
2126        self.assertRaises(TypeError, c.remainder, 1, '2')
2127
2128    def test_remainder_near(self):
2129        c = Context()
2130        d = c.remainder_near(Decimal(1), Decimal(2))
2131        self.assertEqual(c.remainder_near(1, 2), d)
2132        self.assertEqual(c.remainder_near(Decimal(1), 2), d)
2133        self.assertEqual(c.remainder_near(1, Decimal(2)), d)
2134        self.assertRaises(TypeError, c.remainder_near, '1', 2)
2135        self.assertRaises(TypeError, c.remainder_near, 1, '2')
2136
2137    def test_rotate(self):
2138        c = Context()
2139        d = c.rotate(Decimal(1), Decimal(2))
2140        self.assertEqual(c.rotate(1, 2), d)
2141        self.assertEqual(c.rotate(Decimal(1), 2), d)
2142        self.assertEqual(c.rotate(1, Decimal(2)), d)
2143        self.assertRaises(TypeError, c.rotate, '1', 2)
2144        self.assertRaises(TypeError, c.rotate, 1, '2')
2145
2146    def test_sqrt(self):
2147        c = Context()
2148        d = c.sqrt(Decimal(10))
2149        self.assertEqual(c.sqrt(10), d)
2150        self.assertRaises(TypeError, c.sqrt, '10')
2151
2152    def test_same_quantum(self):
2153        c = Context()
2154        d = c.same_quantum(Decimal(1), Decimal(2))
2155        self.assertEqual(c.same_quantum(1, 2), d)
2156        self.assertEqual(c.same_quantum(Decimal(1), 2), d)
2157        self.assertEqual(c.same_quantum(1, Decimal(2)), d)
2158        self.assertRaises(TypeError, c.same_quantum, '1', 2)
2159        self.assertRaises(TypeError, c.same_quantum, 1, '2')
2160
2161    def test_scaleb(self):
2162        c = Context()
2163        d = c.scaleb(Decimal(1), Decimal(2))
2164        self.assertEqual(c.scaleb(1, 2), d)
2165        self.assertEqual(c.scaleb(Decimal(1), 2), d)
2166        self.assertEqual(c.scaleb(1, Decimal(2)), d)
2167        self.assertRaises(TypeError, c.scaleb, '1', 2)
2168        self.assertRaises(TypeError, c.scaleb, 1, '2')
2169
2170    def test_shift(self):
2171        c = Context()
2172        d = c.shift(Decimal(1), Decimal(2))
2173        self.assertEqual(c.shift(1, 2), d)
2174        self.assertEqual(c.shift(Decimal(1), 2), d)
2175        self.assertEqual(c.shift(1, Decimal(2)), d)
2176        self.assertRaises(TypeError, c.shift, '1', 2)
2177        self.assertRaises(TypeError, c.shift, 1, '2')
2178
2179    def test_subtract(self):
2180        c = Context()
2181        d = c.subtract(Decimal(1), Decimal(2))
2182        self.assertEqual(c.subtract(1, 2), d)
2183        self.assertEqual(c.subtract(Decimal(1), 2), d)
2184        self.assertEqual(c.subtract(1, Decimal(2)), d)
2185        self.assertRaises(TypeError, c.subtract, '1', 2)
2186        self.assertRaises(TypeError, c.subtract, 1, '2')
2187
2188    def test_to_eng_string(self):
2189        c = Context()
2190        d = c.to_eng_string(Decimal(10))
2191        self.assertEqual(c.to_eng_string(10), d)
2192        self.assertRaises(TypeError, c.to_eng_string, '10')
2193
2194    def test_to_sci_string(self):
2195        c = Context()
2196        d = c.to_sci_string(Decimal(10))
2197        self.assertEqual(c.to_sci_string(10), d)
2198        self.assertRaises(TypeError, c.to_sci_string, '10')
2199
2200    def test_to_integral_exact(self):
2201        c = Context()
2202        d = c.to_integral_exact(Decimal(10))
2203        self.assertEqual(c.to_integral_exact(10), d)
2204        self.assertRaises(TypeError, c.to_integral_exact, '10')
2205
2206    def test_to_integral_value(self):
2207        c = Context()
2208        d = c.to_integral_value(Decimal(10))
2209        self.assertEqual(c.to_integral_value(10), d)
2210        self.assertRaises(TypeError, c.to_integral_value, '10')
2211
2212class WithStatementTest(unittest.TestCase):
2213    # Can't do these as docstrings until Python 2.6
2214    # as doctest can't handle __future__ statements
2215
2216    def test_localcontext(self):
2217        # Use a copy of the current context in the block
2218        orig_ctx = getcontext()
2219        with localcontext() as enter_ctx:
2220            set_ctx = getcontext()
2221        final_ctx = getcontext()
2222        self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
2223        self.assertIsNot(orig_ctx, set_ctx, 'did not copy the context')
2224        self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
2225
2226    def test_localcontextarg(self):
2227        # Use a copy of the supplied context in the block
2228        orig_ctx = getcontext()
2229        new_ctx = Context(prec=42)
2230        with localcontext(new_ctx) as enter_ctx:
2231            set_ctx = getcontext()
2232        final_ctx = getcontext()
2233        self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
2234        self.assertEqual(set_ctx.prec, new_ctx.prec, 'did not set correct context')
2235        self.assertIsNot(new_ctx, set_ctx, 'did not copy the context')
2236        self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
2237
2238class ContextFlags(unittest.TestCase):
2239    def test_flags_irrelevant(self):
2240        # check that the result (numeric result + flags raised) of an
2241        # arithmetic operation doesn't depend on the current flags
2242
2243        context = Context(prec=9, Emin = -999999999, Emax = 999999999,
2244                    rounding=ROUND_HALF_EVEN, traps=[], flags=[])
2245
2246        # operations that raise various flags, in the form (function, arglist)
2247        operations = [
2248            (context._apply, [Decimal("100E-1000000009")]),
2249            (context.sqrt, [Decimal(2)]),
2250            (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]),
2251            (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]),
2252            (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]),
2253            ]
2254
2255        # try various flags individually, then a whole lot at once
2256        flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal],
2257                    [Inexact, Rounded, Underflow, Clamped, Subnormal]]
2258
2259        for fn, args in operations:
2260            # find answer and flags raised using a clean context
2261            context.clear_flags()
2262            ans = fn(*args)
2263            flags = [k for k, v in context.flags.items() if v]
2264
2265            for extra_flags in flagsets:
2266                # set flags, before calling operation
2267                context.clear_flags()
2268                for flag in extra_flags:
2269                    context._raise_error(flag)
2270                new_ans = fn(*args)
2271
2272                # flags that we expect to be set after the operation
2273                expected_flags = list(flags)
2274                for flag in extra_flags:
2275                    if flag not in expected_flags:
2276                        expected_flags.append(flag)
2277
2278                # flags we actually got
2279                new_flags = [k for k,v in context.flags.items() if v]
2280
2281                self.assertEqual(ans, new_ans,
2282                                 "operation produces different answers depending on flags set: " +
2283                                 "expected %s, got %s." % (ans, new_ans))
2284                self.assertItemsEqual(new_flags, expected_flags,
2285                                  "operation raises different flags depending on flags set: " +
2286                                  "expected %s, got %s" % (expected_flags, new_flags))
2287
2288def test_main(arith=False, verbose=None, todo_tests=None, debug=None):
2289    """ Execute the tests.
2290
2291    Runs all arithmetic tests if arith is True or if the "decimal" resource
2292    is enabled in regrtest.py
2293    """
2294
2295    init()
2296    global TEST_ALL, DEBUG
2297    TEST_ALL = arith or is_resource_enabled('decimal')
2298    DEBUG = debug
2299
2300    if todo_tests is None:
2301        test_classes = [
2302            DecimalExplicitConstructionTest,
2303            DecimalImplicitConstructionTest,
2304            DecimalArithmeticOperatorsTest,
2305            DecimalFormatTest,
2306            DecimalUseOfContextTest,
2307            DecimalUsabilityTest,
2308            DecimalPythonAPItests,
2309            ContextAPItests,
2310            DecimalTest,
2311            WithStatementTest,
2312            ContextFlags
2313        ]
2314    else:
2315        test_classes = [DecimalTest]
2316
2317    # Dynamically build custom test definition for each file in the test
2318    # directory and add the definitions to the DecimalTest class.  This
2319    # procedure insures that new files do not get skipped.
2320    for filename in os.listdir(directory):
2321        if '.decTest' not in filename or filename.startswith("."):
2322            continue
2323        head, tail = filename.split('.')
2324        if todo_tests is not None and head not in todo_tests:
2325            continue
2326        tester = lambda self, f=filename: self.eval_file(directory + f)
2327        setattr(DecimalTest, 'test_' + head, tester)
2328        del filename, head, tail, tester
2329
2330
2331    try:
2332        run_unittest(*test_classes)
2333        if todo_tests is None:
2334            import decimal as DecimalModule
2335            run_doctest(DecimalModule, verbose)
2336    finally:
2337        setcontext(ORIGINAL_CONTEXT)
2338
2339if __name__ == '__main__':
2340    import optparse
2341    p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]")
2342    p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test')
2343    p.add_option('--skip',  '-s', action='store_true', help='skip over 90% of the arithmetic tests')
2344    (opt, args) = p.parse_args()
2345
2346    if opt.skip:
2347        test_main(arith=False, verbose=True)
2348    elif args:
2349        test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug)
2350    else:
2351        test_main(arith=True, verbose=True)
2352