blob: d6e170d1e4193d2b8c08f450c9708bba846ba23f [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
19 www2.hursley.ibm.com/decimal/dectest.zip
20
21This test module can be called from command line with one parameter (Arithmetic
22or Behaviour) to test each part, or without parameter to test both parts. If
23you're working through IDLE, you can import this test module and call test_main()
24with the corresponding argument.
25"""
26
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
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000030import pickle, copy
Christian Heimes400adb02008-02-01 08:12:03 +000031import unittest
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000032from decimal import *
Raymond Hettinger82417ca2009-02-03 03:54:28 +000033import numbers
Benjamin Petersone549ead2009-03-28 21:42:05 +000034from test.support import run_unittest, run_doctest, is_resource_enabled
Raymond Hettinger0aeac102004-07-05 22:53:03 +000035import random
Raymond Hettinger7e71fa52004-12-18 19:07:19 +000036try:
37 import threading
38except ImportError:
39 threading = None
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000040
Raymond Hettingerfed52962004-07-14 15:41:57 +000041# Useful Test Constant
Guido van Rossumc1f779c2007-07-03 08:25:58 +000042Signals = tuple(getcontext().flags.keys())
Raymond Hettingerfed52962004-07-14 15:41:57 +000043
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000044# Tests are built around these assumed context defaults.
45# test_main() restores the original context.
46def init():
47 global ORIGINAL_CONTEXT
48 ORIGINAL_CONTEXT = getcontext().copy()
Christian Heimes81ee3ef2008-05-04 22:42:01 +000049 DefaultTestContext = Context(
50 prec = 9,
51 rounding = ROUND_HALF_EVEN,
52 traps = dict.fromkeys(Signals, 0)
53 )
54 setcontext(DefaultTestContext)
Raymond Hettinger6ea48452004-07-03 12:26:21 +000055
Raymond Hettinger96798592010-04-02 16:58:27 +000056# decorator for skipping tests on non-IEEE 754 platforms
57requires_IEEE_754 = unittest.skipUnless(
58 float.__getformat__("double").startswith("IEEE"),
59 "test requires IEEE 754 doubles")
60
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000061TESTDATADIR = 'decimaltestdata'
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +000062if __name__ == '__main__':
63 file = sys.argv[0]
64else:
65 file = __file__
66testdir = os.path.dirname(file) or os.curdir
Raymond Hettinger267b8682005-03-27 10:47:39 +000067directory = testdir + os.sep + TESTDATADIR + os.sep
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000068
Raymond Hettinger267b8682005-03-27 10:47:39 +000069skip_expected = not os.path.isdir(directory)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000070
Mark Dickinson8a546532009-10-08 16:30:38 +000071# list of individual .decTest test ids that correspond to tests that
72# we're skipping for one reason or another.
73skipped_test_ids = [
74 'scbx164', # skipping apparently implementation-specific scaleb
75 'scbx165', # tests, pending clarification of scaleb rules.
76]
77
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000078# Make sure it actually raises errors when not expected and caught in flags
79# Slower, since it runs some things several times.
80EXTENDEDERRORTEST = False
81
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000082#Map the test cases' error names to the actual errors
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000083ErrorNames = {'clamped' : Clamped,
Raymond Hettinger5aa478b2004-07-09 10:02:53 +000084 'conversion_syntax' : InvalidOperation,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000085 'division_by_zero' : DivisionByZero,
Raymond Hettinger5aa478b2004-07-09 10:02:53 +000086 'division_impossible' : InvalidOperation,
87 'division_undefined' : InvalidOperation,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000088 'inexact' : Inexact,
Raymond Hettinger5aa478b2004-07-09 10:02:53 +000089 'invalid_context' : InvalidOperation,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000090 'invalid_operation' : InvalidOperation,
91 'overflow' : Overflow,
92 'rounded' : Rounded,
93 'subnormal' : Subnormal,
94 'underflow' : Underflow}
95
96
97def Nonfunction(*args):
98 """Doesn't do anything."""
99 return None
100
101RoundingDict = {'ceiling' : ROUND_CEILING, #Maps test-case names to roundings.
102 'down' : ROUND_DOWN,
103 'floor' : ROUND_FLOOR,
104 'half_down' : ROUND_HALF_DOWN,
105 'half_even' : ROUND_HALF_EVEN,
106 'half_up' : ROUND_HALF_UP,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000107 'up' : ROUND_UP,
108 '05up' : ROUND_05UP}
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000109
110# Name adapter to be able to change the Decimal and Context
111# interface without changing the test files from Cowlishaw
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000112nameAdapter = {'and':'logical_and',
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000113 'apply':'_apply',
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000114 'class':'number_class',
115 'comparesig':'compare_signal',
116 'comparetotal':'compare_total',
117 'comparetotmag':'compare_total_mag',
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000118 'copy':'copy_decimal',
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000119 'copyabs':'copy_abs',
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000120 'copynegate':'copy_negate',
121 'copysign':'copy_sign',
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000122 'divideint':'divide_int',
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000123 'invert':'logical_invert',
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000124 'iscanonical':'is_canonical',
125 'isfinite':'is_finite',
126 'isinfinite':'is_infinite',
127 'isnan':'is_nan',
128 'isnormal':'is_normal',
129 'isqnan':'is_qnan',
130 'issigned':'is_signed',
131 'issnan':'is_snan',
132 'issubnormal':'is_subnormal',
133 'iszero':'is_zero',
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000134 'maxmag':'max_mag',
135 'minmag':'min_mag',
136 'nextminus':'next_minus',
137 'nextplus':'next_plus',
138 'nexttoward':'next_toward',
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000139 'or':'logical_or',
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000140 'reduce':'normalize',
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000141 'remaindernear':'remainder_near',
142 'samequantum':'same_quantum',
143 'squareroot':'sqrt',
144 'toeng':'to_eng_string',
145 'tointegral':'to_integral_value',
146 'tointegralx':'to_integral_exact',
147 'tosci':'to_sci_string',
148 'xor':'logical_xor',
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000149 }
150
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000151# The following functions return True/False rather than a Decimal instance
152
153LOGICAL_FUNCTIONS = (
154 'is_canonical',
155 'is_finite',
156 'is_infinite',
157 'is_nan',
158 'is_normal',
159 'is_qnan',
160 'is_signed',
161 'is_snan',
162 'is_subnormal',
163 'is_zero',
164 'same_quantum',
165 )
166
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000167# For some operations (currently exp, ln, log10, power), the decNumber
168# reference implementation imposes additional restrictions on the
169# context and operands. These restrictions are not part of the
170# specification; however, the effect of these restrictions does show
171# up in some of the testcases. We skip testcases that violate these
172# restrictions, since Decimal behaves differently from decNumber for
173# these testcases so these testcases would otherwise fail.
174
175decNumberRestricted = ('power', 'ln', 'log10', 'exp')
176DEC_MAX_MATH = 999999
177def outside_decNumber_bounds(v, context):
178 if (context.prec > DEC_MAX_MATH or
179 context.Emax > DEC_MAX_MATH or
180 -context.Emin > DEC_MAX_MATH):
181 return True
182 if not v._is_special and v and (
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000183 v.adjusted() > DEC_MAX_MATH or
184 v.adjusted() < 1-2*DEC_MAX_MATH):
185 return True
186 return False
187
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000188class DecimalTest(unittest.TestCase):
189 """Class which tests the Decimal class against the test cases.
190
191 Changed for unittest.
192 """
193 def setUp(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000194 self.context = Context()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000195 self.ignore_list = ['#']
196 # Basically, a # means return NaN InvalidOperation.
197 # Different from a sNaN in trim
198
199 self.ChangeDict = {'precision' : self.change_precision,
200 'rounding' : self.change_rounding_method,
201 'maxexponent' : self.change_max_exponent,
202 'minexponent' : self.change_min_exponent,
203 'clamp' : self.change_clamp}
204
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000205 def eval_file(self, file):
206 global skip_expected
207 if skip_expected:
Benjamin Petersone549ead2009-03-28 21:42:05 +0000208 raise unittest.SkipTest
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000209 return
Neal Norwitz70967602006-03-17 08:29:44 +0000210 for line in open(file):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000211 line = line.replace('\r\n', '').replace('\n', '')
Raymond Hettinger5aa478b2004-07-09 10:02:53 +0000212 #print line
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000213 try:
214 t = self.eval_line(line)
Guido van Rossumb940e112007-01-10 16:19:56 +0000215 except DecimalException as exception:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000216 #Exception raised where there shoudn't have been one.
217 self.fail('Exception "'+exception.__class__.__name__ + '" raised on line '+line)
218
219 return
220
221 def eval_line(self, s):
222 if s.find(' -> ') >= 0 and s[:2] != '--' and not s.startswith(' --'):
223 s = (s.split('->')[0] + '->' +
224 s.split('->')[1].split('--')[0]).strip()
225 else:
226 s = s.split('--')[0].strip()
227
228 for ignore in self.ignore_list:
229 if s.find(ignore) >= 0:
230 #print s.split()[0], 'NotImplemented--', ignore
231 return
232 if not s:
233 return
234 elif ':' in s:
235 return self.eval_directive(s)
236 else:
237 return self.eval_equation(s)
238
239 def eval_directive(self, s):
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000240 funct, value = (x.strip().lower() for x in s.split(':'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000241 if funct == 'rounding':
242 value = RoundingDict[value]
243 else:
244 try:
245 value = int(value)
246 except ValueError:
247 pass
248
249 funct = self.ChangeDict.get(funct, Nonfunction)
250 funct(value)
251
252 def eval_equation(self, s):
253 #global DEFAULT_PRECISION
254 #print DEFAULT_PRECISION
Raymond Hettingered20ad82004-09-04 20:09:13 +0000255
256 if not TEST_ALL and random.random() < 0.90:
257 return
258
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000259 try:
260 Sides = s.split('->')
261 L = Sides[0].strip().split()
262 id = L[0]
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000263 if DEBUG:
264 print("Test ", id, end=" ")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000265 funct = L[1].lower()
266 valstemp = L[2:]
267 L = Sides[1].strip().split()
268 ans = L[0]
269 exceptions = L[1:]
270 except (TypeError, AttributeError, IndexError):
Raymond Hettingerd87ac8f2004-07-09 10:52:54 +0000271 raise InvalidOperation
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000272 def FixQuotes(val):
273 val = val.replace("''", 'SingleQuote').replace('""', 'DoubleQuote')
274 val = val.replace("'", '').replace('"', '')
275 val = val.replace('SingleQuote', "'").replace('DoubleQuote', '"')
276 return val
Mark Dickinson8a546532009-10-08 16:30:38 +0000277
278 if id in skipped_test_ids:
279 return
280
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000281 fname = nameAdapter.get(funct, funct)
282 if fname == 'rescale':
283 return
284 funct = getattr(self.context, fname)
285 vals = []
286 conglomerate = ''
287 quote = 0
288 theirexceptions = [ErrorNames[x.lower()] for x in exceptions]
289
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000290 for exception in Signals:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000291 self.context.traps[exception] = 1 #Catch these bugs...
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000292 for exception in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000293 self.context.traps[exception] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000294 for i, val in enumerate(valstemp):
295 if val.count("'") % 2 == 1:
296 quote = 1 - quote
297 if quote:
298 conglomerate = conglomerate + ' ' + val
299 continue
300 else:
301 val = conglomerate + val
302 conglomerate = ''
303 v = FixQuotes(val)
304 if fname in ('to_sci_string', 'to_eng_string'):
305 if EXTENDEDERRORTEST:
306 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000307 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000308 try:
309 funct(self.context.create_decimal(v))
310 except error:
311 pass
Guido van Rossumb940e112007-01-10 16:19:56 +0000312 except Signals as e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000313 self.fail("Raised %s in %s when %s disabled" % \
314 (e, s, error))
315 else:
316 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000317 self.context.traps[error] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000318 v = self.context.create_decimal(v)
319 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000320 v = Decimal(v, self.context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000321 vals.append(v)
322
323 ans = FixQuotes(ans)
324
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000325 # skip tests that are related to bounds imposed in the decNumber
326 # reference implementation
327 if fname in decNumberRestricted:
328 if fname == 'power':
329 if not (vals[1]._isinteger() and
330 -1999999997 <= vals[1] <= 999999999):
331 if outside_decNumber_bounds(vals[0], self.context) or \
332 outside_decNumber_bounds(vals[1], self.context):
333 #print "Skipping test %s" % s
334 return
335 else:
336 if outside_decNumber_bounds(vals[0], self.context):
337 #print "Skipping test %s" % s
338 return
339
340
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000341 if EXTENDEDERRORTEST and fname not in ('to_sci_string', 'to_eng_string'):
342 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000343 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000344 try:
345 funct(*vals)
346 except error:
347 pass
Guido van Rossumb940e112007-01-10 16:19:56 +0000348 except Signals as e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000349 self.fail("Raised %s in %s when %s disabled" % \
350 (e, s, error))
351 else:
352 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000353 self.context.traps[error] = 0
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000354 if DEBUG:
355 print("--", self.context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000356 try:
357 result = str(funct(*vals))
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000358 if fname in LOGICAL_FUNCTIONS:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000359 result = str(int(eval(result))) # 'True', 'False' -> '1', '0'
Guido van Rossumb940e112007-01-10 16:19:56 +0000360 except Signals as error:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000361 self.fail("Raised %s in %s" % (error, s))
362 except: #Catch any error long enough to state the test case.
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000363 print("ERROR:", s)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000364 raise
365
366 myexceptions = self.getexceptions()
Raymond Hettingerbf440692004-07-10 14:14:37 +0000367 self.context.clear_flags()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000368
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000369 myexceptions.sort(key=repr)
370 theirexceptions.sort(key=repr)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000371
372 self.assertEqual(result, ans,
373 'Incorrect answer for ' + s + ' -- got ' + result)
374 self.assertEqual(myexceptions, theirexceptions,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000375 'Incorrect flags set in ' + s + ' -- got ' + str(myexceptions))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000376 return
377
378 def getexceptions(self):
Raymond Hettingerf63ba432004-08-17 05:42:09 +0000379 return [e for e in Signals if self.context.flags[e]]
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000380
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000381 def change_precision(self, prec):
382 self.context.prec = prec
383 def change_rounding_method(self, rounding):
384 self.context.rounding = rounding
385 def change_min_exponent(self, exp):
386 self.context.Emin = exp
387 def change_max_exponent(self, exp):
388 self.context.Emax = exp
389 def change_clamp(self, clamp):
390 self.context._clamp = clamp
391
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000392
393
394# The following classes test the behaviour of Decimal according to PEP 327
395
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000396class DecimalExplicitConstructionTest(unittest.TestCase):
397 '''Unit tests for Explicit Construction cases of Decimal.'''
398
399 def test_explicit_empty(self):
400 self.assertEqual(Decimal(), Decimal("0"))
401
402 def test_explicit_from_None(self):
403 self.assertRaises(TypeError, Decimal, None)
404
405 def test_explicit_from_int(self):
406
407 #positive
408 d = Decimal(45)
409 self.assertEqual(str(d), '45')
410
411 #very large positive
412 d = Decimal(500000123)
413 self.assertEqual(str(d), '500000123')
414
415 #negative
416 d = Decimal(-45)
417 self.assertEqual(str(d), '-45')
418
419 #zero
420 d = Decimal(0)
421 self.assertEqual(str(d), '0')
422
423 def test_explicit_from_string(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000424
425 #empty
426 self.assertEqual(str(Decimal('')), 'NaN')
427
428 #int
429 self.assertEqual(str(Decimal('45')), '45')
430
431 #float
432 self.assertEqual(str(Decimal('45.34')), '45.34')
433
434 #engineer notation
435 self.assertEqual(str(Decimal('45e2')), '4.5E+3')
436
437 #just not a number
438 self.assertEqual(str(Decimal('ugly')), 'NaN')
439
Christian Heimesa62da1d2008-01-12 19:39:10 +0000440 #leading and trailing whitespace permitted
441 self.assertEqual(str(Decimal('1.3E4 \n')), '1.3E+4')
442 self.assertEqual(str(Decimal(' -7.89')), '-7.89')
443
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000444 def test_explicit_from_tuples(self):
445
446 #zero
447 d = Decimal( (0, (0,), 0) )
448 self.assertEqual(str(d), '0')
449
450 #int
451 d = Decimal( (1, (4, 5), 0) )
452 self.assertEqual(str(d), '-45')
453
454 #float
455 d = Decimal( (0, (4, 5, 3, 4), -2) )
456 self.assertEqual(str(d), '45.34')
457
458 #weird
459 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
460 self.assertEqual(str(d), '-4.34913534E-17')
461
462 #wrong number of items
463 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1)) )
464
465 #bad sign
466 self.assertRaises(ValueError, Decimal, (8, (4, 3, 4, 9, 1), 2) )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000467 self.assertRaises(ValueError, Decimal, (0., (4, 3, 4, 9, 1), 2) )
468 self.assertRaises(ValueError, Decimal, (Decimal(1), (4, 3, 4, 9, 1), 2))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000469
470 #bad exp
471 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 'wrong!') )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000472 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 0.) )
473 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), '1') )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000474
475 #bad coefficients
476 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, None, 1), 2) )
477 self.assertRaises(ValueError, Decimal, (1, (4, -3, 4, 9, 1), 2) )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000478 self.assertRaises(ValueError, Decimal, (1, (4, 10, 4, 9, 1), 2) )
Guido van Rossum0d3fb8a2007-11-26 23:23:18 +0000479 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 'a', 1), 2) )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000480
Antoine Pitrou503ab332010-03-30 18:56:19 +0000481 def test_explicit_from_bool(self):
482 self.assertIs(bool(Decimal(0)), False)
483 self.assertIs(bool(Decimal(1)), True)
484 self.assertEqual(Decimal(False), Decimal(0))
485 self.assertEqual(Decimal(True), Decimal(1))
486
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000487 def test_explicit_from_Decimal(self):
488
489 #positive
490 d = Decimal(45)
491 e = Decimal(d)
492 self.assertEqual(str(e), '45')
493 self.assertNotEqual(id(d), id(e))
494
495 #very large positive
496 d = Decimal(500000123)
497 e = Decimal(d)
498 self.assertEqual(str(e), '500000123')
499 self.assertNotEqual(id(d), id(e))
500
501 #negative
502 d = Decimal(-45)
503 e = Decimal(d)
504 self.assertEqual(str(e), '-45')
505 self.assertNotEqual(id(d), id(e))
506
507 #zero
508 d = Decimal(0)
509 e = Decimal(d)
510 self.assertEqual(str(e), '0')
511 self.assertNotEqual(id(d), id(e))
512
Raymond Hettinger96798592010-04-02 16:58:27 +0000513 @requires_IEEE_754
514 def test_explicit_from_float(self):
515 r = Decimal(0.1)
516 self.assertEqual(type(r), Decimal)
517 self.assertEqual(str(r),
518 '0.1000000000000000055511151231257827021181583404541015625')
519 self.assertTrue(Decimal(float('nan')).is_qnan())
520 self.assertTrue(Decimal(float('inf')).is_infinite())
521 self.assertTrue(Decimal(float('-inf')).is_infinite())
522 self.assertEqual(str(Decimal(float('nan'))),
523 str(Decimal('NaN')))
524 self.assertEqual(str(Decimal(float('inf'))),
525 str(Decimal('Infinity')))
526 self.assertEqual(str(Decimal(float('-inf'))),
527 str(Decimal('-Infinity')))
528 self.assertEqual(str(Decimal(float('-0.0'))),
529 str(Decimal('-0')))
530 for i in range(200):
531 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
532 self.assertEqual(x, float(Decimal(x))) # roundtrip
533
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000534 def test_explicit_context_create_decimal(self):
535
536 nc = copy.copy(getcontext())
537 nc.prec = 3
538
539 # empty
Raymond Hettingerfed52962004-07-14 15:41:57 +0000540 d = Decimal()
541 self.assertEqual(str(d), '0')
542 d = nc.create_decimal()
543 self.assertEqual(str(d), '0')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000544
545 # from None
546 self.assertRaises(TypeError, nc.create_decimal, None)
547
548 # from int
549 d = nc.create_decimal(456)
Ezio Melottie9615932010-01-24 19:26:24 +0000550 self.assertIsInstance(d, Decimal)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000551 self.assertEqual(nc.create_decimal(45678),
552 nc.create_decimal('457E+2'))
553
554 # from string
555 d = Decimal('456789')
556 self.assertEqual(str(d), '456789')
557 d = nc.create_decimal('456789')
558 self.assertEqual(str(d), '4.57E+5')
Christian Heimesa62da1d2008-01-12 19:39:10 +0000559 # leading and trailing whitespace should result in a NaN;
560 # spaces are already checked in Cowlishaw's test-suite, so
561 # here we just check that a trailing newline results in a NaN
562 self.assertEqual(str(nc.create_decimal('3.14\n')), 'NaN')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000563
564 # from tuples
565 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
566 self.assertEqual(str(d), '-4.34913534E-17')
567 d = nc.create_decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
568 self.assertEqual(str(d), '-4.35E-17')
569
570 # from Decimal
571 prevdec = Decimal(500000123)
572 d = Decimal(prevdec)
573 self.assertEqual(str(d), '500000123')
574 d = nc.create_decimal(prevdec)
575 self.assertEqual(str(d), '5.00E+8')
576
Mark Dickinson345adc42009-08-02 10:14:23 +0000577 def test_unicode_digits(self):
578 test_values = {
579 '\uff11': '1',
580 '\u0660.\u0660\u0663\u0667\u0662e-\u0663' : '0.0000372',
581 '-nan\u0c68\u0c6a\u0c66\u0c66' : '-NaN2400',
582 }
583 for input, expected in test_values.items():
584 self.assertEqual(str(Decimal(input)), expected)
585
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000586
587class DecimalImplicitConstructionTest(unittest.TestCase):
588 '''Unit tests for Implicit Construction cases of Decimal.'''
589
590 def test_implicit_from_None(self):
591 self.assertRaises(TypeError, eval, 'Decimal(5) + None', globals())
592
593 def test_implicit_from_int(self):
594 #normal
595 self.assertEqual(str(Decimal(5) + 45), '50')
596 #exceeding precision
597 self.assertEqual(Decimal(5) + 123456789000, Decimal(123456789000))
598
599 def test_implicit_from_string(self):
600 self.assertRaises(TypeError, eval, 'Decimal(5) + "3"', globals())
601
602 def test_implicit_from_float(self):
603 self.assertRaises(TypeError, eval, 'Decimal(5) + 2.2', globals())
604
605 def test_implicit_from_Decimal(self):
606 self.assertEqual(Decimal(5) + Decimal(45), Decimal(50))
607
Raymond Hettinger267b8682005-03-27 10:47:39 +0000608 def test_rop(self):
609 # Allow other classes to be trained to interact with Decimals
610 class E:
611 def __divmod__(self, other):
612 return 'divmod ' + str(other)
613 def __rdivmod__(self, other):
614 return str(other) + ' rdivmod'
615 def __lt__(self, other):
616 return 'lt ' + str(other)
617 def __gt__(self, other):
618 return 'gt ' + str(other)
619 def __le__(self, other):
620 return 'le ' + str(other)
621 def __ge__(self, other):
622 return 'ge ' + str(other)
623 def __eq__(self, other):
624 return 'eq ' + str(other)
625 def __ne__(self, other):
626 return 'ne ' + str(other)
627
628 self.assertEqual(divmod(E(), Decimal(10)), 'divmod 10')
629 self.assertEqual(divmod(Decimal(10), E()), '10 rdivmod')
630 self.assertEqual(eval('Decimal(10) < E()'), 'gt 10')
631 self.assertEqual(eval('Decimal(10) > E()'), 'lt 10')
632 self.assertEqual(eval('Decimal(10) <= E()'), 'ge 10')
633 self.assertEqual(eval('Decimal(10) >= E()'), 'le 10')
634 self.assertEqual(eval('Decimal(10) == E()'), 'eq 10')
635 self.assertEqual(eval('Decimal(10) != E()'), 'ne 10')
636
637 # insert operator methods and then exercise them
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000638 oplist = [
639 ('+', '__add__', '__radd__'),
640 ('-', '__sub__', '__rsub__'),
641 ('*', '__mul__', '__rmul__'),
Thomas Woutersdcc6d322006-04-21 11:30:52 +0000642 ('/', '__truediv__', '__rtruediv__'),
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000643 ('%', '__mod__', '__rmod__'),
644 ('//', '__floordiv__', '__rfloordiv__'),
645 ('**', '__pow__', '__rpow__')
646 ]
Raymond Hettinger267b8682005-03-27 10:47:39 +0000647
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000648 for sym, lop, rop in oplist:
Raymond Hettinger267b8682005-03-27 10:47:39 +0000649 setattr(E, lop, lambda self, other: 'str' + lop + str(other))
650 setattr(E, rop, lambda self, other: str(other) + rop + 'str')
651 self.assertEqual(eval('E()' + sym + 'Decimal(10)'),
652 'str' + lop + '10')
653 self.assertEqual(eval('Decimal(10)' + sym + 'E()'),
654 '10' + rop + 'str')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000655
Mark Dickinson79f52032009-03-17 23:12:51 +0000656
Christian Heimesf16baeb2008-02-29 14:57:44 +0000657class DecimalFormatTest(unittest.TestCase):
658 '''Unit tests for the format function.'''
659 def test_formatting(self):
660 # triples giving a format, a Decimal, and the expected result
661 test_values = [
662 ('e', '0E-15', '0e-15'),
663 ('e', '2.3E-15', '2.3e-15'),
664 ('e', '2.30E+2', '2.30e+2'), # preserve significant zeros
665 ('e', '2.30000E-15', '2.30000e-15'),
666 ('e', '1.23456789123456789e40', '1.23456789123456789e+40'),
667 ('e', '1.5', '1.5e+0'),
668 ('e', '0.15', '1.5e-1'),
669 ('e', '0.015', '1.5e-2'),
670 ('e', '0.0000000000015', '1.5e-12'),
671 ('e', '15.0', '1.50e+1'),
672 ('e', '-15', '-1.5e+1'),
673 ('e', '0', '0e+0'),
674 ('e', '0E1', '0e+1'),
675 ('e', '0.0', '0e-1'),
676 ('e', '0.00', '0e-2'),
677 ('.6e', '0E-15', '0.000000e-9'),
678 ('.6e', '0', '0.000000e+6'),
679 ('.6e', '9.999999', '9.999999e+0'),
680 ('.6e', '9.9999999', '1.000000e+1'),
681 ('.6e', '-1.23e5', '-1.230000e+5'),
682 ('.6e', '1.23456789e-3', '1.234568e-3'),
683 ('f', '0', '0'),
684 ('f', '0.0', '0.0'),
685 ('f', '0E-2', '0.00'),
686 ('f', '0.00E-8', '0.0000000000'),
687 ('f', '0E1', '0'), # loses exponent information
688 ('f', '3.2E1', '32'),
689 ('f', '3.2E2', '320'),
690 ('f', '3.20E2', '320'),
691 ('f', '3.200E2', '320.0'),
692 ('f', '3.2E-6', '0.0000032'),
693 ('.6f', '0E-15', '0.000000'), # all zeros treated equally
694 ('.6f', '0E1', '0.000000'),
695 ('.6f', '0', '0.000000'),
696 ('.0f', '0', '0'), # no decimal point
697 ('.0f', '0e-2', '0'),
698 ('.0f', '3.14159265', '3'),
699 ('.1f', '3.14159265', '3.1'),
700 ('.4f', '3.14159265', '3.1416'),
701 ('.6f', '3.14159265', '3.141593'),
702 ('.7f', '3.14159265', '3.1415926'), # round-half-even!
703 ('.8f', '3.14159265', '3.14159265'),
704 ('.9f', '3.14159265', '3.141592650'),
705
706 ('g', '0', '0'),
707 ('g', '0.0', '0.0'),
708 ('g', '0E1', '0e+1'),
709 ('G', '0E1', '0E+1'),
710 ('g', '0E-5', '0.00000'),
711 ('g', '0E-6', '0.000000'),
712 ('g', '0E-7', '0e-7'),
713 ('g', '-0E2', '-0e+2'),
714 ('.0g', '3.14159265', '3'), # 0 sig fig -> 1 sig fig
715 ('.1g', '3.14159265', '3'),
716 ('.2g', '3.14159265', '3.1'),
717 ('.5g', '3.14159265', '3.1416'),
718 ('.7g', '3.14159265', '3.141593'),
719 ('.8g', '3.14159265', '3.1415926'), # round-half-even!
720 ('.9g', '3.14159265', '3.14159265'),
721 ('.10g', '3.14159265', '3.14159265'), # don't pad
722
723 ('%', '0E1', '0%'),
724 ('%', '0E0', '0%'),
725 ('%', '0E-1', '0%'),
726 ('%', '0E-2', '0%'),
727 ('%', '0E-3', '0.0%'),
728 ('%', '0E-4', '0.00%'),
729
730 ('.3%', '0', '0.000%'), # all zeros treated equally
731 ('.3%', '0E10', '0.000%'),
732 ('.3%', '0E-10', '0.000%'),
733 ('.3%', '2.34', '234.000%'),
734 ('.3%', '1.234567', '123.457%'),
735 ('.0%', '1.23', '123%'),
736
737 ('e', 'NaN', 'NaN'),
738 ('f', '-NaN123', '-NaN123'),
739 ('+g', 'NaN456', '+NaN456'),
740 ('.3e', 'Inf', 'Infinity'),
741 ('.16f', '-Inf', '-Infinity'),
742 ('.0g', '-sNaN', '-sNaN'),
743
744 ('', '1.00', '1.00'),
Mark Dickinsonad416342009-03-17 18:10:15 +0000745
Mark Dickinson79f52032009-03-17 23:12:51 +0000746 # test alignment and padding
Mark Dickinson46ab5d02009-09-08 20:22:46 +0000747 ('6', '123', ' 123'),
Mark Dickinsonad416342009-03-17 18:10:15 +0000748 ('<6', '123', '123 '),
749 ('>6', '123', ' 123'),
750 ('^6', '123', ' 123 '),
751 ('=+6', '123', '+ 123'),
Mark Dickinson79f52032009-03-17 23:12:51 +0000752 ('#<10', 'NaN', 'NaN#######'),
753 ('#<10', '-4.3', '-4.3######'),
754 ('#<+10', '0.0130', '+0.0130###'),
755 ('#< 10', '0.0130', ' 0.0130###'),
756 ('@>10', '-Inf', '@-Infinity'),
757 ('#>5', '-Inf', '-Infinity'),
758 ('?^5', '123', '?123?'),
759 ('%^6', '123', '%123%%'),
760 (' ^6', '-45.6', '-45.6 '),
761 ('/=10', '-45.6', '-/////45.6'),
762 ('/=+10', '45.6', '+/////45.6'),
763 ('/= 10', '45.6', ' /////45.6'),
764
765 # thousands separator
766 (',', '1234567', '1,234,567'),
767 (',', '123456', '123,456'),
768 (',', '12345', '12,345'),
769 (',', '1234', '1,234'),
770 (',', '123', '123'),
771 (',', '12', '12'),
772 (',', '1', '1'),
773 (',', '0', '0'),
774 (',', '-1234567', '-1,234,567'),
775 (',', '-123456', '-123,456'),
776 ('7,', '123456', '123,456'),
Mark Dickinson46ab5d02009-09-08 20:22:46 +0000777 ('8,', '123456', ' 123,456'),
Mark Dickinson79f52032009-03-17 23:12:51 +0000778 ('08,', '123456', '0,123,456'), # special case: extra 0 needed
779 ('+08,', '123456', '+123,456'), # but not if there's a sign
780 (' 08,', '123456', ' 123,456'),
781 ('08,', '-123456', '-123,456'),
782 ('+09,', '123456', '+0,123,456'),
783 # ... with fractional part...
784 ('07,', '1234.56', '1,234.56'),
785 ('08,', '1234.56', '1,234.56'),
786 ('09,', '1234.56', '01,234.56'),
787 ('010,', '1234.56', '001,234.56'),
788 ('011,', '1234.56', '0,001,234.56'),
789 ('012,', '1234.56', '0,001,234.56'),
790 ('08,.1f', '1234.5', '01,234.5'),
791 # no thousands separators in fraction part
792 (',', '1.23456789', '1.23456789'),
793 (',%', '123.456789', '12,345.6789%'),
794 (',e', '123456', '1.23456e+5'),
795 (',E', '123456', '1.23456E+5'),
Mark Dickinson7718d2b2009-09-07 16:21:56 +0000796
797 # issue 6850
798 ('a=-7.0', '0.12345', 'aaaa0.1'),
Christian Heimesf16baeb2008-02-29 14:57:44 +0000799 ]
800 for fmt, d, result in test_values:
801 self.assertEqual(format(Decimal(d), fmt), result)
802
Mark Dickinson79f52032009-03-17 23:12:51 +0000803 def test_n_format(self):
804 try:
805 from locale import CHAR_MAX
806 except ImportError:
807 return
808
809 # Set up some localeconv-like dictionaries
810 en_US = {
811 'decimal_point' : '.',
812 'grouping' : [3, 3, 0],
813 'thousands_sep': ','
814 }
815
816 fr_FR = {
817 'decimal_point' : ',',
818 'grouping' : [CHAR_MAX],
819 'thousands_sep' : ''
820 }
821
822 ru_RU = {
823 'decimal_point' : ',',
824 'grouping' : [3, 3, 0],
825 'thousands_sep' : ' '
826 }
827
828 crazy = {
829 'decimal_point' : '&',
830 'grouping' : [1, 4, 2, CHAR_MAX],
831 'thousands_sep' : '-'
832 }
833
834
835 def get_fmt(x, locale, fmt='n'):
836 return Decimal.__format__(Decimal(x), fmt, _localeconv=locale)
837
838 self.assertEqual(get_fmt(Decimal('12.7'), en_US), '12.7')
839 self.assertEqual(get_fmt(Decimal('12.7'), fr_FR), '12,7')
840 self.assertEqual(get_fmt(Decimal('12.7'), ru_RU), '12,7')
841 self.assertEqual(get_fmt(Decimal('12.7'), crazy), '1-2&7')
842
843 self.assertEqual(get_fmt(123456789, en_US), '123,456,789')
844 self.assertEqual(get_fmt(123456789, fr_FR), '123456789')
845 self.assertEqual(get_fmt(123456789, ru_RU), '123 456 789')
846 self.assertEqual(get_fmt(1234567890123, crazy), '123456-78-9012-3')
847
848 self.assertEqual(get_fmt(123456789, en_US, '.6n'), '1.23457e+8')
849 self.assertEqual(get_fmt(123456789, fr_FR, '.6n'), '1,23457e+8')
850 self.assertEqual(get_fmt(123456789, ru_RU, '.6n'), '1,23457e+8')
851 self.assertEqual(get_fmt(123456789, crazy, '.6n'), '1&23457e+8')
852
Mark Dickinson7303b592009-03-18 08:25:36 +0000853 # zero padding
854 self.assertEqual(get_fmt(1234, fr_FR, '03n'), '1234')
855 self.assertEqual(get_fmt(1234, fr_FR, '04n'), '1234')
856 self.assertEqual(get_fmt(1234, fr_FR, '05n'), '01234')
857 self.assertEqual(get_fmt(1234, fr_FR, '06n'), '001234')
858
859 self.assertEqual(get_fmt(12345, en_US, '05n'), '12,345')
860 self.assertEqual(get_fmt(12345, en_US, '06n'), '12,345')
861 self.assertEqual(get_fmt(12345, en_US, '07n'), '012,345')
862 self.assertEqual(get_fmt(12345, en_US, '08n'), '0,012,345')
863 self.assertEqual(get_fmt(12345, en_US, '09n'), '0,012,345')
864 self.assertEqual(get_fmt(12345, en_US, '010n'), '00,012,345')
865
866 self.assertEqual(get_fmt(123456, crazy, '06n'), '1-2345-6')
867 self.assertEqual(get_fmt(123456, crazy, '07n'), '1-2345-6')
868 self.assertEqual(get_fmt(123456, crazy, '08n'), '1-2345-6')
869 self.assertEqual(get_fmt(123456, crazy, '09n'), '01-2345-6')
870 self.assertEqual(get_fmt(123456, crazy, '010n'), '0-01-2345-6')
871 self.assertEqual(get_fmt(123456, crazy, '011n'), '0-01-2345-6')
872 self.assertEqual(get_fmt(123456, crazy, '012n'), '00-01-2345-6')
873 self.assertEqual(get_fmt(123456, crazy, '013n'), '000-01-2345-6')
874
Mark Dickinson79f52032009-03-17 23:12:51 +0000875
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000876class DecimalArithmeticOperatorsTest(unittest.TestCase):
877 '''Unit tests for all arithmetic operators, binary and unary.'''
878
879 def test_addition(self):
880
881 d1 = Decimal('-11.1')
882 d2 = Decimal('22.2')
883
884 #two Decimals
885 self.assertEqual(d1+d2, Decimal('11.1'))
886 self.assertEqual(d2+d1, Decimal('11.1'))
887
888 #with other type, left
889 c = d1 + 5
890 self.assertEqual(c, Decimal('-6.1'))
891 self.assertEqual(type(c), type(d1))
892
893 #with other type, right
894 c = 5 + d1
895 self.assertEqual(c, Decimal('-6.1'))
896 self.assertEqual(type(c), type(d1))
897
898 #inline with decimal
899 d1 += d2
900 self.assertEqual(d1, Decimal('11.1'))
901
902 #inline with other type
903 d1 += 5
904 self.assertEqual(d1, Decimal('16.1'))
905
906 def test_subtraction(self):
907
908 d1 = Decimal('-11.1')
909 d2 = Decimal('22.2')
910
911 #two Decimals
912 self.assertEqual(d1-d2, Decimal('-33.3'))
913 self.assertEqual(d2-d1, Decimal('33.3'))
914
915 #with other type, left
916 c = d1 - 5
917 self.assertEqual(c, Decimal('-16.1'))
918 self.assertEqual(type(c), type(d1))
919
920 #with other type, right
921 c = 5 - d1
922 self.assertEqual(c, Decimal('16.1'))
923 self.assertEqual(type(c), type(d1))
924
925 #inline with decimal
926 d1 -= d2
927 self.assertEqual(d1, Decimal('-33.3'))
928
929 #inline with other type
930 d1 -= 5
931 self.assertEqual(d1, Decimal('-38.3'))
932
933 def test_multiplication(self):
934
935 d1 = Decimal('-5')
936 d2 = Decimal('3')
937
938 #two Decimals
939 self.assertEqual(d1*d2, Decimal('-15'))
940 self.assertEqual(d2*d1, Decimal('-15'))
941
942 #with other type, left
943 c = d1 * 5
944 self.assertEqual(c, Decimal('-25'))
945 self.assertEqual(type(c), type(d1))
946
947 #with other type, right
948 c = 5 * d1
949 self.assertEqual(c, Decimal('-25'))
950 self.assertEqual(type(c), type(d1))
951
952 #inline with decimal
953 d1 *= d2
954 self.assertEqual(d1, Decimal('-15'))
955
956 #inline with other type
957 d1 *= 5
958 self.assertEqual(d1, Decimal('-75'))
959
960 def test_division(self):
961
962 d1 = Decimal('-5')
963 d2 = Decimal('2')
964
965 #two Decimals
966 self.assertEqual(d1/d2, Decimal('-2.5'))
967 self.assertEqual(d2/d1, Decimal('-0.4'))
968
969 #with other type, left
970 c = d1 / 4
971 self.assertEqual(c, Decimal('-1.25'))
972 self.assertEqual(type(c), type(d1))
973
974 #with other type, right
975 c = 4 / d1
976 self.assertEqual(c, Decimal('-0.8'))
977 self.assertEqual(type(c), type(d1))
978
979 #inline with decimal
980 d1 /= d2
981 self.assertEqual(d1, Decimal('-2.5'))
982
983 #inline with other type
984 d1 /= 4
985 self.assertEqual(d1, Decimal('-0.625'))
986
987 def test_floor_division(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000988
989 d1 = Decimal('5')
990 d2 = Decimal('2')
991
992 #two Decimals
993 self.assertEqual(d1//d2, Decimal('2'))
994 self.assertEqual(d2//d1, Decimal('0'))
995
996 #with other type, left
997 c = d1 // 4
998 self.assertEqual(c, Decimal('1'))
999 self.assertEqual(type(c), type(d1))
1000
1001 #with other type, right
1002 c = 7 // d1
1003 self.assertEqual(c, Decimal('1'))
1004 self.assertEqual(type(c), type(d1))
1005
1006 #inline with decimal
1007 d1 //= d2
1008 self.assertEqual(d1, Decimal('2'))
1009
1010 #inline with other type
1011 d1 //= 2
1012 self.assertEqual(d1, Decimal('1'))
1013
1014 def test_powering(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001015
1016 d1 = Decimal('5')
1017 d2 = Decimal('2')
1018
1019 #two Decimals
1020 self.assertEqual(d1**d2, Decimal('25'))
1021 self.assertEqual(d2**d1, Decimal('32'))
1022
1023 #with other type, left
1024 c = d1 ** 4
1025 self.assertEqual(c, Decimal('625'))
1026 self.assertEqual(type(c), type(d1))
1027
1028 #with other type, right
1029 c = 7 ** d1
1030 self.assertEqual(c, Decimal('16807'))
1031 self.assertEqual(type(c), type(d1))
1032
1033 #inline with decimal
1034 d1 **= d2
1035 self.assertEqual(d1, Decimal('25'))
1036
1037 #inline with other type
1038 d1 **= 4
1039 self.assertEqual(d1, Decimal('390625'))
1040
1041 def test_module(self):
1042
1043 d1 = Decimal('5')
1044 d2 = Decimal('2')
1045
1046 #two Decimals
1047 self.assertEqual(d1%d2, Decimal('1'))
1048 self.assertEqual(d2%d1, Decimal('2'))
1049
1050 #with other type, left
1051 c = d1 % 4
1052 self.assertEqual(c, Decimal('1'))
1053 self.assertEqual(type(c), type(d1))
1054
1055 #with other type, right
1056 c = 7 % d1
1057 self.assertEqual(c, Decimal('2'))
1058 self.assertEqual(type(c), type(d1))
1059
1060 #inline with decimal
1061 d1 %= d2
1062 self.assertEqual(d1, Decimal('1'))
1063
1064 #inline with other type
1065 d1 %= 4
1066 self.assertEqual(d1, Decimal('1'))
1067
1068 def test_floor_div_module(self):
1069
1070 d1 = Decimal('5')
1071 d2 = Decimal('2')
1072
1073 #two Decimals
1074 (p, q) = divmod(d1, d2)
1075 self.assertEqual(p, Decimal('2'))
1076 self.assertEqual(q, Decimal('1'))
1077 self.assertEqual(type(p), type(d1))
1078 self.assertEqual(type(q), type(d1))
1079
1080 #with other type, left
1081 (p, q) = divmod(d1, 4)
1082 self.assertEqual(p, Decimal('1'))
1083 self.assertEqual(q, Decimal('1'))
1084 self.assertEqual(type(p), type(d1))
1085 self.assertEqual(type(q), type(d1))
1086
1087 #with other type, right
1088 (p, q) = divmod(7, d1)
1089 self.assertEqual(p, Decimal('1'))
1090 self.assertEqual(q, Decimal('2'))
1091 self.assertEqual(type(p), type(d1))
1092 self.assertEqual(type(q), type(d1))
1093
1094 def test_unary_operators(self):
1095 self.assertEqual(+Decimal(45), Decimal(+45)) # +
1096 self.assertEqual(-Decimal(45), Decimal(-45)) # -
1097 self.assertEqual(abs(Decimal(45)), abs(Decimal(-45))) # abs
1098
Christian Heimes77c02eb2008-02-09 02:18:51 +00001099 def test_nan_comparisons(self):
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001100 # comparisons involving signaling nans signal InvalidOperation
1101
1102 # order comparisons (<, <=, >, >=) involving only quiet nans
1103 # also signal InvalidOperation
1104
1105 # equality comparisons (==, !=) involving only quiet nans
1106 # don't signal, but return False or True respectively.
1107
Christian Heimes77c02eb2008-02-09 02:18:51 +00001108 n = Decimal('NaN')
1109 s = Decimal('sNaN')
1110 i = Decimal('Inf')
1111 f = Decimal('2')
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001112
1113 qnan_pairs = (n, n), (n, i), (i, n), (n, f), (f, n)
1114 snan_pairs = (s, n), (n, s), (s, i), (i, s), (s, f), (f, s), (s, s)
1115 order_ops = operator.lt, operator.le, operator.gt, operator.ge
1116 equality_ops = operator.eq, operator.ne
1117
1118 # results when InvalidOperation is not trapped
1119 for x, y in qnan_pairs + snan_pairs:
1120 for op in order_ops + equality_ops:
1121 got = op(x, y)
1122 expected = True if op is operator.ne else False
1123 self.assertIs(expected, got,
1124 "expected {0!r} for operator.{1}({2!r}, {3!r}); "
1125 "got {4!r}".format(
1126 expected, op.__name__, x, y, got))
1127
1128 # repeat the above, but this time trap the InvalidOperation
1129 with localcontext() as ctx:
1130 ctx.traps[InvalidOperation] = 1
1131
1132 for x, y in qnan_pairs:
1133 for op in equality_ops:
1134 got = op(x, y)
1135 expected = True if op is operator.ne else False
1136 self.assertIs(expected, got,
1137 "expected {0!r} for "
1138 "operator.{1}({2!r}, {3!r}); "
1139 "got {4!r}".format(
1140 expected, op.__name__, x, y, got))
1141
1142 for x, y in snan_pairs:
1143 for op in equality_ops:
1144 self.assertRaises(InvalidOperation, operator.eq, x, y)
1145 self.assertRaises(InvalidOperation, operator.ne, x, y)
1146
1147 for x, y in qnan_pairs + snan_pairs:
1148 for op in order_ops:
1149 self.assertRaises(InvalidOperation, op, x, y)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001150
Mark Dickinson84230a12010-02-18 14:49:50 +00001151 def test_copy_sign(self):
1152 d = Decimal(1).copy_sign(Decimal(-2))
1153
1154 self.assertEqual(Decimal(1).copy_sign(-2), d)
1155 self.assertRaises(TypeError, Decimal(1).copy_sign, '-2')
1156
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001157# The following are two functions used to test threading in the next class
1158
1159def thfunc1(cls):
1160 d1 = Decimal(1)
1161 d3 = Decimal(3)
Christian Heimesfe337bf2008-03-23 21:54:12 +00001162 test1 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001163 cls.synchro.wait()
Christian Heimesfe337bf2008-03-23 21:54:12 +00001164 test2 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001165 cls.finish1.set()
Christian Heimesfe337bf2008-03-23 21:54:12 +00001166
Christian Heimes81ee3ef2008-05-04 22:42:01 +00001167 cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
1168 cls.assertEqual(test2, Decimal('0.3333333333333333333333333333'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001169 return
1170
1171def thfunc2(cls):
1172 d1 = Decimal(1)
1173 d3 = Decimal(3)
Christian Heimesfe337bf2008-03-23 21:54:12 +00001174 test1 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001175 thiscontext = getcontext()
1176 thiscontext.prec = 18
Christian Heimesfe337bf2008-03-23 21:54:12 +00001177 test2 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001178 cls.synchro.set()
1179 cls.finish2.set()
Christian Heimesfe337bf2008-03-23 21:54:12 +00001180
Christian Heimes81ee3ef2008-05-04 22:42:01 +00001181 cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
Christian Heimesfe337bf2008-03-23 21:54:12 +00001182 cls.assertEqual(test2, Decimal('0.333333333333333333'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001183 return
1184
1185
1186class DecimalUseOfContextTest(unittest.TestCase):
1187 '''Unit tests for Use of Context cases in Decimal.'''
1188
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001189 try:
1190 import threading
1191 except ImportError:
1192 threading = None
1193
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001194 # Take care executing this test from IDLE, there's an issue in threading
1195 # that hangs IDLE and I couldn't find it
1196
1197 def test_threading(self):
1198 #Test the "threading isolation" of a Context.
1199
1200 self.synchro = threading.Event()
1201 self.finish1 = threading.Event()
1202 self.finish2 = threading.Event()
1203
1204 th1 = threading.Thread(target=thfunc1, args=(self,))
1205 th2 = threading.Thread(target=thfunc2, args=(self,))
1206
1207 th1.start()
1208 th2.start()
1209
1210 self.finish1.wait()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001211 self.finish2.wait()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001212 return
1213
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001214 if threading is None:
1215 del test_threading
1216
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001217
1218class DecimalUsabilityTest(unittest.TestCase):
1219 '''Unit tests for Usability cases of Decimal.'''
1220
1221 def test_comparison_operators(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001222
1223 da = Decimal('23.42')
1224 db = Decimal('23.42')
1225 dc = Decimal('45')
1226
1227 #two Decimals
Ezio Melotti6607d512010-04-03 14:59:49 +00001228 self.assertGreater(dc, da)
1229 self.assertGreaterEqual(dc, da)
1230 self.assertLess(da, dc)
1231 self.assertLessEqual(da, dc)
Guido van Rossume61fd5b2007-07-11 12:20:59 +00001232 self.assertEqual(da, db)
Ezio Melotti6607d512010-04-03 14:59:49 +00001233 self.assertNotEqual(da, dc)
1234 self.assertLessEqual(da, db)
1235 self.assertGreaterEqual(da, db)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001236
1237 #a Decimal and an int
Ezio Melotti6607d512010-04-03 14:59:49 +00001238 self.assertGreater(dc, 23)
1239 self.assertLess(23, dc)
Guido van Rossume61fd5b2007-07-11 12:20:59 +00001240 self.assertEqual(dc, 45)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001241
1242 #a Decimal and uncomparable
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001243 self.assertNotEqual(da, 'ugly')
1244 self.assertNotEqual(da, 32.7)
1245 self.assertNotEqual(da, object())
1246 self.assertNotEqual(da, object)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001247
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001248 # sortable
Guido van Rossumc1f779c2007-07-03 08:25:58 +00001249 a = list(map(Decimal, range(100)))
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001250 b = a[:]
1251 random.shuffle(a)
1252 a.sort()
1253 self.assertEqual(a, b)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001254
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001255 def test_decimal_float_comparison(self):
1256 da = Decimal('0.25')
1257 db = Decimal('3.0')
Ezio Melotti6607d512010-04-03 14:59:49 +00001258 self.assertLess(da, 3.0)
1259 self.assertLessEqual(da, 3.0)
1260 self.assertGreater(db, 0.25)
1261 self.assertGreaterEqual(db, 0.25)
1262 self.assertNotEqual(da, 1.5)
1263 self.assertEqual(da, 0.25)
1264 self.assertGreater(3.0, da)
1265 self.assertGreaterEqual(3.0, da)
1266 self.assertLess(0.25, db)
1267 self.assertLessEqual(0.25, db)
1268 self.assertNotEqual(0.25, db)
1269 self.assertEqual(3.0, db)
1270 self.assertNotEqual(0.1, Decimal('0.1'))
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001271
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001272 def test_copy_and_deepcopy_methods(self):
1273 d = Decimal('43.24')
1274 c = copy.copy(d)
1275 self.assertEqual(id(c), id(d))
1276 dc = copy.deepcopy(d)
1277 self.assertEqual(id(dc), id(d))
1278
1279 def test_hash_method(self):
1280 #just that it's hashable
1281 hash(Decimal(23))
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001282 hash(Decimal('Infinity'))
1283 hash(Decimal('-Infinity'))
1284 hash(Decimal('nan123'))
1285 hash(Decimal('-NaN'))
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001286
1287 test_values = [Decimal(sign*(2**m + n))
1288 for m in [0, 14, 15, 16, 17, 30, 31,
1289 32, 33, 62, 63, 64, 65, 66]
1290 for n in range(-10, 10)
1291 for sign in [-1, 1]]
1292 test_values.extend([
1293 Decimal("-0"), # zeros
1294 Decimal("0.00"),
1295 Decimal("-0.000"),
1296 Decimal("0E10"),
1297 Decimal("-0E12"),
1298 Decimal("10.0"), # negative exponent
1299 Decimal("-23.00000"),
1300 Decimal("1230E100"), # positive exponent
1301 Decimal("-4.5678E50"),
1302 # a value for which hash(n) != hash(n % (2**64-1))
1303 # in Python pre-2.6
1304 Decimal(2**64 + 2**32 - 1),
1305 # selection of values which fail with the old (before
1306 # version 2.6) long.__hash__
1307 Decimal("1.634E100"),
1308 Decimal("90.697E100"),
1309 Decimal("188.83E100"),
1310 Decimal("1652.9E100"),
1311 Decimal("56531E100"),
1312 ])
1313
1314 # check that hash(d) == hash(int(d)) for integral values
1315 for value in test_values:
1316 self.assertEqual(hash(value), hash(int(value)))
1317
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001318 #the same hash that to an int
1319 self.assertEqual(hash(Decimal(23)), hash(23))
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001320 self.assertRaises(TypeError, hash, Decimal('sNaN'))
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001321 self.assertTrue(hash(Decimal('Inf')))
1322 self.assertTrue(hash(Decimal('-Inf')))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001323
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001324 # check that the hashes of a Decimal float match when they
1325 # represent exactly the same values
1326 test_strings = ['inf', '-Inf', '0.0', '-.0e1',
1327 '34.0', '2.5', '112390.625', '-0.515625']
1328 for s in test_strings:
1329 f = float(s)
1330 d = Decimal(s)
1331 self.assertEqual(hash(f), hash(d))
1332
Christian Heimes2380ac72008-01-09 00:17:24 +00001333 # check that the value of the hash doesn't depend on the
1334 # current context (issue #1757)
1335 c = getcontext()
1336 old_precision = c.prec
1337 x = Decimal("123456789.1")
1338
1339 c.prec = 6
1340 h1 = hash(x)
1341 c.prec = 10
1342 h2 = hash(x)
1343 c.prec = 16
1344 h3 = hash(x)
1345
1346 self.assertEqual(h1, h2)
1347 self.assertEqual(h1, h3)
1348 c.prec = old_precision
1349
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001350 def test_min_and_max_methods(self):
1351
1352 d1 = Decimal('15.32')
1353 d2 = Decimal('28.5')
1354 l1 = 15
1355 l2 = 28
1356
1357 #between Decimals
Ezio Melotti6607d512010-04-03 14:59:49 +00001358 self.assertIs(min(d1,d2), d1)
1359 self.assertIs(min(d2,d1), d1)
1360 self.assertIs(max(d1,d2), d2)
1361 self.assertIs(max(d2,d1), d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001362
1363 #between Decimal and long
Ezio Melotti6607d512010-04-03 14:59:49 +00001364 self.assertIs(min(d1,l2), d1)
1365 self.assertIs(min(l2,d1), d1)
1366 self.assertIs(max(l1,d2), d2)
1367 self.assertIs(max(d2,l1), d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001368
1369 def test_as_nonzero(self):
1370 #as false
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001371 self.assertFalse(Decimal(0))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001372 #as true
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001373 self.assertTrue(Decimal('0.372'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001374
1375 def test_tostring_methods(self):
1376 #Test str and repr methods.
1377
1378 d = Decimal('15.32')
1379 self.assertEqual(str(d), '15.32') # str
Christian Heimes68f5fbe2008-02-14 08:27:37 +00001380 self.assertEqual(repr(d), "Decimal('15.32')") # repr
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001381
1382 def test_tonum_methods(self):
Mark Dickinson5c2db372009-12-05 20:28:34 +00001383 #Test float and int methods.
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001384
1385 d1 = Decimal('66')
1386 d2 = Decimal('15.32')
1387
1388 #int
1389 self.assertEqual(int(d1), 66)
1390 self.assertEqual(int(d2), 15)
1391
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001392 #float
1393 self.assertEqual(float(d1), 66)
1394 self.assertEqual(float(d2), 15.32)
1395
Mark Dickinsonb27406c2008-05-09 13:42:33 +00001396 #floor
1397 test_pairs = [
1398 ('123.00', 123),
1399 ('3.2', 3),
1400 ('3.54', 3),
1401 ('3.899', 3),
1402 ('-2.3', -3),
1403 ('-11.0', -11),
1404 ('0.0', 0),
1405 ('-0E3', 0),
1406 ]
1407 for d, i in test_pairs:
1408 self.assertEqual(math.floor(Decimal(d)), i)
1409 self.assertRaises(ValueError, math.floor, Decimal('-NaN'))
1410 self.assertRaises(ValueError, math.floor, Decimal('sNaN'))
1411 self.assertRaises(ValueError, math.floor, Decimal('NaN123'))
1412 self.assertRaises(OverflowError, math.floor, Decimal('Inf'))
1413 self.assertRaises(OverflowError, math.floor, Decimal('-Inf'))
1414
1415 #ceiling
1416 test_pairs = [
1417 ('123.00', 123),
1418 ('3.2', 4),
1419 ('3.54', 4),
1420 ('3.899', 4),
1421 ('-2.3', -2),
1422 ('-11.0', -11),
1423 ('0.0', 0),
1424 ('-0E3', 0),
1425 ]
1426 for d, i in test_pairs:
1427 self.assertEqual(math.ceil(Decimal(d)), i)
1428 self.assertRaises(ValueError, math.ceil, Decimal('-NaN'))
1429 self.assertRaises(ValueError, math.ceil, Decimal('sNaN'))
1430 self.assertRaises(ValueError, math.ceil, Decimal('NaN123'))
1431 self.assertRaises(OverflowError, math.ceil, Decimal('Inf'))
1432 self.assertRaises(OverflowError, math.ceil, Decimal('-Inf'))
1433
1434 #round, single argument
1435 test_pairs = [
1436 ('123.00', 123),
1437 ('3.2', 3),
1438 ('3.54', 4),
1439 ('3.899', 4),
1440 ('-2.3', -2),
1441 ('-11.0', -11),
1442 ('0.0', 0),
1443 ('-0E3', 0),
1444 ('-3.5', -4),
1445 ('-2.5', -2),
1446 ('-1.5', -2),
1447 ('-0.5', 0),
1448 ('0.5', 0),
1449 ('1.5', 2),
1450 ('2.5', 2),
1451 ('3.5', 4),
1452 ]
1453 for d, i in test_pairs:
1454 self.assertEqual(round(Decimal(d)), i)
1455 self.assertRaises(ValueError, round, Decimal('-NaN'))
1456 self.assertRaises(ValueError, round, Decimal('sNaN'))
1457 self.assertRaises(ValueError, round, Decimal('NaN123'))
1458 self.assertRaises(OverflowError, round, Decimal('Inf'))
1459 self.assertRaises(OverflowError, round, Decimal('-Inf'))
1460
1461 #round, two arguments; this is essentially equivalent
1462 #to quantize, which is already extensively tested
1463 test_triples = [
1464 ('123.456', -4, '0E+4'),
1465 ('123.456', -3, '0E+3'),
1466 ('123.456', -2, '1E+2'),
1467 ('123.456', -1, '1.2E+2'),
1468 ('123.456', 0, '123'),
1469 ('123.456', 1, '123.5'),
1470 ('123.456', 2, '123.46'),
1471 ('123.456', 3, '123.456'),
1472 ('123.456', 4, '123.4560'),
1473 ('123.455', 2, '123.46'),
1474 ('123.445', 2, '123.44'),
1475 ('Inf', 4, 'NaN'),
1476 ('-Inf', -23, 'NaN'),
1477 ('sNaN314', 3, 'NaN314'),
1478 ]
1479 for d, n, r in test_triples:
1480 self.assertEqual(str(round(Decimal(d), n)), r)
1481
1482
1483
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001484 def test_eval_round_trip(self):
1485
1486 #with zero
1487 d = Decimal( (0, (0,), 0) )
1488 self.assertEqual(d, eval(repr(d)))
1489
1490 #int
1491 d = Decimal( (1, (4, 5), 0) )
1492 self.assertEqual(d, eval(repr(d)))
1493
1494 #float
1495 d = Decimal( (0, (4, 5, 3, 4), -2) )
1496 self.assertEqual(d, eval(repr(d)))
1497
1498 #weird
1499 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1500 self.assertEqual(d, eval(repr(d)))
1501
1502 def test_as_tuple(self):
1503
1504 #with zero
1505 d = Decimal(0)
1506 self.assertEqual(d.as_tuple(), (0, (0,), 0) )
1507
1508 #int
1509 d = Decimal(-45)
1510 self.assertEqual(d.as_tuple(), (1, (4, 5), 0) )
1511
1512 #complicated string
1513 d = Decimal("-4.34913534E-17")
1514 self.assertEqual(d.as_tuple(), (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1515
1516 #inf
1517 d = Decimal("Infinity")
1518 self.assertEqual(d.as_tuple(), (0, (0,), 'F') )
1519
Guido van Rossum8ce8a782007-11-01 19:42:39 +00001520 #leading zeros in coefficient should be stripped
1521 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), -2) )
1522 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), -2) )
1523 d = Decimal( (1, (0, 0, 0), 37) )
1524 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1525 d = Decimal( (1, (), 37) )
1526 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1527
1528 #leading zeros in NaN diagnostic info should be stripped
1529 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), 'n') )
1530 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), 'n') )
1531 d = Decimal( (1, (0, 0, 0), 'N') )
1532 self.assertEqual(d.as_tuple(), (1, (), 'N') )
1533 d = Decimal( (1, (), 'n') )
1534 self.assertEqual(d.as_tuple(), (1, (), 'n') )
1535
1536 #coefficient in infinity should be ignored
1537 d = Decimal( (0, (4, 5, 3, 4), 'F') )
1538 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
1539 d = Decimal( (1, (0, 2, 7, 1), 'F') )
1540 self.assertEqual(d.as_tuple(), (1, (0,), 'F'))
1541
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001542 def test_immutability_operations(self):
1543 # Do operations and check that it didn't change change internal objects.
1544
1545 d1 = Decimal('-25e55')
1546 b1 = Decimal('-25e55')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001547 d2 = Decimal('33e+33')
1548 b2 = Decimal('33e+33')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001549
1550 def checkSameDec(operation, useOther=False):
1551 if useOther:
1552 eval("d1." + operation + "(d2)")
1553 self.assertEqual(d1._sign, b1._sign)
1554 self.assertEqual(d1._int, b1._int)
1555 self.assertEqual(d1._exp, b1._exp)
1556 self.assertEqual(d2._sign, b2._sign)
1557 self.assertEqual(d2._int, b2._int)
1558 self.assertEqual(d2._exp, b2._exp)
1559 else:
1560 eval("d1." + operation + "()")
1561 self.assertEqual(d1._sign, b1._sign)
1562 self.assertEqual(d1._int, b1._int)
1563 self.assertEqual(d1._exp, b1._exp)
1564 return
1565
1566 Decimal(d1)
1567 self.assertEqual(d1._sign, b1._sign)
1568 self.assertEqual(d1._int, b1._int)
1569 self.assertEqual(d1._exp, b1._exp)
1570
1571 checkSameDec("__abs__")
1572 checkSameDec("__add__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001573 checkSameDec("__divmod__", True)
Christian Heimes77c02eb2008-02-09 02:18:51 +00001574 checkSameDec("__eq__", True)
1575 checkSameDec("__ne__", True)
1576 checkSameDec("__le__", True)
1577 checkSameDec("__lt__", True)
1578 checkSameDec("__ge__", True)
1579 checkSameDec("__gt__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001580 checkSameDec("__float__")
1581 checkSameDec("__floordiv__", True)
1582 checkSameDec("__hash__")
1583 checkSameDec("__int__")
Christian Heimes969fe572008-01-25 11:23:10 +00001584 checkSameDec("__trunc__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001585 checkSameDec("__mod__", True)
1586 checkSameDec("__mul__", True)
1587 checkSameDec("__neg__")
Jack Diederich4dafcc42006-11-28 19:15:13 +00001588 checkSameDec("__bool__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001589 checkSameDec("__pos__")
1590 checkSameDec("__pow__", True)
1591 checkSameDec("__radd__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001592 checkSameDec("__rdivmod__", True)
1593 checkSameDec("__repr__")
1594 checkSameDec("__rfloordiv__", True)
1595 checkSameDec("__rmod__", True)
1596 checkSameDec("__rmul__", True)
1597 checkSameDec("__rpow__", True)
1598 checkSameDec("__rsub__", True)
1599 checkSameDec("__str__")
1600 checkSameDec("__sub__", True)
1601 checkSameDec("__truediv__", True)
1602 checkSameDec("adjusted")
1603 checkSameDec("as_tuple")
1604 checkSameDec("compare", True)
1605 checkSameDec("max", True)
1606 checkSameDec("min", True)
1607 checkSameDec("normalize")
1608 checkSameDec("quantize", True)
1609 checkSameDec("remainder_near", True)
1610 checkSameDec("same_quantum", True)
1611 checkSameDec("sqrt")
1612 checkSameDec("to_eng_string")
1613 checkSameDec("to_integral")
1614
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001615 def test_subclassing(self):
1616 # Different behaviours when subclassing Decimal
1617
1618 class MyDecimal(Decimal):
1619 pass
1620
1621 d1 = MyDecimal(1)
1622 d2 = MyDecimal(2)
1623 d = d1 + d2
Ezio Melotti6607d512010-04-03 14:59:49 +00001624 self.assertIs(type(d), Decimal)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001625
1626 d = d1.max(d2)
Ezio Melotti6607d512010-04-03 14:59:49 +00001627 self.assertIs(type(d), Decimal)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001628
Christian Heimes0348fb62008-03-26 12:55:56 +00001629 def test_implicit_context(self):
1630 # Check results when context given implicitly. (Issue 2478)
1631 c = getcontext()
1632 self.assertEqual(str(Decimal(0).sqrt()),
1633 str(c.sqrt(Decimal(0))))
1634
Mark Dickinsona2d1fe02009-10-29 12:23:02 +00001635 def test_conversions_from_int(self):
1636 # Check that methods taking a second Decimal argument will
1637 # always accept an integer in place of a Decimal.
1638 self.assertEqual(Decimal(4).compare(3),
1639 Decimal(4).compare(Decimal(3)))
1640 self.assertEqual(Decimal(4).compare_signal(3),
1641 Decimal(4).compare_signal(Decimal(3)))
1642 self.assertEqual(Decimal(4).compare_total(3),
1643 Decimal(4).compare_total(Decimal(3)))
1644 self.assertEqual(Decimal(4).compare_total_mag(3),
1645 Decimal(4).compare_total_mag(Decimal(3)))
1646 self.assertEqual(Decimal(10101).logical_and(1001),
1647 Decimal(10101).logical_and(Decimal(1001)))
1648 self.assertEqual(Decimal(10101).logical_or(1001),
1649 Decimal(10101).logical_or(Decimal(1001)))
1650 self.assertEqual(Decimal(10101).logical_xor(1001),
1651 Decimal(10101).logical_xor(Decimal(1001)))
1652 self.assertEqual(Decimal(567).max(123),
1653 Decimal(567).max(Decimal(123)))
1654 self.assertEqual(Decimal(567).max_mag(123),
1655 Decimal(567).max_mag(Decimal(123)))
1656 self.assertEqual(Decimal(567).min(123),
1657 Decimal(567).min(Decimal(123)))
1658 self.assertEqual(Decimal(567).min_mag(123),
1659 Decimal(567).min_mag(Decimal(123)))
1660 self.assertEqual(Decimal(567).next_toward(123),
1661 Decimal(567).next_toward(Decimal(123)))
1662 self.assertEqual(Decimal(1234).quantize(100),
1663 Decimal(1234).quantize(Decimal(100)))
1664 self.assertEqual(Decimal(768).remainder_near(1234),
1665 Decimal(768).remainder_near(Decimal(1234)))
1666 self.assertEqual(Decimal(123).rotate(1),
1667 Decimal(123).rotate(Decimal(1)))
1668 self.assertEqual(Decimal(1234).same_quantum(1000),
1669 Decimal(1234).same_quantum(Decimal(1000)))
1670 self.assertEqual(Decimal('9.123').scaleb(-100),
1671 Decimal('9.123').scaleb(Decimal(-100)))
1672 self.assertEqual(Decimal(456).shift(-1),
1673 Decimal(456).shift(Decimal(-1)))
1674
1675 self.assertEqual(Decimal(-12).fma(Decimal(45), 67),
1676 Decimal(-12).fma(Decimal(45), Decimal(67)))
1677 self.assertEqual(Decimal(-12).fma(45, 67),
1678 Decimal(-12).fma(Decimal(45), Decimal(67)))
1679 self.assertEqual(Decimal(-12).fma(45, Decimal(67)),
1680 Decimal(-12).fma(Decimal(45), Decimal(67)))
1681
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001682
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001683class DecimalPythonAPItests(unittest.TestCase):
1684
Raymond Hettinger82417ca2009-02-03 03:54:28 +00001685 def test_abc(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001686 self.assertTrue(issubclass(Decimal, numbers.Number))
Ezio Melotti6607d512010-04-03 14:59:49 +00001687 self.assertFalse(issubclass(Decimal, numbers.Real))
Ezio Melottie9615932010-01-24 19:26:24 +00001688 self.assertIsInstance(Decimal(0), numbers.Number)
1689 self.assertNotIsInstance(Decimal(0), numbers.Real)
Raymond Hettinger82417ca2009-02-03 03:54:28 +00001690
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001691 def test_pickle(self):
1692 d = Decimal('-3.141590000')
1693 p = pickle.dumps(d)
1694 e = pickle.loads(p)
1695 self.assertEqual(d, e)
1696
Raymond Hettinger5548be22004-07-05 18:49:38 +00001697 def test_int(self):
Raymond Hettinger605ed022004-11-24 07:28:48 +00001698 for x in range(-250, 250):
1699 s = '%0.2f' % (x / 100.0)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001700 # should work the same as for floats
1701 self.assertEqual(int(Decimal(s)), int(float(s)))
Raymond Hettinger605ed022004-11-24 07:28:48 +00001702 # should work the same as to_integral in the ROUND_DOWN mode
Raymond Hettinger5548be22004-07-05 18:49:38 +00001703 d = Decimal(s)
Raymond Hettinger605ed022004-11-24 07:28:48 +00001704 r = d.to_integral(ROUND_DOWN)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001705 self.assertEqual(Decimal(int(d)), r)
1706
Mark Dickinson825fce32009-09-07 18:08:12 +00001707 self.assertRaises(ValueError, int, Decimal('-nan'))
1708 self.assertRaises(ValueError, int, Decimal('snan'))
1709 self.assertRaises(OverflowError, int, Decimal('inf'))
1710 self.assertRaises(OverflowError, int, Decimal('-inf'))
1711
Christian Heimes969fe572008-01-25 11:23:10 +00001712 def test_trunc(self):
1713 for x in range(-250, 250):
1714 s = '%0.2f' % (x / 100.0)
1715 # should work the same as for floats
1716 self.assertEqual(int(Decimal(s)), int(float(s)))
1717 # should work the same as to_integral in the ROUND_DOWN mode
1718 d = Decimal(s)
1719 r = d.to_integral(ROUND_DOWN)
Christian Heimes400adb02008-02-01 08:12:03 +00001720 self.assertEqual(Decimal(math.trunc(d)), r)
Christian Heimes969fe572008-01-25 11:23:10 +00001721
Raymond Hettinger771ed762009-01-03 19:20:32 +00001722 def test_from_float(self):
1723
1724 class MyDecimal(Decimal):
1725 pass
1726
1727 r = MyDecimal.from_float(0.1)
1728 self.assertEqual(type(r), MyDecimal)
1729 self.assertEqual(str(r),
1730 '0.1000000000000000055511151231257827021181583404541015625')
1731 bigint = 12345678901234567890123456789
1732 self.assertEqual(MyDecimal.from_float(bigint), MyDecimal(bigint))
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001733 self.assertTrue(MyDecimal.from_float(float('nan')).is_qnan())
1734 self.assertTrue(MyDecimal.from_float(float('inf')).is_infinite())
1735 self.assertTrue(MyDecimal.from_float(float('-inf')).is_infinite())
Raymond Hettinger771ed762009-01-03 19:20:32 +00001736 self.assertEqual(str(MyDecimal.from_float(float('nan'))),
1737 str(Decimal('NaN')))
1738 self.assertEqual(str(MyDecimal.from_float(float('inf'))),
1739 str(Decimal('Infinity')))
1740 self.assertEqual(str(MyDecimal.from_float(float('-inf'))),
1741 str(Decimal('-Infinity')))
1742 self.assertRaises(TypeError, MyDecimal.from_float, 'abc')
1743 for i in range(200):
1744 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
1745 self.assertEqual(x, float(MyDecimal.from_float(x))) # roundtrip
1746
1747 def test_create_decimal_from_float(self):
1748 context = Context(prec=5, rounding=ROUND_DOWN)
1749 self.assertEqual(
1750 context.create_decimal_from_float(math.pi),
1751 Decimal('3.1415')
1752 )
1753 context = Context(prec=5, rounding=ROUND_UP)
1754 self.assertEqual(
1755 context.create_decimal_from_float(math.pi),
1756 Decimal('3.1416')
1757 )
1758 context = Context(prec=5, traps=[Inexact])
1759 self.assertRaises(
1760 Inexact,
1761 context.create_decimal_from_float,
1762 math.pi
1763 )
1764 self.assertEqual(repr(context.create_decimal_from_float(-0.0)),
1765 "Decimal('-0')")
1766 self.assertEqual(repr(context.create_decimal_from_float(1.0)),
1767 "Decimal('1')")
1768 self.assertEqual(repr(context.create_decimal_from_float(10)),
1769 "Decimal('10')")
1770
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00001771class ContextAPItests(unittest.TestCase):
1772
1773 def test_pickle(self):
1774 c = Context()
1775 e = pickle.loads(pickle.dumps(c))
1776 for k in vars(c):
1777 v1 = vars(c)[k]
1778 v2 = vars(e)[k]
1779 self.assertEqual(v1, v2)
1780
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001781 def test_equality_with_other_types(self):
Benjamin Peterson577473f2010-01-19 00:09:57 +00001782 self.assertIn(Decimal(10), ['a', 1.0, Decimal(10), (1,2), {}])
1783 self.assertNotIn(Decimal(10), ['a', 1.0, (1,2), {}])
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001784
Raymond Hettinger955d2b22004-08-08 20:17:45 +00001785 def test_copy(self):
1786 # All copies should be deep
1787 c = Context()
1788 d = c.copy()
1789 self.assertNotEqual(id(c), id(d))
1790 self.assertNotEqual(id(c.flags), id(d.flags))
1791 self.assertNotEqual(id(c.traps), id(d.traps))
1792
Mark Dickinson84230a12010-02-18 14:49:50 +00001793 def test_abs(self):
1794 c = Context()
1795 d = c.abs(Decimal(-1))
1796 self.assertEqual(c.abs(-1), d)
1797 self.assertRaises(TypeError, c.abs, '-1')
1798
1799 def test_add(self):
1800 c = Context()
1801 d = c.add(Decimal(1), Decimal(1))
1802 self.assertEqual(c.add(1, 1), d)
1803 self.assertEqual(c.add(Decimal(1), 1), d)
1804 self.assertEqual(c.add(1, Decimal(1)), d)
1805 self.assertRaises(TypeError, c.add, '1', 1)
1806 self.assertRaises(TypeError, c.add, 1, '1')
1807
1808 def test_compare(self):
1809 c = Context()
1810 d = c.compare(Decimal(1), Decimal(1))
1811 self.assertEqual(c.compare(1, 1), d)
1812 self.assertEqual(c.compare(Decimal(1), 1), d)
1813 self.assertEqual(c.compare(1, Decimal(1)), d)
1814 self.assertRaises(TypeError, c.compare, '1', 1)
1815 self.assertRaises(TypeError, c.compare, 1, '1')
1816
1817 def test_compare_signal(self):
1818 c = Context()
1819 d = c.compare_signal(Decimal(1), Decimal(1))
1820 self.assertEqual(c.compare_signal(1, 1), d)
1821 self.assertEqual(c.compare_signal(Decimal(1), 1), d)
1822 self.assertEqual(c.compare_signal(1, Decimal(1)), d)
1823 self.assertRaises(TypeError, c.compare_signal, '1', 1)
1824 self.assertRaises(TypeError, c.compare_signal, 1, '1')
1825
1826 def test_compare_total(self):
1827 c = Context()
1828 d = c.compare_total(Decimal(1), Decimal(1))
1829 self.assertEqual(c.compare_total(1, 1), d)
1830 self.assertEqual(c.compare_total(Decimal(1), 1), d)
1831 self.assertEqual(c.compare_total(1, Decimal(1)), d)
1832 self.assertRaises(TypeError, c.compare_total, '1', 1)
1833 self.assertRaises(TypeError, c.compare_total, 1, '1')
1834
1835 def test_compare_total_mag(self):
1836 c = Context()
1837 d = c.compare_total_mag(Decimal(1), Decimal(1))
1838 self.assertEqual(c.compare_total_mag(1, 1), d)
1839 self.assertEqual(c.compare_total_mag(Decimal(1), 1), d)
1840 self.assertEqual(c.compare_total_mag(1, Decimal(1)), d)
1841 self.assertRaises(TypeError, c.compare_total_mag, '1', 1)
1842 self.assertRaises(TypeError, c.compare_total_mag, 1, '1')
1843
1844 def test_copy_abs(self):
1845 c = Context()
1846 d = c.copy_abs(Decimal(-1))
1847 self.assertEqual(c.copy_abs(-1), d)
1848 self.assertRaises(TypeError, c.copy_abs, '-1')
1849
1850 def test_copy_decimal(self):
1851 c = Context()
1852 d = c.copy_decimal(Decimal(-1))
1853 self.assertEqual(c.copy_decimal(-1), d)
1854 self.assertRaises(TypeError, c.copy_decimal, '-1')
1855
1856 def test_copy_negate(self):
1857 c = Context()
1858 d = c.copy_negate(Decimal(-1))
1859 self.assertEqual(c.copy_negate(-1), d)
1860 self.assertRaises(TypeError, c.copy_negate, '-1')
1861
1862 def test_copy_sign(self):
1863 c = Context()
1864 d = c.copy_sign(Decimal(1), Decimal(-2))
1865 self.assertEqual(c.copy_sign(1, -2), d)
1866 self.assertEqual(c.copy_sign(Decimal(1), -2), d)
1867 self.assertEqual(c.copy_sign(1, Decimal(-2)), d)
1868 self.assertRaises(TypeError, c.copy_sign, '1', -2)
1869 self.assertRaises(TypeError, c.copy_sign, 1, '-2')
1870
1871 def test_divide(self):
1872 c = Context()
1873 d = c.divide(Decimal(1), Decimal(2))
1874 self.assertEqual(c.divide(1, 2), d)
1875 self.assertEqual(c.divide(Decimal(1), 2), d)
1876 self.assertEqual(c.divide(1, Decimal(2)), d)
1877 self.assertRaises(TypeError, c.divide, '1', 2)
1878 self.assertRaises(TypeError, c.divide, 1, '2')
1879
1880 def test_divide_int(self):
1881 c = Context()
1882 d = c.divide_int(Decimal(1), Decimal(2))
1883 self.assertEqual(c.divide_int(1, 2), d)
1884 self.assertEqual(c.divide_int(Decimal(1), 2), d)
1885 self.assertEqual(c.divide_int(1, Decimal(2)), d)
1886 self.assertRaises(TypeError, c.divide_int, '1', 2)
1887 self.assertRaises(TypeError, c.divide_int, 1, '2')
1888
1889 def test_divmod(self):
1890 c = Context()
1891 d = c.divmod(Decimal(1), Decimal(2))
1892 self.assertEqual(c.divmod(1, 2), d)
1893 self.assertEqual(c.divmod(Decimal(1), 2), d)
1894 self.assertEqual(c.divmod(1, Decimal(2)), d)
1895 self.assertRaises(TypeError, c.divmod, '1', 2)
1896 self.assertRaises(TypeError, c.divmod, 1, '2')
1897
1898 def test_exp(self):
1899 c = Context()
1900 d = c.exp(Decimal(10))
1901 self.assertEqual(c.exp(10), d)
1902 self.assertRaises(TypeError, c.exp, '10')
1903
1904 def test_fma(self):
1905 c = Context()
1906 d = c.fma(Decimal(2), Decimal(3), Decimal(4))
1907 self.assertEqual(c.fma(2, 3, 4), d)
1908 self.assertEqual(c.fma(Decimal(2), 3, 4), d)
1909 self.assertEqual(c.fma(2, Decimal(3), 4), d)
1910 self.assertEqual(c.fma(2, 3, Decimal(4)), d)
1911 self.assertEqual(c.fma(Decimal(2), Decimal(3), 4), d)
1912 self.assertRaises(TypeError, c.fma, '2', 3, 4)
1913 self.assertRaises(TypeError, c.fma, 2, '3', 4)
1914 self.assertRaises(TypeError, c.fma, 2, 3, '4')
1915
1916 def test_is_finite(self):
1917 c = Context()
1918 d = c.is_finite(Decimal(10))
1919 self.assertEqual(c.is_finite(10), d)
1920 self.assertRaises(TypeError, c.is_finite, '10')
1921
1922 def test_is_infinite(self):
1923 c = Context()
1924 d = c.is_infinite(Decimal(10))
1925 self.assertEqual(c.is_infinite(10), d)
1926 self.assertRaises(TypeError, c.is_infinite, '10')
1927
1928 def test_is_nan(self):
1929 c = Context()
1930 d = c.is_nan(Decimal(10))
1931 self.assertEqual(c.is_nan(10), d)
1932 self.assertRaises(TypeError, c.is_nan, '10')
1933
1934 def test_is_normal(self):
1935 c = Context()
1936 d = c.is_normal(Decimal(10))
1937 self.assertEqual(c.is_normal(10), d)
1938 self.assertRaises(TypeError, c.is_normal, '10')
1939
1940 def test_is_qnan(self):
1941 c = Context()
1942 d = c.is_qnan(Decimal(10))
1943 self.assertEqual(c.is_qnan(10), d)
1944 self.assertRaises(TypeError, c.is_qnan, '10')
1945
1946 def test_is_signed(self):
1947 c = Context()
1948 d = c.is_signed(Decimal(10))
1949 self.assertEqual(c.is_signed(10), d)
1950 self.assertRaises(TypeError, c.is_signed, '10')
1951
1952 def test_is_snan(self):
1953 c = Context()
1954 d = c.is_snan(Decimal(10))
1955 self.assertEqual(c.is_snan(10), d)
1956 self.assertRaises(TypeError, c.is_snan, '10')
1957
1958 def test_is_subnormal(self):
1959 c = Context()
1960 d = c.is_subnormal(Decimal(10))
1961 self.assertEqual(c.is_subnormal(10), d)
1962 self.assertRaises(TypeError, c.is_subnormal, '10')
1963
1964 def test_is_zero(self):
1965 c = Context()
1966 d = c.is_zero(Decimal(10))
1967 self.assertEqual(c.is_zero(10), d)
1968 self.assertRaises(TypeError, c.is_zero, '10')
1969
1970 def test_ln(self):
1971 c = Context()
1972 d = c.ln(Decimal(10))
1973 self.assertEqual(c.ln(10), d)
1974 self.assertRaises(TypeError, c.ln, '10')
1975
1976 def test_log10(self):
1977 c = Context()
1978 d = c.log10(Decimal(10))
1979 self.assertEqual(c.log10(10), d)
1980 self.assertRaises(TypeError, c.log10, '10')
1981
1982 def test_logb(self):
1983 c = Context()
1984 d = c.logb(Decimal(10))
1985 self.assertEqual(c.logb(10), d)
1986 self.assertRaises(TypeError, c.logb, '10')
1987
1988 def test_logical_and(self):
1989 c = Context()
1990 d = c.logical_and(Decimal(1), Decimal(1))
1991 self.assertEqual(c.logical_and(1, 1), d)
1992 self.assertEqual(c.logical_and(Decimal(1), 1), d)
1993 self.assertEqual(c.logical_and(1, Decimal(1)), d)
1994 self.assertRaises(TypeError, c.logical_and, '1', 1)
1995 self.assertRaises(TypeError, c.logical_and, 1, '1')
1996
1997 def test_logical_invert(self):
1998 c = Context()
1999 d = c.logical_invert(Decimal(1000))
2000 self.assertEqual(c.logical_invert(1000), d)
2001 self.assertRaises(TypeError, c.logical_invert, '1000')
2002
2003 def test_logical_or(self):
2004 c = Context()
2005 d = c.logical_or(Decimal(1), Decimal(1))
2006 self.assertEqual(c.logical_or(1, 1), d)
2007 self.assertEqual(c.logical_or(Decimal(1), 1), d)
2008 self.assertEqual(c.logical_or(1, Decimal(1)), d)
2009 self.assertRaises(TypeError, c.logical_or, '1', 1)
2010 self.assertRaises(TypeError, c.logical_or, 1, '1')
2011
2012 def test_logical_xor(self):
2013 c = Context()
2014 d = c.logical_xor(Decimal(1), Decimal(1))
2015 self.assertEqual(c.logical_xor(1, 1), d)
2016 self.assertEqual(c.logical_xor(Decimal(1), 1), d)
2017 self.assertEqual(c.logical_xor(1, Decimal(1)), d)
2018 self.assertRaises(TypeError, c.logical_xor, '1', 1)
2019 self.assertRaises(TypeError, c.logical_xor, 1, '1')
2020
2021 def test_max(self):
2022 c = Context()
2023 d = c.max(Decimal(1), Decimal(2))
2024 self.assertEqual(c.max(1, 2), d)
2025 self.assertEqual(c.max(Decimal(1), 2), d)
2026 self.assertEqual(c.max(1, Decimal(2)), d)
2027 self.assertRaises(TypeError, c.max, '1', 2)
2028 self.assertRaises(TypeError, c.max, 1, '2')
2029
2030 def test_max_mag(self):
2031 c = Context()
2032 d = c.max_mag(Decimal(1), Decimal(2))
2033 self.assertEqual(c.max_mag(1, 2), d)
2034 self.assertEqual(c.max_mag(Decimal(1), 2), d)
2035 self.assertEqual(c.max_mag(1, Decimal(2)), d)
2036 self.assertRaises(TypeError, c.max_mag, '1', 2)
2037 self.assertRaises(TypeError, c.max_mag, 1, '2')
2038
2039 def test_min(self):
2040 c = Context()
2041 d = c.min(Decimal(1), Decimal(2))
2042 self.assertEqual(c.min(1, 2), d)
2043 self.assertEqual(c.min(Decimal(1), 2), d)
2044 self.assertEqual(c.min(1, Decimal(2)), d)
2045 self.assertRaises(TypeError, c.min, '1', 2)
2046 self.assertRaises(TypeError, c.min, 1, '2')
2047
2048 def test_min_mag(self):
2049 c = Context()
2050 d = c.min_mag(Decimal(1), Decimal(2))
2051 self.assertEqual(c.min_mag(1, 2), d)
2052 self.assertEqual(c.min_mag(Decimal(1), 2), d)
2053 self.assertEqual(c.min_mag(1, Decimal(2)), d)
2054 self.assertRaises(TypeError, c.min_mag, '1', 2)
2055 self.assertRaises(TypeError, c.min_mag, 1, '2')
2056
2057 def test_minus(self):
2058 c = Context()
2059 d = c.minus(Decimal(10))
2060 self.assertEqual(c.minus(10), d)
2061 self.assertRaises(TypeError, c.minus, '10')
2062
2063 def test_multiply(self):
2064 c = Context()
2065 d = c.multiply(Decimal(1), Decimal(2))
2066 self.assertEqual(c.multiply(1, 2), d)
2067 self.assertEqual(c.multiply(Decimal(1), 2), d)
2068 self.assertEqual(c.multiply(1, Decimal(2)), d)
2069 self.assertRaises(TypeError, c.multiply, '1', 2)
2070 self.assertRaises(TypeError, c.multiply, 1, '2')
2071
2072 def test_next_minus(self):
2073 c = Context()
2074 d = c.next_minus(Decimal(10))
2075 self.assertEqual(c.next_minus(10), d)
2076 self.assertRaises(TypeError, c.next_minus, '10')
2077
2078 def test_next_plus(self):
2079 c = Context()
2080 d = c.next_plus(Decimal(10))
2081 self.assertEqual(c.next_plus(10), d)
2082 self.assertRaises(TypeError, c.next_plus, '10')
2083
2084 def test_next_toward(self):
2085 c = Context()
2086 d = c.next_toward(Decimal(1), Decimal(2))
2087 self.assertEqual(c.next_toward(1, 2), d)
2088 self.assertEqual(c.next_toward(Decimal(1), 2), d)
2089 self.assertEqual(c.next_toward(1, Decimal(2)), d)
2090 self.assertRaises(TypeError, c.next_toward, '1', 2)
2091 self.assertRaises(TypeError, c.next_toward, 1, '2')
2092
2093 def test_normalize(self):
2094 c = Context()
2095 d = c.normalize(Decimal(10))
2096 self.assertEqual(c.normalize(10), d)
2097 self.assertRaises(TypeError, c.normalize, '10')
2098
2099 def test_number_class(self):
2100 c = Context()
2101 self.assertEqual(c.number_class(123), c.number_class(Decimal(123)))
2102 self.assertEqual(c.number_class(0), c.number_class(Decimal(0)))
2103 self.assertEqual(c.number_class(-45), c.number_class(Decimal(-45)))
2104
2105 def test_power(self):
2106 c = Context()
2107 d = c.power(Decimal(1), Decimal(4), Decimal(2))
2108 self.assertEqual(c.power(1, 4, 2), d)
2109 self.assertEqual(c.power(Decimal(1), 4, 2), d)
2110 self.assertEqual(c.power(1, Decimal(4), 2), d)
2111 self.assertEqual(c.power(1, 4, Decimal(2)), d)
2112 self.assertEqual(c.power(Decimal(1), Decimal(4), 2), d)
2113 self.assertRaises(TypeError, c.power, '1', 4, 2)
2114 self.assertRaises(TypeError, c.power, 1, '4', 2)
2115 self.assertRaises(TypeError, c.power, 1, 4, '2')
2116
2117 def test_plus(self):
2118 c = Context()
2119 d = c.plus(Decimal(10))
2120 self.assertEqual(c.plus(10), d)
2121 self.assertRaises(TypeError, c.plus, '10')
2122
2123 def test_quantize(self):
2124 c = Context()
2125 d = c.quantize(Decimal(1), Decimal(2))
2126 self.assertEqual(c.quantize(1, 2), d)
2127 self.assertEqual(c.quantize(Decimal(1), 2), d)
2128 self.assertEqual(c.quantize(1, Decimal(2)), d)
2129 self.assertRaises(TypeError, c.quantize, '1', 2)
2130 self.assertRaises(TypeError, c.quantize, 1, '2')
2131
2132 def test_remainder(self):
2133 c = Context()
2134 d = c.remainder(Decimal(1), Decimal(2))
2135 self.assertEqual(c.remainder(1, 2), d)
2136 self.assertEqual(c.remainder(Decimal(1), 2), d)
2137 self.assertEqual(c.remainder(1, Decimal(2)), d)
2138 self.assertRaises(TypeError, c.remainder, '1', 2)
2139 self.assertRaises(TypeError, c.remainder, 1, '2')
2140
2141 def test_remainder_near(self):
2142 c = Context()
2143 d = c.remainder_near(Decimal(1), Decimal(2))
2144 self.assertEqual(c.remainder_near(1, 2), d)
2145 self.assertEqual(c.remainder_near(Decimal(1), 2), d)
2146 self.assertEqual(c.remainder_near(1, Decimal(2)), d)
2147 self.assertRaises(TypeError, c.remainder_near, '1', 2)
2148 self.assertRaises(TypeError, c.remainder_near, 1, '2')
2149
2150 def test_rotate(self):
2151 c = Context()
2152 d = c.rotate(Decimal(1), Decimal(2))
2153 self.assertEqual(c.rotate(1, 2), d)
2154 self.assertEqual(c.rotate(Decimal(1), 2), d)
2155 self.assertEqual(c.rotate(1, Decimal(2)), d)
2156 self.assertRaises(TypeError, c.rotate, '1', 2)
2157 self.assertRaises(TypeError, c.rotate, 1, '2')
2158
2159 def test_sqrt(self):
2160 c = Context()
2161 d = c.sqrt(Decimal(10))
2162 self.assertEqual(c.sqrt(10), d)
2163 self.assertRaises(TypeError, c.sqrt, '10')
2164
2165 def test_same_quantum(self):
2166 c = Context()
2167 d = c.same_quantum(Decimal(1), Decimal(2))
2168 self.assertEqual(c.same_quantum(1, 2), d)
2169 self.assertEqual(c.same_quantum(Decimal(1), 2), d)
2170 self.assertEqual(c.same_quantum(1, Decimal(2)), d)
2171 self.assertRaises(TypeError, c.same_quantum, '1', 2)
2172 self.assertRaises(TypeError, c.same_quantum, 1, '2')
2173
2174 def test_scaleb(self):
2175 c = Context()
2176 d = c.scaleb(Decimal(1), Decimal(2))
2177 self.assertEqual(c.scaleb(1, 2), d)
2178 self.assertEqual(c.scaleb(Decimal(1), 2), d)
2179 self.assertEqual(c.scaleb(1, Decimal(2)), d)
2180 self.assertRaises(TypeError, c.scaleb, '1', 2)
2181 self.assertRaises(TypeError, c.scaleb, 1, '2')
2182
2183 def test_shift(self):
2184 c = Context()
2185 d = c.shift(Decimal(1), Decimal(2))
2186 self.assertEqual(c.shift(1, 2), d)
2187 self.assertEqual(c.shift(Decimal(1), 2), d)
2188 self.assertEqual(c.shift(1, Decimal(2)), d)
2189 self.assertRaises(TypeError, c.shift, '1', 2)
2190 self.assertRaises(TypeError, c.shift, 1, '2')
2191
2192 def test_subtract(self):
2193 c = Context()
2194 d = c.subtract(Decimal(1), Decimal(2))
2195 self.assertEqual(c.subtract(1, 2), d)
2196 self.assertEqual(c.subtract(Decimal(1), 2), d)
2197 self.assertEqual(c.subtract(1, Decimal(2)), d)
2198 self.assertRaises(TypeError, c.subtract, '1', 2)
2199 self.assertRaises(TypeError, c.subtract, 1, '2')
2200
2201 def test_to_eng_string(self):
2202 c = Context()
2203 d = c.to_eng_string(Decimal(10))
2204 self.assertEqual(c.to_eng_string(10), d)
2205 self.assertRaises(TypeError, c.to_eng_string, '10')
2206
2207 def test_to_sci_string(self):
2208 c = Context()
2209 d = c.to_sci_string(Decimal(10))
2210 self.assertEqual(c.to_sci_string(10), d)
2211 self.assertRaises(TypeError, c.to_sci_string, '10')
2212
2213 def test_to_integral_exact(self):
2214 c = Context()
2215 d = c.to_integral_exact(Decimal(10))
2216 self.assertEqual(c.to_integral_exact(10), d)
2217 self.assertRaises(TypeError, c.to_integral_exact, '10')
2218
2219 def test_to_integral_value(self):
2220 c = Context()
2221 d = c.to_integral_value(Decimal(10))
2222 self.assertEqual(c.to_integral_value(10), d)
2223 self.assertRaises(TypeError, c.to_integral_value, '10')
2224
Thomas Wouters89f507f2006-12-13 04:49:30 +00002225class WithStatementTest(unittest.TestCase):
2226 # Can't do these as docstrings until Python 2.6
2227 # as doctest can't handle __future__ statements
2228
2229 def test_localcontext(self):
2230 # Use a copy of the current context in the block
2231 orig_ctx = getcontext()
2232 with localcontext() as enter_ctx:
2233 set_ctx = getcontext()
2234 final_ctx = getcontext()
Ezio Melotti6607d512010-04-03 14:59:49 +00002235 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
2236 self.assertIsNot(orig_ctx, set_ctx, 'did not copy the context')
2237 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
Thomas Wouters89f507f2006-12-13 04:49:30 +00002238
2239 def test_localcontextarg(self):
2240 # Use a copy of the supplied context in the block
2241 orig_ctx = getcontext()
2242 new_ctx = Context(prec=42)
2243 with localcontext(new_ctx) as enter_ctx:
2244 set_ctx = getcontext()
2245 final_ctx = getcontext()
Ezio Melotti6607d512010-04-03 14:59:49 +00002246 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
2247 self.assertEqual(set_ctx.prec, new_ctx.prec, 'did not set correct context')
2248 self.assertIsNot(new_ctx, set_ctx, 'did not copy the context')
2249 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
Thomas Wouters89f507f2006-12-13 04:49:30 +00002250
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002251class ContextFlags(unittest.TestCase):
2252 def test_flags_irrelevant(self):
2253 # check that the result (numeric result + flags raised) of an
2254 # arithmetic operation doesn't depend on the current flags
2255
2256 context = Context(prec=9, Emin = -999999999, Emax = 999999999,
2257 rounding=ROUND_HALF_EVEN, traps=[], flags=[])
2258
2259 # operations that raise various flags, in the form (function, arglist)
2260 operations = [
2261 (context._apply, [Decimal("100E-1000000009")]),
2262 (context.sqrt, [Decimal(2)]),
2263 (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]),
2264 (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]),
2265 (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]),
2266 ]
2267
2268 # try various flags individually, then a whole lot at once
2269 flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal],
2270 [Inexact, Rounded, Underflow, Clamped, Subnormal]]
2271
2272 for fn, args in operations:
2273 # find answer and flags raised using a clean context
2274 context.clear_flags()
2275 ans = fn(*args)
2276 flags = [k for k, v in context.flags.items() if v]
2277
2278 for extra_flags in flagsets:
2279 # set flags, before calling operation
2280 context.clear_flags()
2281 for flag in extra_flags:
2282 context._raise_error(flag)
2283 new_ans = fn(*args)
2284
2285 # flags that we expect to be set after the operation
2286 expected_flags = list(flags)
2287 for flag in extra_flags:
2288 if flag not in expected_flags:
2289 expected_flags.append(flag)
2290 expected_flags.sort(key=id)
2291
2292 # flags we actually got
2293 new_flags = [k for k,v in context.flags.items() if v]
2294 new_flags.sort(key=id)
2295
2296 self.assertEqual(ans, new_ans,
2297 "operation produces different answers depending on flags set: " +
2298 "expected %s, got %s." % (ans, new_ans))
2299 self.assertEqual(new_flags, expected_flags,
2300 "operation raises different flags depending on flags set: " +
2301 "expected %s, got %s" % (expected_flags, new_flags))
2302
2303def test_main(arith=False, verbose=None, todo_tests=None, debug=None):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002304 """ Execute the tests.
2305
Raymond Hettingered20ad82004-09-04 20:09:13 +00002306 Runs all arithmetic tests if arith is True or if the "decimal" resource
2307 is enabled in regrtest.py
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002308 """
Raymond Hettingered20ad82004-09-04 20:09:13 +00002309
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002310 init()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002311 global TEST_ALL, DEBUG
Raymond Hettingered20ad82004-09-04 20:09:13 +00002312 TEST_ALL = arith or is_resource_enabled('decimal')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002313 DEBUG = debug
Raymond Hettingered20ad82004-09-04 20:09:13 +00002314
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002315 if todo_tests is None:
2316 test_classes = [
2317 DecimalExplicitConstructionTest,
2318 DecimalImplicitConstructionTest,
2319 DecimalArithmeticOperatorsTest,
Christian Heimesf16baeb2008-02-29 14:57:44 +00002320 DecimalFormatTest,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002321 DecimalUseOfContextTest,
2322 DecimalUsabilityTest,
2323 DecimalPythonAPItests,
2324 ContextAPItests,
2325 DecimalTest,
2326 WithStatementTest,
2327 ContextFlags
2328 ]
2329 else:
2330 test_classes = [DecimalTest]
2331
2332 # Dynamically build custom test definition for each file in the test
2333 # directory and add the definitions to the DecimalTest class. This
2334 # procedure insures that new files do not get skipped.
2335 for filename in os.listdir(directory):
2336 if '.decTest' not in filename or filename.startswith("."):
2337 continue
2338 head, tail = filename.split('.')
2339 if todo_tests is not None and head not in todo_tests:
2340 continue
2341 tester = lambda self, f=filename: self.eval_file(directory + f)
2342 setattr(DecimalTest, 'test_' + head, tester)
2343 del filename, head, tail, tester
2344
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002345
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002346 try:
2347 run_unittest(*test_classes)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002348 if todo_tests is None:
2349 import decimal as DecimalModule
2350 run_doctest(DecimalModule, verbose)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002351 finally:
2352 setcontext(ORIGINAL_CONTEXT)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002353
2354if __name__ == '__main__':
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002355 import optparse
2356 p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]")
2357 p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test')
2358 p.add_option('--skip', '-s', action='store_true', help='skip over 90% of the arithmetic tests')
2359 (opt, args) = p.parse_args()
2360
2361 if opt.skip:
2362 test_main(arith=False, verbose=True)
2363 elif args:
2364 test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002365 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002366 test_main(arith=True, verbose=True)