blob: 716e6eb7fb127e2d7b417669f69e58f6381444b7 [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,
Stefan Krah6b794b82014-05-01 17:42:33 +020036 requires_IEEE_754, requires_docstrings)
Hai Shif7ba40b2020-06-25 18:38:51 +080037from test.support import (TestFailed,
Stefan Krah6e467042012-11-10 23:09:04 +010038 run_with_locale, cpython_only)
Hai Shif7ba40b2020-06-25 18:38:51 +080039from test.support.import_helper import import_fresh_module
Raymond Hettinger0aeac102004-07-05 22:53:03 +000040import random
Stefan Krah5de1f822014-05-01 15:53:42 +020041import inspect
Antoine Pitroua6a4dc82017-09-07 18:56:24 +020042import threading
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000043
Raymond Hettingerfed52962004-07-14 15:41:57 +000044
Stefan Krah1919b7e2012-03-21 18:25:23 +010045C = import_fresh_module('decimal', fresh=['_decimal'])
46P = import_fresh_module('decimal', blocked=['_decimal'])
47orig_sys_decimal = sys.modules['decimal']
48
49# fractions module must import the correct decimal module.
50cfractions = import_fresh_module('fractions', fresh=['fractions'])
51sys.modules['decimal'] = P
52pfractions = import_fresh_module('fractions', fresh=['fractions'])
53sys.modules['decimal'] = C
54fractions = {C:cfractions, P:pfractions}
55sys.modules['decimal'] = orig_sys_decimal
56
57
58# Useful Test Constant
59Signals = {
60 C: tuple(C.getcontext().flags.keys()) if C else None,
61 P: tuple(P.getcontext().flags.keys())
62}
Mark Dickinsonc69160e2010-05-04 14:35:33 +000063# Signals ordered with respect to precedence: when an operation
64# produces multiple signals, signals occurring later in the list
65# should be handled before those occurring earlier in the list.
Stefan Krah1919b7e2012-03-21 18:25:23 +010066OrderedSignals = {
67 C: [C.Clamped, C.Rounded, C.Inexact, C.Subnormal, C.Underflow,
68 C.Overflow, C.DivisionByZero, C.InvalidOperation,
69 C.FloatOperation] if C else None,
70 P: [P.Clamped, P.Rounded, P.Inexact, P.Subnormal, P.Underflow,
71 P.Overflow, P.DivisionByZero, P.InvalidOperation,
72 P.FloatOperation]
73}
74def assert_signals(cls, context, attr, expected):
75 d = getattr(context, attr)
76 cls.assertTrue(all(d[s] if s in expected else not d[s] for s in d))
77
Stefan Krah59a4a932013-01-16 12:58:59 +010078ROUND_UP = P.ROUND_UP
79ROUND_DOWN = P.ROUND_DOWN
80ROUND_CEILING = P.ROUND_CEILING
81ROUND_FLOOR = P.ROUND_FLOOR
82ROUND_HALF_UP = P.ROUND_HALF_UP
83ROUND_HALF_DOWN = P.ROUND_HALF_DOWN
84ROUND_HALF_EVEN = P.ROUND_HALF_EVEN
85ROUND_05UP = P.ROUND_05UP
86
87RoundingModes = [
88 ROUND_UP, ROUND_DOWN, ROUND_CEILING, ROUND_FLOOR,
89 ROUND_HALF_UP, ROUND_HALF_DOWN, ROUND_HALF_EVEN,
90 ROUND_05UP
91]
Mark Dickinsonc69160e2010-05-04 14:35:33 +000092
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000093# Tests are built around these assumed context defaults.
94# test_main() restores the original context.
Stefan Krah1919b7e2012-03-21 18:25:23 +010095ORIGINAL_CONTEXT = {
96 C: C.getcontext().copy() if C else None,
97 P: P.getcontext().copy()
98}
99def init(m):
100 if not m: return
101 DefaultTestContext = m.Context(
Stefan Krah59a4a932013-01-16 12:58:59 +0100102 prec=9, rounding=ROUND_HALF_EVEN, traps=dict.fromkeys(Signals[m], 0)
Stefan Krah1919b7e2012-03-21 18:25:23 +0100103 )
104 m.setcontext(DefaultTestContext)
Raymond Hettinger6ea48452004-07-03 12:26:21 +0000105
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000106TESTDATADIR = 'decimaltestdata'
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000107if __name__ == '__main__':
108 file = sys.argv[0]
109else:
110 file = __file__
111testdir = os.path.dirname(file) or os.curdir
Raymond Hettinger267b8682005-03-27 10:47:39 +0000112directory = testdir + os.sep + TESTDATADIR + os.sep
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000113
Raymond Hettinger267b8682005-03-27 10:47:39 +0000114skip_expected = not os.path.isdir(directory)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000115
116# Make sure it actually raises errors when not expected and caught in flags
117# Slower, since it runs some things several times.
118EXTENDEDERRORTEST = False
119
Stefan Krah1919b7e2012-03-21 18:25:23 +0100120# Test extra functionality in the C version (-DEXTRA_FUNCTIONALITY).
121EXTRA_FUNCTIONALITY = True if hasattr(C, 'DecClamped') else False
122requires_extra_functionality = unittest.skipUnless(
123 EXTRA_FUNCTIONALITY, "test requires build with -DEXTRA_FUNCTIONALITY")
124skip_if_extra_functionality = unittest.skipIf(
125 EXTRA_FUNCTIONALITY, "test requires regular build")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000126
127
Stefan Krah1919b7e2012-03-21 18:25:23 +0100128class IBMTestCases(unittest.TestCase):
129 """Class which tests the Decimal class against the IBM test cases."""
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000130
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000131 def setUp(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100132 self.context = self.decimal.Context()
133 self.readcontext = self.decimal.Context()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000134 self.ignore_list = ['#']
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000135
Stefan Krah1919b7e2012-03-21 18:25:23 +0100136 # List of individual .decTest test ids that correspond to tests that
137 # we're skipping for one reason or another.
138 self.skipped_test_ids = set([
139 # Skip implementation-specific scaleb tests.
140 'scbx164',
141 'scbx165',
142
143 # For some operations (currently exp, ln, log10, power), the decNumber
144 # reference implementation imposes additional restrictions on the context
145 # and operands. These restrictions are not part of the specification;
146 # however, the effect of these restrictions does show up in some of the
147 # testcases. We skip testcases that violate these restrictions, since
148 # Decimal behaves differently from decNumber for these testcases so these
149 # testcases would otherwise fail.
150 'expx901',
151 'expx902',
152 'expx903',
153 'expx905',
154 'lnx901',
155 'lnx902',
156 'lnx903',
157 'lnx905',
158 'logx901',
159 'logx902',
160 'logx903',
161 'logx905',
162 'powx1183',
163 'powx1184',
164 'powx4001',
165 'powx4002',
166 'powx4003',
167 'powx4005',
168 'powx4008',
169 'powx4010',
170 'powx4012',
171 'powx4014',
172 ])
173
174 if self.decimal == C:
175 # status has additional Subnormal, Underflow
176 self.skipped_test_ids.add('pwsx803')
177 self.skipped_test_ids.add('pwsx805')
178 # Correct rounding (skipped for decNumber, too)
179 self.skipped_test_ids.add('powx4302')
180 self.skipped_test_ids.add('powx4303')
181 self.skipped_test_ids.add('powx4342')
182 self.skipped_test_ids.add('powx4343')
183 # http://bugs.python.org/issue7049
184 self.skipped_test_ids.add('pwmx325')
185 self.skipped_test_ids.add('pwmx326')
186
187 # Map test directives to setter functions.
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000188 self.ChangeDict = {'precision' : self.change_precision,
Stefan Krah1919b7e2012-03-21 18:25:23 +0100189 'rounding' : self.change_rounding_method,
190 'maxexponent' : self.change_max_exponent,
191 'minexponent' : self.change_min_exponent,
192 'clamp' : self.change_clamp}
193
194 # Name adapter to be able to change the Decimal and Context
195 # interface without changing the test files from Cowlishaw.
196 self.NameAdapter = {'and':'logical_and',
197 'apply':'_apply',
198 'class':'number_class',
199 'comparesig':'compare_signal',
200 'comparetotal':'compare_total',
201 'comparetotmag':'compare_total_mag',
202 'copy':'copy_decimal',
203 'copyabs':'copy_abs',
204 'copynegate':'copy_negate',
205 'copysign':'copy_sign',
206 'divideint':'divide_int',
207 'invert':'logical_invert',
208 'iscanonical':'is_canonical',
209 'isfinite':'is_finite',
210 'isinfinite':'is_infinite',
211 'isnan':'is_nan',
212 'isnormal':'is_normal',
213 'isqnan':'is_qnan',
214 'issigned':'is_signed',
215 'issnan':'is_snan',
216 'issubnormal':'is_subnormal',
217 'iszero':'is_zero',
218 'maxmag':'max_mag',
219 'minmag':'min_mag',
220 'nextminus':'next_minus',
221 'nextplus':'next_plus',
222 'nexttoward':'next_toward',
223 'or':'logical_or',
224 'reduce':'normalize',
225 'remaindernear':'remainder_near',
226 'samequantum':'same_quantum',
227 'squareroot':'sqrt',
228 'toeng':'to_eng_string',
229 'tointegral':'to_integral_value',
230 'tointegralx':'to_integral_exact',
231 'tosci':'to_sci_string',
232 'xor':'logical_xor'}
233
234 # Map test-case names to roundings.
Stefan Krah59a4a932013-01-16 12:58:59 +0100235 self.RoundingDict = {'ceiling' : ROUND_CEILING,
236 'down' : ROUND_DOWN,
237 'floor' : ROUND_FLOOR,
238 'half_down' : ROUND_HALF_DOWN,
239 'half_even' : ROUND_HALF_EVEN,
240 'half_up' : ROUND_HALF_UP,
241 'up' : ROUND_UP,
242 '05up' : ROUND_05UP}
Stefan Krah1919b7e2012-03-21 18:25:23 +0100243
244 # Map the test cases' error names to the actual errors.
245 self.ErrorNames = {'clamped' : self.decimal.Clamped,
246 'conversion_syntax' : self.decimal.InvalidOperation,
247 'division_by_zero' : self.decimal.DivisionByZero,
248 'division_impossible' : self.decimal.InvalidOperation,
249 'division_undefined' : self.decimal.InvalidOperation,
250 'inexact' : self.decimal.Inexact,
251 'invalid_context' : self.decimal.InvalidOperation,
252 'invalid_operation' : self.decimal.InvalidOperation,
253 'overflow' : self.decimal.Overflow,
254 'rounded' : self.decimal.Rounded,
255 'subnormal' : self.decimal.Subnormal,
256 'underflow' : self.decimal.Underflow}
257
258 # The following functions return True/False rather than a
259 # Decimal instance.
260 self.LogicalFunctions = ('is_canonical',
261 'is_finite',
262 'is_infinite',
263 'is_nan',
264 'is_normal',
265 'is_qnan',
266 'is_signed',
267 'is_snan',
268 'is_subnormal',
269 'is_zero',
270 'same_quantum')
271
272 def read_unlimited(self, v, context):
273 """Work around the limitations of the 32-bit _decimal version. The
274 guaranteed maximum values for prec, Emax etc. are 425000000,
275 but higher values usually work, except for rare corner cases.
276 In particular, all of the IBM tests pass with maximum values
277 of 1070000000."""
278 if self.decimal == C and self.decimal.MAX_EMAX == 425000000:
279 self.readcontext._unsafe_setprec(1070000000)
280 self.readcontext._unsafe_setemax(1070000000)
281 self.readcontext._unsafe_setemin(-1070000000)
282 return self.readcontext.create_decimal(v)
283 else:
284 return self.decimal.Decimal(v, context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000285
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000286 def eval_file(self, file):
287 global skip_expected
288 if skip_expected:
Benjamin Petersone549ead2009-03-28 21:42:05 +0000289 raise unittest.SkipTest
Antoine Pitrou92f60ed2010-10-14 22:11:44 +0000290 with open(file) as f:
291 for line in f:
292 line = line.replace('\r\n', '').replace('\n', '')
293 #print line
294 try:
295 t = self.eval_line(line)
Stefan Krah1919b7e2012-03-21 18:25:23 +0100296 except self.decimal.DecimalException as exception:
Ezio Melotti13925002011-03-16 11:05:33 +0200297 #Exception raised where there shouldn't have been one.
Antoine Pitrou92f60ed2010-10-14 22:11:44 +0000298 self.fail('Exception "'+exception.__class__.__name__ + '" raised on line '+line)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000299
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000300
301 def eval_line(self, s):
302 if s.find(' -> ') >= 0 and s[:2] != '--' and not s.startswith(' --'):
303 s = (s.split('->')[0] + '->' +
304 s.split('->')[1].split('--')[0]).strip()
305 else:
306 s = s.split('--')[0].strip()
307
308 for ignore in self.ignore_list:
309 if s.find(ignore) >= 0:
310 #print s.split()[0], 'NotImplemented--', ignore
311 return
312 if not s:
313 return
314 elif ':' in s:
315 return self.eval_directive(s)
316 else:
317 return self.eval_equation(s)
318
319 def eval_directive(self, s):
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000320 funct, value = (x.strip().lower() for x in s.split(':'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000321 if funct == 'rounding':
Stefan Krah1919b7e2012-03-21 18:25:23 +0100322 value = self.RoundingDict[value]
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000323 else:
324 try:
325 value = int(value)
326 except ValueError:
327 pass
328
Stefan Krah1919b7e2012-03-21 18:25:23 +0100329 funct = self.ChangeDict.get(funct, (lambda *args: None))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000330 funct(value)
331
332 def eval_equation(self, s):
Raymond Hettingered20ad82004-09-04 20:09:13 +0000333
334 if not TEST_ALL and random.random() < 0.90:
335 return
336
Stefan Krah1919b7e2012-03-21 18:25:23 +0100337 self.context.clear_flags()
338
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000339 try:
340 Sides = s.split('->')
341 L = Sides[0].strip().split()
342 id = L[0]
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000343 if DEBUG:
344 print("Test ", id, end=" ")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000345 funct = L[1].lower()
346 valstemp = L[2:]
347 L = Sides[1].strip().split()
348 ans = L[0]
349 exceptions = L[1:]
350 except (TypeError, AttributeError, IndexError):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100351 raise self.decimal.InvalidOperation
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000352 def FixQuotes(val):
353 val = val.replace("''", 'SingleQuote').replace('""', 'DoubleQuote')
354 val = val.replace("'", '').replace('"', '')
355 val = val.replace('SingleQuote', "'").replace('DoubleQuote', '"')
356 return val
Mark Dickinson8a546532009-10-08 16:30:38 +0000357
Stefan Krah1919b7e2012-03-21 18:25:23 +0100358 if id in self.skipped_test_ids:
Mark Dickinson8a546532009-10-08 16:30:38 +0000359 return
360
Stefan Krah1919b7e2012-03-21 18:25:23 +0100361 fname = self.NameAdapter.get(funct, funct)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000362 if fname == 'rescale':
363 return
364 funct = getattr(self.context, fname)
365 vals = []
366 conglomerate = ''
367 quote = 0
Stefan Krah1919b7e2012-03-21 18:25:23 +0100368 theirexceptions = [self.ErrorNames[x.lower()] for x in exceptions]
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000369
Stefan Krah1919b7e2012-03-21 18:25:23 +0100370 for exception in Signals[self.decimal]:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000371 self.context.traps[exception] = 1 #Catch these bugs...
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000372 for exception in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000373 self.context.traps[exception] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000374 for i, val in enumerate(valstemp):
375 if val.count("'") % 2 == 1:
376 quote = 1 - quote
377 if quote:
378 conglomerate = conglomerate + ' ' + val
379 continue
380 else:
381 val = conglomerate + val
382 conglomerate = ''
383 v = FixQuotes(val)
384 if fname in ('to_sci_string', 'to_eng_string'):
385 if EXTENDEDERRORTEST:
386 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000387 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000388 try:
389 funct(self.context.create_decimal(v))
390 except error:
391 pass
Stefan Krah1919b7e2012-03-21 18:25:23 +0100392 except Signals[self.decimal] as e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000393 self.fail("Raised %s in %s when %s disabled" % \
394 (e, s, error))
395 else:
396 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000397 self.context.traps[error] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000398 v = self.context.create_decimal(v)
399 else:
Stefan Krah1919b7e2012-03-21 18:25:23 +0100400 v = self.read_unlimited(v, self.context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000401 vals.append(v)
402
403 ans = FixQuotes(ans)
404
405 if EXTENDEDERRORTEST and fname not in ('to_sci_string', 'to_eng_string'):
406 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000407 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000408 try:
409 funct(*vals)
410 except error:
411 pass
Stefan Krah1919b7e2012-03-21 18:25:23 +0100412 except Signals[self.decimal] as e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000413 self.fail("Raised %s in %s when %s disabled" % \
414 (e, s, error))
415 else:
416 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000417 self.context.traps[error] = 0
Mark Dickinsonc69160e2010-05-04 14:35:33 +0000418
419 # as above, but add traps cumulatively, to check precedence
Stefan Krah1919b7e2012-03-21 18:25:23 +0100420 ordered_errors = [e for e in OrderedSignals[self.decimal] if e in theirexceptions]
Mark Dickinsonc69160e2010-05-04 14:35:33 +0000421 for error in ordered_errors:
422 self.context.traps[error] = 1
423 try:
424 funct(*vals)
425 except error:
426 pass
Stefan Krah1919b7e2012-03-21 18:25:23 +0100427 except Signals[self.decimal] as e:
Mark Dickinsonc69160e2010-05-04 14:35:33 +0000428 self.fail("Raised %s in %s; expected %s" %
429 (type(e), s, error))
430 else:
431 self.fail("Did not raise %s in %s" % (error, s))
432 # reset traps
433 for error in ordered_errors:
434 self.context.traps[error] = 0
435
436
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000437 if DEBUG:
438 print("--", self.context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000439 try:
440 result = str(funct(*vals))
Stefan Krah1919b7e2012-03-21 18:25:23 +0100441 if fname in self.LogicalFunctions:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000442 result = str(int(eval(result))) # 'True', 'False' -> '1', '0'
Stefan Krah1919b7e2012-03-21 18:25:23 +0100443 except Signals[self.decimal] as error:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000444 self.fail("Raised %s in %s" % (error, s))
445 except: #Catch any error long enough to state the test case.
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000446 print("ERROR:", s)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000447 raise
448
449 myexceptions = self.getexceptions()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000450
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000451 myexceptions.sort(key=repr)
452 theirexceptions.sort(key=repr)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000453
454 self.assertEqual(result, ans,
455 'Incorrect answer for ' + s + ' -- got ' + result)
Stefan Krah1919b7e2012-03-21 18:25:23 +0100456
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000457 self.assertEqual(myexceptions, theirexceptions,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000458 'Incorrect flags set in ' + s + ' -- got ' + str(myexceptions))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000459
460 def getexceptions(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100461 return [e for e in Signals[self.decimal] if self.context.flags[e]]
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000462
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000463 def change_precision(self, prec):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100464 if self.decimal == C and self.decimal.MAX_PREC == 425000000:
465 self.context._unsafe_setprec(prec)
466 else:
467 self.context.prec = prec
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000468 def change_rounding_method(self, rounding):
469 self.context.rounding = rounding
470 def change_min_exponent(self, exp):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100471 if self.decimal == C and self.decimal.MAX_PREC == 425000000:
472 self.context._unsafe_setemin(exp)
473 else:
474 self.context.Emin = exp
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000475 def change_max_exponent(self, exp):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100476 if self.decimal == C and self.decimal.MAX_PREC == 425000000:
477 self.context._unsafe_setemax(exp)
478 else:
479 self.context.Emax = exp
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000480 def change_clamp(self, clamp):
Mark Dickinsonb1d8e322010-05-22 18:35:36 +0000481 self.context.clamp = clamp
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000482
Stefan Krah1919b7e2012-03-21 18:25:23 +0100483class CIBMTestCases(IBMTestCases):
484 decimal = C
485class PyIBMTestCases(IBMTestCases):
486 decimal = P
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000487
488# The following classes test the behaviour of Decimal according to PEP 327
489
Stefan Krah1919b7e2012-03-21 18:25:23 +0100490class ExplicitConstructionTest(unittest.TestCase):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000491 '''Unit tests for Explicit Construction cases of Decimal.'''
492
493 def test_explicit_empty(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100494 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000495 self.assertEqual(Decimal(), Decimal("0"))
496
497 def test_explicit_from_None(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100498 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000499 self.assertRaises(TypeError, Decimal, None)
500
501 def test_explicit_from_int(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100502 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000503
504 #positive
505 d = Decimal(45)
506 self.assertEqual(str(d), '45')
507
508 #very large positive
509 d = Decimal(500000123)
510 self.assertEqual(str(d), '500000123')
511
512 #negative
513 d = Decimal(-45)
514 self.assertEqual(str(d), '-45')
515
516 #zero
517 d = Decimal(0)
518 self.assertEqual(str(d), '0')
519
Stefan Krah1919b7e2012-03-21 18:25:23 +0100520 # single word longs
521 for n in range(0, 32):
522 for sign in (-1, 1):
523 for x in range(-5, 5):
524 i = sign * (2**n + x)
525 d = Decimal(i)
526 self.assertEqual(str(d), str(i))
527
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000528 def test_explicit_from_string(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100529 Decimal = self.decimal.Decimal
530 InvalidOperation = self.decimal.InvalidOperation
531 localcontext = self.decimal.localcontext
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000532
533 #empty
534 self.assertEqual(str(Decimal('')), 'NaN')
535
536 #int
537 self.assertEqual(str(Decimal('45')), '45')
538
539 #float
540 self.assertEqual(str(Decimal('45.34')), '45.34')
541
542 #engineer notation
543 self.assertEqual(str(Decimal('45e2')), '4.5E+3')
544
545 #just not a number
546 self.assertEqual(str(Decimal('ugly')), 'NaN')
547
Christian Heimesa62da1d2008-01-12 19:39:10 +0000548 #leading and trailing whitespace permitted
549 self.assertEqual(str(Decimal('1.3E4 \n')), '1.3E+4')
550 self.assertEqual(str(Decimal(' -7.89')), '-7.89')
Stefan Krah1919b7e2012-03-21 18:25:23 +0100551 self.assertEqual(str(Decimal(" 3.45679 ")), '3.45679')
552
Brett Cannona721aba2016-09-09 14:57:09 -0700553 # underscores
554 self.assertEqual(str(Decimal('1_3.3e4_0')), '1.33E+41')
555 self.assertEqual(str(Decimal('1_0_0_0')), '1000')
556
Stefan Krah1919b7e2012-03-21 18:25:23 +0100557 # unicode whitespace
558 for lead in ["", ' ', '\u00a0', '\u205f']:
559 for trail in ["", ' ', '\u00a0', '\u205f']:
560 self.assertEqual(str(Decimal(lead + '9.311E+28' + trail)),
561 '9.311E+28')
562
563 with localcontext() as c:
564 c.traps[InvalidOperation] = True
565 # Invalid string
566 self.assertRaises(InvalidOperation, Decimal, "xyz")
567 # Two arguments max
568 self.assertRaises(TypeError, Decimal, "1234", "x", "y")
569
570 # space within the numeric part
571 self.assertRaises(InvalidOperation, Decimal, "1\u00a02\u00a03")
572 self.assertRaises(InvalidOperation, Decimal, "\u00a01\u00a02\u00a0")
573
574 # unicode whitespace
575 self.assertRaises(InvalidOperation, Decimal, "\u00a0")
576 self.assertRaises(InvalidOperation, Decimal, "\u00a0\u00a0")
577
578 # embedded NUL
579 self.assertRaises(InvalidOperation, Decimal, "12\u00003")
580
Brett Cannona721aba2016-09-09 14:57:09 -0700581 # underscores don't prevent errors
582 self.assertRaises(InvalidOperation, Decimal, "1_2_\u00003")
583
Stefan Krah6e467042012-11-10 23:09:04 +0100584 @cpython_only
585 def test_from_legacy_strings(self):
586 import _testcapi
587 Decimal = self.decimal.Decimal
588 context = self.decimal.Context()
589
590 s = _testcapi.unicode_legacy_string('9.999999')
591 self.assertEqual(str(Decimal(s)), '9.999999')
592 self.assertEqual(str(context.create_decimal(s)), '9.999999')
Christian Heimesa62da1d2008-01-12 19:39:10 +0000593
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000594 def test_explicit_from_tuples(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100595 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000596
597 #zero
598 d = Decimal( (0, (0,), 0) )
599 self.assertEqual(str(d), '0')
600
601 #int
602 d = Decimal( (1, (4, 5), 0) )
603 self.assertEqual(str(d), '-45')
604
605 #float
606 d = Decimal( (0, (4, 5, 3, 4), -2) )
607 self.assertEqual(str(d), '45.34')
608
609 #weird
610 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
611 self.assertEqual(str(d), '-4.34913534E-17')
612
Stefan Krah1919b7e2012-03-21 18:25:23 +0100613 #inf
614 d = Decimal( (0, (), "F") )
615 self.assertEqual(str(d), 'Infinity')
616
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000617 #wrong number of items
618 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1)) )
619
620 #bad sign
621 self.assertRaises(ValueError, Decimal, (8, (4, 3, 4, 9, 1), 2) )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000622 self.assertRaises(ValueError, Decimal, (0., (4, 3, 4, 9, 1), 2) )
623 self.assertRaises(ValueError, Decimal, (Decimal(1), (4, 3, 4, 9, 1), 2))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000624
625 #bad exp
626 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 'wrong!') )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000627 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 0.) )
628 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), '1') )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000629
630 #bad coefficients
Stefan Krah1919b7e2012-03-21 18:25:23 +0100631 self.assertRaises(ValueError, Decimal, (1, "xyz", 2) )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000632 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, None, 1), 2) )
633 self.assertRaises(ValueError, Decimal, (1, (4, -3, 4, 9, 1), 2) )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000634 self.assertRaises(ValueError, Decimal, (1, (4, 10, 4, 9, 1), 2) )
Guido van Rossum0d3fb8a2007-11-26 23:23:18 +0000635 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 'a', 1), 2) )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000636
Stefan Krah1919b7e2012-03-21 18:25:23 +0100637 def test_explicit_from_list(self):
638 Decimal = self.decimal.Decimal
639
640 d = Decimal([0, [0], 0])
641 self.assertEqual(str(d), '0')
642
643 d = Decimal([1, [4, 3, 4, 9, 1, 3, 5, 3, 4], -25])
644 self.assertEqual(str(d), '-4.34913534E-17')
645
646 d = Decimal([1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25])
647 self.assertEqual(str(d), '-4.34913534E-17')
648
649 d = Decimal((1, [4, 3, 4, 9, 1, 3, 5, 3, 4], -25))
650 self.assertEqual(str(d), '-4.34913534E-17')
651
Antoine Pitrou503ab332010-03-30 18:56:19 +0000652 def test_explicit_from_bool(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100653 Decimal = self.decimal.Decimal
654
Antoine Pitrou503ab332010-03-30 18:56:19 +0000655 self.assertIs(bool(Decimal(0)), False)
656 self.assertIs(bool(Decimal(1)), True)
657 self.assertEqual(Decimal(False), Decimal(0))
658 self.assertEqual(Decimal(True), Decimal(1))
659
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000660 def test_explicit_from_Decimal(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100661 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000662
663 #positive
664 d = Decimal(45)
665 e = Decimal(d)
666 self.assertEqual(str(e), '45')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000667
668 #very large positive
669 d = Decimal(500000123)
670 e = Decimal(d)
671 self.assertEqual(str(e), '500000123')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000672
673 #negative
674 d = Decimal(-45)
675 e = Decimal(d)
676 self.assertEqual(str(e), '-45')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000677
678 #zero
679 d = Decimal(0)
680 e = Decimal(d)
681 self.assertEqual(str(e), '0')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000682
Raymond Hettinger96798592010-04-02 16:58:27 +0000683 @requires_IEEE_754
684 def test_explicit_from_float(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100685
686 Decimal = self.decimal.Decimal
687
Raymond Hettinger96798592010-04-02 16:58:27 +0000688 r = Decimal(0.1)
689 self.assertEqual(type(r), Decimal)
690 self.assertEqual(str(r),
691 '0.1000000000000000055511151231257827021181583404541015625')
692 self.assertTrue(Decimal(float('nan')).is_qnan())
693 self.assertTrue(Decimal(float('inf')).is_infinite())
694 self.assertTrue(Decimal(float('-inf')).is_infinite())
695 self.assertEqual(str(Decimal(float('nan'))),
696 str(Decimal('NaN')))
697 self.assertEqual(str(Decimal(float('inf'))),
698 str(Decimal('Infinity')))
699 self.assertEqual(str(Decimal(float('-inf'))),
700 str(Decimal('-Infinity')))
701 self.assertEqual(str(Decimal(float('-0.0'))),
702 str(Decimal('-0')))
703 for i in range(200):
704 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
705 self.assertEqual(x, float(Decimal(x))) # roundtrip
706
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000707 def test_explicit_context_create_decimal(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100708 Decimal = self.decimal.Decimal
709 InvalidOperation = self.decimal.InvalidOperation
710 Rounded = self.decimal.Rounded
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000711
Stefan Krah1919b7e2012-03-21 18:25:23 +0100712 nc = copy.copy(self.decimal.getcontext())
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000713 nc.prec = 3
714
715 # empty
Raymond Hettingerfed52962004-07-14 15:41:57 +0000716 d = Decimal()
717 self.assertEqual(str(d), '0')
718 d = nc.create_decimal()
719 self.assertEqual(str(d), '0')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000720
721 # from None
722 self.assertRaises(TypeError, nc.create_decimal, None)
723
724 # from int
725 d = nc.create_decimal(456)
Ezio Melottie9615932010-01-24 19:26:24 +0000726 self.assertIsInstance(d, Decimal)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000727 self.assertEqual(nc.create_decimal(45678),
728 nc.create_decimal('457E+2'))
729
730 # from string
731 d = Decimal('456789')
732 self.assertEqual(str(d), '456789')
733 d = nc.create_decimal('456789')
734 self.assertEqual(str(d), '4.57E+5')
Christian Heimesa62da1d2008-01-12 19:39:10 +0000735 # leading and trailing whitespace should result in a NaN;
736 # spaces are already checked in Cowlishaw's test-suite, so
737 # here we just check that a trailing newline results in a NaN
738 self.assertEqual(str(nc.create_decimal('3.14\n')), 'NaN')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000739
740 # from tuples
741 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
742 self.assertEqual(str(d), '-4.34913534E-17')
743 d = nc.create_decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
744 self.assertEqual(str(d), '-4.35E-17')
745
746 # from Decimal
747 prevdec = Decimal(500000123)
748 d = Decimal(prevdec)
749 self.assertEqual(str(d), '500000123')
750 d = nc.create_decimal(prevdec)
751 self.assertEqual(str(d), '5.00E+8')
752
Stefan Krah1919b7e2012-03-21 18:25:23 +0100753 # more integers
754 nc.prec = 28
755 nc.traps[InvalidOperation] = True
756
757 for v in [-2**63-1, -2**63, -2**31-1, -2**31, 0,
758 2**31-1, 2**31, 2**63-1, 2**63]:
759 d = nc.create_decimal(v)
760 self.assertTrue(isinstance(d, Decimal))
761 self.assertEqual(int(d), v)
762
763 nc.prec = 3
764 nc.traps[Rounded] = True
765 self.assertRaises(Rounded, nc.create_decimal, 1234)
766
767 # from string
768 nc.prec = 28
769 self.assertEqual(str(nc.create_decimal('0E-017')), '0E-17')
770 self.assertEqual(str(nc.create_decimal('45')), '45')
771 self.assertEqual(str(nc.create_decimal('-Inf')), '-Infinity')
772 self.assertEqual(str(nc.create_decimal('NaN123')), 'NaN123')
773
774 # invalid arguments
775 self.assertRaises(InvalidOperation, nc.create_decimal, "xyz")
776 self.assertRaises(ValueError, nc.create_decimal, (1, "xyz", -25))
777 self.assertRaises(TypeError, nc.create_decimal, "1234", "5678")
Brett Cannona721aba2016-09-09 14:57:09 -0700778 # no whitespace and underscore stripping is done with this method
779 self.assertRaises(InvalidOperation, nc.create_decimal, " 1234")
780 self.assertRaises(InvalidOperation, nc.create_decimal, "12_34")
Stefan Krah1919b7e2012-03-21 18:25:23 +0100781
782 # too many NaN payload digits
783 nc.prec = 3
784 self.assertRaises(InvalidOperation, nc.create_decimal, 'NaN12345')
785 self.assertRaises(InvalidOperation, nc.create_decimal,
786 Decimal('NaN12345'))
787
788 nc.traps[InvalidOperation] = False
789 self.assertEqual(str(nc.create_decimal('NaN12345')), 'NaN')
790 self.assertTrue(nc.flags[InvalidOperation])
791
792 nc.flags[InvalidOperation] = False
793 self.assertEqual(str(nc.create_decimal(Decimal('NaN12345'))), 'NaN')
794 self.assertTrue(nc.flags[InvalidOperation])
795
796 def test_explicit_context_create_from_float(self):
797
798 Decimal = self.decimal.Decimal
799
800 nc = self.decimal.Context()
801 r = nc.create_decimal(0.1)
802 self.assertEqual(type(r), Decimal)
803 self.assertEqual(str(r), '0.1000000000000000055511151231')
804 self.assertTrue(nc.create_decimal(float('nan')).is_qnan())
805 self.assertTrue(nc.create_decimal(float('inf')).is_infinite())
806 self.assertTrue(nc.create_decimal(float('-inf')).is_infinite())
807 self.assertEqual(str(nc.create_decimal(float('nan'))),
808 str(nc.create_decimal('NaN')))
809 self.assertEqual(str(nc.create_decimal(float('inf'))),
810 str(nc.create_decimal('Infinity')))
811 self.assertEqual(str(nc.create_decimal(float('-inf'))),
812 str(nc.create_decimal('-Infinity')))
813 self.assertEqual(str(nc.create_decimal(float('-0.0'))),
814 str(nc.create_decimal('-0')))
815 nc.prec = 100
816 for i in range(200):
817 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
818 self.assertEqual(x, float(nc.create_decimal(x))) # roundtrip
819
Mark Dickinson345adc42009-08-02 10:14:23 +0000820 def test_unicode_digits(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100821 Decimal = self.decimal.Decimal
822
Mark Dickinson345adc42009-08-02 10:14:23 +0000823 test_values = {
824 '\uff11': '1',
825 '\u0660.\u0660\u0663\u0667\u0662e-\u0663' : '0.0000372',
826 '-nan\u0c68\u0c6a\u0c66\u0c66' : '-NaN2400',
827 }
828 for input, expected in test_values.items():
829 self.assertEqual(str(Decimal(input)), expected)
830
Stefan Krah1919b7e2012-03-21 18:25:23 +0100831class CExplicitConstructionTest(ExplicitConstructionTest):
832 decimal = C
833class PyExplicitConstructionTest(ExplicitConstructionTest):
834 decimal = P
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000835
Stefan Krah1919b7e2012-03-21 18:25:23 +0100836class ImplicitConstructionTest(unittest.TestCase):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000837 '''Unit tests for Implicit Construction cases of Decimal.'''
838
839 def test_implicit_from_None(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100840 Decimal = self.decimal.Decimal
841 self.assertRaises(TypeError, eval, 'Decimal(5) + None', locals())
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000842
843 def test_implicit_from_int(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100844 Decimal = self.decimal.Decimal
845
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000846 #normal
847 self.assertEqual(str(Decimal(5) + 45), '50')
848 #exceeding precision
849 self.assertEqual(Decimal(5) + 123456789000, Decimal(123456789000))
850
851 def test_implicit_from_string(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100852 Decimal = self.decimal.Decimal
853 self.assertRaises(TypeError, eval, 'Decimal(5) + "3"', locals())
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000854
855 def test_implicit_from_float(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100856 Decimal = self.decimal.Decimal
857 self.assertRaises(TypeError, eval, 'Decimal(5) + 2.2', locals())
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000858
859 def test_implicit_from_Decimal(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100860 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000861 self.assertEqual(Decimal(5) + Decimal(45), Decimal(50))
862
Raymond Hettinger267b8682005-03-27 10:47:39 +0000863 def test_rop(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100864 Decimal = self.decimal.Decimal
865
Raymond Hettinger267b8682005-03-27 10:47:39 +0000866 # Allow other classes to be trained to interact with Decimals
867 class E:
868 def __divmod__(self, other):
869 return 'divmod ' + str(other)
870 def __rdivmod__(self, other):
871 return str(other) + ' rdivmod'
872 def __lt__(self, other):
873 return 'lt ' + str(other)
874 def __gt__(self, other):
875 return 'gt ' + str(other)
876 def __le__(self, other):
877 return 'le ' + str(other)
878 def __ge__(self, other):
879 return 'ge ' + str(other)
880 def __eq__(self, other):
881 return 'eq ' + str(other)
882 def __ne__(self, other):
883 return 'ne ' + str(other)
884
885 self.assertEqual(divmod(E(), Decimal(10)), 'divmod 10')
886 self.assertEqual(divmod(Decimal(10), E()), '10 rdivmod')
887 self.assertEqual(eval('Decimal(10) < E()'), 'gt 10')
888 self.assertEqual(eval('Decimal(10) > E()'), 'lt 10')
889 self.assertEqual(eval('Decimal(10) <= E()'), 'ge 10')
890 self.assertEqual(eval('Decimal(10) >= E()'), 'le 10')
891 self.assertEqual(eval('Decimal(10) == E()'), 'eq 10')
892 self.assertEqual(eval('Decimal(10) != E()'), 'ne 10')
893
894 # insert operator methods and then exercise them
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000895 oplist = [
896 ('+', '__add__', '__radd__'),
897 ('-', '__sub__', '__rsub__'),
898 ('*', '__mul__', '__rmul__'),
Thomas Woutersdcc6d322006-04-21 11:30:52 +0000899 ('/', '__truediv__', '__rtruediv__'),
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000900 ('%', '__mod__', '__rmod__'),
901 ('//', '__floordiv__', '__rfloordiv__'),
902 ('**', '__pow__', '__rpow__')
903 ]
Raymond Hettinger267b8682005-03-27 10:47:39 +0000904
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000905 for sym, lop, rop in oplist:
Raymond Hettinger267b8682005-03-27 10:47:39 +0000906 setattr(E, lop, lambda self, other: 'str' + lop + str(other))
907 setattr(E, rop, lambda self, other: str(other) + rop + 'str')
908 self.assertEqual(eval('E()' + sym + 'Decimal(10)'),
909 'str' + lop + '10')
910 self.assertEqual(eval('Decimal(10)' + sym + 'E()'),
911 '10' + rop + 'str')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000912
Stefan Krah1919b7e2012-03-21 18:25:23 +0100913class CImplicitConstructionTest(ImplicitConstructionTest):
914 decimal = C
915class PyImplicitConstructionTest(ImplicitConstructionTest):
916 decimal = P
Mark Dickinson79f52032009-03-17 23:12:51 +0000917
Stefan Krah1919b7e2012-03-21 18:25:23 +0100918class FormatTest(unittest.TestCase):
Christian Heimesf16baeb2008-02-29 14:57:44 +0000919 '''Unit tests for the format function.'''
920 def test_formatting(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100921 Decimal = self.decimal.Decimal
922
Christian Heimesf16baeb2008-02-29 14:57:44 +0000923 # triples giving a format, a Decimal, and the expected result
924 test_values = [
925 ('e', '0E-15', '0e-15'),
926 ('e', '2.3E-15', '2.3e-15'),
927 ('e', '2.30E+2', '2.30e+2'), # preserve significant zeros
928 ('e', '2.30000E-15', '2.30000e-15'),
929 ('e', '1.23456789123456789e40', '1.23456789123456789e+40'),
930 ('e', '1.5', '1.5e+0'),
931 ('e', '0.15', '1.5e-1'),
932 ('e', '0.015', '1.5e-2'),
933 ('e', '0.0000000000015', '1.5e-12'),
934 ('e', '15.0', '1.50e+1'),
935 ('e', '-15', '-1.5e+1'),
936 ('e', '0', '0e+0'),
937 ('e', '0E1', '0e+1'),
938 ('e', '0.0', '0e-1'),
939 ('e', '0.00', '0e-2'),
940 ('.6e', '0E-15', '0.000000e-9'),
941 ('.6e', '0', '0.000000e+6'),
942 ('.6e', '9.999999', '9.999999e+0'),
943 ('.6e', '9.9999999', '1.000000e+1'),
944 ('.6e', '-1.23e5', '-1.230000e+5'),
945 ('.6e', '1.23456789e-3', '1.234568e-3'),
946 ('f', '0', '0'),
947 ('f', '0.0', '0.0'),
948 ('f', '0E-2', '0.00'),
949 ('f', '0.00E-8', '0.0000000000'),
950 ('f', '0E1', '0'), # loses exponent information
951 ('f', '3.2E1', '32'),
952 ('f', '3.2E2', '320'),
953 ('f', '3.20E2', '320'),
954 ('f', '3.200E2', '320.0'),
955 ('f', '3.2E-6', '0.0000032'),
956 ('.6f', '0E-15', '0.000000'), # all zeros treated equally
957 ('.6f', '0E1', '0.000000'),
958 ('.6f', '0', '0.000000'),
959 ('.0f', '0', '0'), # no decimal point
960 ('.0f', '0e-2', '0'),
961 ('.0f', '3.14159265', '3'),
962 ('.1f', '3.14159265', '3.1'),
963 ('.4f', '3.14159265', '3.1416'),
964 ('.6f', '3.14159265', '3.141593'),
965 ('.7f', '3.14159265', '3.1415926'), # round-half-even!
966 ('.8f', '3.14159265', '3.14159265'),
967 ('.9f', '3.14159265', '3.141592650'),
968
969 ('g', '0', '0'),
970 ('g', '0.0', '0.0'),
971 ('g', '0E1', '0e+1'),
972 ('G', '0E1', '0E+1'),
973 ('g', '0E-5', '0.00000'),
974 ('g', '0E-6', '0.000000'),
975 ('g', '0E-7', '0e-7'),
976 ('g', '-0E2', '-0e+2'),
977 ('.0g', '3.14159265', '3'), # 0 sig fig -> 1 sig fig
Stefan Krah1919b7e2012-03-21 18:25:23 +0100978 ('.0n', '3.14159265', '3'), # same for 'n'
Christian Heimesf16baeb2008-02-29 14:57:44 +0000979 ('.1g', '3.14159265', '3'),
980 ('.2g', '3.14159265', '3.1'),
981 ('.5g', '3.14159265', '3.1416'),
982 ('.7g', '3.14159265', '3.141593'),
983 ('.8g', '3.14159265', '3.1415926'), # round-half-even!
984 ('.9g', '3.14159265', '3.14159265'),
985 ('.10g', '3.14159265', '3.14159265'), # don't pad
986
987 ('%', '0E1', '0%'),
988 ('%', '0E0', '0%'),
989 ('%', '0E-1', '0%'),
990 ('%', '0E-2', '0%'),
991 ('%', '0E-3', '0.0%'),
992 ('%', '0E-4', '0.00%'),
993
994 ('.3%', '0', '0.000%'), # all zeros treated equally
995 ('.3%', '0E10', '0.000%'),
996 ('.3%', '0E-10', '0.000%'),
997 ('.3%', '2.34', '234.000%'),
998 ('.3%', '1.234567', '123.457%'),
999 ('.0%', '1.23', '123%'),
1000
1001 ('e', 'NaN', 'NaN'),
1002 ('f', '-NaN123', '-NaN123'),
1003 ('+g', 'NaN456', '+NaN456'),
1004 ('.3e', 'Inf', 'Infinity'),
1005 ('.16f', '-Inf', '-Infinity'),
1006 ('.0g', '-sNaN', '-sNaN'),
1007
1008 ('', '1.00', '1.00'),
Mark Dickinsonad416342009-03-17 18:10:15 +00001009
Mark Dickinson79f52032009-03-17 23:12:51 +00001010 # test alignment and padding
Mark Dickinson46ab5d02009-09-08 20:22:46 +00001011 ('6', '123', ' 123'),
Mark Dickinsonad416342009-03-17 18:10:15 +00001012 ('<6', '123', '123 '),
1013 ('>6', '123', ' 123'),
1014 ('^6', '123', ' 123 '),
1015 ('=+6', '123', '+ 123'),
Mark Dickinson79f52032009-03-17 23:12:51 +00001016 ('#<10', 'NaN', 'NaN#######'),
1017 ('#<10', '-4.3', '-4.3######'),
1018 ('#<+10', '0.0130', '+0.0130###'),
1019 ('#< 10', '0.0130', ' 0.0130###'),
1020 ('@>10', '-Inf', '@-Infinity'),
1021 ('#>5', '-Inf', '-Infinity'),
1022 ('?^5', '123', '?123?'),
1023 ('%^6', '123', '%123%%'),
1024 (' ^6', '-45.6', '-45.6 '),
1025 ('/=10', '-45.6', '-/////45.6'),
1026 ('/=+10', '45.6', '+/////45.6'),
1027 ('/= 10', '45.6', ' /////45.6'),
Stefan Krah6edda142013-05-29 15:45:38 +02001028 ('\x00=10', '-inf', '-\x00Infinity'),
1029 ('\x00^16', '-inf', '\x00\x00\x00-Infinity\x00\x00\x00\x00'),
1030 ('\x00>10', '1.2345', '\x00\x00\x00\x001.2345'),
1031 ('\x00<10', '1.2345', '1.2345\x00\x00\x00\x00'),
Mark Dickinson79f52032009-03-17 23:12:51 +00001032
1033 # thousands separator
1034 (',', '1234567', '1,234,567'),
1035 (',', '123456', '123,456'),
1036 (',', '12345', '12,345'),
1037 (',', '1234', '1,234'),
1038 (',', '123', '123'),
1039 (',', '12', '12'),
1040 (',', '1', '1'),
1041 (',', '0', '0'),
1042 (',', '-1234567', '-1,234,567'),
1043 (',', '-123456', '-123,456'),
1044 ('7,', '123456', '123,456'),
Mark Dickinson46ab5d02009-09-08 20:22:46 +00001045 ('8,', '123456', ' 123,456'),
Mark Dickinson79f52032009-03-17 23:12:51 +00001046 ('08,', '123456', '0,123,456'), # special case: extra 0 needed
1047 ('+08,', '123456', '+123,456'), # but not if there's a sign
1048 (' 08,', '123456', ' 123,456'),
1049 ('08,', '-123456', '-123,456'),
1050 ('+09,', '123456', '+0,123,456'),
1051 # ... with fractional part...
1052 ('07,', '1234.56', '1,234.56'),
1053 ('08,', '1234.56', '1,234.56'),
1054 ('09,', '1234.56', '01,234.56'),
1055 ('010,', '1234.56', '001,234.56'),
1056 ('011,', '1234.56', '0,001,234.56'),
1057 ('012,', '1234.56', '0,001,234.56'),
1058 ('08,.1f', '1234.5', '01,234.5'),
1059 # no thousands separators in fraction part
1060 (',', '1.23456789', '1.23456789'),
1061 (',%', '123.456789', '12,345.6789%'),
1062 (',e', '123456', '1.23456e+5'),
1063 (',E', '123456', '1.23456E+5'),
Mark Dickinson7718d2b2009-09-07 16:21:56 +00001064
1065 # issue 6850
1066 ('a=-7.0', '0.12345', 'aaaa0.1'),
Stefan Krah298131a2014-08-26 20:46:49 +02001067
1068 # issue 22090
1069 ('<^+15.20%', 'inf', '<<+Infinity%<<<'),
1070 ('\x07>,%', 'sNaN1234567', 'sNaN1234567%'),
1071 ('=10.10%', 'NaN123', ' NaN123%'),
Christian Heimesf16baeb2008-02-29 14:57:44 +00001072 ]
1073 for fmt, d, result in test_values:
1074 self.assertEqual(format(Decimal(d), fmt), result)
1075
Stefan Krah1919b7e2012-03-21 18:25:23 +01001076 # bytes format argument
1077 self.assertRaises(TypeError, Decimal(1).__format__, b'-020')
1078
Mark Dickinson79f52032009-03-17 23:12:51 +00001079 def test_n_format(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001080 Decimal = self.decimal.Decimal
1081
Mark Dickinson79f52032009-03-17 23:12:51 +00001082 try:
1083 from locale import CHAR_MAX
1084 except ImportError:
Zachary Ware9fe6d862013-12-08 00:20:35 -06001085 self.skipTest('locale.CHAR_MAX not available')
Mark Dickinson79f52032009-03-17 23:12:51 +00001086
Stefan Krah1919b7e2012-03-21 18:25:23 +01001087 def make_grouping(lst):
1088 return ''.join([chr(x) for x in lst]) if self.decimal == C else lst
1089
1090 def get_fmt(x, override=None, fmt='n'):
1091 if self.decimal == C:
1092 return Decimal(x).__format__(fmt, override)
1093 else:
1094 return Decimal(x).__format__(fmt, _localeconv=override)
1095
Mark Dickinson79f52032009-03-17 23:12:51 +00001096 # Set up some localeconv-like dictionaries
1097 en_US = {
1098 'decimal_point' : '.',
Stefan Krah1919b7e2012-03-21 18:25:23 +01001099 'grouping' : make_grouping([3, 3, 0]),
1100 'thousands_sep' : ','
Mark Dickinson79f52032009-03-17 23:12:51 +00001101 }
1102
1103 fr_FR = {
1104 'decimal_point' : ',',
Stefan Krah1919b7e2012-03-21 18:25:23 +01001105 'grouping' : make_grouping([CHAR_MAX]),
Mark Dickinson79f52032009-03-17 23:12:51 +00001106 'thousands_sep' : ''
1107 }
1108
1109 ru_RU = {
1110 'decimal_point' : ',',
Stefan Krah1919b7e2012-03-21 18:25:23 +01001111 'grouping': make_grouping([3, 3, 0]),
Mark Dickinson79f52032009-03-17 23:12:51 +00001112 'thousands_sep' : ' '
1113 }
1114
1115 crazy = {
1116 'decimal_point' : '&',
Stefan Krah1919b7e2012-03-21 18:25:23 +01001117 'grouping': make_grouping([1, 4, 2, CHAR_MAX]),
Mark Dickinson79f52032009-03-17 23:12:51 +00001118 'thousands_sep' : '-'
1119 }
1120
Stefan Krah1919b7e2012-03-21 18:25:23 +01001121 dotsep_wide = {
1122 'decimal_point' : b'\xc2\xbf'.decode('utf-8'),
1123 'grouping': make_grouping([3, 3, 0]),
1124 'thousands_sep' : b'\xc2\xb4'.decode('utf-8')
1125 }
Mark Dickinson79f52032009-03-17 23:12:51 +00001126
1127 self.assertEqual(get_fmt(Decimal('12.7'), en_US), '12.7')
1128 self.assertEqual(get_fmt(Decimal('12.7'), fr_FR), '12,7')
1129 self.assertEqual(get_fmt(Decimal('12.7'), ru_RU), '12,7')
1130 self.assertEqual(get_fmt(Decimal('12.7'), crazy), '1-2&7')
1131
1132 self.assertEqual(get_fmt(123456789, en_US), '123,456,789')
1133 self.assertEqual(get_fmt(123456789, fr_FR), '123456789')
1134 self.assertEqual(get_fmt(123456789, ru_RU), '123 456 789')
1135 self.assertEqual(get_fmt(1234567890123, crazy), '123456-78-9012-3')
1136
1137 self.assertEqual(get_fmt(123456789, en_US, '.6n'), '1.23457e+8')
1138 self.assertEqual(get_fmt(123456789, fr_FR, '.6n'), '1,23457e+8')
1139 self.assertEqual(get_fmt(123456789, ru_RU, '.6n'), '1,23457e+8')
1140 self.assertEqual(get_fmt(123456789, crazy, '.6n'), '1&23457e+8')
1141
Mark Dickinson7303b592009-03-18 08:25:36 +00001142 # zero padding
1143 self.assertEqual(get_fmt(1234, fr_FR, '03n'), '1234')
1144 self.assertEqual(get_fmt(1234, fr_FR, '04n'), '1234')
1145 self.assertEqual(get_fmt(1234, fr_FR, '05n'), '01234')
1146 self.assertEqual(get_fmt(1234, fr_FR, '06n'), '001234')
1147
1148 self.assertEqual(get_fmt(12345, en_US, '05n'), '12,345')
1149 self.assertEqual(get_fmt(12345, en_US, '06n'), '12,345')
1150 self.assertEqual(get_fmt(12345, en_US, '07n'), '012,345')
1151 self.assertEqual(get_fmt(12345, en_US, '08n'), '0,012,345')
1152 self.assertEqual(get_fmt(12345, en_US, '09n'), '0,012,345')
1153 self.assertEqual(get_fmt(12345, en_US, '010n'), '00,012,345')
1154
1155 self.assertEqual(get_fmt(123456, crazy, '06n'), '1-2345-6')
1156 self.assertEqual(get_fmt(123456, crazy, '07n'), '1-2345-6')
1157 self.assertEqual(get_fmt(123456, crazy, '08n'), '1-2345-6')
1158 self.assertEqual(get_fmt(123456, crazy, '09n'), '01-2345-6')
1159 self.assertEqual(get_fmt(123456, crazy, '010n'), '0-01-2345-6')
1160 self.assertEqual(get_fmt(123456, crazy, '011n'), '0-01-2345-6')
1161 self.assertEqual(get_fmt(123456, crazy, '012n'), '00-01-2345-6')
1162 self.assertEqual(get_fmt(123456, crazy, '013n'), '000-01-2345-6')
1163
Stefan Krah1919b7e2012-03-21 18:25:23 +01001164 # wide char separator and decimal point
1165 self.assertEqual(get_fmt(Decimal('-1.5'), dotsep_wide, '020n'),
1166 '-0\u00b4000\u00b4000\u00b4000\u00b4001\u00bf5')
Mark Dickinson79f52032009-03-17 23:12:51 +00001167
Stefan Krah6fb204a2012-09-28 16:18:54 +02001168 @run_with_locale('LC_ALL', 'ps_AF')
Stefan Krah1919b7e2012-03-21 18:25:23 +01001169 def test_wide_char_separator_decimal_point(self):
1170 # locale with wide char separator and decimal point
1171 Decimal = self.decimal.Decimal
1172
Stefan Krah8a491a82012-09-28 17:17:11 +02001173 decimal_point = locale.localeconv()['decimal_point']
1174 thousands_sep = locale.localeconv()['thousands_sep']
Zachary Ware9fe6d862013-12-08 00:20:35 -06001175 if decimal_point != '\u066b':
Serhiy Storchaka34fd4c22018-11-05 16:20:25 +02001176 self.skipTest('inappropriate decimal point separator '
Zachary Ware0f533ac2013-12-12 10:32:16 -06001177 '({!a} not {!a})'.format(decimal_point, '\u066b'))
Zachary Ware9fe6d862013-12-08 00:20:35 -06001178 if thousands_sep != '\u066c':
Serhiy Storchaka34fd4c22018-11-05 16:20:25 +02001179 self.skipTest('inappropriate thousands separator '
Zachary Ware0f533ac2013-12-12 10:32:16 -06001180 '({!a} not {!a})'.format(thousands_sep, '\u066c'))
Stefan Krah8a491a82012-09-28 17:17:11 +02001181
Stefan Krah1919b7e2012-03-21 18:25:23 +01001182 self.assertEqual(format(Decimal('100000000.123'), 'n'),
1183 '100\u066c000\u066c000\u066b123')
Stefan Krah1919b7e2012-03-21 18:25:23 +01001184
Andrew Nester6d1dece2017-02-14 21:22:55 +03001185 def test_decimal_from_float_argument_type(self):
1186 class A(self.decimal.Decimal):
1187 def __init__(self, a):
1188 self.a_type = type(a)
1189 a = A.from_float(42.5)
1190 self.assertEqual(self.decimal.Decimal, a.a_type)
1191
1192 a = A.from_float(42)
1193 self.assertEqual(self.decimal.Decimal, a.a_type)
1194
Stefan Krah1919b7e2012-03-21 18:25:23 +01001195class CFormatTest(FormatTest):
1196 decimal = C
1197class PyFormatTest(FormatTest):
1198 decimal = P
1199
1200class ArithmeticOperatorsTest(unittest.TestCase):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001201 '''Unit tests for all arithmetic operators, binary and unary.'''
1202
1203 def test_addition(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001204 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001205
1206 d1 = Decimal('-11.1')
1207 d2 = Decimal('22.2')
1208
1209 #two Decimals
1210 self.assertEqual(d1+d2, Decimal('11.1'))
1211 self.assertEqual(d2+d1, Decimal('11.1'))
1212
1213 #with other type, left
1214 c = d1 + 5
1215 self.assertEqual(c, Decimal('-6.1'))
1216 self.assertEqual(type(c), type(d1))
1217
1218 #with other type, right
1219 c = 5 + d1
1220 self.assertEqual(c, Decimal('-6.1'))
1221 self.assertEqual(type(c), type(d1))
1222
1223 #inline with decimal
1224 d1 += d2
1225 self.assertEqual(d1, Decimal('11.1'))
1226
1227 #inline with other type
1228 d1 += 5
1229 self.assertEqual(d1, Decimal('16.1'))
1230
1231 def test_subtraction(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001232 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001233
1234 d1 = Decimal('-11.1')
1235 d2 = Decimal('22.2')
1236
1237 #two Decimals
1238 self.assertEqual(d1-d2, Decimal('-33.3'))
1239 self.assertEqual(d2-d1, Decimal('33.3'))
1240
1241 #with other type, left
1242 c = d1 - 5
1243 self.assertEqual(c, Decimal('-16.1'))
1244 self.assertEqual(type(c), type(d1))
1245
1246 #with other type, right
1247 c = 5 - d1
1248 self.assertEqual(c, Decimal('16.1'))
1249 self.assertEqual(type(c), type(d1))
1250
1251 #inline with decimal
1252 d1 -= d2
1253 self.assertEqual(d1, Decimal('-33.3'))
1254
1255 #inline with other type
1256 d1 -= 5
1257 self.assertEqual(d1, Decimal('-38.3'))
1258
1259 def test_multiplication(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001260 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001261
1262 d1 = Decimal('-5')
1263 d2 = Decimal('3')
1264
1265 #two Decimals
1266 self.assertEqual(d1*d2, Decimal('-15'))
1267 self.assertEqual(d2*d1, Decimal('-15'))
1268
1269 #with other type, left
1270 c = d1 * 5
1271 self.assertEqual(c, Decimal('-25'))
1272 self.assertEqual(type(c), type(d1))
1273
1274 #with other type, right
1275 c = 5 * d1
1276 self.assertEqual(c, Decimal('-25'))
1277 self.assertEqual(type(c), type(d1))
1278
1279 #inline with decimal
1280 d1 *= d2
1281 self.assertEqual(d1, Decimal('-15'))
1282
1283 #inline with other type
1284 d1 *= 5
1285 self.assertEqual(d1, Decimal('-75'))
1286
1287 def test_division(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001288 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001289
1290 d1 = Decimal('-5')
1291 d2 = Decimal('2')
1292
1293 #two Decimals
1294 self.assertEqual(d1/d2, Decimal('-2.5'))
1295 self.assertEqual(d2/d1, Decimal('-0.4'))
1296
1297 #with other type, left
1298 c = d1 / 4
1299 self.assertEqual(c, Decimal('-1.25'))
1300 self.assertEqual(type(c), type(d1))
1301
1302 #with other type, right
1303 c = 4 / d1
1304 self.assertEqual(c, Decimal('-0.8'))
1305 self.assertEqual(type(c), type(d1))
1306
1307 #inline with decimal
1308 d1 /= d2
1309 self.assertEqual(d1, Decimal('-2.5'))
1310
1311 #inline with other type
1312 d1 /= 4
1313 self.assertEqual(d1, Decimal('-0.625'))
1314
1315 def test_floor_division(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001316 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001317
1318 d1 = Decimal('5')
1319 d2 = Decimal('2')
1320
1321 #two Decimals
1322 self.assertEqual(d1//d2, Decimal('2'))
1323 self.assertEqual(d2//d1, Decimal('0'))
1324
1325 #with other type, left
1326 c = d1 // 4
1327 self.assertEqual(c, Decimal('1'))
1328 self.assertEqual(type(c), type(d1))
1329
1330 #with other type, right
1331 c = 7 // d1
1332 self.assertEqual(c, Decimal('1'))
1333 self.assertEqual(type(c), type(d1))
1334
1335 #inline with decimal
1336 d1 //= d2
1337 self.assertEqual(d1, Decimal('2'))
1338
1339 #inline with other type
1340 d1 //= 2
1341 self.assertEqual(d1, Decimal('1'))
1342
1343 def test_powering(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001344 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001345
1346 d1 = Decimal('5')
1347 d2 = Decimal('2')
1348
1349 #two Decimals
1350 self.assertEqual(d1**d2, Decimal('25'))
1351 self.assertEqual(d2**d1, Decimal('32'))
1352
1353 #with other type, left
1354 c = d1 ** 4
1355 self.assertEqual(c, Decimal('625'))
1356 self.assertEqual(type(c), type(d1))
1357
1358 #with other type, right
1359 c = 7 ** d1
1360 self.assertEqual(c, Decimal('16807'))
1361 self.assertEqual(type(c), type(d1))
1362
1363 #inline with decimal
1364 d1 **= d2
1365 self.assertEqual(d1, Decimal('25'))
1366
1367 #inline with other type
1368 d1 **= 4
1369 self.assertEqual(d1, Decimal('390625'))
1370
1371 def test_module(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001372 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001373
1374 d1 = Decimal('5')
1375 d2 = Decimal('2')
1376
1377 #two Decimals
1378 self.assertEqual(d1%d2, Decimal('1'))
1379 self.assertEqual(d2%d1, Decimal('2'))
1380
1381 #with other type, left
1382 c = d1 % 4
1383 self.assertEqual(c, Decimal('1'))
1384 self.assertEqual(type(c), type(d1))
1385
1386 #with other type, right
1387 c = 7 % d1
1388 self.assertEqual(c, Decimal('2'))
1389 self.assertEqual(type(c), type(d1))
1390
1391 #inline with decimal
1392 d1 %= d2
1393 self.assertEqual(d1, Decimal('1'))
1394
1395 #inline with other type
1396 d1 %= 4
1397 self.assertEqual(d1, Decimal('1'))
1398
1399 def test_floor_div_module(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001400 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001401
1402 d1 = Decimal('5')
1403 d2 = Decimal('2')
1404
1405 #two Decimals
1406 (p, q) = divmod(d1, d2)
1407 self.assertEqual(p, Decimal('2'))
1408 self.assertEqual(q, Decimal('1'))
1409 self.assertEqual(type(p), type(d1))
1410 self.assertEqual(type(q), type(d1))
1411
1412 #with other type, left
1413 (p, q) = divmod(d1, 4)
1414 self.assertEqual(p, Decimal('1'))
1415 self.assertEqual(q, Decimal('1'))
1416 self.assertEqual(type(p), type(d1))
1417 self.assertEqual(type(q), type(d1))
1418
1419 #with other type, right
1420 (p, q) = divmod(7, d1)
1421 self.assertEqual(p, Decimal('1'))
1422 self.assertEqual(q, Decimal('2'))
1423 self.assertEqual(type(p), type(d1))
1424 self.assertEqual(type(q), type(d1))
1425
1426 def test_unary_operators(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001427 Decimal = self.decimal.Decimal
1428
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001429 self.assertEqual(+Decimal(45), Decimal(+45)) # +
1430 self.assertEqual(-Decimal(45), Decimal(-45)) # -
1431 self.assertEqual(abs(Decimal(45)), abs(Decimal(-45))) # abs
1432
Christian Heimes77c02eb2008-02-09 02:18:51 +00001433 def test_nan_comparisons(self):
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001434 # comparisons involving signaling nans signal InvalidOperation
1435
1436 # order comparisons (<, <=, >, >=) involving only quiet nans
1437 # also signal InvalidOperation
1438
1439 # equality comparisons (==, !=) involving only quiet nans
1440 # don't signal, but return False or True respectively.
Stefan Krah1919b7e2012-03-21 18:25:23 +01001441 Decimal = self.decimal.Decimal
1442 InvalidOperation = self.decimal.InvalidOperation
1443 localcontext = self.decimal.localcontext
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001444
Christian Heimes77c02eb2008-02-09 02:18:51 +00001445 n = Decimal('NaN')
1446 s = Decimal('sNaN')
1447 i = Decimal('Inf')
1448 f = Decimal('2')
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001449
1450 qnan_pairs = (n, n), (n, i), (i, n), (n, f), (f, n)
1451 snan_pairs = (s, n), (n, s), (s, i), (i, s), (s, f), (f, s), (s, s)
1452 order_ops = operator.lt, operator.le, operator.gt, operator.ge
1453 equality_ops = operator.eq, operator.ne
1454
1455 # results when InvalidOperation is not trapped
1456 for x, y in qnan_pairs + snan_pairs:
1457 for op in order_ops + equality_ops:
1458 got = op(x, y)
1459 expected = True if op is operator.ne else False
1460 self.assertIs(expected, got,
1461 "expected {0!r} for operator.{1}({2!r}, {3!r}); "
1462 "got {4!r}".format(
1463 expected, op.__name__, x, y, got))
1464
1465 # repeat the above, but this time trap the InvalidOperation
1466 with localcontext() as ctx:
1467 ctx.traps[InvalidOperation] = 1
1468
1469 for x, y in qnan_pairs:
1470 for op in equality_ops:
1471 got = op(x, y)
1472 expected = True if op is operator.ne else False
1473 self.assertIs(expected, got,
1474 "expected {0!r} for "
1475 "operator.{1}({2!r}, {3!r}); "
1476 "got {4!r}".format(
1477 expected, op.__name__, x, y, got))
1478
1479 for x, y in snan_pairs:
1480 for op in equality_ops:
1481 self.assertRaises(InvalidOperation, operator.eq, x, y)
1482 self.assertRaises(InvalidOperation, operator.ne, x, y)
1483
1484 for x, y in qnan_pairs + snan_pairs:
1485 for op in order_ops:
1486 self.assertRaises(InvalidOperation, op, x, y)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001487
Mark Dickinson84230a12010-02-18 14:49:50 +00001488 def test_copy_sign(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001489 Decimal = self.decimal.Decimal
Mark Dickinson84230a12010-02-18 14:49:50 +00001490
Stefan Krah1919b7e2012-03-21 18:25:23 +01001491 d = Decimal(1).copy_sign(Decimal(-2))
Mark Dickinson84230a12010-02-18 14:49:50 +00001492 self.assertEqual(Decimal(1).copy_sign(-2), d)
1493 self.assertRaises(TypeError, Decimal(1).copy_sign, '-2')
1494
Stefan Krah1919b7e2012-03-21 18:25:23 +01001495class CArithmeticOperatorsTest(ArithmeticOperatorsTest):
1496 decimal = C
1497class PyArithmeticOperatorsTest(ArithmeticOperatorsTest):
1498 decimal = P
1499
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001500# The following are two functions used to test threading in the next class
1501
1502def thfunc1(cls):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001503 Decimal = cls.decimal.Decimal
1504 InvalidOperation = cls.decimal.InvalidOperation
1505 DivisionByZero = cls.decimal.DivisionByZero
1506 Overflow = cls.decimal.Overflow
1507 Underflow = cls.decimal.Underflow
1508 Inexact = cls.decimal.Inexact
1509 getcontext = cls.decimal.getcontext
1510 localcontext = cls.decimal.localcontext
1511
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001512 d1 = Decimal(1)
1513 d3 = Decimal(3)
Christian Heimesfe337bf2008-03-23 21:54:12 +00001514 test1 = d1/d3
Christian Heimesfe337bf2008-03-23 21:54:12 +00001515
Stefan Krah1919b7e2012-03-21 18:25:23 +01001516 cls.finish1.set()
1517 cls.synchro.wait()
1518
1519 test2 = d1/d3
1520 with localcontext() as c2:
1521 cls.assertTrue(c2.flags[Inexact])
1522 cls.assertRaises(DivisionByZero, c2.divide, d1, 0)
1523 cls.assertTrue(c2.flags[DivisionByZero])
1524 with localcontext() as c3:
1525 cls.assertTrue(c3.flags[Inexact])
1526 cls.assertTrue(c3.flags[DivisionByZero])
1527 cls.assertRaises(InvalidOperation, c3.compare, d1, Decimal('sNaN'))
1528 cls.assertTrue(c3.flags[InvalidOperation])
1529 del c3
1530 cls.assertFalse(c2.flags[InvalidOperation])
1531 del c2
1532
1533 cls.assertEqual(test1, Decimal('0.333333333333333333333333'))
1534 cls.assertEqual(test2, Decimal('0.333333333333333333333333'))
1535
1536 c1 = getcontext()
1537 cls.assertTrue(c1.flags[Inexact])
1538 for sig in Overflow, Underflow, DivisionByZero, InvalidOperation:
1539 cls.assertFalse(c1.flags[sig])
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001540
1541def thfunc2(cls):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001542 Decimal = cls.decimal.Decimal
1543 InvalidOperation = cls.decimal.InvalidOperation
1544 DivisionByZero = cls.decimal.DivisionByZero
1545 Overflow = cls.decimal.Overflow
1546 Underflow = cls.decimal.Underflow
1547 Inexact = cls.decimal.Inexact
1548 getcontext = cls.decimal.getcontext
1549 localcontext = cls.decimal.localcontext
1550
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001551 d1 = Decimal(1)
1552 d3 = Decimal(3)
Christian Heimesfe337bf2008-03-23 21:54:12 +00001553 test1 = d1/d3
Stefan Krah1919b7e2012-03-21 18:25:23 +01001554
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001555 thiscontext = getcontext()
1556 thiscontext.prec = 18
Christian Heimesfe337bf2008-03-23 21:54:12 +00001557 test2 = d1/d3
Stefan Krah1919b7e2012-03-21 18:25:23 +01001558
1559 with localcontext() as c2:
1560 cls.assertTrue(c2.flags[Inexact])
1561 cls.assertRaises(Overflow, c2.multiply, Decimal('1e425000000'), 999)
1562 cls.assertTrue(c2.flags[Overflow])
1563 with localcontext(thiscontext) as c3:
1564 cls.assertTrue(c3.flags[Inexact])
1565 cls.assertFalse(c3.flags[Overflow])
1566 c3.traps[Underflow] = True
1567 cls.assertRaises(Underflow, c3.divide, Decimal('1e-425000000'), 999)
1568 cls.assertTrue(c3.flags[Underflow])
1569 del c3
1570 cls.assertFalse(c2.flags[Underflow])
1571 cls.assertFalse(c2.traps[Underflow])
1572 del c2
1573
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001574 cls.synchro.set()
1575 cls.finish2.set()
Christian Heimesfe337bf2008-03-23 21:54:12 +00001576
Stefan Krah1919b7e2012-03-21 18:25:23 +01001577 cls.assertEqual(test1, Decimal('0.333333333333333333333333'))
Christian Heimesfe337bf2008-03-23 21:54:12 +00001578 cls.assertEqual(test2, Decimal('0.333333333333333333'))
Stefan Krah1919b7e2012-03-21 18:25:23 +01001579
1580 cls.assertFalse(thiscontext.traps[Underflow])
1581 cls.assertTrue(thiscontext.flags[Inexact])
1582 for sig in Overflow, Underflow, DivisionByZero, InvalidOperation:
1583 cls.assertFalse(thiscontext.flags[sig])
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001584
Stefan Krah1919b7e2012-03-21 18:25:23 +01001585class ThreadingTest(unittest.TestCase):
1586 '''Unit tests for thread local contexts in Decimal.'''
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001587
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001588 # Take care executing this test from IDLE, there's an issue in threading
1589 # that hangs IDLE and I couldn't find it
1590
1591 def test_threading(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001592 DefaultContext = self.decimal.DefaultContext
1593
1594 if self.decimal == C and not self.decimal.HAVE_THREADS:
1595 self.skipTest("compiled without threading")
1596 # Test the "threading isolation" of a Context. Also test changing
1597 # the DefaultContext, which acts as a template for the thread-local
1598 # contexts.
1599 save_prec = DefaultContext.prec
1600 save_emax = DefaultContext.Emax
1601 save_emin = DefaultContext.Emin
1602 DefaultContext.prec = 24
1603 DefaultContext.Emax = 425000000
1604 DefaultContext.Emin = -425000000
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001605
1606 self.synchro = threading.Event()
1607 self.finish1 = threading.Event()
1608 self.finish2 = threading.Event()
1609
1610 th1 = threading.Thread(target=thfunc1, args=(self,))
1611 th2 = threading.Thread(target=thfunc2, args=(self,))
1612
1613 th1.start()
1614 th2.start()
1615
1616 self.finish1.wait()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001617 self.finish2.wait()
Stefan Krah1919b7e2012-03-21 18:25:23 +01001618
1619 for sig in Signals[self.decimal]:
1620 self.assertFalse(DefaultContext.flags[sig])
1621
Victor Stinner18e95b42017-09-14 08:43:04 -07001622 th1.join()
1623 th2.join()
1624
Stefan Krah1919b7e2012-03-21 18:25:23 +01001625 DefaultContext.prec = save_prec
1626 DefaultContext.Emax = save_emax
1627 DefaultContext.Emin = save_emin
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001628
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02001629
Stefan Krah1919b7e2012-03-21 18:25:23 +01001630class CThreadingTest(ThreadingTest):
1631 decimal = C
Antoine Pitroua6a4dc82017-09-07 18:56:24 +02001632
Stefan Krah1919b7e2012-03-21 18:25:23 +01001633class PyThreadingTest(ThreadingTest):
1634 decimal = P
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001635
Stefan Krah1919b7e2012-03-21 18:25:23 +01001636class UsabilityTest(unittest.TestCase):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001637 '''Unit tests for Usability cases of Decimal.'''
1638
1639 def test_comparison_operators(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001640
Stefan Krah1919b7e2012-03-21 18:25:23 +01001641 Decimal = self.decimal.Decimal
1642
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001643 da = Decimal('23.42')
1644 db = Decimal('23.42')
1645 dc = Decimal('45')
1646
1647 #two Decimals
Ezio Melotti6607d512010-04-03 14:59:49 +00001648 self.assertGreater(dc, da)
1649 self.assertGreaterEqual(dc, da)
1650 self.assertLess(da, dc)
1651 self.assertLessEqual(da, dc)
Guido van Rossume61fd5b2007-07-11 12:20:59 +00001652 self.assertEqual(da, db)
Ezio Melotti6607d512010-04-03 14:59:49 +00001653 self.assertNotEqual(da, dc)
1654 self.assertLessEqual(da, db)
1655 self.assertGreaterEqual(da, db)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001656
1657 #a Decimal and an int
Ezio Melotti6607d512010-04-03 14:59:49 +00001658 self.assertGreater(dc, 23)
1659 self.assertLess(23, dc)
Guido van Rossume61fd5b2007-07-11 12:20:59 +00001660 self.assertEqual(dc, 45)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001661
1662 #a Decimal and uncomparable
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001663 self.assertNotEqual(da, 'ugly')
1664 self.assertNotEqual(da, 32.7)
1665 self.assertNotEqual(da, object())
1666 self.assertNotEqual(da, object)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001667
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001668 # sortable
Guido van Rossumc1f779c2007-07-03 08:25:58 +00001669 a = list(map(Decimal, range(100)))
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001670 b = a[:]
1671 random.shuffle(a)
1672 a.sort()
1673 self.assertEqual(a, b)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001674
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001675 def test_decimal_float_comparison(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001676 Decimal = self.decimal.Decimal
1677
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001678 da = Decimal('0.25')
1679 db = Decimal('3.0')
Ezio Melotti6607d512010-04-03 14:59:49 +00001680 self.assertLess(da, 3.0)
1681 self.assertLessEqual(da, 3.0)
1682 self.assertGreater(db, 0.25)
1683 self.assertGreaterEqual(db, 0.25)
1684 self.assertNotEqual(da, 1.5)
1685 self.assertEqual(da, 0.25)
1686 self.assertGreater(3.0, da)
1687 self.assertGreaterEqual(3.0, da)
1688 self.assertLess(0.25, db)
1689 self.assertLessEqual(0.25, db)
1690 self.assertNotEqual(0.25, db)
1691 self.assertEqual(3.0, db)
1692 self.assertNotEqual(0.1, Decimal('0.1'))
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001693
Stefan Krah1919b7e2012-03-21 18:25:23 +01001694 def test_decimal_complex_comparison(self):
1695 Decimal = self.decimal.Decimal
1696
1697 da = Decimal('0.25')
1698 db = Decimal('3.0')
1699 self.assertNotEqual(da, (1.5+0j))
1700 self.assertNotEqual((1.5+0j), da)
1701 self.assertEqual(da, (0.25+0j))
1702 self.assertEqual((0.25+0j), da)
1703 self.assertEqual((3.0+0j), db)
1704 self.assertEqual(db, (3.0+0j))
1705
1706 self.assertNotEqual(db, (3.0+1j))
1707 self.assertNotEqual((3.0+1j), db)
1708
1709 self.assertIs(db.__lt__(3.0+0j), NotImplemented)
1710 self.assertIs(db.__le__(3.0+0j), NotImplemented)
1711 self.assertIs(db.__gt__(3.0+0j), NotImplemented)
1712 self.assertIs(db.__le__(3.0+0j), NotImplemented)
1713
1714 def test_decimal_fraction_comparison(self):
1715 D = self.decimal.Decimal
1716 F = fractions[self.decimal].Fraction
1717 Context = self.decimal.Context
1718 localcontext = self.decimal.localcontext
1719 InvalidOperation = self.decimal.InvalidOperation
1720
1721
1722 emax = C.MAX_EMAX if C else 999999999
1723 emin = C.MIN_EMIN if C else -999999999
1724 etiny = C.MIN_ETINY if C else -1999999997
1725 c = Context(Emax=emax, Emin=emin)
1726
1727 with localcontext(c):
1728 c.prec = emax
1729 self.assertLess(D(0), F(1,9999999999999999999999999999999999999))
1730 self.assertLess(F(-1,9999999999999999999999999999999999999), D(0))
1731 self.assertLess(F(0,1), D("1e" + str(etiny)))
1732 self.assertLess(D("-1e" + str(etiny)), F(0,1))
1733 self.assertLess(F(0,9999999999999999999999999), D("1e" + str(etiny)))
1734 self.assertLess(D("-1e" + str(etiny)), F(0,9999999999999999999999999))
1735
1736 self.assertEqual(D("0.1"), F(1,10))
1737 self.assertEqual(F(1,10), D("0.1"))
1738
1739 c.prec = 300
1740 self.assertNotEqual(D(1)/3, F(1,3))
1741 self.assertNotEqual(F(1,3), D(1)/3)
1742
1743 self.assertLessEqual(F(120984237, 9999999999), D("9e" + str(emax)))
1744 self.assertGreaterEqual(D("9e" + str(emax)), F(120984237, 9999999999))
1745
1746 self.assertGreater(D('inf'), F(99999999999,123))
1747 self.assertGreater(D('inf'), F(-99999999999,123))
1748 self.assertLess(D('-inf'), F(99999999999,123))
1749 self.assertLess(D('-inf'), F(-99999999999,123))
1750
1751 self.assertRaises(InvalidOperation, D('nan').__gt__, F(-9,123))
1752 self.assertIs(NotImplemented, F(-9,123).__lt__(D('nan')))
1753 self.assertNotEqual(D('nan'), F(-9,123))
1754 self.assertNotEqual(F(-9,123), D('nan'))
1755
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001756 def test_copy_and_deepcopy_methods(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001757 Decimal = self.decimal.Decimal
1758
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001759 d = Decimal('43.24')
1760 c = copy.copy(d)
1761 self.assertEqual(id(c), id(d))
1762 dc = copy.deepcopy(d)
1763 self.assertEqual(id(dc), id(d))
1764
1765 def test_hash_method(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001766
1767 Decimal = self.decimal.Decimal
1768 localcontext = self.decimal.localcontext
1769
Stefan Krahdc817b22010-11-17 11:16:34 +00001770 def hashit(d):
1771 a = hash(d)
1772 b = d.__hash__()
1773 self.assertEqual(a, b)
1774 return a
1775
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001776 #just that it's hashable
Stefan Krahdc817b22010-11-17 11:16:34 +00001777 hashit(Decimal(23))
1778 hashit(Decimal('Infinity'))
1779 hashit(Decimal('-Infinity'))
1780 hashit(Decimal('nan123'))
1781 hashit(Decimal('-NaN'))
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001782
1783 test_values = [Decimal(sign*(2**m + n))
1784 for m in [0, 14, 15, 16, 17, 30, 31,
Stefan Krahdc817b22010-11-17 11:16:34 +00001785 32, 33, 61, 62, 63, 64, 65, 66]
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001786 for n in range(-10, 10)
1787 for sign in [-1, 1]]
1788 test_values.extend([
Stefan Krahdc817b22010-11-17 11:16:34 +00001789 Decimal("-1"), # ==> -2
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001790 Decimal("-0"), # zeros
1791 Decimal("0.00"),
1792 Decimal("-0.000"),
1793 Decimal("0E10"),
1794 Decimal("-0E12"),
1795 Decimal("10.0"), # negative exponent
1796 Decimal("-23.00000"),
1797 Decimal("1230E100"), # positive exponent
1798 Decimal("-4.5678E50"),
1799 # a value for which hash(n) != hash(n % (2**64-1))
1800 # in Python pre-2.6
1801 Decimal(2**64 + 2**32 - 1),
1802 # selection of values which fail with the old (before
1803 # version 2.6) long.__hash__
1804 Decimal("1.634E100"),
1805 Decimal("90.697E100"),
1806 Decimal("188.83E100"),
1807 Decimal("1652.9E100"),
1808 Decimal("56531E100"),
1809 ])
1810
1811 # check that hash(d) == hash(int(d)) for integral values
1812 for value in test_values:
Stefan Krahdc817b22010-11-17 11:16:34 +00001813 self.assertEqual(hashit(value), hashit(int(value)))
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001814
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001815 #the same hash that to an int
Stefan Krahdc817b22010-11-17 11:16:34 +00001816 self.assertEqual(hashit(Decimal(23)), hashit(23))
Raymond Hettingerd325c4b2010-11-21 04:08:28 +00001817 self.assertRaises(TypeError, hash, Decimal('sNaN'))
Stefan Krahdc817b22010-11-17 11:16:34 +00001818 self.assertTrue(hashit(Decimal('Inf')))
1819 self.assertTrue(hashit(Decimal('-Inf')))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001820
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001821 # check that the hashes of a Decimal float match when they
1822 # represent exactly the same values
1823 test_strings = ['inf', '-Inf', '0.0', '-.0e1',
1824 '34.0', '2.5', '112390.625', '-0.515625']
1825 for s in test_strings:
1826 f = float(s)
1827 d = Decimal(s)
Stefan Krahdc817b22010-11-17 11:16:34 +00001828 self.assertEqual(hashit(f), hashit(d))
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001829
Stefan Krah1919b7e2012-03-21 18:25:23 +01001830 with localcontext() as c:
1831 # check that the value of the hash doesn't depend on the
1832 # current context (issue #1757)
1833 x = Decimal("123456789.1")
Christian Heimes2380ac72008-01-09 00:17:24 +00001834
Stefan Krah1919b7e2012-03-21 18:25:23 +01001835 c.prec = 6
1836 h1 = hashit(x)
1837 c.prec = 10
1838 h2 = hashit(x)
1839 c.prec = 16
1840 h3 = hashit(x)
Christian Heimes2380ac72008-01-09 00:17:24 +00001841
Stefan Krah1919b7e2012-03-21 18:25:23 +01001842 self.assertEqual(h1, h2)
1843 self.assertEqual(h1, h3)
1844
1845 c.prec = 10000
1846 x = 1100 ** 1248
1847 self.assertEqual(hashit(Decimal(x)), hashit(x))
Christian Heimes2380ac72008-01-09 00:17:24 +00001848
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001849 def test_min_and_max_methods(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001850 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001851
1852 d1 = Decimal('15.32')
1853 d2 = Decimal('28.5')
1854 l1 = 15
1855 l2 = 28
1856
1857 #between Decimals
Ezio Melotti6607d512010-04-03 14:59:49 +00001858 self.assertIs(min(d1,d2), d1)
1859 self.assertIs(min(d2,d1), d1)
1860 self.assertIs(max(d1,d2), d2)
1861 self.assertIs(max(d2,d1), d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001862
Serhiy Storchaka95949422013-08-27 19:40:23 +03001863 #between Decimal and int
Ezio Melotti6607d512010-04-03 14:59:49 +00001864 self.assertIs(min(d1,l2), d1)
1865 self.assertIs(min(l2,d1), d1)
1866 self.assertIs(max(l1,d2), d2)
1867 self.assertIs(max(d2,l1), d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001868
1869 def test_as_nonzero(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001870 Decimal = self.decimal.Decimal
1871
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001872 #as false
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001873 self.assertFalse(Decimal(0))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001874 #as true
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001875 self.assertTrue(Decimal('0.372'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001876
1877 def test_tostring_methods(self):
1878 #Test str and repr methods.
Stefan Krah1919b7e2012-03-21 18:25:23 +01001879 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001880
1881 d = Decimal('15.32')
1882 self.assertEqual(str(d), '15.32') # str
Christian Heimes68f5fbe2008-02-14 08:27:37 +00001883 self.assertEqual(repr(d), "Decimal('15.32')") # repr
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001884
1885 def test_tonum_methods(self):
Mark Dickinson5c2db372009-12-05 20:28:34 +00001886 #Test float and int methods.
Stefan Krah1919b7e2012-03-21 18:25:23 +01001887 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001888
1889 d1 = Decimal('66')
1890 d2 = Decimal('15.32')
1891
1892 #int
1893 self.assertEqual(int(d1), 66)
1894 self.assertEqual(int(d2), 15)
1895
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001896 #float
1897 self.assertEqual(float(d1), 66)
1898 self.assertEqual(float(d2), 15.32)
1899
Mark Dickinsonb27406c2008-05-09 13:42:33 +00001900 #floor
1901 test_pairs = [
1902 ('123.00', 123),
1903 ('3.2', 3),
1904 ('3.54', 3),
1905 ('3.899', 3),
1906 ('-2.3', -3),
1907 ('-11.0', -11),
1908 ('0.0', 0),
1909 ('-0E3', 0),
Stefan Krah1919b7e2012-03-21 18:25:23 +01001910 ('89891211712379812736.1', 89891211712379812736),
Mark Dickinsonb27406c2008-05-09 13:42:33 +00001911 ]
1912 for d, i in test_pairs:
1913 self.assertEqual(math.floor(Decimal(d)), i)
1914 self.assertRaises(ValueError, math.floor, Decimal('-NaN'))
1915 self.assertRaises(ValueError, math.floor, Decimal('sNaN'))
1916 self.assertRaises(ValueError, math.floor, Decimal('NaN123'))
1917 self.assertRaises(OverflowError, math.floor, Decimal('Inf'))
1918 self.assertRaises(OverflowError, math.floor, Decimal('-Inf'))
1919
1920 #ceiling
1921 test_pairs = [
1922 ('123.00', 123),
1923 ('3.2', 4),
1924 ('3.54', 4),
1925 ('3.899', 4),
1926 ('-2.3', -2),
1927 ('-11.0', -11),
1928 ('0.0', 0),
1929 ('-0E3', 0),
Stefan Krah1919b7e2012-03-21 18:25:23 +01001930 ('89891211712379812736.1', 89891211712379812737),
Mark Dickinsonb27406c2008-05-09 13:42:33 +00001931 ]
1932 for d, i in test_pairs:
1933 self.assertEqual(math.ceil(Decimal(d)), i)
1934 self.assertRaises(ValueError, math.ceil, Decimal('-NaN'))
1935 self.assertRaises(ValueError, math.ceil, Decimal('sNaN'))
1936 self.assertRaises(ValueError, math.ceil, Decimal('NaN123'))
1937 self.assertRaises(OverflowError, math.ceil, Decimal('Inf'))
1938 self.assertRaises(OverflowError, math.ceil, Decimal('-Inf'))
1939
1940 #round, single argument
1941 test_pairs = [
1942 ('123.00', 123),
1943 ('3.2', 3),
1944 ('3.54', 4),
1945 ('3.899', 4),
1946 ('-2.3', -2),
1947 ('-11.0', -11),
1948 ('0.0', 0),
1949 ('-0E3', 0),
1950 ('-3.5', -4),
1951 ('-2.5', -2),
1952 ('-1.5', -2),
1953 ('-0.5', 0),
1954 ('0.5', 0),
1955 ('1.5', 2),
1956 ('2.5', 2),
1957 ('3.5', 4),
1958 ]
1959 for d, i in test_pairs:
1960 self.assertEqual(round(Decimal(d)), i)
1961 self.assertRaises(ValueError, round, Decimal('-NaN'))
1962 self.assertRaises(ValueError, round, Decimal('sNaN'))
1963 self.assertRaises(ValueError, round, Decimal('NaN123'))
1964 self.assertRaises(OverflowError, round, Decimal('Inf'))
1965 self.assertRaises(OverflowError, round, Decimal('-Inf'))
1966
1967 #round, two arguments; this is essentially equivalent
1968 #to quantize, which is already extensively tested
1969 test_triples = [
1970 ('123.456', -4, '0E+4'),
1971 ('123.456', -3, '0E+3'),
1972 ('123.456', -2, '1E+2'),
1973 ('123.456', -1, '1.2E+2'),
1974 ('123.456', 0, '123'),
1975 ('123.456', 1, '123.5'),
1976 ('123.456', 2, '123.46'),
1977 ('123.456', 3, '123.456'),
1978 ('123.456', 4, '123.4560'),
1979 ('123.455', 2, '123.46'),
1980 ('123.445', 2, '123.44'),
1981 ('Inf', 4, 'NaN'),
1982 ('-Inf', -23, 'NaN'),
1983 ('sNaN314', 3, 'NaN314'),
1984 ]
1985 for d, n, r in test_triples:
1986 self.assertEqual(str(round(Decimal(d), n)), r)
1987
Mark Dickinsonfc33d4c2012-08-24 18:53:10 +01001988 def test_nan_to_float(self):
1989 # Test conversions of decimal NANs to float.
1990 # See http://bugs.python.org/issue15544
1991 Decimal = self.decimal.Decimal
1992 for s in ('nan', 'nan1234', '-nan', '-nan2468'):
1993 f = float(Decimal(s))
1994 self.assertTrue(math.isnan(f))
1995 sign = math.copysign(1.0, f)
1996 self.assertEqual(sign, -1.0 if s.startswith('-') else 1.0)
1997
1998 def test_snan_to_float(self):
1999 Decimal = self.decimal.Decimal
2000 for s in ('snan', '-snan', 'snan1357', '-snan1234'):
2001 d = Decimal(s)
2002 self.assertRaises(ValueError, float, d)
2003
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002004 def test_eval_round_trip(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01002005 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002006
2007 #with zero
2008 d = Decimal( (0, (0,), 0) )
2009 self.assertEqual(d, eval(repr(d)))
2010
2011 #int
2012 d = Decimal( (1, (4, 5), 0) )
2013 self.assertEqual(d, eval(repr(d)))
2014
2015 #float
2016 d = Decimal( (0, (4, 5, 3, 4), -2) )
2017 self.assertEqual(d, eval(repr(d)))
2018
2019 #weird
2020 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
2021 self.assertEqual(d, eval(repr(d)))
2022
2023 def test_as_tuple(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01002024 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002025
2026 #with zero
2027 d = Decimal(0)
2028 self.assertEqual(d.as_tuple(), (0, (0,), 0) )
2029
2030 #int
2031 d = Decimal(-45)
2032 self.assertEqual(d.as_tuple(), (1, (4, 5), 0) )
2033
2034 #complicated string
2035 d = Decimal("-4.34913534E-17")
2036 self.assertEqual(d.as_tuple(), (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
2037
Stefan Krah76e12172012-09-10 19:34:58 +02002038 # The '0' coefficient is implementation specific to decimal.py.
2039 # It has no meaning in the C-version and is ignored there.
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002040 d = Decimal("Infinity")
2041 self.assertEqual(d.as_tuple(), (0, (0,), 'F') )
2042
Guido van Rossum8ce8a782007-11-01 19:42:39 +00002043 #leading zeros in coefficient should be stripped
2044 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), -2) )
2045 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), -2) )
2046 d = Decimal( (1, (0, 0, 0), 37) )
2047 self.assertEqual(d.as_tuple(), (1, (0,), 37))
2048 d = Decimal( (1, (), 37) )
2049 self.assertEqual(d.as_tuple(), (1, (0,), 37))
2050
2051 #leading zeros in NaN diagnostic info should be stripped
2052 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), 'n') )
2053 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), 'n') )
2054 d = Decimal( (1, (0, 0, 0), 'N') )
2055 self.assertEqual(d.as_tuple(), (1, (), 'N') )
2056 d = Decimal( (1, (), 'n') )
2057 self.assertEqual(d.as_tuple(), (1, (), 'n') )
2058
Stefan Krah76e12172012-09-10 19:34:58 +02002059 # For infinities, decimal.py has always silently accepted any
2060 # coefficient tuple.
2061 d = Decimal( (0, (0,), 'F') )
2062 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
2063 d = Decimal( (0, (4, 5, 3, 4), 'F') )
2064 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
2065 d = Decimal( (1, (0, 2, 7, 1), 'F') )
2066 self.assertEqual(d.as_tuple(), (1, (0,), 'F'))
Guido van Rossum8ce8a782007-11-01 19:42:39 +00002067
Stefan Krah53f2e0a2015-12-28 23:02:02 +01002068 def test_as_integer_ratio(self):
2069 Decimal = self.decimal.Decimal
2070
2071 # exceptional cases
2072 self.assertRaises(OverflowError,
2073 Decimal.as_integer_ratio, Decimal('inf'))
2074 self.assertRaises(OverflowError,
2075 Decimal.as_integer_ratio, Decimal('-inf'))
2076 self.assertRaises(ValueError,
2077 Decimal.as_integer_ratio, Decimal('-nan'))
2078 self.assertRaises(ValueError,
2079 Decimal.as_integer_ratio, Decimal('snan123'))
2080
2081 for exp in range(-4, 2):
2082 for coeff in range(1000):
2083 for sign in '+', '-':
2084 d = Decimal('%s%dE%d' % (sign, coeff, exp))
2085 pq = d.as_integer_ratio()
2086 p, q = pq
2087
2088 # check return type
2089 self.assertIsInstance(pq, tuple)
2090 self.assertIsInstance(p, int)
2091 self.assertIsInstance(q, int)
2092
2093 # check normalization: q should be positive;
2094 # p should be relatively prime to q.
2095 self.assertGreater(q, 0)
2096 self.assertEqual(math.gcd(p, q), 1)
2097
2098 # check that p/q actually gives the correct value
2099 self.assertEqual(Decimal(p) / Decimal(q), d)
2100
Stefan Krah1919b7e2012-03-21 18:25:23 +01002101 def test_subclassing(self):
2102 # Different behaviours when subclassing Decimal
2103 Decimal = self.decimal.Decimal
2104
2105 class MyDecimal(Decimal):
Stefan Krah0f82b762012-11-08 11:17:29 +01002106 y = None
Stefan Krah1919b7e2012-03-21 18:25:23 +01002107
2108 d1 = MyDecimal(1)
2109 d2 = MyDecimal(2)
2110 d = d1 + d2
2111 self.assertIs(type(d), Decimal)
2112
2113 d = d1.max(d2)
2114 self.assertIs(type(d), Decimal)
2115
2116 d = copy.copy(d1)
2117 self.assertIs(type(d), MyDecimal)
2118 self.assertEqual(d, d1)
2119
2120 d = copy.deepcopy(d1)
2121 self.assertIs(type(d), MyDecimal)
2122 self.assertEqual(d, d1)
2123
Stefan Krah0f82b762012-11-08 11:17:29 +01002124 # Decimal(Decimal)
2125 d = Decimal('1.0')
2126 x = Decimal(d)
2127 self.assertIs(type(x), Decimal)
2128 self.assertEqual(x, d)
Stefan Krahf4abc7b2012-11-07 23:12:25 +01002129
Stefan Krah0f82b762012-11-08 11:17:29 +01002130 # MyDecimal(Decimal)
2131 m = MyDecimal(d)
2132 self.assertIs(type(m), MyDecimal)
2133 self.assertEqual(m, d)
2134 self.assertIs(m.y, None)
2135
2136 # Decimal(MyDecimal)
2137 x = Decimal(m)
2138 self.assertIs(type(x), Decimal)
2139 self.assertEqual(x, d)
2140
2141 # MyDecimal(MyDecimal)
2142 m.y = 9
2143 x = MyDecimal(m)
2144 self.assertIs(type(x), MyDecimal)
2145 self.assertEqual(x, d)
2146 self.assertIs(x.y, None)
Stefan Krahed16eff2012-11-07 23:47:19 +01002147
Stefan Krah1919b7e2012-03-21 18:25:23 +01002148 def test_implicit_context(self):
2149 Decimal = self.decimal.Decimal
2150 getcontext = self.decimal.getcontext
2151
2152 # Check results when context given implicitly. (Issue 2478)
2153 c = getcontext()
2154 self.assertEqual(str(Decimal(0).sqrt()),
2155 str(c.sqrt(Decimal(0))))
2156
Stefan Krah040e3112012-12-15 22:33:33 +01002157 def test_none_args(self):
2158 Decimal = self.decimal.Decimal
2159 Context = self.decimal.Context
2160 localcontext = self.decimal.localcontext
2161 InvalidOperation = self.decimal.InvalidOperation
2162 DivisionByZero = self.decimal.DivisionByZero
2163 Overflow = self.decimal.Overflow
2164 Underflow = self.decimal.Underflow
2165 Subnormal = self.decimal.Subnormal
2166 Inexact = self.decimal.Inexact
2167 Rounded = self.decimal.Rounded
2168 Clamped = self.decimal.Clamped
Stefan Krah040e3112012-12-15 22:33:33 +01002169
2170 with localcontext(Context()) as c:
2171 c.prec = 7
2172 c.Emax = 999
2173 c.Emin = -999
2174
2175 x = Decimal("111")
2176 y = Decimal("1e9999")
2177 z = Decimal("1e-9999")
2178
2179 ##### Unary functions
2180 c.clear_flags()
2181 self.assertEqual(str(x.exp(context=None)), '1.609487E+48')
2182 self.assertTrue(c.flags[Inexact])
2183 self.assertTrue(c.flags[Rounded])
2184 c.clear_flags()
2185 self.assertRaises(Overflow, y.exp, context=None)
2186 self.assertTrue(c.flags[Overflow])
2187
2188 self.assertIs(z.is_normal(context=None), False)
2189 self.assertIs(z.is_subnormal(context=None), True)
2190
2191 c.clear_flags()
2192 self.assertEqual(str(x.ln(context=None)), '4.709530')
2193 self.assertTrue(c.flags[Inexact])
2194 self.assertTrue(c.flags[Rounded])
2195 c.clear_flags()
2196 self.assertRaises(InvalidOperation, Decimal(-1).ln, context=None)
2197 self.assertTrue(c.flags[InvalidOperation])
2198
2199 c.clear_flags()
2200 self.assertEqual(str(x.log10(context=None)), '2.045323')
2201 self.assertTrue(c.flags[Inexact])
2202 self.assertTrue(c.flags[Rounded])
2203 c.clear_flags()
2204 self.assertRaises(InvalidOperation, Decimal(-1).log10, context=None)
2205 self.assertTrue(c.flags[InvalidOperation])
2206
2207 c.clear_flags()
2208 self.assertEqual(str(x.logb(context=None)), '2')
2209 self.assertRaises(DivisionByZero, Decimal(0).logb, context=None)
2210 self.assertTrue(c.flags[DivisionByZero])
2211
2212 c.clear_flags()
2213 self.assertEqual(str(x.logical_invert(context=None)), '1111000')
2214 self.assertRaises(InvalidOperation, y.logical_invert, context=None)
2215 self.assertTrue(c.flags[InvalidOperation])
2216
2217 c.clear_flags()
2218 self.assertEqual(str(y.next_minus(context=None)), '9.999999E+999')
2219 self.assertRaises(InvalidOperation, Decimal('sNaN').next_minus, context=None)
2220 self.assertTrue(c.flags[InvalidOperation])
2221
2222 c.clear_flags()
2223 self.assertEqual(str(y.next_plus(context=None)), 'Infinity')
2224 self.assertRaises(InvalidOperation, Decimal('sNaN').next_plus, context=None)
2225 self.assertTrue(c.flags[InvalidOperation])
2226
2227 c.clear_flags()
2228 self.assertEqual(str(z.normalize(context=None)), '0')
2229 self.assertRaises(Overflow, y.normalize, context=None)
2230 self.assertTrue(c.flags[Overflow])
2231
2232 self.assertEqual(str(z.number_class(context=None)), '+Subnormal')
2233
2234 c.clear_flags()
2235 self.assertEqual(str(z.sqrt(context=None)), '0E-1005')
2236 self.assertTrue(c.flags[Clamped])
2237 self.assertTrue(c.flags[Inexact])
2238 self.assertTrue(c.flags[Rounded])
2239 self.assertTrue(c.flags[Subnormal])
2240 self.assertTrue(c.flags[Underflow])
2241 c.clear_flags()
2242 self.assertRaises(Overflow, y.sqrt, context=None)
2243 self.assertTrue(c.flags[Overflow])
2244
2245 c.capitals = 0
2246 self.assertEqual(str(z.to_eng_string(context=None)), '1e-9999')
2247 c.capitals = 1
2248
2249
2250 ##### Binary functions
2251 c.clear_flags()
2252 ans = str(x.compare(Decimal('Nan891287828'), context=None))
2253 self.assertEqual(ans, 'NaN1287828')
2254 self.assertRaises(InvalidOperation, x.compare, Decimal('sNaN'), context=None)
2255 self.assertTrue(c.flags[InvalidOperation])
2256
2257 c.clear_flags()
2258 ans = str(x.compare_signal(8224, context=None))
2259 self.assertEqual(ans, '-1')
2260 self.assertRaises(InvalidOperation, x.compare_signal, Decimal('NaN'), context=None)
2261 self.assertTrue(c.flags[InvalidOperation])
2262
2263 c.clear_flags()
2264 ans = str(x.logical_and(101, context=None))
2265 self.assertEqual(ans, '101')
2266 self.assertRaises(InvalidOperation, x.logical_and, 123, context=None)
2267 self.assertTrue(c.flags[InvalidOperation])
2268
2269 c.clear_flags()
2270 ans = str(x.logical_or(101, context=None))
2271 self.assertEqual(ans, '111')
2272 self.assertRaises(InvalidOperation, x.logical_or, 123, context=None)
2273 self.assertTrue(c.flags[InvalidOperation])
2274
2275 c.clear_flags()
2276 ans = str(x.logical_xor(101, context=None))
2277 self.assertEqual(ans, '10')
2278 self.assertRaises(InvalidOperation, x.logical_xor, 123, context=None)
2279 self.assertTrue(c.flags[InvalidOperation])
2280
2281 c.clear_flags()
2282 ans = str(x.max(101, context=None))
2283 self.assertEqual(ans, '111')
2284 self.assertRaises(InvalidOperation, x.max, Decimal('sNaN'), context=None)
2285 self.assertTrue(c.flags[InvalidOperation])
2286
2287 c.clear_flags()
2288 ans = str(x.max_mag(101, context=None))
2289 self.assertEqual(ans, '111')
2290 self.assertRaises(InvalidOperation, x.max_mag, Decimal('sNaN'), context=None)
2291 self.assertTrue(c.flags[InvalidOperation])
2292
2293 c.clear_flags()
2294 ans = str(x.min(101, context=None))
2295 self.assertEqual(ans, '101')
2296 self.assertRaises(InvalidOperation, x.min, Decimal('sNaN'), context=None)
2297 self.assertTrue(c.flags[InvalidOperation])
2298
2299 c.clear_flags()
2300 ans = str(x.min_mag(101, context=None))
2301 self.assertEqual(ans, '101')
2302 self.assertRaises(InvalidOperation, x.min_mag, Decimal('sNaN'), context=None)
2303 self.assertTrue(c.flags[InvalidOperation])
2304
2305 c.clear_flags()
2306 ans = str(x.remainder_near(101, context=None))
2307 self.assertEqual(ans, '10')
2308 self.assertRaises(InvalidOperation, y.remainder_near, 101, context=None)
2309 self.assertTrue(c.flags[InvalidOperation])
2310
2311 c.clear_flags()
2312 ans = str(x.rotate(2, context=None))
2313 self.assertEqual(ans, '11100')
2314 self.assertRaises(InvalidOperation, x.rotate, 101, context=None)
2315 self.assertTrue(c.flags[InvalidOperation])
2316
2317 c.clear_flags()
2318 ans = str(x.scaleb(7, context=None))
2319 self.assertEqual(ans, '1.11E+9')
2320 self.assertRaises(InvalidOperation, x.scaleb, 10000, context=None)
2321 self.assertTrue(c.flags[InvalidOperation])
2322
2323 c.clear_flags()
2324 ans = str(x.shift(2, context=None))
2325 self.assertEqual(ans, '11100')
2326 self.assertRaises(InvalidOperation, x.shift, 10000, context=None)
2327 self.assertTrue(c.flags[InvalidOperation])
2328
2329
2330 ##### Ternary functions
2331 c.clear_flags()
2332 ans = str(x.fma(2, 3, context=None))
2333 self.assertEqual(ans, '225')
2334 self.assertRaises(Overflow, x.fma, Decimal('1e9999'), 3, context=None)
2335 self.assertTrue(c.flags[Overflow])
2336
2337
2338 ##### Special cases
2339 c.rounding = ROUND_HALF_EVEN
2340 ans = str(Decimal('1.5').to_integral(rounding=None, context=None))
2341 self.assertEqual(ans, '2')
2342 c.rounding = ROUND_DOWN
2343 ans = str(Decimal('1.5').to_integral(rounding=None, context=None))
2344 self.assertEqual(ans, '1')
2345 ans = str(Decimal('1.5').to_integral(rounding=ROUND_UP, context=None))
2346 self.assertEqual(ans, '2')
2347 c.clear_flags()
2348 self.assertRaises(InvalidOperation, Decimal('sNaN').to_integral, context=None)
2349 self.assertTrue(c.flags[InvalidOperation])
2350
2351 c.rounding = ROUND_HALF_EVEN
2352 ans = str(Decimal('1.5').to_integral_value(rounding=None, context=None))
2353 self.assertEqual(ans, '2')
2354 c.rounding = ROUND_DOWN
2355 ans = str(Decimal('1.5').to_integral_value(rounding=None, context=None))
2356 self.assertEqual(ans, '1')
2357 ans = str(Decimal('1.5').to_integral_value(rounding=ROUND_UP, context=None))
2358 self.assertEqual(ans, '2')
2359 c.clear_flags()
2360 self.assertRaises(InvalidOperation, Decimal('sNaN').to_integral_value, context=None)
2361 self.assertTrue(c.flags[InvalidOperation])
2362
2363 c.rounding = ROUND_HALF_EVEN
2364 ans = str(Decimal('1.5').to_integral_exact(rounding=None, context=None))
2365 self.assertEqual(ans, '2')
2366 c.rounding = ROUND_DOWN
2367 ans = str(Decimal('1.5').to_integral_exact(rounding=None, context=None))
2368 self.assertEqual(ans, '1')
2369 ans = str(Decimal('1.5').to_integral_exact(rounding=ROUND_UP, context=None))
2370 self.assertEqual(ans, '2')
2371 c.clear_flags()
2372 self.assertRaises(InvalidOperation, Decimal('sNaN').to_integral_exact, context=None)
2373 self.assertTrue(c.flags[InvalidOperation])
2374
2375 c.rounding = ROUND_UP
2376 ans = str(Decimal('1.50001').quantize(exp=Decimal('1e-3'), rounding=None, context=None))
2377 self.assertEqual(ans, '1.501')
2378 c.rounding = ROUND_DOWN
2379 ans = str(Decimal('1.50001').quantize(exp=Decimal('1e-3'), rounding=None, context=None))
2380 self.assertEqual(ans, '1.500')
2381 ans = str(Decimal('1.50001').quantize(exp=Decimal('1e-3'), rounding=ROUND_UP, context=None))
2382 self.assertEqual(ans, '1.501')
2383 c.clear_flags()
2384 self.assertRaises(InvalidOperation, y.quantize, Decimal('1e-10'), rounding=ROUND_UP, context=None)
2385 self.assertTrue(c.flags[InvalidOperation])
2386
2387 with localcontext(Context()) as context:
2388 context.prec = 7
2389 context.Emax = 999
2390 context.Emin = -999
2391 with localcontext(ctx=None) as c:
2392 self.assertEqual(c.prec, 7)
2393 self.assertEqual(c.Emax, 999)
2394 self.assertEqual(c.Emin, -999)
2395
Stefan Krah1919b7e2012-03-21 18:25:23 +01002396 def test_conversions_from_int(self):
2397 # Check that methods taking a second Decimal argument will
2398 # always accept an integer in place of a Decimal.
2399 Decimal = self.decimal.Decimal
2400
2401 self.assertEqual(Decimal(4).compare(3),
2402 Decimal(4).compare(Decimal(3)))
2403 self.assertEqual(Decimal(4).compare_signal(3),
2404 Decimal(4).compare_signal(Decimal(3)))
2405 self.assertEqual(Decimal(4).compare_total(3),
2406 Decimal(4).compare_total(Decimal(3)))
2407 self.assertEqual(Decimal(4).compare_total_mag(3),
2408 Decimal(4).compare_total_mag(Decimal(3)))
2409 self.assertEqual(Decimal(10101).logical_and(1001),
2410 Decimal(10101).logical_and(Decimal(1001)))
2411 self.assertEqual(Decimal(10101).logical_or(1001),
2412 Decimal(10101).logical_or(Decimal(1001)))
2413 self.assertEqual(Decimal(10101).logical_xor(1001),
2414 Decimal(10101).logical_xor(Decimal(1001)))
2415 self.assertEqual(Decimal(567).max(123),
2416 Decimal(567).max(Decimal(123)))
2417 self.assertEqual(Decimal(567).max_mag(123),
2418 Decimal(567).max_mag(Decimal(123)))
2419 self.assertEqual(Decimal(567).min(123),
2420 Decimal(567).min(Decimal(123)))
2421 self.assertEqual(Decimal(567).min_mag(123),
2422 Decimal(567).min_mag(Decimal(123)))
2423 self.assertEqual(Decimal(567).next_toward(123),
2424 Decimal(567).next_toward(Decimal(123)))
2425 self.assertEqual(Decimal(1234).quantize(100),
2426 Decimal(1234).quantize(Decimal(100)))
2427 self.assertEqual(Decimal(768).remainder_near(1234),
2428 Decimal(768).remainder_near(Decimal(1234)))
2429 self.assertEqual(Decimal(123).rotate(1),
2430 Decimal(123).rotate(Decimal(1)))
2431 self.assertEqual(Decimal(1234).same_quantum(1000),
2432 Decimal(1234).same_quantum(Decimal(1000)))
2433 self.assertEqual(Decimal('9.123').scaleb(-100),
2434 Decimal('9.123').scaleb(Decimal(-100)))
2435 self.assertEqual(Decimal(456).shift(-1),
2436 Decimal(456).shift(Decimal(-1)))
2437
2438 self.assertEqual(Decimal(-12).fma(Decimal(45), 67),
2439 Decimal(-12).fma(Decimal(45), Decimal(67)))
2440 self.assertEqual(Decimal(-12).fma(45, 67),
2441 Decimal(-12).fma(Decimal(45), Decimal(67)))
2442 self.assertEqual(Decimal(-12).fma(45, Decimal(67)),
2443 Decimal(-12).fma(Decimal(45), Decimal(67)))
2444
2445class CUsabilityTest(UsabilityTest):
2446 decimal = C
2447class PyUsabilityTest(UsabilityTest):
2448 decimal = P
2449
2450class PythonAPItests(unittest.TestCase):
2451
2452 def test_abc(self):
2453 Decimal = self.decimal.Decimal
2454
2455 self.assertTrue(issubclass(Decimal, numbers.Number))
2456 self.assertFalse(issubclass(Decimal, numbers.Real))
2457 self.assertIsInstance(Decimal(0), numbers.Number)
2458 self.assertNotIsInstance(Decimal(0), numbers.Real)
2459
2460 def test_pickle(self):
Serhiy Storchakabad12572014-12-15 14:03:42 +02002461 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
2462 Decimal = self.decimal.Decimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01002463
Serhiy Storchakabad12572014-12-15 14:03:42 +02002464 savedecimal = sys.modules['decimal']
Stefan Krah1919b7e2012-03-21 18:25:23 +01002465
Serhiy Storchakabad12572014-12-15 14:03:42 +02002466 # Round trip
2467 sys.modules['decimal'] = self.decimal
2468 d = Decimal('-3.141590000')
2469 p = pickle.dumps(d, proto)
2470 e = pickle.loads(p)
2471 self.assertEqual(d, e)
Stefan Krah1919b7e2012-03-21 18:25:23 +01002472
Serhiy Storchakabad12572014-12-15 14:03:42 +02002473 if C:
2474 # Test interchangeability
2475 x = C.Decimal('-3.123e81723')
2476 y = P.Decimal('-3.123e81723')
Stefan Krah1919b7e2012-03-21 18:25:23 +01002477
Serhiy Storchakabad12572014-12-15 14:03:42 +02002478 sys.modules['decimal'] = C
2479 sx = pickle.dumps(x, proto)
2480 sys.modules['decimal'] = P
2481 r = pickle.loads(sx)
2482 self.assertIsInstance(r, P.Decimal)
2483 self.assertEqual(r, y)
Stefan Krah1919b7e2012-03-21 18:25:23 +01002484
Serhiy Storchakabad12572014-12-15 14:03:42 +02002485 sys.modules['decimal'] = P
2486 sy = pickle.dumps(y, proto)
2487 sys.modules['decimal'] = C
2488 r = pickle.loads(sy)
2489 self.assertIsInstance(r, C.Decimal)
2490 self.assertEqual(r, x)
Stefan Krah1919b7e2012-03-21 18:25:23 +01002491
Serhiy Storchakabad12572014-12-15 14:03:42 +02002492 x = C.Decimal('-3.123e81723').as_tuple()
2493 y = P.Decimal('-3.123e81723').as_tuple()
Stefan Krahf1d4e422014-04-29 18:23:35 +02002494
Serhiy Storchakabad12572014-12-15 14:03:42 +02002495 sys.modules['decimal'] = C
2496 sx = pickle.dumps(x, proto)
2497 sys.modules['decimal'] = P
2498 r = pickle.loads(sx)
2499 self.assertIsInstance(r, P.DecimalTuple)
2500 self.assertEqual(r, y)
Stefan Krahf1d4e422014-04-29 18:23:35 +02002501
Serhiy Storchakabad12572014-12-15 14:03:42 +02002502 sys.modules['decimal'] = P
2503 sy = pickle.dumps(y, proto)
2504 sys.modules['decimal'] = C
2505 r = pickle.loads(sy)
2506 self.assertIsInstance(r, C.DecimalTuple)
2507 self.assertEqual(r, x)
Stefan Krahf1d4e422014-04-29 18:23:35 +02002508
Serhiy Storchakabad12572014-12-15 14:03:42 +02002509 sys.modules['decimal'] = savedecimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01002510
2511 def test_int(self):
2512 Decimal = self.decimal.Decimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01002513
2514 for x in range(-250, 250):
2515 s = '%0.2f' % (x / 100.0)
2516 # should work the same as for floats
2517 self.assertEqual(int(Decimal(s)), int(float(s)))
2518 # should work the same as to_integral in the ROUND_DOWN mode
2519 d = Decimal(s)
2520 r = d.to_integral(ROUND_DOWN)
2521 self.assertEqual(Decimal(int(d)), r)
2522
2523 self.assertRaises(ValueError, int, Decimal('-nan'))
2524 self.assertRaises(ValueError, int, Decimal('snan'))
2525 self.assertRaises(OverflowError, int, Decimal('inf'))
2526 self.assertRaises(OverflowError, int, Decimal('-inf'))
2527
2528 def test_trunc(self):
2529 Decimal = self.decimal.Decimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01002530
2531 for x in range(-250, 250):
2532 s = '%0.2f' % (x / 100.0)
2533 # should work the same as for floats
2534 self.assertEqual(int(Decimal(s)), int(float(s)))
2535 # should work the same as to_integral in the ROUND_DOWN mode
2536 d = Decimal(s)
2537 r = d.to_integral(ROUND_DOWN)
2538 self.assertEqual(Decimal(math.trunc(d)), r)
2539
2540 def test_from_float(self):
2541
2542 Decimal = self.decimal.Decimal
2543
2544 class MyDecimal(Decimal):
Stefan Krah6817c592016-06-20 12:10:13 +02002545 def __init__(self, _):
2546 self.x = 'y'
Stefan Krah1919b7e2012-03-21 18:25:23 +01002547
2548 self.assertTrue(issubclass(MyDecimal, Decimal))
2549
2550 r = MyDecimal.from_float(0.1)
2551 self.assertEqual(type(r), MyDecimal)
2552 self.assertEqual(str(r),
2553 '0.1000000000000000055511151231257827021181583404541015625')
Stefan Krah6817c592016-06-20 12:10:13 +02002554 self.assertEqual(r.x, 'y')
2555
Stefan Krah1919b7e2012-03-21 18:25:23 +01002556 bigint = 12345678901234567890123456789
2557 self.assertEqual(MyDecimal.from_float(bigint), MyDecimal(bigint))
2558 self.assertTrue(MyDecimal.from_float(float('nan')).is_qnan())
2559 self.assertTrue(MyDecimal.from_float(float('inf')).is_infinite())
2560 self.assertTrue(MyDecimal.from_float(float('-inf')).is_infinite())
2561 self.assertEqual(str(MyDecimal.from_float(float('nan'))),
2562 str(Decimal('NaN')))
2563 self.assertEqual(str(MyDecimal.from_float(float('inf'))),
2564 str(Decimal('Infinity')))
2565 self.assertEqual(str(MyDecimal.from_float(float('-inf'))),
2566 str(Decimal('-Infinity')))
2567 self.assertRaises(TypeError, MyDecimal.from_float, 'abc')
2568 for i in range(200):
2569 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
2570 self.assertEqual(x, float(MyDecimal.from_float(x))) # roundtrip
2571
2572 def test_create_decimal_from_float(self):
2573 Decimal = self.decimal.Decimal
2574 Context = self.decimal.Context
Stefan Krah1919b7e2012-03-21 18:25:23 +01002575 Inexact = self.decimal.Inexact
2576
2577 context = Context(prec=5, rounding=ROUND_DOWN)
2578 self.assertEqual(
2579 context.create_decimal_from_float(math.pi),
2580 Decimal('3.1415')
2581 )
2582 context = Context(prec=5, rounding=ROUND_UP)
2583 self.assertEqual(
2584 context.create_decimal_from_float(math.pi),
2585 Decimal('3.1416')
2586 )
2587 context = Context(prec=5, traps=[Inexact])
2588 self.assertRaises(
2589 Inexact,
2590 context.create_decimal_from_float,
2591 math.pi
2592 )
2593 self.assertEqual(repr(context.create_decimal_from_float(-0.0)),
2594 "Decimal('-0')")
2595 self.assertEqual(repr(context.create_decimal_from_float(1.0)),
2596 "Decimal('1')")
2597 self.assertEqual(repr(context.create_decimal_from_float(10)),
2598 "Decimal('10')")
2599
2600 def test_quantize(self):
2601 Decimal = self.decimal.Decimal
2602 Context = self.decimal.Context
2603 InvalidOperation = self.decimal.InvalidOperation
Stefan Krah1919b7e2012-03-21 18:25:23 +01002604
2605 c = Context(Emax=99999, Emin=-99999)
2606 self.assertEqual(
2607 Decimal('7.335').quantize(Decimal('.01')),
2608 Decimal('7.34')
2609 )
2610 self.assertEqual(
2611 Decimal('7.335').quantize(Decimal('.01'), rounding=ROUND_DOWN),
2612 Decimal('7.33')
2613 )
2614 self.assertRaises(
2615 InvalidOperation,
2616 Decimal("10e99999").quantize, Decimal('1e100000'), context=c
2617 )
2618
2619 c = Context()
2620 d = Decimal("0.871831e800")
2621 x = d.quantize(context=c, exp=Decimal("1e797"), rounding=ROUND_DOWN)
2622 self.assertEqual(x, Decimal('8.71E+799'))
2623
2624 def test_complex(self):
2625 Decimal = self.decimal.Decimal
2626
2627 x = Decimal("9.8182731e181273")
2628 self.assertEqual(x.real, x)
2629 self.assertEqual(x.imag, 0)
2630 self.assertEqual(x.conjugate(), x)
2631
2632 x = Decimal("1")
2633 self.assertEqual(complex(x), complex(float(1)))
2634
2635 self.assertRaises(AttributeError, setattr, x, 'real', 100)
2636 self.assertRaises(AttributeError, setattr, x, 'imag', 100)
2637 self.assertRaises(AttributeError, setattr, x, 'conjugate', 100)
2638 self.assertRaises(AttributeError, setattr, x, '__complex__', 100)
2639
2640 def test_named_parameters(self):
2641 D = self.decimal.Decimal
2642 Context = self.decimal.Context
2643 localcontext = self.decimal.localcontext
2644 InvalidOperation = self.decimal.InvalidOperation
2645 Overflow = self.decimal.Overflow
2646
2647 xc = Context()
2648 xc.prec = 1
2649 xc.Emax = 1
2650 xc.Emin = -1
2651
2652 with localcontext() as c:
2653 c.clear_flags()
2654
2655 self.assertEqual(D(9, xc), 9)
2656 self.assertEqual(D(9, context=xc), 9)
2657 self.assertEqual(D(context=xc, value=9), 9)
2658 self.assertEqual(D(context=xc), 0)
2659 xc.clear_flags()
2660 self.assertRaises(InvalidOperation, D, "xyz", context=xc)
2661 self.assertTrue(xc.flags[InvalidOperation])
2662 self.assertFalse(c.flags[InvalidOperation])
2663
2664 xc.clear_flags()
2665 self.assertEqual(D(2).exp(context=xc), 7)
2666 self.assertRaises(Overflow, D(8).exp, context=xc)
2667 self.assertTrue(xc.flags[Overflow])
2668 self.assertFalse(c.flags[Overflow])
2669
2670 xc.clear_flags()
2671 self.assertEqual(D(2).ln(context=xc), D('0.7'))
2672 self.assertRaises(InvalidOperation, D(-1).ln, context=xc)
2673 self.assertTrue(xc.flags[InvalidOperation])
2674 self.assertFalse(c.flags[InvalidOperation])
2675
2676 self.assertEqual(D(0).log10(context=xc), D('-inf'))
2677 self.assertEqual(D(-1).next_minus(context=xc), -2)
2678 self.assertEqual(D(-1).next_plus(context=xc), D('-0.9'))
2679 self.assertEqual(D("9.73").normalize(context=xc), D('1E+1'))
2680 self.assertEqual(D("9999").to_integral(context=xc), 9999)
2681 self.assertEqual(D("-2000").to_integral_exact(context=xc), -2000)
2682 self.assertEqual(D("123").to_integral_value(context=xc), 123)
2683 self.assertEqual(D("0.0625").sqrt(context=xc), D('0.2'))
2684
2685 self.assertEqual(D("0.0625").compare(context=xc, other=3), -1)
2686 xc.clear_flags()
2687 self.assertRaises(InvalidOperation,
2688 D("0").compare_signal, D('nan'), context=xc)
2689 self.assertTrue(xc.flags[InvalidOperation])
2690 self.assertFalse(c.flags[InvalidOperation])
2691 self.assertEqual(D("0.01").max(D('0.0101'), context=xc), D('0.0'))
2692 self.assertEqual(D("0.01").max(D('0.0101'), context=xc), D('0.0'))
2693 self.assertEqual(D("0.2").max_mag(D('-0.3'), context=xc),
2694 D('-0.3'))
2695 self.assertEqual(D("0.02").min(D('-0.03'), context=xc), D('-0.0'))
2696 self.assertEqual(D("0.02").min_mag(D('-0.03'), context=xc),
2697 D('0.0'))
2698 self.assertEqual(D("0.2").next_toward(D('-1'), context=xc), D('0.1'))
2699 xc.clear_flags()
2700 self.assertRaises(InvalidOperation,
2701 D("0.2").quantize, D('1e10'), context=xc)
2702 self.assertTrue(xc.flags[InvalidOperation])
2703 self.assertFalse(c.flags[InvalidOperation])
2704 self.assertEqual(D("9.99").remainder_near(D('1.5'), context=xc),
2705 D('-0.5'))
2706
2707 self.assertEqual(D("9.9").fma(third=D('0.9'), context=xc, other=7),
2708 D('7E+1'))
2709
2710 self.assertRaises(TypeError, D(1).is_canonical, context=xc)
2711 self.assertRaises(TypeError, D(1).is_finite, context=xc)
2712 self.assertRaises(TypeError, D(1).is_infinite, context=xc)
2713 self.assertRaises(TypeError, D(1).is_nan, context=xc)
2714 self.assertRaises(TypeError, D(1).is_qnan, context=xc)
2715 self.assertRaises(TypeError, D(1).is_snan, context=xc)
2716 self.assertRaises(TypeError, D(1).is_signed, context=xc)
2717 self.assertRaises(TypeError, D(1).is_zero, context=xc)
2718
2719 self.assertFalse(D("0.01").is_normal(context=xc))
2720 self.assertTrue(D("0.01").is_subnormal(context=xc))
2721
2722 self.assertRaises(TypeError, D(1).adjusted, context=xc)
2723 self.assertRaises(TypeError, D(1).conjugate, context=xc)
2724 self.assertRaises(TypeError, D(1).radix, context=xc)
2725
2726 self.assertEqual(D(-111).logb(context=xc), 2)
2727 self.assertEqual(D(0).logical_invert(context=xc), 1)
2728 self.assertEqual(D('0.01').number_class(context=xc), '+Subnormal')
2729 self.assertEqual(D('0.21').to_eng_string(context=xc), '0.21')
2730
2731 self.assertEqual(D('11').logical_and(D('10'), context=xc), 0)
2732 self.assertEqual(D('11').logical_or(D('10'), context=xc), 1)
2733 self.assertEqual(D('01').logical_xor(D('10'), context=xc), 1)
2734 self.assertEqual(D('23').rotate(1, context=xc), 3)
2735 self.assertEqual(D('23').rotate(1, context=xc), 3)
2736 xc.clear_flags()
2737 self.assertRaises(Overflow,
2738 D('23').scaleb, 1, context=xc)
2739 self.assertTrue(xc.flags[Overflow])
2740 self.assertFalse(c.flags[Overflow])
2741 self.assertEqual(D('23').shift(-1, context=xc), 0)
2742
2743 self.assertRaises(TypeError, D.from_float, 1.1, context=xc)
2744 self.assertRaises(TypeError, D(0).as_tuple, context=xc)
2745
Stefan Krah040e3112012-12-15 22:33:33 +01002746 self.assertEqual(D(1).canonical(), 1)
2747 self.assertRaises(TypeError, D("-1").copy_abs, context=xc)
2748 self.assertRaises(TypeError, D("-1").copy_negate, context=xc)
2749 self.assertRaises(TypeError, D(1).canonical, context="x")
2750 self.assertRaises(TypeError, D(1).canonical, xyz="x")
Stefan Krah1919b7e2012-03-21 18:25:23 +01002751
Stefan Krahb6405ef2012-03-23 14:46:48 +01002752 def test_exception_hierarchy(self):
2753
2754 decimal = self.decimal
2755 DecimalException = decimal.DecimalException
2756 InvalidOperation = decimal.InvalidOperation
2757 FloatOperation = decimal.FloatOperation
2758 DivisionByZero = decimal.DivisionByZero
2759 Overflow = decimal.Overflow
2760 Underflow = decimal.Underflow
2761 Subnormal = decimal.Subnormal
2762 Inexact = decimal.Inexact
2763 Rounded = decimal.Rounded
2764 Clamped = decimal.Clamped
2765
2766 self.assertTrue(issubclass(DecimalException, ArithmeticError))
2767
2768 self.assertTrue(issubclass(InvalidOperation, DecimalException))
2769 self.assertTrue(issubclass(FloatOperation, DecimalException))
2770 self.assertTrue(issubclass(FloatOperation, TypeError))
2771 self.assertTrue(issubclass(DivisionByZero, DecimalException))
2772 self.assertTrue(issubclass(DivisionByZero, ZeroDivisionError))
2773 self.assertTrue(issubclass(Overflow, Rounded))
2774 self.assertTrue(issubclass(Overflow, Inexact))
2775 self.assertTrue(issubclass(Overflow, DecimalException))
2776 self.assertTrue(issubclass(Underflow, Inexact))
2777 self.assertTrue(issubclass(Underflow, Rounded))
2778 self.assertTrue(issubclass(Underflow, Subnormal))
2779 self.assertTrue(issubclass(Underflow, DecimalException))
2780
2781 self.assertTrue(issubclass(Subnormal, DecimalException))
2782 self.assertTrue(issubclass(Inexact, DecimalException))
2783 self.assertTrue(issubclass(Rounded, DecimalException))
2784 self.assertTrue(issubclass(Clamped, DecimalException))
2785
2786 self.assertTrue(issubclass(decimal.ConversionSyntax, InvalidOperation))
2787 self.assertTrue(issubclass(decimal.DivisionImpossible, InvalidOperation))
2788 self.assertTrue(issubclass(decimal.DivisionUndefined, InvalidOperation))
2789 self.assertTrue(issubclass(decimal.DivisionUndefined, ZeroDivisionError))
2790 self.assertTrue(issubclass(decimal.InvalidContext, InvalidOperation))
2791
Stefan Krah1919b7e2012-03-21 18:25:23 +01002792class CPythonAPItests(PythonAPItests):
2793 decimal = C
2794class PyPythonAPItests(PythonAPItests):
2795 decimal = P
2796
2797class ContextAPItests(unittest.TestCase):
2798
Stefan Krah9a4ff432012-12-16 21:10:35 +01002799 def test_none_args(self):
2800 Context = self.decimal.Context
2801 InvalidOperation = self.decimal.InvalidOperation
2802 DivisionByZero = self.decimal.DivisionByZero
2803 Overflow = self.decimal.Overflow
Stefan Krah9a4ff432012-12-16 21:10:35 +01002804
2805 c1 = Context()
2806 c2 = Context(prec=None, rounding=None, Emax=None, Emin=None,
2807 capitals=None, clamp=None, flags=None, traps=None)
2808 for c in [c1, c2]:
2809 self.assertEqual(c.prec, 28)
2810 self.assertEqual(c.rounding, ROUND_HALF_EVEN)
2811 self.assertEqual(c.Emax, 999999)
2812 self.assertEqual(c.Emin, -999999)
2813 self.assertEqual(c.capitals, 1)
2814 self.assertEqual(c.clamp, 0)
2815 assert_signals(self, c, 'flags', [])
2816 assert_signals(self, c, 'traps', [InvalidOperation, DivisionByZero,
2817 Overflow])
2818
Stefan Krah59a4a932013-01-16 12:58:59 +01002819 @cpython_only
2820 def test_from_legacy_strings(self):
2821 import _testcapi
2822 c = self.decimal.Context()
2823
2824 for rnd in RoundingModes:
2825 c.rounding = _testcapi.unicode_legacy_string(rnd)
2826 self.assertEqual(c.rounding, rnd)
2827
2828 s = _testcapi.unicode_legacy_string('')
2829 self.assertRaises(TypeError, setattr, c, 'rounding', s)
2830
2831 s = _testcapi.unicode_legacy_string('ROUND_\x00UP')
2832 self.assertRaises(TypeError, setattr, c, 'rounding', s)
2833
Stefan Krah1919b7e2012-03-21 18:25:23 +01002834 def test_pickle(self):
2835
Serhiy Storchakabad12572014-12-15 14:03:42 +02002836 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
2837 Context = self.decimal.Context
Stefan Krah1919b7e2012-03-21 18:25:23 +01002838
Serhiy Storchakabad12572014-12-15 14:03:42 +02002839 savedecimal = sys.modules['decimal']
Stefan Krah1919b7e2012-03-21 18:25:23 +01002840
Serhiy Storchakabad12572014-12-15 14:03:42 +02002841 # Round trip
2842 sys.modules['decimal'] = self.decimal
2843 c = Context()
2844 e = pickle.loads(pickle.dumps(c, proto))
Stefan Krah1919b7e2012-03-21 18:25:23 +01002845
Serhiy Storchakabad12572014-12-15 14:03:42 +02002846 self.assertEqual(c.prec, e.prec)
2847 self.assertEqual(c.Emin, e.Emin)
2848 self.assertEqual(c.Emax, e.Emax)
2849 self.assertEqual(c.rounding, e.rounding)
2850 self.assertEqual(c.capitals, e.capitals)
2851 self.assertEqual(c.clamp, e.clamp)
2852 self.assertEqual(c.flags, e.flags)
2853 self.assertEqual(c.traps, e.traps)
Stefan Krah1919b7e2012-03-21 18:25:23 +01002854
Serhiy Storchakabad12572014-12-15 14:03:42 +02002855 # Test interchangeability
2856 combinations = [(C, P), (P, C)] if C else [(P, P)]
2857 for dumper, loader in combinations:
2858 for ri, _ in enumerate(RoundingModes):
2859 for fi, _ in enumerate(OrderedSignals[dumper]):
2860 for ti, _ in enumerate(OrderedSignals[dumper]):
Stefan Krah1919b7e2012-03-21 18:25:23 +01002861
Serhiy Storchakabad12572014-12-15 14:03:42 +02002862 prec = random.randrange(1, 100)
2863 emin = random.randrange(-100, 0)
2864 emax = random.randrange(1, 100)
2865 caps = random.randrange(2)
2866 clamp = random.randrange(2)
Stefan Krah1919b7e2012-03-21 18:25:23 +01002867
Serhiy Storchakabad12572014-12-15 14:03:42 +02002868 # One module dumps
2869 sys.modules['decimal'] = dumper
2870 c = dumper.Context(
2871 prec=prec, Emin=emin, Emax=emax,
2872 rounding=RoundingModes[ri],
2873 capitals=caps, clamp=clamp,
2874 flags=OrderedSignals[dumper][:fi],
2875 traps=OrderedSignals[dumper][:ti]
2876 )
2877 s = pickle.dumps(c, proto)
Stefan Krah1919b7e2012-03-21 18:25:23 +01002878
Serhiy Storchakabad12572014-12-15 14:03:42 +02002879 # The other module loads
2880 sys.modules['decimal'] = loader
2881 d = pickle.loads(s)
2882 self.assertIsInstance(d, loader.Context)
Stefan Krah1919b7e2012-03-21 18:25:23 +01002883
Serhiy Storchakabad12572014-12-15 14:03:42 +02002884 self.assertEqual(d.prec, prec)
2885 self.assertEqual(d.Emin, emin)
2886 self.assertEqual(d.Emax, emax)
2887 self.assertEqual(d.rounding, RoundingModes[ri])
2888 self.assertEqual(d.capitals, caps)
2889 self.assertEqual(d.clamp, clamp)
2890 assert_signals(self, d, 'flags', OrderedSignals[loader][:fi])
2891 assert_signals(self, d, 'traps', OrderedSignals[loader][:ti])
Stefan Krah1919b7e2012-03-21 18:25:23 +01002892
Serhiy Storchakabad12572014-12-15 14:03:42 +02002893 sys.modules['decimal'] = savedecimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01002894
2895 def test_equality_with_other_types(self):
2896 Decimal = self.decimal.Decimal
2897
2898 self.assertIn(Decimal(10), ['a', 1.0, Decimal(10), (1,2), {}])
2899 self.assertNotIn(Decimal(10), ['a', 1.0, (1,2), {}])
2900
2901 def test_copy(self):
2902 # All copies should be deep
2903 Decimal = self.decimal.Decimal
2904 Context = self.decimal.Context
2905
2906 c = Context()
2907 d = c.copy()
2908 self.assertNotEqual(id(c), id(d))
2909 self.assertNotEqual(id(c.flags), id(d.flags))
2910 self.assertNotEqual(id(c.traps), id(d.traps))
2911 k1 = set(c.flags.keys())
2912 k2 = set(d.flags.keys())
2913 self.assertEqual(k1, k2)
2914 self.assertEqual(c.flags, d.flags)
2915
2916 def test__clamp(self):
2917 # In Python 3.2, the private attribute `_clamp` was made
2918 # public (issue 8540), with the old `_clamp` becoming a
2919 # property wrapping `clamp`. For the duration of Python 3.2
2920 # only, the attribute should be gettable/settable via both
2921 # `clamp` and `_clamp`; in Python 3.3, `_clamp` should be
2922 # removed.
2923 Context = self.decimal.Context
2924 c = Context()
2925 self.assertRaises(AttributeError, getattr, c, '_clamp')
2926
2927 def test_abs(self):
2928 Decimal = self.decimal.Decimal
2929 Context = self.decimal.Context
2930
2931 c = Context()
2932 d = c.abs(Decimal(-1))
2933 self.assertEqual(c.abs(-1), d)
2934 self.assertRaises(TypeError, c.abs, '-1')
2935
2936 def test_add(self):
2937 Decimal = self.decimal.Decimal
2938 Context = self.decimal.Context
2939
2940 c = Context()
2941 d = c.add(Decimal(1), Decimal(1))
2942 self.assertEqual(c.add(1, 1), d)
2943 self.assertEqual(c.add(Decimal(1), 1), d)
2944 self.assertEqual(c.add(1, Decimal(1)), d)
2945 self.assertRaises(TypeError, c.add, '1', 1)
2946 self.assertRaises(TypeError, c.add, 1, '1')
2947
2948 def test_compare(self):
2949 Decimal = self.decimal.Decimal
2950 Context = self.decimal.Context
2951
2952 c = Context()
2953 d = c.compare(Decimal(1), Decimal(1))
2954 self.assertEqual(c.compare(1, 1), d)
2955 self.assertEqual(c.compare(Decimal(1), 1), d)
2956 self.assertEqual(c.compare(1, Decimal(1)), d)
2957 self.assertRaises(TypeError, c.compare, '1', 1)
2958 self.assertRaises(TypeError, c.compare, 1, '1')
2959
2960 def test_compare_signal(self):
2961 Decimal = self.decimal.Decimal
2962 Context = self.decimal.Context
2963
2964 c = Context()
2965 d = c.compare_signal(Decimal(1), Decimal(1))
2966 self.assertEqual(c.compare_signal(1, 1), d)
2967 self.assertEqual(c.compare_signal(Decimal(1), 1), d)
2968 self.assertEqual(c.compare_signal(1, Decimal(1)), d)
2969 self.assertRaises(TypeError, c.compare_signal, '1', 1)
2970 self.assertRaises(TypeError, c.compare_signal, 1, '1')
2971
2972 def test_compare_total(self):
2973 Decimal = self.decimal.Decimal
2974 Context = self.decimal.Context
2975
2976 c = Context()
2977 d = c.compare_total(Decimal(1), Decimal(1))
2978 self.assertEqual(c.compare_total(1, 1), d)
2979 self.assertEqual(c.compare_total(Decimal(1), 1), d)
2980 self.assertEqual(c.compare_total(1, Decimal(1)), d)
2981 self.assertRaises(TypeError, c.compare_total, '1', 1)
2982 self.assertRaises(TypeError, c.compare_total, 1, '1')
2983
2984 def test_compare_total_mag(self):
2985 Decimal = self.decimal.Decimal
2986 Context = self.decimal.Context
2987
2988 c = Context()
2989 d = c.compare_total_mag(Decimal(1), Decimal(1))
2990 self.assertEqual(c.compare_total_mag(1, 1), d)
2991 self.assertEqual(c.compare_total_mag(Decimal(1), 1), d)
2992 self.assertEqual(c.compare_total_mag(1, Decimal(1)), d)
2993 self.assertRaises(TypeError, c.compare_total_mag, '1', 1)
2994 self.assertRaises(TypeError, c.compare_total_mag, 1, '1')
2995
2996 def test_copy_abs(self):
2997 Decimal = self.decimal.Decimal
2998 Context = self.decimal.Context
2999
3000 c = Context()
3001 d = c.copy_abs(Decimal(-1))
3002 self.assertEqual(c.copy_abs(-1), d)
3003 self.assertRaises(TypeError, c.copy_abs, '-1')
3004
3005 def test_copy_decimal(self):
3006 Decimal = self.decimal.Decimal
3007 Context = self.decimal.Context
3008
3009 c = Context()
3010 d = c.copy_decimal(Decimal(-1))
3011 self.assertEqual(c.copy_decimal(-1), d)
3012 self.assertRaises(TypeError, c.copy_decimal, '-1')
3013
3014 def test_copy_negate(self):
3015 Decimal = self.decimal.Decimal
3016 Context = self.decimal.Context
3017
3018 c = Context()
3019 d = c.copy_negate(Decimal(-1))
3020 self.assertEqual(c.copy_negate(-1), d)
3021 self.assertRaises(TypeError, c.copy_negate, '-1')
3022
3023 def test_copy_sign(self):
3024 Decimal = self.decimal.Decimal
3025 Context = self.decimal.Context
3026
3027 c = Context()
3028 d = c.copy_sign(Decimal(1), Decimal(-2))
3029 self.assertEqual(c.copy_sign(1, -2), d)
3030 self.assertEqual(c.copy_sign(Decimal(1), -2), d)
3031 self.assertEqual(c.copy_sign(1, Decimal(-2)), d)
3032 self.assertRaises(TypeError, c.copy_sign, '1', -2)
3033 self.assertRaises(TypeError, c.copy_sign, 1, '-2')
3034
3035 def test_divide(self):
3036 Decimal = self.decimal.Decimal
3037 Context = self.decimal.Context
3038
3039 c = Context()
3040 d = c.divide(Decimal(1), Decimal(2))
3041 self.assertEqual(c.divide(1, 2), d)
3042 self.assertEqual(c.divide(Decimal(1), 2), d)
3043 self.assertEqual(c.divide(1, Decimal(2)), d)
3044 self.assertRaises(TypeError, c.divide, '1', 2)
3045 self.assertRaises(TypeError, c.divide, 1, '2')
3046
3047 def test_divide_int(self):
3048 Decimal = self.decimal.Decimal
3049 Context = self.decimal.Context
3050
3051 c = Context()
3052 d = c.divide_int(Decimal(1), Decimal(2))
3053 self.assertEqual(c.divide_int(1, 2), d)
3054 self.assertEqual(c.divide_int(Decimal(1), 2), d)
3055 self.assertEqual(c.divide_int(1, Decimal(2)), d)
3056 self.assertRaises(TypeError, c.divide_int, '1', 2)
3057 self.assertRaises(TypeError, c.divide_int, 1, '2')
3058
3059 def test_divmod(self):
3060 Decimal = self.decimal.Decimal
3061 Context = self.decimal.Context
3062
3063 c = Context()
3064 d = c.divmod(Decimal(1), Decimal(2))
3065 self.assertEqual(c.divmod(1, 2), d)
3066 self.assertEqual(c.divmod(Decimal(1), 2), d)
3067 self.assertEqual(c.divmod(1, Decimal(2)), d)
3068 self.assertRaises(TypeError, c.divmod, '1', 2)
3069 self.assertRaises(TypeError, c.divmod, 1, '2')
3070
3071 def test_exp(self):
3072 Decimal = self.decimal.Decimal
3073 Context = self.decimal.Context
3074
3075 c = Context()
3076 d = c.exp(Decimal(10))
3077 self.assertEqual(c.exp(10), d)
3078 self.assertRaises(TypeError, c.exp, '10')
3079
3080 def test_fma(self):
3081 Decimal = self.decimal.Decimal
3082 Context = self.decimal.Context
3083
3084 c = Context()
3085 d = c.fma(Decimal(2), Decimal(3), Decimal(4))
3086 self.assertEqual(c.fma(2, 3, 4), d)
3087 self.assertEqual(c.fma(Decimal(2), 3, 4), d)
3088 self.assertEqual(c.fma(2, Decimal(3), 4), d)
3089 self.assertEqual(c.fma(2, 3, Decimal(4)), d)
3090 self.assertEqual(c.fma(Decimal(2), Decimal(3), 4), d)
3091 self.assertRaises(TypeError, c.fma, '2', 3, 4)
3092 self.assertRaises(TypeError, c.fma, 2, '3', 4)
3093 self.assertRaises(TypeError, c.fma, 2, 3, '4')
3094
3095 # Issue 12079 for Context.fma ...
3096 self.assertRaises(TypeError, c.fma,
3097 Decimal('Infinity'), Decimal(0), "not a decimal")
3098 self.assertRaises(TypeError, c.fma,
3099 Decimal(1), Decimal('snan'), 1.222)
3100 # ... and for Decimal.fma.
3101 self.assertRaises(TypeError, Decimal('Infinity').fma,
3102 Decimal(0), "not a decimal")
3103 self.assertRaises(TypeError, Decimal(1).fma,
3104 Decimal('snan'), 1.222)
3105
3106 def test_is_finite(self):
3107 Decimal = self.decimal.Decimal
3108 Context = self.decimal.Context
3109
3110 c = Context()
3111 d = c.is_finite(Decimal(10))
3112 self.assertEqual(c.is_finite(10), d)
3113 self.assertRaises(TypeError, c.is_finite, '10')
3114
3115 def test_is_infinite(self):
3116 Decimal = self.decimal.Decimal
3117 Context = self.decimal.Context
3118
3119 c = Context()
3120 d = c.is_infinite(Decimal(10))
3121 self.assertEqual(c.is_infinite(10), d)
3122 self.assertRaises(TypeError, c.is_infinite, '10')
3123
3124 def test_is_nan(self):
3125 Decimal = self.decimal.Decimal
3126 Context = self.decimal.Context
3127
3128 c = Context()
3129 d = c.is_nan(Decimal(10))
3130 self.assertEqual(c.is_nan(10), d)
3131 self.assertRaises(TypeError, c.is_nan, '10')
3132
3133 def test_is_normal(self):
3134 Decimal = self.decimal.Decimal
3135 Context = self.decimal.Context
3136
3137 c = Context()
3138 d = c.is_normal(Decimal(10))
3139 self.assertEqual(c.is_normal(10), d)
3140 self.assertRaises(TypeError, c.is_normal, '10')
3141
3142 def test_is_qnan(self):
3143 Decimal = self.decimal.Decimal
3144 Context = self.decimal.Context
3145
3146 c = Context()
3147 d = c.is_qnan(Decimal(10))
3148 self.assertEqual(c.is_qnan(10), d)
3149 self.assertRaises(TypeError, c.is_qnan, '10')
3150
3151 def test_is_signed(self):
3152 Decimal = self.decimal.Decimal
3153 Context = self.decimal.Context
3154
3155 c = Context()
3156 d = c.is_signed(Decimal(10))
3157 self.assertEqual(c.is_signed(10), d)
3158 self.assertRaises(TypeError, c.is_signed, '10')
3159
3160 def test_is_snan(self):
3161 Decimal = self.decimal.Decimal
3162 Context = self.decimal.Context
3163
3164 c = Context()
3165 d = c.is_snan(Decimal(10))
3166 self.assertEqual(c.is_snan(10), d)
3167 self.assertRaises(TypeError, c.is_snan, '10')
3168
3169 def test_is_subnormal(self):
3170 Decimal = self.decimal.Decimal
3171 Context = self.decimal.Context
3172
3173 c = Context()
3174 d = c.is_subnormal(Decimal(10))
3175 self.assertEqual(c.is_subnormal(10), d)
3176 self.assertRaises(TypeError, c.is_subnormal, '10')
3177
3178 def test_is_zero(self):
3179 Decimal = self.decimal.Decimal
3180 Context = self.decimal.Context
3181
3182 c = Context()
3183 d = c.is_zero(Decimal(10))
3184 self.assertEqual(c.is_zero(10), d)
3185 self.assertRaises(TypeError, c.is_zero, '10')
3186
3187 def test_ln(self):
3188 Decimal = self.decimal.Decimal
3189 Context = self.decimal.Context
3190
3191 c = Context()
3192 d = c.ln(Decimal(10))
3193 self.assertEqual(c.ln(10), d)
3194 self.assertRaises(TypeError, c.ln, '10')
3195
3196 def test_log10(self):
3197 Decimal = self.decimal.Decimal
3198 Context = self.decimal.Context
3199
3200 c = Context()
3201 d = c.log10(Decimal(10))
3202 self.assertEqual(c.log10(10), d)
3203 self.assertRaises(TypeError, c.log10, '10')
3204
3205 def test_logb(self):
3206 Decimal = self.decimal.Decimal
3207 Context = self.decimal.Context
3208
3209 c = Context()
3210 d = c.logb(Decimal(10))
3211 self.assertEqual(c.logb(10), d)
3212 self.assertRaises(TypeError, c.logb, '10')
3213
3214 def test_logical_and(self):
3215 Decimal = self.decimal.Decimal
3216 Context = self.decimal.Context
3217
3218 c = Context()
3219 d = c.logical_and(Decimal(1), Decimal(1))
3220 self.assertEqual(c.logical_and(1, 1), d)
3221 self.assertEqual(c.logical_and(Decimal(1), 1), d)
3222 self.assertEqual(c.logical_and(1, Decimal(1)), d)
3223 self.assertRaises(TypeError, c.logical_and, '1', 1)
3224 self.assertRaises(TypeError, c.logical_and, 1, '1')
3225
3226 def test_logical_invert(self):
3227 Decimal = self.decimal.Decimal
3228 Context = self.decimal.Context
3229
3230 c = Context()
3231 d = c.logical_invert(Decimal(1000))
3232 self.assertEqual(c.logical_invert(1000), d)
3233 self.assertRaises(TypeError, c.logical_invert, '1000')
3234
3235 def test_logical_or(self):
3236 Decimal = self.decimal.Decimal
3237 Context = self.decimal.Context
3238
3239 c = Context()
3240 d = c.logical_or(Decimal(1), Decimal(1))
3241 self.assertEqual(c.logical_or(1, 1), d)
3242 self.assertEqual(c.logical_or(Decimal(1), 1), d)
3243 self.assertEqual(c.logical_or(1, Decimal(1)), d)
3244 self.assertRaises(TypeError, c.logical_or, '1', 1)
3245 self.assertRaises(TypeError, c.logical_or, 1, '1')
3246
3247 def test_logical_xor(self):
3248 Decimal = self.decimal.Decimal
3249 Context = self.decimal.Context
3250
3251 c = Context()
3252 d = c.logical_xor(Decimal(1), Decimal(1))
3253 self.assertEqual(c.logical_xor(1, 1), d)
3254 self.assertEqual(c.logical_xor(Decimal(1), 1), d)
3255 self.assertEqual(c.logical_xor(1, Decimal(1)), d)
3256 self.assertRaises(TypeError, c.logical_xor, '1', 1)
3257 self.assertRaises(TypeError, c.logical_xor, 1, '1')
3258
3259 def test_max(self):
3260 Decimal = self.decimal.Decimal
3261 Context = self.decimal.Context
3262
3263 c = Context()
3264 d = c.max(Decimal(1), Decimal(2))
3265 self.assertEqual(c.max(1, 2), d)
3266 self.assertEqual(c.max(Decimal(1), 2), d)
3267 self.assertEqual(c.max(1, Decimal(2)), d)
3268 self.assertRaises(TypeError, c.max, '1', 2)
3269 self.assertRaises(TypeError, c.max, 1, '2')
3270
3271 def test_max_mag(self):
3272 Decimal = self.decimal.Decimal
3273 Context = self.decimal.Context
3274
3275 c = Context()
3276 d = c.max_mag(Decimal(1), Decimal(2))
3277 self.assertEqual(c.max_mag(1, 2), d)
3278 self.assertEqual(c.max_mag(Decimal(1), 2), d)
3279 self.assertEqual(c.max_mag(1, Decimal(2)), d)
3280 self.assertRaises(TypeError, c.max_mag, '1', 2)
3281 self.assertRaises(TypeError, c.max_mag, 1, '2')
3282
3283 def test_min(self):
3284 Decimal = self.decimal.Decimal
3285 Context = self.decimal.Context
3286
3287 c = Context()
3288 d = c.min(Decimal(1), Decimal(2))
3289 self.assertEqual(c.min(1, 2), d)
3290 self.assertEqual(c.min(Decimal(1), 2), d)
3291 self.assertEqual(c.min(1, Decimal(2)), d)
3292 self.assertRaises(TypeError, c.min, '1', 2)
3293 self.assertRaises(TypeError, c.min, 1, '2')
3294
3295 def test_min_mag(self):
3296 Decimal = self.decimal.Decimal
3297 Context = self.decimal.Context
3298
3299 c = Context()
3300 d = c.min_mag(Decimal(1), Decimal(2))
3301 self.assertEqual(c.min_mag(1, 2), d)
3302 self.assertEqual(c.min_mag(Decimal(1), 2), d)
3303 self.assertEqual(c.min_mag(1, Decimal(2)), d)
3304 self.assertRaises(TypeError, c.min_mag, '1', 2)
3305 self.assertRaises(TypeError, c.min_mag, 1, '2')
3306
3307 def test_minus(self):
3308 Decimal = self.decimal.Decimal
3309 Context = self.decimal.Context
3310
3311 c = Context()
3312 d = c.minus(Decimal(10))
3313 self.assertEqual(c.minus(10), d)
3314 self.assertRaises(TypeError, c.minus, '10')
3315
3316 def test_multiply(self):
3317 Decimal = self.decimal.Decimal
3318 Context = self.decimal.Context
3319
3320 c = Context()
3321 d = c.multiply(Decimal(1), Decimal(2))
3322 self.assertEqual(c.multiply(1, 2), d)
3323 self.assertEqual(c.multiply(Decimal(1), 2), d)
3324 self.assertEqual(c.multiply(1, Decimal(2)), d)
3325 self.assertRaises(TypeError, c.multiply, '1', 2)
3326 self.assertRaises(TypeError, c.multiply, 1, '2')
3327
3328 def test_next_minus(self):
3329 Decimal = self.decimal.Decimal
3330 Context = self.decimal.Context
3331
3332 c = Context()
3333 d = c.next_minus(Decimal(10))
3334 self.assertEqual(c.next_minus(10), d)
3335 self.assertRaises(TypeError, c.next_minus, '10')
3336
3337 def test_next_plus(self):
3338 Decimal = self.decimal.Decimal
3339 Context = self.decimal.Context
3340
3341 c = Context()
3342 d = c.next_plus(Decimal(10))
3343 self.assertEqual(c.next_plus(10), d)
3344 self.assertRaises(TypeError, c.next_plus, '10')
3345
3346 def test_next_toward(self):
3347 Decimal = self.decimal.Decimal
3348 Context = self.decimal.Context
3349
3350 c = Context()
3351 d = c.next_toward(Decimal(1), Decimal(2))
3352 self.assertEqual(c.next_toward(1, 2), d)
3353 self.assertEqual(c.next_toward(Decimal(1), 2), d)
3354 self.assertEqual(c.next_toward(1, Decimal(2)), d)
3355 self.assertRaises(TypeError, c.next_toward, '1', 2)
3356 self.assertRaises(TypeError, c.next_toward, 1, '2')
3357
3358 def test_normalize(self):
3359 Decimal = self.decimal.Decimal
3360 Context = self.decimal.Context
3361
3362 c = Context()
3363 d = c.normalize(Decimal(10))
3364 self.assertEqual(c.normalize(10), d)
3365 self.assertRaises(TypeError, c.normalize, '10')
3366
3367 def test_number_class(self):
3368 Decimal = self.decimal.Decimal
3369 Context = self.decimal.Context
3370
3371 c = Context()
3372 self.assertEqual(c.number_class(123), c.number_class(Decimal(123)))
3373 self.assertEqual(c.number_class(0), c.number_class(Decimal(0)))
3374 self.assertEqual(c.number_class(-45), c.number_class(Decimal(-45)))
3375
3376 def test_plus(self):
3377 Decimal = self.decimal.Decimal
3378 Context = self.decimal.Context
3379
3380 c = Context()
3381 d = c.plus(Decimal(10))
3382 self.assertEqual(c.plus(10), d)
3383 self.assertRaises(TypeError, c.plus, '10')
3384
3385 def test_power(self):
3386 Decimal = self.decimal.Decimal
3387 Context = self.decimal.Context
3388
3389 c = Context()
3390 d = c.power(Decimal(1), Decimal(4))
3391 self.assertEqual(c.power(1, 4), d)
3392 self.assertEqual(c.power(Decimal(1), 4), d)
3393 self.assertEqual(c.power(1, Decimal(4)), d)
3394 self.assertEqual(c.power(Decimal(1), Decimal(4)), d)
3395 self.assertRaises(TypeError, c.power, '1', 4)
3396 self.assertRaises(TypeError, c.power, 1, '4')
3397 self.assertEqual(c.power(modulo=5, b=8, a=2), 1)
3398
3399 def test_quantize(self):
3400 Decimal = self.decimal.Decimal
3401 Context = self.decimal.Context
3402
3403 c = Context()
3404 d = c.quantize(Decimal(1), Decimal(2))
3405 self.assertEqual(c.quantize(1, 2), d)
3406 self.assertEqual(c.quantize(Decimal(1), 2), d)
3407 self.assertEqual(c.quantize(1, Decimal(2)), d)
3408 self.assertRaises(TypeError, c.quantize, '1', 2)
3409 self.assertRaises(TypeError, c.quantize, 1, '2')
3410
3411 def test_remainder(self):
3412 Decimal = self.decimal.Decimal
3413 Context = self.decimal.Context
3414
3415 c = Context()
3416 d = c.remainder(Decimal(1), Decimal(2))
3417 self.assertEqual(c.remainder(1, 2), d)
3418 self.assertEqual(c.remainder(Decimal(1), 2), d)
3419 self.assertEqual(c.remainder(1, Decimal(2)), d)
3420 self.assertRaises(TypeError, c.remainder, '1', 2)
3421 self.assertRaises(TypeError, c.remainder, 1, '2')
3422
3423 def test_remainder_near(self):
3424 Decimal = self.decimal.Decimal
3425 Context = self.decimal.Context
3426
3427 c = Context()
3428 d = c.remainder_near(Decimal(1), Decimal(2))
3429 self.assertEqual(c.remainder_near(1, 2), d)
3430 self.assertEqual(c.remainder_near(Decimal(1), 2), d)
3431 self.assertEqual(c.remainder_near(1, Decimal(2)), d)
3432 self.assertRaises(TypeError, c.remainder_near, '1', 2)
3433 self.assertRaises(TypeError, c.remainder_near, 1, '2')
3434
3435 def test_rotate(self):
3436 Decimal = self.decimal.Decimal
3437 Context = self.decimal.Context
3438
3439 c = Context()
3440 d = c.rotate(Decimal(1), Decimal(2))
3441 self.assertEqual(c.rotate(1, 2), d)
3442 self.assertEqual(c.rotate(Decimal(1), 2), d)
3443 self.assertEqual(c.rotate(1, Decimal(2)), d)
3444 self.assertRaises(TypeError, c.rotate, '1', 2)
3445 self.assertRaises(TypeError, c.rotate, 1, '2')
3446
3447 def test_sqrt(self):
3448 Decimal = self.decimal.Decimal
3449 Context = self.decimal.Context
3450
3451 c = Context()
3452 d = c.sqrt(Decimal(10))
3453 self.assertEqual(c.sqrt(10), d)
3454 self.assertRaises(TypeError, c.sqrt, '10')
3455
3456 def test_same_quantum(self):
3457 Decimal = self.decimal.Decimal
3458 Context = self.decimal.Context
3459
3460 c = Context()
3461 d = c.same_quantum(Decimal(1), Decimal(2))
3462 self.assertEqual(c.same_quantum(1, 2), d)
3463 self.assertEqual(c.same_quantum(Decimal(1), 2), d)
3464 self.assertEqual(c.same_quantum(1, Decimal(2)), d)
3465 self.assertRaises(TypeError, c.same_quantum, '1', 2)
3466 self.assertRaises(TypeError, c.same_quantum, 1, '2')
3467
3468 def test_scaleb(self):
3469 Decimal = self.decimal.Decimal
3470 Context = self.decimal.Context
3471
3472 c = Context()
3473 d = c.scaleb(Decimal(1), Decimal(2))
3474 self.assertEqual(c.scaleb(1, 2), d)
3475 self.assertEqual(c.scaleb(Decimal(1), 2), d)
3476 self.assertEqual(c.scaleb(1, Decimal(2)), d)
3477 self.assertRaises(TypeError, c.scaleb, '1', 2)
3478 self.assertRaises(TypeError, c.scaleb, 1, '2')
3479
3480 def test_shift(self):
3481 Decimal = self.decimal.Decimal
3482 Context = self.decimal.Context
3483
3484 c = Context()
3485 d = c.shift(Decimal(1), Decimal(2))
3486 self.assertEqual(c.shift(1, 2), d)
3487 self.assertEqual(c.shift(Decimal(1), 2), d)
3488 self.assertEqual(c.shift(1, Decimal(2)), d)
3489 self.assertRaises(TypeError, c.shift, '1', 2)
3490 self.assertRaises(TypeError, c.shift, 1, '2')
3491
3492 def test_subtract(self):
3493 Decimal = self.decimal.Decimal
3494 Context = self.decimal.Context
3495
3496 c = Context()
3497 d = c.subtract(Decimal(1), Decimal(2))
3498 self.assertEqual(c.subtract(1, 2), d)
3499 self.assertEqual(c.subtract(Decimal(1), 2), d)
3500 self.assertEqual(c.subtract(1, Decimal(2)), d)
3501 self.assertRaises(TypeError, c.subtract, '1', 2)
3502 self.assertRaises(TypeError, c.subtract, 1, '2')
3503
3504 def test_to_eng_string(self):
3505 Decimal = self.decimal.Decimal
3506 Context = self.decimal.Context
3507
3508 c = Context()
3509 d = c.to_eng_string(Decimal(10))
3510 self.assertEqual(c.to_eng_string(10), d)
3511 self.assertRaises(TypeError, c.to_eng_string, '10')
3512
3513 def test_to_sci_string(self):
3514 Decimal = self.decimal.Decimal
3515 Context = self.decimal.Context
3516
3517 c = Context()
3518 d = c.to_sci_string(Decimal(10))
3519 self.assertEqual(c.to_sci_string(10), d)
3520 self.assertRaises(TypeError, c.to_sci_string, '10')
3521
3522 def test_to_integral_exact(self):
3523 Decimal = self.decimal.Decimal
3524 Context = self.decimal.Context
3525
3526 c = Context()
3527 d = c.to_integral_exact(Decimal(10))
3528 self.assertEqual(c.to_integral_exact(10), d)
3529 self.assertRaises(TypeError, c.to_integral_exact, '10')
3530
3531 def test_to_integral_value(self):
3532 Decimal = self.decimal.Decimal
3533 Context = self.decimal.Context
3534
3535 c = Context()
3536 d = c.to_integral_value(Decimal(10))
3537 self.assertEqual(c.to_integral_value(10), d)
3538 self.assertRaises(TypeError, c.to_integral_value, '10')
3539 self.assertRaises(TypeError, c.to_integral_value, 10, 'x')
3540
3541class CContextAPItests(ContextAPItests):
3542 decimal = C
3543class PyContextAPItests(ContextAPItests):
3544 decimal = P
3545
3546class ContextWithStatement(unittest.TestCase):
3547 # Can't do these as docstrings until Python 2.6
3548 # as doctest can't handle __future__ statements
3549
3550 def test_localcontext(self):
3551 # Use a copy of the current context in the block
3552 getcontext = self.decimal.getcontext
3553 localcontext = self.decimal.localcontext
3554
3555 orig_ctx = getcontext()
3556 with localcontext() as enter_ctx:
3557 set_ctx = getcontext()
3558 final_ctx = getcontext()
3559 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
3560 self.assertIsNot(orig_ctx, set_ctx, 'did not copy the context')
3561 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
3562
3563 def test_localcontextarg(self):
3564 # Use a copy of the supplied context in the block
3565 Context = self.decimal.Context
3566 getcontext = self.decimal.getcontext
3567 localcontext = self.decimal.localcontext
3568
3569 localcontext = self.decimal.localcontext
3570 orig_ctx = getcontext()
3571 new_ctx = Context(prec=42)
3572 with localcontext(new_ctx) as enter_ctx:
3573 set_ctx = getcontext()
3574 final_ctx = getcontext()
3575 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
3576 self.assertEqual(set_ctx.prec, new_ctx.prec, 'did not set correct context')
3577 self.assertIsNot(new_ctx, set_ctx, 'did not copy the context')
3578 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
3579
3580 def test_nested_with_statements(self):
3581 # Use a copy of the supplied context in the block
3582 Decimal = self.decimal.Decimal
3583 Context = self.decimal.Context
3584 getcontext = self.decimal.getcontext
3585 localcontext = self.decimal.localcontext
3586 Clamped = self.decimal.Clamped
3587 Overflow = self.decimal.Overflow
3588
3589 orig_ctx = getcontext()
3590 orig_ctx.clear_flags()
3591 new_ctx = Context(Emax=384)
3592 with localcontext() as c1:
3593 self.assertEqual(c1.flags, orig_ctx.flags)
3594 self.assertEqual(c1.traps, orig_ctx.traps)
3595 c1.traps[Clamped] = True
3596 c1.Emin = -383
3597 self.assertNotEqual(orig_ctx.Emin, -383)
3598 self.assertRaises(Clamped, c1.create_decimal, '0e-999')
3599 self.assertTrue(c1.flags[Clamped])
3600 with localcontext(new_ctx) as c2:
3601 self.assertEqual(c2.flags, new_ctx.flags)
3602 self.assertEqual(c2.traps, new_ctx.traps)
3603 self.assertRaises(Overflow, c2.power, Decimal('3.4e200'), 2)
3604 self.assertFalse(c2.flags[Clamped])
3605 self.assertTrue(c2.flags[Overflow])
3606 del c2
3607 self.assertFalse(c1.flags[Overflow])
3608 del c1
3609 self.assertNotEqual(orig_ctx.Emin, -383)
3610 self.assertFalse(orig_ctx.flags[Clamped])
3611 self.assertFalse(orig_ctx.flags[Overflow])
3612 self.assertFalse(new_ctx.flags[Clamped])
3613 self.assertFalse(new_ctx.flags[Overflow])
3614
3615 def test_with_statements_gc1(self):
3616 localcontext = self.decimal.localcontext
3617
3618 with localcontext() as c1:
3619 del c1
3620 with localcontext() as c2:
3621 del c2
3622 with localcontext() as c3:
3623 del c3
3624 with localcontext() as c4:
3625 del c4
3626
3627 def test_with_statements_gc2(self):
3628 localcontext = self.decimal.localcontext
3629
3630 with localcontext() as c1:
3631 with localcontext(c1) as c2:
3632 del c1
3633 with localcontext(c2) as c3:
3634 del c2
3635 with localcontext(c3) as c4:
3636 del c3
3637 del c4
3638
3639 def test_with_statements_gc3(self):
3640 Context = self.decimal.Context
3641 localcontext = self.decimal.localcontext
3642 getcontext = self.decimal.getcontext
3643 setcontext = self.decimal.setcontext
3644
3645 with localcontext() as c1:
3646 del c1
3647 n1 = Context(prec=1)
3648 setcontext(n1)
3649 with localcontext(n1) as c2:
3650 del n1
3651 self.assertEqual(c2.prec, 1)
3652 del c2
3653 n2 = Context(prec=2)
3654 setcontext(n2)
3655 del n2
3656 self.assertEqual(getcontext().prec, 2)
3657 n3 = Context(prec=3)
3658 setcontext(n3)
3659 self.assertEqual(getcontext().prec, 3)
3660 with localcontext(n3) as c3:
3661 del n3
3662 self.assertEqual(c3.prec, 3)
3663 del c3
3664 n4 = Context(prec=4)
3665 setcontext(n4)
3666 del n4
3667 self.assertEqual(getcontext().prec, 4)
3668 with localcontext() as c4:
3669 self.assertEqual(c4.prec, 4)
3670 del c4
3671
3672class CContextWithStatement(ContextWithStatement):
3673 decimal = C
3674class PyContextWithStatement(ContextWithStatement):
3675 decimal = P
3676
3677class ContextFlags(unittest.TestCase):
3678
3679 def test_flags_irrelevant(self):
3680 # check that the result (numeric result + flags raised) of an
3681 # arithmetic operation doesn't depend on the current flags
3682 Decimal = self.decimal.Decimal
3683 Context = self.decimal.Context
3684 Inexact = self.decimal.Inexact
3685 Rounded = self.decimal.Rounded
3686 Underflow = self.decimal.Underflow
3687 Clamped = self.decimal.Clamped
3688 Subnormal = self.decimal.Subnormal
Stefan Krah1919b7e2012-03-21 18:25:23 +01003689
3690 def raise_error(context, flag):
3691 if self.decimal == C:
3692 context.flags[flag] = True
3693 if context.traps[flag]:
3694 raise flag
3695 else:
3696 context._raise_error(flag)
3697
3698 context = Context(prec=9, Emin = -425000000, Emax = 425000000,
3699 rounding=ROUND_HALF_EVEN, traps=[], flags=[])
3700
3701 # operations that raise various flags, in the form (function, arglist)
3702 operations = [
3703 (context._apply, [Decimal("100E-425000010")]),
3704 (context.sqrt, [Decimal(2)]),
3705 (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]),
3706 (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]),
3707 (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]),
3708 ]
3709
3710 # try various flags individually, then a whole lot at once
3711 flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal],
3712 [Inexact, Rounded, Underflow, Clamped, Subnormal]]
3713
3714 for fn, args in operations:
3715 # find answer and flags raised using a clean context
3716 context.clear_flags()
3717 ans = fn(*args)
3718 flags = [k for k, v in context.flags.items() if v]
3719
3720 for extra_flags in flagsets:
3721 # set flags, before calling operation
3722 context.clear_flags()
3723 for flag in extra_flags:
3724 raise_error(context, flag)
3725 new_ans = fn(*args)
3726
3727 # flags that we expect to be set after the operation
3728 expected_flags = list(flags)
3729 for flag in extra_flags:
3730 if flag not in expected_flags:
3731 expected_flags.append(flag)
3732 expected_flags.sort(key=id)
3733
3734 # flags we actually got
3735 new_flags = [k for k,v in context.flags.items() if v]
3736 new_flags.sort(key=id)
3737
3738 self.assertEqual(ans, new_ans,
3739 "operation produces different answers depending on flags set: " +
3740 "expected %s, got %s." % (ans, new_ans))
3741 self.assertEqual(new_flags, expected_flags,
3742 "operation raises different flags depending on flags set: " +
3743 "expected %s, got %s" % (expected_flags, new_flags))
3744
3745 def test_flag_comparisons(self):
3746 Context = self.decimal.Context
3747 Inexact = self.decimal.Inexact
3748 Rounded = self.decimal.Rounded
3749
3750 c = Context()
3751
3752 # Valid SignalDict
3753 self.assertNotEqual(c.flags, c.traps)
3754 self.assertNotEqual(c.traps, c.flags)
3755
3756 c.flags = c.traps
3757 self.assertEqual(c.flags, c.traps)
3758 self.assertEqual(c.traps, c.flags)
3759
3760 c.flags[Rounded] = True
3761 c.traps = c.flags
3762 self.assertEqual(c.flags, c.traps)
3763 self.assertEqual(c.traps, c.flags)
3764
3765 d = {}
3766 d.update(c.flags)
3767 self.assertEqual(d, c.flags)
3768 self.assertEqual(c.flags, d)
3769
3770 d[Inexact] = True
3771 self.assertNotEqual(d, c.flags)
3772 self.assertNotEqual(c.flags, d)
3773
3774 # Invalid SignalDict
3775 d = {Inexact:False}
3776 self.assertNotEqual(d, c.flags)
3777 self.assertNotEqual(c.flags, d)
3778
3779 d = ["xyz"]
3780 self.assertNotEqual(d, c.flags)
3781 self.assertNotEqual(c.flags, d)
3782
3783 @requires_IEEE_754
3784 def test_float_operation(self):
3785 Decimal = self.decimal.Decimal
3786 FloatOperation = self.decimal.FloatOperation
3787 localcontext = self.decimal.localcontext
3788
3789 with localcontext() as c:
3790 ##### trap is off by default
3791 self.assertFalse(c.traps[FloatOperation])
3792
3793 # implicit conversion sets the flag
3794 c.clear_flags()
3795 self.assertEqual(Decimal(7.5), 7.5)
3796 self.assertTrue(c.flags[FloatOperation])
3797
3798 c.clear_flags()
3799 self.assertEqual(c.create_decimal(7.5), 7.5)
3800 self.assertTrue(c.flags[FloatOperation])
3801
3802 # explicit conversion does not set the flag
3803 c.clear_flags()
3804 x = Decimal.from_float(7.5)
3805 self.assertFalse(c.flags[FloatOperation])
3806 # comparison sets the flag
3807 self.assertEqual(x, 7.5)
3808 self.assertTrue(c.flags[FloatOperation])
3809
3810 c.clear_flags()
3811 x = c.create_decimal_from_float(7.5)
3812 self.assertFalse(c.flags[FloatOperation])
3813 self.assertEqual(x, 7.5)
3814 self.assertTrue(c.flags[FloatOperation])
3815
3816 ##### set the trap
3817 c.traps[FloatOperation] = True
3818
3819 # implicit conversion raises
3820 c.clear_flags()
3821 self.assertRaises(FloatOperation, Decimal, 7.5)
3822 self.assertTrue(c.flags[FloatOperation])
3823
3824 c.clear_flags()
3825 self.assertRaises(FloatOperation, c.create_decimal, 7.5)
3826 self.assertTrue(c.flags[FloatOperation])
3827
3828 # explicit conversion is silent
3829 c.clear_flags()
3830 x = Decimal.from_float(7.5)
3831 self.assertFalse(c.flags[FloatOperation])
3832
3833 c.clear_flags()
3834 x = c.create_decimal_from_float(7.5)
3835 self.assertFalse(c.flags[FloatOperation])
3836
3837 def test_float_comparison(self):
3838 Decimal = self.decimal.Decimal
3839 Context = self.decimal.Context
3840 FloatOperation = self.decimal.FloatOperation
3841 localcontext = self.decimal.localcontext
3842
3843 def assert_attr(a, b, attr, context, signal=None):
3844 context.clear_flags()
3845 f = getattr(a, attr)
3846 if signal == FloatOperation:
3847 self.assertRaises(signal, f, b)
3848 else:
3849 self.assertIs(f(b), True)
3850 self.assertTrue(context.flags[FloatOperation])
3851
3852 small_d = Decimal('0.25')
3853 big_d = Decimal('3.0')
3854 small_f = 0.25
3855 big_f = 3.0
3856
3857 zero_d = Decimal('0.0')
3858 neg_zero_d = Decimal('-0.0')
3859 zero_f = 0.0
3860 neg_zero_f = -0.0
3861
3862 inf_d = Decimal('Infinity')
3863 neg_inf_d = Decimal('-Infinity')
3864 inf_f = float('inf')
3865 neg_inf_f = float('-inf')
3866
3867 def doit(c, signal=None):
3868 # Order
3869 for attr in '__lt__', '__le__':
3870 assert_attr(small_d, big_f, attr, c, signal)
3871
3872 for attr in '__gt__', '__ge__':
3873 assert_attr(big_d, small_f, attr, c, signal)
3874
3875 # Equality
3876 assert_attr(small_d, small_f, '__eq__', c, None)
3877
3878 assert_attr(neg_zero_d, neg_zero_f, '__eq__', c, None)
3879 assert_attr(neg_zero_d, zero_f, '__eq__', c, None)
3880
3881 assert_attr(zero_d, neg_zero_f, '__eq__', c, None)
3882 assert_attr(zero_d, zero_f, '__eq__', c, None)
3883
3884 assert_attr(neg_inf_d, neg_inf_f, '__eq__', c, None)
3885 assert_attr(inf_d, inf_f, '__eq__', c, None)
3886
3887 # Inequality
3888 assert_attr(small_d, big_f, '__ne__', c, None)
3889
3890 assert_attr(Decimal('0.1'), 0.1, '__ne__', c, None)
3891
3892 assert_attr(neg_inf_d, inf_f, '__ne__', c, None)
3893 assert_attr(inf_d, neg_inf_f, '__ne__', c, None)
3894
3895 assert_attr(Decimal('NaN'), float('nan'), '__ne__', c, None)
3896
3897 def test_containers(c, signal=None):
3898 c.clear_flags()
3899 s = set([100.0, Decimal('100.0')])
3900 self.assertEqual(len(s), 1)
3901 self.assertTrue(c.flags[FloatOperation])
3902
3903 c.clear_flags()
3904 if signal:
3905 self.assertRaises(signal, sorted, [1.0, Decimal('10.0')])
3906 else:
3907 s = sorted([10.0, Decimal('10.0')])
3908 self.assertTrue(c.flags[FloatOperation])
3909
3910 c.clear_flags()
3911 b = 10.0 in [Decimal('10.0'), 1.0]
3912 self.assertTrue(c.flags[FloatOperation])
3913
3914 c.clear_flags()
3915 b = 10.0 in {Decimal('10.0'):'a', 1.0:'b'}
3916 self.assertTrue(c.flags[FloatOperation])
3917
3918 nc = Context()
3919 with localcontext(nc) as c:
3920 self.assertFalse(c.traps[FloatOperation])
3921 doit(c, signal=None)
3922 test_containers(c, signal=None)
3923
3924 c.traps[FloatOperation] = True
3925 doit(c, signal=FloatOperation)
3926 test_containers(c, signal=FloatOperation)
3927
3928 def test_float_operation_default(self):
3929 Decimal = self.decimal.Decimal
3930 Context = self.decimal.Context
3931 Inexact = self.decimal.Inexact
3932 FloatOperation= self.decimal.FloatOperation
3933
3934 context = Context()
3935 self.assertFalse(context.flags[FloatOperation])
3936 self.assertFalse(context.traps[FloatOperation])
3937
3938 context.clear_traps()
3939 context.traps[Inexact] = True
3940 context.traps[FloatOperation] = True
3941 self.assertTrue(context.traps[FloatOperation])
3942 self.assertTrue(context.traps[Inexact])
3943
3944class CContextFlags(ContextFlags):
3945 decimal = C
3946class PyContextFlags(ContextFlags):
3947 decimal = P
3948
3949class SpecialContexts(unittest.TestCase):
3950 """Test the context templates."""
3951
3952 def test_context_templates(self):
3953 BasicContext = self.decimal.BasicContext
3954 ExtendedContext = self.decimal.ExtendedContext
3955 getcontext = self.decimal.getcontext
3956 setcontext = self.decimal.setcontext
3957 InvalidOperation = self.decimal.InvalidOperation
3958 DivisionByZero = self.decimal.DivisionByZero
3959 Overflow = self.decimal.Overflow
3960 Underflow = self.decimal.Underflow
3961 Clamped = self.decimal.Clamped
3962
3963 assert_signals(self, BasicContext, 'traps',
3964 [InvalidOperation, DivisionByZero, Overflow, Underflow, Clamped]
3965 )
3966
3967 savecontext = getcontext().copy()
3968 basic_context_prec = BasicContext.prec
3969 extended_context_prec = ExtendedContext.prec
3970
3971 ex = None
3972 try:
3973 BasicContext.prec = ExtendedContext.prec = 441
3974 for template in BasicContext, ExtendedContext:
3975 setcontext(template)
3976 c = getcontext()
3977 self.assertIsNot(c, template)
3978 self.assertEqual(c.prec, 441)
3979 except Exception as e:
3980 ex = e.__class__
3981 finally:
3982 BasicContext.prec = basic_context_prec
3983 ExtendedContext.prec = extended_context_prec
3984 setcontext(savecontext)
3985 if ex:
3986 raise ex
3987
3988 def test_default_context(self):
3989 DefaultContext = self.decimal.DefaultContext
3990 BasicContext = self.decimal.BasicContext
3991 ExtendedContext = self.decimal.ExtendedContext
3992 getcontext = self.decimal.getcontext
3993 setcontext = self.decimal.setcontext
3994 InvalidOperation = self.decimal.InvalidOperation
3995 DivisionByZero = self.decimal.DivisionByZero
3996 Overflow = self.decimal.Overflow
3997
3998 self.assertEqual(BasicContext.prec, 9)
3999 self.assertEqual(ExtendedContext.prec, 9)
4000
4001 assert_signals(self, DefaultContext, 'traps',
4002 [InvalidOperation, DivisionByZero, Overflow]
4003 )
4004
4005 savecontext = getcontext().copy()
4006 default_context_prec = DefaultContext.prec
4007
4008 ex = None
4009 try:
4010 c = getcontext()
4011 saveprec = c.prec
4012
4013 DefaultContext.prec = 961
4014 c = getcontext()
4015 self.assertEqual(c.prec, saveprec)
4016
4017 setcontext(DefaultContext)
4018 c = getcontext()
4019 self.assertIsNot(c, DefaultContext)
4020 self.assertEqual(c.prec, 961)
4021 except Exception as e:
4022 ex = e.__class__
4023 finally:
4024 DefaultContext.prec = default_context_prec
4025 setcontext(savecontext)
4026 if ex:
4027 raise ex
4028
4029class CSpecialContexts(SpecialContexts):
4030 decimal = C
4031class PySpecialContexts(SpecialContexts):
4032 decimal = P
4033
4034class ContextInputValidation(unittest.TestCase):
4035
4036 def test_invalid_context(self):
4037 Context = self.decimal.Context
4038 DefaultContext = self.decimal.DefaultContext
4039
4040 c = DefaultContext.copy()
4041
4042 # prec, Emax
4043 for attr in ['prec', 'Emax']:
4044 setattr(c, attr, 999999)
4045 self.assertEqual(getattr(c, attr), 999999)
4046 self.assertRaises(ValueError, setattr, c, attr, -1)
4047 self.assertRaises(TypeError, setattr, c, attr, 'xyz')
4048
4049 # Emin
4050 setattr(c, 'Emin', -999999)
4051 self.assertEqual(getattr(c, 'Emin'), -999999)
4052 self.assertRaises(ValueError, setattr, c, 'Emin', 1)
4053 self.assertRaises(TypeError, setattr, c, 'Emin', (1,2,3))
4054
Stefan Krah1919b7e2012-03-21 18:25:23 +01004055 self.assertRaises(TypeError, setattr, c, 'rounding', -1)
4056 self.assertRaises(TypeError, setattr, c, 'rounding', 9)
4057 self.assertRaises(TypeError, setattr, c, 'rounding', 1.0)
4058 self.assertRaises(TypeError, setattr, c, 'rounding', 'xyz')
4059
4060 # capitals, clamp
4061 for attr in ['capitals', 'clamp']:
4062 self.assertRaises(ValueError, setattr, c, attr, -1)
4063 self.assertRaises(ValueError, setattr, c, attr, 2)
4064 self.assertRaises(TypeError, setattr, c, attr, [1,2,3])
4065
4066 # Invalid attribute
4067 self.assertRaises(AttributeError, setattr, c, 'emax', 100)
4068
4069 # Invalid signal dict
4070 self.assertRaises(TypeError, setattr, c, 'flags', [])
4071 self.assertRaises(KeyError, setattr, c, 'flags', {})
4072 self.assertRaises(KeyError, setattr, c, 'traps',
4073 {'InvalidOperation':0})
4074
4075 # Attributes cannot be deleted
4076 for attr in ['prec', 'Emax', 'Emin', 'rounding', 'capitals', 'clamp',
4077 'flags', 'traps']:
4078 self.assertRaises(AttributeError, c.__delattr__, attr)
4079
4080 # Invalid attributes
4081 self.assertRaises(TypeError, getattr, c, 9)
4082 self.assertRaises(TypeError, setattr, c, 9)
4083
4084 # Invalid values in constructor
4085 self.assertRaises(TypeError, Context, rounding=999999)
4086 self.assertRaises(TypeError, Context, rounding='xyz')
4087 self.assertRaises(ValueError, Context, clamp=2)
4088 self.assertRaises(ValueError, Context, capitals=-1)
4089 self.assertRaises(KeyError, Context, flags=["P"])
4090 self.assertRaises(KeyError, Context, traps=["Q"])
4091
4092 # Type error in conversion
4093 self.assertRaises(TypeError, Context, flags=(0,1))
4094 self.assertRaises(TypeError, Context, traps=(1,0))
4095
4096class CContextInputValidation(ContextInputValidation):
4097 decimal = C
4098class PyContextInputValidation(ContextInputValidation):
4099 decimal = P
4100
4101class ContextSubclassing(unittest.TestCase):
4102
4103 def test_context_subclassing(self):
4104 decimal = self.decimal
4105 Decimal = decimal.Decimal
4106 Context = decimal.Context
Stefan Krah1919b7e2012-03-21 18:25:23 +01004107 Clamped = decimal.Clamped
4108 DivisionByZero = decimal.DivisionByZero
4109 Inexact = decimal.Inexact
4110 Overflow = decimal.Overflow
4111 Rounded = decimal.Rounded
4112 Subnormal = decimal.Subnormal
4113 Underflow = decimal.Underflow
4114 InvalidOperation = decimal.InvalidOperation
4115
4116 class MyContext(Context):
4117 def __init__(self, prec=None, rounding=None, Emin=None, Emax=None,
4118 capitals=None, clamp=None, flags=None,
4119 traps=None):
4120 Context.__init__(self)
4121 if prec is not None:
4122 self.prec = prec
4123 if rounding is not None:
4124 self.rounding = rounding
4125 if Emin is not None:
4126 self.Emin = Emin
4127 if Emax is not None:
4128 self.Emax = Emax
4129 if capitals is not None:
4130 self.capitals = capitals
4131 if clamp is not None:
4132 self.clamp = clamp
4133 if flags is not None:
4134 if isinstance(flags, list):
4135 flags = {v:(v in flags) for v in OrderedSignals[decimal] + flags}
4136 self.flags = flags
4137 if traps is not None:
4138 if isinstance(traps, list):
4139 traps = {v:(v in traps) for v in OrderedSignals[decimal] + traps}
4140 self.traps = traps
4141
4142 c = Context()
4143 d = MyContext()
4144 for attr in ('prec', 'rounding', 'Emin', 'Emax', 'capitals', 'clamp',
4145 'flags', 'traps'):
4146 self.assertEqual(getattr(c, attr), getattr(d, attr))
4147
4148 # prec
4149 self.assertRaises(ValueError, MyContext, **{'prec':-1})
4150 c = MyContext(prec=1)
4151 self.assertEqual(c.prec, 1)
4152 self.assertRaises(InvalidOperation, c.quantize, Decimal('9e2'), 0)
4153
4154 # rounding
4155 self.assertRaises(TypeError, MyContext, **{'rounding':'XYZ'})
4156 c = MyContext(rounding=ROUND_DOWN, prec=1)
4157 self.assertEqual(c.rounding, ROUND_DOWN)
4158 self.assertEqual(c.plus(Decimal('9.9')), 9)
4159
4160 # Emin
4161 self.assertRaises(ValueError, MyContext, **{'Emin':5})
4162 c = MyContext(Emin=-1, prec=1)
4163 self.assertEqual(c.Emin, -1)
4164 x = c.add(Decimal('1e-99'), Decimal('2.234e-2000'))
4165 self.assertEqual(x, Decimal('0.0'))
4166 for signal in (Inexact, Underflow, Subnormal, Rounded, Clamped):
4167 self.assertTrue(c.flags[signal])
4168
4169 # Emax
4170 self.assertRaises(ValueError, MyContext, **{'Emax':-1})
4171 c = MyContext(Emax=1, prec=1)
4172 self.assertEqual(c.Emax, 1)
4173 self.assertRaises(Overflow, c.add, Decimal('1e99'), Decimal('2.234e2000'))
4174 if self.decimal == C:
4175 for signal in (Inexact, Overflow, Rounded):
4176 self.assertTrue(c.flags[signal])
4177
4178 # capitals
4179 self.assertRaises(ValueError, MyContext, **{'capitals':-1})
4180 c = MyContext(capitals=0)
4181 self.assertEqual(c.capitals, 0)
4182 x = c.create_decimal('1E222')
4183 self.assertEqual(c.to_sci_string(x), '1e+222')
4184
4185 # clamp
4186 self.assertRaises(ValueError, MyContext, **{'clamp':2})
4187 c = MyContext(clamp=1, Emax=99)
4188 self.assertEqual(c.clamp, 1)
4189 x = c.plus(Decimal('1e99'))
4190 self.assertEqual(str(x), '1.000000000000000000000000000E+99')
4191
4192 # flags
4193 self.assertRaises(TypeError, MyContext, **{'flags':'XYZ'})
4194 c = MyContext(flags=[Rounded, DivisionByZero])
4195 for signal in (Rounded, DivisionByZero):
4196 self.assertTrue(c.flags[signal])
4197 c.clear_flags()
4198 for signal in OrderedSignals[decimal]:
4199 self.assertFalse(c.flags[signal])
4200
4201 # traps
4202 self.assertRaises(TypeError, MyContext, **{'traps':'XYZ'})
4203 c = MyContext(traps=[Rounded, DivisionByZero])
4204 for signal in (Rounded, DivisionByZero):
4205 self.assertTrue(c.traps[signal])
4206 c.clear_traps()
4207 for signal in OrderedSignals[decimal]:
4208 self.assertFalse(c.traps[signal])
4209
4210class CContextSubclassing(ContextSubclassing):
4211 decimal = C
4212class PyContextSubclassing(ContextSubclassing):
4213 decimal = P
4214
4215@skip_if_extra_functionality
4216class CheckAttributes(unittest.TestCase):
4217
4218 def test_module_attributes(self):
4219
4220 # Architecture dependent context limits
4221 self.assertEqual(C.MAX_PREC, P.MAX_PREC)
4222 self.assertEqual(C.MAX_EMAX, P.MAX_EMAX)
4223 self.assertEqual(C.MIN_EMIN, P.MIN_EMIN)
4224 self.assertEqual(C.MIN_ETINY, P.MIN_ETINY)
4225
4226 self.assertTrue(C.HAVE_THREADS is True or C.HAVE_THREADS is False)
4227 self.assertTrue(P.HAVE_THREADS is True or P.HAVE_THREADS is False)
4228
4229 self.assertEqual(C.__version__, P.__version__)
4230
Stefan Krahb578f8a2014-09-10 17:58:15 +02004231 self.assertEqual(dir(C), dir(P))
Stefan Krah1919b7e2012-03-21 18:25:23 +01004232
4233 def test_context_attributes(self):
4234
4235 x = [s for s in dir(C.Context()) if '__' in s or not s.startswith('_')]
4236 y = [s for s in dir(P.Context()) if '__' in s or not s.startswith('_')]
4237 self.assertEqual(set(x) - set(y), set())
4238
4239 def test_decimal_attributes(self):
4240
4241 x = [s for s in dir(C.Decimal(9)) if '__' in s or not s.startswith('_')]
4242 y = [s for s in dir(C.Decimal(9)) if '__' in s or not s.startswith('_')]
4243 self.assertEqual(set(x) - set(y), set())
4244
4245class Coverage(unittest.TestCase):
4246
4247 def test_adjusted(self):
4248 Decimal = self.decimal.Decimal
4249
4250 self.assertEqual(Decimal('1234e9999').adjusted(), 10002)
4251 # XXX raise?
4252 self.assertEqual(Decimal('nan').adjusted(), 0)
4253 self.assertEqual(Decimal('inf').adjusted(), 0)
4254
4255 def test_canonical(self):
4256 Decimal = self.decimal.Decimal
4257 getcontext = self.decimal.getcontext
4258
4259 x = Decimal(9).canonical()
4260 self.assertEqual(x, 9)
4261
4262 c = getcontext()
4263 x = c.canonical(Decimal(9))
4264 self.assertEqual(x, 9)
4265
4266 def test_context_repr(self):
4267 c = self.decimal.DefaultContext.copy()
4268
4269 c.prec = 425000000
4270 c.Emax = 425000000
4271 c.Emin = -425000000
Stefan Krah59a4a932013-01-16 12:58:59 +01004272 c.rounding = ROUND_HALF_DOWN
Stefan Krah1919b7e2012-03-21 18:25:23 +01004273 c.capitals = 0
4274 c.clamp = 1
4275 for sig in OrderedSignals[self.decimal]:
4276 c.flags[sig] = False
4277 c.traps[sig] = False
4278
4279 s = c.__repr__()
4280 t = "Context(prec=425000000, rounding=ROUND_HALF_DOWN, " \
4281 "Emin=-425000000, Emax=425000000, capitals=0, clamp=1, " \
4282 "flags=[], traps=[])"
4283 self.assertEqual(s, t)
4284
4285 def test_implicit_context(self):
4286 Decimal = self.decimal.Decimal
4287 localcontext = self.decimal.localcontext
4288
4289 with localcontext() as c:
4290 c.prec = 1
4291 c.Emax = 1
4292 c.Emin = -1
4293
4294 # abs
4295 self.assertEqual(abs(Decimal("-10")), 10)
4296 # add
4297 self.assertEqual(Decimal("7") + 1, 8)
4298 # divide
4299 self.assertEqual(Decimal("10") / 5, 2)
4300 # divide_int
4301 self.assertEqual(Decimal("10") // 7, 1)
4302 # fma
4303 self.assertEqual(Decimal("1.2").fma(Decimal("0.01"), 1), 1)
4304 self.assertIs(Decimal("NaN").fma(7, 1).is_nan(), True)
4305 # three arg power
4306 self.assertEqual(pow(Decimal(10), 2, 7), 2)
4307 # exp
4308 self.assertEqual(Decimal("1.01").exp(), 3)
4309 # is_normal
4310 self.assertIs(Decimal("0.01").is_normal(), False)
4311 # is_subnormal
4312 self.assertIs(Decimal("0.01").is_subnormal(), True)
4313 # ln
4314 self.assertEqual(Decimal("20").ln(), 3)
4315 # log10
4316 self.assertEqual(Decimal("20").log10(), 1)
4317 # logb
4318 self.assertEqual(Decimal("580").logb(), 2)
4319 # logical_invert
4320 self.assertEqual(Decimal("10").logical_invert(), 1)
4321 # minus
4322 self.assertEqual(-Decimal("-10"), 10)
4323 # multiply
4324 self.assertEqual(Decimal("2") * 4, 8)
4325 # next_minus
4326 self.assertEqual(Decimal("10").next_minus(), 9)
4327 # next_plus
4328 self.assertEqual(Decimal("10").next_plus(), Decimal('2E+1'))
4329 # normalize
4330 self.assertEqual(Decimal("-10").normalize(), Decimal('-1E+1'))
4331 # number_class
4332 self.assertEqual(Decimal("10").number_class(), '+Normal')
4333 # plus
4334 self.assertEqual(+Decimal("-1"), -1)
4335 # remainder
4336 self.assertEqual(Decimal("10") % 7, 3)
4337 # subtract
4338 self.assertEqual(Decimal("10") - 7, 3)
4339 # to_integral_exact
4340 self.assertEqual(Decimal("1.12345").to_integral_exact(), 1)
4341
4342 # Boolean functions
4343 self.assertTrue(Decimal("1").is_canonical())
4344 self.assertTrue(Decimal("1").is_finite())
4345 self.assertTrue(Decimal("1").is_finite())
4346 self.assertTrue(Decimal("snan").is_snan())
4347 self.assertTrue(Decimal("-1").is_signed())
4348 self.assertTrue(Decimal("0").is_zero())
4349 self.assertTrue(Decimal("0").is_zero())
4350
4351 # Copy
4352 with localcontext() as c:
4353 c.prec = 10000
4354 x = 1228 ** 1523
4355 y = -Decimal(x)
4356
4357 z = y.copy_abs()
4358 self.assertEqual(z, x)
4359
4360 z = y.copy_negate()
4361 self.assertEqual(z, x)
4362
4363 z = y.copy_sign(Decimal(1))
4364 self.assertEqual(z, x)
4365
4366 def test_divmod(self):
4367 Decimal = self.decimal.Decimal
4368 localcontext = self.decimal.localcontext
4369 InvalidOperation = self.decimal.InvalidOperation
4370 DivisionByZero = self.decimal.DivisionByZero
4371
4372 with localcontext() as c:
4373 q, r = divmod(Decimal("10912837129"), 1001)
4374 self.assertEqual(q, Decimal('10901935'))
4375 self.assertEqual(r, Decimal('194'))
4376
4377 q, r = divmod(Decimal("NaN"), 7)
4378 self.assertTrue(q.is_nan() and r.is_nan())
4379
4380 c.traps[InvalidOperation] = False
4381 q, r = divmod(Decimal("NaN"), 7)
4382 self.assertTrue(q.is_nan() and r.is_nan())
4383
4384 c.traps[InvalidOperation] = False
4385 c.clear_flags()
4386 q, r = divmod(Decimal("inf"), Decimal("inf"))
4387 self.assertTrue(q.is_nan() and r.is_nan())
4388 self.assertTrue(c.flags[InvalidOperation])
4389
4390 c.clear_flags()
4391 q, r = divmod(Decimal("inf"), 101)
4392 self.assertTrue(q.is_infinite() and r.is_nan())
4393 self.assertTrue(c.flags[InvalidOperation])
4394
4395 c.clear_flags()
4396 q, r = divmod(Decimal(0), 0)
4397 self.assertTrue(q.is_nan() and r.is_nan())
4398 self.assertTrue(c.flags[InvalidOperation])
4399
4400 c.traps[DivisionByZero] = False
4401 c.clear_flags()
4402 q, r = divmod(Decimal(11), 0)
4403 self.assertTrue(q.is_infinite() and r.is_nan())
4404 self.assertTrue(c.flags[InvalidOperation] and
4405 c.flags[DivisionByZero])
4406
4407 def test_power(self):
4408 Decimal = self.decimal.Decimal
4409 localcontext = self.decimal.localcontext
4410 Overflow = self.decimal.Overflow
4411 Rounded = self.decimal.Rounded
4412
4413 with localcontext() as c:
4414 c.prec = 3
4415 c.clear_flags()
4416 self.assertEqual(Decimal("1.0") ** 100, Decimal('1.00'))
4417 self.assertTrue(c.flags[Rounded])
4418
4419 c.prec = 1
4420 c.Emax = 1
4421 c.Emin = -1
4422 c.clear_flags()
4423 c.traps[Overflow] = False
4424 self.assertEqual(Decimal(10000) ** Decimal("0.5"), Decimal('inf'))
4425 self.assertTrue(c.flags[Overflow])
4426
4427 def test_quantize(self):
4428 Decimal = self.decimal.Decimal
4429 localcontext = self.decimal.localcontext
4430 InvalidOperation = self.decimal.InvalidOperation
4431
4432 with localcontext() as c:
4433 c.prec = 1
4434 c.Emax = 1
4435 c.Emin = -1
4436 c.traps[InvalidOperation] = False
4437 x = Decimal(99).quantize(Decimal("1e1"))
4438 self.assertTrue(x.is_nan())
4439
4440 def test_radix(self):
4441 Decimal = self.decimal.Decimal
4442 getcontext = self.decimal.getcontext
4443
4444 c = getcontext()
4445 self.assertEqual(Decimal("1").radix(), 10)
4446 self.assertEqual(c.radix(), 10)
4447
4448 def test_rop(self):
4449 Decimal = self.decimal.Decimal
4450
4451 for attr in ('__radd__', '__rsub__', '__rmul__', '__rtruediv__',
4452 '__rdivmod__', '__rmod__', '__rfloordiv__', '__rpow__'):
4453 self.assertIs(getattr(Decimal("1"), attr)("xyz"), NotImplemented)
4454
4455 def test_round(self):
4456 # Python3 behavior: round() returns Decimal
4457 Decimal = self.decimal.Decimal
Stefan Krahe95dfc52018-06-03 18:40:00 +02004458 localcontext = self.decimal.localcontext
Stefan Krah1919b7e2012-03-21 18:25:23 +01004459
Stefan Krahe95dfc52018-06-03 18:40:00 +02004460 with localcontext() as c:
4461 c.prec = 28
Stefan Krah1919b7e2012-03-21 18:25:23 +01004462
Stefan Krahe95dfc52018-06-03 18:40:00 +02004463 self.assertEqual(str(Decimal("9.99").__round__()), "10")
4464 self.assertEqual(str(Decimal("9.99e-5").__round__()), "0")
4465 self.assertEqual(str(Decimal("1.23456789").__round__(5)), "1.23457")
4466 self.assertEqual(str(Decimal("1.2345").__round__(10)), "1.2345000000")
4467 self.assertEqual(str(Decimal("1.2345").__round__(-10)), "0E+10")
Stefan Krah1919b7e2012-03-21 18:25:23 +01004468
Stefan Krahe95dfc52018-06-03 18:40:00 +02004469 self.assertRaises(TypeError, Decimal("1.23").__round__, "5")
4470 self.assertRaises(TypeError, Decimal("1.23").__round__, 5, 8)
Stefan Krah1919b7e2012-03-21 18:25:23 +01004471
4472 def test_create_decimal(self):
4473 c = self.decimal.Context()
4474 self.assertRaises(ValueError, c.create_decimal, ["%"])
4475
4476 def test_int(self):
4477 Decimal = self.decimal.Decimal
4478 localcontext = self.decimal.localcontext
4479
4480 with localcontext() as c:
4481 c.prec = 9999
4482 x = Decimal(1221**1271) / 10**3923
4483 self.assertEqual(int(x), 1)
4484 self.assertEqual(x.to_integral(), 2)
4485
4486 def test_copy(self):
4487 Context = self.decimal.Context
4488
4489 c = Context()
4490 c.prec = 10000
4491 x = -(1172 ** 1712)
4492
4493 y = c.copy_abs(x)
4494 self.assertEqual(y, -x)
4495
4496 y = c.copy_negate(x)
4497 self.assertEqual(y, -x)
4498
4499 y = c.copy_sign(x, 1)
4500 self.assertEqual(y, -x)
4501
4502class CCoverage(Coverage):
4503 decimal = C
4504class PyCoverage(Coverage):
4505 decimal = P
4506
4507class PyFunctionality(unittest.TestCase):
4508 """Extra functionality in decimal.py"""
4509
Stefan Krah1919b7e2012-03-21 18:25:23 +01004510 def test_py_alternate_formatting(self):
4511 # triples giving a format, a Decimal, and the expected result
4512 Decimal = P.Decimal
4513 localcontext = P.localcontext
4514
4515 test_values = [
4516 # Issue 7094: Alternate formatting (specified by #)
4517 ('.0e', '1.0', '1e+0'),
4518 ('#.0e', '1.0', '1.e+0'),
4519 ('.0f', '1.0', '1'),
4520 ('#.0f', '1.0', '1.'),
4521 ('g', '1.1', '1.1'),
4522 ('#g', '1.1', '1.1'),
4523 ('.0g', '1', '1'),
4524 ('#.0g', '1', '1.'),
4525 ('.0%', '1.0', '100%'),
4526 ('#.0%', '1.0', '100.%'),
4527 ]
4528 for fmt, d, result in test_values:
4529 self.assertEqual(format(Decimal(d), fmt), result)
4530
4531class PyWhitebox(unittest.TestCase):
4532 """White box testing for decimal.py"""
4533
4534 def test_py_exact_power(self):
4535 # Rarely exercised lines in _power_exact.
4536 Decimal = P.Decimal
4537 localcontext = P.localcontext
4538
4539 with localcontext() as c:
4540 c.prec = 8
4541 x = Decimal(2**16) ** Decimal("-0.5")
4542 self.assertEqual(x, Decimal('0.00390625'))
4543
4544 x = Decimal(2**16) ** Decimal("-0.6")
4545 self.assertEqual(x, Decimal('0.0012885819'))
4546
4547 x = Decimal("256e7") ** Decimal("-0.5")
4548
4549 x = Decimal(152587890625) ** Decimal('-0.0625')
4550 self.assertEqual(x, Decimal("0.2"))
4551
4552 x = Decimal("152587890625e7") ** Decimal('-0.0625')
4553
4554 x = Decimal(5**2659) ** Decimal('-0.0625')
4555
4556 c.prec = 1
4557 x = Decimal("152587890625") ** Decimal('-0.5')
4558 c.prec = 201
4559 x = Decimal(2**578) ** Decimal("-0.5")
4560
4561 def test_py_immutability_operations(self):
Terry Jan Reedy0f847642013-03-11 18:34:00 -04004562 # Do operations and check that it didn't change internal objects.
Stefan Krah1919b7e2012-03-21 18:25:23 +01004563 Decimal = P.Decimal
4564 DefaultContext = P.DefaultContext
4565 setcontext = P.setcontext
4566
4567 c = DefaultContext.copy()
4568 c.traps = dict((s, 0) for s in OrderedSignals[P])
4569 setcontext(c)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004570
4571 d1 = Decimal('-25e55')
4572 b1 = Decimal('-25e55')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004573 d2 = Decimal('33e+33')
4574 b2 = Decimal('33e+33')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004575
4576 def checkSameDec(operation, useOther=False):
4577 if useOther:
4578 eval("d1." + operation + "(d2)")
4579 self.assertEqual(d1._sign, b1._sign)
4580 self.assertEqual(d1._int, b1._int)
4581 self.assertEqual(d1._exp, b1._exp)
4582 self.assertEqual(d2._sign, b2._sign)
4583 self.assertEqual(d2._int, b2._int)
4584 self.assertEqual(d2._exp, b2._exp)
4585 else:
4586 eval("d1." + operation + "()")
4587 self.assertEqual(d1._sign, b1._sign)
4588 self.assertEqual(d1._int, b1._int)
4589 self.assertEqual(d1._exp, b1._exp)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004590
4591 Decimal(d1)
4592 self.assertEqual(d1._sign, b1._sign)
4593 self.assertEqual(d1._int, b1._int)
4594 self.assertEqual(d1._exp, b1._exp)
4595
4596 checkSameDec("__abs__")
4597 checkSameDec("__add__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004598 checkSameDec("__divmod__", True)
Christian Heimes77c02eb2008-02-09 02:18:51 +00004599 checkSameDec("__eq__", True)
4600 checkSameDec("__ne__", True)
4601 checkSameDec("__le__", True)
4602 checkSameDec("__lt__", True)
4603 checkSameDec("__ge__", True)
4604 checkSameDec("__gt__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004605 checkSameDec("__float__")
4606 checkSameDec("__floordiv__", True)
4607 checkSameDec("__hash__")
4608 checkSameDec("__int__")
Christian Heimes969fe572008-01-25 11:23:10 +00004609 checkSameDec("__trunc__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004610 checkSameDec("__mod__", True)
4611 checkSameDec("__mul__", True)
4612 checkSameDec("__neg__")
Jack Diederich4dafcc42006-11-28 19:15:13 +00004613 checkSameDec("__bool__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004614 checkSameDec("__pos__")
4615 checkSameDec("__pow__", True)
4616 checkSameDec("__radd__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004617 checkSameDec("__rdivmod__", True)
4618 checkSameDec("__repr__")
4619 checkSameDec("__rfloordiv__", True)
4620 checkSameDec("__rmod__", True)
4621 checkSameDec("__rmul__", True)
4622 checkSameDec("__rpow__", True)
4623 checkSameDec("__rsub__", True)
4624 checkSameDec("__str__")
4625 checkSameDec("__sub__", True)
4626 checkSameDec("__truediv__", True)
4627 checkSameDec("adjusted")
4628 checkSameDec("as_tuple")
4629 checkSameDec("compare", True)
4630 checkSameDec("max", True)
4631 checkSameDec("min", True)
4632 checkSameDec("normalize")
4633 checkSameDec("quantize", True)
4634 checkSameDec("remainder_near", True)
4635 checkSameDec("same_quantum", True)
4636 checkSameDec("sqrt")
4637 checkSameDec("to_eng_string")
4638 checkSameDec("to_integral")
4639
Stefan Krah1919b7e2012-03-21 18:25:23 +01004640 def test_py_decimal_id(self):
4641 Decimal = P.Decimal
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004642
Stefan Krah1919b7e2012-03-21 18:25:23 +01004643 d = Decimal(45)
4644 e = Decimal(d)
4645 self.assertEqual(str(e), '45')
4646 self.assertNotEqual(id(d), id(e))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004647
Stefan Krah1919b7e2012-03-21 18:25:23 +01004648 def test_py_rescale(self):
4649 # Coverage
4650 Decimal = P.Decimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01004651 localcontext = P.localcontext
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004652
Stefan Krah1919b7e2012-03-21 18:25:23 +01004653 with localcontext() as c:
4654 x = Decimal("NaN")._rescale(3, ROUND_UP)
4655 self.assertTrue(x.is_nan())
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004656
Stefan Krah1919b7e2012-03-21 18:25:23 +01004657 def test_py__round(self):
4658 # Coverage
4659 Decimal = P.Decimal
Christian Heimes0348fb62008-03-26 12:55:56 +00004660
Stefan Krah1919b7e2012-03-21 18:25:23 +01004661 self.assertRaises(ValueError, Decimal("3.1234")._round, 0, ROUND_UP)
Mark Dickinsona2d1fe02009-10-29 12:23:02 +00004662
Stefan Krah1919b7e2012-03-21 18:25:23 +01004663class CFunctionality(unittest.TestCase):
4664 """Extra functionality in _decimal"""
Mark Dickinsona2d1fe02009-10-29 12:23:02 +00004665
Stefan Krah1919b7e2012-03-21 18:25:23 +01004666 @requires_extra_functionality
4667 def test_c_ieee_context(self):
4668 # issue 8786: Add support for IEEE 754 contexts to decimal module.
4669 IEEEContext = C.IEEEContext
4670 DECIMAL32 = C.DECIMAL32
4671 DECIMAL64 = C.DECIMAL64
4672 DECIMAL128 = C.DECIMAL128
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004673
Stefan Krah1919b7e2012-03-21 18:25:23 +01004674 def assert_rest(self, context):
4675 self.assertEqual(context.clamp, 1)
4676 assert_signals(self, context, 'traps', [])
4677 assert_signals(self, context, 'flags', [])
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004678
Stefan Krah1919b7e2012-03-21 18:25:23 +01004679 c = IEEEContext(DECIMAL32)
4680 self.assertEqual(c.prec, 7)
4681 self.assertEqual(c.Emax, 96)
4682 self.assertEqual(c.Emin, -95)
4683 assert_rest(self, c)
Raymond Hettinger82417ca2009-02-03 03:54:28 +00004684
Stefan Krah1919b7e2012-03-21 18:25:23 +01004685 c = IEEEContext(DECIMAL64)
4686 self.assertEqual(c.prec, 16)
4687 self.assertEqual(c.Emax, 384)
4688 self.assertEqual(c.Emin, -383)
4689 assert_rest(self, c)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004690
Stefan Krah1919b7e2012-03-21 18:25:23 +01004691 c = IEEEContext(DECIMAL128)
4692 self.assertEqual(c.prec, 34)
4693 self.assertEqual(c.Emax, 6144)
4694 self.assertEqual(c.Emin, -6143)
4695 assert_rest(self, c)
Raymond Hettinger5548be22004-07-05 18:49:38 +00004696
Stefan Krah1919b7e2012-03-21 18:25:23 +01004697 # Invalid values
4698 self.assertRaises(OverflowError, IEEEContext, 2**63)
4699 self.assertRaises(ValueError, IEEEContext, -1)
4700 self.assertRaises(ValueError, IEEEContext, 1024)
Mark Dickinson825fce32009-09-07 18:08:12 +00004701
Stefan Krah1919b7e2012-03-21 18:25:23 +01004702 @requires_extra_functionality
4703 def test_c_context(self):
4704 Context = C.Context
Christian Heimes969fe572008-01-25 11:23:10 +00004705
Stefan Krah1919b7e2012-03-21 18:25:23 +01004706 c = Context(flags=C.DecClamped, traps=C.DecRounded)
4707 self.assertEqual(c._flags, C.DecClamped)
4708 self.assertEqual(c._traps, C.DecRounded)
Raymond Hettinger771ed762009-01-03 19:20:32 +00004709
Stefan Krah1919b7e2012-03-21 18:25:23 +01004710 @requires_extra_functionality
4711 def test_constants(self):
4712 # Condition flags
4713 cond = (
4714 C.DecClamped, C.DecConversionSyntax, C.DecDivisionByZero,
4715 C.DecDivisionImpossible, C.DecDivisionUndefined,
4716 C.DecFpuError, C.DecInexact, C.DecInvalidContext,
4717 C.DecInvalidOperation, C.DecMallocError,
4718 C.DecFloatOperation, C.DecOverflow, C.DecRounded,
4719 C.DecSubnormal, C.DecUnderflow
Raymond Hettinger771ed762009-01-03 19:20:32 +00004720 )
Stefan Krah1919b7e2012-03-21 18:25:23 +01004721
4722 # IEEEContext
4723 self.assertEqual(C.DECIMAL32, 32)
4724 self.assertEqual(C.DECIMAL64, 64)
4725 self.assertEqual(C.DECIMAL128, 128)
4726 self.assertEqual(C.IEEE_CONTEXT_MAX_BITS, 512)
4727
Stefan Krah1919b7e2012-03-21 18:25:23 +01004728 # Conditions
4729 for i, v in enumerate(cond):
4730 self.assertEqual(v, 1<<i)
4731
4732 self.assertEqual(C.DecIEEEInvalidOperation,
4733 C.DecConversionSyntax|
4734 C.DecDivisionImpossible|
4735 C.DecDivisionUndefined|
4736 C.DecFpuError|
4737 C.DecInvalidContext|
4738 C.DecInvalidOperation|
4739 C.DecMallocError)
4740
4741 self.assertEqual(C.DecErrors,
4742 C.DecIEEEInvalidOperation|
4743 C.DecDivisionByZero)
4744
4745 self.assertEqual(C.DecTraps,
4746 C.DecErrors|C.DecOverflow|C.DecUnderflow)
4747
4748class CWhitebox(unittest.TestCase):
4749 """Whitebox testing for _decimal"""
4750
4751 def test_bignum(self):
4752 # Not exactly whitebox, but too slow with pydecimal.
4753
4754 Decimal = C.Decimal
4755 localcontext = C.localcontext
4756
4757 b1 = 10**35
4758 b2 = 10**36
4759 with localcontext() as c:
4760 c.prec = 1000000
4761 for i in range(5):
4762 a = random.randrange(b1, b2)
4763 b = random.randrange(1000, 1200)
4764 x = a ** b
4765 y = Decimal(a) ** Decimal(b)
4766 self.assertEqual(x, y)
4767
4768 def test_invalid_construction(self):
4769 self.assertRaises(TypeError, C.Decimal, 9, "xyz")
4770
4771 def test_c_input_restriction(self):
4772 # Too large for _decimal to be converted exactly
4773 Decimal = C.Decimal
4774 InvalidOperation = C.InvalidOperation
4775 Context = C.Context
4776 localcontext = C.localcontext
4777
4778 with localcontext(Context()):
4779 self.assertRaises(InvalidOperation, Decimal,
4780 "1e9999999999999999999")
4781
4782 def test_c_context_repr(self):
4783 # This test is _decimal-only because flags are not printed
4784 # in the same order.
4785 DefaultContext = C.DefaultContext
4786 FloatOperation = C.FloatOperation
Stefan Krah1919b7e2012-03-21 18:25:23 +01004787
4788 c = DefaultContext.copy()
4789
4790 c.prec = 425000000
4791 c.Emax = 425000000
4792 c.Emin = -425000000
4793 c.rounding = ROUND_HALF_DOWN
4794 c.capitals = 0
4795 c.clamp = 1
4796 for sig in OrderedSignals[C]:
4797 c.flags[sig] = True
4798 c.traps[sig] = True
4799 c.flags[FloatOperation] = True
4800 c.traps[FloatOperation] = True
4801
4802 s = c.__repr__()
4803 t = "Context(prec=425000000, rounding=ROUND_HALF_DOWN, " \
4804 "Emin=-425000000, Emax=425000000, capitals=0, clamp=1, " \
4805 "flags=[Clamped, InvalidOperation, DivisionByZero, Inexact, " \
4806 "FloatOperation, Overflow, Rounded, Subnormal, Underflow], " \
4807 "traps=[Clamped, InvalidOperation, DivisionByZero, Inexact, " \
4808 "FloatOperation, Overflow, Rounded, Subnormal, Underflow])"
4809 self.assertEqual(s, t)
4810
4811 def test_c_context_errors(self):
4812 Context = C.Context
4813 InvalidOperation = C.InvalidOperation
4814 Overflow = C.Overflow
4815 FloatOperation = C.FloatOperation
4816 localcontext = C.localcontext
4817 getcontext = C.getcontext
4818 setcontext = C.setcontext
4819 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
4820
4821 c = Context()
4822
4823 # SignalDict: input validation
4824 self.assertRaises(KeyError, c.flags.__setitem__, 801, 0)
4825 self.assertRaises(KeyError, c.traps.__setitem__, 801, 0)
4826 self.assertRaises(ValueError, c.flags.__delitem__, Overflow)
4827 self.assertRaises(ValueError, c.traps.__delitem__, InvalidOperation)
4828 self.assertRaises(TypeError, setattr, c, 'flags', ['x'])
4829 self.assertRaises(TypeError, setattr, c,'traps', ['y'])
4830 self.assertRaises(KeyError, setattr, c, 'flags', {0:1})
4831 self.assertRaises(KeyError, setattr, c, 'traps', {0:1})
4832
4833 # Test assignment from a signal dict with the correct length but
4834 # one invalid key.
4835 d = c.flags.copy()
4836 del d[FloatOperation]
4837 d["XYZ"] = 91283719
4838 self.assertRaises(KeyError, setattr, c, 'flags', d)
4839 self.assertRaises(KeyError, setattr, c, 'traps', d)
4840
4841 # Input corner cases
4842 int_max = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
4843 gt_max_emax = 10**18 if HAVE_CONFIG_64 else 10**9
4844
4845 # prec, Emax, Emin
4846 for attr in ['prec', 'Emax']:
4847 self.assertRaises(ValueError, setattr, c, attr, gt_max_emax)
4848 self.assertRaises(ValueError, setattr, c, 'Emin', -gt_max_emax)
4849
4850 # prec, Emax, Emin in context constructor
4851 self.assertRaises(ValueError, Context, prec=gt_max_emax)
4852 self.assertRaises(ValueError, Context, Emax=gt_max_emax)
4853 self.assertRaises(ValueError, Context, Emin=-gt_max_emax)
4854
4855 # Overflow in conversion
4856 self.assertRaises(OverflowError, Context, prec=int_max+1)
4857 self.assertRaises(OverflowError, Context, Emax=int_max+1)
4858 self.assertRaises(OverflowError, Context, Emin=-int_max-2)
Stefan Krah1919b7e2012-03-21 18:25:23 +01004859 self.assertRaises(OverflowError, Context, clamp=int_max+1)
4860 self.assertRaises(OverflowError, Context, capitals=int_max+1)
4861
4862 # OverflowError, general ValueError
4863 for attr in ('prec', 'Emin', 'Emax', 'capitals', 'clamp'):
4864 self.assertRaises(OverflowError, setattr, c, attr, int_max+1)
4865 self.assertRaises(OverflowError, setattr, c, attr, -int_max-2)
4866 if sys.platform != 'win32':
4867 self.assertRaises(ValueError, setattr, c, attr, int_max)
4868 self.assertRaises(ValueError, setattr, c, attr, -int_max-1)
4869
Stefan Krah1919b7e2012-03-21 18:25:23 +01004870 # OverflowError: _unsafe_setprec, _unsafe_setemin, _unsafe_setemax
4871 if C.MAX_PREC == 425000000:
4872 self.assertRaises(OverflowError, getattr(c, '_unsafe_setprec'),
4873 int_max+1)
4874 self.assertRaises(OverflowError, getattr(c, '_unsafe_setemax'),
4875 int_max+1)
4876 self.assertRaises(OverflowError, getattr(c, '_unsafe_setemin'),
4877 -int_max-2)
4878
4879 # ValueError: _unsafe_setprec, _unsafe_setemin, _unsafe_setemax
4880 if C.MAX_PREC == 425000000:
4881 self.assertRaises(ValueError, getattr(c, '_unsafe_setprec'), 0)
4882 self.assertRaises(ValueError, getattr(c, '_unsafe_setprec'),
4883 1070000001)
4884 self.assertRaises(ValueError, getattr(c, '_unsafe_setemax'), -1)
4885 self.assertRaises(ValueError, getattr(c, '_unsafe_setemax'),
4886 1070000001)
4887 self.assertRaises(ValueError, getattr(c, '_unsafe_setemin'),
4888 -1070000001)
4889 self.assertRaises(ValueError, getattr(c, '_unsafe_setemin'), 1)
4890
4891 # capitals, clamp
4892 for attr in ['capitals', 'clamp']:
4893 self.assertRaises(ValueError, setattr, c, attr, -1)
4894 self.assertRaises(ValueError, setattr, c, attr, 2)
4895 self.assertRaises(TypeError, setattr, c, attr, [1,2,3])
4896 if HAVE_CONFIG_64:
4897 self.assertRaises(ValueError, setattr, c, attr, 2**32)
4898 self.assertRaises(ValueError, setattr, c, attr, 2**32+1)
4899
4900 # Invalid local context
4901 self.assertRaises(TypeError, exec, 'with localcontext("xyz"): pass',
4902 locals())
Stefan Krah040e3112012-12-15 22:33:33 +01004903 self.assertRaises(TypeError, exec,
4904 'with localcontext(context=getcontext()): pass',
4905 locals())
Stefan Krah1919b7e2012-03-21 18:25:23 +01004906
4907 # setcontext
4908 saved_context = getcontext()
4909 self.assertRaises(TypeError, setcontext, "xyz")
4910 setcontext(saved_context)
4911
Stefan Krah59a4a932013-01-16 12:58:59 +01004912 def test_rounding_strings_interned(self):
4913
4914 self.assertIs(C.ROUND_UP, P.ROUND_UP)
4915 self.assertIs(C.ROUND_DOWN, P.ROUND_DOWN)
4916 self.assertIs(C.ROUND_CEILING, P.ROUND_CEILING)
4917 self.assertIs(C.ROUND_FLOOR, P.ROUND_FLOOR)
4918 self.assertIs(C.ROUND_HALF_UP, P.ROUND_HALF_UP)
4919 self.assertIs(C.ROUND_HALF_DOWN, P.ROUND_HALF_DOWN)
4920 self.assertIs(C.ROUND_HALF_EVEN, P.ROUND_HALF_EVEN)
4921 self.assertIs(C.ROUND_05UP, P.ROUND_05UP)
4922
Stefan Krah1919b7e2012-03-21 18:25:23 +01004923 @requires_extra_functionality
4924 def test_c_context_errors_extra(self):
4925 Context = C.Context
4926 InvalidOperation = C.InvalidOperation
4927 Overflow = C.Overflow
4928 localcontext = C.localcontext
4929 getcontext = C.getcontext
4930 setcontext = C.setcontext
4931 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
4932
4933 c = Context()
4934
4935 # Input corner cases
4936 int_max = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
4937
4938 # OverflowError, general ValueError
4939 self.assertRaises(OverflowError, setattr, c, '_allcr', int_max+1)
4940 self.assertRaises(OverflowError, setattr, c, '_allcr', -int_max-2)
4941 if sys.platform != 'win32':
4942 self.assertRaises(ValueError, setattr, c, '_allcr', int_max)
4943 self.assertRaises(ValueError, setattr, c, '_allcr', -int_max-1)
4944
4945 # OverflowError, general TypeError
4946 for attr in ('_flags', '_traps'):
4947 self.assertRaises(OverflowError, setattr, c, attr, int_max+1)
4948 self.assertRaises(OverflowError, setattr, c, attr, -int_max-2)
4949 if sys.platform != 'win32':
4950 self.assertRaises(TypeError, setattr, c, attr, int_max)
4951 self.assertRaises(TypeError, setattr, c, attr, -int_max-1)
4952
4953 # _allcr
4954 self.assertRaises(ValueError, setattr, c, '_allcr', -1)
4955 self.assertRaises(ValueError, setattr, c, '_allcr', 2)
4956 self.assertRaises(TypeError, setattr, c, '_allcr', [1,2,3])
4957 if HAVE_CONFIG_64:
4958 self.assertRaises(ValueError, setattr, c, '_allcr', 2**32)
4959 self.assertRaises(ValueError, setattr, c, '_allcr', 2**32+1)
4960
4961 # _flags, _traps
4962 for attr in ['_flags', '_traps']:
4963 self.assertRaises(TypeError, setattr, c, attr, 999999)
4964 self.assertRaises(TypeError, setattr, c, attr, 'x')
4965
4966 def test_c_valid_context(self):
4967 # These tests are for code coverage in _decimal.
4968 DefaultContext = C.DefaultContext
Stefan Krah1919b7e2012-03-21 18:25:23 +01004969 Clamped = C.Clamped
4970 Underflow = C.Underflow
4971 Inexact = C.Inexact
4972 Rounded = C.Rounded
4973 Subnormal = C.Subnormal
4974
4975 c = DefaultContext.copy()
4976
4977 # Exercise all getters and setters
4978 c.prec = 34
4979 c.rounding = ROUND_HALF_UP
4980 c.Emax = 3000
4981 c.Emin = -3000
4982 c.capitals = 1
4983 c.clamp = 0
4984
4985 self.assertEqual(c.prec, 34)
4986 self.assertEqual(c.rounding, ROUND_HALF_UP)
4987 self.assertEqual(c.Emin, -3000)
4988 self.assertEqual(c.Emax, 3000)
4989 self.assertEqual(c.capitals, 1)
4990 self.assertEqual(c.clamp, 0)
4991
4992 self.assertEqual(c.Etiny(), -3033)
4993 self.assertEqual(c.Etop(), 2967)
4994
4995 # Exercise all unsafe setters
4996 if C.MAX_PREC == 425000000:
4997 c._unsafe_setprec(999999999)
4998 c._unsafe_setemax(999999999)
4999 c._unsafe_setemin(-999999999)
5000 self.assertEqual(c.prec, 999999999)
5001 self.assertEqual(c.Emax, 999999999)
5002 self.assertEqual(c.Emin, -999999999)
5003
5004 @requires_extra_functionality
5005 def test_c_valid_context_extra(self):
5006 DefaultContext = C.DefaultContext
5007
5008 c = DefaultContext.copy()
5009 self.assertEqual(c._allcr, 1)
5010 c._allcr = 0
5011 self.assertEqual(c._allcr, 0)
5012
5013 def test_c_round(self):
5014 # Restricted input.
5015 Decimal = C.Decimal
5016 InvalidOperation = C.InvalidOperation
5017 localcontext = C.localcontext
5018 MAX_EMAX = C.MAX_EMAX
5019 MIN_ETINY = C.MIN_ETINY
5020 int_max = 2**63-1 if C.MAX_PREC > 425000000 else 2**31-1
5021
5022 with localcontext() as c:
5023 c.traps[InvalidOperation] = True
5024 self.assertRaises(InvalidOperation, Decimal("1.23").__round__,
5025 -int_max-1)
5026 self.assertRaises(InvalidOperation, Decimal("1.23").__round__,
5027 int_max)
5028 self.assertRaises(InvalidOperation, Decimal("1").__round__,
5029 int(MAX_EMAX+1))
5030 self.assertRaises(C.InvalidOperation, Decimal("1").__round__,
5031 -int(MIN_ETINY-1))
5032 self.assertRaises(OverflowError, Decimal("1.23").__round__,
5033 -int_max-2)
5034 self.assertRaises(OverflowError, Decimal("1.23").__round__,
5035 int_max+1)
5036
5037 def test_c_format(self):
5038 # Restricted input
5039 Decimal = C.Decimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01005040 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
5041
5042 self.assertRaises(TypeError, Decimal(1).__format__, "=10.10", [], 9)
5043 self.assertRaises(TypeError, Decimal(1).__format__, "=10.10", 9)
5044 self.assertRaises(TypeError, Decimal(1).__format__, [])
5045
Stefan Kraheb8c4512013-01-24 15:22:33 +01005046 self.assertRaises(ValueError, Decimal(1).__format__, "<>=10.10")
5047 maxsize = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
5048 self.assertRaises(ValueError, Decimal("1.23456789").__format__,
5049 "=%d.1" % maxsize)
Stefan Krah1919b7e2012-03-21 18:25:23 +01005050
5051 def test_c_integral(self):
5052 Decimal = C.Decimal
5053 Inexact = C.Inexact
Stefan Krah1919b7e2012-03-21 18:25:23 +01005054 localcontext = C.localcontext
5055
5056 x = Decimal(10)
5057 self.assertEqual(x.to_integral(), 10)
5058 self.assertRaises(TypeError, x.to_integral, '10')
5059 self.assertRaises(TypeError, x.to_integral, 10, 'x')
5060 self.assertRaises(TypeError, x.to_integral, 10)
5061
5062 self.assertEqual(x.to_integral_value(), 10)
5063 self.assertRaises(TypeError, x.to_integral_value, '10')
5064 self.assertRaises(TypeError, x.to_integral_value, 10, 'x')
5065 self.assertRaises(TypeError, x.to_integral_value, 10)
5066
5067 self.assertEqual(x.to_integral_exact(), 10)
5068 self.assertRaises(TypeError, x.to_integral_exact, '10')
5069 self.assertRaises(TypeError, x.to_integral_exact, 10, 'x')
5070 self.assertRaises(TypeError, x.to_integral_exact, 10)
5071
5072 with localcontext() as c:
5073 x = Decimal("99999999999999999999999999.9").to_integral_value(ROUND_UP)
5074 self.assertEqual(x, Decimal('100000000000000000000000000'))
5075
5076 x = Decimal("99999999999999999999999999.9").to_integral_exact(ROUND_UP)
5077 self.assertEqual(x, Decimal('100000000000000000000000000'))
5078
5079 c.traps[Inexact] = True
5080 self.assertRaises(Inexact, Decimal("999.9").to_integral_exact, ROUND_UP)
5081
5082 def test_c_funcs(self):
5083 # Invalid arguments
5084 Decimal = C.Decimal
5085 InvalidOperation = C.InvalidOperation
5086 DivisionByZero = C.DivisionByZero
Stefan Krah1919b7e2012-03-21 18:25:23 +01005087 getcontext = C.getcontext
5088 localcontext = C.localcontext
5089
5090 self.assertEqual(Decimal('9.99e10').to_eng_string(), '99.9E+9')
5091
5092 self.assertRaises(TypeError, pow, Decimal(1), 2, "3")
5093 self.assertRaises(TypeError, Decimal(9).number_class, "x", "y")
5094 self.assertRaises(TypeError, Decimal(9).same_quantum, 3, "x", "y")
5095
Raymond Hettinger771ed762009-01-03 19:20:32 +00005096 self.assertRaises(
Stefan Krah1919b7e2012-03-21 18:25:23 +01005097 TypeError,
5098 Decimal("1.23456789").quantize, Decimal('1e-100000'), []
Raymond Hettinger771ed762009-01-03 19:20:32 +00005099 )
Stefan Krah1919b7e2012-03-21 18:25:23 +01005100 self.assertRaises(
5101 TypeError,
5102 Decimal("1.23456789").quantize, Decimal('1e-100000'), getcontext()
5103 )
5104 self.assertRaises(
5105 TypeError,
5106 Decimal("1.23456789").quantize, Decimal('1e-100000'), 10
5107 )
5108 self.assertRaises(
5109 TypeError,
5110 Decimal("1.23456789").quantize, Decimal('1e-100000'), ROUND_UP, 1000
5111 )
Raymond Hettinger771ed762009-01-03 19:20:32 +00005112
Stefan Krah1919b7e2012-03-21 18:25:23 +01005113 with localcontext() as c:
5114 c.clear_traps()
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00005115
Stefan Krah1919b7e2012-03-21 18:25:23 +01005116 # Invalid arguments
5117 self.assertRaises(TypeError, c.copy_sign, Decimal(1), "x", "y")
5118 self.assertRaises(TypeError, c.canonical, 200)
5119 self.assertRaises(TypeError, c.is_canonical, 200)
5120 self.assertRaises(TypeError, c.divmod, 9, 8, "x", "y")
5121 self.assertRaises(TypeError, c.same_quantum, 9, 3, "x", "y")
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00005122
Stefan Krah1919b7e2012-03-21 18:25:23 +01005123 self.assertEqual(str(c.canonical(Decimal(200))), '200')
5124 self.assertEqual(c.radix(), 10)
Raymond Hettinger0aeac102004-07-05 22:53:03 +00005125
Stefan Krah1919b7e2012-03-21 18:25:23 +01005126 c.traps[DivisionByZero] = True
5127 self.assertRaises(DivisionByZero, Decimal(9).__divmod__, 0)
5128 self.assertRaises(DivisionByZero, c.divmod, 9, 0)
5129 self.assertTrue(c.flags[InvalidOperation])
Raymond Hettinger955d2b22004-08-08 20:17:45 +00005130
Stefan Krah1919b7e2012-03-21 18:25:23 +01005131 c.clear_flags()
5132 c.traps[InvalidOperation] = True
5133 self.assertRaises(InvalidOperation, Decimal(9).__divmod__, 0)
5134 self.assertRaises(InvalidOperation, c.divmod, 9, 0)
5135 self.assertTrue(c.flags[DivisionByZero])
Mark Dickinsonb1d8e322010-05-22 18:35:36 +00005136
Stefan Krah1919b7e2012-03-21 18:25:23 +01005137 c.traps[InvalidOperation] = True
5138 c.prec = 2
5139 self.assertRaises(InvalidOperation, pow, Decimal(1000), 1, 501)
Mark Dickinson84230a12010-02-18 14:49:50 +00005140
Stefan Krah040e3112012-12-15 22:33:33 +01005141 def test_va_args_exceptions(self):
5142 Decimal = C.Decimal
5143 Context = C.Context
5144
5145 x = Decimal("10001111111")
5146
5147 for attr in ['exp', 'is_normal', 'is_subnormal', 'ln', 'log10',
5148 'logb', 'logical_invert', 'next_minus', 'next_plus',
5149 'normalize', 'number_class', 'sqrt', 'to_eng_string']:
5150 func = getattr(x, attr)
5151 self.assertRaises(TypeError, func, context="x")
5152 self.assertRaises(TypeError, func, "x", context=None)
5153
5154 for attr in ['compare', 'compare_signal', 'logical_and',
5155 'logical_or', 'max', 'max_mag', 'min', 'min_mag',
5156 'remainder_near', 'rotate', 'scaleb', 'shift']:
5157 func = getattr(x, attr)
5158 self.assertRaises(TypeError, func, context="x")
5159 self.assertRaises(TypeError, func, "x", context=None)
5160
5161 self.assertRaises(TypeError, x.to_integral, rounding=None, context=[])
5162 self.assertRaises(TypeError, x.to_integral, rounding={}, context=[])
5163 self.assertRaises(TypeError, x.to_integral, [], [])
5164
5165 self.assertRaises(TypeError, x.to_integral_value, rounding=None, context=[])
5166 self.assertRaises(TypeError, x.to_integral_value, rounding={}, context=[])
5167 self.assertRaises(TypeError, x.to_integral_value, [], [])
5168
5169 self.assertRaises(TypeError, x.to_integral_exact, rounding=None, context=[])
5170 self.assertRaises(TypeError, x.to_integral_exact, rounding={}, context=[])
5171 self.assertRaises(TypeError, x.to_integral_exact, [], [])
5172
5173 self.assertRaises(TypeError, x.fma, 1, 2, context="x")
5174 self.assertRaises(TypeError, x.fma, 1, 2, "x", context=None)
5175
5176 self.assertRaises(TypeError, x.quantize, 1, [], context=None)
5177 self.assertRaises(TypeError, x.quantize, 1, [], rounding=None)
5178 self.assertRaises(TypeError, x.quantize, 1, [], [])
5179
5180 c = Context()
5181 self.assertRaises(TypeError, c.power, 1, 2, mod="x")
5182 self.assertRaises(TypeError, c.power, 1, "x", mod=None)
5183 self.assertRaises(TypeError, c.power, "x", 2, mod=None)
5184
Stefan Krah1919b7e2012-03-21 18:25:23 +01005185 @requires_extra_functionality
5186 def test_c_context_templates(self):
5187 self.assertEqual(
5188 C.BasicContext._traps,
5189 C.DecIEEEInvalidOperation|C.DecDivisionByZero|C.DecOverflow|
5190 C.DecUnderflow|C.DecClamped
5191 )
5192 self.assertEqual(
5193 C.DefaultContext._traps,
5194 C.DecIEEEInvalidOperation|C.DecDivisionByZero|C.DecOverflow
5195 )
Mark Dickinson84230a12010-02-18 14:49:50 +00005196
Stefan Krah1919b7e2012-03-21 18:25:23 +01005197 @requires_extra_functionality
5198 def test_c_signal_dict(self):
Mark Dickinson84230a12010-02-18 14:49:50 +00005199
Stefan Krah1919b7e2012-03-21 18:25:23 +01005200 # SignalDict coverage
5201 Context = C.Context
5202 DefaultContext = C.DefaultContext
Mark Dickinson84230a12010-02-18 14:49:50 +00005203
Stefan Krah1919b7e2012-03-21 18:25:23 +01005204 InvalidOperation = C.InvalidOperation
Stefan Krah5fe1df12020-06-05 22:01:18 +02005205 FloatOperation = C.FloatOperation
Stefan Krah1919b7e2012-03-21 18:25:23 +01005206 DivisionByZero = C.DivisionByZero
5207 Overflow = C.Overflow
5208 Subnormal = C.Subnormal
5209 Underflow = C.Underflow
5210 Rounded = C.Rounded
5211 Inexact = C.Inexact
5212 Clamped = C.Clamped
Mark Dickinson84230a12010-02-18 14:49:50 +00005213
Stefan Krah1919b7e2012-03-21 18:25:23 +01005214 DecClamped = C.DecClamped
5215 DecInvalidOperation = C.DecInvalidOperation
5216 DecIEEEInvalidOperation = C.DecIEEEInvalidOperation
Mark Dickinson84230a12010-02-18 14:49:50 +00005217
Stefan Krah1919b7e2012-03-21 18:25:23 +01005218 def assertIsExclusivelySet(signal, signal_dict):
5219 for sig in signal_dict:
5220 if sig == signal:
5221 self.assertTrue(signal_dict[sig])
5222 else:
5223 self.assertFalse(signal_dict[sig])
Mark Dickinson84230a12010-02-18 14:49:50 +00005224
Stefan Krah1919b7e2012-03-21 18:25:23 +01005225 c = DefaultContext.copy()
Mark Dickinson84230a12010-02-18 14:49:50 +00005226
Stefan Krah1919b7e2012-03-21 18:25:23 +01005227 # Signal dict methods
5228 self.assertTrue(Overflow in c.traps)
5229 c.clear_traps()
5230 for k in c.traps.keys():
5231 c.traps[k] = True
5232 for v in c.traps.values():
5233 self.assertTrue(v)
5234 c.clear_traps()
5235 for k, v in c.traps.items():
5236 self.assertFalse(v)
Mark Dickinson84230a12010-02-18 14:49:50 +00005237
Stefan Krah1919b7e2012-03-21 18:25:23 +01005238 self.assertFalse(c.flags.get(Overflow))
5239 self.assertIs(c.flags.get("x"), None)
5240 self.assertEqual(c.flags.get("x", "y"), "y")
5241 self.assertRaises(TypeError, c.flags.get, "x", "y", "z")
Mark Dickinson84230a12010-02-18 14:49:50 +00005242
Stefan Krah1919b7e2012-03-21 18:25:23 +01005243 self.assertEqual(len(c.flags), len(c.traps))
5244 s = sys.getsizeof(c.flags)
5245 s = sys.getsizeof(c.traps)
5246 s = c.flags.__repr__()
Mark Dickinson84230a12010-02-18 14:49:50 +00005247
Stefan Krah1919b7e2012-03-21 18:25:23 +01005248 # Set flags/traps.
5249 c.clear_flags()
5250 c._flags = DecClamped
5251 self.assertTrue(c.flags[Clamped])
Mark Dickinson84230a12010-02-18 14:49:50 +00005252
Stefan Krah1919b7e2012-03-21 18:25:23 +01005253 c.clear_traps()
5254 c._traps = DecInvalidOperation
5255 self.assertTrue(c.traps[InvalidOperation])
Mark Dickinson84230a12010-02-18 14:49:50 +00005256
Stefan Krah1919b7e2012-03-21 18:25:23 +01005257 # Set flags/traps from dictionary.
5258 c.clear_flags()
5259 d = c.flags.copy()
5260 d[DivisionByZero] = True
5261 c.flags = d
5262 assertIsExclusivelySet(DivisionByZero, c.flags)
Mark Dickinson84230a12010-02-18 14:49:50 +00005263
Stefan Krah1919b7e2012-03-21 18:25:23 +01005264 c.clear_traps()
5265 d = c.traps.copy()
5266 d[Underflow] = True
5267 c.traps = d
5268 assertIsExclusivelySet(Underflow, c.traps)
Mark Dickinson84230a12010-02-18 14:49:50 +00005269
Stefan Krah1919b7e2012-03-21 18:25:23 +01005270 # Random constructors
5271 IntSignals = {
5272 Clamped: C.DecClamped,
5273 Rounded: C.DecRounded,
5274 Inexact: C.DecInexact,
5275 Subnormal: C.DecSubnormal,
5276 Underflow: C.DecUnderflow,
5277 Overflow: C.DecOverflow,
5278 DivisionByZero: C.DecDivisionByZero,
Stefan Krah5fe1df12020-06-05 22:01:18 +02005279 FloatOperation: C.DecFloatOperation,
Stefan Krah1919b7e2012-03-21 18:25:23 +01005280 InvalidOperation: C.DecIEEEInvalidOperation
5281 }
5282 IntCond = [
5283 C.DecDivisionImpossible, C.DecDivisionUndefined, C.DecFpuError,
5284 C.DecInvalidContext, C.DecInvalidOperation, C.DecMallocError,
5285 C.DecConversionSyntax,
5286 ]
Mark Dickinsonb455e582011-05-22 12:53:18 +01005287
Stefan Krah1919b7e2012-03-21 18:25:23 +01005288 lim = len(OrderedSignals[C])
5289 for r in range(lim):
5290 for t in range(lim):
Stefan Krah59a4a932013-01-16 12:58:59 +01005291 for round in RoundingModes:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005292 flags = random.sample(OrderedSignals[C], r)
5293 traps = random.sample(OrderedSignals[C], t)
5294 prec = random.randrange(1, 10000)
5295 emin = random.randrange(-10000, 0)
5296 emax = random.randrange(0, 10000)
5297 clamp = random.randrange(0, 2)
5298 caps = random.randrange(0, 2)
5299 cr = random.randrange(0, 2)
5300 c = Context(prec=prec, rounding=round, Emin=emin, Emax=emax,
5301 capitals=caps, clamp=clamp, flags=list(flags),
5302 traps=list(traps))
Mark Dickinson84230a12010-02-18 14:49:50 +00005303
Stefan Krah1919b7e2012-03-21 18:25:23 +01005304 self.assertEqual(c.prec, prec)
5305 self.assertEqual(c.rounding, round)
5306 self.assertEqual(c.Emin, emin)
5307 self.assertEqual(c.Emax, emax)
5308 self.assertEqual(c.capitals, caps)
5309 self.assertEqual(c.clamp, clamp)
Mark Dickinson84230a12010-02-18 14:49:50 +00005310
Stefan Krah1919b7e2012-03-21 18:25:23 +01005311 f = 0
5312 for x in flags:
5313 f |= IntSignals[x]
5314 self.assertEqual(c._flags, f)
Mark Dickinson84230a12010-02-18 14:49:50 +00005315
Stefan Krah1919b7e2012-03-21 18:25:23 +01005316 f = 0
5317 for x in traps:
5318 f |= IntSignals[x]
5319 self.assertEqual(c._traps, f)
Mark Dickinson84230a12010-02-18 14:49:50 +00005320
Stefan Krah1919b7e2012-03-21 18:25:23 +01005321 for cond in IntCond:
5322 c._flags = cond
5323 self.assertTrue(c._flags&DecIEEEInvalidOperation)
5324 assertIsExclusivelySet(InvalidOperation, c.flags)
Mark Dickinson84230a12010-02-18 14:49:50 +00005325
Stefan Krah1919b7e2012-03-21 18:25:23 +01005326 for cond in IntCond:
5327 c._traps = cond
5328 self.assertTrue(c._traps&DecIEEEInvalidOperation)
5329 assertIsExclusivelySet(InvalidOperation, c.traps)
Mark Dickinson84230a12010-02-18 14:49:50 +00005330
Stefan Krah1919b7e2012-03-21 18:25:23 +01005331 def test_invalid_override(self):
5332 Decimal = C.Decimal
Mark Dickinson84230a12010-02-18 14:49:50 +00005333
Stefan Krah1919b7e2012-03-21 18:25:23 +01005334 try:
5335 from locale import CHAR_MAX
5336 except ImportError:
Zachary Ware9fe6d862013-12-08 00:20:35 -06005337 self.skipTest('locale.CHAR_MAX not available')
Mark Dickinson84230a12010-02-18 14:49:50 +00005338
Stefan Krah1919b7e2012-03-21 18:25:23 +01005339 def make_grouping(lst):
5340 return ''.join([chr(x) for x in lst])
Mark Dickinson84230a12010-02-18 14:49:50 +00005341
Stefan Krah1919b7e2012-03-21 18:25:23 +01005342 def get_fmt(x, override=None, fmt='n'):
5343 return Decimal(x).__format__(fmt, override)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005344
Stefan Krah1919b7e2012-03-21 18:25:23 +01005345 invalid_grouping = {
5346 'decimal_point' : ',',
5347 'grouping' : make_grouping([255, 255, 0]),
5348 'thousands_sep' : ','
5349 }
5350 invalid_dot = {
5351 'decimal_point' : 'xxxxx',
5352 'grouping' : make_grouping([3, 3, 0]),
5353 'thousands_sep' : ','
5354 }
5355 invalid_sep = {
5356 'decimal_point' : '.',
5357 'grouping' : make_grouping([3, 3, 0]),
5358 'thousands_sep' : 'yyyyy'
5359 }
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005360
Stefan Krah1919b7e2012-03-21 18:25:23 +01005361 if CHAR_MAX == 127: # negative grouping in override
5362 self.assertRaises(ValueError, get_fmt, 12345,
5363 invalid_grouping, 'g')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005364
Stefan Krah1919b7e2012-03-21 18:25:23 +01005365 self.assertRaises(ValueError, get_fmt, 12345, invalid_dot, 'g')
5366 self.assertRaises(ValueError, get_fmt, 12345, invalid_sep, 'g')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005367
Stefan Krah0774e9b2012-04-05 15:21:58 +02005368 def test_exact_conversion(self):
5369 Decimal = C.Decimal
5370 localcontext = C.localcontext
5371 InvalidOperation = C.InvalidOperation
5372
5373 with localcontext() as c:
5374
5375 c.traps[InvalidOperation] = True
5376
5377 # Clamped
5378 x = "0e%d" % sys.maxsize
5379 self.assertRaises(InvalidOperation, Decimal, x)
5380
5381 x = "0e%d" % (-sys.maxsize-1)
5382 self.assertRaises(InvalidOperation, Decimal, x)
5383
5384 # Overflow
5385 x = "1e%d" % sys.maxsize
5386 self.assertRaises(InvalidOperation, Decimal, x)
5387
5388 # Underflow
5389 x = "1e%d" % (-sys.maxsize-1)
5390 self.assertRaises(InvalidOperation, Decimal, x)
5391
Stefan Krahff3eca02012-04-05 15:46:19 +02005392 def test_from_tuple(self):
5393 Decimal = C.Decimal
5394 localcontext = C.localcontext
5395 InvalidOperation = C.InvalidOperation
5396 Overflow = C.Overflow
5397 Underflow = C.Underflow
5398
5399 with localcontext() as c:
5400
5401 c.traps[InvalidOperation] = True
5402 c.traps[Overflow] = True
5403 c.traps[Underflow] = True
5404
5405 # SSIZE_MAX
5406 x = (1, (), sys.maxsize)
5407 self.assertEqual(str(c.create_decimal(x)), '-0E+999999')
5408 self.assertRaises(InvalidOperation, Decimal, x)
5409
5410 x = (1, (0, 1, 2), sys.maxsize)
5411 self.assertRaises(Overflow, c.create_decimal, x)
5412 self.assertRaises(InvalidOperation, Decimal, x)
5413
5414 # SSIZE_MIN
5415 x = (1, (), -sys.maxsize-1)
Stefan Krahe95dfc52018-06-03 18:40:00 +02005416 self.assertEqual(str(c.create_decimal(x)), '-0E-1000007')
Stefan Krahff3eca02012-04-05 15:46:19 +02005417 self.assertRaises(InvalidOperation, Decimal, x)
5418
5419 x = (1, (0, 1, 2), -sys.maxsize-1)
5420 self.assertRaises(Underflow, c.create_decimal, x)
5421 self.assertRaises(InvalidOperation, Decimal, x)
5422
5423 # OverflowError
5424 x = (1, (), sys.maxsize+1)
5425 self.assertRaises(OverflowError, c.create_decimal, x)
5426 self.assertRaises(OverflowError, Decimal, x)
5427
5428 x = (1, (), -sys.maxsize-2)
5429 self.assertRaises(OverflowError, c.create_decimal, x)
5430 self.assertRaises(OverflowError, Decimal, x)
5431
5432 # Specials
5433 x = (1, (), "N")
5434 self.assertEqual(str(Decimal(x)), '-sNaN')
5435 x = (1, (0,), "N")
5436 self.assertEqual(str(Decimal(x)), '-sNaN')
5437 x = (1, (0, 1), "N")
5438 self.assertEqual(str(Decimal(x)), '-sNaN1')
5439
Stefan Krah891ca9e2013-05-29 19:14:17 +02005440 def test_sizeof(self):
5441 Decimal = C.Decimal
5442 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
5443
5444 self.assertGreater(Decimal(0).__sizeof__(), 0)
5445 if HAVE_CONFIG_64:
5446 x = Decimal(10**(19*24)).__sizeof__()
5447 y = Decimal(10**(19*25)).__sizeof__()
5448 self.assertEqual(y, x+8)
5449 else:
5450 x = Decimal(10**(9*24)).__sizeof__()
5451 y = Decimal(10**(9*25)).__sizeof__()
5452 self.assertEqual(y, x+4)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005453
Stefan Krah8c126f12016-07-17 14:01:42 +02005454 def test_internal_use_of_overridden_methods(self):
5455 Decimal = C.Decimal
5456
5457 # Unsound subtyping
5458 class X(float):
5459 def as_integer_ratio(self):
5460 return 1
5461 def __abs__(self):
5462 return self
5463
5464 class Y(float):
5465 def __abs__(self):
5466 return [1]*200
5467
5468 class I(int):
5469 def bit_length(self):
5470 return [1]*200
5471
5472 class Z(float):
5473 def as_integer_ratio(self):
5474 return (I(1), I(1))
5475 def __abs__(self):
5476 return self
5477
5478 for cls in X, Y, Z:
5479 self.assertEqual(Decimal.from_float(cls(101.1)),
5480 Decimal.from_float(101.1))
5481
Stefan Krah90930e62020-02-21 01:52:47 +01005482 def test_maxcontext_exact_arith(self):
5483
5484 # Make sure that exact operations do not raise MemoryError due
5485 # to huge intermediate values when the context precision is very
5486 # large.
5487
5488 # The following functions fill the available precision and are
5489 # therefore not suitable for large precisions (by design of the
5490 # specification).
5491 MaxContextSkip = ['logical_invert', 'next_minus', 'next_plus',
5492 'logical_and', 'logical_or', 'logical_xor',
5493 'next_toward', 'rotate', 'shift']
5494
5495 Decimal = C.Decimal
5496 Context = C.Context
5497 localcontext = C.localcontext
5498
5499 # Here only some functions that are likely candidates for triggering a
5500 # MemoryError are tested. deccheck.py has an exhaustive test.
5501 maxcontext = Context(prec=C.MAX_PREC, Emin=C.MIN_EMIN, Emax=C.MAX_EMAX)
5502 with localcontext(maxcontext):
5503 self.assertEqual(Decimal(0).exp(), 1)
5504 self.assertEqual(Decimal(1).ln(), 0)
5505 self.assertEqual(Decimal(1).log10(), 0)
5506 self.assertEqual(Decimal(10**2).log10(), 2)
5507 self.assertEqual(Decimal(10**223).log10(), 223)
5508 self.assertEqual(Decimal(10**19).logb(), 19)
5509 self.assertEqual(Decimal(4).sqrt(), 2)
5510 self.assertEqual(Decimal("40E9").sqrt(), Decimal('2.0E+5'))
5511 self.assertEqual(divmod(Decimal(10), 3), (3, 1))
5512 self.assertEqual(Decimal(10) // 3, 3)
5513 self.assertEqual(Decimal(4) / 2, 2)
5514 self.assertEqual(Decimal(400) ** -1, Decimal('0.0025'))
5515
5516
Stefan Krah6b794b82014-05-01 17:42:33 +02005517@requires_docstrings
5518@unittest.skipUnless(C, "test requires C version")
Stefan Krah5de1f822014-05-01 15:53:42 +02005519class SignatureTest(unittest.TestCase):
5520 """Function signatures"""
5521
5522 def test_inspect_module(self):
5523 for attr in dir(P):
5524 if attr.startswith('_'):
5525 continue
5526 p_func = getattr(P, attr)
5527 c_func = getattr(C, attr)
5528 if (attr == 'Decimal' or attr == 'Context' or
5529 inspect.isfunction(p_func)):
5530 p_sig = inspect.signature(p_func)
5531 c_sig = inspect.signature(c_func)
5532
5533 # parameter names:
5534 c_names = list(c_sig.parameters.keys())
5535 p_names = [x for x in p_sig.parameters.keys() if not
5536 x.startswith('_')]
5537
5538 self.assertEqual(c_names, p_names,
5539 msg="parameter name mismatch in %s" % p_func)
5540
5541 c_kind = [x.kind for x in c_sig.parameters.values()]
5542 p_kind = [x[1].kind for x in p_sig.parameters.items() if not
5543 x[0].startswith('_')]
5544
5545 # parameters:
5546 if attr != 'setcontext':
5547 self.assertEqual(c_kind, p_kind,
5548 msg="parameter kind mismatch in %s" % p_func)
5549
5550 def test_inspect_types(self):
5551
5552 POS = inspect._ParameterKind.POSITIONAL_ONLY
5553 POS_KWD = inspect._ParameterKind.POSITIONAL_OR_KEYWORD
5554
5555 # Type heuristic (type annotations would help!):
5556 pdict = {C: {'other': C.Decimal(1),
5557 'third': C.Decimal(1),
5558 'x': C.Decimal(1),
5559 'y': C.Decimal(1),
5560 'z': C.Decimal(1),
5561 'a': C.Decimal(1),
5562 'b': C.Decimal(1),
5563 'c': C.Decimal(1),
5564 'exp': C.Decimal(1),
5565 'modulo': C.Decimal(1),
5566 'num': "1",
5567 'f': 1.0,
5568 'rounding': C.ROUND_HALF_UP,
5569 'context': C.getcontext()},
5570 P: {'other': P.Decimal(1),
5571 'third': P.Decimal(1),
5572 'a': P.Decimal(1),
5573 'b': P.Decimal(1),
5574 'c': P.Decimal(1),
5575 'exp': P.Decimal(1),
5576 'modulo': P.Decimal(1),
5577 'num': "1",
5578 'f': 1.0,
5579 'rounding': P.ROUND_HALF_UP,
5580 'context': P.getcontext()}}
5581
5582 def mkargs(module, sig):
5583 args = []
5584 kwargs = {}
5585 for name, param in sig.parameters.items():
5586 if name == 'self': continue
5587 if param.kind == POS:
5588 args.append(pdict[module][name])
5589 elif param.kind == POS_KWD:
5590 kwargs[name] = pdict[module][name]
5591 else:
5592 raise TestFailed("unexpected parameter kind")
5593 return args, kwargs
5594
5595 def tr(s):
5596 """The C Context docstrings use 'x' in order to prevent confusion
5597 with the article 'a' in the descriptions."""
5598 if s == 'x': return 'a'
5599 if s == 'y': return 'b'
5600 if s == 'z': return 'c'
5601 return s
5602
5603 def doit(ty):
5604 p_type = getattr(P, ty)
5605 c_type = getattr(C, ty)
5606 for attr in dir(p_type):
5607 if attr.startswith('_'):
5608 continue
5609 p_func = getattr(p_type, attr)
5610 c_func = getattr(c_type, attr)
5611 if inspect.isfunction(p_func):
5612 p_sig = inspect.signature(p_func)
5613 c_sig = inspect.signature(c_func)
5614
5615 # parameter names:
5616 p_names = list(p_sig.parameters.keys())
5617 c_names = [tr(x) for x in c_sig.parameters.keys()]
5618
5619 self.assertEqual(c_names, p_names,
5620 msg="parameter name mismatch in %s" % p_func)
5621
5622 p_kind = [x.kind for x in p_sig.parameters.values()]
5623 c_kind = [x.kind for x in c_sig.parameters.values()]
5624
5625 # 'self' parameter:
5626 self.assertIs(p_kind[0], POS_KWD)
5627 self.assertIs(c_kind[0], POS)
5628
5629 # remaining parameters:
5630 if ty == 'Decimal':
5631 self.assertEqual(c_kind[1:], p_kind[1:],
5632 msg="parameter kind mismatch in %s" % p_func)
5633 else: # Context methods are positional only in the C version.
5634 self.assertEqual(len(c_kind), len(p_kind),
5635 msg="parameter kind mismatch in %s" % p_func)
5636
5637 # Run the function:
5638 args, kwds = mkargs(C, c_sig)
5639 try:
5640 getattr(c_type(9), attr)(*args, **kwds)
Pablo Galindo293dd232019-11-19 21:34:03 +00005641 except Exception:
Stefan Krah5de1f822014-05-01 15:53:42 +02005642 raise TestFailed("invalid signature for %s: %s %s" % (c_func, args, kwds))
5643
5644 args, kwds = mkargs(P, p_sig)
5645 try:
5646 getattr(p_type(9), attr)(*args, **kwds)
Pablo Galindo293dd232019-11-19 21:34:03 +00005647 except Exception:
Stefan Krah5de1f822014-05-01 15:53:42 +02005648 raise TestFailed("invalid signature for %s: %s %s" % (p_func, args, kwds))
5649
5650 doit('Decimal')
5651 doit('Context')
5652
5653
Stefan Krah1919b7e2012-03-21 18:25:23 +01005654all_tests = [
5655 CExplicitConstructionTest, PyExplicitConstructionTest,
5656 CImplicitConstructionTest, PyImplicitConstructionTest,
5657 CFormatTest, PyFormatTest,
5658 CArithmeticOperatorsTest, PyArithmeticOperatorsTest,
5659 CThreadingTest, PyThreadingTest,
5660 CUsabilityTest, PyUsabilityTest,
5661 CPythonAPItests, PyPythonAPItests,
5662 CContextAPItests, PyContextAPItests,
5663 CContextWithStatement, PyContextWithStatement,
5664 CContextFlags, PyContextFlags,
5665 CSpecialContexts, PySpecialContexts,
5666 CContextInputValidation, PyContextInputValidation,
5667 CContextSubclassing, PyContextSubclassing,
5668 CCoverage, PyCoverage,
5669 CFunctionality, PyFunctionality,
5670 CWhitebox, PyWhitebox,
5671 CIBMTestCases, PyIBMTestCases,
5672]
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005673
Stefan Krah1919b7e2012-03-21 18:25:23 +01005674# Delete C tests if _decimal.so is not present.
5675if not C:
5676 all_tests = all_tests[1::2]
5677else:
5678 all_tests.insert(0, CheckAttributes)
Stefan Krah5de1f822014-05-01 15:53:42 +02005679 all_tests.insert(1, SignatureTest)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005680
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005681
Zachary Ware66f29282014-06-02 16:01:29 -05005682def test_main(arith=None, verbose=None, todo_tests=None, debug=None):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005683 """ Execute the tests.
5684
Raymond Hettingered20ad82004-09-04 20:09:13 +00005685 Runs all arithmetic tests if arith is True or if the "decimal" resource
5686 is enabled in regrtest.py
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005687 """
Raymond Hettingered20ad82004-09-04 20:09:13 +00005688
Stefan Krah1919b7e2012-03-21 18:25:23 +01005689 init(C)
5690 init(P)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005691 global TEST_ALL, DEBUG
Zachary Ware66f29282014-06-02 16:01:29 -05005692 TEST_ALL = arith if arith is not None else is_resource_enabled('decimal')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005693 DEBUG = debug
Raymond Hettingered20ad82004-09-04 20:09:13 +00005694
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005695 if todo_tests is None:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005696 test_classes = all_tests
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005697 else:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005698 test_classes = [CIBMTestCases, PyIBMTestCases]
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005699
5700 # Dynamically build custom test definition for each file in the test
5701 # directory and add the definitions to the DecimalTest class. This
5702 # procedure insures that new files do not get skipped.
5703 for filename in os.listdir(directory):
5704 if '.decTest' not in filename or filename.startswith("."):
5705 continue
5706 head, tail = filename.split('.')
5707 if todo_tests is not None and head not in todo_tests:
5708 continue
5709 tester = lambda self, f=filename: self.eval_file(directory + f)
Stefan Krah1919b7e2012-03-21 18:25:23 +01005710 setattr(CIBMTestCases, 'test_' + head, tester)
5711 setattr(PyIBMTestCases, 'test_' + head, tester)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005712 del filename, head, tail, tester
5713
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005714
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005715 try:
5716 run_unittest(*test_classes)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005717 if todo_tests is None:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005718 from doctest import IGNORE_EXCEPTION_DETAIL
5719 savedecimal = sys.modules['decimal']
5720 if C:
5721 sys.modules['decimal'] = C
5722 run_doctest(C, verbose, optionflags=IGNORE_EXCEPTION_DETAIL)
5723 sys.modules['decimal'] = P
5724 run_doctest(P, verbose)
5725 sys.modules['decimal'] = savedecimal
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005726 finally:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005727 if C: C.setcontext(ORIGINAL_CONTEXT[C])
5728 P.setcontext(ORIGINAL_CONTEXT[P])
5729 if not C:
5730 warnings.warn('C tests skipped: no module named _decimal.',
5731 UserWarning)
5732 if not orig_sys_decimal is sys.modules['decimal']:
5733 raise TestFailed("Internal error: unbalanced number of changes to "
5734 "sys.modules['decimal'].")
5735
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005736
5737if __name__ == '__main__':
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005738 import optparse
5739 p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]")
5740 p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test')
5741 p.add_option('--skip', '-s', action='store_true', help='skip over 90% of the arithmetic tests')
5742 (opt, args) = p.parse_args()
5743
5744 if opt.skip:
5745 test_main(arith=False, verbose=True)
5746 elif args:
5747 test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005748 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005749 test_main(arith=True, verbose=True)