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_eval_round_trip(self):
1452
1453        #with zero
1454        d = Decimal( (0, (0,), 0) )
1455        self.assertEqual(d, eval(repr(d)))
1456
1457        #int
1458        d = Decimal( (1, (4, 5), 0) )
1459        self.assertEqual(d, eval(repr(d)))
1460
1461        #float
1462        d = Decimal( (0, (4, 5, 3, 4), -2) )
1463        self.assertEqual(d, eval(repr(d)))
1464
1465        #weird
1466        d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1467        self.assertEqual(d, eval(repr(d)))
1468
1469    def test_as_tuple(self):
1470
1471        #with zero
1472        d = Decimal(0)
1473        self.assertEqual(d.as_tuple(), (0, (0,), 0) )
1474
1475        #int
1476        d = Decimal(-45)
1477        self.assertEqual(d.as_tuple(), (1, (4, 5), 0) )
1478
1479        #complicated string
1480        d = Decimal("-4.34913534E-17")
1481        self.assertEqual(d.as_tuple(), (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1482
1483        #inf
1484        d = Decimal("Infinity")
1485        self.assertEqual(d.as_tuple(), (0, (0,), 'F') )
1486
1487        #leading zeros in coefficient should be stripped
1488        d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), -2) )
1489        self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), -2) )
1490        d = Decimal( (1, (0, 0, 0), 37) )
1491        self.assertEqual(d.as_tuple(), (1, (0,), 37))
1492        d = Decimal( (1, (), 37) )
1493        self.assertEqual(d.as_tuple(), (1, (0,), 37))
1494
1495        #leading zeros in NaN diagnostic info should be stripped
1496        d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), 'n') )
1497        self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), 'n') )
1498        d = Decimal( (1, (0, 0, 0), 'N') )
1499        self.assertEqual(d.as_tuple(), (1, (), 'N') )
1500        d = Decimal( (1, (), 'n') )
1501        self.assertEqual(d.as_tuple(), (1, (), 'n') )
1502
1503        #coefficient in infinity should be ignored
1504        d = Decimal( (0, (4, 5, 3, 4), 'F') )
1505        self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
1506        d = Decimal( (1, (0, 2, 7, 1), 'F') )
1507        self.assertEqual(d.as_tuple(), (1, (0,), 'F'))
1508
1509    def test_immutability_operations(self):
1510        # Do operations and check that it didn't change change internal objects.
1511
1512        d1 = Decimal('-25e55')
1513        b1 = Decimal('-25e55')
1514        d2 = Decimal('33e+33')
1515        b2 = Decimal('33e+33')
1516
1517        def checkSameDec(operation, useOther=False):
1518            if useOther:
1519                eval("d1." + operation + "(d2)")
1520                self.assertEqual(d1._sign, b1._sign)
1521                self.assertEqual(d1._int, b1._int)
1522                self.assertEqual(d1._exp, b1._exp)
1523                self.assertEqual(d2._sign, b2._sign)
1524                self.assertEqual(d2._int, b2._int)
1525                self.assertEqual(d2._exp, b2._exp)
1526            else:
1527                eval("d1." + operation + "()")
1528                self.assertEqual(d1._sign, b1._sign)
1529                self.assertEqual(d1._int, b1._int)
1530                self.assertEqual(d1._exp, b1._exp)
1531            return
1532
1533        Decimal(d1)
1534        self.assertEqual(d1._sign, b1._sign)
1535        self.assertEqual(d1._int, b1._int)
1536        self.assertEqual(d1._exp, b1._exp)
1537
1538        checkSameDec("__abs__")
1539        checkSameDec("__add__", True)
1540        checkSameDec("__div__", True)
1541        checkSameDec("__divmod__", True)
1542        checkSameDec("__eq__", True)
1543        checkSameDec("__ne__", True)
1544        checkSameDec("__le__", True)
1545        checkSameDec("__lt__", True)
1546        checkSameDec("__ge__", True)
1547        checkSameDec("__gt__", True)
1548        checkSameDec("__float__")
1549        checkSameDec("__floordiv__", True)
1550        checkSameDec("__hash__")
1551        checkSameDec("__int__")
1552        checkSameDec("__trunc__")
1553        checkSameDec("__long__")
1554        checkSameDec("__mod__", True)
1555        checkSameDec("__mul__", True)
1556        checkSameDec("__neg__")
1557        checkSameDec("__nonzero__")
1558        checkSameDec("__pos__")
1559        checkSameDec("__pow__", True)
1560        checkSameDec("__radd__", True)
1561        checkSameDec("__rdiv__", True)
1562        checkSameDec("__rdivmod__", True)
1563        checkSameDec("__repr__")
1564        checkSameDec("__rfloordiv__", True)
1565        checkSameDec("__rmod__", True)
1566        checkSameDec("__rmul__", True)
1567        checkSameDec("__rpow__", True)
1568        checkSameDec("__rsub__", True)
1569        checkSameDec("__str__")
1570        checkSameDec("__sub__", True)
1571        checkSameDec("__truediv__", True)
1572        checkSameDec("adjusted")
1573        checkSameDec("as_tuple")
1574        checkSameDec("compare", True)
1575        checkSameDec("max", True)
1576        checkSameDec("min", True)
1577        checkSameDec("normalize")
1578        checkSameDec("quantize", True)
1579        checkSameDec("remainder_near", True)
1580        checkSameDec("same_quantum", True)
1581        checkSameDec("sqrt")
1582        checkSameDec("to_eng_string")
1583        checkSameDec("to_integral")
1584
1585    def test_subclassing(self):
1586        # Different behaviours when subclassing Decimal
1587
1588        class MyDecimal(Decimal):
1589            pass
1590
1591        d1 = MyDecimal(1)
1592        d2 = MyDecimal(2)
1593        d = d1 + d2
1594        self.assertIs(type(d), Decimal)
1595
1596        d = d1.max(d2)
1597        self.assertIs(type(d), Decimal)
1598
1599    def test_implicit_context(self):
1600        # Check results when context given implicitly.  (Issue 2478)
1601        c = getcontext()
1602        self.assertEqual(str(Decimal(0).sqrt()),
1603                         str(c.sqrt(Decimal(0))))
1604
1605    def test_conversions_from_int(self):
1606        # Check that methods taking a second Decimal argument will
1607        # always accept an integer in place of a Decimal.
1608        self.assertEqual(Decimal(4).compare(3),
1609                         Decimal(4).compare(Decimal(3)))
1610        self.assertEqual(Decimal(4).compare_signal(3),
1611                         Decimal(4).compare_signal(Decimal(3)))
1612        self.assertEqual(Decimal(4).compare_total(3),
1613                         Decimal(4).compare_total(Decimal(3)))
1614        self.assertEqual(Decimal(4).compare_total_mag(3),
1615                         Decimal(4).compare_total_mag(Decimal(3)))
1616        self.assertEqual(Decimal(10101).logical_and(1001),
1617                         Decimal(10101).logical_and(Decimal(1001)))
1618        self.assertEqual(Decimal(10101).logical_or(1001),
1619                         Decimal(10101).logical_or(Decimal(1001)))
1620        self.assertEqual(Decimal(10101).logical_xor(1001),
1621                         Decimal(10101).logical_xor(Decimal(1001)))
1622        self.assertEqual(Decimal(567).max(123),
1623                         Decimal(567).max(Decimal(123)))
1624        self.assertEqual(Decimal(567).max_mag(123),
1625                         Decimal(567).max_mag(Decimal(123)))
1626        self.assertEqual(Decimal(567).min(123),
1627                         Decimal(567).min(Decimal(123)))
1628        self.assertEqual(Decimal(567).min_mag(123),
1629                         Decimal(567).min_mag(Decimal(123)))
1630        self.assertEqual(Decimal(567).next_toward(123),
1631                         Decimal(567).next_toward(Decimal(123)))
1632        self.assertEqual(Decimal(1234).quantize(100),
1633                         Decimal(1234).quantize(Decimal(100)))
1634        self.assertEqual(Decimal(768).remainder_near(1234),
1635                         Decimal(768).remainder_near(Decimal(1234)))
1636        self.assertEqual(Decimal(123).rotate(1),
1637                         Decimal(123).rotate(Decimal(1)))
1638        self.assertEqual(Decimal(1234).same_quantum(1000),
1639                         Decimal(1234).same_quantum(Decimal(1000)))
1640        self.assertEqual(Decimal('9.123').scaleb(-100),
1641                         Decimal('9.123').scaleb(Decimal(-100)))
1642        self.assertEqual(Decimal(456).shift(-1),
1643                         Decimal(456).shift(Decimal(-1)))
1644
1645        self.assertEqual(Decimal(-12).fma(Decimal(45), 67),
1646                         Decimal(-12).fma(Decimal(45), Decimal(67)))
1647        self.assertEqual(Decimal(-12).fma(45, 67),
1648                         Decimal(-12).fma(Decimal(45), Decimal(67)))
1649        self.assertEqual(Decimal(-12).fma(45, Decimal(67)),
1650                         Decimal(-12).fma(Decimal(45), Decimal(67)))
1651
1652
1653class DecimalPythonAPItests(unittest.TestCase):
1654
1655    def test_abc(self):
1656        self.assertTrue(issubclass(Decimal, numbers.Number))
1657        self.assertFalse(issubclass(Decimal, numbers.Real))
1658        self.assertIsInstance(Decimal(0), numbers.Number)
1659        self.assertNotIsInstance(Decimal(0), numbers.Real)
1660
1661    def test_pickle(self):
1662        d = Decimal('-3.141590000')
1663        p = pickle.dumps(d)
1664        e = pickle.loads(p)
1665        self.assertEqual(d, e)
1666
1667    def test_int(self):
1668        for x in range(-250, 250):
1669            s = '%0.2f' % (x / 100.0)
1670            # should work the same as for floats
1671            self.assertEqual(int(Decimal(s)), int(float(s)))
1672            # should work the same as to_integral in the ROUND_DOWN mode
1673            d = Decimal(s)
1674            r = d.to_integral(ROUND_DOWN)
1675            self.assertEqual(Decimal(int(d)), r)
1676
1677        self.assertRaises(ValueError, int, Decimal('-nan'))
1678        self.assertRaises(ValueError, int, Decimal('snan'))
1679        self.assertRaises(OverflowError, int, Decimal('inf'))
1680        self.assertRaises(OverflowError, int, Decimal('-inf'))
1681
1682        self.assertRaises(ValueError, long, Decimal('-nan'))
1683        self.assertRaises(ValueError, long, Decimal('snan'))
1684        self.assertRaises(OverflowError, long, Decimal('inf'))
1685        self.assertRaises(OverflowError, long, Decimal('-inf'))
1686
1687    def test_trunc(self):
1688        for x in range(-250, 250):
1689            s = '%0.2f' % (x / 100.0)
1690            # should work the same as for floats
1691            self.assertEqual(int(Decimal(s)), int(float(s)))
1692            # should work the same as to_integral in the ROUND_DOWN mode
1693            d = Decimal(s)
1694            r = d.to_integral(ROUND_DOWN)
1695            self.assertEqual(Decimal(math.trunc(d)), r)
1696
1697    def test_from_float(self):
1698
1699        class  MyDecimal(Decimal):
1700            pass
1701
1702        r = MyDecimal.from_float(0.1)
1703        self.assertEqual(type(r), MyDecimal)
1704        self.assertEqual(str(r),
1705                '0.1000000000000000055511151231257827021181583404541015625')
1706        bigint = 12345678901234567890123456789
1707        self.assertEqual(MyDecimal.from_float(bigint), MyDecimal(bigint))
1708        self.assertTrue(MyDecimal.from_float(float('nan')).is_qnan())
1709        self.assertTrue(MyDecimal.from_float(float('inf')).is_infinite())
1710        self.assertTrue(MyDecimal.from_float(float('-inf')).is_infinite())
1711        self.assertEqual(str(MyDecimal.from_float(float('nan'))),
1712                         str(Decimal('NaN')))
1713        self.assertEqual(str(MyDecimal.from_float(float('inf'))),
1714                         str(Decimal('Infinity')))
1715        self.assertEqual(str(MyDecimal.from_float(float('-inf'))),
1716                         str(Decimal('-Infinity')))
1717        self.assertRaises(TypeError, MyDecimal.from_float, 'abc')
1718        for i in range(200):
1719            x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
1720            self.assertEqual(x, float(MyDecimal.from_float(x))) # roundtrip
1721
1722    def test_create_decimal_from_float(self):
1723        context = Context(prec=5, rounding=ROUND_DOWN)
1724        self.assertEqual(
1725            context.create_decimal_from_float(math.pi),
1726            Decimal('3.1415')
1727        )
1728        context = Context(prec=5, rounding=ROUND_UP)
1729        self.assertEqual(
1730            context.create_decimal_from_float(math.pi),
1731            Decimal('3.1416')
1732        )
1733        context = Context(prec=5, traps=[Inexact])
1734        self.assertRaises(
1735            Inexact,
1736            context.create_decimal_from_float,
1737            math.pi
1738        )
1739        self.assertEqual(repr(context.create_decimal_from_float(-0.0)),
1740                         "Decimal('-0')")
1741        self.assertEqual(repr(context.create_decimal_from_float(1.0)),
1742                         "Decimal('1')")
1743        self.assertEqual(repr(context.create_decimal_from_float(10)),
1744                         "Decimal('10')")
1745
1746class ContextAPItests(unittest.TestCase):
1747
1748    def test_pickle(self):
1749        c = Context()
1750        e = pickle.loads(pickle.dumps(c))
1751        for k in vars(c):
1752            v1 = vars(c)[k]
1753            v2 = vars(e)[k]
1754            self.assertEqual(v1, v2)
1755
1756    def test_equality_with_other_types(self):
1757        self.assertIn(Decimal(10), ['a', 1.0, Decimal(10), (1,2), {}])
1758        self.assertNotIn(Decimal(10), ['a', 1.0, (1,2), {}])
1759
1760    def test_copy(self):
1761        # All copies should be deep
1762        c = Context()
1763        d = c.copy()
1764        self.assertNotEqual(id(c), id(d))
1765        self.assertNotEqual(id(c.flags), id(d.flags))
1766        self.assertNotEqual(id(c.traps), id(d.traps))
1767
1768    def test_abs(self):
1769        c = Context()
1770        d = c.abs(Decimal(-1))
1771        self.assertEqual(c.abs(-1), d)
1772        self.assertRaises(TypeError, c.abs, '-1')
1773
1774    def test_add(self):
1775        c = Context()
1776        d = c.add(Decimal(1), Decimal(1))
1777        self.assertEqual(c.add(1, 1), d)
1778        self.assertEqual(c.add(Decimal(1), 1), d)
1779        self.assertEqual(c.add(1, Decimal(1)), d)
1780        self.assertRaises(TypeError, c.add, '1', 1)
1781        self.assertRaises(TypeError, c.add, 1, '1')
1782
1783    def test_compare(self):
1784        c = Context()
1785        d = c.compare(Decimal(1), Decimal(1))
1786        self.assertEqual(c.compare(1, 1), d)
1787        self.assertEqual(c.compare(Decimal(1), 1), d)
1788        self.assertEqual(c.compare(1, Decimal(1)), d)
1789        self.assertRaises(TypeError, c.compare, '1', 1)
1790        self.assertRaises(TypeError, c.compare, 1, '1')
1791
1792    def test_compare_signal(self):
1793        c = Context()
1794        d = c.compare_signal(Decimal(1), Decimal(1))
1795        self.assertEqual(c.compare_signal(1, 1), d)
1796        self.assertEqual(c.compare_signal(Decimal(1), 1), d)
1797        self.assertEqual(c.compare_signal(1, Decimal(1)), d)
1798        self.assertRaises(TypeError, c.compare_signal, '1', 1)
1799        self.assertRaises(TypeError, c.compare_signal, 1, '1')
1800
1801    def test_compare_total(self):
1802        c = Context()
1803        d = c.compare_total(Decimal(1), Decimal(1))
1804        self.assertEqual(c.compare_total(1, 1), d)
1805        self.assertEqual(c.compare_total(Decimal(1), 1), d)
1806        self.assertEqual(c.compare_total(1, Decimal(1)), d)
1807        self.assertRaises(TypeError, c.compare_total, '1', 1)
1808        self.assertRaises(TypeError, c.compare_total, 1, '1')
1809
1810    def test_compare_total_mag(self):
1811        c = Context()
1812        d = c.compare_total_mag(Decimal(1), Decimal(1))
1813        self.assertEqual(c.compare_total_mag(1, 1), d)
1814        self.assertEqual(c.compare_total_mag(Decimal(1), 1), d)
1815        self.assertEqual(c.compare_total_mag(1, Decimal(1)), d)
1816        self.assertRaises(TypeError, c.compare_total_mag, '1', 1)
1817        self.assertRaises(TypeError, c.compare_total_mag, 1, '1')
1818
1819    def test_copy_abs(self):
1820        c = Context()
1821        d = c.copy_abs(Decimal(-1))
1822        self.assertEqual(c.copy_abs(-1), d)
1823        self.assertRaises(TypeError, c.copy_abs, '-1')
1824
1825    def test_copy_decimal(self):
1826        c = Context()
1827        d = c.copy_decimal(Decimal(-1))
1828        self.assertEqual(c.copy_decimal(-1), d)
1829        self.assertRaises(TypeError, c.copy_decimal, '-1')
1830
1831    def test_copy_negate(self):
1832        c = Context()
1833        d = c.copy_negate(Decimal(-1))
1834        self.assertEqual(c.copy_negate(-1), d)
1835        self.assertRaises(TypeError, c.copy_negate, '-1')
1836
1837    def test_copy_sign(self):
1838        c = Context()
1839        d = c.copy_sign(Decimal(1), Decimal(-2))
1840        self.assertEqual(c.copy_sign(1, -2), d)
1841        self.assertEqual(c.copy_sign(Decimal(1), -2), d)
1842        self.assertEqual(c.copy_sign(1, Decimal(-2)), d)
1843        self.assertRaises(TypeError, c.copy_sign, '1', -2)
1844        self.assertRaises(TypeError, c.copy_sign, 1, '-2')
1845
1846    def test_divide(self):
1847        c = Context()
1848        d = c.divide(Decimal(1), Decimal(2))
1849        self.assertEqual(c.divide(1, 2), d)
1850        self.assertEqual(c.divide(Decimal(1), 2), d)
1851        self.assertEqual(c.divide(1, Decimal(2)), d)
1852        self.assertRaises(TypeError, c.divide, '1', 2)
1853        self.assertRaises(TypeError, c.divide, 1, '2')
1854
1855    def test_divide_int(self):
1856        c = Context()
1857        d = c.divide_int(Decimal(1), Decimal(2))
1858        self.assertEqual(c.divide_int(1, 2), d)
1859        self.assertEqual(c.divide_int(Decimal(1), 2), d)
1860        self.assertEqual(c.divide_int(1, Decimal(2)), d)
1861        self.assertRaises(TypeError, c.divide_int, '1', 2)
1862        self.assertRaises(TypeError, c.divide_int, 1, '2')
1863
1864    def test_divmod(self):
1865        c = Context()
1866        d = c.divmod(Decimal(1), Decimal(2))
1867        self.assertEqual(c.divmod(1, 2), d)
1868        self.assertEqual(c.divmod(Decimal(1), 2), d)
1869        self.assertEqual(c.divmod(1, Decimal(2)), d)
1870        self.assertRaises(TypeError, c.divmod, '1', 2)
1871        self.assertRaises(TypeError, c.divmod, 1, '2')
1872
1873    def test_exp(self):
1874        c = Context()
1875        d = c.exp(Decimal(10))
1876        self.assertEqual(c.exp(10), d)
1877        self.assertRaises(TypeError, c.exp, '10')
1878
1879    def test_fma(self):
1880        c = Context()
1881        d = c.fma(Decimal(2), Decimal(3), Decimal(4))
1882        self.assertEqual(c.fma(2, 3, 4), d)
1883        self.assertEqual(c.fma(Decimal(2), 3, 4), d)
1884        self.assertEqual(c.fma(2, Decimal(3), 4), d)
1885        self.assertEqual(c.fma(2, 3, Decimal(4)), d)
1886        self.assertEqual(c.fma(Decimal(2), Decimal(3), 4), d)
1887        self.assertRaises(TypeError, c.fma, '2', 3, 4)
1888        self.assertRaises(TypeError, c.fma, 2, '3', 4)
1889        self.assertRaises(TypeError, c.fma, 2, 3, '4')
1890
1891    def test_is_finite(self):
1892        c = Context()
1893        d = c.is_finite(Decimal(10))
1894        self.assertEqual(c.is_finite(10), d)
1895        self.assertRaises(TypeError, c.is_finite, '10')
1896
1897    def test_is_infinite(self):
1898        c = Context()
1899        d = c.is_infinite(Decimal(10))
1900        self.assertEqual(c.is_infinite(10), d)
1901        self.assertRaises(TypeError, c.is_infinite, '10')
1902
1903    def test_is_nan(self):
1904        c = Context()
1905        d = c.is_nan(Decimal(10))
1906        self.assertEqual(c.is_nan(10), d)
1907        self.assertRaises(TypeError, c.is_nan, '10')
1908
1909    def test_is_normal(self):
1910        c = Context()
1911        d = c.is_normal(Decimal(10))
1912        self.assertEqual(c.is_normal(10), d)
1913        self.assertRaises(TypeError, c.is_normal, '10')
1914
1915    def test_is_qnan(self):
1916        c = Context()
1917        d = c.is_qnan(Decimal(10))
1918        self.assertEqual(c.is_qnan(10), d)
1919        self.assertRaises(TypeError, c.is_qnan, '10')
1920
1921    def test_is_signed(self):
1922        c = Context()
1923        d = c.is_signed(Decimal(10))
1924        self.assertEqual(c.is_signed(10), d)
1925        self.assertRaises(TypeError, c.is_signed, '10')
1926
1927    def test_is_snan(self):
1928        c = Context()
1929        d = c.is_snan(Decimal(10))
1930        self.assertEqual(c.is_snan(10), d)
1931        self.assertRaises(TypeError, c.is_snan, '10')
1932
1933    def test_is_subnormal(self):
1934        c = Context()
1935        d = c.is_subnormal(Decimal(10))
1936        self.assertEqual(c.is_subnormal(10), d)
1937        self.assertRaises(TypeError, c.is_subnormal, '10')
1938
1939    def test_is_zero(self):
1940        c = Context()
1941        d = c.is_zero(Decimal(10))
1942        self.assertEqual(c.is_zero(10), d)
1943        self.assertRaises(TypeError, c.is_zero, '10')
1944
1945    def test_ln(self):
1946        c = Context()
1947        d = c.ln(Decimal(10))
1948        self.assertEqual(c.ln(10), d)
1949        self.assertRaises(TypeError, c.ln, '10')
1950
1951    def test_log10(self):
1952        c = Context()
1953        d = c.log10(Decimal(10))
1954        self.assertEqual(c.log10(10), d)
1955        self.assertRaises(TypeError, c.log10, '10')
1956
1957    def test_logb(self):
1958        c = Context()
1959        d = c.logb(Decimal(10))
1960        self.assertEqual(c.logb(10), d)
1961        self.assertRaises(TypeError, c.logb, '10')
1962
1963    def test_logical_and(self):
1964        c = Context()
1965        d = c.logical_and(Decimal(1), Decimal(1))
1966        self.assertEqual(c.logical_and(1, 1), d)
1967        self.assertEqual(c.logical_and(Decimal(1), 1), d)
1968        self.assertEqual(c.logical_and(1, Decimal(1)), d)
1969        self.assertRaises(TypeError, c.logical_and, '1', 1)
1970        self.assertRaises(TypeError, c.logical_and, 1, '1')
1971
1972    def test_logical_invert(self):
1973        c = Context()
1974        d = c.logical_invert(Decimal(1000))
1975        self.assertEqual(c.logical_invert(1000), d)
1976        self.assertRaises(TypeError, c.logical_invert, '1000')
1977
1978    def test_logical_or(self):
1979        c = Context()
1980        d = c.logical_or(Decimal(1), Decimal(1))
1981        self.assertEqual(c.logical_or(1, 1), d)
1982        self.assertEqual(c.logical_or(Decimal(1), 1), d)
1983        self.assertEqual(c.logical_or(1, Decimal(1)), d)
1984        self.assertRaises(TypeError, c.logical_or, '1', 1)
1985        self.assertRaises(TypeError, c.logical_or, 1, '1')
1986
1987    def test_logical_xor(self):
1988        c = Context()
1989        d = c.logical_xor(Decimal(1), Decimal(1))
1990        self.assertEqual(c.logical_xor(1, 1), d)
1991        self.assertEqual(c.logical_xor(Decimal(1), 1), d)
1992        self.assertEqual(c.logical_xor(1, Decimal(1)), d)
1993        self.assertRaises(TypeError, c.logical_xor, '1', 1)
1994        self.assertRaises(TypeError, c.logical_xor, 1, '1')
1995
1996    def test_max(self):
1997        c = Context()
1998        d = c.max(Decimal(1), Decimal(2))
1999        self.assertEqual(c.max(1, 2), d)
2000        self.assertEqual(c.max(Decimal(1), 2), d)
2001        self.assertEqual(c.max(1, Decimal(2)), d)
2002        self.assertRaises(TypeError, c.max, '1', 2)
2003        self.assertRaises(TypeError, c.max, 1, '2')
2004
2005    def test_max_mag(self):
2006        c = Context()
2007        d = c.max_mag(Decimal(1), Decimal(2))
2008        self.assertEqual(c.max_mag(1, 2), d)
2009        self.assertEqual(c.max_mag(Decimal(1), 2), d)
2010        self.assertEqual(c.max_mag(1, Decimal(2)), d)
2011        self.assertRaises(TypeError, c.max_mag, '1', 2)
2012        self.assertRaises(TypeError, c.max_mag, 1, '2')
2013
2014    def test_min(self):
2015        c = Context()
2016        d = c.min(Decimal(1), Decimal(2))
2017        self.assertEqual(c.min(1, 2), d)
2018        self.assertEqual(c.min(Decimal(1), 2), d)
2019        self.assertEqual(c.min(1, Decimal(2)), d)
2020        self.assertRaises(TypeError, c.min, '1', 2)
2021        self.assertRaises(TypeError, c.min, 1, '2')
2022
2023    def test_min_mag(self):
2024        c = Context()
2025        d = c.min_mag(Decimal(1), Decimal(2))
2026        self.assertEqual(c.min_mag(1, 2), d)
2027        self.assertEqual(c.min_mag(Decimal(1), 2), d)
2028        self.assertEqual(c.min_mag(1, Decimal(2)), d)
2029        self.assertRaises(TypeError, c.min_mag, '1', 2)
2030        self.assertRaises(TypeError, c.min_mag, 1, '2')
2031
2032    def test_minus(self):
2033        c = Context()
2034        d = c.minus(Decimal(10))
2035        self.assertEqual(c.minus(10), d)
2036        self.assertRaises(TypeError, c.minus, '10')
2037
2038    def test_multiply(self):
2039        c = Context()
2040        d = c.multiply(Decimal(1), Decimal(2))
2041        self.assertEqual(c.multiply(1, 2), d)
2042        self.assertEqual(c.multiply(Decimal(1), 2), d)
2043        self.assertEqual(c.multiply(1, Decimal(2)), d)
2044        self.assertRaises(TypeError, c.multiply, '1', 2)
2045        self.assertRaises(TypeError, c.multiply, 1, '2')
2046
2047    def test_next_minus(self):
2048        c = Context()
2049        d = c.next_minus(Decimal(10))
2050        self.assertEqual(c.next_minus(10), d)
2051        self.assertRaises(TypeError, c.next_minus, '10')
2052
2053    def test_next_plus(self):
2054        c = Context()
2055        d = c.next_plus(Decimal(10))
2056        self.assertEqual(c.next_plus(10), d)
2057        self.assertRaises(TypeError, c.next_plus, '10')
2058
2059    def test_next_toward(self):
2060        c = Context()
2061        d = c.next_toward(Decimal(1), Decimal(2))
2062        self.assertEqual(c.next_toward(1, 2), d)
2063        self.assertEqual(c.next_toward(Decimal(1), 2), d)
2064        self.assertEqual(c.next_toward(1, Decimal(2)), d)
2065        self.assertRaises(TypeError, c.next_toward, '1', 2)
2066        self.assertRaises(TypeError, c.next_toward, 1, '2')
2067
2068    def test_normalize(self):
2069        c = Context()
2070        d = c.normalize(Decimal(10))
2071        self.assertEqual(c.normalize(10), d)
2072        self.assertRaises(TypeError, c.normalize, '10')
2073
2074    def test_number_class(self):
2075        c = Context()
2076        self.assertEqual(c.number_class(123), c.number_class(Decimal(123)))
2077        self.assertEqual(c.number_class(0), c.number_class(Decimal(0)))
2078        self.assertEqual(c.number_class(-45), c.number_class(Decimal(-45)))
2079
2080    def test_power(self):
2081        c = Context()
2082        d = c.power(Decimal(1), Decimal(4), Decimal(2))
2083        self.assertEqual(c.power(1, 4, 2), d)
2084        self.assertEqual(c.power(Decimal(1), 4, 2), d)
2085        self.assertEqual(c.power(1, Decimal(4), 2), d)
2086        self.assertEqual(c.power(1, 4, Decimal(2)), d)
2087        self.assertEqual(c.power(Decimal(1), Decimal(4), 2), d)
2088        self.assertRaises(TypeError, c.power, '1', 4, 2)
2089        self.assertRaises(TypeError, c.power, 1, '4', 2)
2090        self.assertRaises(TypeError, c.power, 1, 4, '2')
2091
2092    def test_plus(self):
2093        c = Context()
2094        d = c.plus(Decimal(10))
2095        self.assertEqual(c.plus(10), d)
2096        self.assertRaises(TypeError, c.plus, '10')
2097
2098    def test_quantize(self):
2099        c = Context()
2100        d = c.quantize(Decimal(1), Decimal(2))
2101        self.assertEqual(c.quantize(1, 2), d)
2102        self.assertEqual(c.quantize(Decimal(1), 2), d)
2103        self.assertEqual(c.quantize(1, Decimal(2)), d)
2104        self.assertRaises(TypeError, c.quantize, '1', 2)
2105        self.assertRaises(TypeError, c.quantize, 1, '2')
2106
2107    def test_remainder(self):
2108        c = Context()
2109        d = c.remainder(Decimal(1), Decimal(2))
2110        self.assertEqual(c.remainder(1, 2), d)
2111        self.assertEqual(c.remainder(Decimal(1), 2), d)
2112        self.assertEqual(c.remainder(1, Decimal(2)), d)
2113        self.assertRaises(TypeError, c.remainder, '1', 2)
2114        self.assertRaises(TypeError, c.remainder, 1, '2')
2115
2116    def test_remainder_near(self):
2117        c = Context()
2118        d = c.remainder_near(Decimal(1), Decimal(2))
2119        self.assertEqual(c.remainder_near(1, 2), d)
2120        self.assertEqual(c.remainder_near(Decimal(1), 2), d)
2121        self.assertEqual(c.remainder_near(1, Decimal(2)), d)
2122        self.assertRaises(TypeError, c.remainder_near, '1', 2)
2123        self.assertRaises(TypeError, c.remainder_near, 1, '2')
2124
2125    def test_rotate(self):
2126        c = Context()
2127        d = c.rotate(Decimal(1), Decimal(2))
2128        self.assertEqual(c.rotate(1, 2), d)
2129        self.assertEqual(c.rotate(Decimal(1), 2), d)
2130        self.assertEqual(c.rotate(1, Decimal(2)), d)
2131        self.assertRaises(TypeError, c.rotate, '1', 2)
2132        self.assertRaises(TypeError, c.rotate, 1, '2')
2133
2134    def test_sqrt(self):
2135        c = Context()
2136        d = c.sqrt(Decimal(10))
2137        self.assertEqual(c.sqrt(10), d)
2138        self.assertRaises(TypeError, c.sqrt, '10')
2139
2140    def test_same_quantum(self):
2141        c = Context()
2142        d = c.same_quantum(Decimal(1), Decimal(2))
2143        self.assertEqual(c.same_quantum(1, 2), d)
2144        self.assertEqual(c.same_quantum(Decimal(1), 2), d)
2145        self.assertEqual(c.same_quantum(1, Decimal(2)), d)
2146        self.assertRaises(TypeError, c.same_quantum, '1', 2)
2147        self.assertRaises(TypeError, c.same_quantum, 1, '2')
2148
2149    def test_scaleb(self):
2150        c = Context()
2151        d = c.scaleb(Decimal(1), Decimal(2))
2152        self.assertEqual(c.scaleb(1, 2), d)
2153        self.assertEqual(c.scaleb(Decimal(1), 2), d)
2154        self.assertEqual(c.scaleb(1, Decimal(2)), d)
2155        self.assertRaises(TypeError, c.scaleb, '1', 2)
2156        self.assertRaises(TypeError, c.scaleb, 1, '2')
2157
2158    def test_shift(self):
2159        c = Context()
2160        d = c.shift(Decimal(1), Decimal(2))
2161        self.assertEqual(c.shift(1, 2), d)
2162        self.assertEqual(c.shift(Decimal(1), 2), d)
2163        self.assertEqual(c.shift(1, Decimal(2)), d)
2164        self.assertRaises(TypeError, c.shift, '1', 2)
2165        self.assertRaises(TypeError, c.shift, 1, '2')
2166
2167    def test_subtract(self):
2168        c = Context()
2169        d = c.subtract(Decimal(1), Decimal(2))
2170        self.assertEqual(c.subtract(1, 2), d)
2171        self.assertEqual(c.subtract(Decimal(1), 2), d)
2172        self.assertEqual(c.subtract(1, Decimal(2)), d)
2173        self.assertRaises(TypeError, c.subtract, '1', 2)
2174        self.assertRaises(TypeError, c.subtract, 1, '2')
2175
2176    def test_to_eng_string(self):
2177        c = Context()
2178        d = c.to_eng_string(Decimal(10))
2179        self.assertEqual(c.to_eng_string(10), d)
2180        self.assertRaises(TypeError, c.to_eng_string, '10')
2181
2182    def test_to_sci_string(self):
2183        c = Context()
2184        d = c.to_sci_string(Decimal(10))
2185        self.assertEqual(c.to_sci_string(10), d)
2186        self.assertRaises(TypeError, c.to_sci_string, '10')
2187
2188    def test_to_integral_exact(self):
2189        c = Context()
2190        d = c.to_integral_exact(Decimal(10))
2191        self.assertEqual(c.to_integral_exact(10), d)
2192        self.assertRaises(TypeError, c.to_integral_exact, '10')
2193
2194    def test_to_integral_value(self):
2195        c = Context()
2196        d = c.to_integral_value(Decimal(10))
2197        self.assertEqual(c.to_integral_value(10), d)
2198        self.assertRaises(TypeError, c.to_integral_value, '10')
2199
2200class WithStatementTest(unittest.TestCase):
2201    # Can't do these as docstrings until Python 2.6
2202    # as doctest can't handle __future__ statements
2203
2204    def test_localcontext(self):
2205        # Use a copy of the current context in the block
2206        orig_ctx = getcontext()
2207        with localcontext() as enter_ctx:
2208            set_ctx = getcontext()
2209        final_ctx = getcontext()
2210        self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
2211        self.assertIsNot(orig_ctx, set_ctx, 'did not copy the context')
2212        self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
2213
2214    def test_localcontextarg(self):
2215        # Use a copy of the supplied context in the block
2216        orig_ctx = getcontext()
2217        new_ctx = Context(prec=42)
2218        with localcontext(new_ctx) as enter_ctx:
2219            set_ctx = getcontext()
2220        final_ctx = getcontext()
2221        self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
2222        self.assertEqual(set_ctx.prec, new_ctx.prec, 'did not set correct context')
2223        self.assertIsNot(new_ctx, set_ctx, 'did not copy the context')
2224        self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
2225
2226class ContextFlags(unittest.TestCase):
2227    def test_flags_irrelevant(self):
2228        # check that the result (numeric result + flags raised) of an
2229        # arithmetic operation doesn't depend on the current flags
2230
2231        context = Context(prec=9, Emin = -999999999, Emax = 999999999,
2232                    rounding=ROUND_HALF_EVEN, traps=[], flags=[])
2233
2234        # operations that raise various flags, in the form (function, arglist)
2235        operations = [
2236            (context._apply, [Decimal("100E-1000000009")]),
2237            (context.sqrt, [Decimal(2)]),
2238            (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]),
2239            (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]),
2240            (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]),
2241            ]
2242
2243        # try various flags individually, then a whole lot at once
2244        flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal],
2245                    [Inexact, Rounded, Underflow, Clamped, Subnormal]]
2246
2247        for fn, args in operations:
2248            # find answer and flags raised using a clean context
2249            context.clear_flags()
2250            ans = fn(*args)
2251            flags = [k for k, v in context.flags.items() if v]
2252
2253            for extra_flags in flagsets:
2254                # set flags, before calling operation
2255                context.clear_flags()
2256                for flag in extra_flags:
2257                    context._raise_error(flag)
2258                new_ans = fn(*args)
2259
2260                # flags that we expect to be set after the operation
2261                expected_flags = list(flags)
2262                for flag in extra_flags:
2263                    if flag not in expected_flags:
2264                        expected_flags.append(flag)
2265
2266                # flags we actually got
2267                new_flags = [k for k,v in context.flags.items() if v]
2268
2269                self.assertEqual(ans, new_ans,
2270                                 "operation produces different answers depending on flags set: " +
2271                                 "expected %s, got %s." % (ans, new_ans))
2272                self.assertItemsEqual(new_flags, expected_flags,
2273                                  "operation raises different flags depending on flags set: " +
2274                                  "expected %s, got %s" % (expected_flags, new_flags))
2275
2276def test_main(arith=False, verbose=None, todo_tests=None, debug=None):
2277    """ Execute the tests.
2278
2279    Runs all arithmetic tests if arith is True or if the "decimal" resource
2280    is enabled in regrtest.py
2281    """
2282
2283    init()
2284    global TEST_ALL, DEBUG
2285    TEST_ALL = arith or is_resource_enabled('decimal')
2286    DEBUG = debug
2287
2288    if todo_tests is None:
2289        test_classes = [
2290            DecimalExplicitConstructionTest,
2291            DecimalImplicitConstructionTest,
2292            DecimalArithmeticOperatorsTest,
2293            DecimalFormatTest,
2294            DecimalUseOfContextTest,
2295            DecimalUsabilityTest,
2296            DecimalPythonAPItests,
2297            ContextAPItests,
2298            DecimalTest,
2299            WithStatementTest,
2300            ContextFlags
2301        ]
2302    else:
2303        test_classes = [DecimalTest]
2304
2305    # Dynamically build custom test definition for each file in the test
2306    # directory and add the definitions to the DecimalTest class.  This
2307    # procedure insures that new files do not get skipped.
2308    for filename in os.listdir(directory):
2309        if '.decTest' not in filename or filename.startswith("."):
2310            continue
2311        head, tail = filename.split('.')
2312        if todo_tests is not None and head not in todo_tests:
2313            continue
2314        tester = lambda self, f=filename: self.eval_file(directory + f)
2315        setattr(DecimalTest, 'test_' + head, tester)
2316        del filename, head, tail, tester
2317
2318
2319    try:
2320        run_unittest(*test_classes)
2321        if todo_tests is None:
2322            import decimal as DecimalModule
2323            run_doctest(DecimalModule, verbose)
2324    finally:
2325        setcontext(ORIGINAL_CONTEXT)
2326
2327if __name__ == '__main__':
2328    import optparse
2329    p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]")
2330    p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test')
2331    p.add_option('--skip',  '-s', action='store_true', help='skip over 90% of the arithmetic tests')
2332    (opt, args) = p.parse_args()
2333
2334    if opt.skip:
2335        test_main(arith=False, verbose=True)
2336    elif args:
2337        test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug)
2338    else:
2339        test_main(arith=True, verbose=True)
2340