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