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