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