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