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