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