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