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