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