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