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