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 warnings 31import pickle, copy 32import unittest 33import numbers 34import locale 35from test.test_support import run_unittest, run_doctest, is_resource_enabled 36from test.test_support import check_warnings, TestFailed 37import random 38import time 39import warnings 40import fractions 41try: 42 import threading 43except ImportError: 44 threading = None 45 46 47import cdecimal as C 48import decimal as P 49orig_sys_decimal = sys.modules['decimal'] 50 51py_minor = sys.version_info[1] 52 53# Testing all failures of API functions for _decimal. First, 54# the number of API calls in a test case is determined. Then, 55# the testcase is run with all possible API failures, checking 56# that FailAPIException is properly raised. 57def assertRaises(expEx, func, *args, **kwargs): 58 """assertRaises has to reraise FailAPIException.""" 59 try: 60 func(*args, **kwargs) 61 except Exception as e: 62 if e.__class__ is C.FailAPIException: 63 raise C.FailAPIException 64 if not e.__class__ is expEx: 65 raise e 66 67def withFailpoint(func): 68 """Wrap a function for testing all possible API failures.""" 69 def iter_failpoint(testcase, *args): 70 # These tests will not work. 71 setattr(testcase, 'assertRaises', assertRaises) 72 # Determine number of API calls. 73 C.setapicalls(0) 74 C.setfailpoint(0) 75 func(testcase, *args) 76 n = C.getapicalls() 77 # Fail at each possible API call. 78 for i in range(1, n+1): 79 C.setapicalls(0) 80 C.setfailpoint(i) 81 try: 82 func(testcase, *args) 83 except C.FailAPIException: 84 continue 85 # Error: FailAPIException was not raised 86 raise TestFailed("FailAPIException not raised in: %s" % func) 87 C.setapicalls(0) 88 C.setfailpoint(0) 89 return iter_failpoint 90 91class ProtectFail(object): 92 """Protect code regions that modify global state (e.g. lines 93 that set or restore global context values). Otherwise it 94 would not be possible to rerun a test case several times.""" 95 def __enter__(self): 96 if hasattr(C, 'setfailpoint'): 97 self.calls = C.getapicalls() 98 self.fpoint = C.getfailpoint() 99 C.setfailpoint(0) 100 def __exit__(self, *_): 101 if hasattr(C, 'setfailpoint'): 102 C.setfailpoint(self.fpoint) 103 if self.fpoint: 104 if self.calls < self.fpoint <= C.getapicalls(): 105 # Pretend that API calls in the protected block failed. 106 raise C.FailAPIException 107 108def protectfail(): 109 return ProtectFail() 110 111if hasattr(C, 'setfailpoint'): 112 # Functions that are iterated several times must use 113 # the same random sequence each time. 114 randseed = int(time.time()) 115 # Implicit initialization of the module context must 116 # be tested first. 117 for i in range(1, 100): 118 C.setapicalls(0) 119 C.setfailpoint(i) 120 try: 121 C.getcontext() 122 except C.FailAPIException as e: 123 continue 124 C.setapicalls(0) 125 C.setfailpoint(0) 126 127# Useful Test Constant 128Signals = { 129 C: C.getcontext().flags.keys() if C else None, 130 P: P.getcontext().flags.keys() 131} 132# Signals ordered with respect to precedence: when an operation 133# produces multiple signals, signals occurring later in the list 134# should be handled before those occurring earlier in the list. 135OrderedSignals = { 136 C: [C.Clamped, C.Rounded, C.Inexact, C.Subnormal, C.Underflow, 137 C.Overflow, C.DivisionByZero, C.InvalidOperation] if C else None, 138 P: [P.Clamped, P.Rounded, P.Inexact, P.Subnormal, P.Underflow, 139 P.Overflow, P.DivisionByZero, P.InvalidOperation] 140} 141def assert_signals(cls, context, attr, expected): 142 d = getattr(context, attr) 143 cls.assertTrue(all(d[s] if s in expected else not d[s] for s in d)) 144 145RoundingModes = { 146 C: (C.ROUND_UP, C.ROUND_DOWN, C.ROUND_CEILING, C.ROUND_FLOOR, 147 C.ROUND_HALF_UP, C.ROUND_HALF_DOWN, C.ROUND_HALF_EVEN, 148 C.ROUND_05UP) if C else None, 149 P: (P.ROUND_UP, P.ROUND_DOWN, P.ROUND_CEILING, P.ROUND_FLOOR, 150 P.ROUND_HALF_UP, P.ROUND_HALF_DOWN, P.ROUND_HALF_EVEN, 151 P.ROUND_05UP) 152} 153 154# Tests are built around these assumed context defaults. 155# test_main() restores the original context. 156ORIGINAL_CONTEXT = { 157 C: C.getcontext().copy() if C else None, 158 P: P.getcontext().copy() 159} 160def init(m): 161 if not m: return 162 DefaultTestContext = m.Context( 163 prec=9, rounding=m.ROUND_HALF_EVEN, traps=dict.fromkeys(Signals[m], 0) 164 ) 165 m.setcontext(DefaultTestContext) 166 167TESTDATADIR = 'decimaltestdata' 168if __name__ == '__main__': 169 file = sys.argv[0] 170else: 171 file = __file__ 172testdir = os.path.dirname(file) or os.curdir 173directory = testdir + os.sep + TESTDATADIR + os.sep 174 175skip_expected = not os.path.isdir(directory) 176 177# Make sure it actually raises errors when not expected and caught in flags 178# Slower, since it runs some things several times. 179EXTENDEDERRORTEST = False 180 181 182class IBMTestCases(unittest.TestCase): 183 """Class which tests the Decimal class against the IBM test cases.""" 184 185 def setUp(self): 186 self.context = self.decimal.Context() 187 self.readcontext = self.decimal.Context() 188 self.ignore_list = ['#'] 189 190 # List of individual .decTest test ids that correspond to tests that 191 # we're skipping for one reason or another. 192 self.skipped_test_ids = set([ 193 # Skip implementation-specific scaleb tests. 194 'scbx164', 195 'scbx165', 196 197 # Skip large powers for _power_exact: 198 'extr1700', 199 'extr1701', 200 'extr1702', 201 'extr1703', 202 203 # For some operations (currently exp, ln, log10, power), the decNumber 204 # reference implementation imposes additional restrictions on the context 205 # and operands. These restrictions are not part of the specification; 206 # however, the effect of these restrictions does show up in some of the 207 # testcases. We skip testcases that violate these restrictions, since 208 # Decimal behaves differently from decNumber for these testcases so these 209 # testcases would otherwise fail. 210 'expx901', 211 'expx902', 212 'expx903', 213 'expx905', 214 'lnx901', 215 'lnx902', 216 'lnx903', 217 'lnx905', 218 'logx901', 219 'logx902', 220 'logx903', 221 'logx905', 222 'powx1183', 223 'powx1184', 224 'powx4001', 225 'powx4002', 226 'powx4003', 227 'powx4005', 228 'powx4008', 229 'powx4010', 230 'powx4012', 231 'powx4014', 232 # plus/minus special cases with ROUND_FLOOR (fixed in 3.3) 233 'minx1030', 234 'plux1031', 235 ]) 236 237 if self.decimal == C: 238 # status has additional Subnormal, Underflow 239 self.skipped_test_ids.add('pwsx803') 240 self.skipped_test_ids.add('pwsx805') 241 # Correct rounding (skipped for decNumber, too) 242 self.skipped_test_ids.add('powx4302') 243 self.skipped_test_ids.add('powx4303') 244 self.skipped_test_ids.add('powx4342') 245 self.skipped_test_ids.add('powx4343') 246 # http://bugs.python.org/issue7049 247 self.skipped_test_ids.add('pwmx325') 248 self.skipped_test_ids.add('pwmx326') 249 250 # Map test directives to setter functions. 251 self.ChangeDict = {'precision' : self.change_precision, 252 'rounding' : self.change_rounding_method, 253 'maxexponent' : self.change_max_exponent, 254 'minexponent' : self.change_min_exponent, 255 'clamp' : self.change_clamp} 256 257 # Name adapter to be able to change the Decimal and Context 258 # interface without changing the test files from Cowlishaw. 259 self.NameAdapter = {'and':'logical_and', 260 'apply':'_apply', 261 'class':'number_class', 262 'comparesig':'compare_signal', 263 'comparetotal':'compare_total', 264 'comparetotmag':'compare_total_mag', 265 'copy':'copy_decimal', 266 'copyabs':'copy_abs', 267 'copynegate':'copy_negate', 268 'copysign':'copy_sign', 269 'divideint':'divide_int', 270 'invert':'logical_invert', 271 'iscanonical':'is_canonical', 272 'isfinite':'is_finite', 273 'isinfinite':'is_infinite', 274 'isnan':'is_nan', 275 'isnormal':'is_normal', 276 'isqnan':'is_qnan', 277 'issigned':'is_signed', 278 'issnan':'is_snan', 279 'issubnormal':'is_subnormal', 280 'iszero':'is_zero', 281 'maxmag':'max_mag', 282 'minmag':'min_mag', 283 'nextminus':'next_minus', 284 'nextplus':'next_plus', 285 'nexttoward':'next_toward', 286 'or':'logical_or', 287 'reduce':'normalize', 288 'remaindernear':'remainder_near', 289 'samequantum':'same_quantum', 290 'squareroot':'sqrt', 291 'toeng':'to_eng_string', 292 'tointegral':'to_integral_value', 293 'tointegralx':'to_integral_exact', 294 'tosci':'to_sci_string', 295 'xor':'logical_xor'} 296 297 # Map test-case names to roundings. 298 self.RoundingDict = {'ceiling' : self.decimal.ROUND_CEILING, 299 'down' : self.decimal.ROUND_DOWN, 300 'floor' : self.decimal.ROUND_FLOOR, 301 'half_down' : self.decimal.ROUND_HALF_DOWN, 302 'half_even' : self.decimal.ROUND_HALF_EVEN, 303 'half_up' : self.decimal.ROUND_HALF_UP, 304 'up' : self.decimal.ROUND_UP, 305 '05up' : self.decimal.ROUND_05UP} 306 307 # Map the test cases' error names to the actual errors. 308 self.ErrorNames = {'clamped' : self.decimal.Clamped, 309 'conversion_syntax' : self.decimal.InvalidOperation, 310 'division_by_zero' : self.decimal.DivisionByZero, 311 'division_impossible' : self.decimal.InvalidOperation, 312 'division_undefined' : self.decimal.InvalidOperation, 313 'inexact' : self.decimal.Inexact, 314 'invalid_context' : self.decimal.InvalidOperation, 315 'invalid_operation' : self.decimal.InvalidOperation, 316 'overflow' : self.decimal.Overflow, 317 'rounded' : self.decimal.Rounded, 318 'subnormal' : self.decimal.Subnormal, 319 'underflow' : self.decimal.Underflow} 320 321 # The following functions return True/False rather than a 322 # Decimal instance. 323 self.LogicalFunctions = ('is_canonical', 324 'is_finite', 325 'is_infinite', 326 'is_nan', 327 'is_normal', 328 'is_qnan', 329 'is_signed', 330 'is_snan', 331 'is_subnormal', 332 'is_zero', 333 'same_quantum') 334 335 def read_unlimited(self, v, context): 336 """Work around the limitations of the 32-bit _decimal version. The 337 guaranteed maximum values for prec, Emax etc. are 425000000, 338 but higher values usually work, except for rare corner cases. 339 In particular, all of the IBM tests pass with maximum values 340 of 1070000000.""" 341 if self.decimal == C and self.decimal.MAX_EMAX == 425000000: 342 self.readcontext.unsafe_setprec(1070000000) 343 self.readcontext.unsafe_setemax(1070000000) 344 self.readcontext.unsafe_setemin(-1070000000) 345 return self.readcontext.create_decimal(v) 346 else: 347 return self.decimal.Decimal(v, context) 348 349 def eval_file(self, file): 350 global skip_expected 351 if skip_expected: 352 raise unittest.SkipTest 353 return 354 with open(file) as f: 355 for line in f: 356 line = line.replace('\r\n', '').replace('\n', '') 357 #print line 358 try: 359 t = self.eval_line(line) 360 except self.decimal.DecimalException as exception: 361 #Exception raised where there shouldn't have been one. 362 self.fail('Exception "'+exception.__class__.__name__ + '" raised on line '+line) 363 364 return 365 366 def eval_line(self, s): 367 if s.find(' -> ') >= 0 and s[:2] != '--' and not s.startswith(' --'): 368 s = (s.split('->')[0] + '->' + 369 s.split('->')[1].split('--')[0]).strip() 370 else: 371 s = s.split('--')[0].strip() 372 373 for ignore in self.ignore_list: 374 if s.find(ignore) >= 0: 375 #print s.split()[0], 'NotImplemented--', ignore 376 return 377 if not s: 378 return 379 elif ':' in s: 380 return self.eval_directive(s) 381 else: 382 return self.eval_equation(s) 383 384 def eval_directive(self, s): 385 funct, value = (x.strip().lower() for x in s.split(':')) 386 if funct == 'rounding': 387 value = self.RoundingDict[value] 388 else: 389 try: 390 value = int(value) 391 except ValueError: 392 pass 393 394 funct = self.ChangeDict.get(funct, (lambda *args: None)) 395 funct(value) 396 397 def eval_equation(self, s): 398 399 if not TEST_ALL and not hasattr(C, 'setfailpoint') and \ 400 random.random() < 0.90: 401 return 402 403 with protectfail(): 404 self.context.clear_flags() 405 406 try: 407 Sides = s.split('->') 408 L = Sides[0].strip().split() 409 id = L[0] 410 if DEBUG: 411 print("Test ", id) 412 funct = L[1].lower() 413 valstemp = L[2:] 414 L = Sides[1].strip().split() 415 ans = L[0] 416 exceptions = L[1:] 417 except (TypeError, AttributeError, IndexError): 418 raise self.decimal.InvalidOperation 419 def FixQuotes(val): 420 val = val.replace("''", 'SingleQuote').replace('""', 'DoubleQuote') 421 val = val.replace("'", '').replace('"', '') 422 val = val.replace('SingleQuote', "'").replace('DoubleQuote', '"') 423 return val 424 425 if id in self.skipped_test_ids: 426 return 427 428 fname = self.NameAdapter.get(funct, funct) 429 if fname == 'rescale': 430 return 431 funct = getattr(self.context, fname) 432 vals = [] 433 conglomerate = '' 434 quote = 0 435 theirexceptions = [self.ErrorNames[x.lower()] for x in exceptions] 436 437 for exception in Signals[self.decimal]: 438 self.context.traps[exception] = 1 #Catch these bugs... 439 for exception in theirexceptions: 440 self.context.traps[exception] = 0 441 for i, val in enumerate(valstemp): 442 if val.count("'") % 2 == 1: 443 quote = 1 - quote 444 if quote: 445 conglomerate = conglomerate + ' ' + val 446 continue 447 else: 448 val = conglomerate + val 449 conglomerate = '' 450 v = FixQuotes(val) 451 if fname in ('to_sci_string', 'to_eng_string'): 452 if EXTENDEDERRORTEST: 453 for error in theirexceptions: 454 self.context.traps[error] = 1 455 try: 456 funct(self.context.create_decimal(v)) 457 except error: 458 pass 459 except Signals[self.decimal] as e: 460 self.fail("Raised %s in %s when %s disabled" % \ 461 (e, s, error)) 462 else: 463 self.fail("Did not raise %s in %s" % (error, s)) 464 self.context.traps[error] = 0 465 v = self.context.create_decimal(v) 466 else: 467 v = self.read_unlimited(v, self.context) 468 vals.append(v) 469 470 ans = FixQuotes(ans) 471 472 # three argument power/powmod (deprecated) 473 if self.decimal == C: 474 if fname == 'power' and len(vals) == 3: 475 # name is different 476 fname = 'powmod' 477 funct = getattr(self.context, fname) 478 479 if EXTENDEDERRORTEST and fname not in ('to_sci_string', 'to_eng_string'): 480 for error in theirexceptions: 481 self.context.traps[error] = 1 482 try: 483 funct(*vals) 484 except error: 485 pass 486 except Signals[self.decimal] as e: 487 self.fail("Raised %s in %s when %s disabled" % \ 488 (e, s, error)) 489 else: 490 self.fail("Did not raise %s in %s" % (error, s)) 491 self.context.traps[error] = 0 492 493 # as above, but add traps cumulatively, to check precedence 494 ordered_errors = [e for e in OrderedSignals[self.decimal] if e in theirexceptions] 495 for error in ordered_errors: 496 self.context.traps[error] = 1 497 try: 498 funct(*vals) 499 except error: 500 pass 501 except Signals[self.decimal] as e: 502 self.fail("Raised %s in %s; expected %s" % 503 (type(e), s, error)) 504 else: 505 self.fail("Did not raise %s in %s" % (error, s)) 506 # reset traps 507 for error in ordered_errors: 508 self.context.traps[error] = 0 509 510 511 if DEBUG: 512 print("--", self.context) 513 try: 514 result = str(funct(*vals)) 515 if fname in self.LogicalFunctions: 516 result = str(int(eval(result))) # 'True', 'False' -> '1', '0' 517 except Signals[self.decimal] as error: 518 self.fail("Raised %s in %s" % (error, s)) 519 except Exception as e: #Catch any error long enough to state the test case. 520 # Errors are expected with failpoints. 521 if not hasattr(C, 'setfailpoint'): 522 print("ERROR:", s) 523 raise e.__class__ 524 525 myexceptions = self.getexceptions() 526 527 myexceptions.sort(key=repr) 528 theirexceptions.sort(key=repr) 529 530 self.assertEqual(result, ans, 531 'Incorrect answer for ' + s + ' -- got ' + result) 532 533 self.assertEqual(myexceptions, theirexceptions, 534 'Incorrect flags set in ' + s + ' -- got ' + str(myexceptions)) 535 return 536 537 def getexceptions(self): 538 return [e for e in Signals[self.decimal] if self.context.flags[e]] 539 540 def change_precision(self, prec): 541 if self.decimal == C and self.decimal.MAX_PREC == 425000000: 542 self.context.unsafe_setprec(prec) 543 else: 544 self.context.prec = prec 545 def change_rounding_method(self, rounding): 546 self.context.rounding = rounding 547 def change_min_exponent(self, exp): 548 if self.decimal == C and self.decimal.MAX_PREC == 425000000: 549 self.context.unsafe_setemin(exp) 550 else: 551 self.context.Emin = exp 552 def change_max_exponent(self, exp): 553 if self.decimal == C and self.decimal.MAX_PREC == 425000000: 554 self.context.unsafe_setemax(exp) 555 else: 556 self.context.Emax = exp 557 def change_clamp(self, clamp): 558 self.context._clamp = clamp 559 560class CIBMTestCases(IBMTestCases): 561 decimal = C 562class PyIBMTestCases(IBMTestCases): 563 decimal = P 564 565# The following classes test the behaviour of Decimal according to PEP 327 566 567class ExplicitConstructionTest(unittest.TestCase): 568 '''Unit tests for Explicit Construction cases of Decimal.''' 569 570 def test_explicit_empty(self): 571 Decimal = self.decimal.Decimal 572 self.assertEqual(Decimal(), Decimal("0")) 573 574 def test_explicit_from_None(self): 575 Decimal = self.decimal.Decimal 576 self.assertRaises(TypeError, Decimal, None) 577 578 def test_explicit_from_int(self): 579 Decimal = self.decimal.Decimal 580 581 #positive 582 d = Decimal(45) 583 self.assertEqual(str(d), '45') 584 585 #very large positive 586 d = Decimal(500000123) 587 self.assertEqual(str(d), '500000123') 588 589 #negative 590 d = Decimal(-45) 591 self.assertEqual(str(d), '-45') 592 593 #zero 594 d = Decimal(0) 595 self.assertEqual(str(d), '0') 596 d = Decimal(0L) 597 self.assertEqual(str(d), '0') 598 599 # single word longs 600 for n in range(0, 32): 601 for sign in (-1, 1): 602 for x in range(-5, 5): 603 i = sign * (2**n + x) 604 d = Decimal(i) 605 self.assertEqual(str(d), str(i)) 606 607 def test_explicit_from_string(self): 608 Decimal = self.decimal.Decimal 609 InvalidOperation = self.decimal.InvalidOperation 610 localcontext = self.decimal.localcontext 611 612 #empty 613 self.assertEqual(str(Decimal('')), 'NaN') 614 615 #int 616 self.assertEqual(str(Decimal('45')), '45') 617 618 #float 619 self.assertEqual(str(Decimal('45.34')), '45.34') 620 621 #engineer notation 622 self.assertEqual(str(Decimal('45e2')), '4.5E+3') 623 624 #just not a number 625 self.assertEqual(str(Decimal('ugly')), 'NaN') 626 627 #leading and trailing whitespace permitted 628 self.assertEqual(str(Decimal('1.3E4 \n')), '1.3E+4') 629 self.assertEqual(str(Decimal(' -7.89')), '-7.89') 630 self.assertEqual(str(Decimal(" 3.45679 ")), '3.45679') 631 632 #same for unicode 633 self.assertEqual(str(Decimal(u" 3.45679 ")), '3.45679') 634 635 #unicode strings should be permitted 636 self.assertEqual(str(Decimal(u'0E-017')), '0E-17') 637 self.assertEqual(str(Decimal(u'45')), '45') 638 self.assertEqual(str(Decimal(u'-Inf')), '-Infinity') 639 self.assertEqual(str(Decimal(u'NaN123')), 'NaN123') 640 641 with localcontext() as c: 642 c.traps[InvalidOperation] = True 643 # Invalid string 644 self.assertRaises(InvalidOperation, Decimal, "xyz") 645 self.assertRaises(InvalidOperation, Decimal, u"xyz") 646 # Two arguments max 647 self.assertRaises(TypeError, Decimal, "1234", "x", "y") 648 649 def test_explicit_from_tuples(self): 650 Decimal = self.decimal.Decimal 651 652 #zero 653 d = Decimal( (0, (0,), 0) ) 654 self.assertEqual(str(d), '0') 655 656 #int 657 d = Decimal( (1, (4, 5), 0) ) 658 self.assertEqual(str(d), '-45') 659 660 #float 661 d = Decimal( (0, (4, 5, 3, 4), -2) ) 662 self.assertEqual(str(d), '45.34') 663 664 #weird 665 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) ) 666 self.assertEqual(str(d), '-4.34913534E-17') 667 668 #inf 669 d = Decimal( (0, (), "F") ) 670 self.assertEqual(str(d), 'Infinity') 671 672 #wrong number of items 673 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1)) ) 674 675 #bad sign 676 self.assertRaises(ValueError, Decimal, (8, (4, 3, 4, 9, 1), 2) ) 677 self.assertRaises(ValueError, Decimal, (0., (4, 3, 4, 9, 1), 2) ) 678 self.assertRaises(ValueError, Decimal, (Decimal(1), (4, 3, 4, 9, 1), 2)) 679 680 #bad exp 681 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 'wrong!') ) 682 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 0.) ) 683 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), '1') ) 684 685 #bad coefficients 686 self.assertRaises(ValueError, Decimal, (1, "xyz", 2) ) 687 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, None, 1), 2) ) 688 self.assertRaises(ValueError, Decimal, (1, (4, -3, 4, 9, 1), 2) ) 689 self.assertRaises(ValueError, Decimal, (1, (4, 10, 4, 9, 1), 2) ) 690 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 'a', 1), 2) ) 691 692 def test_explicit_from_bool(self): 693 Decimal = self.decimal.Decimal 694 695 self.assertTrue(bool(Decimal(0)) is False) 696 self.assertTrue(bool(Decimal(1)) is True) 697 self.assertEqual(Decimal(False), Decimal(0)) 698 self.assertEqual(Decimal(True), Decimal(1)) 699 700 def test_explicit_from_Decimal(self): 701 Decimal = self.decimal.Decimal 702 703 #positive 704 d = Decimal(45) 705 e = Decimal(d) 706 self.assertEqual(str(e), '45') 707 708 #very large positive 709 d = Decimal(500000123) 710 e = Decimal(d) 711 self.assertEqual(str(e), '500000123') 712 713 #negative 714 d = Decimal(-45) 715 e = Decimal(d) 716 self.assertEqual(str(e), '-45') 717 718 #zero 719 d = Decimal(0) 720 e = Decimal(d) 721 self.assertEqual(str(e), '0') 722 723 def test_explicit_from_float(self): 724 if not float.__getformat__("double").startswith("IEEE"): 725 return 726 if hasattr(C, 'setfailpoint'): 727 random.seed(randseed) 728 729 Decimal = self.decimal.Decimal 730 localcontext = self.decimal.localcontext 731 732 if self.decimal == C: 733 FloatOperation = self.decimal.FloatOperation 734 if py_minor <= 6: 735 with localcontext() as c: 736 # TypeError in 2.6 737 c.clear_flags() 738 self.assertRaises(TypeError, Decimal, 7.5) 739 self.assertFalse(c.flags[FloatOperation]) 740 741 c.traps[FloatOperation] = True 742 self.assertRaises(TypeError, Decimal, 7.5) 743 self.assertFalse(c.flags[FloatOperation]) 744 return 745 else: 746 with localcontext() as c: 747 c.clear_flags() 748 self.assertEqual(Decimal(7.5), 7.5) 749 self.assertTrue(c.flags[FloatOperation]) 750 751 c.traps[FloatOperation] = True 752 self.assertRaises(FloatOperation, Decimal, 7.5) 753 self.assertTrue(c.flags[FloatOperation]) 754 755 r = Decimal.from_float(0.1) 756 self.assertEqual(type(r), Decimal) 757 self.assertEqual(str(r), 758 '0.1000000000000000055511151231257827021181583404541015625') 759 self.assertTrue(Decimal.from_float(float('nan')).is_qnan()) 760 self.assertTrue(Decimal.from_float(float('inf')).is_infinite()) 761 self.assertTrue(Decimal.from_float(float('-inf')).is_infinite()) 762 self.assertEqual(str(Decimal.from_float(float('nan'))), 763 str(Decimal('NaN'))) 764 self.assertEqual(str(Decimal.from_float(float('inf'))), 765 str(Decimal('Infinity'))) 766 self.assertEqual(str(Decimal.from_float(float('-inf'))), 767 str(Decimal('-Infinity'))) 768 self.assertEqual(str(Decimal.from_float(float('-0.0'))), 769 str(Decimal('-0'))) 770 for i in range(200): 771 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0) 772 self.assertEqual(x, float(Decimal.from_float(x))) # roundtrip 773 774 775 def test_explicit_context_create_decimal(self): 776 Decimal = self.decimal.Decimal 777 InvalidOperation = self.decimal.InvalidOperation 778 Rounded = self.decimal.Rounded 779 780 nc = copy.copy(self.decimal.getcontext()) 781 nc.prec = 3 782 783 # empty 784 d = Decimal() 785 self.assertEqual(str(d), '0') 786 d = nc.create_decimal() 787 self.assertEqual(str(d), '0') 788 789 # from None 790 self.assertRaises(TypeError, nc.create_decimal, None) 791 792 # from int 793 d = nc.create_decimal(456) 794 self.assertTrue(isinstance(d, Decimal)) 795 self.assertEqual(nc.create_decimal(45678), 796 nc.create_decimal('457E+2')) 797 798 # from string 799 d = Decimal('456789') 800 self.assertEqual(str(d), '456789') 801 d = nc.create_decimal('456789') 802 self.assertEqual(str(d), '4.57E+5') 803 # leading and trailing whitespace should result in a NaN; 804 # spaces are already checked in Cowlishaw's test-suite, so 805 # here we just check that a trailing newline results in a NaN 806 self.assertEqual(str(nc.create_decimal('3.14\n')), 'NaN') 807 808 # from tuples 809 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) ) 810 self.assertEqual(str(d), '-4.34913534E-17') 811 d = nc.create_decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) ) 812 self.assertEqual(str(d), '-4.35E-17') 813 814 # from Decimal 815 prevdec = Decimal(500000123) 816 d = Decimal(prevdec) 817 self.assertEqual(str(d), '500000123') 818 d = nc.create_decimal(prevdec) 819 self.assertEqual(str(d), '5.00E+8') 820 821 # more integers 822 nc.prec = 28 823 nc.traps[InvalidOperation] = True 824 825 for v in [-2**63-1, -2**63, -2**31-1, -2**31, 0, 0L, 826 2**31-1, 2**31, 2**63-1, 2**63]: 827 d = nc.create_decimal(v) 828 self.assertTrue(isinstance(d, Decimal)) 829 self.assertEqual(int(d), v) 830 831 nc.prec = 3 832 nc.traps[Rounded] = True 833 self.assertRaises(Rounded, nc.create_decimal, 1234) 834 self.assertRaises(Rounded, nc.create_decimal, 1234L) 835 836 # from string 837 nc.prec = 28 838 self.assertEqual(str(nc.create_decimal('0E-017')), '0E-17') 839 self.assertEqual(str(nc.create_decimal('45')), '45') 840 self.assertEqual(str(nc.create_decimal('-Inf')), '-Infinity') 841 self.assertEqual(str(nc.create_decimal('NaN123')), 'NaN123') 842 843 # from unicode 844 self.assertEqual(str(nc.create_decimal(u'0E-017')), '0E-17') 845 self.assertEqual(str(nc.create_decimal(u'45')), '45') 846 self.assertEqual(str(nc.create_decimal(u'-Inf')), '-Infinity') 847 self.assertEqual(str(nc.create_decimal(u'NaN123')), 'NaN123') 848 849 # invalid arguments 850 self.assertRaises(InvalidOperation, nc.create_decimal, "xyz") 851 self.assertRaises(InvalidOperation, nc.create_decimal, u'xyz') 852 self.assertRaises(ValueError, nc.create_decimal, (1, "xyz", -25)) 853 self.assertRaises(TypeError, nc.create_decimal, "1234", "5678") 854 855 # too many NaN payload digits 856 nc.prec = 3 857 self.assertRaises(InvalidOperation, nc.create_decimal, 'NaN12345') 858 self.assertRaises(InvalidOperation, nc.create_decimal, 859 Decimal('NaN12345')) 860 861 nc.traps[InvalidOperation] = False 862 self.assertEqual(str(nc.create_decimal('NaN12345')), 'NaN') 863 self.assertTrue(nc.flags[InvalidOperation]) 864 865 nc.flags[InvalidOperation] = False 866 self.assertEqual(str(nc.create_decimal(Decimal('NaN12345'))), 'NaN') 867 self.assertTrue(nc.flags[InvalidOperation]) 868 869 def test_explicit_context_create_from_float(self): 870 if hasattr(C, 'setfailpoint'): 871 random.seed(randseed) 872 873 Decimal = self.decimal.Decimal 874 Context = self.decimal.Context 875 876 nc = Context() 877 if self.decimal == C: 878 FloatOperation = self.decimal.FloatOperation 879 if py_minor <= 6: 880 # TypeError in 2.6 881 nc.clear_flags() 882 self.assertRaises(TypeError, nc.create_decimal, 7.5) 883 self.assertFalse(nc.flags[FloatOperation]) 884 885 nc.traps[FloatOperation] = True 886 self.assertRaises(TypeError, nc.create_decimal, 7.5) 887 self.assertFalse(nc.flags[FloatOperation]) 888 nc.traps[FloatOperation] = False 889 return 890 else: 891 nc.clear_flags() 892 self.assertEqual(nc.create_decimal(7.5), 7.5) 893 self.assertTrue(nc.flags[FloatOperation]) 894 895 nc.traps[FloatOperation] = True 896 self.assertRaises(FloatOperation, nc.create_decimal, 7.5) 897 self.assertTrue(nc.flags[FloatOperation]) 898 nc.traps[FloatOperation] = False 899 900 r = nc.create_decimal_from_float(0.1) 901 self.assertEqual(type(r), Decimal) 902 self.assertEqual(str(r), '0.1000000000000000055511151231') 903 self.assertTrue(nc.create_decimal_from_float(float('nan')).is_qnan()) 904 self.assertTrue(nc.create_decimal_from_float(float('inf')).is_infinite()) 905 self.assertTrue(nc.create_decimal_from_float(float('-inf')).is_infinite()) 906 self.assertEqual(str(nc.create_decimal_from_float(float('nan'))), 907 str(nc.create_decimal('NaN'))) 908 self.assertEqual(str(nc.create_decimal_from_float(float('inf'))), 909 str(nc.create_decimal('Infinity'))) 910 self.assertEqual(str(nc.create_decimal_from_float(float('-inf'))), 911 str(nc.create_decimal('-Infinity'))) 912 self.assertEqual(str(nc.create_decimal_from_float(float('-0.0'))), 913 str(nc.create_decimal('-0'))) 914 nc.prec = 100 915 for i in range(200): 916 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0) 917 self.assertEqual(x, float(nc.create_decimal_from_float(x))) # roundtrip 918 919 def test_unicode_digits(self): 920 Decimal = self.decimal.Decimal 921 922 test_values = { 923 u'\uff11': '1', 924 u'\u0660.\u0660\u0663\u0667\u0662e-\u0663' : '0.0000372', 925 u'-nan\u0c68\u0c6a\u0c66\u0c66' : '-NaN2400', 926 } 927 for input, expected in test_values.items(): 928 self.assertEqual(str(Decimal(input)), expected) 929 930class CExplicitConstructionTest(ExplicitConstructionTest): 931 decimal = C 932class PyExplicitConstructionTest(ExplicitConstructionTest): 933 decimal = P 934 935class ImplicitConstructionTest(unittest.TestCase): 936 '''Unit tests for Implicit Construction cases of Decimal.''' 937 938 def test_implicit_from_None(self): 939 Decimal = self.decimal.Decimal 940 self.assertRaises(TypeError, eval, 'Decimal(5) + None', locals()) 941 942 def test_implicit_from_int(self): 943 Decimal = self.decimal.Decimal 944 945 #normal 946 self.assertEqual(str(Decimal(5) + 45), '50') 947 #exceeding precision 948 self.assertEqual(Decimal(5) + 123456789000, Decimal(123456789000)) 949 950 def test_implicit_from_string(self): 951 Decimal = self.decimal.Decimal 952 self.assertRaises(TypeError, eval, 'Decimal(5) + "3"', locals()) 953 954 def test_implicit_from_float(self): 955 Decimal = self.decimal.Decimal 956 self.assertRaises(TypeError, eval, 'Decimal(5) + 2.2', locals()) 957 958 def test_implicit_from_Decimal(self): 959 Decimal = self.decimal.Decimal 960 self.assertEqual(Decimal(5) + Decimal(45), Decimal(50)) 961 962 def test_rop(self): 963 Decimal = self.decimal.Decimal 964 965 # Allow other classes to be trained to interact with Decimals 966 class E: 967 def __divmod__(self, other): 968 return 'divmod ' + str(other) 969 def __rdivmod__(self, other): 970 return str(other) + ' rdivmod' 971 def __lt__(self, other): 972 return 'lt ' + str(other) 973 def __gt__(self, other): 974 return 'gt ' + str(other) 975 def __le__(self, other): 976 return 'le ' + str(other) 977 def __ge__(self, other): 978 return 'ge ' + str(other) 979 def __eq__(self, other): 980 return 'eq ' + str(other) 981 def __ne__(self, other): 982 return 'ne ' + str(other) 983 984 self.assertEqual(divmod(E(), Decimal(10)), 'divmod 10') 985 self.assertEqual(divmod(Decimal(10), E()), '10 rdivmod') 986 self.assertEqual(eval('Decimal(10) < E()'), 'gt 10') 987 self.assertEqual(eval('Decimal(10) > E()'), 'lt 10') 988 self.assertEqual(eval('Decimal(10) <= E()'), 'ge 10') 989 self.assertEqual(eval('Decimal(10) >= E()'), 'le 10') 990 self.assertEqual(eval('Decimal(10) == E()'), 'eq 10') 991 self.assertEqual(eval('Decimal(10) != E()'), 'ne 10') 992 993 # insert operator methods and then exercise them 994 oplist = [ 995 ('+', '__add__', '__radd__'), 996 ('-', '__sub__', '__rsub__'), 997 ('*', '__mul__', '__rmul__'), 998 ('%', '__mod__', '__rmod__'), 999 ('//', '__floordiv__', '__rfloordiv__'), 1000 ('**', '__pow__', '__rpow__') 1001 ] 1002 if 1/2 == 0: 1003 # testing with classic division, so add __div__ 1004 oplist.append(('/', '__div__', '__rdiv__')) 1005 else: 1006 # testing with -Qnew, so add __truediv__ 1007 oplist.append(('/', '__truediv__', '__rtruediv__')) 1008 1009 for sym, lop, rop in oplist: 1010 setattr(E, lop, lambda self, other: 'str' + lop + str(other)) 1011 setattr(E, rop, lambda self, other: str(other) + rop + 'str') 1012 self.assertEqual(eval('E()' + sym + 'Decimal(10)'), 1013 'str' + lop + '10') 1014 self.assertEqual(eval('Decimal(10)' + sym + 'E()'), 1015 '10' + rop + 'str') 1016 1017class CImplicitConstructionTest(ImplicitConstructionTest): 1018 decimal = C 1019class PyImplicitConstructionTest(ImplicitConstructionTest): 1020 decimal = P 1021 1022class FormatTest(unittest.TestCase): 1023 '''Unit tests for the format function.''' 1024 def test_formatting(self): 1025 Decimal = self.decimal.Decimal 1026 1027 if py_minor <= 1 and self.decimal == P: 1028 raise unittest.SkipTest("requires Python 3.2") 1029 1030 # triples giving a format, a Decimal, and the expected result 1031 test_values = [ 1032 ('e', '0E-15', '0e-15'), 1033 ('e', '2.3E-15', '2.3e-15'), 1034 ('e', '2.30E+2', '2.30e+2'), # preserve significant zeros 1035 ('e', '2.30000E-15', '2.30000e-15'), 1036 ('e', '1.23456789123456789e40', '1.23456789123456789e+40'), 1037 ('e', '1.5', '1.5e+0'), 1038 ('e', '0.15', '1.5e-1'), 1039 ('e', '0.015', '1.5e-2'), 1040 ('e', '0.0000000000015', '1.5e-12'), 1041 ('e', '15.0', '1.50e+1'), 1042 ('e', '-15', '-1.5e+1'), 1043 ('e', '0', '0e+0'), 1044 ('e', '0E1', '0e+1'), 1045 ('e', '0.0', '0e-1'), 1046 ('e', '0.00', '0e-2'), 1047 ('.6e', '0E-15', '0.000000e-9'), 1048 ('.6e', '0', '0.000000e+6'), 1049 ('.6e', '9.999999', '9.999999e+0'), 1050 ('.6e', '9.9999999', '1.000000e+1'), 1051 ('.6e', '-1.23e5', '-1.230000e+5'), 1052 ('.6e', '1.23456789e-3', '1.234568e-3'), 1053 ('f', '0', '0'), 1054 ('f', '0.0', '0.0'), 1055 ('f', '0E-2', '0.00'), 1056 ('f', '0.00E-8', '0.0000000000'), 1057 ('f', '0E1', '0'), # loses exponent information 1058 ('f', '3.2E1', '32'), 1059 ('f', '3.2E2', '320'), 1060 ('f', '3.20E2', '320'), 1061 ('f', '3.200E2', '320.0'), 1062 ('f', '3.2E-6', '0.0000032'), 1063 ('.6f', '0E-15', '0.000000'), # all zeros treated equally 1064 ('.6f', '0E1', '0.000000'), 1065 ('.6f', '0', '0.000000'), 1066 ('.0f', '0', '0'), # no decimal point 1067 ('.0f', '0e-2', '0'), 1068 ('.0f', '3.14159265', '3'), 1069 ('.1f', '3.14159265', '3.1'), 1070 ('.4f', '3.14159265', '3.1416'), 1071 ('.6f', '3.14159265', '3.141593'), 1072 ('.7f', '3.14159265', '3.1415926'), # round-half-even! 1073 ('.8f', '3.14159265', '3.14159265'), 1074 ('.9f', '3.14159265', '3.141592650'), 1075 1076 ('g', '0', '0'), 1077 ('g', '0.0', '0.0'), 1078 ('g', '0E1', '0e+1'), 1079 ('G', '0E1', '0E+1'), 1080 ('g', '0E-5', '0.00000'), 1081 ('g', '0E-6', '0.000000'), 1082 ('g', '0E-7', '0e-7'), 1083 ('g', '-0E2', '-0e+2'), 1084 ('.0g', '3.14159265', '3'), # 0 sig fig -> 1 sig fig 1085 ('.1g', '3.14159265', '3'), 1086 ('.2g', '3.14159265', '3.1'), 1087 ('.5g', '3.14159265', '3.1416'), 1088 ('.7g', '3.14159265', '3.141593'), 1089 ('.8g', '3.14159265', '3.1415926'), # round-half-even! 1090 ('.9g', '3.14159265', '3.14159265'), 1091 ('.10g', '3.14159265', '3.14159265'), # don't pad 1092 1093 ('%', '0E1', '0%'), 1094 ('%', '0E0', '0%'), 1095 ('%', '0E-1', '0%'), 1096 ('%', '0E-2', '0%'), 1097 ('%', '0E-3', '0.0%'), 1098 ('%', '0E-4', '0.00%'), 1099 1100 ('.3%', '0', '0.000%'), # all zeros treated equally 1101 ('.3%', '0E10', '0.000%'), 1102 ('.3%', '0E-10', '0.000%'), 1103 ('.3%', '2.34', '234.000%'), 1104 ('.3%', '1.234567', '123.457%'), 1105 ('.0%', '1.23', '123%'), 1106 1107 ('e', 'NaN', 'NaN'), 1108 ('f', '-NaN123', '-NaN123'), 1109 ('+g', 'NaN456', '+NaN456'), 1110 ('.3e', 'Inf', 'Infinity'), 1111 ('.16f', '-Inf', '-Infinity'), 1112 ('.0g', '-sNaN', '-sNaN'), 1113 1114 ('', '1.00', '1.00'), 1115 1116 # test alignment and padding 1117 ('6', '123', ' 123'), 1118 ('<6', '123', '123 '), 1119 ('>6', '123', ' 123'), 1120 ('^6', '123', ' 123 '), 1121 ('=+6', '123', '+ 123'), 1122 ('#<10', 'NaN', 'NaN#######'), 1123 ('#<10', '-4.3', '-4.3######'), 1124 ('#<+10', '0.0130', '+0.0130###'), 1125 ('#< 10', '0.0130', ' 0.0130###'), 1126 ('@>10', '-Inf', '@-Infinity'), 1127 ('#>5', '-Inf', '-Infinity'), 1128 ('?^5', '123', '?123?'), 1129 ('%^6', '123', '%123%%'), 1130 (' ^6', '-45.6', '-45.6 '), 1131 ('/=10', '-45.6', '-/////45.6'), 1132 ('/=+10', '45.6', '+/////45.6'), 1133 ('/= 10', '45.6', ' /////45.6'), 1134 1135 # thousands separator 1136 (',', '1234567', '1,234,567'), 1137 (',', '123456', '123,456'), 1138 (',', '12345', '12,345'), 1139 (',', '1234', '1,234'), 1140 (',', '123', '123'), 1141 (',', '12', '12'), 1142 (',', '1', '1'), 1143 (',', '0', '0'), 1144 (',', '-1234567', '-1,234,567'), 1145 (',', '-123456', '-123,456'), 1146 ('7,', '123456', '123,456'), 1147 ('8,', '123456', ' 123,456'), 1148 ('08,', '123456', '0,123,456'), # special case: extra 0 needed 1149 ('+08,', '123456', '+123,456'), # but not if there's a sign 1150 (' 08,', '123456', ' 123,456'), 1151 ('08,', '-123456', '-123,456'), 1152 ('+09,', '123456', '+0,123,456'), 1153 # ... with fractional part... 1154 ('07,', '1234.56', '1,234.56'), 1155 ('08,', '1234.56', '1,234.56'), 1156 ('09,', '1234.56', '01,234.56'), 1157 ('010,', '1234.56', '001,234.56'), 1158 ('011,', '1234.56', '0,001,234.56'), 1159 ('012,', '1234.56', '0,001,234.56'), 1160 ('08,.1f', '1234.5', '01,234.5'), 1161 # no thousands separators in fraction part 1162 (',', '1.23456789', '1.23456789'), 1163 (',%', '123.456789', '12,345.6789%'), 1164 (',e', '123456', '1.23456e+5'), 1165 (',E', '123456', '1.23456E+5'), 1166 1167 # issue 6850 1168 ('a=-7.0', '0.12345', 'aaaa0.1'), 1169 ] 1170 for fmt, d, result in test_values: 1171 self.assertEqual(format(Decimal(d), fmt), result) 1172 1173 def test_n_format(self): 1174 Decimal = self.decimal.Decimal 1175 1176 try: 1177 from locale import CHAR_MAX 1178 except ImportError: 1179 return 1180 1181 def make_grouping(lst): 1182 return unicode(''.join([chr(x) for x in lst])) if self.decimal == C else lst 1183 1184 def get_fmt(x, override=None, fmt='n'): 1185 if self.decimal == C: 1186 return Decimal(x).__format__(fmt, override) 1187 else: 1188 return Decimal(x).__format__(fmt, _localeconv=override) 1189 1190 # Set up some localeconv-like dictionaries 1191 en_US = { 1192 'decimal_point' : u'.', 1193 'grouping' : make_grouping([3, 3, 0]), 1194 'thousands_sep' : u',' 1195 } 1196 1197 fr_FR = { 1198 'decimal_point' : u',', 1199 'grouping' : make_grouping([CHAR_MAX]), 1200 'thousands_sep' : u'' 1201 } 1202 1203 ru_RU = { 1204 'decimal_point' : u',', 1205 'grouping': make_grouping([3, 3, 0]), 1206 'thousands_sep' : u' ' 1207 } 1208 1209 crazy = { 1210 'decimal_point' : u'&', 1211 'grouping': make_grouping([1, 4, 2, CHAR_MAX]), 1212 'thousands_sep' : u'-' 1213 } 1214 1215 dotsep_wide = { 1216 'decimal_point' : b'\xc2\xbf'.decode('utf-8'), 1217 'grouping': make_grouping([3, 3, 0]), 1218 'thousands_sep' : b'\xc2\xb4'.decode('utf-8') 1219 } 1220 1221 self.assertEqual(get_fmt(Decimal('12.7'), en_US), '12.7') 1222 self.assertEqual(get_fmt(Decimal('12.7'), fr_FR), '12,7') 1223 self.assertEqual(get_fmt(Decimal('12.7'), ru_RU), '12,7') 1224 self.assertEqual(get_fmt(Decimal('12.7'), crazy), '1-2&7') 1225 1226 self.assertEqual(get_fmt(123456789, en_US), '123,456,789') 1227 self.assertEqual(get_fmt(123456789, fr_FR), '123456789') 1228 self.assertEqual(get_fmt(123456789, ru_RU), '123 456 789') 1229 self.assertEqual(get_fmt(1234567890123, crazy), '123456-78-9012-3') 1230 1231 self.assertEqual(get_fmt(123456789, en_US, '.6n'), '1.23457e+8') 1232 self.assertEqual(get_fmt(123456789, fr_FR, '.6n'), '1,23457e+8') 1233 self.assertEqual(get_fmt(123456789, ru_RU, '.6n'), '1,23457e+8') 1234 self.assertEqual(get_fmt(123456789, crazy, '.6n'), '1&23457e+8') 1235 1236 # zero padding 1237 self.assertEqual(get_fmt(1234, fr_FR, '03n'), '1234') 1238 self.assertEqual(get_fmt(1234, fr_FR, '04n'), '1234') 1239 self.assertEqual(get_fmt(1234, fr_FR, '05n'), '01234') 1240 self.assertEqual(get_fmt(1234, fr_FR, '06n'), '001234') 1241 1242 self.assertEqual(get_fmt(12345, en_US, '05n'), '12,345') 1243 self.assertEqual(get_fmt(12345, en_US, '06n'), '12,345') 1244 self.assertEqual(get_fmt(12345, en_US, '07n'), '012,345') 1245 self.assertEqual(get_fmt(12345, en_US, '08n'), '0,012,345') 1246 self.assertEqual(get_fmt(12345, en_US, '09n'), '0,012,345') 1247 self.assertEqual(get_fmt(12345, en_US, '010n'), '00,012,345') 1248 1249 self.assertEqual(get_fmt(123456, crazy, '06n'), '1-2345-6') 1250 self.assertEqual(get_fmt(123456, crazy, '07n'), '1-2345-6') 1251 self.assertEqual(get_fmt(123456, crazy, '08n'), '1-2345-6') 1252 self.assertEqual(get_fmt(123456, crazy, '09n'), '01-2345-6') 1253 self.assertEqual(get_fmt(123456, crazy, '010n'), '0-01-2345-6') 1254 self.assertEqual(get_fmt(123456, crazy, '011n'), '0-01-2345-6') 1255 self.assertEqual(get_fmt(123456, crazy, '012n'), '00-01-2345-6') 1256 self.assertEqual(get_fmt(123456, crazy, '013n'), '000-01-2345-6') 1257 1258 # wide char separator and decimal point 1259 if self.decimal == C: 1260 self.assertEqual(get_fmt(Decimal('-1.5'), dotsep_wide, '020n'), 1261 '-0\xc2\xb4000\xc2\xb4000\xc2\xb4000\xc2\xb4001\xc2\xbf5') 1262 1263class CFormatTest(FormatTest): 1264 decimal = C 1265class PyFormatTest(FormatTest): 1266 decimal = P 1267 1268class ArithmeticOperatorsTest(unittest.TestCase): 1269 '''Unit tests for all arithmetic operators, binary and unary.''' 1270 1271 def test_addition(self): 1272 Decimal = self.decimal.Decimal 1273 1274 d1 = Decimal('-11.1') 1275 d2 = Decimal('22.2') 1276 1277 #two Decimals 1278 self.assertEqual(d1+d2, Decimal('11.1')) 1279 self.assertEqual(d2+d1, Decimal('11.1')) 1280 1281 #with other type, left 1282 c = d1 + 5 1283 self.assertEqual(c, Decimal('-6.1')) 1284 self.assertEqual(type(c), type(d1)) 1285 1286 #with other type, right 1287 c = 5 + d1 1288 self.assertEqual(c, Decimal('-6.1')) 1289 self.assertEqual(type(c), type(d1)) 1290 1291 #inline with decimal 1292 d1 += d2 1293 self.assertEqual(d1, Decimal('11.1')) 1294 1295 #inline with other type 1296 d1 += 5 1297 self.assertEqual(d1, Decimal('16.1')) 1298 1299 def test_subtraction(self): 1300 Decimal = self.decimal.Decimal 1301 1302 d1 = Decimal('-11.1') 1303 d2 = Decimal('22.2') 1304 1305 #two Decimals 1306 self.assertEqual(d1-d2, Decimal('-33.3')) 1307 self.assertEqual(d2-d1, Decimal('33.3')) 1308 1309 #with other type, left 1310 c = d1 - 5 1311 self.assertEqual(c, Decimal('-16.1')) 1312 self.assertEqual(type(c), type(d1)) 1313 1314 #with other type, right 1315 c = 5 - d1 1316 self.assertEqual(c, Decimal('16.1')) 1317 self.assertEqual(type(c), type(d1)) 1318 1319 #inline with decimal 1320 d1 -= d2 1321 self.assertEqual(d1, Decimal('-33.3')) 1322 1323 #inline with other type 1324 d1 -= 5 1325 self.assertEqual(d1, Decimal('-38.3')) 1326 1327 def test_multiplication(self): 1328 Decimal = self.decimal.Decimal 1329 1330 d1 = Decimal('-5') 1331 d2 = Decimal('3') 1332 1333 #two Decimals 1334 self.assertEqual(d1*d2, Decimal('-15')) 1335 self.assertEqual(d2*d1, Decimal('-15')) 1336 1337 #with other type, left 1338 c = d1 * 5 1339 self.assertEqual(c, Decimal('-25')) 1340 self.assertEqual(type(c), type(d1)) 1341 1342 #with other type, right 1343 c = 5 * d1 1344 self.assertEqual(c, Decimal('-25')) 1345 self.assertEqual(type(c), type(d1)) 1346 1347 #inline with decimal 1348 d1 *= d2 1349 self.assertEqual(d1, Decimal('-15')) 1350 1351 #inline with other type 1352 d1 *= 5 1353 self.assertEqual(d1, Decimal('-75')) 1354 1355 def test_division(self): 1356 Decimal = self.decimal.Decimal 1357 1358 d1 = Decimal('-5') 1359 d2 = Decimal('2') 1360 1361 #two Decimals 1362 self.assertEqual(d1/d2, Decimal('-2.5')) 1363 self.assertEqual(d2/d1, Decimal('-0.4')) 1364 1365 #with other type, left 1366 c = d1 / 4 1367 self.assertEqual(c, Decimal('-1.25')) 1368 self.assertEqual(type(c), type(d1)) 1369 1370 #with other type, right 1371 c = 4 / d1 1372 self.assertEqual(c, Decimal('-0.8')) 1373 self.assertEqual(type(c), type(d1)) 1374 1375 #inline with decimal 1376 d1 /= d2 1377 self.assertEqual(d1, Decimal('-2.5')) 1378 1379 #inline with other type 1380 d1 /= 4 1381 self.assertEqual(d1, Decimal('-0.625')) 1382 1383 def test_floor_division(self): 1384 Decimal = self.decimal.Decimal 1385 1386 d1 = Decimal('5') 1387 d2 = Decimal('2') 1388 1389 #two Decimals 1390 self.assertEqual(d1//d2, Decimal('2')) 1391 self.assertEqual(d2//d1, Decimal('0')) 1392 1393 #with other type, left 1394 c = d1 // 4 1395 self.assertEqual(c, Decimal('1')) 1396 self.assertEqual(type(c), type(d1)) 1397 1398 #with other type, right 1399 c = 7 // d1 1400 self.assertEqual(c, Decimal('1')) 1401 self.assertEqual(type(c), type(d1)) 1402 1403 #inline with decimal 1404 d1 //= d2 1405 self.assertEqual(d1, Decimal('2')) 1406 1407 #inline with other type 1408 d1 //= 2 1409 self.assertEqual(d1, Decimal('1')) 1410 1411 def test_powering(self): 1412 Decimal = self.decimal.Decimal 1413 1414 d1 = Decimal('5') 1415 d2 = Decimal('2') 1416 1417 #two Decimals 1418 self.assertEqual(d1**d2, Decimal('25')) 1419 self.assertEqual(d2**d1, Decimal('32')) 1420 1421 #with other type, left 1422 c = d1 ** 4 1423 self.assertEqual(c, Decimal('625')) 1424 self.assertEqual(type(c), type(d1)) 1425 1426 #with other type, right 1427 c = 7 ** d1 1428 self.assertEqual(c, Decimal('16807')) 1429 self.assertEqual(type(c), type(d1)) 1430 1431 #inline with decimal 1432 d1 **= d2 1433 self.assertEqual(d1, Decimal('25')) 1434 1435 #inline with other type 1436 d1 **= 4 1437 self.assertEqual(d1, Decimal('390625')) 1438 1439 def test_module(self): 1440 Decimal = self.decimal.Decimal 1441 1442 d1 = Decimal('5') 1443 d2 = Decimal('2') 1444 1445 #two Decimals 1446 self.assertEqual(d1%d2, Decimal('1')) 1447 self.assertEqual(d2%d1, Decimal('2')) 1448 1449 #with other type, left 1450 c = d1 % 4 1451 self.assertEqual(c, Decimal('1')) 1452 self.assertEqual(type(c), type(d1)) 1453 1454 #with other type, right 1455 c = 7 % d1 1456 self.assertEqual(c, Decimal('2')) 1457 self.assertEqual(type(c), type(d1)) 1458 1459 #inline with decimal 1460 d1 %= d2 1461 self.assertEqual(d1, Decimal('1')) 1462 1463 #inline with other type 1464 d1 %= 4 1465 self.assertEqual(d1, Decimal('1')) 1466 1467 def test_floor_div_module(self): 1468 Decimal = self.decimal.Decimal 1469 1470 d1 = Decimal('5') 1471 d2 = Decimal('2') 1472 1473 #two Decimals 1474 (p, q) = divmod(d1, d2) 1475 self.assertEqual(p, Decimal('2')) 1476 self.assertEqual(q, Decimal('1')) 1477 self.assertEqual(type(p), type(d1)) 1478 self.assertEqual(type(q), type(d1)) 1479 1480 #with other type, left 1481 (p, q) = divmod(d1, 4) 1482 self.assertEqual(p, Decimal('1')) 1483 self.assertEqual(q, Decimal('1')) 1484 self.assertEqual(type(p), type(d1)) 1485 self.assertEqual(type(q), type(d1)) 1486 1487 #with other type, right 1488 (p, q) = divmod(7, d1) 1489 self.assertEqual(p, Decimal('1')) 1490 self.assertEqual(q, Decimal('2')) 1491 self.assertEqual(type(p), type(d1)) 1492 self.assertEqual(type(q), type(d1)) 1493 1494 def test_unary_operators(self): 1495 Decimal = self.decimal.Decimal 1496 1497 self.assertEqual(+Decimal(45), Decimal(+45)) # + 1498 self.assertEqual(-Decimal(45), Decimal(-45)) # - 1499 self.assertEqual(abs(Decimal(45)), abs(Decimal(-45))) # abs 1500 1501 def test_nan_comparisons(self): 1502 # comparisons involving signaling nans signal InvalidOperation 1503 1504 # order comparisons (<, <=, >, >=) involving only quiet nans 1505 # also signal InvalidOperation 1506 1507 # equality comparisons (==, !=) involving only quiet nans 1508 # don't signal, but return False or True respectively. 1509 Decimal = self.decimal.Decimal 1510 InvalidOperation = self.decimal.InvalidOperation 1511 localcontext = self.decimal.localcontext 1512 1513 if py_minor <= 1 and self.decimal == P: 1514 raise unittest.SkipTest("requires Python 3.2") 1515 1516 n = Decimal('NaN') 1517 s = Decimal('sNaN') 1518 i = Decimal('Inf') 1519 f = Decimal('2') 1520 1521 qnan_pairs = (n, n), (n, i), (i, n), (n, f), (f, n) 1522 snan_pairs = (s, n), (n, s), (s, i), (i, s), (s, f), (f, s), (s, s) 1523 order_ops = operator.lt, operator.le, operator.gt, operator.ge 1524 equality_ops = operator.eq, operator.ne 1525 1526 # results when InvalidOperation is not trapped 1527 for x, y in qnan_pairs + snan_pairs: 1528 for op in order_ops + equality_ops: 1529 got = op(x, y) 1530 expected = True if op is operator.ne else False 1531 self.assertTrue(expected is got) 1532 1533 # repeat the above, but this time trap the InvalidOperation 1534 with localcontext() as ctx: 1535 ctx.traps[InvalidOperation] = 1 1536 1537 for x, y in qnan_pairs: 1538 for op in equality_ops: 1539 got = op(x, y) 1540 expected = True if op is operator.ne else False 1541 self.assertTrue(expected is got) 1542 1543 for x, y in snan_pairs: 1544 for op in equality_ops: 1545 self.assertRaises(InvalidOperation, operator.eq, x, y) 1546 self.assertRaises(InvalidOperation, operator.ne, x, y) 1547 1548 for x, y in qnan_pairs + snan_pairs: 1549 for op in order_ops: 1550 self.assertRaises(InvalidOperation, op, x, y) 1551 1552 def test_copy_sign(self): 1553 Decimal = self.decimal.Decimal 1554 1555 if py_minor <= 1 and self.decimal == P: 1556 raise unittest.SkipTest("requires Python 3.2") 1557 1558 d = Decimal(1).copy_sign(Decimal(-2)) 1559 self.assertEqual(Decimal(1).copy_sign(-2), d) 1560 self.assertRaises(TypeError, Decimal(1).copy_sign, '-2') 1561 1562class CArithmeticOperatorsTest(ArithmeticOperatorsTest): 1563 decimal = C 1564class PyArithmeticOperatorsTest(ArithmeticOperatorsTest): 1565 decimal = P 1566 1567# The following are two functions used to test threading in the next class 1568 1569def thfunc1(cls): 1570 Decimal = cls.decimal.Decimal 1571 InvalidOperation = cls.decimal.InvalidOperation 1572 DivisionByZero = cls.decimal.DivisionByZero 1573 Overflow = cls.decimal.Overflow 1574 Underflow = cls.decimal.Underflow 1575 Inexact = cls.decimal.Inexact 1576 getcontext = cls.decimal.getcontext 1577 localcontext = cls.decimal.localcontext 1578 1579 d1 = Decimal(1) 1580 d3 = Decimal(3) 1581 test1 = d1/d3 1582 1583 cls.finish1.set() 1584 cls.synchro.wait() 1585 1586 test2 = d1/d3 1587 with localcontext() as c2: 1588 cls.assertTrue(c2.flags[Inexact]) 1589 cls.assertRaises(DivisionByZero, c2.divide, d1, 0) 1590 cls.assertTrue(c2.flags[DivisionByZero]) 1591 with localcontext() as c3: 1592 cls.assertTrue(c3.flags[Inexact]) 1593 cls.assertTrue(c3.flags[DivisionByZero]) 1594 cls.assertRaises(InvalidOperation, c3.compare, d1, Decimal('sNaN')) 1595 cls.assertTrue(c3.flags[InvalidOperation]) 1596 del c3 1597 cls.assertFalse(c2.flags[InvalidOperation]) 1598 del c2 1599 1600 cls.assertEqual(test1, Decimal('0.333333333333333333333333')) 1601 cls.assertEqual(test2, Decimal('0.333333333333333333333333')) 1602 1603 c1 = getcontext() 1604 cls.assertTrue(c1.flags[Inexact]) 1605 for sig in Overflow, Underflow, DivisionByZero, InvalidOperation: 1606 cls.assertFalse(c1.flags[sig]) 1607 return 1608 1609def thfunc2(cls): 1610 Decimal = cls.decimal.Decimal 1611 InvalidOperation = cls.decimal.InvalidOperation 1612 DivisionByZero = cls.decimal.DivisionByZero 1613 Overflow = cls.decimal.Overflow 1614 Underflow = cls.decimal.Underflow 1615 Inexact = cls.decimal.Inexact 1616 getcontext = cls.decimal.getcontext 1617 localcontext = cls.decimal.localcontext 1618 1619 d1 = Decimal(1) 1620 d3 = Decimal(3) 1621 test1 = d1/d3 1622 1623 thiscontext = getcontext() 1624 thiscontext.prec = 18 1625 test2 = d1/d3 1626 1627 with localcontext() as c2: 1628 cls.assertTrue(c2.flags[Inexact]) 1629 cls.assertRaises(Overflow, c2.multiply, Decimal('1e425000000'), 999) 1630 cls.assertTrue(c2.flags[Overflow]) 1631 with localcontext(thiscontext) as c3: 1632 cls.assertTrue(c3.flags[Inexact]) 1633 cls.assertFalse(c3.flags[Overflow]) 1634 c3.traps[Underflow] = True 1635 cls.assertRaises(Underflow, c3.divide, Decimal('1e-425000000'), 999) 1636 cls.assertTrue(c3.flags[Underflow]) 1637 del c3 1638 cls.assertFalse(c2.flags[Underflow]) 1639 cls.assertFalse(c2.traps[Underflow]) 1640 del c2 1641 1642 cls.synchro.set() 1643 cls.finish2.set() 1644 1645 cls.assertEqual(test1, Decimal('0.333333333333333333333333')) 1646 cls.assertEqual(test2, Decimal('0.333333333333333333')) 1647 1648 cls.assertFalse(thiscontext.traps[Underflow]) 1649 cls.assertTrue(thiscontext.flags[Inexact]) 1650 for sig in Overflow, Underflow, DivisionByZero, InvalidOperation: 1651 cls.assertFalse(thiscontext.flags[sig]) 1652 return 1653 1654class ThreadingTest(unittest.TestCase): 1655 '''Unit tests for thread local contexts in Decimal.''' 1656 1657 # Take care executing this test from IDLE, there's an issue in threading 1658 # that hangs IDLE and I couldn't find it 1659 1660 def test_threading(self): 1661 if threading is None: 1662 return 1663 if self.decimal == C and not self.decimal.HAVE_THREADS: 1664 return 1665 1666 DefaultContext = self.decimal.DefaultContext 1667 1668 # Test the "threading isolation" of a Context. Also test changing 1669 # the DefaultContext, which acts as a template for the thread-local 1670 # contexts. 1671 save_prec = DefaultContext.prec 1672 save_emax = DefaultContext.Emax 1673 save_emin = DefaultContext.Emin 1674 DefaultContext.prec = 24 1675 DefaultContext.Emax = 425000000 1676 DefaultContext.Emin = -425000000 1677 1678 with protectfail(): 1679 self.synchro = threading.Event() 1680 self.finish1 = threading.Event() 1681 self.finish2 = threading.Event() 1682 1683 th1 = threading.Thread(target=thfunc1, args=(self,)) 1684 th2 = threading.Thread(target=thfunc2, args=(self,)) 1685 1686 th1.start() 1687 th2.start() 1688 1689 self.finish1.wait() 1690 self.finish2.wait() 1691 1692 for sig in Signals[self.decimal]: 1693 self.assertFalse(DefaultContext.flags[sig]) 1694 1695 DefaultContext.prec = save_prec 1696 DefaultContext.Emax = save_emax 1697 DefaultContext.Emin = save_emin 1698 return 1699 1700class CThreadingTest(ThreadingTest): 1701 decimal = C 1702class PyThreadingTest(ThreadingTest): 1703 decimal = P 1704 1705class UsabilityTest(unittest.TestCase): 1706 '''Unit tests for Usability cases of Decimal.''' 1707 1708 def test_comparison_operators(self): 1709 if hasattr(C, 'setfailpoint'): 1710 random.seed(randseed) 1711 1712 Decimal = self.decimal.Decimal 1713 1714 da = Decimal('23.42') 1715 db = Decimal('23.42') 1716 dc = Decimal('45') 1717 1718 #two Decimals 1719 self.assertTrue(dc > da) 1720 self.assertTrue(dc >= da) 1721 self.assertTrue(da < dc) 1722 self.assertTrue(da <= dc) 1723 self.assertTrue(da == db) 1724 self.assertTrue(da != dc) 1725 self.assertTrue(da <= db) 1726 self.assertTrue(da >= db) 1727 self.assertEqual(cmp(dc,da), 1) 1728 self.assertEqual(cmp(da,dc), -1) 1729 self.assertEqual(cmp(da,db), 0) 1730 1731 #a Decimal and an int 1732 self.assertTrue(dc > 23) 1733 self.assertTrue(23 < dc) 1734 self.assertTrue(dc == 45) 1735 self.assertEqual(cmp(dc,23), 1) 1736 self.assertEqual(cmp(23,dc), -1) 1737 self.assertEqual(cmp(dc,45), 0) 1738 1739 #a Decimal and uncomparable 1740 self.assertNotEqual(da, 'ugly') 1741 self.assertNotEqual(da, 32.7) 1742 self.assertNotEqual(da, object()) 1743 self.assertNotEqual(da, object) 1744 1745 # sortable 1746 a = list(map(Decimal, range(100))) 1747 b = a[:] 1748 random.shuffle(a) 1749 a.sort() 1750 self.assertEqual(a, b) 1751 1752 # with None 1753 self.assertFalse(Decimal(1) < None) 1754 self.assertTrue(Decimal(1) > None) 1755 1756 # long 1757 x = 28847289182731823123121213123823129L 1758 self.assertTrue(dc < x) 1759 self.assertTrue(dc <= x) 1760 self.assertTrue(dc > -x) 1761 self.assertTrue(dc >= -x) 1762 self.assertTrue(dc != -x) 1763 self.assertTrue(Decimal(x) == x) 1764 1765 def test_decimal_float_comparison(self): 1766 Decimal = self.decimal.Decimal 1767 Context = self.decimal.Context 1768 localcontext = self.decimal.localcontext 1769 1770 def assert_attr(a, b, attr, context, signal=None): 1771 context.clear_flags() 1772 f = getattr(a, attr) 1773 if self.decimal == C: 1774 if signal == C.FloatOperation: 1775 self.assertRaises(signal, f, b) 1776 elif py_minor <= 6: 1777 # The actual TypeError is raised by 1778 # the caller of the comparison methods. 1779 self.assertTrue(f(b) is NotImplemented) 1780 else: 1781 self.assertTrue(f(b) is True) 1782 self.assertTrue(context.flags[C.FloatOperation]) 1783 else: 1784 if py_minor <= 6: 1785 self.assertTrue(f(b) is NotImplemented) 1786 else: 1787 self.assertTrue(f(b) is True) 1788 1789 small_d = Decimal('0.25') 1790 big_d = Decimal('3.0') 1791 small_f = 0.25 1792 big_f = 3.0 1793 1794 zero_d = Decimal('0.0') 1795 neg_zero_d = Decimal('-0.0') 1796 zero_f = 0.0 1797 neg_zero_f = -0.0 1798 1799 inf_d = Decimal('Infinity') 1800 neg_inf_d = Decimal('-Infinity') 1801 inf_f = float('inf') 1802 neg_inf_f = float('-inf') 1803 1804 def doit(c, signal=None): 1805 # Order 1806 for attr in '__lt__', '__le__': 1807 assert_attr(small_d, big_f, attr, c, signal) 1808 1809 for attr in '__gt__', '__ge__': 1810 assert_attr(big_d, small_f, attr, c, signal) 1811 1812 # Equality 1813 assert_attr(small_d, small_f, '__eq__', c, None) 1814 1815 assert_attr(neg_zero_d, neg_zero_f, '__eq__', c, None) 1816 assert_attr(neg_zero_d, zero_f, '__eq__', c, None) 1817 1818 assert_attr(zero_d, neg_zero_f, '__eq__', c, None) 1819 assert_attr(zero_d, zero_f, '__eq__', c, None) 1820 1821 assert_attr(neg_inf_d, neg_inf_f, '__eq__', c, None) 1822 assert_attr(inf_d, inf_f, '__eq__', c, None) 1823 1824 # Inequality 1825 assert_attr(small_d, big_f, '__ne__', c, None) 1826 1827 assert_attr(Decimal('0.1'), 0.1, '__ne__', c, None) 1828 1829 assert_attr(neg_inf_d, inf_f, '__ne__', c, None) 1830 assert_attr(inf_d, neg_inf_f, '__ne__', c, None) 1831 1832 assert_attr(Decimal('NaN'), float('nan'), '__ne__', c, None) 1833 1834 def test_containers(c, signal): 1835 c.clear_flags() 1836 s = set([100.0, Decimal('100.0')]) 1837 expected_len = 2 if py_minor <= 6 else 1 1838 self.assertEqual(len(s), expected_len) 1839 self.assertTrue(c.flags[C.FloatOperation]) 1840 1841 c.clear_flags() 1842 if signal: 1843 self.assertRaises(signal, sorted, [1.0, Decimal('10.0')]) 1844 else: 1845 s = sorted([10.0, Decimal('10.0')]) 1846 self.assertTrue(c.flags[C.FloatOperation]) 1847 1848 c.clear_flags() 1849 b = 10.0 in [Decimal('10.0'), 1.0] 1850 self.assertTrue(c.flags[C.FloatOperation]) 1851 1852 c.clear_flags() 1853 b = 10.0 in {Decimal('10.0'):'a', 1.0:'b'} 1854 self.assertTrue(c.flags[C.FloatOperation]) 1855 1856 if self.decimal == C: 1857 nc = Context() 1858 with localcontext(nc) as c: 1859 self.assertFalse(c.traps[C.FloatOperation]) 1860 doit(c, signal=None) 1861 test_containers(c, None) 1862 1863 c.traps[C.FloatOperation] = True 1864 doit(c, signal=C.FloatOperation) 1865 test_containers(c, C.FloatOperation) 1866 else: 1867 # decimal.py does not have the FloatOperation signal. 1868 nc = Context() 1869 with localcontext(nc) as c: 1870 doit(c, signal=False) 1871 1872 def test_decimal_complex_comparison(self): 1873 Decimal = self.decimal.Decimal 1874 1875 da = Decimal('0.25') 1876 db = Decimal('3.0') 1877 self.assertNotEqual(da, (1.5+0j)) 1878 self.assertNotEqual((1.5+0j), da) 1879 1880 if py_minor >= 8: 1881 self.assertEqual(da, (0.25+0j)) 1882 self.assertEqual((0.25+0j), da) 1883 self.assertEqual((3.0+0j), db) 1884 self.assertEqual(db, (3.0+0j)) 1885 else: 1886 self.assertNotEqual(da, (0.25+0j)) 1887 self.assertNotEqual((0.25+0j), da) 1888 self.assertNotEqual((3.0+0j), db) 1889 self.assertNotEqual(db, (3.0+0j)) 1890 1891 self.assertNotEqual(db, (3.0+1j)) 1892 self.assertNotEqual((3.0+1j), db) 1893 1894 self.assertTrue(db.__lt__(3.0+0j) is NotImplemented) 1895 self.assertTrue(db.__le__(3.0+0j) is NotImplemented) 1896 self.assertTrue(db.__gt__(3.0+0j) is NotImplemented) 1897 self.assertTrue(db.__le__(3.0+0j) is NotImplemented) 1898 1899 def test_decimal_fraction_comparison(self): 1900 D = self.decimal.Decimal 1901 F = fractions.Fraction 1902 Context = self.decimal.Context 1903 localcontext = self.decimal.localcontext 1904 InvalidOperation = self.decimal.InvalidOperation 1905 1906 1907 emax = C.MAX_EMAX if C else 999999999 1908 emin = C.MIN_EMIN if C else -999999999 1909 etiny = C.MIN_ETINY if C else -1999999997 1910 c = Context(Emax=emax, Emin=emin) 1911 1912 with localcontext(c): 1913 c.prec = emax 1914 if py_minor >= 8: 1915 self.assertTrue(D(0) < F(1,9999999999999999999999999999999999999)) 1916 self.assertTrue(F(-1,9999999999999999999999999999999999999) < D(0)) 1917 self.assertTrue(F(0,1) < D("1e" + str(etiny))) 1918 self.assertTrue(D("-1e" + str(etiny)) < F(0,1)) 1919 self.assertTrue(F(0,9999999999999999999999999) < D("1e" + str(etiny))) 1920 self.assertTrue(D("-1e" + str(etiny)) < F(0,9999999999999999999999999)) 1921 else: 1922 self.assertTrue(NotImplemented is D(0).__lt__(F(1,1))) 1923 self.assertTrue(NotImplemented is D(0).__le__(F(1,1))) 1924 self.assertTrue(NotImplemented is D(0).__gt__(F(1,1))) 1925 self.assertTrue(NotImplemented is D(0).__ge__(F(1,1))) 1926 1927 if py_minor >= 8: 1928 self.assertEqual(D("0.1"), F(1,10)) 1929 self.assertEqual(F(1,10), D("0.1")) 1930 else: 1931 self.assertNotEqual(D("0.1"), F(1,10)) 1932 self.assertNotEqual(F(1,10), D("0.1")) 1933 1934 c.prec = 300 1935 self.assertNotEqual(D(1)/3, F(1,3)) 1936 self.assertNotEqual(F(1,3), D(1)/3) 1937 1938 if py_minor >= 8: 1939 self.assertTrue(F(120984237, 9999999999) <= D("9e" + str(emax))) 1940 self.assertTrue(D("9e" + str(emax)) >= F(120984237, 9999999999)) 1941 1942 self.assertTrue(D('inf') > F(99999999999,123)) 1943 self.assertTrue(D('inf') > F(-99999999999,123)) 1944 self.assertTrue(D('-inf') < F(99999999999,123)) 1945 self.assertTrue(D('-inf') < F(-99999999999,123)) 1946 1947 self.assertRaises(InvalidOperation, D('nan').__gt__, F(-9,123)) 1948 1949 self.assertTrue(NotImplemented is F(-9,123).__lt__(D('nan'))) 1950 self.assertNotEqual(D('nan'), F(-9,123)) 1951 self.assertNotEqual(F(-9,123), D('nan')) 1952 1953 def test_copy_and_deepcopy_methods(self): 1954 Decimal = self.decimal.Decimal 1955 1956 d = Decimal('43.24') 1957 c = copy.copy(d) 1958 self.assertEqual(id(c), id(d)) 1959 dc = copy.deepcopy(d) 1960 self.assertEqual(id(dc), id(d)) 1961 1962 def test_hash_method(self): 1963 if hasattr(C, 'setfailpoint'): 1964 random.seed(randseed) 1965 1966 Decimal = self.decimal.Decimal 1967 localcontext = self.decimal.localcontext 1968 1969 def hashit(d): 1970 a = hash(d) 1971 b = d.__hash__() 1972 self.assertEqual(a, b) 1973 return a 1974 1975 #just that it's hashable 1976 hashit(Decimal(23)) 1977 hashit(Decimal('Infinity')) 1978 hashit(Decimal('-Infinity')) 1979 if py_minor >= 7: 1980 hashit(Decimal('nan123')) 1981 hashit(Decimal('-NaN')) 1982 1983 test_values = [Decimal(sign*(2**m + n)) 1984 for m in [0, 14, 15, 16, 17, 30, 31, 1985 32, 33, 61, 62, 63, 64, 65, 66] 1986 for n in range(-10, 10) 1987 for sign in [-1, 1]] 1988 if hasattr(C, 'setfailpoint'): 1989 test_values = random.sample(test_values, 10) 1990 test_values.extend([ 1991 Decimal("-1"), # ==> -2 1992 Decimal("-0"), # zeros 1993 Decimal("0.00"), 1994 Decimal("-0.000"), 1995 Decimal("0E10"), 1996 Decimal("-0E12"), 1997 Decimal("10.0"), # negative exponent 1998 Decimal("-23.00000"), 1999 Decimal("1230E100"), # positive exponent 2000 Decimal("-4.5678E50"), 2001 # a value for which hash(n) != hash(n % (2**64-1)) 2002 # in Python pre-2.6 2003 Decimal(2**64 + 2**32 - 1), 2004 # selection of values which fail with the old (before 2005 # version 2.6) long.__hash__ 2006 Decimal("1.634E100"), 2007 Decimal("90.697E100"), 2008 Decimal("188.83E100"), 2009 Decimal("1652.9E100"), 2010 Decimal("56531E100"), 2011 ]) 2012 2013 # check that hash(d) == hash(int(d)) for integral values 2014 for value in test_values: 2015 self.assertEqual(hashit(value), hashit(int(value))) 2016 2017 #the same hash that to an int 2018 self.assertEqual(hashit(Decimal(23)), hashit(23)) 2019 self.assertRaises(TypeError, hash, Decimal('sNaN')) 2020 self.assertTrue(hashit(Decimal('Inf'))) 2021 self.assertTrue(hashit(Decimal('-Inf'))) 2022 2023 if py_minor >= 7: 2024 # check that the hashes of a Decimal float match when they 2025 # represent exactly the same values 2026 test_strings = ['inf', '-Inf', '0.0', '-.0e1', 2027 '34.0', '2.5', '112390.625', '-0.515625'] 2028 for s in test_strings: 2029 f = float(s) 2030 d = Decimal(s) 2031 self.assertEqual(hashit(f), hashit(d)) 2032 2033 with localcontext() as c: 2034 # check that the value of the hash doesn't depend on the 2035 # current context (issue #1757) 2036 x = Decimal("123456789.1") 2037 2038 c.prec = 6 2039 h1 = hashit(x) 2040 c.prec = 10 2041 h2 = hashit(x) 2042 c.prec = 16 2043 h3 = hashit(x) 2044 2045 self.assertEqual(h1, h2) 2046 self.assertEqual(h1, h3) 2047 2048 c.prec = 10000 2049 x = 1100 ** 1248 2050 self.assertEqual(hashit(Decimal(x)), hashit(x)) 2051 2052 def test_min_and_max_methods(self): 2053 Decimal = self.decimal.Decimal 2054 2055 d1 = Decimal('15.32') 2056 d2 = Decimal('28.5') 2057 l1 = 15 2058 l2 = 28 2059 2060 #between Decimals 2061 self.assertTrue(min(d1,d2) is d1) 2062 self.assertTrue(min(d2,d1) is d1) 2063 self.assertTrue(max(d1,d2) is d2) 2064 self.assertTrue(max(d2,d1) is d2) 2065 2066 #between Decimal and long 2067 self.assertTrue(min(d1,l2) is d1) 2068 self.assertTrue(min(l2,d1) is d1) 2069 self.assertTrue(max(l1,d2) is d2) 2070 self.assertTrue(max(d2,l1) is d2) 2071 2072 def test_as_nonzero(self): 2073 Decimal = self.decimal.Decimal 2074 2075 #as false 2076 self.assertFalse(Decimal(0)) 2077 #as true 2078 self.assertTrue(Decimal('0.372')) 2079 2080 def test_tostring_methods(self): 2081 #Test str and repr methods. 2082 Decimal = self.decimal.Decimal 2083 2084 d = Decimal('15.32') 2085 self.assertEqual(str(d), '15.32') # str 2086 self.assertEqual(repr(d), "Decimal('15.32')") # repr 2087 2088 # result type of string methods should be str, not unicode 2089 unicode_inputs = [u'123.4', u'0.5E2', u'Infinity', u'sNaN', 2090 u'-0.0E100', u'-NaN001', u'-Inf'] 2091 2092 for u in unicode_inputs: 2093 d = Decimal(u) 2094 self.assertEqual(type(str(d)), str) 2095 self.assertEqual(type(repr(d)), str) 2096 self.assertEqual(type(d.to_eng_string()), str) 2097 2098 def test_tonum_methods(self): 2099 #Test float, int and long methods. 2100 Decimal = self.decimal.Decimal 2101 2102 d1 = Decimal('66') 2103 d2 = Decimal('15.32') 2104 2105 #int 2106 self.assertEqual(int(d1), 66) 2107 self.assertEqual(int(d2), 15) 2108 2109 #long 2110 self.assertEqual(long(d1), 66) 2111 self.assertEqual(long(d2), 15) 2112 2113 #float 2114 self.assertEqual(float(d1), 66) 2115 self.assertEqual(float(d2), 15.32) 2116 2117 def test_eval_round_trip(self): 2118 Decimal = self.decimal.Decimal 2119 2120 #with zero 2121 d = Decimal( (0, (0,), 0) ) 2122 self.assertEqual(d, eval(repr(d))) 2123 2124 #int 2125 d = Decimal( (1, (4, 5), 0) ) 2126 self.assertEqual(d, eval(repr(d))) 2127 2128 #float 2129 d = Decimal( (0, (4, 5, 3, 4), -2) ) 2130 self.assertEqual(d, eval(repr(d))) 2131 2132 #weird 2133 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) ) 2134 self.assertEqual(d, eval(repr(d))) 2135 2136 def test_as_tuple(self): 2137 Decimal = self.decimal.Decimal 2138 2139 #with zero 2140 d = Decimal(0) 2141 self.assertEqual(d.as_tuple(), (0, (0,), 0) ) 2142 2143 #int 2144 d = Decimal(-45) 2145 self.assertEqual(d.as_tuple(), (1, (4, 5), 0) ) 2146 2147 #complicated string 2148 d = Decimal("-4.34913534E-17") 2149 self.assertEqual(d.as_tuple(), (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) ) 2150 2151 # XXX non-compliant infinity payload. 2152 d = Decimal("Infinity") 2153 self.assertEqual(d.as_tuple(), (0, (0,), 'F') ) 2154 2155 #leading zeros in coefficient should be stripped 2156 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), -2) ) 2157 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), -2) ) 2158 d = Decimal( (1, (0, 0, 0), 37) ) 2159 self.assertEqual(d.as_tuple(), (1, (0,), 37)) 2160 d = Decimal( (1, (), 37) ) 2161 self.assertEqual(d.as_tuple(), (1, (0,), 37)) 2162 2163 #leading zeros in NaN diagnostic info should be stripped 2164 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), 'n') ) 2165 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), 'n') ) 2166 d = Decimal( (1, (0, 0, 0), 'N') ) 2167 self.assertEqual(d.as_tuple(), (1, (), 'N') ) 2168 d = Decimal( (1, (), 'n') ) 2169 self.assertEqual(d.as_tuple(), (1, (), 'n') ) 2170 2171 # XXX coefficient in infinity should raise an error 2172 if self.decimal == P: 2173 d = Decimal( (0, (4, 5, 3, 4), 'F') ) 2174 self.assertEqual(d.as_tuple(), (0, (0,), 'F')) 2175 d = Decimal( (1, (0, 2, 7, 1), 'F') ) 2176 self.assertEqual(d.as_tuple(), (1, (0,), 'F')) 2177 2178 def test_subclassing(self): 2179 # Different behaviours when subclassing Decimal 2180 Decimal = self.decimal.Decimal 2181 2182 class MyDecimal(Decimal): 2183 pass 2184 2185 d1 = MyDecimal(1) 2186 d2 = MyDecimal(2) 2187 d = d1 + d2 2188 self.assertTrue(type(d) is Decimal) 2189 2190 d = d1.max(d2) 2191 self.assertTrue(type(d) is Decimal) 2192 2193 d = copy.copy(d1) 2194 self.assertTrue(type(d) is MyDecimal) 2195 self.assertEqual(d, d1) 2196 2197 d = copy.deepcopy(d1) 2198 self.assertTrue(type(d) is MyDecimal) 2199 self.assertEqual(d, d1) 2200 2201 def test_implicit_context(self): 2202 Decimal = self.decimal.Decimal 2203 getcontext = self.decimal.getcontext 2204 2205 # Check results when context given implicitly. (Issue 2478) 2206 c = getcontext() 2207 self.assertEqual(str(Decimal(0).sqrt()), 2208 str(c.sqrt(Decimal(0)))) 2209 2210 def test_conversions_from_int(self): 2211 # Check that methods taking a second Decimal argument will 2212 # always accept an integer in place of a Decimal. 2213 Decimal = self.decimal.Decimal 2214 2215 self.assertEqual(Decimal(4).compare(3), 2216 Decimal(4).compare(Decimal(3))) 2217 self.assertEqual(Decimal(4).compare_signal(3), 2218 Decimal(4).compare_signal(Decimal(3))) 2219 self.assertEqual(Decimal(4).compare_total(3), 2220 Decimal(4).compare_total(Decimal(3))) 2221 self.assertEqual(Decimal(4).compare_total_mag(3), 2222 Decimal(4).compare_total_mag(Decimal(3))) 2223 self.assertEqual(Decimal(10101).logical_and(1001), 2224 Decimal(10101).logical_and(Decimal(1001))) 2225 self.assertEqual(Decimal(10101).logical_or(1001), 2226 Decimal(10101).logical_or(Decimal(1001))) 2227 self.assertEqual(Decimal(10101).logical_xor(1001), 2228 Decimal(10101).logical_xor(Decimal(1001))) 2229 self.assertEqual(Decimal(567).max(123), 2230 Decimal(567).max(Decimal(123))) 2231 self.assertEqual(Decimal(567).max_mag(123), 2232 Decimal(567).max_mag(Decimal(123))) 2233 self.assertEqual(Decimal(567).min(123), 2234 Decimal(567).min(Decimal(123))) 2235 self.assertEqual(Decimal(567).min_mag(123), 2236 Decimal(567).min_mag(Decimal(123))) 2237 self.assertEqual(Decimal(567).next_toward(123), 2238 Decimal(567).next_toward(Decimal(123))) 2239 self.assertEqual(Decimal(1234).quantize(100), 2240 Decimal(1234).quantize(Decimal(100))) 2241 self.assertEqual(Decimal(768).remainder_near(1234), 2242 Decimal(768).remainder_near(Decimal(1234))) 2243 self.assertEqual(Decimal(123).rotate(1), 2244 Decimal(123).rotate(Decimal(1))) 2245 self.assertEqual(Decimal(1234).same_quantum(1000), 2246 Decimal(1234).same_quantum(Decimal(1000))) 2247 self.assertEqual(Decimal('9.123').scaleb(-100), 2248 Decimal('9.123').scaleb(Decimal(-100))) 2249 self.assertEqual(Decimal(456).shift(-1), 2250 Decimal(456).shift(Decimal(-1))) 2251 2252 self.assertEqual(Decimal(-12).fma(Decimal(45), 67), 2253 Decimal(-12).fma(Decimal(45), Decimal(67))) 2254 self.assertEqual(Decimal(-12).fma(45, 67), 2255 Decimal(-12).fma(Decimal(45), Decimal(67))) 2256 self.assertEqual(Decimal(-12).fma(45, Decimal(67)), 2257 Decimal(-12).fma(Decimal(45), Decimal(67))) 2258 2259class CUsabilityTest(UsabilityTest): 2260 decimal = C 2261class PyUsabilityTest(UsabilityTest): 2262 decimal = P 2263 2264class PythonAPItests(unittest.TestCase): 2265 2266 def test_abc(self): 2267 Decimal = self.decimal.Decimal 2268 2269 self.assertTrue(issubclass(Decimal, numbers.Number)) 2270 self.assertTrue(not issubclass(Decimal, numbers.Real)) 2271 self.assertTrue(isinstance(Decimal(0), numbers.Number)) 2272 self.assertTrue(not isinstance(Decimal(0), numbers.Real)) 2273 2274 def test_pickle(self): 2275 Decimal = self.decimal.Decimal 2276 2277 # Round trip 2278 d = Decimal('-3.141590000') 2279 p = pickle.dumps(d) 2280 e = pickle.loads(p) 2281 self.assertEqual(d, e) 2282 2283 def test_int(self): 2284 Decimal = self.decimal.Decimal 2285 ROUND_DOWN = self.decimal.ROUND_DOWN 2286 2287 lim = 10 if hasattr(C, 'setfailpoint') else 250 2288 for x in range(-lim, lim): 2289 s = '%0.2f' % (x / 100.0) 2290 # should work the same as for floats 2291 self.assertEqual(int(Decimal(s)), int(float(s))) 2292 # should work the same as to_integral in the ROUND_DOWN mode 2293 d = Decimal(s) 2294 r = d.to_integral(ROUND_DOWN) 2295 self.assertEqual(Decimal(int(d)), r) 2296 2297 self.assertRaises(ValueError, int, Decimal('-nan')) 2298 self.assertRaises(ValueError, int, Decimal('snan')) 2299 self.assertRaises(OverflowError, int, Decimal('inf')) 2300 self.assertRaises(OverflowError, int, Decimal('-inf')) 2301 2302 self.assertRaises(ValueError, long, Decimal('-nan')) 2303 self.assertRaises(ValueError, long, Decimal('snan')) 2304 self.assertRaises(OverflowError, long, Decimal('inf')) 2305 self.assertRaises(OverflowError, long, Decimal('-inf')) 2306 2307 def test_trunc(self): 2308 Decimal = self.decimal.Decimal 2309 ROUND_DOWN = self.decimal.ROUND_DOWN 2310 2311 lim = 10 if hasattr(C, 'setfailpoint') else 250 2312 for x in range(-lim, lim): 2313 s = '%0.2f' % (x / 100.0) 2314 # should work the same as for floats 2315 self.assertEqual(int(Decimal(s)), int(float(s))) 2316 # should work the same as to_integral in the ROUND_DOWN mode 2317 d = Decimal(s) 2318 r = d.to_integral(ROUND_DOWN) 2319 self.assertEqual(Decimal(math.trunc(d)), r) 2320 2321 def test_from_float(self): 2322 if hasattr(C, 'setfailpoint'): 2323 random.seed(randseed) 2324 2325 Decimal = self.decimal.Decimal 2326 2327 class MyDecimal(Decimal): 2328 pass 2329 2330 self.assertTrue(issubclass(MyDecimal, Decimal)) 2331 2332 r = MyDecimal.from_float(0.1) 2333 self.assertEqual(type(r), MyDecimal) 2334 self.assertEqual(str(r), 2335 '0.1000000000000000055511151231257827021181583404541015625') 2336 bigint = 12345678901234567890123456789 2337 self.assertEqual(MyDecimal.from_float(bigint), MyDecimal(bigint)) 2338 self.assertTrue(MyDecimal.from_float(float('nan')).is_qnan()) 2339 self.assertTrue(MyDecimal.from_float(float('inf')).is_infinite()) 2340 self.assertTrue(MyDecimal.from_float(float('-inf')).is_infinite()) 2341 self.assertEqual(str(MyDecimal.from_float(float('nan'))), 2342 str(Decimal('NaN'))) 2343 self.assertEqual(str(MyDecimal.from_float(float('inf'))), 2344 str(Decimal('Infinity'))) 2345 self.assertEqual(str(MyDecimal.from_float(float('-inf'))), 2346 str(Decimal('-Infinity'))) 2347 self.assertRaises(TypeError, MyDecimal.from_float, 'abc') 2348 lim = 10 if hasattr(C, 'setfailpoint') else 200 2349 for i in range(lim): 2350 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0) 2351 self.assertEqual(x, float(MyDecimal.from_float(x))) # roundtrip 2352 2353 def test_create_decimal_from_float(self): 2354 Decimal = self.decimal.Decimal 2355 Context = self.decimal.Context 2356 ROUND_DOWN = self.decimal.ROUND_DOWN 2357 ROUND_UP = self.decimal.ROUND_UP 2358 Inexact = self.decimal.Inexact 2359 2360 context = Context(prec=5, rounding=ROUND_DOWN) 2361 self.assertEqual( 2362 context.create_decimal_from_float(math.pi), 2363 Decimal('3.1415') 2364 ) 2365 context = Context(prec=5, rounding=ROUND_UP) 2366 self.assertEqual( 2367 context.create_decimal_from_float(math.pi), 2368 Decimal('3.1416') 2369 ) 2370 context = Context(prec=5, traps=[Inexact]) 2371 self.assertRaises( 2372 Inexact, 2373 context.create_decimal_from_float, 2374 math.pi 2375 ) 2376 self.assertEqual(repr(context.create_decimal_from_float(-0.0)), 2377 "Decimal('-0')") 2378 self.assertEqual(repr(context.create_decimal_from_float(1.0)), 2379 "Decimal('1')") 2380 self.assertEqual(repr(context.create_decimal_from_float(10)), 2381 "Decimal('10')") 2382 2383 def test_quantize(self): 2384 Decimal = self.decimal.Decimal 2385 Context = self.decimal.Context 2386 InvalidOperation = self.decimal.InvalidOperation 2387 ROUND_DOWN = self.decimal.ROUND_DOWN 2388 2389 c = Context(Emax=99999, Emin=-99999) 2390 self.assertEqual( 2391 Decimal('7.335').quantize(Decimal('.01')), 2392 Decimal('7.34') 2393 ) 2394 self.assertEqual( 2395 Decimal('7.335').quantize(Decimal('.01'), rounding=ROUND_DOWN), 2396 Decimal('7.33') 2397 ) 2398 self.assertRaises( 2399 InvalidOperation, 2400 Decimal("10e99999").quantize, Decimal('1e100000'), context=c 2401 ) 2402 2403 c = Context() 2404 d = Decimal("0.871831e800") 2405 x = d.quantize(context=c, exp=Decimal("1e797"), rounding=ROUND_DOWN) 2406 self.assertEqual(x, Decimal('8.71E+799')) 2407 2408 def test_complex(self): 2409 Decimal = self.decimal.Decimal 2410 2411 x = Decimal("9.8182731e181273") 2412 self.assertEqual(x.real, x) 2413 self.assertEqual(x.imag, 0) 2414 self.assertEqual(x.conjugate(), x) 2415 2416 x = Decimal("1") 2417 self.assertEqual(complex(x), complex(float(1))) 2418 2419 self.assertRaises(AttributeError, setattr, x, 'real', 100) 2420 self.assertRaises(AttributeError, setattr, x, 'imag', 100) 2421 self.assertRaises(AttributeError, setattr, x, 'conjugate', 100) 2422 self.assertRaises(AttributeError, setattr, x, '__complex__', 100) 2423 2424class CPythonAPItests(PythonAPItests): 2425 decimal = C 2426class PyPythonAPItests(PythonAPItests): 2427 decimal = P 2428 2429class ContextAPItests(unittest.TestCase): 2430 2431 def test_pickle(self): 2432 Context = self.decimal.Context 2433 2434 c = Context() 2435 e = pickle.loads(pickle.dumps(c)) 2436 if self.decimal == C: 2437 self.assertEqual(c.prec, e.prec) 2438 self.assertEqual(c.Emin, e.Emin) 2439 self.assertEqual(c.Emax, e.Emax) 2440 self.assertEqual(c.rounding, e.rounding) 2441 self.assertEqual(c.capitals, e.capitals) 2442 self.assertEqual(c.traps, e.traps) 2443 self.assertEqual(c.flags, e.flags) 2444 self.assertEqual(c._clamp, e._clamp) 2445 else: 2446 for k in vars(c): 2447 v1 = vars(c)[k] 2448 v2 = vars(e)[k] 2449 self.assertEqual(v1, v2) 2450 2451 def test_equality_with_other_types(self): 2452 Decimal = self.decimal.Decimal 2453 2454 self.assertTrue(Decimal(10) in ['a', 1.0, Decimal(10), (1,2), {}]) 2455 self.assertTrue(Decimal(10) not in ['a', 1.0, (1,2), {}]) 2456 2457 def test_copy(self): 2458 # All copies should be deep 2459 Decimal = self.decimal.Decimal 2460 Context = self.decimal.Context 2461 2462 c = Context() 2463 d = c.copy() 2464 self.assertNotEqual(id(c), id(d)) 2465 self.assertNotEqual(id(c.flags), id(d.flags)) 2466 self.assertNotEqual(id(c.traps), id(d.traps)) 2467 k1 = set(c.flags.keys()) 2468 k2 = set(d.flags.keys()) 2469 self.assertEqual(k1, k2) 2470 self.assertEqual(c.flags, d.flags) 2471 2472 def test_abs(self): 2473 Decimal = self.decimal.Decimal 2474 Context = self.decimal.Context 2475 2476 c = Context() 2477 d = c.abs(Decimal(-1)) 2478 self.assertEqual(c.abs(-1), d) 2479 self.assertRaises(TypeError, c.abs, '-1') 2480 2481 def test_add(self): 2482 Decimal = self.decimal.Decimal 2483 Context = self.decimal.Context 2484 2485 c = Context() 2486 d = c.add(Decimal(1), Decimal(1)) 2487 self.assertEqual(c.add(1, 1), d) 2488 self.assertEqual(c.add(Decimal(1), 1), d) 2489 self.assertEqual(c.add(1, Decimal(1)), d) 2490 self.assertRaises(TypeError, c.add, '1', 1) 2491 self.assertRaises(TypeError, c.add, 1, '1') 2492 2493 def test_compare(self): 2494 Decimal = self.decimal.Decimal 2495 Context = self.decimal.Context 2496 2497 c = Context() 2498 d = c.compare(Decimal(1), Decimal(1)) 2499 self.assertEqual(c.compare(1, 1), d) 2500 self.assertEqual(c.compare(Decimal(1), 1), d) 2501 self.assertEqual(c.compare(1, Decimal(1)), d) 2502 self.assertRaises(TypeError, c.compare, '1', 1) 2503 self.assertRaises(TypeError, c.compare, 1, '1') 2504 2505 def test_compare_signal(self): 2506 Decimal = self.decimal.Decimal 2507 Context = self.decimal.Context 2508 2509 c = Context() 2510 d = c.compare_signal(Decimal(1), Decimal(1)) 2511 self.assertEqual(c.compare_signal(1, 1), d) 2512 self.assertEqual(c.compare_signal(Decimal(1), 1), d) 2513 self.assertEqual(c.compare_signal(1, Decimal(1)), d) 2514 self.assertRaises(TypeError, c.compare_signal, '1', 1) 2515 self.assertRaises(TypeError, c.compare_signal, 1, '1') 2516 2517 def test_compare_total(self): 2518 Decimal = self.decimal.Decimal 2519 Context = self.decimal.Context 2520 2521 c = Context() 2522 d = c.compare_total(Decimal(1), Decimal(1)) 2523 self.assertEqual(c.compare_total(1, 1), d) 2524 self.assertEqual(c.compare_total(Decimal(1), 1), d) 2525 self.assertEqual(c.compare_total(1, Decimal(1)), d) 2526 self.assertRaises(TypeError, c.compare_total, '1', 1) 2527 self.assertRaises(TypeError, c.compare_total, 1, '1') 2528 2529 def test_compare_total_mag(self): 2530 Decimal = self.decimal.Decimal 2531 Context = self.decimal.Context 2532 2533 c = Context() 2534 d = c.compare_total_mag(Decimal(1), Decimal(1)) 2535 self.assertEqual(c.compare_total_mag(1, 1), d) 2536 self.assertEqual(c.compare_total_mag(Decimal(1), 1), d) 2537 self.assertEqual(c.compare_total_mag(1, Decimal(1)), d) 2538 self.assertRaises(TypeError, c.compare_total_mag, '1', 1) 2539 self.assertRaises(TypeError, c.compare_total_mag, 1, '1') 2540 2541 def test_copy_abs(self): 2542 Decimal = self.decimal.Decimal 2543 Context = self.decimal.Context 2544 2545 c = Context() 2546 d = c.copy_abs(Decimal(-1)) 2547 self.assertEqual(c.copy_abs(-1), d) 2548 self.assertRaises(TypeError, c.copy_abs, '-1') 2549 2550 def test_copy_decimal(self): 2551 Decimal = self.decimal.Decimal 2552 Context = self.decimal.Context 2553 2554 c = Context() 2555 d = c.copy_decimal(Decimal(-1)) 2556 self.assertEqual(c.copy_decimal(-1), d) 2557 self.assertRaises(TypeError, c.copy_decimal, '-1') 2558 2559 def test_copy_negate(self): 2560 Decimal = self.decimal.Decimal 2561 Context = self.decimal.Context 2562 2563 c = Context() 2564 d = c.copy_negate(Decimal(-1)) 2565 self.assertEqual(c.copy_negate(-1), d) 2566 self.assertRaises(TypeError, c.copy_negate, '-1') 2567 2568 def test_copy_sign(self): 2569 Decimal = self.decimal.Decimal 2570 Context = self.decimal.Context 2571 2572 c = Context() 2573 d = c.copy_sign(Decimal(1), Decimal(-2)) 2574 self.assertEqual(c.copy_sign(1, -2), d) 2575 self.assertEqual(c.copy_sign(Decimal(1), -2), d) 2576 self.assertEqual(c.copy_sign(1, Decimal(-2)), d) 2577 self.assertRaises(TypeError, c.copy_sign, '1', -2) 2578 self.assertRaises(TypeError, c.copy_sign, 1, '-2') 2579 2580 def test_divide(self): 2581 Decimal = self.decimal.Decimal 2582 Context = self.decimal.Context 2583 2584 c = Context() 2585 d = c.divide(Decimal(1), Decimal(2)) 2586 self.assertEqual(c.divide(1, 2), d) 2587 self.assertEqual(c.divide(Decimal(1), 2), d) 2588 self.assertEqual(c.divide(1, Decimal(2)), d) 2589 self.assertRaises(TypeError, c.divide, '1', 2) 2590 self.assertRaises(TypeError, c.divide, 1, '2') 2591 2592 def test_divide_int(self): 2593 Decimal = self.decimal.Decimal 2594 Context = self.decimal.Context 2595 2596 c = Context() 2597 d = c.divide_int(Decimal(1), Decimal(2)) 2598 self.assertEqual(c.divide_int(1, 2), d) 2599 self.assertEqual(c.divide_int(Decimal(1), 2), d) 2600 self.assertEqual(c.divide_int(1, Decimal(2)), d) 2601 self.assertRaises(TypeError, c.divide_int, '1', 2) 2602 self.assertRaises(TypeError, c.divide_int, 1, '2') 2603 2604 def test_divmod(self): 2605 Decimal = self.decimal.Decimal 2606 Context = self.decimal.Context 2607 2608 c = Context() 2609 d = c.divmod(Decimal(1), Decimal(2)) 2610 self.assertEqual(c.divmod(1, 2), d) 2611 self.assertEqual(c.divmod(Decimal(1), 2), d) 2612 self.assertEqual(c.divmod(1, Decimal(2)), d) 2613 self.assertRaises(TypeError, c.divmod, '1', 2) 2614 self.assertRaises(TypeError, c.divmod, 1, '2') 2615 2616 def test_exp(self): 2617 Decimal = self.decimal.Decimal 2618 Context = self.decimal.Context 2619 2620 c = Context() 2621 d = c.exp(Decimal(10)) 2622 self.assertEqual(c.exp(10), d) 2623 self.assertRaises(TypeError, c.exp, '10') 2624 2625 def test_fma(self): 2626 Decimal = self.decimal.Decimal 2627 Context = self.decimal.Context 2628 2629 c = Context() 2630 d = c.fma(Decimal(2), Decimal(3), Decimal(4)) 2631 self.assertEqual(c.fma(2, 3, 4), d) 2632 self.assertEqual(c.fma(Decimal(2), 3, 4), d) 2633 self.assertEqual(c.fma(2, Decimal(3), 4), d) 2634 self.assertEqual(c.fma(2, 3, Decimal(4)), d) 2635 self.assertEqual(c.fma(Decimal(2), Decimal(3), 4), d) 2636 self.assertRaises(TypeError, c.fma, '2', 3, 4) 2637 self.assertRaises(TypeError, c.fma, 2, '3', 4) 2638 self.assertRaises(TypeError, c.fma, 2, 3, '4') 2639 2640 if self.decimal == C or py_minor >= 8: 2641 # Issue 12079 for Context.fma ... 2642 self.assertRaises(TypeError, c.fma, 2643 Decimal('Infinity'), Decimal(0), "not a decimal") 2644 self.assertRaises(TypeError, c.fma, 2645 Decimal(1), Decimal('snan'), 1.222) 2646 # ... and for Decimal.fma. 2647 self.assertRaises(TypeError, Decimal('Infinity').fma, 2648 Decimal(0), "not a decimal") 2649 self.assertRaises(TypeError, Decimal(1).fma, 2650 Decimal('snan'), 1.222) 2651 2652 def test_is_finite(self): 2653 Decimal = self.decimal.Decimal 2654 Context = self.decimal.Context 2655 2656 c = Context() 2657 d = c.is_finite(Decimal(10)) 2658 self.assertEqual(c.is_finite(10), d) 2659 self.assertRaises(TypeError, c.is_finite, '10') 2660 2661 def test_is_infinite(self): 2662 Decimal = self.decimal.Decimal 2663 Context = self.decimal.Context 2664 2665 c = Context() 2666 d = c.is_infinite(Decimal(10)) 2667 self.assertEqual(c.is_infinite(10), d) 2668 self.assertRaises(TypeError, c.is_infinite, '10') 2669 2670 def test_is_nan(self): 2671 Decimal = self.decimal.Decimal 2672 Context = self.decimal.Context 2673 2674 c = Context() 2675 d = c.is_nan(Decimal(10)) 2676 self.assertEqual(c.is_nan(10), d) 2677 self.assertRaises(TypeError, c.is_nan, '10') 2678 2679 def test_is_normal(self): 2680 Decimal = self.decimal.Decimal 2681 Context = self.decimal.Context 2682 2683 c = Context() 2684 d = c.is_normal(Decimal(10)) 2685 self.assertEqual(c.is_normal(10), d) 2686 self.assertRaises(TypeError, c.is_normal, '10') 2687 2688 def test_is_qnan(self): 2689 Decimal = self.decimal.Decimal 2690 Context = self.decimal.Context 2691 2692 c = Context() 2693 d = c.is_qnan(Decimal(10)) 2694 self.assertEqual(c.is_qnan(10), d) 2695 self.assertRaises(TypeError, c.is_qnan, '10') 2696 2697 def test_is_signed(self): 2698 Decimal = self.decimal.Decimal 2699 Context = self.decimal.Context 2700 2701 c = Context() 2702 d = c.is_signed(Decimal(10)) 2703 self.assertEqual(c.is_signed(10), d) 2704 self.assertRaises(TypeError, c.is_signed, '10') 2705 2706 def test_is_snan(self): 2707 Decimal = self.decimal.Decimal 2708 Context = self.decimal.Context 2709 2710 c = Context() 2711 d = c.is_snan(Decimal(10)) 2712 self.assertEqual(c.is_snan(10), d) 2713 self.assertRaises(TypeError, c.is_snan, '10') 2714 2715 def test_is_subnormal(self): 2716 Decimal = self.decimal.Decimal 2717 Context = self.decimal.Context 2718 2719 c = Context() 2720 d = c.is_subnormal(Decimal(10)) 2721 self.assertEqual(c.is_subnormal(10), d) 2722 self.assertRaises(TypeError, c.is_subnormal, '10') 2723 2724 def test_is_zero(self): 2725 Decimal = self.decimal.Decimal 2726 Context = self.decimal.Context 2727 2728 c = Context() 2729 d = c.is_zero(Decimal(10)) 2730 self.assertEqual(c.is_zero(10), d) 2731 self.assertRaises(TypeError, c.is_zero, '10') 2732 2733 def test_ln(self): 2734 Decimal = self.decimal.Decimal 2735 Context = self.decimal.Context 2736 2737 c = Context() 2738 d = c.ln(Decimal(10)) 2739 self.assertEqual(c.ln(10), d) 2740 self.assertRaises(TypeError, c.ln, '10') 2741 2742 def test_log10(self): 2743 Decimal = self.decimal.Decimal 2744 Context = self.decimal.Context 2745 2746 c = Context() 2747 d = c.log10(Decimal(10)) 2748 self.assertEqual(c.log10(10), d) 2749 self.assertRaises(TypeError, c.log10, '10') 2750 2751 def test_logb(self): 2752 Decimal = self.decimal.Decimal 2753 Context = self.decimal.Context 2754 2755 c = Context() 2756 d = c.logb(Decimal(10)) 2757 self.assertEqual(c.logb(10), d) 2758 self.assertRaises(TypeError, c.logb, '10') 2759 2760 def test_logical_and(self): 2761 Decimal = self.decimal.Decimal 2762 Context = self.decimal.Context 2763 2764 c = Context() 2765 d = c.logical_and(Decimal(1), Decimal(1)) 2766 self.assertEqual(c.logical_and(1, 1), d) 2767 self.assertEqual(c.logical_and(Decimal(1), 1), d) 2768 self.assertEqual(c.logical_and(1, Decimal(1)), d) 2769 self.assertRaises(TypeError, c.logical_and, '1', 1) 2770 self.assertRaises(TypeError, c.logical_and, 1, '1') 2771 2772 def test_logical_invert(self): 2773 Decimal = self.decimal.Decimal 2774 Context = self.decimal.Context 2775 2776 c = Context() 2777 d = c.logical_invert(Decimal(1000)) 2778 self.assertEqual(c.logical_invert(1000), d) 2779 self.assertRaises(TypeError, c.logical_invert, '1000') 2780 2781 def test_logical_or(self): 2782 Decimal = self.decimal.Decimal 2783 Context = self.decimal.Context 2784 2785 c = Context() 2786 d = c.logical_or(Decimal(1), Decimal(1)) 2787 self.assertEqual(c.logical_or(1, 1), d) 2788 self.assertEqual(c.logical_or(Decimal(1), 1), d) 2789 self.assertEqual(c.logical_or(1, Decimal(1)), d) 2790 self.assertRaises(TypeError, c.logical_or, '1', 1) 2791 self.assertRaises(TypeError, c.logical_or, 1, '1') 2792 2793 def test_logical_xor(self): 2794 Decimal = self.decimal.Decimal 2795 Context = self.decimal.Context 2796 2797 c = Context() 2798 d = c.logical_xor(Decimal(1), Decimal(1)) 2799 self.assertEqual(c.logical_xor(1, 1), d) 2800 self.assertEqual(c.logical_xor(Decimal(1), 1), d) 2801 self.assertEqual(c.logical_xor(1, Decimal(1)), d) 2802 self.assertRaises(TypeError, c.logical_xor, '1', 1) 2803 self.assertRaises(TypeError, c.logical_xor, 1, '1') 2804 2805 def test_max(self): 2806 Decimal = self.decimal.Decimal 2807 Context = self.decimal.Context 2808 2809 c = Context() 2810 d = c.max(Decimal(1), Decimal(2)) 2811 self.assertEqual(c.max(1, 2), d) 2812 self.assertEqual(c.max(Decimal(1), 2), d) 2813 self.assertEqual(c.max(1, Decimal(2)), d) 2814 self.assertRaises(TypeError, c.max, '1', 2) 2815 self.assertRaises(TypeError, c.max, 1, '2') 2816 2817 def test_max_mag(self): 2818 Decimal = self.decimal.Decimal 2819 Context = self.decimal.Context 2820 2821 c = Context() 2822 d = c.max_mag(Decimal(1), Decimal(2)) 2823 self.assertEqual(c.max_mag(1, 2), d) 2824 self.assertEqual(c.max_mag(Decimal(1), 2), d) 2825 self.assertEqual(c.max_mag(1, Decimal(2)), d) 2826 self.assertRaises(TypeError, c.max_mag, '1', 2) 2827 self.assertRaises(TypeError, c.max_mag, 1, '2') 2828 2829 def test_min(self): 2830 Decimal = self.decimal.Decimal 2831 Context = self.decimal.Context 2832 2833 c = Context() 2834 d = c.min(Decimal(1), Decimal(2)) 2835 self.assertEqual(c.min(1, 2), d) 2836 self.assertEqual(c.min(Decimal(1), 2), d) 2837 self.assertEqual(c.min(1, Decimal(2)), d) 2838 self.assertRaises(TypeError, c.min, '1', 2) 2839 self.assertRaises(TypeError, c.min, 1, '2') 2840 2841 def test_min_mag(self): 2842 Decimal = self.decimal.Decimal 2843 Context = self.decimal.Context 2844 2845 c = Context() 2846 d = c.min_mag(Decimal(1), Decimal(2)) 2847 self.assertEqual(c.min_mag(1, 2), d) 2848 self.assertEqual(c.min_mag(Decimal(1), 2), d) 2849 self.assertEqual(c.min_mag(1, Decimal(2)), d) 2850 self.assertRaises(TypeError, c.min_mag, '1', 2) 2851 self.assertRaises(TypeError, c.min_mag, 1, '2') 2852 2853 def test_minus(self): 2854 Decimal = self.decimal.Decimal 2855 Context = self.decimal.Context 2856 2857 c = Context() 2858 d = c.minus(Decimal(10)) 2859 self.assertEqual(c.minus(10), d) 2860 self.assertRaises(TypeError, c.minus, '10') 2861 2862 def test_multiply(self): 2863 Decimal = self.decimal.Decimal 2864 Context = self.decimal.Context 2865 2866 c = Context() 2867 d = c.multiply(Decimal(1), Decimal(2)) 2868 self.assertEqual(c.multiply(1, 2), d) 2869 self.assertEqual(c.multiply(Decimal(1), 2), d) 2870 self.assertEqual(c.multiply(1, Decimal(2)), d) 2871 self.assertRaises(TypeError, c.multiply, '1', 2) 2872 self.assertRaises(TypeError, c.multiply, 1, '2') 2873 2874 def test_next_minus(self): 2875 Decimal = self.decimal.Decimal 2876 Context = self.decimal.Context 2877 2878 c = Context() 2879 d = c.next_minus(Decimal(10)) 2880 self.assertEqual(c.next_minus(10), d) 2881 self.assertRaises(TypeError, c.next_minus, '10') 2882 2883 def test_next_plus(self): 2884 Decimal = self.decimal.Decimal 2885 Context = self.decimal.Context 2886 2887 c = Context() 2888 d = c.next_plus(Decimal(10)) 2889 self.assertEqual(c.next_plus(10), d) 2890 self.assertRaises(TypeError, c.next_plus, '10') 2891 2892 def test_next_toward(self): 2893 Decimal = self.decimal.Decimal 2894 Context = self.decimal.Context 2895 2896 c = Context() 2897 d = c.next_toward(Decimal(1), Decimal(2)) 2898 self.assertEqual(c.next_toward(1, 2), d) 2899 self.assertEqual(c.next_toward(Decimal(1), 2), d) 2900 self.assertEqual(c.next_toward(1, Decimal(2)), d) 2901 self.assertRaises(TypeError, c.next_toward, '1', 2) 2902 self.assertRaises(TypeError, c.next_toward, 1, '2') 2903 2904 def test_normalize(self): 2905 Decimal = self.decimal.Decimal 2906 Context = self.decimal.Context 2907 2908 c = Context() 2909 d = c.normalize(Decimal(10)) 2910 self.assertEqual(c.normalize(10), d) 2911 self.assertRaises(TypeError, c.normalize, '10') 2912 2913 def test_number_class(self): 2914 Decimal = self.decimal.Decimal 2915 Context = self.decimal.Context 2916 2917 c = Context() 2918 self.assertEqual(c.number_class(123), c.number_class(Decimal(123))) 2919 self.assertEqual(c.number_class(0), c.number_class(Decimal(0))) 2920 self.assertEqual(c.number_class(-45), c.number_class(Decimal(-45))) 2921 2922 def test_plus(self): 2923 Decimal = self.decimal.Decimal 2924 Context = self.decimal.Context 2925 2926 c = Context() 2927 d = c.plus(Decimal(10)) 2928 self.assertEqual(c.plus(10), d) 2929 self.assertRaises(TypeError, c.plus, '10') 2930 2931 def test_power(self): 2932 Decimal = self.decimal.Decimal 2933 Context = self.decimal.Context 2934 2935 c = Context() 2936 d = c.power(Decimal(1), Decimal(4)) 2937 self.assertEqual(c.power(1, 4), d) 2938 self.assertEqual(c.power(Decimal(1), 4), d) 2939 self.assertEqual(c.power(1, Decimal(4)), d) 2940 self.assertEqual(c.power(Decimal(1), Decimal(4)), d) 2941 self.assertRaises(TypeError, c.power, '1', 4) 2942 self.assertRaises(TypeError, c.power, 1, '4') 2943 2944 def test_quantize(self): 2945 Decimal = self.decimal.Decimal 2946 Context = self.decimal.Context 2947 2948 c = Context() 2949 d = c.quantize(Decimal(1), Decimal(2)) 2950 self.assertEqual(c.quantize(1, 2), d) 2951 self.assertEqual(c.quantize(Decimal(1), 2), d) 2952 self.assertEqual(c.quantize(1, Decimal(2)), d) 2953 self.assertRaises(TypeError, c.quantize, '1', 2) 2954 self.assertRaises(TypeError, c.quantize, 1, '2') 2955 2956 def test_remainder(self): 2957 Decimal = self.decimal.Decimal 2958 Context = self.decimal.Context 2959 2960 c = Context() 2961 d = c.remainder(Decimal(1), Decimal(2)) 2962 self.assertEqual(c.remainder(1, 2), d) 2963 self.assertEqual(c.remainder(Decimal(1), 2), d) 2964 self.assertEqual(c.remainder(1, Decimal(2)), d) 2965 self.assertRaises(TypeError, c.remainder, '1', 2) 2966 self.assertRaises(TypeError, c.remainder, 1, '2') 2967 2968 def test_remainder_near(self): 2969 Decimal = self.decimal.Decimal 2970 Context = self.decimal.Context 2971 2972 c = Context() 2973 d = c.remainder_near(Decimal(1), Decimal(2)) 2974 self.assertEqual(c.remainder_near(1, 2), d) 2975 self.assertEqual(c.remainder_near(Decimal(1), 2), d) 2976 self.assertEqual(c.remainder_near(1, Decimal(2)), d) 2977 self.assertRaises(TypeError, c.remainder_near, '1', 2) 2978 self.assertRaises(TypeError, c.remainder_near, 1, '2') 2979 2980 def test_rotate(self): 2981 Decimal = self.decimal.Decimal 2982 Context = self.decimal.Context 2983 2984 c = Context() 2985 d = c.rotate(Decimal(1), Decimal(2)) 2986 self.assertEqual(c.rotate(1, 2), d) 2987 self.assertEqual(c.rotate(Decimal(1), 2), d) 2988 self.assertEqual(c.rotate(1, Decimal(2)), d) 2989 self.assertRaises(TypeError, c.rotate, '1', 2) 2990 self.assertRaises(TypeError, c.rotate, 1, '2') 2991 2992 def test_sqrt(self): 2993 Decimal = self.decimal.Decimal 2994 Context = self.decimal.Context 2995 2996 c = Context() 2997 d = c.sqrt(Decimal(10)) 2998 self.assertEqual(c.sqrt(10), d) 2999 self.assertRaises(TypeError, c.sqrt, '10') 3000 3001 def test_same_quantum(self): 3002 Decimal = self.decimal.Decimal 3003 Context = self.decimal.Context 3004 3005 c = Context() 3006 d = c.same_quantum(Decimal(1), Decimal(2)) 3007 self.assertEqual(c.same_quantum(1, 2), d) 3008 self.assertEqual(c.same_quantum(Decimal(1), 2), d) 3009 self.assertEqual(c.same_quantum(1, Decimal(2)), d) 3010 self.assertRaises(TypeError, c.same_quantum, '1', 2) 3011 self.assertRaises(TypeError, c.same_quantum, 1, '2') 3012 3013 def test_scaleb(self): 3014 Decimal = self.decimal.Decimal 3015 Context = self.decimal.Context 3016 3017 c = Context() 3018 d = c.scaleb(Decimal(1), Decimal(2)) 3019 self.assertEqual(c.scaleb(1, 2), d) 3020 self.assertEqual(c.scaleb(Decimal(1), 2), d) 3021 self.assertEqual(c.scaleb(1, Decimal(2)), d) 3022 self.assertRaises(TypeError, c.scaleb, '1', 2) 3023 self.assertRaises(TypeError, c.scaleb, 1, '2') 3024 3025 def test_shift(self): 3026 Decimal = self.decimal.Decimal 3027 Context = self.decimal.Context 3028 3029 c = Context() 3030 d = c.shift(Decimal(1), Decimal(2)) 3031 self.assertEqual(c.shift(1, 2), d) 3032 self.assertEqual(c.shift(Decimal(1), 2), d) 3033 self.assertEqual(c.shift(1, Decimal(2)), d) 3034 self.assertRaises(TypeError, c.shift, '1', 2) 3035 self.assertRaises(TypeError, c.shift, 1, '2') 3036 3037 def test_subtract(self): 3038 Decimal = self.decimal.Decimal 3039 Context = self.decimal.Context 3040 3041 c = Context() 3042 d = c.subtract(Decimal(1), Decimal(2)) 3043 self.assertEqual(c.subtract(1, 2), d) 3044 self.assertEqual(c.subtract(Decimal(1), 2), d) 3045 self.assertEqual(c.subtract(1, Decimal(2)), d) 3046 self.assertRaises(TypeError, c.subtract, '1', 2) 3047 self.assertRaises(TypeError, c.subtract, 1, '2') 3048 3049 def test_to_eng_string(self): 3050 Decimal = self.decimal.Decimal 3051 Context = self.decimal.Context 3052 3053 c = Context() 3054 d = c.to_eng_string(Decimal(10)) 3055 self.assertEqual(c.to_eng_string(10), d) 3056 self.assertRaises(TypeError, c.to_eng_string, '10') 3057 3058 def test_to_sci_string(self): 3059 Decimal = self.decimal.Decimal 3060 Context = self.decimal.Context 3061 3062 c = Context() 3063 d = c.to_sci_string(Decimal(10)) 3064 self.assertEqual(c.to_sci_string(10), d) 3065 self.assertRaises(TypeError, c.to_sci_string, '10') 3066 3067 def test_to_integral_exact(self): 3068 Decimal = self.decimal.Decimal 3069 Context = self.decimal.Context 3070 3071 c = Context() 3072 d = c.to_integral_exact(Decimal(10)) 3073 self.assertEqual(c.to_integral_exact(10), d) 3074 self.assertRaises(TypeError, c.to_integral_exact, '10') 3075 3076 def test_to_integral_value(self): 3077 Decimal = self.decimal.Decimal 3078 Context = self.decimal.Context 3079 3080 c = Context() 3081 d = c.to_integral_value(Decimal(10)) 3082 self.assertEqual(c.to_integral_value(10), d) 3083 self.assertRaises(TypeError, c.to_integral_value, '10') 3084 self.assertRaises(TypeError, c.to_integral_value, 10, 'x') 3085 3086class CContextAPItests(ContextAPItests): 3087 decimal = C 3088if py_minor >= 7: 3089 class PyContextAPItests(ContextAPItests): 3090 decimal = P 3091else: 3092 class PyContextAPItests(unittest.TestCase): 3093 pass 3094 3095class ContextWithStatement(unittest.TestCase): 3096 # Can't do these as docstrings until Python 2.6 3097 # as doctest can't handle __future__ statements 3098 3099 def test_localcontext(self): 3100 # Use a copy of the current context in the block 3101 getcontext = self.decimal.getcontext 3102 localcontext = self.decimal.localcontext 3103 3104 orig_ctx = getcontext() 3105 with localcontext() as enter_ctx: 3106 set_ctx = getcontext() 3107 final_ctx = getcontext() 3108 self.assertTrue(orig_ctx is final_ctx, 'did not restore context correctly') 3109 self.assertTrue(orig_ctx is not set_ctx, 'did not copy the context') 3110 self.assertTrue(set_ctx is enter_ctx, '__enter__ returned wrong context') 3111 3112 def test_localcontextarg(self): 3113 # Use a copy of the supplied context in the block 3114 Context = self.decimal.Context 3115 getcontext = self.decimal.getcontext 3116 localcontext = self.decimal.localcontext 3117 3118 localcontext = self.decimal.localcontext 3119 orig_ctx = getcontext() 3120 new_ctx = Context(prec=42) 3121 with localcontext(new_ctx) as enter_ctx: 3122 set_ctx = getcontext() 3123 final_ctx = getcontext() 3124 self.assertTrue(orig_ctx is final_ctx, 'did not restore context correctly') 3125 self.assertTrue(set_ctx.prec == new_ctx.prec, 'did not set correct context') 3126 self.assertTrue(new_ctx is not set_ctx, 'did not copy the context') 3127 self.assertTrue(set_ctx is enter_ctx, '__enter__ returned wrong context') 3128 3129 def test_nested_with_statements(self): 3130 # Use a copy of the supplied context in the block 3131 Decimal = self.decimal.Decimal 3132 Context = self.decimal.Context 3133 getcontext = self.decimal.getcontext 3134 localcontext = self.decimal.localcontext 3135 Clamped = self.decimal.Clamped 3136 Overflow = self.decimal.Overflow 3137 3138 orig_ctx = getcontext() 3139 orig_ctx.clear_flags() 3140 new_ctx = Context(Emax=384) 3141 with localcontext() as c1: 3142 self.assertEqual(c1.flags, orig_ctx.flags) 3143 self.assertEqual(c1.traps, orig_ctx.traps) 3144 c1.traps[Clamped] = True 3145 c1.Emin = -383 3146 self.assertNotEqual(orig_ctx.Emin, -383) 3147 self.assertRaises(Clamped, c1.create_decimal, '0e-999') 3148 self.assertTrue(c1.flags[Clamped]) 3149 with localcontext(new_ctx) as c2: 3150 self.assertEqual(c2.flags, new_ctx.flags) 3151 self.assertEqual(c2.traps, new_ctx.traps) 3152 self.assertRaises(Overflow, c2.power, Decimal('3.4e200'), 2) 3153 self.assertFalse(c2.flags[Clamped]) 3154 self.assertTrue(c2.flags[Overflow]) 3155 del c2 3156 self.assertFalse(c1.flags[Overflow]) 3157 del c1 3158 self.assertNotEqual(orig_ctx.Emin, -383) 3159 self.assertFalse(orig_ctx.flags[Clamped]) 3160 self.assertFalse(orig_ctx.flags[Overflow]) 3161 self.assertFalse(new_ctx.flags[Clamped]) 3162 self.assertFalse(new_ctx.flags[Overflow]) 3163 3164 def test_with_statements_gc1(self): 3165 localcontext = self.decimal.localcontext 3166 3167 with localcontext() as c1: 3168 del c1 3169 with localcontext() as c2: 3170 del c2 3171 with localcontext() as c3: 3172 del c3 3173 with localcontext() as c4: 3174 del c4 3175 3176 def test_with_statements_gc2(self): 3177 localcontext = self.decimal.localcontext 3178 3179 with localcontext() as c1: 3180 with localcontext(c1) as c2: 3181 del c1 3182 with localcontext(c2) as c3: 3183 del c2 3184 with localcontext(c3) as c4: 3185 del c3 3186 del c4 3187 3188 def test_with_statements_gc3(self): 3189 Context = self.decimal.Context 3190 localcontext = self.decimal.localcontext 3191 getcontext = self.decimal.getcontext 3192 setcontext = self.decimal.setcontext 3193 3194 with localcontext() as c1: 3195 del c1 3196 n1 = Context(prec=1) 3197 setcontext(n1) 3198 with localcontext(n1) as c2: 3199 del n1 3200 self.assertEqual(c2.prec, 1) 3201 del c2 3202 n2 = Context(prec=2) 3203 setcontext(n2) 3204 del n2 3205 self.assertEqual(getcontext().prec, 2) 3206 n3 = Context(prec=3) 3207 setcontext(n3) 3208 self.assertEqual(getcontext().prec, 3) 3209 with localcontext(n3) as c3: 3210 del n3 3211 self.assertEqual(c3.prec, 3) 3212 del c3 3213 n4 = Context(prec=4) 3214 setcontext(n4) 3215 del n4 3216 self.assertEqual(getcontext().prec, 4) 3217 with localcontext() as c4: 3218 self.assertEqual(c4.prec, 4) 3219 del c4 3220 3221class CContextWithStatement(ContextWithStatement): 3222 decimal = C 3223class PyContextWithStatement(ContextWithStatement): 3224 decimal = P 3225 3226class ContextFlags(unittest.TestCase): 3227 def test_flags_irrelevant(self): 3228 # check that the result (numeric result + flags raised) of an 3229 # arithmetic operation doesn't depend on the current flags 3230 Decimal = self.decimal.Decimal 3231 Context = self.decimal.Context 3232 Inexact = self.decimal.Inexact 3233 Rounded = self.decimal.Rounded 3234 Underflow = self.decimal.Underflow 3235 Clamped = self.decimal.Clamped 3236 Subnormal = self.decimal.Subnormal 3237 ROUND_HALF_EVEN = self.decimal.ROUND_HALF_EVEN 3238 3239 def raise_error(context, flag): 3240 if self.decimal == C: 3241 context.flags[flag] = True 3242 if context.traps[flag]: 3243 raise flag 3244 else: 3245 context._raise_error(flag) 3246 3247 context = Context(prec=9, Emin = -425000000, Emax = 425000000, 3248 rounding=ROUND_HALF_EVEN, traps=[], flags=[]) 3249 3250 # operations that raise various flags, in the form (function, arglist) 3251 operations = [ 3252 (context._apply, [Decimal("100E-425000010")]), 3253 (context.sqrt, [Decimal(2)]), 3254 (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]), 3255 (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]), 3256 (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]), 3257 ] 3258 3259 # try various flags individually, then a whole lot at once 3260 flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal], 3261 [Inexact, Rounded, Underflow, Clamped, Subnormal]] 3262 3263 for fn, args in operations: 3264 # find answer and flags raised using a clean context 3265 context.clear_flags() 3266 ans = fn(*args) 3267 flags = [k for k, v in context.flags.items() if v] 3268 3269 for extra_flags in flagsets: 3270 # set flags, before calling operation 3271 context.clear_flags() 3272 for flag in extra_flags: 3273 raise_error(context, flag) 3274 new_ans = fn(*args) 3275 3276 # flags that we expect to be set after the operation 3277 expected_flags = list(flags) 3278 for flag in extra_flags: 3279 if flag not in expected_flags: 3280 expected_flags.append(flag) 3281 expected_flags.sort(key=id) 3282 3283 # flags we actually got 3284 new_flags = [k for k,v in context.flags.items() if v] 3285 new_flags.sort(key=id) 3286 3287 self.assertEqual(ans, new_ans, 3288 "operation produces different answers depending on flags set: " + 3289 "expected %s, got %s." % (ans, new_ans)) 3290 self.assertEqual(new_flags, expected_flags, 3291 "operation raises different flags depending on flags set: " + 3292 "expected %s, got %s" % (expected_flags, new_flags)) 3293 3294class CContextFlags(ContextFlags): 3295 decimal = C 3296class PyContextFlags(ContextFlags): 3297 decimal = P 3298 3299class SpecialContexts(unittest.TestCase): 3300 """Test the context templates.""" 3301 3302 def test_context_templates(self): 3303 BasicContext = self.decimal.BasicContext 3304 ExtendedContext = self.decimal.ExtendedContext 3305 getcontext = self.decimal.getcontext 3306 setcontext = self.decimal.setcontext 3307 InvalidOperation = self.decimal.InvalidOperation 3308 DivisionByZero = self.decimal.DivisionByZero 3309 Overflow = self.decimal.Overflow 3310 Underflow = self.decimal.Underflow 3311 Clamped = self.decimal.Clamped 3312 3313 assert_signals(self, BasicContext, 'traps', 3314 [InvalidOperation, DivisionByZero, Overflow, Underflow, Clamped] 3315 ) 3316 3317 savecontext = getcontext().copy() 3318 basic_context_prec = BasicContext.prec 3319 extended_context_prec = ExtendedContext.prec 3320 3321 ex = None 3322 try: 3323 BasicContext.prec = ExtendedContext.prec = 441 3324 for template in BasicContext, ExtendedContext: 3325 setcontext(template) 3326 c = getcontext() 3327 self.assertFalse(c is template) 3328 self.assertEqual(c.prec, 441) 3329 except Exception as e: 3330 ex = e.__class__ 3331 finally: 3332 with protectfail(): 3333 BasicContext.prec = basic_context_prec 3334 ExtendedContext.prec = extended_context_prec 3335 setcontext(savecontext) 3336 if ex: 3337 raise ex 3338 3339 def test_default_context(self): 3340 DefaultContext = self.decimal.DefaultContext 3341 BasicContext = self.decimal.BasicContext 3342 ExtendedContext = self.decimal.ExtendedContext 3343 getcontext = self.decimal.getcontext 3344 setcontext = self.decimal.setcontext 3345 InvalidOperation = self.decimal.InvalidOperation 3346 DivisionByZero = self.decimal.DivisionByZero 3347 Overflow = self.decimal.Overflow 3348 3349 self.assertEqual(BasicContext.prec, 9) 3350 self.assertEqual(ExtendedContext.prec, 9) 3351 3352 assert_signals(self, DefaultContext, 'traps', 3353 [InvalidOperation, DivisionByZero, Overflow] 3354 ) 3355 3356 savecontext = getcontext().copy() 3357 default_context_prec = DefaultContext.prec 3358 3359 ex = None 3360 try: 3361 c = getcontext() 3362 saveprec = c.prec 3363 3364 DefaultContext.prec = 961 3365 c = getcontext() 3366 self.assertEqual(c.prec, saveprec) 3367 3368 setcontext(DefaultContext) 3369 c = getcontext() 3370 self.assertFalse(c is DefaultContext) 3371 self.assertEqual(c.prec, 961) 3372 except Exception as e: 3373 ex = e.__class__ 3374 finally: 3375 with protectfail(): 3376 DefaultContext.prec = default_context_prec 3377 setcontext(savecontext) 3378 if ex: 3379 raise ex 3380 3381class CSpecialContexts(SpecialContexts): 3382 decimal = C 3383class PySpecialContexts(SpecialContexts): 3384 decimal = P 3385 3386class ContextInputValidation(unittest.TestCase): 3387 3388 def test_invalid_context(self): 3389 Context = self.decimal.Context 3390 DefaultContext = self.decimal.DefaultContext 3391 3392 c = DefaultContext.copy() 3393 3394 # prec, Emax 3395 for attr in ['prec', 'Emax']: 3396 setattr(c, attr, 999999) 3397 self.assertEqual(getattr(c, attr), 999999) 3398 self.assertRaises(ValueError, setattr, c, attr, -1) 3399 self.assertRaises(TypeError, setattr, c, attr, 'xyz') 3400 3401 # Emin 3402 setattr(c, 'Emin', -999999) 3403 self.assertEqual(getattr(c, 'Emin'), -999999) 3404 self.assertRaises(ValueError, setattr, c, 'Emin', 1) 3405 self.assertRaises(TypeError, setattr, c, 'Emin', (1,2,3)) 3406 3407 # rounding: always raise TypeError in order to get consistent 3408 # exceptions across implementations. In decimal, rounding 3409 # modes are strings, in _decimal they are integers. The idea 3410 # is to view rounding as an abstract type and not mind the 3411 # implementation details. 3412 # Hence, a user should view the rounding modes as if they 3413 # had been defined in a language that supports abstract 3414 # data types, e.g. ocaml: 3415 # 3416 # type rounding = ROUND_DOWN | ROUND_HALF_UP | ... ;; 3417 # 3418 self.assertRaises(TypeError, setattr, c, 'rounding', -1) 3419 self.assertRaises(TypeError, setattr, c, 'rounding', 9) 3420 self.assertRaises(TypeError, setattr, c, 'rounding', 1.0) 3421 self.assertRaises(TypeError, setattr, c, 'rounding', 'xyz') 3422 3423 # capitals, clamp 3424 for attr in ['capitals', 'clamp']: 3425 self.assertRaises(ValueError, setattr, c, attr, -1) 3426 self.assertRaises(ValueError, setattr, c, attr, 2) 3427 self.assertRaises(TypeError, setattr, c, attr, [1,2,3]) 3428 3429 # Invalid attribute 3430 self.assertRaises(AttributeError, setattr, c, 'emax', 100) 3431 3432 # Invalid signal dict 3433 self.assertRaises(TypeError, setattr, c, 'flags', []) 3434 self.assertRaises(TypeError, setattr, c, 'flags', {}) 3435 self.assertRaises(TypeError, setattr, c, 'traps', 3436 {'InvalidOperation':0}) 3437 3438 # Attributes cannot be deleted 3439 for attr in ['prec', 'Emax', 'Emin', 'rounding', 'capitals', 'clamp', 3440 'flags', 'traps']: 3441 self.assertRaises(AttributeError, c.__delattr__, attr) 3442 3443 # Invalid attributes 3444 self.assertRaises(TypeError, getattr, c, 9) 3445 self.assertRaises(TypeError, setattr, c, 9) 3446 3447 # Invalid values in constructor 3448 self.assertRaises(TypeError, Context, rounding=999999) 3449 self.assertRaises(TypeError, Context, rounding='xyz') 3450 self.assertRaises(ValueError, Context, clamp=2) 3451 self.assertRaises(ValueError, Context, capitals=-1) 3452 self.assertRaises(TypeError, Context, flags=["P"]) 3453 self.assertRaises(TypeError, Context, traps=["Q"]) 3454 3455 # Type error in conversion 3456 self.assertRaises(TypeError, Context, flags=(0,1)) 3457 self.assertRaises(TypeError, Context, traps=(1,0)) 3458 3459class CContextInputValidation(ContextInputValidation): 3460 decimal = C 3461class PyContextInputValidation(unittest.TestCase): 3462 # No context input validation in decimal.py 3463 pass 3464 3465class Coverage(unittest.TestCase): 3466 3467 def test_adjusted(self): 3468 Decimal = self.decimal.Decimal 3469 3470 self.assertEqual(Decimal('1234e9999').adjusted(), 10002) 3471 # XXX raise? 3472 self.assertEqual(Decimal('nan').adjusted(), 0) 3473 self.assertEqual(Decimal('inf').adjusted(), 0) 3474 3475 def test_canonical(self): 3476 Decimal = self.decimal.Decimal 3477 getcontext = self.decimal.getcontext 3478 3479 x = Decimal(9).canonical() 3480 self.assertEqual(x, 9) 3481 3482 c = getcontext() 3483 x = c.canonical(Decimal(9)) 3484 self.assertEqual(x, 9) 3485 3486 def test_context_repr(self): 3487 c = self.decimal.DefaultContext.copy() 3488 3489 if py_minor <= 8 and self.decimal == P: 3490 raise unittest.SkipTest("requires Python 3.2") 3491 3492 c.prec = 425000000 3493 c.Emax = 425000000 3494 c.Emin = -425000000 3495 c.rounding = self.decimal.ROUND_HALF_DOWN 3496 c.capitals = 0 3497 c.clamp = 1 3498 for sig in OrderedSignals[self.decimal]: 3499 c.flags[sig] = False 3500 c.traps[sig] = False 3501 3502 s = c.__repr__() 3503 t = "Context(prec=425000000, rounding=ROUND_HALF_DOWN, " \ 3504 "Emin=-425000000, Emax=425000000, capitals=0, clamp=1, " \ 3505 "flags=[], traps=[])" 3506 self.assertEqual(s, t) 3507 3508 def test_implicit_context(self): 3509 Decimal = self.decimal.Decimal 3510 localcontext = self.decimal.localcontext 3511 3512 with localcontext() as c: 3513 c.prec = 1 3514 c.Emax = 1 3515 c.Emin = -1 3516 3517 # abs 3518 self.assertEqual(abs(Decimal("-10")), 10) 3519 # add 3520 self.assertEqual(Decimal("7") + 1, 8) 3521 # divide 3522 self.assertEqual(Decimal("10") / 5, 2) 3523 # divide_int 3524 self.assertEqual(Decimal("10") // 7, 1) 3525 # fma 3526 self.assertEqual(Decimal("1.2").fma(Decimal("0.01"), 1), 1) 3527 self.assertTrue(Decimal("NaN").fma(7, 1).is_nan() is True) 3528 # three arg power 3529 self.assertEqual(pow(Decimal(10), 2, 7), 2) 3530 # exp 3531 self.assertEqual(Decimal("1.01").exp(), 3) 3532 # is_normal 3533 self.assertTrue(Decimal("0.01").is_normal() is False) 3534 # is_subnormal 3535 self.assertTrue(Decimal("0.01").is_subnormal() is True) 3536 # ln 3537 self.assertEqual(Decimal("20").ln(), 3) 3538 # log10 3539 self.assertEqual(Decimal("20").log10(), 1) 3540 # logb 3541 self.assertEqual(Decimal("580").logb(), 2) 3542 # logical_invert 3543 self.assertEqual(Decimal("10").logical_invert(), 1) 3544 # minus 3545 self.assertEqual(-Decimal("-10"), 10) 3546 # multiply 3547 self.assertEqual(Decimal("2") * 4, 8) 3548 # next_minus 3549 self.assertEqual(Decimal("10").next_minus(), 9) 3550 # next_plus 3551 self.assertEqual(Decimal("10").next_plus(), Decimal('2E+1')) 3552 # normalize 3553 self.assertEqual(Decimal("-10").normalize(), Decimal('-1E+1')) 3554 # number_class 3555 self.assertEqual(Decimal("10").number_class(), '+Normal') 3556 # plus 3557 self.assertEqual(+Decimal("-1"), -1) 3558 # remainder 3559 self.assertEqual(Decimal("10") % 7, 3) 3560 # subtract 3561 self.assertEqual(Decimal("10") - 7, 3) 3562 # to_integral_exact 3563 self.assertEqual(Decimal("1.12345").to_integral_exact(), 1) 3564 3565 # Boolean functions 3566 self.assertTrue(Decimal("1").is_canonical()) 3567 self.assertTrue(Decimal("1").is_finite()) 3568 self.assertTrue(Decimal("1").is_finite()) 3569 self.assertTrue(Decimal("snan").is_snan()) 3570 self.assertTrue(Decimal("-1").is_signed()) 3571 self.assertTrue(Decimal("0").is_zero()) 3572 self.assertTrue(Decimal("0").is_zero()) 3573 3574 # Copy 3575 with localcontext() as c: 3576 c.prec = 10000 3577 x = 1228 ** 1523 3578 y = -Decimal(x) 3579 3580 z = y.copy_abs() 3581 self.assertEqual(z, x) 3582 3583 z = y.copy_negate() 3584 self.assertEqual(z, x) 3585 3586 z = y.copy_sign(Decimal(1)) 3587 self.assertEqual(z, x) 3588 3589 def test_divmod(self): 3590 Decimal = self.decimal.Decimal 3591 localcontext = self.decimal.localcontext 3592 InvalidOperation = self.decimal.InvalidOperation 3593 DivisionByZero = self.decimal.DivisionByZero 3594 3595 with localcontext() as c: 3596 q, r = divmod(Decimal("10912837129"), 1001) 3597 self.assertEqual(q, Decimal('10901935')) 3598 self.assertEqual(r, Decimal('194')) 3599 3600 q, r = divmod(Decimal("NaN"), 7) 3601 self.assertTrue(q.is_nan() and r.is_nan()) 3602 3603 c.traps[InvalidOperation] = False 3604 q, r = divmod(Decimal("NaN"), 7) 3605 self.assertTrue(q.is_nan() and r.is_nan()) 3606 3607 c.traps[InvalidOperation] = False 3608 c.clear_flags() 3609 q, r = divmod(Decimal("inf"), Decimal("inf")) 3610 self.assertTrue(q.is_nan() and r.is_nan()) 3611 self.assertTrue(c.flags[InvalidOperation]) 3612 3613 c.clear_flags() 3614 q, r = divmod(Decimal("inf"), 101) 3615 self.assertTrue(q.is_infinite() and r.is_nan()) 3616 self.assertTrue(c.flags[InvalidOperation]) 3617 3618 c.clear_flags() 3619 q, r = divmod(Decimal(0), 0) 3620 self.assertTrue(q.is_nan() and r.is_nan()) 3621 self.assertTrue(c.flags[InvalidOperation]) 3622 3623 c.traps[DivisionByZero] = False 3624 c.clear_flags() 3625 q, r = divmod(Decimal(11), 0) 3626 self.assertTrue(q.is_infinite() and r.is_nan()) 3627 self.assertTrue(c.flags[InvalidOperation] and 3628 c.flags[DivisionByZero]) 3629 3630 def test_power(self): 3631 Decimal = self.decimal.Decimal 3632 localcontext = self.decimal.localcontext 3633 Overflow = self.decimal.Overflow 3634 Rounded = self.decimal.Rounded 3635 3636 with localcontext() as c: 3637 c.prec = 3 3638 c.clear_flags() 3639 self.assertEqual(Decimal("1.0") ** 100, Decimal('1.00')) 3640 self.assertTrue(c.flags[Rounded]) 3641 3642 c.prec = 1 3643 c.Emax = 1 3644 c.Emin = -1 3645 c.clear_flags() 3646 c.traps[Overflow] = False 3647 self.assertEqual(Decimal(10000) ** Decimal("0.5"), Decimal('inf')) 3648 self.assertTrue(c.flags[Overflow]) 3649 3650 def test_quantize(self): 3651 Decimal = self.decimal.Decimal 3652 localcontext = self.decimal.localcontext 3653 InvalidOperation = self.decimal.InvalidOperation 3654 3655 with localcontext() as c: 3656 c.prec = 1 3657 c.Emax = 1 3658 c.Emin = -1 3659 c.traps[InvalidOperation] = False 3660 x = Decimal(99).quantize(Decimal("1e1")) 3661 self.assertTrue(x.is_nan()) 3662 3663 def test_radix(self): 3664 Decimal = self.decimal.Decimal 3665 getcontext = self.decimal.getcontext 3666 3667 c = getcontext() 3668 self.assertEqual(Decimal("1").radix(), 10) 3669 self.assertEqual(c.radix(), 10) 3670 3671 def test_rop(self): 3672 Decimal = self.decimal.Decimal 3673 3674 for attr in ('__radd__', '__rsub__', '__rmul__', '__rtruediv__', 3675 '__rdivmod__', '__rmod__', '__rfloordiv__', '__rpow__'): 3676 self.assertTrue(getattr(Decimal("1"), attr)("xyz") is NotImplemented) 3677 3678 def test_round(self): 3679 # Python3 behavior: round() returns Decimal 3680 Decimal = self.decimal.Decimal 3681 getcontext = self.decimal.getcontext 3682 3683 if self.decimal == P: 3684 return 3685 3686 c = getcontext() 3687 c.prec = 28 3688 3689 self.assertEqual(str(Decimal("9.99").__round__()), "10") 3690 self.assertEqual(str(Decimal("9.99e-5").__round__()), "0") 3691 self.assertEqual(str(Decimal("1.23456789").__round__(5)), "1.23457") 3692 self.assertEqual(str(Decimal("1.2345").__round__(10)), "1.2345000000") 3693 self.assertEqual(str(Decimal("1.2345").__round__(-10)), "0E+10") 3694 3695 self.assertRaises(TypeError, Decimal("1.23").__round__, "5") 3696 self.assertRaises(TypeError, Decimal("1.23").__round__, 5, 8) 3697 3698 def test_create_decimal(self): 3699 c = self.decimal.Context() 3700 self.assertRaises(ValueError, c.create_decimal, ["%"]) 3701 3702 def test_int(self): 3703 Decimal = self.decimal.Decimal 3704 localcontext = self.decimal.localcontext 3705 3706 with localcontext() as c: 3707 c.prec = 9999 3708 x = Decimal(1221**1271) / 10**3923 3709 self.assertEqual(int(x), 1) 3710 self.assertEqual(x.to_integral(), 2) 3711 3712 def test_long(self): 3713 Decimal = self.decimal.Decimal 3714 DefaultContext = self.decimal.DefaultContext 3715 3716 c = DefaultContext.copy() 3717 3718 x = Decimal(28) * 28L 3719 self.assertEqual(str(x), '784') 3720 3721 x = c.multiply(Decimal(101), 101L) 3722 self.assertEqual(str(x), '10201') 3723 3724 def test_copy(self): 3725 Context = self.decimal.Context 3726 3727 if py_minor <= 1 and self.decimal == P: 3728 raise unittest.SkipTest("requires Python 3.2") 3729 3730 c = Context() 3731 c.prec = 10000 3732 x = -(1172 ** 1712) 3733 3734 y = c.copy_abs(x) 3735 self.assertEqual(y, -x) 3736 3737 y = c.copy_negate(x) 3738 self.assertEqual(y, -x) 3739 3740 y = c.copy_sign(x, 1) 3741 self.assertEqual(y, -x) 3742 3743class CCoverage(Coverage): 3744 decimal = C 3745class PyCoverage(Coverage): 3746 decimal = P 3747 3748class PyFunctionality(unittest.TestCase): 3749 """Extra functionality in decimal.py""" 3750 3751 def test_py_quantize_watchexp(self): 3752 # watchexp functionality 3753 Decimal = P.Decimal 3754 localcontext = P.localcontext 3755 3756 with localcontext() as c: 3757 c.prec = 1 3758 c.Emax = 1 3759 c.Emin = -1 3760 x = Decimal(99999).quantize(Decimal("1e3"), watchexp=False) 3761 self.assertEqual(x, Decimal('1.00E+5')) 3762 3763class PyWhitebox(unittest.TestCase): 3764 """White box testing for decimal.py""" 3765 3766 def test_py_exact_power(self): 3767 # Rarely exercised lines in _power_exact. 3768 Decimal = P.Decimal 3769 localcontext = P.localcontext 3770 3771 with localcontext() as c: 3772 c.prec = 8 3773 x = Decimal(2**16) ** Decimal("-0.5") 3774 self.assertEqual(x, Decimal('0.00390625')) 3775 3776 x = Decimal(2**16) ** Decimal("-0.6") 3777 self.assertEqual(x, Decimal('0.0012885819')) 3778 3779 x = Decimal("256e7") ** Decimal("-0.5") 3780 3781 x = Decimal(152587890625) ** Decimal('-0.0625') 3782 self.assertEqual(x, Decimal("0.2")) 3783 3784 x = Decimal("152587890625e7") ** Decimal('-0.0625') 3785 3786 x = Decimal(5**2659) ** Decimal('-0.0625') 3787 3788 c.prec = 1 3789 x = Decimal("152587890625") ** Decimal('-0.5') 3790 c.prec = 201 3791 x = Decimal(2**578) ** Decimal("-0.5") 3792 3793 def test_py_immutability_operations(self): 3794 # Do operations and check that it didn't change change internal objects. 3795 Decimal = P.Decimal 3796 DefaultContext = P.DefaultContext 3797 setcontext = P.setcontext 3798 3799 c = DefaultContext.copy() 3800 c.traps = dict((s, 0) for s in OrderedSignals[P]) 3801 setcontext(c) 3802 3803 d1 = Decimal('-25e55') 3804 b1 = Decimal('-25e55') 3805 d2 = Decimal('33e+33') 3806 b2 = Decimal('33e+33') 3807 3808 def checkSameDec(operation, useOther=False): 3809 if useOther: 3810 eval("d1." + operation + "(d2)") 3811 self.assertEqual(d1._sign, b1._sign) 3812 self.assertEqual(d1._int, b1._int) 3813 self.assertEqual(d1._exp, b1._exp) 3814 self.assertEqual(d2._sign, b2._sign) 3815 self.assertEqual(d2._int, b2._int) 3816 self.assertEqual(d2._exp, b2._exp) 3817 else: 3818 eval("d1." + operation + "()") 3819 self.assertEqual(d1._sign, b1._sign) 3820 self.assertEqual(d1._int, b1._int) 3821 self.assertEqual(d1._exp, b1._exp) 3822 return 3823 3824 Decimal(d1) 3825 self.assertEqual(d1._sign, b1._sign) 3826 self.assertEqual(d1._int, b1._int) 3827 self.assertEqual(d1._exp, b1._exp) 3828 3829 checkSameDec("__abs__") 3830 checkSameDec("__add__", True) 3831 checkSameDec("__div__", True) 3832 checkSameDec("__divmod__", True) 3833 checkSameDec("__eq__", True) 3834 checkSameDec("__ne__", True) 3835 checkSameDec("__le__", True) 3836 checkSameDec("__lt__", True) 3837 checkSameDec("__ge__", True) 3838 checkSameDec("__gt__", True) 3839 checkSameDec("__float__") 3840 checkSameDec("__floordiv__", True) 3841 checkSameDec("__hash__") 3842 checkSameDec("__int__") 3843 checkSameDec("__trunc__") 3844 checkSameDec("__long__") 3845 checkSameDec("__mod__", True) 3846 checkSameDec("__mul__", True) 3847 checkSameDec("__neg__") 3848 checkSameDec("__nonzero__") 3849 checkSameDec("__pos__") 3850 checkSameDec("__pow__", True) 3851 checkSameDec("__radd__", True) 3852 checkSameDec("__rdiv__", True) 3853 checkSameDec("__rdivmod__", True) 3854 checkSameDec("__repr__") 3855 checkSameDec("__rfloordiv__", True) 3856 checkSameDec("__rmod__", True) 3857 checkSameDec("__rmul__", True) 3858 checkSameDec("__rpow__", True) 3859 checkSameDec("__rsub__", True) 3860 checkSameDec("__str__") 3861 checkSameDec("__sub__", True) 3862 checkSameDec("__truediv__", True) 3863 checkSameDec("adjusted") 3864 checkSameDec("as_tuple") 3865 checkSameDec("compare", True) 3866 checkSameDec("max", True) 3867 checkSameDec("min", True) 3868 checkSameDec("normalize") 3869 checkSameDec("quantize", True) 3870 checkSameDec("remainder_near", True) 3871 checkSameDec("same_quantum", True) 3872 checkSameDec("sqrt") 3873 checkSameDec("to_eng_string") 3874 checkSameDec("to_integral") 3875 3876 def test_py_decimal_id(self): 3877 Decimal = P.Decimal 3878 3879 d = Decimal(45) 3880 e = Decimal(d) 3881 self.assertEqual(str(e), '45') 3882 self.assertNotEqual(id(d), id(e)) 3883 3884 def test_py_rescale(self): 3885 # Coverage 3886 Decimal = P.Decimal 3887 ROUND_UP = P.ROUND_UP 3888 localcontext = P.localcontext 3889 3890 with localcontext() as c: 3891 x = Decimal("NaN")._rescale(3, ROUND_UP) 3892 self.assertTrue(x.is_nan()) 3893 3894 def test_py__round(self): 3895 # Coverage 3896 Decimal = P.Decimal 3897 ROUND_UP = P.ROUND_UP 3898 3899 self.assertRaises(ValueError, Decimal("3.1234")._round, 0, ROUND_UP) 3900 3901class CFunctionality(unittest.TestCase): 3902 """Extra functionality in _decimal""" 3903 3904 def test_c_ieee_context(self): 3905 # issue 8786: Add support for IEEE 754 contexts to decimal module. 3906 IEEEContext = C.IEEEContext 3907 DECIMAL32 = C.DECIMAL32 3908 DECIMAL64 = C.DECIMAL64 3909 DECIMAL128 = C.DECIMAL128 3910 3911 def assert_rest(self, context): 3912 self.assertEqual(context.clamp, 1) 3913 assert_signals(self, context, 'traps', []) 3914 assert_signals(self, context, 'flags', []) 3915 3916 c = IEEEContext(DECIMAL32) 3917 self.assertEqual(c.prec, 7) 3918 self.assertEqual(c.Emax, 96) 3919 self.assertEqual(c.Emin, -95) 3920 assert_rest(self, c) 3921 3922 c = IEEEContext(DECIMAL64) 3923 self.assertEqual(c.prec, 16) 3924 self.assertEqual(c.Emax, 384) 3925 self.assertEqual(c.Emin, -383) 3926 assert_rest(self, c) 3927 3928 c = IEEEContext(DECIMAL128) 3929 self.assertEqual(c.prec, 34) 3930 self.assertEqual(c.Emax, 6144) 3931 self.assertEqual(c.Emin, -6143) 3932 assert_rest(self, c) 3933 3934 # Invalid values 3935 self.assertRaises(OverflowError, IEEEContext, 2**63) 3936 self.assertRaises(ValueError, IEEEContext, -1) 3937 self.assertRaises(ValueError, IEEEContext, 1024) 3938 3939 def test_apply(self): 3940 # Decimal("9.9999999").apply() applies the current context. 3941 Decimal = C.Decimal 3942 localcontext = C.localcontext 3943 3944 with localcontext() as c: 3945 c.prec = 5 3946 c.Emax = 99999 3947 c.Emin = -99999 3948 3949 d = c.copy() 3950 d.prec = 4 3951 3952 x = Decimal("123456") 3953 self.assertEqual(str(x.apply()), "1.2346E+5") 3954 self.assertEqual(str(c.apply(x)), "1.2346E+5") 3955 3956 self.assertEqual(str(x.apply(d)), "1.235E+5") 3957 self.assertEqual(str(d.apply(x)), "1.235E+5") 3958 3959 self.assertRaises(TypeError, x.apply, "p") 3960 self.assertRaises(TypeError, x.apply, "p", "q") 3961 self.assertRaises(TypeError, c.apply, "p") 3962 3963 x = Decimal(1171**2221) 3964 self.assertEqual(str(x.apply()), "1.8402E+6815") 3965 self.assertEqual(str(c.apply(x)), "1.8402E+6815") 3966 self.assertEqual(str(d.apply(x)), "1.840E+6815") 3967 3968 def test_c_float_operation_default(self): 3969 Decimal = C.Decimal 3970 Context = C.Context 3971 Inexact = C.Inexact 3972 DecInexact = C.DecInexact 3973 FloatOperation= C.FloatOperation 3974 DecFloatOperation= C.DecFloatOperation 3975 3976 context = Context() 3977 self.assertFalse(context.flags[FloatOperation]) 3978 self.assertFalse(context.traps[FloatOperation]) 3979 self.assertFalse(context._flags&DecFloatOperation) 3980 self.assertFalse(context._traps&DecFloatOperation) 3981 3982 context.settraps([Inexact, FloatOperation]) 3983 self.assertEqual(context._traps, DecInexact|DecFloatOperation) 3984 self.assertTrue(context.traps[FloatOperation]) 3985 self.assertTrue(context.traps[Inexact]) 3986 3987 def test_c_powmod(self): 3988 Decimal = C.Decimal 3989 Context = C.Context 3990 3991 c = Context() 3992 d = c.powmod(Decimal(1), Decimal(4), Decimal(2)) 3993 self.assertEqual(c.powmod(1, 4, 2), d) 3994 self.assertEqual(c.powmod(Decimal(1), 4, 2), d) 3995 self.assertEqual(c.powmod(1, Decimal(4), 2), d) 3996 self.assertEqual(c.powmod(1, 4, Decimal(2)), d) 3997 self.assertEqual(c.powmod(Decimal(1), Decimal(4), 2), d) 3998 self.assertRaises(TypeError, c.powmod, '1', 4, 2) 3999 self.assertRaises(TypeError, c.powmod, 1, '4', 2) 4000 self.assertRaises(TypeError, c.powmod, 1, 4, '2') 4001 4002 def test_c_context(self): 4003 Context = C.Context 4004 4005 c = Context(flags=C.DecClamped, traps=C.DecRounded) 4006 self.assertEqual(c._flags, C.DecClamped) 4007 self.assertEqual(c._traps, C.DecRounded) 4008 4009 def test_sundry(self): 4010 Decimal = C.Decimal 4011 4012 # mpd_isinteger 4013 self.assertTrue(Decimal("1.234e5").is_integer()) 4014 self.assertTrue(Decimal("snan").is_special()) 4015 4016 # Extra functions 4017 self.assertEqual(Decimal(-1).abs(), 1) 4018 self.assertEqual(Decimal(1).minus(), -1) 4019 self.assertEqual(Decimal(1).plus(), 1) 4020 self.assertEqual(Decimal(1).add(1), 2) 4021 self.assertEqual(Decimal(12).div(2), 6) 4022 self.assertEqual(Decimal(10).divint(7), 1) 4023 self.assertEqual(Decimal(10).mul(12), 120) 4024 self.assertEqual(Decimal(10).rem(7), 3) 4025 self.assertEqual(Decimal(10).sub(7), 3) 4026 self.assertEqual(Decimal(10).divmod(7), (1, 3)) 4027 4028 def test_constants(self): 4029 # Condition flags 4030 cond = ( 4031 C.DecClamped, C.DecConversionSyntax, C.DecDivisionByZero, 4032 C.DecDivisionImpossible, C.DecDivisionUndefined, 4033 C.DecFpuError, C.DecInexact, C.DecInvalidContext, 4034 C.DecInvalidOperation, C.DecMallocError, 4035 C.DecFloatOperation, C.DecOverflow, C.DecRounded, 4036 C.DecSubnormal, C.DecUnderflow 4037 ) 4038 4039 # Architecture dependent context limits 4040 if C.MAX_EMAX > 425000000: 4041 self.assertEqual(C.MAX_PREC, 999999999999999999) 4042 self.assertEqual(C.MAX_EMAX, 999999999999999999) 4043 self.assertEqual(C.MIN_EMIN, -999999999999999999) 4044 self.assertEqual(C.MIN_ETINY, -1999999999999999997) 4045 else: 4046 self.assertEqual(C.MAX_PREC, 425000000) 4047 self.assertEqual(C.MAX_EMAX, 425000000) 4048 self.assertEqual(C.MIN_EMIN, -425000000) 4049 self.assertEqual(C.MIN_ETINY, -849999999) 4050 4051 # IEEEContext 4052 self.assertEqual(C.DECIMAL32, 32) 4053 self.assertEqual(C.DECIMAL64, 64) 4054 self.assertEqual(C.DECIMAL128, 128) 4055 self.assertEqual(C.IEEE_CONTEXT_MAX_BITS, 512) 4056 4057 # Rounding modes 4058 for i, v in enumerate(RoundingModes[C]): 4059 self.assertEqual(v, i) 4060 self.assertEqual(C.ROUND_TRUNC, 8) 4061 4062 # Conditions 4063 for i, v in enumerate(cond): 4064 self.assertEqual(v, 1<<i) 4065 4066 self.assertEqual(C.DecIEEEInvalidOperation, 4067 C.DecConversionSyntax| 4068 C.DecDivisionImpossible| 4069 C.DecDivisionUndefined| 4070 C.DecFpuError| 4071 C.DecInvalidContext| 4072 C.DecInvalidOperation| 4073 C.DecMallocError) 4074 4075 self.assertEqual(C.DecErrors, 4076 C.DecIEEEInvalidOperation| 4077 C.DecDivisionByZero) 4078 4079 self.assertEqual(C.DecTraps, 4080 C.DecErrors|C.DecOverflow|C.DecUnderflow) 4081 4082class CWhitebox(unittest.TestCase): 4083 """Whitebox testing for _decimal""" 4084 4085 def test_bignum(self): 4086 # Not exactly whitebox, but too slow with pydecimal. 4087 if hasattr(C, 'setfailpoint'): 4088 random.seed(randseed) 4089 4090 Decimal = C.Decimal 4091 localcontext = C.localcontext 4092 4093 b1 = 10**35 4094 b2 = 10**36 4095 with localcontext() as c: 4096 c.prec = 1000000 4097 r = 1 if hasattr(C, 'setfailpoint') else 5 4098 for i in range(r): 4099 a = random.randrange(b1, b2) 4100 b = random.randrange(1000, 1200) 4101 x = a ** b 4102 y = Decimal(a) ** Decimal(b) 4103 self.assertEqual(x, y) 4104 4105 def test_c_input_restriction(self): 4106 # Too large for _decimal to be converted exactly 4107 Decimal = C.Decimal 4108 InvalidOperation = C.InvalidOperation 4109 Context = C.Context 4110 localcontext = C.localcontext 4111 4112 with localcontext(Context()): 4113 self.assertRaises(InvalidOperation, Decimal, 4114 "1e9999999999999999999") 4115 self.assertRaises(InvalidOperation, Decimal, 4116 u"1e9999999999999999999") 4117 4118 def test_c_context_repr(self): 4119 # This test is _decimal-only because flags are not printed 4120 # in the same order. 4121 DefaultContext = C.DefaultContext 4122 FloatOperation = C.FloatOperation 4123 ROUND_HALF_DOWN = C.ROUND_HALF_DOWN 4124 4125 c = DefaultContext.copy() 4126 4127 c.prec = 425000000 4128 c.Emax = 425000000 4129 c.Emin = -425000000 4130 c.rounding = ROUND_HALF_DOWN 4131 c.capitals = 0 4132 c.clamp = 1 4133 for sig in OrderedSignals[C]: 4134 c.flags[sig] = True 4135 c.traps[sig] = True 4136 c.flags[FloatOperation] = True 4137 c.traps[FloatOperation] = True 4138 4139 s = c.__repr__() 4140 t = "Context(prec=425000000, rounding=ROUND_HALF_DOWN, " \ 4141 "Emin=-425000000, Emax=425000000, capitals=0, clamp=1, " \ 4142 "flags=[Clamped, InvalidOperation, DivisionByZero, Inexact, " \ 4143 "FloatOperation, Overflow, Rounded, Subnormal, Underflow], " \ 4144 "traps=[Clamped, InvalidOperation, DivisionByZero, Inexact, " \ 4145 "FloatOperation, Overflow, Rounded, Subnormal, Underflow])" 4146 self.assertEqual(s, t) 4147 4148 def test_c_context_errors(self): 4149 Context = C.Context 4150 InvalidOperation = C.InvalidOperation 4151 Overflow = C.Overflow 4152 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000) 4153 4154 c = Context() 4155 4156 # SignalDict: input validation 4157 self.assertRaises(TypeError, c.flags.__setitem__, 801, 0) 4158 self.assertRaises(TypeError, c.traps.__setitem__, 801, 0) 4159 self.assertRaises(ValueError, c.flags.__delitem__, Overflow) 4160 self.assertRaises(ValueError, c.traps.__delitem__, InvalidOperation) 4161 self.assertRaises(TypeError, setattr, c, 'flags', ['x']) 4162 self.assertRaises(TypeError, setattr, c,'traps', ['y']) 4163 self.assertRaises(TypeError, setattr, c, 'flags', {0:1}) 4164 self.assertRaises(TypeError, setattr, c, 'traps', {0:1}) 4165 4166 self.assertRaises(TypeError, c.setflags, ['x']) 4167 self.assertRaises(TypeError, c.settraps, ['y']) 4168 self.assertRaises(TypeError, c.setflags, 'x') 4169 self.assertRaises(TypeError, c.settraps, 'y') 4170 4171 # Input corner cases 4172 int_max = 2**63-1 if HAVE_CONFIG_64 else 2**31-1 4173 gt_max_emax = 10**18 if HAVE_CONFIG_64 else 10**9 4174 4175 # prec, Emax, Emin 4176 for attr in ['prec', 'Emax']: 4177 self.assertRaises(ValueError, setattr, c, attr, gt_max_emax) 4178 self.assertRaises(ValueError, setattr, c, 'Emin', -gt_max_emax) 4179 4180 # prec, Emax, Emin in context constructor 4181 self.assertRaises(ValueError, Context, prec=gt_max_emax) 4182 self.assertRaises(ValueError, Context, Emax=gt_max_emax) 4183 self.assertRaises(ValueError, Context, Emin=-gt_max_emax) 4184 4185 # Overflow in conversion 4186 self.assertRaises(OverflowError, Context, prec=int_max+1) 4187 self.assertRaises(OverflowError, Context, Emax=int_max+1) 4188 self.assertRaises(OverflowError, Context, Emin=-int_max-2) 4189 self.assertRaises(OverflowError, Context, rounding=int_max+1) 4190 self.assertRaises(OverflowError, Context, clamp=int_max+1) 4191 self.assertRaises(OverflowError, Context, capitals=int_max+1) 4192 self.assertRaises(OverflowError, Context, _allcr=int_max+1) 4193 4194 # OverflowError, general ValueError 4195 for attr in ('prec', 'Emin', 'Emax', 'capitals', 'clamp', '_allcr'): 4196 self.assertRaises(OverflowError, setattr, c, attr, int_max+1) 4197 self.assertRaises(OverflowError, setattr, c, attr, -int_max-2) 4198 if sys.platform != 'win32': 4199 self.assertRaises(ValueError, setattr, c, attr, int_max) 4200 self.assertRaises(ValueError, setattr, c, attr, -int_max-1) 4201 4202 # OverflowError, general TypeError 4203 for attr in ('rounding', '_flags', '_traps'): 4204 self.assertRaises(OverflowError, setattr, c, attr, int_max+1) 4205 self.assertRaises(OverflowError, setattr, c, attr, -int_max-2) 4206 if sys.platform != 'win32': 4207 self.assertRaises(TypeError, setattr, c, attr, int_max) 4208 self.assertRaises(TypeError, setattr, c, attr, -int_max-1) 4209 4210 # OverflowError: unsafe_prec, unsafe_emin, unsafe_emax 4211 self.assertRaises(OverflowError, getattr(c, 'unsafe_setprec'), int_max+1) 4212 self.assertRaises(OverflowError, getattr(c, 'unsafe_setemax'), int_max+1) 4213 self.assertRaises(OverflowError, getattr(c, 'unsafe_setemin'), -int_max-2) 4214 4215 # capitals, clamp, _allcr 4216 for attr in ['capitals', 'clamp', '_allcr']: 4217 self.assertRaises(ValueError, setattr, c, attr, -1) 4218 self.assertRaises(ValueError, setattr, c, attr, 2) 4219 self.assertRaises(TypeError, setattr, c, attr, [1,2,3]) 4220 if HAVE_CONFIG_64: 4221 self.assertRaises(ValueError, setattr, c, attr, 2**32) 4222 self.assertRaises(ValueError, setattr, c, attr, 2**32+1) 4223 4224 self.assertRaises(ValueError, Context, _allcr=2) 4225 4226 # _flags, _traps 4227 for attr in ['_flags', '_traps']: 4228 self.assertRaises(TypeError, setattr, c, attr, 999999) 4229 self.assertRaises(TypeError, setattr, c, attr, 'x') 4230 4231 def test_c_valid_context(self): 4232 # These tests are for code coverage in _decimal. 4233 DefaultContext = C.DefaultContext 4234 ROUND_HALF_UP = C.ROUND_HALF_UP 4235 Clamped = C.Clamped 4236 Underflow = C.Underflow 4237 Inexact = C.Inexact 4238 Rounded = C.Rounded 4239 Subnormal = C.Subnormal 4240 DecClamped = C.DecClamped 4241 DecUnderflow = C.DecUnderflow 4242 DecInexact = C.DecInexact 4243 DecRounded = C.DecRounded 4244 DecSubnormal = C.DecSubnormal 4245 4246 c = DefaultContext.copy() 4247 4248 # Exercise all getters and setters 4249 c.prec = 34 4250 c.rounding = ROUND_HALF_UP 4251 c.Emax = 3000 4252 c.Emin = -3000 4253 c.capitals = 1 4254 c.clamp = 0 4255 c._flags = DecUnderflow 4256 c._traps = DecClamped 4257 c._allcr = 0 4258 4259 self.assertEqual(c.prec, 34) 4260 self.assertEqual(c.rounding, ROUND_HALF_UP) 4261 self.assertEqual(c.Emin, -3000) 4262 self.assertEqual(c.Emax, 3000) 4263 self.assertEqual(c.capitals, 1) 4264 self.assertEqual(c.clamp, 0) 4265 self.assertEqual(c._flags, DecUnderflow) 4266 self.assertEqual(c._traps, DecClamped) 4267 self.assertEqual(c._allcr, 0) 4268 4269 self.assertEqual(c.Etiny(), -3033) 4270 self.assertEqual(c.Etop(), 2967) 4271 4272 # Set traps/flags from list 4273 c.settraps([Clamped, Underflow]) 4274 self.assertEqual(c._traps, DecClamped|DecUnderflow) 4275 4276 c.setflags([Inexact, Rounded, Subnormal]) 4277 self.assertEqual(c._flags, DecInexact|DecRounded|DecSubnormal) 4278 4279 # Exercise all unsafe setters 4280 c.unsafe_setprec(999999999) 4281 c.unsafe_setemax(999999999) 4282 c.unsafe_setemin(-999999999) 4283 4284 self.assertEqual(c.prec, 999999999) 4285 self.assertEqual(c.Emax, 999999999) 4286 self.assertEqual(c.Emin, -999999999) 4287 4288 def test_c_round(self): 4289 # Restricted input. 4290 Decimal = C.Decimal 4291 InvalidOperation = C.InvalidOperation 4292 localcontext = C.localcontext 4293 MAX_EMAX = C.MAX_EMAX 4294 MIN_ETINY = C.MIN_ETINY 4295 int_max = 2**63-1 if C.MAX_PREC > 425000000 else 2**31-1 4296 4297 with localcontext() as c: 4298 c.traps[InvalidOperation] = True 4299 self.assertRaises(InvalidOperation, Decimal("1.23").__round__, 4300 -int_max-1) 4301 self.assertRaises(InvalidOperation, Decimal("1.23").__round__, 4302 int_max) 4303 self.assertRaises(InvalidOperation, Decimal("1").__round__, 4304 int(MAX_EMAX+1)) 4305 self.assertRaises(C.InvalidOperation, Decimal("1").__round__, 4306 -int(MIN_ETINY-1)) 4307 self.assertRaises(OverflowError, Decimal("1.23").__round__, 4308 -int_max-2) 4309 self.assertRaises(OverflowError, Decimal("1.23").__round__, 4310 int_max+1) 4311 4312 def test_c_format(self): 4313 # Restricted input 4314 Decimal = C.Decimal 4315 InvalidOperation = C.InvalidOperation 4316 Rounded = C.Rounded 4317 localcontext = C.localcontext 4318 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000) 4319 4320 self.assertRaises(TypeError, Decimal(1).__format__, "=10.10", [], 9) 4321 self.assertRaises(TypeError, Decimal(1).__format__, "=10.10", 9) 4322 self.assertRaises(TypeError, Decimal(1).__format__, []) 4323 4324 with localcontext() as c: 4325 c.traps[InvalidOperation] = True 4326 c.traps[Rounded] = True 4327 self.assertRaises(ValueError, Decimal(1).__format__, u"<>=10.10") 4328 maxsize = 2**63-1 if HAVE_CONFIG_64 else 2**31-1 4329 self.assertRaises(InvalidOperation, Decimal("1.23456789").__format__, 4330 u"=%d.1" % maxsize) 4331 4332 def test_c_integral(self): 4333 Decimal = C.Decimal 4334 Inexact = C.Inexact 4335 ROUND_UP = C.ROUND_UP 4336 localcontext = C.localcontext 4337 4338 x = Decimal(10) 4339 self.assertEqual(x.to_integral(), 10) 4340 self.assertRaises(TypeError, x.to_integral, '10') 4341 self.assertRaises(TypeError, x.to_integral, 10, 'x') 4342 self.assertRaises(TypeError, x.to_integral, 10) 4343 4344 self.assertEqual(x.to_integral_value(), 10) 4345 self.assertRaises(TypeError, x.to_integral_value, '10') 4346 self.assertRaises(TypeError, x.to_integral_value, 10, 'x') 4347 self.assertRaises(TypeError, x.to_integral_value, 10) 4348 4349 self.assertEqual(x.to_integral_exact(), 10) 4350 self.assertRaises(TypeError, x.to_integral_exact, '10') 4351 self.assertRaises(TypeError, x.to_integral_exact, 10, 'x') 4352 self.assertRaises(TypeError, x.to_integral_exact, 10) 4353 4354 with localcontext() as c: 4355 x = Decimal("99999999999999999999999999.9").to_integral_value(ROUND_UP) 4356 self.assertEqual(x, Decimal('100000000000000000000000000')) 4357 4358 x = Decimal("99999999999999999999999999.9").to_integral_exact(ROUND_UP) 4359 self.assertEqual(x, Decimal('100000000000000000000000000')) 4360 4361 c.traps[Inexact] = True 4362 self.assertRaises(Inexact, Decimal("999.9").to_integral_exact, ROUND_UP) 4363 4364 def test_c_funcs(self): 4365 # Invalid arguments 4366 Decimal = C.Decimal 4367 InvalidOperation = C.InvalidOperation 4368 DivisionByZero = C.DivisionByZero 4369 ROUND_UP = C.ROUND_UP 4370 getcontext = C.getcontext 4371 localcontext = C.localcontext 4372 4373 self.assertEqual(Decimal('9.99e10').to_sci_string(), '9.99E+10') 4374 self.assertEqual(Decimal('9.99e10').to_eng_string(), '99.9E+9') 4375 4376 self.assertRaises(TypeError, pow, Decimal(1), 2, "3") 4377 self.assertRaises(TypeError, Decimal(9).number_class, "x", "y") 4378 self.assertRaises(TypeError, Decimal(9).divmod, 8, "x", "y") 4379 self.assertRaises(TypeError, Decimal(9).same_quantum, 3, "x", "y") 4380 self.assertRaises(TypeError, Decimal(9).to_sci, 3, "x", "y") 4381 self.assertRaises(TypeError, Decimal(9).to_eng, 3, "x", "y") 4382 4383 self.assertEqual(Decimal("1.234e2007").sign(), 1) 4384 self.assertEqual(Decimal("-1.234e2007").sign(), -1) 4385 4386 self.assertRaises( 4387 TypeError, 4388 Decimal("1.23456789").quantize, Decimal('1e-100000'), [] 4389 ) 4390 self.assertRaises( 4391 TypeError, 4392 Decimal("1.23456789").quantize, Decimal('1e-100000'), getcontext() 4393 ) 4394 self.assertRaises( 4395 TypeError, 4396 Decimal("1.23456789").quantize, Decimal('1e-100000'), 10 4397 ) 4398 self.assertRaises( 4399 TypeError, 4400 Decimal("1.23456789").quantize, Decimal('1e-100000'), ROUND_UP, 1000 4401 ) 4402 4403 with localcontext() as c: 4404 c.clear_traps() 4405 4406 # Invalid arguments 4407 self.assertRaises(TypeError, c.copy_sign, Decimal(1), "x", "y") 4408 self.assertRaises(TypeError, c.canonical, 200) 4409 self.assertRaises(TypeError, c.is_canonical, 200) 4410 self.assertRaises(TypeError, c.divmod, 9, 8, "x", "y") 4411 self.assertRaises(TypeError, c.same_quantum, 9, 3, "x", "y") 4412 4413 self.assertEqual(str(c.canonical(Decimal(200))), '200') 4414 self.assertEqual(c.radix(), 10) 4415 4416 c.traps[DivisionByZero] = True 4417 self.assertRaises(DivisionByZero, Decimal(9).__divmod__, 0) 4418 self.assertRaises(DivisionByZero, Decimal(9).divmod, 0) 4419 self.assertRaises(DivisionByZero, c.divmod, 9, 0) 4420 self.assertTrue(c.flags[InvalidOperation]) 4421 4422 c.clear_flags() 4423 c.traps[InvalidOperation] = True 4424 self.assertRaises(InvalidOperation, Decimal(9).__divmod__, 0) 4425 self.assertRaises(InvalidOperation, Decimal(9).divmod, 0) 4426 self.assertRaises(InvalidOperation, c.divmod, 9, 0) 4427 self.assertTrue(c.flags[DivisionByZero]) 4428 4429 c.traps[InvalidOperation] = True 4430 c.prec = 2 4431 self.assertRaises(InvalidOperation, pow, Decimal(1000), 1, 501) 4432 4433 c.prec = 10 4434 x = Decimal(2).invroot() 4435 self.assertEqual(str(x), '0.7071067812') 4436 4437 x = c.invroot(3) 4438 self.assertEqual(str(x), '0.5773502692') 4439 4440 c.prec = 28 4441 x = Decimal(2).power(8) 4442 self.assertEqual(str(x), '256') 4443 4444 x = Decimal(2).powmod(8, 31) 4445 self.assertEqual(str(x), '8') 4446 4447 def test_c_context_templates(self): 4448 self.assertEqual( 4449 C.BasicContext._traps, 4450 C.DecIEEEInvalidOperation|C.DecDivisionByZero|C.DecOverflow| 4451 C.DecUnderflow|C.DecClamped 4452 ) 4453 self.assertEqual( 4454 C.DefaultContext._traps, 4455 C.DecIEEEInvalidOperation|C.DecDivisionByZero|C.DecOverflow 4456 ) 4457 4458 def test_c_signal_dict(self): 4459 if hasattr(C, 'setfailpoint'): 4460 random.seed(randseed) 4461 4462 # SignalDict coverage 4463 Context = C.Context 4464 DefaultContext = C.DefaultContext 4465 4466 InvalidOperation = C.InvalidOperation 4467 DivisionByZero = C.DivisionByZero 4468 Overflow = C.Overflow 4469 Subnormal = C.Subnormal 4470 Underflow = C.Underflow 4471 Rounded = C.Rounded 4472 Inexact = C.Inexact 4473 Clamped = C.Clamped 4474 4475 DecClamped = C.DecClamped 4476 DecInvalidOperation = C.DecInvalidOperation 4477 DecIEEEInvalidOperation = C.DecIEEEInvalidOperation 4478 4479 def assertIsExclusivelySet(signal, signal_dict): 4480 for sig in signal_dict: 4481 if sig == signal: 4482 self.assertTrue(signal_dict[sig]) 4483 else: 4484 self.assertFalse(signal_dict[sig]) 4485 4486 c = DefaultContext.copy() 4487 4488 # Signal dict methods 4489 self.assertTrue(Overflow in c.traps) 4490 self.assertTrue(c.traps.has_key(Overflow)) 4491 4492 c.clear_traps() 4493 for k in c.traps.iterkeys(): 4494 c.traps[k] = True 4495 for v in c.traps.itervalues(): 4496 self.assertTrue(v) 4497 c.clear_traps() 4498 for k, v in c.traps.iteritems(): 4499 self.assertFalse(v) 4500 4501 c.clear_traps() 4502 for k in c.traps.keys(): 4503 c.traps[k] = True 4504 for v in c.traps.values(): 4505 self.assertTrue(v) 4506 c.clear_traps() 4507 for k, v in c.traps.iteritems(): 4508 self.assertFalse(v) 4509 4510 self.assertFalse(c.flags.get(Overflow)) 4511 self.assertTrue(c.flags.get("x") is None) 4512 self.assertEqual(c.flags.get("x", "y"), "y") 4513 self.assertRaises(TypeError, c.flags.get, "x", "y", "z") 4514 4515 self.assertEqual(len(c.flags), len(c.traps)) 4516 s = sys.getsizeof(c.flags) 4517 s = sys.getsizeof(c.traps) 4518 s = c.flags.__repr__() 4519 4520 # Set flags/traps form long. 4521 c.clear_flags() 4522 c._flags = long(DecClamped) 4523 self.assertTrue(c.flags[Clamped]) 4524 4525 c.clear_traps() 4526 c._traps = long(DecInvalidOperation) 4527 self.assertTrue(c.traps[InvalidOperation]) 4528 4529 # Set flags/traps from dictionary. 4530 c.clear_flags() 4531 d = c.flags.copy() 4532 d[DivisionByZero] = True 4533 c.flags = d 4534 assertIsExclusivelySet(DivisionByZero, c.flags) 4535 4536 c.clear_traps() 4537 d = c.traps.copy() 4538 d[Underflow] = True 4539 c.traps = d 4540 assertIsExclusivelySet(Underflow, c.traps) 4541 4542 # Random constructors 4543 IntSignals = { 4544 Clamped: C.DecClamped, 4545 Rounded: C.DecRounded, 4546 Inexact: C.DecInexact, 4547 Subnormal: C.DecSubnormal, 4548 Underflow: C.DecUnderflow, 4549 Overflow: C.DecOverflow, 4550 DivisionByZero: C.DecDivisionByZero, 4551 InvalidOperation: C.DecIEEEInvalidOperation 4552 } 4553 IntCond = [ 4554 C.DecDivisionImpossible, C.DecDivisionUndefined, C.DecFpuError, 4555 C.DecInvalidContext, C.DecInvalidOperation, C.DecMallocError, 4556 C.DecConversionSyntax, 4557 ] 4558 4559 lim = 1 if hasattr(C, 'setfailpoint') else len(OrderedSignals[C]) 4560 for r in range(lim): 4561 for t in range(lim): 4562 for round in RoundingModes[C]: 4563 flags = random.sample(OrderedSignals[C], r) 4564 traps = random.sample(OrderedSignals[C], t) 4565 prec = random.randrange(1, 10000) 4566 emin = random.randrange(-10000, 0) 4567 emax = random.randrange(0, 10000) 4568 clamp = random.randrange(0, 2) 4569 caps = random.randrange(0, 2) 4570 cr = random.randrange(0, 2) 4571 c = Context(prec=prec, rounding=round, Emin=emin, Emax=emax, 4572 capitals=caps, clamp=clamp, flags=list(flags), 4573 traps=list(traps), _allcr=cr) 4574 4575 self.assertEqual(c.prec, prec) 4576 self.assertEqual(c.rounding, round) 4577 self.assertEqual(c.Emin, emin) 4578 self.assertEqual(c.Emax, emax) 4579 self.assertEqual(c.capitals, caps) 4580 self.assertEqual(c.clamp, clamp) 4581 self.assertEqual(c._allcr, cr) 4582 4583 f = 0 4584 for x in flags: 4585 f |= IntSignals[x] 4586 self.assertEqual(c._flags, f) 4587 4588 f = 0 4589 for x in traps: 4590 f |= IntSignals[x] 4591 self.assertEqual(c._traps, f) 4592 4593 for cond in IntCond: 4594 c._flags = cond 4595 self.assertTrue(c._flags&DecIEEEInvalidOperation) 4596 assertIsExclusivelySet(InvalidOperation, c.flags) 4597 4598 for cond in IntCond: 4599 c._traps = cond 4600 self.assertTrue(c._traps&DecIEEEInvalidOperation) 4601 assertIsExclusivelySet(InvalidOperation, c.traps) 4602 4603 4604all_tests = [ 4605 CExplicitConstructionTest, PyExplicitConstructionTest, 4606 CImplicitConstructionTest, PyImplicitConstructionTest, 4607 CFormatTest, PyFormatTest, 4608 CArithmeticOperatorsTest, PyArithmeticOperatorsTest, 4609 CThreadingTest, PyThreadingTest, 4610 CUsabilityTest, PyUsabilityTest, 4611 CPythonAPItests, PyPythonAPItests, 4612 CContextAPItests, PyContextAPItests, 4613 CContextWithStatement, PyContextWithStatement, 4614 CContextFlags, PyContextFlags, 4615 CSpecialContexts, PySpecialContexts, 4616 CContextInputValidation, PyContextInputValidation, 4617 CCoverage, PyCoverage, 4618 CFunctionality, PyFunctionality, 4619 CWhitebox, PyWhitebox, 4620 CIBMTestCases, PyIBMTestCases, 4621] 4622 4623if py_minor <= 6: 4624 all_tests = all_tests[::2] 4625 4626# Wrap test functions for testing api failures. Doing this in 4627# test_main() causes spurious refleaks, so it is done here. 4628if hasattr(C, 'setapicalls'): 4629 for cls in all_tests: 4630 if cls == CIBMTestCases or cls == PyIBMTestCases: 4631 newfunc = withFailpoint(getattr(cls, 'eval_equation')) 4632 setattr(cls, 'eval_equation', newfunc) 4633 else: 4634 for attr in dir(cls): 4635 if attr.startswith('test_'): 4636 if attr == 'test_threading': 4637 continue 4638 newfunc = withFailpoint(getattr(cls, attr)) 4639 setattr(cls, attr, newfunc) 4640 4641def test_main(arith=False, verbose=None, todo_tests=None, debug=None): 4642 """ Execute the tests. 4643 4644 Runs all arithmetic tests if arith is True or if the "decimal" resource 4645 is enabled in regrtest.py 4646 """ 4647 4648 init(C) 4649 init(P) 4650 global TEST_ALL, DEBUG 4651 TEST_ALL = arith or is_resource_enabled('decimal') 4652 DEBUG = debug 4653 4654 if todo_tests is None: 4655 test_classes = all_tests 4656 else: 4657 test_classes = [CIBMTestCases, PyIBMTestCases] 4658 4659 # Dynamically build custom test definition for each file in the test 4660 # directory and add the definitions to the DecimalTest class. This 4661 # procedure insures that new files do not get skipped. 4662 for filename in os.listdir(directory): 4663 if '.decTest' not in filename or filename.startswith("."): 4664 continue 4665 head, tail = filename.split('.') 4666 if todo_tests is not None and head not in todo_tests: 4667 continue 4668 tester = lambda self, f=filename: self.eval_file(directory + f) 4669 setattr(CIBMTestCases, 'test_' + head, tester) 4670 setattr(PyIBMTestCases, 'test_' + head, tester) 4671 del filename, head, tail, tester 4672 4673 4674 try: 4675 run_unittest(*test_classes) 4676 if todo_tests is None: 4677 run_doctest(C, verbose) 4678 run_doctest(P, verbose) 4679 finally: 4680 if C: C.setcontext(ORIGINAL_CONTEXT[C]) 4681 P.setcontext(ORIGINAL_CONTEXT[P]) 4682 if not C: 4683 warnings.warn('C tests skipped: no module named _decimal.', 4684 UserWarning) 4685 if not orig_sys_decimal is sys.modules['decimal']: 4686 raise TestFailed("Internal error: unbalanced number of changes to " 4687 "sys.modules['decimal'].") 4688 4689 4690if __name__ == '__main__': 4691 import optparse 4692 p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]") 4693 p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test') 4694 p.add_option('--skip', '-s', action='store_true', help='skip over 90% of the arithmetic tests') 4695 (opt, args) = p.parse_args() 4696 4697 if opt.skip: 4698 test_main(arith=False, verbose=True) 4699 elif args: 4700 test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug) 4701 else: 4702 test_main(arith=True, verbose=True) 4703