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