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