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 2449class PythonAPItests(unittest.TestCase): 2450 2451 def test_abc(self): 2452 Decimal = self.decimal.Decimal 2453 2454 self.assertTrue(issubclass(Decimal, numbers.Number)) 2455 self.assertFalse(issubclass(Decimal, numbers.Real)) 2456 self.assertIsInstance(Decimal(0), numbers.Number) 2457 self.assertNotIsInstance(Decimal(0), numbers.Real) 2458 2459 def test_pickle(self): 2460 for proto in range(pickle.HIGHEST_PROTOCOL + 1): 2461 Decimal = self.decimal.Decimal 2462 2463 savedecimal = sys.modules['decimal'] 2464 2465 # Round trip 2466 sys.modules['decimal'] = self.decimal 2467 d = Decimal('-3.141590000') 2468 p = pickle.dumps(d, proto) 2469 e = pickle.loads(p) 2470 self.assertEqual(d, e) 2471 2472 if C: 2473 # Test interchangeability 2474 x = C.Decimal('-3.123e81723') 2475 y = P.Decimal('-3.123e81723') 2476 2477 sys.modules['decimal'] = C 2478 sx = pickle.dumps(x, proto) 2479 sys.modules['decimal'] = P 2480 r = pickle.loads(sx) 2481 self.assertIsInstance(r, P.Decimal) 2482 self.assertEqual(r, y) 2483 2484 sys.modules['decimal'] = P 2485 sy = pickle.dumps(y, proto) 2486 sys.modules['decimal'] = C 2487 r = pickle.loads(sy) 2488 self.assertIsInstance(r, C.Decimal) 2489 self.assertEqual(r, x) 2490 2491 x = C.Decimal('-3.123e81723').as_tuple() 2492 y = P.Decimal('-3.123e81723').as_tuple() 2493 2494 sys.modules['decimal'] = C 2495 sx = pickle.dumps(x, proto) 2496 sys.modules['decimal'] = P 2497 r = pickle.loads(sx) 2498 self.assertIsInstance(r, P.DecimalTuple) 2499 self.assertEqual(r, y) 2500 2501 sys.modules['decimal'] = P 2502 sy = pickle.dumps(y, proto) 2503 sys.modules['decimal'] = C 2504 r = pickle.loads(sy) 2505 self.assertIsInstance(r, C.DecimalTuple) 2506 self.assertEqual(r, x) 2507 2508 sys.modules['decimal'] = savedecimal 2509 2510 def test_int(self): 2511 Decimal = self.decimal.Decimal 2512 2513 for x in range(-250, 250): 2514 s = '%0.2f' % (x / 100.0) 2515 # should work the same as for floats 2516 self.assertEqual(int(Decimal(s)), int(float(s))) 2517 # should work the same as to_integral in the ROUND_DOWN mode 2518 d = Decimal(s) 2519 r = d.to_integral(ROUND_DOWN) 2520 self.assertEqual(Decimal(int(d)), r) 2521 2522 self.assertRaises(ValueError, int, Decimal('-nan')) 2523 self.assertRaises(ValueError, int, Decimal('snan')) 2524 self.assertRaises(OverflowError, int, Decimal('inf')) 2525 self.assertRaises(OverflowError, int, Decimal('-inf')) 2526 2527 def test_trunc(self): 2528 Decimal = self.decimal.Decimal 2529 2530 for x in range(-250, 250): 2531 s = '%0.2f' % (x / 100.0) 2532 # should work the same as for floats 2533 self.assertEqual(int(Decimal(s)), int(float(s))) 2534 # should work the same as to_integral in the ROUND_DOWN mode 2535 d = Decimal(s) 2536 r = d.to_integral(ROUND_DOWN) 2537 self.assertEqual(Decimal(math.trunc(d)), r) 2538 2539 def test_from_float(self): 2540 2541 Decimal = self.decimal.Decimal 2542 2543 class MyDecimal(Decimal): 2544 def __init__(self, _): 2545 self.x = 'y' 2546 2547 self.assertTrue(issubclass(MyDecimal, Decimal)) 2548 2549 r = MyDecimal.from_float(0.1) 2550 self.assertEqual(type(r), MyDecimal) 2551 self.assertEqual(str(r), 2552 '0.1000000000000000055511151231257827021181583404541015625') 2553 self.assertEqual(r.x, 'y') 2554 2555 bigint = 12345678901234567890123456789 2556 self.assertEqual(MyDecimal.from_float(bigint), MyDecimal(bigint)) 2557 self.assertTrue(MyDecimal.from_float(float('nan')).is_qnan()) 2558 self.assertTrue(MyDecimal.from_float(float('inf')).is_infinite()) 2559 self.assertTrue(MyDecimal.from_float(float('-inf')).is_infinite()) 2560 self.assertEqual(str(MyDecimal.from_float(float('nan'))), 2561 str(Decimal('NaN'))) 2562 self.assertEqual(str(MyDecimal.from_float(float('inf'))), 2563 str(Decimal('Infinity'))) 2564 self.assertEqual(str(MyDecimal.from_float(float('-inf'))), 2565 str(Decimal('-Infinity'))) 2566 self.assertRaises(TypeError, MyDecimal.from_float, 'abc') 2567 for i in range(200): 2568 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0) 2569 self.assertEqual(x, float(MyDecimal.from_float(x))) # roundtrip 2570 2571 def test_create_decimal_from_float(self): 2572 Decimal = self.decimal.Decimal 2573 Context = self.decimal.Context 2574 Inexact = self.decimal.Inexact 2575 2576 context = Context(prec=5, rounding=ROUND_DOWN) 2577 self.assertEqual( 2578 context.create_decimal_from_float(math.pi), 2579 Decimal('3.1415') 2580 ) 2581 context = Context(prec=5, rounding=ROUND_UP) 2582 self.assertEqual( 2583 context.create_decimal_from_float(math.pi), 2584 Decimal('3.1416') 2585 ) 2586 context = Context(prec=5, traps=[Inexact]) 2587 self.assertRaises( 2588 Inexact, 2589 context.create_decimal_from_float, 2590 math.pi 2591 ) 2592 self.assertEqual(repr(context.create_decimal_from_float(-0.0)), 2593 "Decimal('-0')") 2594 self.assertEqual(repr(context.create_decimal_from_float(1.0)), 2595 "Decimal('1')") 2596 self.assertEqual(repr(context.create_decimal_from_float(10)), 2597 "Decimal('10')") 2598 2599 def test_quantize(self): 2600 Decimal = self.decimal.Decimal 2601 Context = self.decimal.Context 2602 InvalidOperation = self.decimal.InvalidOperation 2603 2604 c = Context(Emax=99999, Emin=-99999) 2605 self.assertEqual( 2606 Decimal('7.335').quantize(Decimal('.01')), 2607 Decimal('7.34') 2608 ) 2609 self.assertEqual( 2610 Decimal('7.335').quantize(Decimal('.01'), rounding=ROUND_DOWN), 2611 Decimal('7.33') 2612 ) 2613 self.assertRaises( 2614 InvalidOperation, 2615 Decimal("10e99999").quantize, Decimal('1e100000'), context=c 2616 ) 2617 2618 c = Context() 2619 d = Decimal("0.871831e800") 2620 x = d.quantize(context=c, exp=Decimal("1e797"), rounding=ROUND_DOWN) 2621 self.assertEqual(x, Decimal('8.71E+799')) 2622 2623 def test_complex(self): 2624 Decimal = self.decimal.Decimal 2625 2626 x = Decimal("9.8182731e181273") 2627 self.assertEqual(x.real, x) 2628 self.assertEqual(x.imag, 0) 2629 self.assertEqual(x.conjugate(), x) 2630 2631 x = Decimal("1") 2632 self.assertEqual(complex(x), complex(float(1))) 2633 2634 self.assertRaises(AttributeError, setattr, x, 'real', 100) 2635 self.assertRaises(AttributeError, setattr, x, 'imag', 100) 2636 self.assertRaises(AttributeError, setattr, x, 'conjugate', 100) 2637 self.assertRaises(AttributeError, setattr, x, '__complex__', 100) 2638 2639 def test_named_parameters(self): 2640 D = self.decimal.Decimal 2641 Context = self.decimal.Context 2642 localcontext = self.decimal.localcontext 2643 InvalidOperation = self.decimal.InvalidOperation 2644 Overflow = self.decimal.Overflow 2645 2646 xc = Context() 2647 xc.prec = 1 2648 xc.Emax = 1 2649 xc.Emin = -1 2650 2651 with localcontext() as c: 2652 c.clear_flags() 2653 2654 self.assertEqual(D(9, xc), 9) 2655 self.assertEqual(D(9, context=xc), 9) 2656 self.assertEqual(D(context=xc, value=9), 9) 2657 self.assertEqual(D(context=xc), 0) 2658 xc.clear_flags() 2659 self.assertRaises(InvalidOperation, D, "xyz", context=xc) 2660 self.assertTrue(xc.flags[InvalidOperation]) 2661 self.assertFalse(c.flags[InvalidOperation]) 2662 2663 xc.clear_flags() 2664 self.assertEqual(D(2).exp(context=xc), 7) 2665 self.assertRaises(Overflow, D(8).exp, context=xc) 2666 self.assertTrue(xc.flags[Overflow]) 2667 self.assertFalse(c.flags[Overflow]) 2668 2669 xc.clear_flags() 2670 self.assertEqual(D(2).ln(context=xc), D('0.7')) 2671 self.assertRaises(InvalidOperation, D(-1).ln, context=xc) 2672 self.assertTrue(xc.flags[InvalidOperation]) 2673 self.assertFalse(c.flags[InvalidOperation]) 2674 2675 self.assertEqual(D(0).log10(context=xc), D('-inf')) 2676 self.assertEqual(D(-1).next_minus(context=xc), -2) 2677 self.assertEqual(D(-1).next_plus(context=xc), D('-0.9')) 2678 self.assertEqual(D("9.73").normalize(context=xc), D('1E+1')) 2679 self.assertEqual(D("9999").to_integral(context=xc), 9999) 2680 self.assertEqual(D("-2000").to_integral_exact(context=xc), -2000) 2681 self.assertEqual(D("123").to_integral_value(context=xc), 123) 2682 self.assertEqual(D("0.0625").sqrt(context=xc), D('0.2')) 2683 2684 self.assertEqual(D("0.0625").compare(context=xc, other=3), -1) 2685 xc.clear_flags() 2686 self.assertRaises(InvalidOperation, 2687 D("0").compare_signal, D('nan'), context=xc) 2688 self.assertTrue(xc.flags[InvalidOperation]) 2689 self.assertFalse(c.flags[InvalidOperation]) 2690 self.assertEqual(D("0.01").max(D('0.0101'), context=xc), D('0.0')) 2691 self.assertEqual(D("0.01").max(D('0.0101'), context=xc), D('0.0')) 2692 self.assertEqual(D("0.2").max_mag(D('-0.3'), context=xc), 2693 D('-0.3')) 2694 self.assertEqual(D("0.02").min(D('-0.03'), context=xc), D('-0.0')) 2695 self.assertEqual(D("0.02").min_mag(D('-0.03'), context=xc), 2696 D('0.0')) 2697 self.assertEqual(D("0.2").next_toward(D('-1'), context=xc), D('0.1')) 2698 xc.clear_flags() 2699 self.assertRaises(InvalidOperation, 2700 D("0.2").quantize, D('1e10'), context=xc) 2701 self.assertTrue(xc.flags[InvalidOperation]) 2702 self.assertFalse(c.flags[InvalidOperation]) 2703 self.assertEqual(D("9.99").remainder_near(D('1.5'), context=xc), 2704 D('-0.5')) 2705 2706 self.assertEqual(D("9.9").fma(third=D('0.9'), context=xc, other=7), 2707 D('7E+1')) 2708 2709 self.assertRaises(TypeError, D(1).is_canonical, context=xc) 2710 self.assertRaises(TypeError, D(1).is_finite, context=xc) 2711 self.assertRaises(TypeError, D(1).is_infinite, context=xc) 2712 self.assertRaises(TypeError, D(1).is_nan, context=xc) 2713 self.assertRaises(TypeError, D(1).is_qnan, context=xc) 2714 self.assertRaises(TypeError, D(1).is_snan, context=xc) 2715 self.assertRaises(TypeError, D(1).is_signed, context=xc) 2716 self.assertRaises(TypeError, D(1).is_zero, context=xc) 2717 2718 self.assertFalse(D("0.01").is_normal(context=xc)) 2719 self.assertTrue(D("0.01").is_subnormal(context=xc)) 2720 2721 self.assertRaises(TypeError, D(1).adjusted, context=xc) 2722 self.assertRaises(TypeError, D(1).conjugate, context=xc) 2723 self.assertRaises(TypeError, D(1).radix, context=xc) 2724 2725 self.assertEqual(D(-111).logb(context=xc), 2) 2726 self.assertEqual(D(0).logical_invert(context=xc), 1) 2727 self.assertEqual(D('0.01').number_class(context=xc), '+Subnormal') 2728 self.assertEqual(D('0.21').to_eng_string(context=xc), '0.21') 2729 2730 self.assertEqual(D('11').logical_and(D('10'), context=xc), 0) 2731 self.assertEqual(D('11').logical_or(D('10'), context=xc), 1) 2732 self.assertEqual(D('01').logical_xor(D('10'), context=xc), 1) 2733 self.assertEqual(D('23').rotate(1, context=xc), 3) 2734 self.assertEqual(D('23').rotate(1, context=xc), 3) 2735 xc.clear_flags() 2736 self.assertRaises(Overflow, 2737 D('23').scaleb, 1, context=xc) 2738 self.assertTrue(xc.flags[Overflow]) 2739 self.assertFalse(c.flags[Overflow]) 2740 self.assertEqual(D('23').shift(-1, context=xc), 0) 2741 2742 self.assertRaises(TypeError, D.from_float, 1.1, context=xc) 2743 self.assertRaises(TypeError, D(0).as_tuple, context=xc) 2744 2745 self.assertEqual(D(1).canonical(), 1) 2746 self.assertRaises(TypeError, D("-1").copy_abs, context=xc) 2747 self.assertRaises(TypeError, D("-1").copy_negate, context=xc) 2748 self.assertRaises(TypeError, D(1).canonical, context="x") 2749 self.assertRaises(TypeError, D(1).canonical, xyz="x") 2750 2751 def test_exception_hierarchy(self): 2752 2753 decimal = self.decimal 2754 DecimalException = decimal.DecimalException 2755 InvalidOperation = decimal.InvalidOperation 2756 FloatOperation = decimal.FloatOperation 2757 DivisionByZero = decimal.DivisionByZero 2758 Overflow = decimal.Overflow 2759 Underflow = decimal.Underflow 2760 Subnormal = decimal.Subnormal 2761 Inexact = decimal.Inexact 2762 Rounded = decimal.Rounded 2763 Clamped = decimal.Clamped 2764 2765 self.assertTrue(issubclass(DecimalException, ArithmeticError)) 2766 2767 self.assertTrue(issubclass(InvalidOperation, DecimalException)) 2768 self.assertTrue(issubclass(FloatOperation, DecimalException)) 2769 self.assertTrue(issubclass(FloatOperation, TypeError)) 2770 self.assertTrue(issubclass(DivisionByZero, DecimalException)) 2771 self.assertTrue(issubclass(DivisionByZero, ZeroDivisionError)) 2772 self.assertTrue(issubclass(Overflow, Rounded)) 2773 self.assertTrue(issubclass(Overflow, Inexact)) 2774 self.assertTrue(issubclass(Overflow, DecimalException)) 2775 self.assertTrue(issubclass(Underflow, Inexact)) 2776 self.assertTrue(issubclass(Underflow, Rounded)) 2777 self.assertTrue(issubclass(Underflow, Subnormal)) 2778 self.assertTrue(issubclass(Underflow, DecimalException)) 2779 2780 self.assertTrue(issubclass(Subnormal, DecimalException)) 2781 self.assertTrue(issubclass(Inexact, DecimalException)) 2782 self.assertTrue(issubclass(Rounded, DecimalException)) 2783 self.assertTrue(issubclass(Clamped, DecimalException)) 2784 2785 self.assertTrue(issubclass(decimal.ConversionSyntax, InvalidOperation)) 2786 self.assertTrue(issubclass(decimal.DivisionImpossible, InvalidOperation)) 2787 self.assertTrue(issubclass(decimal.DivisionUndefined, InvalidOperation)) 2788 self.assertTrue(issubclass(decimal.DivisionUndefined, ZeroDivisionError)) 2789 self.assertTrue(issubclass(decimal.InvalidContext, InvalidOperation)) 2790 2791class CPythonAPItests(PythonAPItests): 2792 decimal = C 2793class PyPythonAPItests(PythonAPItests): 2794 decimal = P 2795 2796class ContextAPItests(unittest.TestCase): 2797 2798 def test_none_args(self): 2799 Context = self.decimal.Context 2800 InvalidOperation = self.decimal.InvalidOperation 2801 DivisionByZero = self.decimal.DivisionByZero 2802 Overflow = self.decimal.Overflow 2803 2804 c1 = Context() 2805 c2 = Context(prec=None, rounding=None, Emax=None, Emin=None, 2806 capitals=None, clamp=None, flags=None, traps=None) 2807 for c in [c1, c2]: 2808 self.assertEqual(c.prec, 28) 2809 self.assertEqual(c.rounding, ROUND_HALF_EVEN) 2810 self.assertEqual(c.Emax, 999999) 2811 self.assertEqual(c.Emin, -999999) 2812 self.assertEqual(c.capitals, 1) 2813 self.assertEqual(c.clamp, 0) 2814 assert_signals(self, c, 'flags', []) 2815 assert_signals(self, c, 'traps', [InvalidOperation, DivisionByZero, 2816 Overflow]) 2817 2818 @cpython_only 2819 def test_from_legacy_strings(self): 2820 import _testcapi 2821 c = self.decimal.Context() 2822 2823 for rnd in RoundingModes: 2824 c.rounding = _testcapi.unicode_legacy_string(rnd) 2825 self.assertEqual(c.rounding, rnd) 2826 2827 s = _testcapi.unicode_legacy_string('') 2828 self.assertRaises(TypeError, setattr, c, 'rounding', s) 2829 2830 s = _testcapi.unicode_legacy_string('ROUND_\x00UP') 2831 self.assertRaises(TypeError, setattr, c, 'rounding', s) 2832 2833 def test_pickle(self): 2834 2835 for proto in range(pickle.HIGHEST_PROTOCOL + 1): 2836 Context = self.decimal.Context 2837 2838 savedecimal = sys.modules['decimal'] 2839 2840 # Round trip 2841 sys.modules['decimal'] = self.decimal 2842 c = Context() 2843 e = pickle.loads(pickle.dumps(c, proto)) 2844 2845 self.assertEqual(c.prec, e.prec) 2846 self.assertEqual(c.Emin, e.Emin) 2847 self.assertEqual(c.Emax, e.Emax) 2848 self.assertEqual(c.rounding, e.rounding) 2849 self.assertEqual(c.capitals, e.capitals) 2850 self.assertEqual(c.clamp, e.clamp) 2851 self.assertEqual(c.flags, e.flags) 2852 self.assertEqual(c.traps, e.traps) 2853 2854 # Test interchangeability 2855 combinations = [(C, P), (P, C)] if C else [(P, P)] 2856 for dumper, loader in combinations: 2857 for ri, _ in enumerate(RoundingModes): 2858 for fi, _ in enumerate(OrderedSignals[dumper]): 2859 for ti, _ in enumerate(OrderedSignals[dumper]): 2860 2861 prec = random.randrange(1, 100) 2862 emin = random.randrange(-100, 0) 2863 emax = random.randrange(1, 100) 2864 caps = random.randrange(2) 2865 clamp = random.randrange(2) 2866 2867 # One module dumps 2868 sys.modules['decimal'] = dumper 2869 c = dumper.Context( 2870 prec=prec, Emin=emin, Emax=emax, 2871 rounding=RoundingModes[ri], 2872 capitals=caps, clamp=clamp, 2873 flags=OrderedSignals[dumper][:fi], 2874 traps=OrderedSignals[dumper][:ti] 2875 ) 2876 s = pickle.dumps(c, proto) 2877 2878 # The other module loads 2879 sys.modules['decimal'] = loader 2880 d = pickle.loads(s) 2881 self.assertIsInstance(d, loader.Context) 2882 2883 self.assertEqual(d.prec, prec) 2884 self.assertEqual(d.Emin, emin) 2885 self.assertEqual(d.Emax, emax) 2886 self.assertEqual(d.rounding, RoundingModes[ri]) 2887 self.assertEqual(d.capitals, caps) 2888 self.assertEqual(d.clamp, clamp) 2889 assert_signals(self, d, 'flags', OrderedSignals[loader][:fi]) 2890 assert_signals(self, d, 'traps', OrderedSignals[loader][:ti]) 2891 2892 sys.modules['decimal'] = savedecimal 2893 2894 def test_equality_with_other_types(self): 2895 Decimal = self.decimal.Decimal 2896 2897 self.assertIn(Decimal(10), ['a', 1.0, Decimal(10), (1,2), {}]) 2898 self.assertNotIn(Decimal(10), ['a', 1.0, (1,2), {}]) 2899 2900 def test_copy(self): 2901 # All copies should be deep 2902 Decimal = self.decimal.Decimal 2903 Context = self.decimal.Context 2904 2905 c = Context() 2906 d = c.copy() 2907 self.assertNotEqual(id(c), id(d)) 2908 self.assertNotEqual(id(c.flags), id(d.flags)) 2909 self.assertNotEqual(id(c.traps), id(d.traps)) 2910 k1 = set(c.flags.keys()) 2911 k2 = set(d.flags.keys()) 2912 self.assertEqual(k1, k2) 2913 self.assertEqual(c.flags, d.flags) 2914 2915 def test__clamp(self): 2916 # In Python 3.2, the private attribute `_clamp` was made 2917 # public (issue 8540), with the old `_clamp` becoming a 2918 # property wrapping `clamp`. For the duration of Python 3.2 2919 # only, the attribute should be gettable/settable via both 2920 # `clamp` and `_clamp`; in Python 3.3, `_clamp` should be 2921 # removed. 2922 Context = self.decimal.Context 2923 c = Context() 2924 self.assertRaises(AttributeError, getattr, c, '_clamp') 2925 2926 def test_abs(self): 2927 Decimal = self.decimal.Decimal 2928 Context = self.decimal.Context 2929 2930 c = Context() 2931 d = c.abs(Decimal(-1)) 2932 self.assertEqual(c.abs(-1), d) 2933 self.assertRaises(TypeError, c.abs, '-1') 2934 2935 def test_add(self): 2936 Decimal = self.decimal.Decimal 2937 Context = self.decimal.Context 2938 2939 c = Context() 2940 d = c.add(Decimal(1), Decimal(1)) 2941 self.assertEqual(c.add(1, 1), d) 2942 self.assertEqual(c.add(Decimal(1), 1), d) 2943 self.assertEqual(c.add(1, Decimal(1)), d) 2944 self.assertRaises(TypeError, c.add, '1', 1) 2945 self.assertRaises(TypeError, c.add, 1, '1') 2946 2947 def test_compare(self): 2948 Decimal = self.decimal.Decimal 2949 Context = self.decimal.Context 2950 2951 c = Context() 2952 d = c.compare(Decimal(1), Decimal(1)) 2953 self.assertEqual(c.compare(1, 1), d) 2954 self.assertEqual(c.compare(Decimal(1), 1), d) 2955 self.assertEqual(c.compare(1, Decimal(1)), d) 2956 self.assertRaises(TypeError, c.compare, '1', 1) 2957 self.assertRaises(TypeError, c.compare, 1, '1') 2958 2959 def test_compare_signal(self): 2960 Decimal = self.decimal.Decimal 2961 Context = self.decimal.Context 2962 2963 c = Context() 2964 d = c.compare_signal(Decimal(1), Decimal(1)) 2965 self.assertEqual(c.compare_signal(1, 1), d) 2966 self.assertEqual(c.compare_signal(Decimal(1), 1), d) 2967 self.assertEqual(c.compare_signal(1, Decimal(1)), d) 2968 self.assertRaises(TypeError, c.compare_signal, '1', 1) 2969 self.assertRaises(TypeError, c.compare_signal, 1, '1') 2970 2971 def test_compare_total(self): 2972 Decimal = self.decimal.Decimal 2973 Context = self.decimal.Context 2974 2975 c = Context() 2976 d = c.compare_total(Decimal(1), Decimal(1)) 2977 self.assertEqual(c.compare_total(1, 1), d) 2978 self.assertEqual(c.compare_total(Decimal(1), 1), d) 2979 self.assertEqual(c.compare_total(1, Decimal(1)), d) 2980 self.assertRaises(TypeError, c.compare_total, '1', 1) 2981 self.assertRaises(TypeError, c.compare_total, 1, '1') 2982 2983 def test_compare_total_mag(self): 2984 Decimal = self.decimal.Decimal 2985 Context = self.decimal.Context 2986 2987 c = Context() 2988 d = c.compare_total_mag(Decimal(1), Decimal(1)) 2989 self.assertEqual(c.compare_total_mag(1, 1), d) 2990 self.assertEqual(c.compare_total_mag(Decimal(1), 1), d) 2991 self.assertEqual(c.compare_total_mag(1, Decimal(1)), d) 2992 self.assertRaises(TypeError, c.compare_total_mag, '1', 1) 2993 self.assertRaises(TypeError, c.compare_total_mag, 1, '1') 2994 2995 def test_copy_abs(self): 2996 Decimal = self.decimal.Decimal 2997 Context = self.decimal.Context 2998 2999 c = Context() 3000 d = c.copy_abs(Decimal(-1)) 3001 self.assertEqual(c.copy_abs(-1), d) 3002 self.assertRaises(TypeError, c.copy_abs, '-1') 3003 3004 def test_copy_decimal(self): 3005 Decimal = self.decimal.Decimal 3006 Context = self.decimal.Context 3007 3008 c = Context() 3009 d = c.copy_decimal(Decimal(-1)) 3010 self.assertEqual(c.copy_decimal(-1), d) 3011 self.assertRaises(TypeError, c.copy_decimal, '-1') 3012 3013 def test_copy_negate(self): 3014 Decimal = self.decimal.Decimal 3015 Context = self.decimal.Context 3016 3017 c = Context() 3018 d = c.copy_negate(Decimal(-1)) 3019 self.assertEqual(c.copy_negate(-1), d) 3020 self.assertRaises(TypeError, c.copy_negate, '-1') 3021 3022 def test_copy_sign(self): 3023 Decimal = self.decimal.Decimal 3024 Context = self.decimal.Context 3025 3026 c = Context() 3027 d = c.copy_sign(Decimal(1), Decimal(-2)) 3028 self.assertEqual(c.copy_sign(1, -2), d) 3029 self.assertEqual(c.copy_sign(Decimal(1), -2), d) 3030 self.assertEqual(c.copy_sign(1, Decimal(-2)), d) 3031 self.assertRaises(TypeError, c.copy_sign, '1', -2) 3032 self.assertRaises(TypeError, c.copy_sign, 1, '-2') 3033 3034 def test_divide(self): 3035 Decimal = self.decimal.Decimal 3036 Context = self.decimal.Context 3037 3038 c = Context() 3039 d = c.divide(Decimal(1), Decimal(2)) 3040 self.assertEqual(c.divide(1, 2), d) 3041 self.assertEqual(c.divide(Decimal(1), 2), d) 3042 self.assertEqual(c.divide(1, Decimal(2)), d) 3043 self.assertRaises(TypeError, c.divide, '1', 2) 3044 self.assertRaises(TypeError, c.divide, 1, '2') 3045 3046 def test_divide_int(self): 3047 Decimal = self.decimal.Decimal 3048 Context = self.decimal.Context 3049 3050 c = Context() 3051 d = c.divide_int(Decimal(1), Decimal(2)) 3052 self.assertEqual(c.divide_int(1, 2), d) 3053 self.assertEqual(c.divide_int(Decimal(1), 2), d) 3054 self.assertEqual(c.divide_int(1, Decimal(2)), d) 3055 self.assertRaises(TypeError, c.divide_int, '1', 2) 3056 self.assertRaises(TypeError, c.divide_int, 1, '2') 3057 3058 def test_divmod(self): 3059 Decimal = self.decimal.Decimal 3060 Context = self.decimal.Context 3061 3062 c = Context() 3063 d = c.divmod(Decimal(1), Decimal(2)) 3064 self.assertEqual(c.divmod(1, 2), d) 3065 self.assertEqual(c.divmod(Decimal(1), 2), d) 3066 self.assertEqual(c.divmod(1, Decimal(2)), d) 3067 self.assertRaises(TypeError, c.divmod, '1', 2) 3068 self.assertRaises(TypeError, c.divmod, 1, '2') 3069 3070 def test_exp(self): 3071 Decimal = self.decimal.Decimal 3072 Context = self.decimal.Context 3073 3074 c = Context() 3075 d = c.exp(Decimal(10)) 3076 self.assertEqual(c.exp(10), d) 3077 self.assertRaises(TypeError, c.exp, '10') 3078 3079 def test_fma(self): 3080 Decimal = self.decimal.Decimal 3081 Context = self.decimal.Context 3082 3083 c = Context() 3084 d = c.fma(Decimal(2), Decimal(3), Decimal(4)) 3085 self.assertEqual(c.fma(2, 3, 4), d) 3086 self.assertEqual(c.fma(Decimal(2), 3, 4), d) 3087 self.assertEqual(c.fma(2, Decimal(3), 4), d) 3088 self.assertEqual(c.fma(2, 3, Decimal(4)), d) 3089 self.assertEqual(c.fma(Decimal(2), Decimal(3), 4), d) 3090 self.assertRaises(TypeError, c.fma, '2', 3, 4) 3091 self.assertRaises(TypeError, c.fma, 2, '3', 4) 3092 self.assertRaises(TypeError, c.fma, 2, 3, '4') 3093 3094 # Issue 12079 for Context.fma ... 3095 self.assertRaises(TypeError, c.fma, 3096 Decimal('Infinity'), Decimal(0), "not a decimal") 3097 self.assertRaises(TypeError, c.fma, 3098 Decimal(1), Decimal('snan'), 1.222) 3099 # ... and for Decimal.fma. 3100 self.assertRaises(TypeError, Decimal('Infinity').fma, 3101 Decimal(0), "not a decimal") 3102 self.assertRaises(TypeError, Decimal(1).fma, 3103 Decimal('snan'), 1.222) 3104 3105 def test_is_finite(self): 3106 Decimal = self.decimal.Decimal 3107 Context = self.decimal.Context 3108 3109 c = Context() 3110 d = c.is_finite(Decimal(10)) 3111 self.assertEqual(c.is_finite(10), d) 3112 self.assertRaises(TypeError, c.is_finite, '10') 3113 3114 def test_is_infinite(self): 3115 Decimal = self.decimal.Decimal 3116 Context = self.decimal.Context 3117 3118 c = Context() 3119 d = c.is_infinite(Decimal(10)) 3120 self.assertEqual(c.is_infinite(10), d) 3121 self.assertRaises(TypeError, c.is_infinite, '10') 3122 3123 def test_is_nan(self): 3124 Decimal = self.decimal.Decimal 3125 Context = self.decimal.Context 3126 3127 c = Context() 3128 d = c.is_nan(Decimal(10)) 3129 self.assertEqual(c.is_nan(10), d) 3130 self.assertRaises(TypeError, c.is_nan, '10') 3131 3132 def test_is_normal(self): 3133 Decimal = self.decimal.Decimal 3134 Context = self.decimal.Context 3135 3136 c = Context() 3137 d = c.is_normal(Decimal(10)) 3138 self.assertEqual(c.is_normal(10), d) 3139 self.assertRaises(TypeError, c.is_normal, '10') 3140 3141 def test_is_qnan(self): 3142 Decimal = self.decimal.Decimal 3143 Context = self.decimal.Context 3144 3145 c = Context() 3146 d = c.is_qnan(Decimal(10)) 3147 self.assertEqual(c.is_qnan(10), d) 3148 self.assertRaises(TypeError, c.is_qnan, '10') 3149 3150 def test_is_signed(self): 3151 Decimal = self.decimal.Decimal 3152 Context = self.decimal.Context 3153 3154 c = Context() 3155 d = c.is_signed(Decimal(10)) 3156 self.assertEqual(c.is_signed(10), d) 3157 self.assertRaises(TypeError, c.is_signed, '10') 3158 3159 def test_is_snan(self): 3160 Decimal = self.decimal.Decimal 3161 Context = self.decimal.Context 3162 3163 c = Context() 3164 d = c.is_snan(Decimal(10)) 3165 self.assertEqual(c.is_snan(10), d) 3166 self.assertRaises(TypeError, c.is_snan, '10') 3167 3168 def test_is_subnormal(self): 3169 Decimal = self.decimal.Decimal 3170 Context = self.decimal.Context 3171 3172 c = Context() 3173 d = c.is_subnormal(Decimal(10)) 3174 self.assertEqual(c.is_subnormal(10), d) 3175 self.assertRaises(TypeError, c.is_subnormal, '10') 3176 3177 def test_is_zero(self): 3178 Decimal = self.decimal.Decimal 3179 Context = self.decimal.Context 3180 3181 c = Context() 3182 d = c.is_zero(Decimal(10)) 3183 self.assertEqual(c.is_zero(10), d) 3184 self.assertRaises(TypeError, c.is_zero, '10') 3185 3186 def test_ln(self): 3187 Decimal = self.decimal.Decimal 3188 Context = self.decimal.Context 3189 3190 c = Context() 3191 d = c.ln(Decimal(10)) 3192 self.assertEqual(c.ln(10), d) 3193 self.assertRaises(TypeError, c.ln, '10') 3194 3195 def test_log10(self): 3196 Decimal = self.decimal.Decimal 3197 Context = self.decimal.Context 3198 3199 c = Context() 3200 d = c.log10(Decimal(10)) 3201 self.assertEqual(c.log10(10), d) 3202 self.assertRaises(TypeError, c.log10, '10') 3203 3204 def test_logb(self): 3205 Decimal = self.decimal.Decimal 3206 Context = self.decimal.Context 3207 3208 c = Context() 3209 d = c.logb(Decimal(10)) 3210 self.assertEqual(c.logb(10), d) 3211 self.assertRaises(TypeError, c.logb, '10') 3212 3213 def test_logical_and(self): 3214 Decimal = self.decimal.Decimal 3215 Context = self.decimal.Context 3216 3217 c = Context() 3218 d = c.logical_and(Decimal(1), Decimal(1)) 3219 self.assertEqual(c.logical_and(1, 1), d) 3220 self.assertEqual(c.logical_and(Decimal(1), 1), d) 3221 self.assertEqual(c.logical_and(1, Decimal(1)), d) 3222 self.assertRaises(TypeError, c.logical_and, '1', 1) 3223 self.assertRaises(TypeError, c.logical_and, 1, '1') 3224 3225 def test_logical_invert(self): 3226 Decimal = self.decimal.Decimal 3227 Context = self.decimal.Context 3228 3229 c = Context() 3230 d = c.logical_invert(Decimal(1000)) 3231 self.assertEqual(c.logical_invert(1000), d) 3232 self.assertRaises(TypeError, c.logical_invert, '1000') 3233 3234 def test_logical_or(self): 3235 Decimal = self.decimal.Decimal 3236 Context = self.decimal.Context 3237 3238 c = Context() 3239 d = c.logical_or(Decimal(1), Decimal(1)) 3240 self.assertEqual(c.logical_or(1, 1), d) 3241 self.assertEqual(c.logical_or(Decimal(1), 1), d) 3242 self.assertEqual(c.logical_or(1, Decimal(1)), d) 3243 self.assertRaises(TypeError, c.logical_or, '1', 1) 3244 self.assertRaises(TypeError, c.logical_or, 1, '1') 3245 3246 def test_logical_xor(self): 3247 Decimal = self.decimal.Decimal 3248 Context = self.decimal.Context 3249 3250 c = Context() 3251 d = c.logical_xor(Decimal(1), Decimal(1)) 3252 self.assertEqual(c.logical_xor(1, 1), d) 3253 self.assertEqual(c.logical_xor(Decimal(1), 1), d) 3254 self.assertEqual(c.logical_xor(1, Decimal(1)), d) 3255 self.assertRaises(TypeError, c.logical_xor, '1', 1) 3256 self.assertRaises(TypeError, c.logical_xor, 1, '1') 3257 3258 def test_max(self): 3259 Decimal = self.decimal.Decimal 3260 Context = self.decimal.Context 3261 3262 c = Context() 3263 d = c.max(Decimal(1), Decimal(2)) 3264 self.assertEqual(c.max(1, 2), d) 3265 self.assertEqual(c.max(Decimal(1), 2), d) 3266 self.assertEqual(c.max(1, Decimal(2)), d) 3267 self.assertRaises(TypeError, c.max, '1', 2) 3268 self.assertRaises(TypeError, c.max, 1, '2') 3269 3270 def test_max_mag(self): 3271 Decimal = self.decimal.Decimal 3272 Context = self.decimal.Context 3273 3274 c = Context() 3275 d = c.max_mag(Decimal(1), Decimal(2)) 3276 self.assertEqual(c.max_mag(1, 2), d) 3277 self.assertEqual(c.max_mag(Decimal(1), 2), d) 3278 self.assertEqual(c.max_mag(1, Decimal(2)), d) 3279 self.assertRaises(TypeError, c.max_mag, '1', 2) 3280 self.assertRaises(TypeError, c.max_mag, 1, '2') 3281 3282 def test_min(self): 3283 Decimal = self.decimal.Decimal 3284 Context = self.decimal.Context 3285 3286 c = Context() 3287 d = c.min(Decimal(1), Decimal(2)) 3288 self.assertEqual(c.min(1, 2), d) 3289 self.assertEqual(c.min(Decimal(1), 2), d) 3290 self.assertEqual(c.min(1, Decimal(2)), d) 3291 self.assertRaises(TypeError, c.min, '1', 2) 3292 self.assertRaises(TypeError, c.min, 1, '2') 3293 3294 def test_min_mag(self): 3295 Decimal = self.decimal.Decimal 3296 Context = self.decimal.Context 3297 3298 c = Context() 3299 d = c.min_mag(Decimal(1), Decimal(2)) 3300 self.assertEqual(c.min_mag(1, 2), d) 3301 self.assertEqual(c.min_mag(Decimal(1), 2), d) 3302 self.assertEqual(c.min_mag(1, Decimal(2)), d) 3303 self.assertRaises(TypeError, c.min_mag, '1', 2) 3304 self.assertRaises(TypeError, c.min_mag, 1, '2') 3305 3306 def test_minus(self): 3307 Decimal = self.decimal.Decimal 3308 Context = self.decimal.Context 3309 3310 c = Context() 3311 d = c.minus(Decimal(10)) 3312 self.assertEqual(c.minus(10), d) 3313 self.assertRaises(TypeError, c.minus, '10') 3314 3315 def test_multiply(self): 3316 Decimal = self.decimal.Decimal 3317 Context = self.decimal.Context 3318 3319 c = Context() 3320 d = c.multiply(Decimal(1), Decimal(2)) 3321 self.assertEqual(c.multiply(1, 2), d) 3322 self.assertEqual(c.multiply(Decimal(1), 2), d) 3323 self.assertEqual(c.multiply(1, Decimal(2)), d) 3324 self.assertRaises(TypeError, c.multiply, '1', 2) 3325 self.assertRaises(TypeError, c.multiply, 1, '2') 3326 3327 def test_next_minus(self): 3328 Decimal = self.decimal.Decimal 3329 Context = self.decimal.Context 3330 3331 c = Context() 3332 d = c.next_minus(Decimal(10)) 3333 self.assertEqual(c.next_minus(10), d) 3334 self.assertRaises(TypeError, c.next_minus, '10') 3335 3336 def test_next_plus(self): 3337 Decimal = self.decimal.Decimal 3338 Context = self.decimal.Context 3339 3340 c = Context() 3341 d = c.next_plus(Decimal(10)) 3342 self.assertEqual(c.next_plus(10), d) 3343 self.assertRaises(TypeError, c.next_plus, '10') 3344 3345 def test_next_toward(self): 3346 Decimal = self.decimal.Decimal 3347 Context = self.decimal.Context 3348 3349 c = Context() 3350 d = c.next_toward(Decimal(1), Decimal(2)) 3351 self.assertEqual(c.next_toward(1, 2), d) 3352 self.assertEqual(c.next_toward(Decimal(1), 2), d) 3353 self.assertEqual(c.next_toward(1, Decimal(2)), d) 3354 self.assertRaises(TypeError, c.next_toward, '1', 2) 3355 self.assertRaises(TypeError, c.next_toward, 1, '2') 3356 3357 def test_normalize(self): 3358 Decimal = self.decimal.Decimal 3359 Context = self.decimal.Context 3360 3361 c = Context() 3362 d = c.normalize(Decimal(10)) 3363 self.assertEqual(c.normalize(10), d) 3364 self.assertRaises(TypeError, c.normalize, '10') 3365 3366 def test_number_class(self): 3367 Decimal = self.decimal.Decimal 3368 Context = self.decimal.Context 3369 3370 c = Context() 3371 self.assertEqual(c.number_class(123), c.number_class(Decimal(123))) 3372 self.assertEqual(c.number_class(0), c.number_class(Decimal(0))) 3373 self.assertEqual(c.number_class(-45), c.number_class(Decimal(-45))) 3374 3375 def test_plus(self): 3376 Decimal = self.decimal.Decimal 3377 Context = self.decimal.Context 3378 3379 c = Context() 3380 d = c.plus(Decimal(10)) 3381 self.assertEqual(c.plus(10), d) 3382 self.assertRaises(TypeError, c.plus, '10') 3383 3384 def test_power(self): 3385 Decimal = self.decimal.Decimal 3386 Context = self.decimal.Context 3387 3388 c = Context() 3389 d = c.power(Decimal(1), Decimal(4)) 3390 self.assertEqual(c.power(1, 4), d) 3391 self.assertEqual(c.power(Decimal(1), 4), d) 3392 self.assertEqual(c.power(1, Decimal(4)), d) 3393 self.assertEqual(c.power(Decimal(1), Decimal(4)), d) 3394 self.assertRaises(TypeError, c.power, '1', 4) 3395 self.assertRaises(TypeError, c.power, 1, '4') 3396 self.assertEqual(c.power(modulo=5, b=8, a=2), 1) 3397 3398 def test_quantize(self): 3399 Decimal = self.decimal.Decimal 3400 Context = self.decimal.Context 3401 3402 c = Context() 3403 d = c.quantize(Decimal(1), Decimal(2)) 3404 self.assertEqual(c.quantize(1, 2), d) 3405 self.assertEqual(c.quantize(Decimal(1), 2), d) 3406 self.assertEqual(c.quantize(1, Decimal(2)), d) 3407 self.assertRaises(TypeError, c.quantize, '1', 2) 3408 self.assertRaises(TypeError, c.quantize, 1, '2') 3409 3410 def test_remainder(self): 3411 Decimal = self.decimal.Decimal 3412 Context = self.decimal.Context 3413 3414 c = Context() 3415 d = c.remainder(Decimal(1), Decimal(2)) 3416 self.assertEqual(c.remainder(1, 2), d) 3417 self.assertEqual(c.remainder(Decimal(1), 2), d) 3418 self.assertEqual(c.remainder(1, Decimal(2)), d) 3419 self.assertRaises(TypeError, c.remainder, '1', 2) 3420 self.assertRaises(TypeError, c.remainder, 1, '2') 3421 3422 def test_remainder_near(self): 3423 Decimal = self.decimal.Decimal 3424 Context = self.decimal.Context 3425 3426 c = Context() 3427 d = c.remainder_near(Decimal(1), Decimal(2)) 3428 self.assertEqual(c.remainder_near(1, 2), d) 3429 self.assertEqual(c.remainder_near(Decimal(1), 2), d) 3430 self.assertEqual(c.remainder_near(1, Decimal(2)), d) 3431 self.assertRaises(TypeError, c.remainder_near, '1', 2) 3432 self.assertRaises(TypeError, c.remainder_near, 1, '2') 3433 3434 def test_rotate(self): 3435 Decimal = self.decimal.Decimal 3436 Context = self.decimal.Context 3437 3438 c = Context() 3439 d = c.rotate(Decimal(1), Decimal(2)) 3440 self.assertEqual(c.rotate(1, 2), d) 3441 self.assertEqual(c.rotate(Decimal(1), 2), d) 3442 self.assertEqual(c.rotate(1, Decimal(2)), d) 3443 self.assertRaises(TypeError, c.rotate, '1', 2) 3444 self.assertRaises(TypeError, c.rotate, 1, '2') 3445 3446 def test_sqrt(self): 3447 Decimal = self.decimal.Decimal 3448 Context = self.decimal.Context 3449 3450 c = Context() 3451 d = c.sqrt(Decimal(10)) 3452 self.assertEqual(c.sqrt(10), d) 3453 self.assertRaises(TypeError, c.sqrt, '10') 3454 3455 def test_same_quantum(self): 3456 Decimal = self.decimal.Decimal 3457 Context = self.decimal.Context 3458 3459 c = Context() 3460 d = c.same_quantum(Decimal(1), Decimal(2)) 3461 self.assertEqual(c.same_quantum(1, 2), d) 3462 self.assertEqual(c.same_quantum(Decimal(1), 2), d) 3463 self.assertEqual(c.same_quantum(1, Decimal(2)), d) 3464 self.assertRaises(TypeError, c.same_quantum, '1', 2) 3465 self.assertRaises(TypeError, c.same_quantum, 1, '2') 3466 3467 def test_scaleb(self): 3468 Decimal = self.decimal.Decimal 3469 Context = self.decimal.Context 3470 3471 c = Context() 3472 d = c.scaleb(Decimal(1), Decimal(2)) 3473 self.assertEqual(c.scaleb(1, 2), d) 3474 self.assertEqual(c.scaleb(Decimal(1), 2), d) 3475 self.assertEqual(c.scaleb(1, Decimal(2)), d) 3476 self.assertRaises(TypeError, c.scaleb, '1', 2) 3477 self.assertRaises(TypeError, c.scaleb, 1, '2') 3478 3479 def test_shift(self): 3480 Decimal = self.decimal.Decimal 3481 Context = self.decimal.Context 3482 3483 c = Context() 3484 d = c.shift(Decimal(1), Decimal(2)) 3485 self.assertEqual(c.shift(1, 2), d) 3486 self.assertEqual(c.shift(Decimal(1), 2), d) 3487 self.assertEqual(c.shift(1, Decimal(2)), d) 3488 self.assertRaises(TypeError, c.shift, '1', 2) 3489 self.assertRaises(TypeError, c.shift, 1, '2') 3490 3491 def test_subtract(self): 3492 Decimal = self.decimal.Decimal 3493 Context = self.decimal.Context 3494 3495 c = Context() 3496 d = c.subtract(Decimal(1), Decimal(2)) 3497 self.assertEqual(c.subtract(1, 2), d) 3498 self.assertEqual(c.subtract(Decimal(1), 2), d) 3499 self.assertEqual(c.subtract(1, Decimal(2)), d) 3500 self.assertRaises(TypeError, c.subtract, '1', 2) 3501 self.assertRaises(TypeError, c.subtract, 1, '2') 3502 3503 def test_to_eng_string(self): 3504 Decimal = self.decimal.Decimal 3505 Context = self.decimal.Context 3506 3507 c = Context() 3508 d = c.to_eng_string(Decimal(10)) 3509 self.assertEqual(c.to_eng_string(10), d) 3510 self.assertRaises(TypeError, c.to_eng_string, '10') 3511 3512 def test_to_sci_string(self): 3513 Decimal = self.decimal.Decimal 3514 Context = self.decimal.Context 3515 3516 c = Context() 3517 d = c.to_sci_string(Decimal(10)) 3518 self.assertEqual(c.to_sci_string(10), d) 3519 self.assertRaises(TypeError, c.to_sci_string, '10') 3520 3521 def test_to_integral_exact(self): 3522 Decimal = self.decimal.Decimal 3523 Context = self.decimal.Context 3524 3525 c = Context() 3526 d = c.to_integral_exact(Decimal(10)) 3527 self.assertEqual(c.to_integral_exact(10), d) 3528 self.assertRaises(TypeError, c.to_integral_exact, '10') 3529 3530 def test_to_integral_value(self): 3531 Decimal = self.decimal.Decimal 3532 Context = self.decimal.Context 3533 3534 c = Context() 3535 d = c.to_integral_value(Decimal(10)) 3536 self.assertEqual(c.to_integral_value(10), d) 3537 self.assertRaises(TypeError, c.to_integral_value, '10') 3538 self.assertRaises(TypeError, c.to_integral_value, 10, 'x') 3539 3540class CContextAPItests(ContextAPItests): 3541 decimal = C 3542class PyContextAPItests(ContextAPItests): 3543 decimal = P 3544 3545class ContextWithStatement(unittest.TestCase): 3546 # Can't do these as docstrings until Python 2.6 3547 # as doctest can't handle __future__ statements 3548 3549 def test_localcontext(self): 3550 # Use a copy of the current context in the block 3551 getcontext = self.decimal.getcontext 3552 localcontext = self.decimal.localcontext 3553 3554 orig_ctx = getcontext() 3555 with localcontext() as enter_ctx: 3556 set_ctx = getcontext() 3557 final_ctx = getcontext() 3558 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly') 3559 self.assertIsNot(orig_ctx, set_ctx, 'did not copy the context') 3560 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context') 3561 3562 def test_localcontextarg(self): 3563 # Use a copy of the supplied context in the block 3564 Context = self.decimal.Context 3565 getcontext = self.decimal.getcontext 3566 localcontext = self.decimal.localcontext 3567 3568 localcontext = self.decimal.localcontext 3569 orig_ctx = getcontext() 3570 new_ctx = Context(prec=42) 3571 with localcontext(new_ctx) as enter_ctx: 3572 set_ctx = getcontext() 3573 final_ctx = getcontext() 3574 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly') 3575 self.assertEqual(set_ctx.prec, new_ctx.prec, 'did not set correct context') 3576 self.assertIsNot(new_ctx, set_ctx, 'did not copy the context') 3577 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context') 3578 3579 def test_nested_with_statements(self): 3580 # Use a copy of the supplied context in the block 3581 Decimal = self.decimal.Decimal 3582 Context = self.decimal.Context 3583 getcontext = self.decimal.getcontext 3584 localcontext = self.decimal.localcontext 3585 Clamped = self.decimal.Clamped 3586 Overflow = self.decimal.Overflow 3587 3588 orig_ctx = getcontext() 3589 orig_ctx.clear_flags() 3590 new_ctx = Context(Emax=384) 3591 with localcontext() as c1: 3592 self.assertEqual(c1.flags, orig_ctx.flags) 3593 self.assertEqual(c1.traps, orig_ctx.traps) 3594 c1.traps[Clamped] = True 3595 c1.Emin = -383 3596 self.assertNotEqual(orig_ctx.Emin, -383) 3597 self.assertRaises(Clamped, c1.create_decimal, '0e-999') 3598 self.assertTrue(c1.flags[Clamped]) 3599 with localcontext(new_ctx) as c2: 3600 self.assertEqual(c2.flags, new_ctx.flags) 3601 self.assertEqual(c2.traps, new_ctx.traps) 3602 self.assertRaises(Overflow, c2.power, Decimal('3.4e200'), 2) 3603 self.assertFalse(c2.flags[Clamped]) 3604 self.assertTrue(c2.flags[Overflow]) 3605 del c2 3606 self.assertFalse(c1.flags[Overflow]) 3607 del c1 3608 self.assertNotEqual(orig_ctx.Emin, -383) 3609 self.assertFalse(orig_ctx.flags[Clamped]) 3610 self.assertFalse(orig_ctx.flags[Overflow]) 3611 self.assertFalse(new_ctx.flags[Clamped]) 3612 self.assertFalse(new_ctx.flags[Overflow]) 3613 3614 def test_with_statements_gc1(self): 3615 localcontext = self.decimal.localcontext 3616 3617 with localcontext() as c1: 3618 del c1 3619 with localcontext() as c2: 3620 del c2 3621 with localcontext() as c3: 3622 del c3 3623 with localcontext() as c4: 3624 del c4 3625 3626 def test_with_statements_gc2(self): 3627 localcontext = self.decimal.localcontext 3628 3629 with localcontext() as c1: 3630 with localcontext(c1) as c2: 3631 del c1 3632 with localcontext(c2) as c3: 3633 del c2 3634 with localcontext(c3) as c4: 3635 del c3 3636 del c4 3637 3638 def test_with_statements_gc3(self): 3639 Context = self.decimal.Context 3640 localcontext = self.decimal.localcontext 3641 getcontext = self.decimal.getcontext 3642 setcontext = self.decimal.setcontext 3643 3644 with localcontext() as c1: 3645 del c1 3646 n1 = Context(prec=1) 3647 setcontext(n1) 3648 with localcontext(n1) as c2: 3649 del n1 3650 self.assertEqual(c2.prec, 1) 3651 del c2 3652 n2 = Context(prec=2) 3653 setcontext(n2) 3654 del n2 3655 self.assertEqual(getcontext().prec, 2) 3656 n3 = Context(prec=3) 3657 setcontext(n3) 3658 self.assertEqual(getcontext().prec, 3) 3659 with localcontext(n3) as c3: 3660 del n3 3661 self.assertEqual(c3.prec, 3) 3662 del c3 3663 n4 = Context(prec=4) 3664 setcontext(n4) 3665 del n4 3666 self.assertEqual(getcontext().prec, 4) 3667 with localcontext() as c4: 3668 self.assertEqual(c4.prec, 4) 3669 del c4 3670 3671class CContextWithStatement(ContextWithStatement): 3672 decimal = C 3673class PyContextWithStatement(ContextWithStatement): 3674 decimal = P 3675 3676class ContextFlags(unittest.TestCase): 3677 3678 def test_flags_irrelevant(self): 3679 # check that the result (numeric result + flags raised) of an 3680 # arithmetic operation doesn't depend on the current flags 3681 Decimal = self.decimal.Decimal 3682 Context = self.decimal.Context 3683 Inexact = self.decimal.Inexact 3684 Rounded = self.decimal.Rounded 3685 Underflow = self.decimal.Underflow 3686 Clamped = self.decimal.Clamped 3687 Subnormal = self.decimal.Subnormal 3688 3689 def raise_error(context, flag): 3690 if self.decimal == C: 3691 context.flags[flag] = True 3692 if context.traps[flag]: 3693 raise flag 3694 else: 3695 context._raise_error(flag) 3696 3697 context = Context(prec=9, Emin = -425000000, Emax = 425000000, 3698 rounding=ROUND_HALF_EVEN, traps=[], flags=[]) 3699 3700 # operations that raise various flags, in the form (function, arglist) 3701 operations = [ 3702 (context._apply, [Decimal("100E-425000010")]), 3703 (context.sqrt, [Decimal(2)]), 3704 (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]), 3705 (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]), 3706 (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]), 3707 ] 3708 3709 # try various flags individually, then a whole lot at once 3710 flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal], 3711 [Inexact, Rounded, Underflow, Clamped, Subnormal]] 3712 3713 for fn, args in operations: 3714 # find answer and flags raised using a clean context 3715 context.clear_flags() 3716 ans = fn(*args) 3717 flags = [k for k, v in context.flags.items() if v] 3718 3719 for extra_flags in flagsets: 3720 # set flags, before calling operation 3721 context.clear_flags() 3722 for flag in extra_flags: 3723 raise_error(context, flag) 3724 new_ans = fn(*args) 3725 3726 # flags that we expect to be set after the operation 3727 expected_flags = list(flags) 3728 for flag in extra_flags: 3729 if flag not in expected_flags: 3730 expected_flags.append(flag) 3731 expected_flags.sort(key=id) 3732 3733 # flags we actually got 3734 new_flags = [k for k,v in context.flags.items() if v] 3735 new_flags.sort(key=id) 3736 3737 self.assertEqual(ans, new_ans, 3738 "operation produces different answers depending on flags set: " + 3739 "expected %s, got %s." % (ans, new_ans)) 3740 self.assertEqual(new_flags, expected_flags, 3741 "operation raises different flags depending on flags set: " + 3742 "expected %s, got %s" % (expected_flags, new_flags)) 3743 3744 def test_flag_comparisons(self): 3745 Context = self.decimal.Context 3746 Inexact = self.decimal.Inexact 3747 Rounded = self.decimal.Rounded 3748 3749 c = Context() 3750 3751 # Valid SignalDict 3752 self.assertNotEqual(c.flags, c.traps) 3753 self.assertNotEqual(c.traps, c.flags) 3754 3755 c.flags = c.traps 3756 self.assertEqual(c.flags, c.traps) 3757 self.assertEqual(c.traps, c.flags) 3758 3759 c.flags[Rounded] = True 3760 c.traps = c.flags 3761 self.assertEqual(c.flags, c.traps) 3762 self.assertEqual(c.traps, c.flags) 3763 3764 d = {} 3765 d.update(c.flags) 3766 self.assertEqual(d, c.flags) 3767 self.assertEqual(c.flags, d) 3768 3769 d[Inexact] = True 3770 self.assertNotEqual(d, c.flags) 3771 self.assertNotEqual(c.flags, d) 3772 3773 # Invalid SignalDict 3774 d = {Inexact:False} 3775 self.assertNotEqual(d, c.flags) 3776 self.assertNotEqual(c.flags, d) 3777 3778 d = ["xyz"] 3779 self.assertNotEqual(d, c.flags) 3780 self.assertNotEqual(c.flags, d) 3781 3782 @requires_IEEE_754 3783 def test_float_operation(self): 3784 Decimal = self.decimal.Decimal 3785 FloatOperation = self.decimal.FloatOperation 3786 localcontext = self.decimal.localcontext 3787 3788 with localcontext() as c: 3789 ##### trap is off by default 3790 self.assertFalse(c.traps[FloatOperation]) 3791 3792 # implicit conversion sets the flag 3793 c.clear_flags() 3794 self.assertEqual(Decimal(7.5), 7.5) 3795 self.assertTrue(c.flags[FloatOperation]) 3796 3797 c.clear_flags() 3798 self.assertEqual(c.create_decimal(7.5), 7.5) 3799 self.assertTrue(c.flags[FloatOperation]) 3800 3801 # explicit conversion does not set the flag 3802 c.clear_flags() 3803 x = Decimal.from_float(7.5) 3804 self.assertFalse(c.flags[FloatOperation]) 3805 # comparison sets the flag 3806 self.assertEqual(x, 7.5) 3807 self.assertTrue(c.flags[FloatOperation]) 3808 3809 c.clear_flags() 3810 x = c.create_decimal_from_float(7.5) 3811 self.assertFalse(c.flags[FloatOperation]) 3812 self.assertEqual(x, 7.5) 3813 self.assertTrue(c.flags[FloatOperation]) 3814 3815 ##### set the trap 3816 c.traps[FloatOperation] = True 3817 3818 # implicit conversion raises 3819 c.clear_flags() 3820 self.assertRaises(FloatOperation, Decimal, 7.5) 3821 self.assertTrue(c.flags[FloatOperation]) 3822 3823 c.clear_flags() 3824 self.assertRaises(FloatOperation, c.create_decimal, 7.5) 3825 self.assertTrue(c.flags[FloatOperation]) 3826 3827 # explicit conversion is silent 3828 c.clear_flags() 3829 x = Decimal.from_float(7.5) 3830 self.assertFalse(c.flags[FloatOperation]) 3831 3832 c.clear_flags() 3833 x = c.create_decimal_from_float(7.5) 3834 self.assertFalse(c.flags[FloatOperation]) 3835 3836 def test_float_comparison(self): 3837 Decimal = self.decimal.Decimal 3838 Context = self.decimal.Context 3839 FloatOperation = self.decimal.FloatOperation 3840 localcontext = self.decimal.localcontext 3841 3842 def assert_attr(a, b, attr, context, signal=None): 3843 context.clear_flags() 3844 f = getattr(a, attr) 3845 if signal == FloatOperation: 3846 self.assertRaises(signal, f, b) 3847 else: 3848 self.assertIs(f(b), True) 3849 self.assertTrue(context.flags[FloatOperation]) 3850 3851 small_d = Decimal('0.25') 3852 big_d = Decimal('3.0') 3853 small_f = 0.25 3854 big_f = 3.0 3855 3856 zero_d = Decimal('0.0') 3857 neg_zero_d = Decimal('-0.0') 3858 zero_f = 0.0 3859 neg_zero_f = -0.0 3860 3861 inf_d = Decimal('Infinity') 3862 neg_inf_d = Decimal('-Infinity') 3863 inf_f = float('inf') 3864 neg_inf_f = float('-inf') 3865 3866 def doit(c, signal=None): 3867 # Order 3868 for attr in '__lt__', '__le__': 3869 assert_attr(small_d, big_f, attr, c, signal) 3870 3871 for attr in '__gt__', '__ge__': 3872 assert_attr(big_d, small_f, attr, c, signal) 3873 3874 # Equality 3875 assert_attr(small_d, small_f, '__eq__', c, None) 3876 3877 assert_attr(neg_zero_d, neg_zero_f, '__eq__', c, None) 3878 assert_attr(neg_zero_d, zero_f, '__eq__', c, None) 3879 3880 assert_attr(zero_d, neg_zero_f, '__eq__', c, None) 3881 assert_attr(zero_d, zero_f, '__eq__', c, None) 3882 3883 assert_attr(neg_inf_d, neg_inf_f, '__eq__', c, None) 3884 assert_attr(inf_d, inf_f, '__eq__', c, None) 3885 3886 # Inequality 3887 assert_attr(small_d, big_f, '__ne__', c, None) 3888 3889 assert_attr(Decimal('0.1'), 0.1, '__ne__', c, None) 3890 3891 assert_attr(neg_inf_d, inf_f, '__ne__', c, None) 3892 assert_attr(inf_d, neg_inf_f, '__ne__', c, None) 3893 3894 assert_attr(Decimal('NaN'), float('nan'), '__ne__', c, None) 3895 3896 def test_containers(c, signal=None): 3897 c.clear_flags() 3898 s = set([100.0, Decimal('100.0')]) 3899 self.assertEqual(len(s), 1) 3900 self.assertTrue(c.flags[FloatOperation]) 3901 3902 c.clear_flags() 3903 if signal: 3904 self.assertRaises(signal, sorted, [1.0, Decimal('10.0')]) 3905 else: 3906 s = sorted([10.0, Decimal('10.0')]) 3907 self.assertTrue(c.flags[FloatOperation]) 3908 3909 c.clear_flags() 3910 b = 10.0 in [Decimal('10.0'), 1.0] 3911 self.assertTrue(c.flags[FloatOperation]) 3912 3913 c.clear_flags() 3914 b = 10.0 in {Decimal('10.0'):'a', 1.0:'b'} 3915 self.assertTrue(c.flags[FloatOperation]) 3916 3917 nc = Context() 3918 with localcontext(nc) as c: 3919 self.assertFalse(c.traps[FloatOperation]) 3920 doit(c, signal=None) 3921 test_containers(c, signal=None) 3922 3923 c.traps[FloatOperation] = True 3924 doit(c, signal=FloatOperation) 3925 test_containers(c, signal=FloatOperation) 3926 3927 def test_float_operation_default(self): 3928 Decimal = self.decimal.Decimal 3929 Context = self.decimal.Context 3930 Inexact = self.decimal.Inexact 3931 FloatOperation= self.decimal.FloatOperation 3932 3933 context = Context() 3934 self.assertFalse(context.flags[FloatOperation]) 3935 self.assertFalse(context.traps[FloatOperation]) 3936 3937 context.clear_traps() 3938 context.traps[Inexact] = True 3939 context.traps[FloatOperation] = True 3940 self.assertTrue(context.traps[FloatOperation]) 3941 self.assertTrue(context.traps[Inexact]) 3942 3943class CContextFlags(ContextFlags): 3944 decimal = C 3945class PyContextFlags(ContextFlags): 3946 decimal = P 3947 3948class SpecialContexts(unittest.TestCase): 3949 """Test the context templates.""" 3950 3951 def test_context_templates(self): 3952 BasicContext = self.decimal.BasicContext 3953 ExtendedContext = self.decimal.ExtendedContext 3954 getcontext = self.decimal.getcontext 3955 setcontext = self.decimal.setcontext 3956 InvalidOperation = self.decimal.InvalidOperation 3957 DivisionByZero = self.decimal.DivisionByZero 3958 Overflow = self.decimal.Overflow 3959 Underflow = self.decimal.Underflow 3960 Clamped = self.decimal.Clamped 3961 3962 assert_signals(self, BasicContext, 'traps', 3963 [InvalidOperation, DivisionByZero, Overflow, Underflow, Clamped] 3964 ) 3965 3966 savecontext = getcontext().copy() 3967 basic_context_prec = BasicContext.prec 3968 extended_context_prec = ExtendedContext.prec 3969 3970 ex = None 3971 try: 3972 BasicContext.prec = ExtendedContext.prec = 441 3973 for template in BasicContext, ExtendedContext: 3974 setcontext(template) 3975 c = getcontext() 3976 self.assertIsNot(c, template) 3977 self.assertEqual(c.prec, 441) 3978 except Exception as e: 3979 ex = e.__class__ 3980 finally: 3981 BasicContext.prec = basic_context_prec 3982 ExtendedContext.prec = extended_context_prec 3983 setcontext(savecontext) 3984 if ex: 3985 raise ex 3986 3987 def test_default_context(self): 3988 DefaultContext = self.decimal.DefaultContext 3989 BasicContext = self.decimal.BasicContext 3990 ExtendedContext = self.decimal.ExtendedContext 3991 getcontext = self.decimal.getcontext 3992 setcontext = self.decimal.setcontext 3993 InvalidOperation = self.decimal.InvalidOperation 3994 DivisionByZero = self.decimal.DivisionByZero 3995 Overflow = self.decimal.Overflow 3996 3997 self.assertEqual(BasicContext.prec, 9) 3998 self.assertEqual(ExtendedContext.prec, 9) 3999 4000 assert_signals(self, DefaultContext, 'traps', 4001 [InvalidOperation, DivisionByZero, Overflow] 4002 ) 4003 4004 savecontext = getcontext().copy() 4005 default_context_prec = DefaultContext.prec 4006 4007 ex = None 4008 try: 4009 c = getcontext() 4010 saveprec = c.prec 4011 4012 DefaultContext.prec = 961 4013 c = getcontext() 4014 self.assertEqual(c.prec, saveprec) 4015 4016 setcontext(DefaultContext) 4017 c = getcontext() 4018 self.assertIsNot(c, DefaultContext) 4019 self.assertEqual(c.prec, 961) 4020 except Exception as e: 4021 ex = e.__class__ 4022 finally: 4023 DefaultContext.prec = default_context_prec 4024 setcontext(savecontext) 4025 if ex: 4026 raise ex 4027 4028class CSpecialContexts(SpecialContexts): 4029 decimal = C 4030class PySpecialContexts(SpecialContexts): 4031 decimal = P 4032 4033class ContextInputValidation(unittest.TestCase): 4034 4035 def test_invalid_context(self): 4036 Context = self.decimal.Context 4037 DefaultContext = self.decimal.DefaultContext 4038 4039 c = DefaultContext.copy() 4040 4041 # prec, Emax 4042 for attr in ['prec', 'Emax']: 4043 setattr(c, attr, 999999) 4044 self.assertEqual(getattr(c, attr), 999999) 4045 self.assertRaises(ValueError, setattr, c, attr, -1) 4046 self.assertRaises(TypeError, setattr, c, attr, 'xyz') 4047 4048 # Emin 4049 setattr(c, 'Emin', -999999) 4050 self.assertEqual(getattr(c, 'Emin'), -999999) 4051 self.assertRaises(ValueError, setattr, c, 'Emin', 1) 4052 self.assertRaises(TypeError, setattr, c, 'Emin', (1,2,3)) 4053 4054 self.assertRaises(TypeError, setattr, c, 'rounding', -1) 4055 self.assertRaises(TypeError, setattr, c, 'rounding', 9) 4056 self.assertRaises(TypeError, setattr, c, 'rounding', 1.0) 4057 self.assertRaises(TypeError, setattr, c, 'rounding', 'xyz') 4058 4059 # capitals, clamp 4060 for attr in ['capitals', 'clamp']: 4061 self.assertRaises(ValueError, setattr, c, attr, -1) 4062 self.assertRaises(ValueError, setattr, c, attr, 2) 4063 self.assertRaises(TypeError, setattr, c, attr, [1,2,3]) 4064 4065 # Invalid attribute 4066 self.assertRaises(AttributeError, setattr, c, 'emax', 100) 4067 4068 # Invalid signal dict 4069 self.assertRaises(TypeError, setattr, c, 'flags', []) 4070 self.assertRaises(KeyError, setattr, c, 'flags', {}) 4071 self.assertRaises(KeyError, setattr, c, 'traps', 4072 {'InvalidOperation':0}) 4073 4074 # Attributes cannot be deleted 4075 for attr in ['prec', 'Emax', 'Emin', 'rounding', 'capitals', 'clamp', 4076 'flags', 'traps']: 4077 self.assertRaises(AttributeError, c.__delattr__, attr) 4078 4079 # Invalid attributes 4080 self.assertRaises(TypeError, getattr, c, 9) 4081 self.assertRaises(TypeError, setattr, c, 9) 4082 4083 # Invalid values in constructor 4084 self.assertRaises(TypeError, Context, rounding=999999) 4085 self.assertRaises(TypeError, Context, rounding='xyz') 4086 self.assertRaises(ValueError, Context, clamp=2) 4087 self.assertRaises(ValueError, Context, capitals=-1) 4088 self.assertRaises(KeyError, Context, flags=["P"]) 4089 self.assertRaises(KeyError, Context, traps=["Q"]) 4090 4091 # Type error in conversion 4092 self.assertRaises(TypeError, Context, flags=(0,1)) 4093 self.assertRaises(TypeError, Context, traps=(1,0)) 4094 4095class CContextInputValidation(ContextInputValidation): 4096 decimal = C 4097class PyContextInputValidation(ContextInputValidation): 4098 decimal = P 4099 4100class ContextSubclassing(unittest.TestCase): 4101 4102 def test_context_subclassing(self): 4103 decimal = self.decimal 4104 Decimal = decimal.Decimal 4105 Context = decimal.Context 4106 Clamped = decimal.Clamped 4107 DivisionByZero = decimal.DivisionByZero 4108 Inexact = decimal.Inexact 4109 Overflow = decimal.Overflow 4110 Rounded = decimal.Rounded 4111 Subnormal = decimal.Subnormal 4112 Underflow = decimal.Underflow 4113 InvalidOperation = decimal.InvalidOperation 4114 4115 class MyContext(Context): 4116 def __init__(self, prec=None, rounding=None, Emin=None, Emax=None, 4117 capitals=None, clamp=None, flags=None, 4118 traps=None): 4119 Context.__init__(self) 4120 if prec is not None: 4121 self.prec = prec 4122 if rounding is not None: 4123 self.rounding = rounding 4124 if Emin is not None: 4125 self.Emin = Emin 4126 if Emax is not None: 4127 self.Emax = Emax 4128 if capitals is not None: 4129 self.capitals = capitals 4130 if clamp is not None: 4131 self.clamp = clamp 4132 if flags is not None: 4133 if isinstance(flags, list): 4134 flags = {v:(v in flags) for v in OrderedSignals[decimal] + flags} 4135 self.flags = flags 4136 if traps is not None: 4137 if isinstance(traps, list): 4138 traps = {v:(v in traps) for v in OrderedSignals[decimal] + traps} 4139 self.traps = traps 4140 4141 c = Context() 4142 d = MyContext() 4143 for attr in ('prec', 'rounding', 'Emin', 'Emax', 'capitals', 'clamp', 4144 'flags', 'traps'): 4145 self.assertEqual(getattr(c, attr), getattr(d, attr)) 4146 4147 # prec 4148 self.assertRaises(ValueError, MyContext, **{'prec':-1}) 4149 c = MyContext(prec=1) 4150 self.assertEqual(c.prec, 1) 4151 self.assertRaises(InvalidOperation, c.quantize, Decimal('9e2'), 0) 4152 4153 # rounding 4154 self.assertRaises(TypeError, MyContext, **{'rounding':'XYZ'}) 4155 c = MyContext(rounding=ROUND_DOWN, prec=1) 4156 self.assertEqual(c.rounding, ROUND_DOWN) 4157 self.assertEqual(c.plus(Decimal('9.9')), 9) 4158 4159 # Emin 4160 self.assertRaises(ValueError, MyContext, **{'Emin':5}) 4161 c = MyContext(Emin=-1, prec=1) 4162 self.assertEqual(c.Emin, -1) 4163 x = c.add(Decimal('1e-99'), Decimal('2.234e-2000')) 4164 self.assertEqual(x, Decimal('0.0')) 4165 for signal in (Inexact, Underflow, Subnormal, Rounded, Clamped): 4166 self.assertTrue(c.flags[signal]) 4167 4168 # Emax 4169 self.assertRaises(ValueError, MyContext, **{'Emax':-1}) 4170 c = MyContext(Emax=1, prec=1) 4171 self.assertEqual(c.Emax, 1) 4172 self.assertRaises(Overflow, c.add, Decimal('1e99'), Decimal('2.234e2000')) 4173 if self.decimal == C: 4174 for signal in (Inexact, Overflow, Rounded): 4175 self.assertTrue(c.flags[signal]) 4176 4177 # capitals 4178 self.assertRaises(ValueError, MyContext, **{'capitals':-1}) 4179 c = MyContext(capitals=0) 4180 self.assertEqual(c.capitals, 0) 4181 x = c.create_decimal('1E222') 4182 self.assertEqual(c.to_sci_string(x), '1e+222') 4183 4184 # clamp 4185 self.assertRaises(ValueError, MyContext, **{'clamp':2}) 4186 c = MyContext(clamp=1, Emax=99) 4187 self.assertEqual(c.clamp, 1) 4188 x = c.plus(Decimal('1e99')) 4189 self.assertEqual(str(x), '1.000000000000000000000000000E+99') 4190 4191 # flags 4192 self.assertRaises(TypeError, MyContext, **{'flags':'XYZ'}) 4193 c = MyContext(flags=[Rounded, DivisionByZero]) 4194 for signal in (Rounded, DivisionByZero): 4195 self.assertTrue(c.flags[signal]) 4196 c.clear_flags() 4197 for signal in OrderedSignals[decimal]: 4198 self.assertFalse(c.flags[signal]) 4199 4200 # traps 4201 self.assertRaises(TypeError, MyContext, **{'traps':'XYZ'}) 4202 c = MyContext(traps=[Rounded, DivisionByZero]) 4203 for signal in (Rounded, DivisionByZero): 4204 self.assertTrue(c.traps[signal]) 4205 c.clear_traps() 4206 for signal in OrderedSignals[decimal]: 4207 self.assertFalse(c.traps[signal]) 4208 4209class CContextSubclassing(ContextSubclassing): 4210 decimal = C 4211class PyContextSubclassing(ContextSubclassing): 4212 decimal = P 4213 4214@skip_if_extra_functionality 4215class CheckAttributes(unittest.TestCase): 4216 4217 def test_module_attributes(self): 4218 4219 # Architecture dependent context limits 4220 self.assertEqual(C.MAX_PREC, P.MAX_PREC) 4221 self.assertEqual(C.MAX_EMAX, P.MAX_EMAX) 4222 self.assertEqual(C.MIN_EMIN, P.MIN_EMIN) 4223 self.assertEqual(C.MIN_ETINY, P.MIN_ETINY) 4224 4225 self.assertTrue(C.HAVE_THREADS is True or C.HAVE_THREADS is False) 4226 self.assertTrue(P.HAVE_THREADS is True or P.HAVE_THREADS is False) 4227 4228 self.assertEqual(C.__version__, P.__version__) 4229 4230 self.assertEqual(dir(C), dir(P)) 4231 4232 def test_context_attributes(self): 4233 4234 x = [s for s in dir(C.Context()) if '__' in s or not s.startswith('_')] 4235 y = [s for s in dir(P.Context()) if '__' in s or not s.startswith('_')] 4236 self.assertEqual(set(x) - set(y), set()) 4237 4238 def test_decimal_attributes(self): 4239 4240 x = [s for s in dir(C.Decimal(9)) if '__' in s or not s.startswith('_')] 4241 y = [s for s in dir(C.Decimal(9)) if '__' in s or not s.startswith('_')] 4242 self.assertEqual(set(x) - set(y), set()) 4243 4244class Coverage(unittest.TestCase): 4245 4246 def test_adjusted(self): 4247 Decimal = self.decimal.Decimal 4248 4249 self.assertEqual(Decimal('1234e9999').adjusted(), 10002) 4250 # XXX raise? 4251 self.assertEqual(Decimal('nan').adjusted(), 0) 4252 self.assertEqual(Decimal('inf').adjusted(), 0) 4253 4254 def test_canonical(self): 4255 Decimal = self.decimal.Decimal 4256 getcontext = self.decimal.getcontext 4257 4258 x = Decimal(9).canonical() 4259 self.assertEqual(x, 9) 4260 4261 c = getcontext() 4262 x = c.canonical(Decimal(9)) 4263 self.assertEqual(x, 9) 4264 4265 def test_context_repr(self): 4266 c = self.decimal.DefaultContext.copy() 4267 4268 c.prec = 425000000 4269 c.Emax = 425000000 4270 c.Emin = -425000000 4271 c.rounding = ROUND_HALF_DOWN 4272 c.capitals = 0 4273 c.clamp = 1 4274 for sig in OrderedSignals[self.decimal]: 4275 c.flags[sig] = False 4276 c.traps[sig] = False 4277 4278 s = c.__repr__() 4279 t = "Context(prec=425000000, rounding=ROUND_HALF_DOWN, " \ 4280 "Emin=-425000000, Emax=425000000, capitals=0, clamp=1, " \ 4281 "flags=[], traps=[])" 4282 self.assertEqual(s, t) 4283 4284 def test_implicit_context(self): 4285 Decimal = self.decimal.Decimal 4286 localcontext = self.decimal.localcontext 4287 4288 with localcontext() as c: 4289 c.prec = 1 4290 c.Emax = 1 4291 c.Emin = -1 4292 4293 # abs 4294 self.assertEqual(abs(Decimal("-10")), 10) 4295 # add 4296 self.assertEqual(Decimal("7") + 1, 8) 4297 # divide 4298 self.assertEqual(Decimal("10") / 5, 2) 4299 # divide_int 4300 self.assertEqual(Decimal("10") // 7, 1) 4301 # fma 4302 self.assertEqual(Decimal("1.2").fma(Decimal("0.01"), 1), 1) 4303 self.assertIs(Decimal("NaN").fma(7, 1).is_nan(), True) 4304 # three arg power 4305 self.assertEqual(pow(Decimal(10), 2, 7), 2) 4306 # exp 4307 self.assertEqual(Decimal("1.01").exp(), 3) 4308 # is_normal 4309 self.assertIs(Decimal("0.01").is_normal(), False) 4310 # is_subnormal 4311 self.assertIs(Decimal("0.01").is_subnormal(), True) 4312 # ln 4313 self.assertEqual(Decimal("20").ln(), 3) 4314 # log10 4315 self.assertEqual(Decimal("20").log10(), 1) 4316 # logb 4317 self.assertEqual(Decimal("580").logb(), 2) 4318 # logical_invert 4319 self.assertEqual(Decimal("10").logical_invert(), 1) 4320 # minus 4321 self.assertEqual(-Decimal("-10"), 10) 4322 # multiply 4323 self.assertEqual(Decimal("2") * 4, 8) 4324 # next_minus 4325 self.assertEqual(Decimal("10").next_minus(), 9) 4326 # next_plus 4327 self.assertEqual(Decimal("10").next_plus(), Decimal('2E+1')) 4328 # normalize 4329 self.assertEqual(Decimal("-10").normalize(), Decimal('-1E+1')) 4330 # number_class 4331 self.assertEqual(Decimal("10").number_class(), '+Normal') 4332 # plus 4333 self.assertEqual(+Decimal("-1"), -1) 4334 # remainder 4335 self.assertEqual(Decimal("10") % 7, 3) 4336 # subtract 4337 self.assertEqual(Decimal("10") - 7, 3) 4338 # to_integral_exact 4339 self.assertEqual(Decimal("1.12345").to_integral_exact(), 1) 4340 4341 # Boolean functions 4342 self.assertTrue(Decimal("1").is_canonical()) 4343 self.assertTrue(Decimal("1").is_finite()) 4344 self.assertTrue(Decimal("1").is_finite()) 4345 self.assertTrue(Decimal("snan").is_snan()) 4346 self.assertTrue(Decimal("-1").is_signed()) 4347 self.assertTrue(Decimal("0").is_zero()) 4348 self.assertTrue(Decimal("0").is_zero()) 4349 4350 # Copy 4351 with localcontext() as c: 4352 c.prec = 10000 4353 x = 1228 ** 1523 4354 y = -Decimal(x) 4355 4356 z = y.copy_abs() 4357 self.assertEqual(z, x) 4358 4359 z = y.copy_negate() 4360 self.assertEqual(z, x) 4361 4362 z = y.copy_sign(Decimal(1)) 4363 self.assertEqual(z, x) 4364 4365 def test_divmod(self): 4366 Decimal = self.decimal.Decimal 4367 localcontext = self.decimal.localcontext 4368 InvalidOperation = self.decimal.InvalidOperation 4369 DivisionByZero = self.decimal.DivisionByZero 4370 4371 with localcontext() as c: 4372 q, r = divmod(Decimal("10912837129"), 1001) 4373 self.assertEqual(q, Decimal('10901935')) 4374 self.assertEqual(r, Decimal('194')) 4375 4376 q, r = divmod(Decimal("NaN"), 7) 4377 self.assertTrue(q.is_nan() and r.is_nan()) 4378 4379 c.traps[InvalidOperation] = False 4380 q, r = divmod(Decimal("NaN"), 7) 4381 self.assertTrue(q.is_nan() and r.is_nan()) 4382 4383 c.traps[InvalidOperation] = False 4384 c.clear_flags() 4385 q, r = divmod(Decimal("inf"), Decimal("inf")) 4386 self.assertTrue(q.is_nan() and r.is_nan()) 4387 self.assertTrue(c.flags[InvalidOperation]) 4388 4389 c.clear_flags() 4390 q, r = divmod(Decimal("inf"), 101) 4391 self.assertTrue(q.is_infinite() and r.is_nan()) 4392 self.assertTrue(c.flags[InvalidOperation]) 4393 4394 c.clear_flags() 4395 q, r = divmod(Decimal(0), 0) 4396 self.assertTrue(q.is_nan() and r.is_nan()) 4397 self.assertTrue(c.flags[InvalidOperation]) 4398 4399 c.traps[DivisionByZero] = False 4400 c.clear_flags() 4401 q, r = divmod(Decimal(11), 0) 4402 self.assertTrue(q.is_infinite() and r.is_nan()) 4403 self.assertTrue(c.flags[InvalidOperation] and 4404 c.flags[DivisionByZero]) 4405 4406 def test_power(self): 4407 Decimal = self.decimal.Decimal 4408 localcontext = self.decimal.localcontext 4409 Overflow = self.decimal.Overflow 4410 Rounded = self.decimal.Rounded 4411 4412 with localcontext() as c: 4413 c.prec = 3 4414 c.clear_flags() 4415 self.assertEqual(Decimal("1.0") ** 100, Decimal('1.00')) 4416 self.assertTrue(c.flags[Rounded]) 4417 4418 c.prec = 1 4419 c.Emax = 1 4420 c.Emin = -1 4421 c.clear_flags() 4422 c.traps[Overflow] = False 4423 self.assertEqual(Decimal(10000) ** Decimal("0.5"), Decimal('inf')) 4424 self.assertTrue(c.flags[Overflow]) 4425 4426 def test_quantize(self): 4427 Decimal = self.decimal.Decimal 4428 localcontext = self.decimal.localcontext 4429 InvalidOperation = self.decimal.InvalidOperation 4430 4431 with localcontext() as c: 4432 c.prec = 1 4433 c.Emax = 1 4434 c.Emin = -1 4435 c.traps[InvalidOperation] = False 4436 x = Decimal(99).quantize(Decimal("1e1")) 4437 self.assertTrue(x.is_nan()) 4438 4439 def test_radix(self): 4440 Decimal = self.decimal.Decimal 4441 getcontext = self.decimal.getcontext 4442 4443 c = getcontext() 4444 self.assertEqual(Decimal("1").radix(), 10) 4445 self.assertEqual(c.radix(), 10) 4446 4447 def test_rop(self): 4448 Decimal = self.decimal.Decimal 4449 4450 for attr in ('__radd__', '__rsub__', '__rmul__', '__rtruediv__', 4451 '__rdivmod__', '__rmod__', '__rfloordiv__', '__rpow__'): 4452 self.assertIs(getattr(Decimal("1"), attr)("xyz"), NotImplemented) 4453 4454 def test_round(self): 4455 # Python3 behavior: round() returns Decimal 4456 Decimal = self.decimal.Decimal 4457 localcontext = self.decimal.localcontext 4458 4459 with localcontext() as c: 4460 c.prec = 28 4461 4462 self.assertEqual(str(Decimal("9.99").__round__()), "10") 4463 self.assertEqual(str(Decimal("9.99e-5").__round__()), "0") 4464 self.assertEqual(str(Decimal("1.23456789").__round__(5)), "1.23457") 4465 self.assertEqual(str(Decimal("1.2345").__round__(10)), "1.2345000000") 4466 self.assertEqual(str(Decimal("1.2345").__round__(-10)), "0E+10") 4467 4468 self.assertRaises(TypeError, Decimal("1.23").__round__, "5") 4469 self.assertRaises(TypeError, Decimal("1.23").__round__, 5, 8) 4470 4471 def test_create_decimal(self): 4472 c = self.decimal.Context() 4473 self.assertRaises(ValueError, c.create_decimal, ["%"]) 4474 4475 def test_int(self): 4476 Decimal = self.decimal.Decimal 4477 localcontext = self.decimal.localcontext 4478 4479 with localcontext() as c: 4480 c.prec = 9999 4481 x = Decimal(1221**1271) / 10**3923 4482 self.assertEqual(int(x), 1) 4483 self.assertEqual(x.to_integral(), 2) 4484 4485 def test_copy(self): 4486 Context = self.decimal.Context 4487 4488 c = Context() 4489 c.prec = 10000 4490 x = -(1172 ** 1712) 4491 4492 y = c.copy_abs(x) 4493 self.assertEqual(y, -x) 4494 4495 y = c.copy_negate(x) 4496 self.assertEqual(y, -x) 4497 4498 y = c.copy_sign(x, 1) 4499 self.assertEqual(y, -x) 4500 4501class CCoverage(Coverage): 4502 decimal = C 4503class PyCoverage(Coverage): 4504 decimal = P 4505 4506class PyFunctionality(unittest.TestCase): 4507 """Extra functionality in decimal.py""" 4508 4509 def test_py_alternate_formatting(self): 4510 # triples giving a format, a Decimal, and the expected result 4511 Decimal = P.Decimal 4512 localcontext = P.localcontext 4513 4514 test_values = [ 4515 # Issue 7094: Alternate formatting (specified by #) 4516 ('.0e', '1.0', '1e+0'), 4517 ('#.0e', '1.0', '1.e+0'), 4518 ('.0f', '1.0', '1'), 4519 ('#.0f', '1.0', '1.'), 4520 ('g', '1.1', '1.1'), 4521 ('#g', '1.1', '1.1'), 4522 ('.0g', '1', '1'), 4523 ('#.0g', '1', '1.'), 4524 ('.0%', '1.0', '100%'), 4525 ('#.0%', '1.0', '100.%'), 4526 ] 4527 for fmt, d, result in test_values: 4528 self.assertEqual(format(Decimal(d), fmt), result) 4529 4530class PyWhitebox(unittest.TestCase): 4531 """White box testing for decimal.py""" 4532 4533 def test_py_exact_power(self): 4534 # Rarely exercised lines in _power_exact. 4535 Decimal = P.Decimal 4536 localcontext = P.localcontext 4537 4538 with localcontext() as c: 4539 c.prec = 8 4540 x = Decimal(2**16) ** Decimal("-0.5") 4541 self.assertEqual(x, Decimal('0.00390625')) 4542 4543 x = Decimal(2**16) ** Decimal("-0.6") 4544 self.assertEqual(x, Decimal('0.0012885819')) 4545 4546 x = Decimal("256e7") ** Decimal("-0.5") 4547 4548 x = Decimal(152587890625) ** Decimal('-0.0625') 4549 self.assertEqual(x, Decimal("0.2")) 4550 4551 x = Decimal("152587890625e7") ** Decimal('-0.0625') 4552 4553 x = Decimal(5**2659) ** Decimal('-0.0625') 4554 4555 c.prec = 1 4556 x = Decimal("152587890625") ** Decimal('-0.5') 4557 c.prec = 201 4558 x = Decimal(2**578) ** Decimal("-0.5") 4559 4560 def test_py_immutability_operations(self): 4561 # Do operations and check that it didn't change internal objects. 4562 Decimal = P.Decimal 4563 DefaultContext = P.DefaultContext 4564 setcontext = P.setcontext 4565 4566 c = DefaultContext.copy() 4567 c.traps = dict((s, 0) for s in OrderedSignals[P]) 4568 setcontext(c) 4569 4570 d1 = Decimal('-25e55') 4571 b1 = Decimal('-25e55') 4572 d2 = Decimal('33e+33') 4573 b2 = Decimal('33e+33') 4574 4575 def checkSameDec(operation, useOther=False): 4576 if useOther: 4577 eval("d1." + operation + "(d2)") 4578 self.assertEqual(d1._sign, b1._sign) 4579 self.assertEqual(d1._int, b1._int) 4580 self.assertEqual(d1._exp, b1._exp) 4581 self.assertEqual(d2._sign, b2._sign) 4582 self.assertEqual(d2._int, b2._int) 4583 self.assertEqual(d2._exp, b2._exp) 4584 else: 4585 eval("d1." + operation + "()") 4586 self.assertEqual(d1._sign, b1._sign) 4587 self.assertEqual(d1._int, b1._int) 4588 self.assertEqual(d1._exp, b1._exp) 4589 4590 Decimal(d1) 4591 self.assertEqual(d1._sign, b1._sign) 4592 self.assertEqual(d1._int, b1._int) 4593 self.assertEqual(d1._exp, b1._exp) 4594 4595 checkSameDec("__abs__") 4596 checkSameDec("__add__", True) 4597 checkSameDec("__divmod__", True) 4598 checkSameDec("__eq__", True) 4599 checkSameDec("__ne__", True) 4600 checkSameDec("__le__", True) 4601 checkSameDec("__lt__", True) 4602 checkSameDec("__ge__", True) 4603 checkSameDec("__gt__", True) 4604 checkSameDec("__float__") 4605 checkSameDec("__floordiv__", True) 4606 checkSameDec("__hash__") 4607 checkSameDec("__int__") 4608 checkSameDec("__trunc__") 4609 checkSameDec("__mod__", True) 4610 checkSameDec("__mul__", True) 4611 checkSameDec("__neg__") 4612 checkSameDec("__bool__") 4613 checkSameDec("__pos__") 4614 checkSameDec("__pow__", True) 4615 checkSameDec("__radd__", True) 4616 checkSameDec("__rdivmod__", True) 4617 checkSameDec("__repr__") 4618 checkSameDec("__rfloordiv__", True) 4619 checkSameDec("__rmod__", True) 4620 checkSameDec("__rmul__", True) 4621 checkSameDec("__rpow__", True) 4622 checkSameDec("__rsub__", True) 4623 checkSameDec("__str__") 4624 checkSameDec("__sub__", True) 4625 checkSameDec("__truediv__", True) 4626 checkSameDec("adjusted") 4627 checkSameDec("as_tuple") 4628 checkSameDec("compare", True) 4629 checkSameDec("max", True) 4630 checkSameDec("min", True) 4631 checkSameDec("normalize") 4632 checkSameDec("quantize", True) 4633 checkSameDec("remainder_near", True) 4634 checkSameDec("same_quantum", True) 4635 checkSameDec("sqrt") 4636 checkSameDec("to_eng_string") 4637 checkSameDec("to_integral") 4638 4639 def test_py_decimal_id(self): 4640 Decimal = P.Decimal 4641 4642 d = Decimal(45) 4643 e = Decimal(d) 4644 self.assertEqual(str(e), '45') 4645 self.assertNotEqual(id(d), id(e)) 4646 4647 def test_py_rescale(self): 4648 # Coverage 4649 Decimal = P.Decimal 4650 localcontext = P.localcontext 4651 4652 with localcontext() as c: 4653 x = Decimal("NaN")._rescale(3, ROUND_UP) 4654 self.assertTrue(x.is_nan()) 4655 4656 def test_py__round(self): 4657 # Coverage 4658 Decimal = P.Decimal 4659 4660 self.assertRaises(ValueError, Decimal("3.1234")._round, 0, ROUND_UP) 4661 4662class CFunctionality(unittest.TestCase): 4663 """Extra functionality in _decimal""" 4664 4665 @requires_extra_functionality 4666 def test_c_ieee_context(self): 4667 # issue 8786: Add support for IEEE 754 contexts to decimal module. 4668 IEEEContext = C.IEEEContext 4669 DECIMAL32 = C.DECIMAL32 4670 DECIMAL64 = C.DECIMAL64 4671 DECIMAL128 = C.DECIMAL128 4672 4673 def assert_rest(self, context): 4674 self.assertEqual(context.clamp, 1) 4675 assert_signals(self, context, 'traps', []) 4676 assert_signals(self, context, 'flags', []) 4677 4678 c = IEEEContext(DECIMAL32) 4679 self.assertEqual(c.prec, 7) 4680 self.assertEqual(c.Emax, 96) 4681 self.assertEqual(c.Emin, -95) 4682 assert_rest(self, c) 4683 4684 c = IEEEContext(DECIMAL64) 4685 self.assertEqual(c.prec, 16) 4686 self.assertEqual(c.Emax, 384) 4687 self.assertEqual(c.Emin, -383) 4688 assert_rest(self, c) 4689 4690 c = IEEEContext(DECIMAL128) 4691 self.assertEqual(c.prec, 34) 4692 self.assertEqual(c.Emax, 6144) 4693 self.assertEqual(c.Emin, -6143) 4694 assert_rest(self, c) 4695 4696 # Invalid values 4697 self.assertRaises(OverflowError, IEEEContext, 2**63) 4698 self.assertRaises(ValueError, IEEEContext, -1) 4699 self.assertRaises(ValueError, IEEEContext, 1024) 4700 4701 @requires_extra_functionality 4702 def test_c_context(self): 4703 Context = C.Context 4704 4705 c = Context(flags=C.DecClamped, traps=C.DecRounded) 4706 self.assertEqual(c._flags, C.DecClamped) 4707 self.assertEqual(c._traps, C.DecRounded) 4708 4709 @requires_extra_functionality 4710 def test_constants(self): 4711 # Condition flags 4712 cond = ( 4713 C.DecClamped, C.DecConversionSyntax, C.DecDivisionByZero, 4714 C.DecDivisionImpossible, C.DecDivisionUndefined, 4715 C.DecFpuError, C.DecInexact, C.DecInvalidContext, 4716 C.DecInvalidOperation, C.DecMallocError, 4717 C.DecFloatOperation, C.DecOverflow, C.DecRounded, 4718 C.DecSubnormal, C.DecUnderflow 4719 ) 4720 4721 # IEEEContext 4722 self.assertEqual(C.DECIMAL32, 32) 4723 self.assertEqual(C.DECIMAL64, 64) 4724 self.assertEqual(C.DECIMAL128, 128) 4725 self.assertEqual(C.IEEE_CONTEXT_MAX_BITS, 512) 4726 4727 # Conditions 4728 for i, v in enumerate(cond): 4729 self.assertEqual(v, 1<<i) 4730 4731 self.assertEqual(C.DecIEEEInvalidOperation, 4732 C.DecConversionSyntax| 4733 C.DecDivisionImpossible| 4734 C.DecDivisionUndefined| 4735 C.DecFpuError| 4736 C.DecInvalidContext| 4737 C.DecInvalidOperation| 4738 C.DecMallocError) 4739 4740 self.assertEqual(C.DecErrors, 4741 C.DecIEEEInvalidOperation| 4742 C.DecDivisionByZero) 4743 4744 self.assertEqual(C.DecTraps, 4745 C.DecErrors|C.DecOverflow|C.DecUnderflow) 4746 4747class CWhitebox(unittest.TestCase): 4748 """Whitebox testing for _decimal""" 4749 4750 def test_bignum(self): 4751 # Not exactly whitebox, but too slow with pydecimal. 4752 4753 Decimal = C.Decimal 4754 localcontext = C.localcontext 4755 4756 b1 = 10**35 4757 b2 = 10**36 4758 with localcontext() as c: 4759 c.prec = 1000000 4760 for i in range(5): 4761 a = random.randrange(b1, b2) 4762 b = random.randrange(1000, 1200) 4763 x = a ** b 4764 y = Decimal(a) ** Decimal(b) 4765 self.assertEqual(x, y) 4766 4767 def test_invalid_construction(self): 4768 self.assertRaises(TypeError, C.Decimal, 9, "xyz") 4769 4770 def test_c_input_restriction(self): 4771 # Too large for _decimal to be converted exactly 4772 Decimal = C.Decimal 4773 InvalidOperation = C.InvalidOperation 4774 Context = C.Context 4775 localcontext = C.localcontext 4776 4777 with localcontext(Context()): 4778 self.assertRaises(InvalidOperation, Decimal, 4779 "1e9999999999999999999") 4780 4781 def test_c_context_repr(self): 4782 # This test is _decimal-only because flags are not printed 4783 # in the same order. 4784 DefaultContext = C.DefaultContext 4785 FloatOperation = C.FloatOperation 4786 4787 c = DefaultContext.copy() 4788 4789 c.prec = 425000000 4790 c.Emax = 425000000 4791 c.Emin = -425000000 4792 c.rounding = ROUND_HALF_DOWN 4793 c.capitals = 0 4794 c.clamp = 1 4795 for sig in OrderedSignals[C]: 4796 c.flags[sig] = True 4797 c.traps[sig] = True 4798 c.flags[FloatOperation] = True 4799 c.traps[FloatOperation] = True 4800 4801 s = c.__repr__() 4802 t = "Context(prec=425000000, rounding=ROUND_HALF_DOWN, " \ 4803 "Emin=-425000000, Emax=425000000, capitals=0, clamp=1, " \ 4804 "flags=[Clamped, InvalidOperation, DivisionByZero, Inexact, " \ 4805 "FloatOperation, Overflow, Rounded, Subnormal, Underflow], " \ 4806 "traps=[Clamped, InvalidOperation, DivisionByZero, Inexact, " \ 4807 "FloatOperation, Overflow, Rounded, Subnormal, Underflow])" 4808 self.assertEqual(s, t) 4809 4810 def test_c_context_errors(self): 4811 Context = C.Context 4812 InvalidOperation = C.InvalidOperation 4813 Overflow = C.Overflow 4814 FloatOperation = C.FloatOperation 4815 localcontext = C.localcontext 4816 getcontext = C.getcontext 4817 setcontext = C.setcontext 4818 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000) 4819 4820 c = Context() 4821 4822 # SignalDict: input validation 4823 self.assertRaises(KeyError, c.flags.__setitem__, 801, 0) 4824 self.assertRaises(KeyError, c.traps.__setitem__, 801, 0) 4825 self.assertRaises(ValueError, c.flags.__delitem__, Overflow) 4826 self.assertRaises(ValueError, c.traps.__delitem__, InvalidOperation) 4827 self.assertRaises(TypeError, setattr, c, 'flags', ['x']) 4828 self.assertRaises(TypeError, setattr, c,'traps', ['y']) 4829 self.assertRaises(KeyError, setattr, c, 'flags', {0:1}) 4830 self.assertRaises(KeyError, setattr, c, 'traps', {0:1}) 4831 4832 # Test assignment from a signal dict with the correct length but 4833 # one invalid key. 4834 d = c.flags.copy() 4835 del d[FloatOperation] 4836 d["XYZ"] = 91283719 4837 self.assertRaises(KeyError, setattr, c, 'flags', d) 4838 self.assertRaises(KeyError, setattr, c, 'traps', d) 4839 4840 # Input corner cases 4841 int_max = 2**63-1 if HAVE_CONFIG_64 else 2**31-1 4842 gt_max_emax = 10**18 if HAVE_CONFIG_64 else 10**9 4843 4844 # prec, Emax, Emin 4845 for attr in ['prec', 'Emax']: 4846 self.assertRaises(ValueError, setattr, c, attr, gt_max_emax) 4847 self.assertRaises(ValueError, setattr, c, 'Emin', -gt_max_emax) 4848 4849 # prec, Emax, Emin in context constructor 4850 self.assertRaises(ValueError, Context, prec=gt_max_emax) 4851 self.assertRaises(ValueError, Context, Emax=gt_max_emax) 4852 self.assertRaises(ValueError, Context, Emin=-gt_max_emax) 4853 4854 # Overflow in conversion 4855 self.assertRaises(OverflowError, Context, prec=int_max+1) 4856 self.assertRaises(OverflowError, Context, Emax=int_max+1) 4857 self.assertRaises(OverflowError, Context, Emin=-int_max-2) 4858 self.assertRaises(OverflowError, Context, clamp=int_max+1) 4859 self.assertRaises(OverflowError, Context, capitals=int_max+1) 4860 4861 # OverflowError, general ValueError 4862 for attr in ('prec', 'Emin', 'Emax', 'capitals', 'clamp'): 4863 self.assertRaises(OverflowError, setattr, c, attr, int_max+1) 4864 self.assertRaises(OverflowError, setattr, c, attr, -int_max-2) 4865 if sys.platform != 'win32': 4866 self.assertRaises(ValueError, setattr, c, attr, int_max) 4867 self.assertRaises(ValueError, setattr, c, attr, -int_max-1) 4868 4869 # OverflowError: _unsafe_setprec, _unsafe_setemin, _unsafe_setemax 4870 if C.MAX_PREC == 425000000: 4871 self.assertRaises(OverflowError, getattr(c, '_unsafe_setprec'), 4872 int_max+1) 4873 self.assertRaises(OverflowError, getattr(c, '_unsafe_setemax'), 4874 int_max+1) 4875 self.assertRaises(OverflowError, getattr(c, '_unsafe_setemin'), 4876 -int_max-2) 4877 4878 # ValueError: _unsafe_setprec, _unsafe_setemin, _unsafe_setemax 4879 if C.MAX_PREC == 425000000: 4880 self.assertRaises(ValueError, getattr(c, '_unsafe_setprec'), 0) 4881 self.assertRaises(ValueError, getattr(c, '_unsafe_setprec'), 4882 1070000001) 4883 self.assertRaises(ValueError, getattr(c, '_unsafe_setemax'), -1) 4884 self.assertRaises(ValueError, getattr(c, '_unsafe_setemax'), 4885 1070000001) 4886 self.assertRaises(ValueError, getattr(c, '_unsafe_setemin'), 4887 -1070000001) 4888 self.assertRaises(ValueError, getattr(c, '_unsafe_setemin'), 1) 4889 4890 # capitals, clamp 4891 for attr in ['capitals', 'clamp']: 4892 self.assertRaises(ValueError, setattr, c, attr, -1) 4893 self.assertRaises(ValueError, setattr, c, attr, 2) 4894 self.assertRaises(TypeError, setattr, c, attr, [1,2,3]) 4895 if HAVE_CONFIG_64: 4896 self.assertRaises(ValueError, setattr, c, attr, 2**32) 4897 self.assertRaises(ValueError, setattr, c, attr, 2**32+1) 4898 4899 # Invalid local context 4900 self.assertRaises(TypeError, exec, 'with localcontext("xyz"): pass', 4901 locals()) 4902 self.assertRaises(TypeError, exec, 4903 'with localcontext(context=getcontext()): pass', 4904 locals()) 4905 4906 # setcontext 4907 saved_context = getcontext() 4908 self.assertRaises(TypeError, setcontext, "xyz") 4909 setcontext(saved_context) 4910 4911 def test_rounding_strings_interned(self): 4912 4913 self.assertIs(C.ROUND_UP, P.ROUND_UP) 4914 self.assertIs(C.ROUND_DOWN, P.ROUND_DOWN) 4915 self.assertIs(C.ROUND_CEILING, P.ROUND_CEILING) 4916 self.assertIs(C.ROUND_FLOOR, P.ROUND_FLOOR) 4917 self.assertIs(C.ROUND_HALF_UP, P.ROUND_HALF_UP) 4918 self.assertIs(C.ROUND_HALF_DOWN, P.ROUND_HALF_DOWN) 4919 self.assertIs(C.ROUND_HALF_EVEN, P.ROUND_HALF_EVEN) 4920 self.assertIs(C.ROUND_05UP, P.ROUND_05UP) 4921 4922 @requires_extra_functionality 4923 def test_c_context_errors_extra(self): 4924 Context = C.Context 4925 InvalidOperation = C.InvalidOperation 4926 Overflow = C.Overflow 4927 localcontext = C.localcontext 4928 getcontext = C.getcontext 4929 setcontext = C.setcontext 4930 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000) 4931 4932 c = Context() 4933 4934 # Input corner cases 4935 int_max = 2**63-1 if HAVE_CONFIG_64 else 2**31-1 4936 4937 # OverflowError, general ValueError 4938 self.assertRaises(OverflowError, setattr, c, '_allcr', int_max+1) 4939 self.assertRaises(OverflowError, setattr, c, '_allcr', -int_max-2) 4940 if sys.platform != 'win32': 4941 self.assertRaises(ValueError, setattr, c, '_allcr', int_max) 4942 self.assertRaises(ValueError, setattr, c, '_allcr', -int_max-1) 4943 4944 # OverflowError, general TypeError 4945 for attr in ('_flags', '_traps'): 4946 self.assertRaises(OverflowError, setattr, c, attr, int_max+1) 4947 self.assertRaises(OverflowError, setattr, c, attr, -int_max-2) 4948 if sys.platform != 'win32': 4949 self.assertRaises(TypeError, setattr, c, attr, int_max) 4950 self.assertRaises(TypeError, setattr, c, attr, -int_max-1) 4951 4952 # _allcr 4953 self.assertRaises(ValueError, setattr, c, '_allcr', -1) 4954 self.assertRaises(ValueError, setattr, c, '_allcr', 2) 4955 self.assertRaises(TypeError, setattr, c, '_allcr', [1,2,3]) 4956 if HAVE_CONFIG_64: 4957 self.assertRaises(ValueError, setattr, c, '_allcr', 2**32) 4958 self.assertRaises(ValueError, setattr, c, '_allcr', 2**32+1) 4959 4960 # _flags, _traps 4961 for attr in ['_flags', '_traps']: 4962 self.assertRaises(TypeError, setattr, c, attr, 999999) 4963 self.assertRaises(TypeError, setattr, c, attr, 'x') 4964 4965 def test_c_valid_context(self): 4966 # These tests are for code coverage in _decimal. 4967 DefaultContext = C.DefaultContext 4968 Clamped = C.Clamped 4969 Underflow = C.Underflow 4970 Inexact = C.Inexact 4971 Rounded = C.Rounded 4972 Subnormal = C.Subnormal 4973 4974 c = DefaultContext.copy() 4975 4976 # Exercise all getters and setters 4977 c.prec = 34 4978 c.rounding = ROUND_HALF_UP 4979 c.Emax = 3000 4980 c.Emin = -3000 4981 c.capitals = 1 4982 c.clamp = 0 4983 4984 self.assertEqual(c.prec, 34) 4985 self.assertEqual(c.rounding, ROUND_HALF_UP) 4986 self.assertEqual(c.Emin, -3000) 4987 self.assertEqual(c.Emax, 3000) 4988 self.assertEqual(c.capitals, 1) 4989 self.assertEqual(c.clamp, 0) 4990 4991 self.assertEqual(c.Etiny(), -3033) 4992 self.assertEqual(c.Etop(), 2967) 4993 4994 # Exercise all unsafe setters 4995 if C.MAX_PREC == 425000000: 4996 c._unsafe_setprec(999999999) 4997 c._unsafe_setemax(999999999) 4998 c._unsafe_setemin(-999999999) 4999 self.assertEqual(c.prec, 999999999) 5000 self.assertEqual(c.Emax, 999999999) 5001 self.assertEqual(c.Emin, -999999999) 5002 5003 @requires_extra_functionality 5004 def test_c_valid_context_extra(self): 5005 DefaultContext = C.DefaultContext 5006 5007 c = DefaultContext.copy() 5008 self.assertEqual(c._allcr, 1) 5009 c._allcr = 0 5010 self.assertEqual(c._allcr, 0) 5011 5012 def test_c_round(self): 5013 # Restricted input. 5014 Decimal = C.Decimal 5015 InvalidOperation = C.InvalidOperation 5016 localcontext = C.localcontext 5017 MAX_EMAX = C.MAX_EMAX 5018 MIN_ETINY = C.MIN_ETINY 5019 int_max = 2**63-1 if C.MAX_PREC > 425000000 else 2**31-1 5020 5021 with localcontext() as c: 5022 c.traps[InvalidOperation] = True 5023 self.assertRaises(InvalidOperation, Decimal("1.23").__round__, 5024 -int_max-1) 5025 self.assertRaises(InvalidOperation, Decimal("1.23").__round__, 5026 int_max) 5027 self.assertRaises(InvalidOperation, Decimal("1").__round__, 5028 int(MAX_EMAX+1)) 5029 self.assertRaises(C.InvalidOperation, Decimal("1").__round__, 5030 -int(MIN_ETINY-1)) 5031 self.assertRaises(OverflowError, Decimal("1.23").__round__, 5032 -int_max-2) 5033 self.assertRaises(OverflowError, Decimal("1.23").__round__, 5034 int_max+1) 5035 5036 def test_c_format(self): 5037 # Restricted input 5038 Decimal = C.Decimal 5039 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000) 5040 5041 self.assertRaises(TypeError, Decimal(1).__format__, "=10.10", [], 9) 5042 self.assertRaises(TypeError, Decimal(1).__format__, "=10.10", 9) 5043 self.assertRaises(TypeError, Decimal(1).__format__, []) 5044 5045 self.assertRaises(ValueError, Decimal(1).__format__, "<>=10.10") 5046 maxsize = 2**63-1 if HAVE_CONFIG_64 else 2**31-1 5047 self.assertRaises(ValueError, Decimal("1.23456789").__format__, 5048 "=%d.1" % maxsize) 5049 5050 def test_c_integral(self): 5051 Decimal = C.Decimal 5052 Inexact = C.Inexact 5053 localcontext = C.localcontext 5054 5055 x = Decimal(10) 5056 self.assertEqual(x.to_integral(), 10) 5057 self.assertRaises(TypeError, x.to_integral, '10') 5058 self.assertRaises(TypeError, x.to_integral, 10, 'x') 5059 self.assertRaises(TypeError, x.to_integral, 10) 5060 5061 self.assertEqual(x.to_integral_value(), 10) 5062 self.assertRaises(TypeError, x.to_integral_value, '10') 5063 self.assertRaises(TypeError, x.to_integral_value, 10, 'x') 5064 self.assertRaises(TypeError, x.to_integral_value, 10) 5065 5066 self.assertEqual(x.to_integral_exact(), 10) 5067 self.assertRaises(TypeError, x.to_integral_exact, '10') 5068 self.assertRaises(TypeError, x.to_integral_exact, 10, 'x') 5069 self.assertRaises(TypeError, x.to_integral_exact, 10) 5070 5071 with localcontext() as c: 5072 x = Decimal("99999999999999999999999999.9").to_integral_value(ROUND_UP) 5073 self.assertEqual(x, Decimal('100000000000000000000000000')) 5074 5075 x = Decimal("99999999999999999999999999.9").to_integral_exact(ROUND_UP) 5076 self.assertEqual(x, Decimal('100000000000000000000000000')) 5077 5078 c.traps[Inexact] = True 5079 self.assertRaises(Inexact, Decimal("999.9").to_integral_exact, ROUND_UP) 5080 5081 def test_c_funcs(self): 5082 # Invalid arguments 5083 Decimal = C.Decimal 5084 InvalidOperation = C.InvalidOperation 5085 DivisionByZero = C.DivisionByZero 5086 getcontext = C.getcontext 5087 localcontext = C.localcontext 5088 5089 self.assertEqual(Decimal('9.99e10').to_eng_string(), '99.9E+9') 5090 5091 self.assertRaises(TypeError, pow, Decimal(1), 2, "3") 5092 self.assertRaises(TypeError, Decimal(9).number_class, "x", "y") 5093 self.assertRaises(TypeError, Decimal(9).same_quantum, 3, "x", "y") 5094 5095 self.assertRaises( 5096 TypeError, 5097 Decimal("1.23456789").quantize, Decimal('1e-100000'), [] 5098 ) 5099 self.assertRaises( 5100 TypeError, 5101 Decimal("1.23456789").quantize, Decimal('1e-100000'), getcontext() 5102 ) 5103 self.assertRaises( 5104 TypeError, 5105 Decimal("1.23456789").quantize, Decimal('1e-100000'), 10 5106 ) 5107 self.assertRaises( 5108 TypeError, 5109 Decimal("1.23456789").quantize, Decimal('1e-100000'), ROUND_UP, 1000 5110 ) 5111 5112 with localcontext() as c: 5113 c.clear_traps() 5114 5115 # Invalid arguments 5116 self.assertRaises(TypeError, c.copy_sign, Decimal(1), "x", "y") 5117 self.assertRaises(TypeError, c.canonical, 200) 5118 self.assertRaises(TypeError, c.is_canonical, 200) 5119 self.assertRaises(TypeError, c.divmod, 9, 8, "x", "y") 5120 self.assertRaises(TypeError, c.same_quantum, 9, 3, "x", "y") 5121 5122 self.assertEqual(str(c.canonical(Decimal(200))), '200') 5123 self.assertEqual(c.radix(), 10) 5124 5125 c.traps[DivisionByZero] = True 5126 self.assertRaises(DivisionByZero, Decimal(9).__divmod__, 0) 5127 self.assertRaises(DivisionByZero, c.divmod, 9, 0) 5128 self.assertTrue(c.flags[InvalidOperation]) 5129 5130 c.clear_flags() 5131 c.traps[InvalidOperation] = True 5132 self.assertRaises(InvalidOperation, Decimal(9).__divmod__, 0) 5133 self.assertRaises(InvalidOperation, c.divmod, 9, 0) 5134 self.assertTrue(c.flags[DivisionByZero]) 5135 5136 c.traps[InvalidOperation] = True 5137 c.prec = 2 5138 self.assertRaises(InvalidOperation, pow, Decimal(1000), 1, 501) 5139 5140 def test_va_args_exceptions(self): 5141 Decimal = C.Decimal 5142 Context = C.Context 5143 5144 x = Decimal("10001111111") 5145 5146 for attr in ['exp', 'is_normal', 'is_subnormal', 'ln', 'log10', 5147 'logb', 'logical_invert', 'next_minus', 'next_plus', 5148 'normalize', 'number_class', 'sqrt', 'to_eng_string']: 5149 func = getattr(x, attr) 5150 self.assertRaises(TypeError, func, context="x") 5151 self.assertRaises(TypeError, func, "x", context=None) 5152 5153 for attr in ['compare', 'compare_signal', 'logical_and', 5154 'logical_or', 'max', 'max_mag', 'min', 'min_mag', 5155 'remainder_near', 'rotate', 'scaleb', 'shift']: 5156 func = getattr(x, attr) 5157 self.assertRaises(TypeError, func, context="x") 5158 self.assertRaises(TypeError, func, "x", context=None) 5159 5160 self.assertRaises(TypeError, x.to_integral, rounding=None, context=[]) 5161 self.assertRaises(TypeError, x.to_integral, rounding={}, context=[]) 5162 self.assertRaises(TypeError, x.to_integral, [], []) 5163 5164 self.assertRaises(TypeError, x.to_integral_value, rounding=None, context=[]) 5165 self.assertRaises(TypeError, x.to_integral_value, rounding={}, context=[]) 5166 self.assertRaises(TypeError, x.to_integral_value, [], []) 5167 5168 self.assertRaises(TypeError, x.to_integral_exact, rounding=None, context=[]) 5169 self.assertRaises(TypeError, x.to_integral_exact, rounding={}, context=[]) 5170 self.assertRaises(TypeError, x.to_integral_exact, [], []) 5171 5172 self.assertRaises(TypeError, x.fma, 1, 2, context="x") 5173 self.assertRaises(TypeError, x.fma, 1, 2, "x", context=None) 5174 5175 self.assertRaises(TypeError, x.quantize, 1, [], context=None) 5176 self.assertRaises(TypeError, x.quantize, 1, [], rounding=None) 5177 self.assertRaises(TypeError, x.quantize, 1, [], []) 5178 5179 c = Context() 5180 self.assertRaises(TypeError, c.power, 1, 2, mod="x") 5181 self.assertRaises(TypeError, c.power, 1, "x", mod=None) 5182 self.assertRaises(TypeError, c.power, "x", 2, mod=None) 5183 5184 @requires_extra_functionality 5185 def test_c_context_templates(self): 5186 self.assertEqual( 5187 C.BasicContext._traps, 5188 C.DecIEEEInvalidOperation|C.DecDivisionByZero|C.DecOverflow| 5189 C.DecUnderflow|C.DecClamped 5190 ) 5191 self.assertEqual( 5192 C.DefaultContext._traps, 5193 C.DecIEEEInvalidOperation|C.DecDivisionByZero|C.DecOverflow 5194 ) 5195 5196 @requires_extra_functionality 5197 def test_c_signal_dict(self): 5198 5199 # SignalDict coverage 5200 Context = C.Context 5201 DefaultContext = C.DefaultContext 5202 5203 InvalidOperation = C.InvalidOperation 5204 DivisionByZero = C.DivisionByZero 5205 Overflow = C.Overflow 5206 Subnormal = C.Subnormal 5207 Underflow = C.Underflow 5208 Rounded = C.Rounded 5209 Inexact = C.Inexact 5210 Clamped = C.Clamped 5211 5212 DecClamped = C.DecClamped 5213 DecInvalidOperation = C.DecInvalidOperation 5214 DecIEEEInvalidOperation = C.DecIEEEInvalidOperation 5215 5216 def assertIsExclusivelySet(signal, signal_dict): 5217 for sig in signal_dict: 5218 if sig == signal: 5219 self.assertTrue(signal_dict[sig]) 5220 else: 5221 self.assertFalse(signal_dict[sig]) 5222 5223 c = DefaultContext.copy() 5224 5225 # Signal dict methods 5226 self.assertTrue(Overflow in c.traps) 5227 c.clear_traps() 5228 for k in c.traps.keys(): 5229 c.traps[k] = True 5230 for v in c.traps.values(): 5231 self.assertTrue(v) 5232 c.clear_traps() 5233 for k, v in c.traps.items(): 5234 self.assertFalse(v) 5235 5236 self.assertFalse(c.flags.get(Overflow)) 5237 self.assertIs(c.flags.get("x"), None) 5238 self.assertEqual(c.flags.get("x", "y"), "y") 5239 self.assertRaises(TypeError, c.flags.get, "x", "y", "z") 5240 5241 self.assertEqual(len(c.flags), len(c.traps)) 5242 s = sys.getsizeof(c.flags) 5243 s = sys.getsizeof(c.traps) 5244 s = c.flags.__repr__() 5245 5246 # Set flags/traps. 5247 c.clear_flags() 5248 c._flags = DecClamped 5249 self.assertTrue(c.flags[Clamped]) 5250 5251 c.clear_traps() 5252 c._traps = DecInvalidOperation 5253 self.assertTrue(c.traps[InvalidOperation]) 5254 5255 # Set flags/traps from dictionary. 5256 c.clear_flags() 5257 d = c.flags.copy() 5258 d[DivisionByZero] = True 5259 c.flags = d 5260 assertIsExclusivelySet(DivisionByZero, c.flags) 5261 5262 c.clear_traps() 5263 d = c.traps.copy() 5264 d[Underflow] = True 5265 c.traps = d 5266 assertIsExclusivelySet(Underflow, c.traps) 5267 5268 # Random constructors 5269 IntSignals = { 5270 Clamped: C.DecClamped, 5271 Rounded: C.DecRounded, 5272 Inexact: C.DecInexact, 5273 Subnormal: C.DecSubnormal, 5274 Underflow: C.DecUnderflow, 5275 Overflow: C.DecOverflow, 5276 DivisionByZero: C.DecDivisionByZero, 5277 InvalidOperation: C.DecIEEEInvalidOperation 5278 } 5279 IntCond = [ 5280 C.DecDivisionImpossible, C.DecDivisionUndefined, C.DecFpuError, 5281 C.DecInvalidContext, C.DecInvalidOperation, C.DecMallocError, 5282 C.DecConversionSyntax, 5283 ] 5284 5285 lim = len(OrderedSignals[C]) 5286 for r in range(lim): 5287 for t in range(lim): 5288 for round in RoundingModes: 5289 flags = random.sample(OrderedSignals[C], r) 5290 traps = random.sample(OrderedSignals[C], t) 5291 prec = random.randrange(1, 10000) 5292 emin = random.randrange(-10000, 0) 5293 emax = random.randrange(0, 10000) 5294 clamp = random.randrange(0, 2) 5295 caps = random.randrange(0, 2) 5296 cr = random.randrange(0, 2) 5297 c = Context(prec=prec, rounding=round, Emin=emin, Emax=emax, 5298 capitals=caps, clamp=clamp, flags=list(flags), 5299 traps=list(traps)) 5300 5301 self.assertEqual(c.prec, prec) 5302 self.assertEqual(c.rounding, round) 5303 self.assertEqual(c.Emin, emin) 5304 self.assertEqual(c.Emax, emax) 5305 self.assertEqual(c.capitals, caps) 5306 self.assertEqual(c.clamp, clamp) 5307 5308 f = 0 5309 for x in flags: 5310 f |= IntSignals[x] 5311 self.assertEqual(c._flags, f) 5312 5313 f = 0 5314 for x in traps: 5315 f |= IntSignals[x] 5316 self.assertEqual(c._traps, f) 5317 5318 for cond in IntCond: 5319 c._flags = cond 5320 self.assertTrue(c._flags&DecIEEEInvalidOperation) 5321 assertIsExclusivelySet(InvalidOperation, c.flags) 5322 5323 for cond in IntCond: 5324 c._traps = cond 5325 self.assertTrue(c._traps&DecIEEEInvalidOperation) 5326 assertIsExclusivelySet(InvalidOperation, c.traps) 5327 5328 def test_invalid_override(self): 5329 Decimal = C.Decimal 5330 5331 try: 5332 from locale import CHAR_MAX 5333 except ImportError: 5334 self.skipTest('locale.CHAR_MAX not available') 5335 5336 def make_grouping(lst): 5337 return ''.join([chr(x) for x in lst]) 5338 5339 def get_fmt(x, override=None, fmt='n'): 5340 return Decimal(x).__format__(fmt, override) 5341 5342 invalid_grouping = { 5343 'decimal_point' : ',', 5344 'grouping' : make_grouping([255, 255, 0]), 5345 'thousands_sep' : ',' 5346 } 5347 invalid_dot = { 5348 'decimal_point' : 'xxxxx', 5349 'grouping' : make_grouping([3, 3, 0]), 5350 'thousands_sep' : ',' 5351 } 5352 invalid_sep = { 5353 'decimal_point' : '.', 5354 'grouping' : make_grouping([3, 3, 0]), 5355 'thousands_sep' : 'yyyyy' 5356 } 5357 5358 if CHAR_MAX == 127: # negative grouping in override 5359 self.assertRaises(ValueError, get_fmt, 12345, 5360 invalid_grouping, 'g') 5361 5362 self.assertRaises(ValueError, get_fmt, 12345, invalid_dot, 'g') 5363 self.assertRaises(ValueError, get_fmt, 12345, invalid_sep, 'g') 5364 5365 def test_exact_conversion(self): 5366 Decimal = C.Decimal 5367 localcontext = C.localcontext 5368 InvalidOperation = C.InvalidOperation 5369 5370 with localcontext() as c: 5371 5372 c.traps[InvalidOperation] = True 5373 5374 # Clamped 5375 x = "0e%d" % sys.maxsize 5376 self.assertRaises(InvalidOperation, Decimal, x) 5377 5378 x = "0e%d" % (-sys.maxsize-1) 5379 self.assertRaises(InvalidOperation, Decimal, x) 5380 5381 # Overflow 5382 x = "1e%d" % sys.maxsize 5383 self.assertRaises(InvalidOperation, Decimal, x) 5384 5385 # Underflow 5386 x = "1e%d" % (-sys.maxsize-1) 5387 self.assertRaises(InvalidOperation, Decimal, x) 5388 5389 def test_from_tuple(self): 5390 Decimal = C.Decimal 5391 localcontext = C.localcontext 5392 InvalidOperation = C.InvalidOperation 5393 Overflow = C.Overflow 5394 Underflow = C.Underflow 5395 5396 with localcontext() as c: 5397 5398 c.traps[InvalidOperation] = True 5399 c.traps[Overflow] = True 5400 c.traps[Underflow] = True 5401 5402 # SSIZE_MAX 5403 x = (1, (), sys.maxsize) 5404 self.assertEqual(str(c.create_decimal(x)), '-0E+999999') 5405 self.assertRaises(InvalidOperation, Decimal, x) 5406 5407 x = (1, (0, 1, 2), sys.maxsize) 5408 self.assertRaises(Overflow, c.create_decimal, x) 5409 self.assertRaises(InvalidOperation, Decimal, x) 5410 5411 # SSIZE_MIN 5412 x = (1, (), -sys.maxsize-1) 5413 self.assertEqual(str(c.create_decimal(x)), '-0E-1000007') 5414 self.assertRaises(InvalidOperation, Decimal, x) 5415 5416 x = (1, (0, 1, 2), -sys.maxsize-1) 5417 self.assertRaises(Underflow, c.create_decimal, x) 5418 self.assertRaises(InvalidOperation, Decimal, x) 5419 5420 # OverflowError 5421 x = (1, (), sys.maxsize+1) 5422 self.assertRaises(OverflowError, c.create_decimal, x) 5423 self.assertRaises(OverflowError, Decimal, x) 5424 5425 x = (1, (), -sys.maxsize-2) 5426 self.assertRaises(OverflowError, c.create_decimal, x) 5427 self.assertRaises(OverflowError, Decimal, x) 5428 5429 # Specials 5430 x = (1, (), "N") 5431 self.assertEqual(str(Decimal(x)), '-sNaN') 5432 x = (1, (0,), "N") 5433 self.assertEqual(str(Decimal(x)), '-sNaN') 5434 x = (1, (0, 1), "N") 5435 self.assertEqual(str(Decimal(x)), '-sNaN1') 5436 5437 def test_sizeof(self): 5438 Decimal = C.Decimal 5439 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000) 5440 5441 self.assertGreater(Decimal(0).__sizeof__(), 0) 5442 if HAVE_CONFIG_64: 5443 x = Decimal(10**(19*24)).__sizeof__() 5444 y = Decimal(10**(19*25)).__sizeof__() 5445 self.assertEqual(y, x+8) 5446 else: 5447 x = Decimal(10**(9*24)).__sizeof__() 5448 y = Decimal(10**(9*25)).__sizeof__() 5449 self.assertEqual(y, x+4) 5450 5451 def test_internal_use_of_overridden_methods(self): 5452 Decimal = C.Decimal 5453 5454 # Unsound subtyping 5455 class X(float): 5456 def as_integer_ratio(self): 5457 return 1 5458 def __abs__(self): 5459 return self 5460 5461 class Y(float): 5462 def __abs__(self): 5463 return [1]*200 5464 5465 class I(int): 5466 def bit_length(self): 5467 return [1]*200 5468 5469 class Z(float): 5470 def as_integer_ratio(self): 5471 return (I(1), I(1)) 5472 def __abs__(self): 5473 return self 5474 5475 for cls in X, Y, Z: 5476 self.assertEqual(Decimal.from_float(cls(101.1)), 5477 Decimal.from_float(101.1)) 5478 5479@requires_docstrings 5480@unittest.skipUnless(C, "test requires C version") 5481class SignatureTest(unittest.TestCase): 5482 """Function signatures""" 5483 5484 def test_inspect_module(self): 5485 for attr in dir(P): 5486 if attr.startswith('_'): 5487 continue 5488 p_func = getattr(P, attr) 5489 c_func = getattr(C, attr) 5490 if (attr == 'Decimal' or attr == 'Context' or 5491 inspect.isfunction(p_func)): 5492 p_sig = inspect.signature(p_func) 5493 c_sig = inspect.signature(c_func) 5494 5495 # parameter names: 5496 c_names = list(c_sig.parameters.keys()) 5497 p_names = [x for x in p_sig.parameters.keys() if not 5498 x.startswith('_')] 5499 5500 self.assertEqual(c_names, p_names, 5501 msg="parameter name mismatch in %s" % p_func) 5502 5503 c_kind = [x.kind for x in c_sig.parameters.values()] 5504 p_kind = [x[1].kind for x in p_sig.parameters.items() if not 5505 x[0].startswith('_')] 5506 5507 # parameters: 5508 if attr != 'setcontext': 5509 self.assertEqual(c_kind, p_kind, 5510 msg="parameter kind mismatch in %s" % p_func) 5511 5512 def test_inspect_types(self): 5513 5514 POS = inspect._ParameterKind.POSITIONAL_ONLY 5515 POS_KWD = inspect._ParameterKind.POSITIONAL_OR_KEYWORD 5516 5517 # Type heuristic (type annotations would help!): 5518 pdict = {C: {'other': C.Decimal(1), 5519 'third': C.Decimal(1), 5520 'x': C.Decimal(1), 5521 'y': C.Decimal(1), 5522 'z': C.Decimal(1), 5523 'a': C.Decimal(1), 5524 'b': C.Decimal(1), 5525 'c': C.Decimal(1), 5526 'exp': C.Decimal(1), 5527 'modulo': C.Decimal(1), 5528 'num': "1", 5529 'f': 1.0, 5530 'rounding': C.ROUND_HALF_UP, 5531 'context': C.getcontext()}, 5532 P: {'other': P.Decimal(1), 5533 'third': P.Decimal(1), 5534 'a': P.Decimal(1), 5535 'b': P.Decimal(1), 5536 'c': P.Decimal(1), 5537 'exp': P.Decimal(1), 5538 'modulo': P.Decimal(1), 5539 'num': "1", 5540 'f': 1.0, 5541 'rounding': P.ROUND_HALF_UP, 5542 'context': P.getcontext()}} 5543 5544 def mkargs(module, sig): 5545 args = [] 5546 kwargs = {} 5547 for name, param in sig.parameters.items(): 5548 if name == 'self': continue 5549 if param.kind == POS: 5550 args.append(pdict[module][name]) 5551 elif param.kind == POS_KWD: 5552 kwargs[name] = pdict[module][name] 5553 else: 5554 raise TestFailed("unexpected parameter kind") 5555 return args, kwargs 5556 5557 def tr(s): 5558 """The C Context docstrings use 'x' in order to prevent confusion 5559 with the article 'a' in the descriptions.""" 5560 if s == 'x': return 'a' 5561 if s == 'y': return 'b' 5562 if s == 'z': return 'c' 5563 return s 5564 5565 def doit(ty): 5566 p_type = getattr(P, ty) 5567 c_type = getattr(C, ty) 5568 for attr in dir(p_type): 5569 if attr.startswith('_'): 5570 continue 5571 p_func = getattr(p_type, attr) 5572 c_func = getattr(c_type, attr) 5573 if inspect.isfunction(p_func): 5574 p_sig = inspect.signature(p_func) 5575 c_sig = inspect.signature(c_func) 5576 5577 # parameter names: 5578 p_names = list(p_sig.parameters.keys()) 5579 c_names = [tr(x) for x in c_sig.parameters.keys()] 5580 5581 self.assertEqual(c_names, p_names, 5582 msg="parameter name mismatch in %s" % p_func) 5583 5584 p_kind = [x.kind for x in p_sig.parameters.values()] 5585 c_kind = [x.kind for x in c_sig.parameters.values()] 5586 5587 # 'self' parameter: 5588 self.assertIs(p_kind[0], POS_KWD) 5589 self.assertIs(c_kind[0], POS) 5590 5591 # remaining parameters: 5592 if ty == 'Decimal': 5593 self.assertEqual(c_kind[1:], p_kind[1:], 5594 msg="parameter kind mismatch in %s" % p_func) 5595 else: # Context methods are positional only in the C version. 5596 self.assertEqual(len(c_kind), len(p_kind), 5597 msg="parameter kind mismatch in %s" % p_func) 5598 5599 # Run the function: 5600 args, kwds = mkargs(C, c_sig) 5601 try: 5602 getattr(c_type(9), attr)(*args, **kwds) 5603 except Exception as err: 5604 raise TestFailed("invalid signature for %s: %s %s" % (c_func, args, kwds)) 5605 5606 args, kwds = mkargs(P, p_sig) 5607 try: 5608 getattr(p_type(9), attr)(*args, **kwds) 5609 except Exception as err: 5610 raise TestFailed("invalid signature for %s: %s %s" % (p_func, args, kwds)) 5611 5612 doit('Decimal') 5613 doit('Context') 5614 5615 5616all_tests = [ 5617 CExplicitConstructionTest, PyExplicitConstructionTest, 5618 CImplicitConstructionTest, PyImplicitConstructionTest, 5619 CFormatTest, PyFormatTest, 5620 CArithmeticOperatorsTest, PyArithmeticOperatorsTest, 5621 CThreadingTest, PyThreadingTest, 5622 CUsabilityTest, PyUsabilityTest, 5623 CPythonAPItests, PyPythonAPItests, 5624 CContextAPItests, PyContextAPItests, 5625 CContextWithStatement, PyContextWithStatement, 5626 CContextFlags, PyContextFlags, 5627 CSpecialContexts, PySpecialContexts, 5628 CContextInputValidation, PyContextInputValidation, 5629 CContextSubclassing, PyContextSubclassing, 5630 CCoverage, PyCoverage, 5631 CFunctionality, PyFunctionality, 5632 CWhitebox, PyWhitebox, 5633 CIBMTestCases, PyIBMTestCases, 5634] 5635 5636# Delete C tests if _decimal.so is not present. 5637if not C: 5638 all_tests = all_tests[1::2] 5639else: 5640 all_tests.insert(0, CheckAttributes) 5641 all_tests.insert(1, SignatureTest) 5642 5643 5644def test_main(arith=None, verbose=None, todo_tests=None, debug=None): 5645 """ Execute the tests. 5646 5647 Runs all arithmetic tests if arith is True or if the "decimal" resource 5648 is enabled in regrtest.py 5649 """ 5650 5651 init(C) 5652 init(P) 5653 global TEST_ALL, DEBUG 5654 TEST_ALL = arith if arith is not None else is_resource_enabled('decimal') 5655 DEBUG = debug 5656 5657 if todo_tests is None: 5658 test_classes = all_tests 5659 else: 5660 test_classes = [CIBMTestCases, PyIBMTestCases] 5661 5662 # Dynamically build custom test definition for each file in the test 5663 # directory and add the definitions to the DecimalTest class. This 5664 # procedure insures that new files do not get skipped. 5665 for filename in os.listdir(directory): 5666 if '.decTest' not in filename or filename.startswith("."): 5667 continue 5668 head, tail = filename.split('.') 5669 if todo_tests is not None and head not in todo_tests: 5670 continue 5671 tester = lambda self, f=filename: self.eval_file(directory + f) 5672 setattr(CIBMTestCases, 'test_' + head, tester) 5673 setattr(PyIBMTestCases, 'test_' + head, tester) 5674 del filename, head, tail, tester 5675 5676 5677 try: 5678 run_unittest(*test_classes) 5679 if todo_tests is None: 5680 from doctest import IGNORE_EXCEPTION_DETAIL 5681 savedecimal = sys.modules['decimal'] 5682 if C: 5683 sys.modules['decimal'] = C 5684 run_doctest(C, verbose, optionflags=IGNORE_EXCEPTION_DETAIL) 5685 sys.modules['decimal'] = P 5686 run_doctest(P, verbose) 5687 sys.modules['decimal'] = savedecimal 5688 finally: 5689 if C: C.setcontext(ORIGINAL_CONTEXT[C]) 5690 P.setcontext(ORIGINAL_CONTEXT[P]) 5691 if not C: 5692 warnings.warn('C tests skipped: no module named _decimal.', 5693 UserWarning) 5694 if not orig_sys_decimal is sys.modules['decimal']: 5695 raise TestFailed("Internal error: unbalanced number of changes to " 5696 "sys.modules['decimal'].") 5697 5698 5699if __name__ == '__main__': 5700 import optparse 5701 p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]") 5702 p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test') 5703 p.add_option('--skip', '-s', action='store_true', help='skip over 90% of the arithmetic tests') 5704 (opt, args) = p.parse_args() 5705 5706 if opt.skip: 5707 test_main(arith=False, verbose=True) 5708 elif args: 5709 test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug) 5710 else: 5711 test_main(arith=True, verbose=True) 5712