blob: 360a5e89b2d07a2120e5085942cda17e30e37209 [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
29import pickle, copy
Christian Heimes400adb02008-02-01 08:12:03 +000030import unittest
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000031from decimal import *
Raymond Hettinger82417ca2009-02-03 03:54:28 +000032import numbers
Benjamin Petersone549ead2009-03-28 21:42:05 +000033from test.support import run_unittest, run_doctest, is_resource_enabled
Raymond Hettinger0aeac102004-07-05 22:53:03 +000034import random
Raymond Hettinger7e71fa52004-12-18 19:07:19 +000035try:
36 import threading
37except ImportError:
38 threading = None
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000039
Raymond Hettingerfed52962004-07-14 15:41:57 +000040# Useful Test Constant
Guido van Rossumc1f779c2007-07-03 08:25:58 +000041Signals = tuple(getcontext().flags.keys())
Raymond Hettingerfed52962004-07-14 15:41:57 +000042
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000043# Tests are built around these assumed context defaults.
44# test_main() restores the original context.
45def init():
46 global ORIGINAL_CONTEXT
47 ORIGINAL_CONTEXT = getcontext().copy()
Christian Heimes81ee3ef2008-05-04 22:42:01 +000048 DefaultTestContext = Context(
49 prec = 9,
50 rounding = ROUND_HALF_EVEN,
51 traps = dict.fromkeys(Signals, 0)
52 )
53 setcontext(DefaultTestContext)
Raymond Hettinger6ea48452004-07-03 12:26:21 +000054
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000055TESTDATADIR = 'decimaltestdata'
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +000056if __name__ == '__main__':
57 file = sys.argv[0]
58else:
59 file = __file__
60testdir = os.path.dirname(file) or os.curdir
Raymond Hettinger267b8682005-03-27 10:47:39 +000061directory = testdir + os.sep + TESTDATADIR + os.sep
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000062
Raymond Hettinger267b8682005-03-27 10:47:39 +000063skip_expected = not os.path.isdir(directory)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000064
Mark Dickinson8a546532009-10-08 16:30:38 +000065# list of individual .decTest test ids that correspond to tests that
66# we're skipping for one reason or another.
67skipped_test_ids = [
68 'scbx164', # skipping apparently implementation-specific scaleb
69 'scbx165', # tests, pending clarification of scaleb rules.
70]
71
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000072# Make sure it actually raises errors when not expected and caught in flags
73# Slower, since it runs some things several times.
74EXTENDEDERRORTEST = False
75
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000076#Map the test cases' error names to the actual errors
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000077ErrorNames = {'clamped' : Clamped,
Raymond Hettinger5aa478b2004-07-09 10:02:53 +000078 'conversion_syntax' : InvalidOperation,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000079 'division_by_zero' : DivisionByZero,
Raymond Hettinger5aa478b2004-07-09 10:02:53 +000080 'division_impossible' : InvalidOperation,
81 'division_undefined' : InvalidOperation,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000082 'inexact' : Inexact,
Raymond Hettinger5aa478b2004-07-09 10:02:53 +000083 'invalid_context' : InvalidOperation,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000084 'invalid_operation' : InvalidOperation,
85 'overflow' : Overflow,
86 'rounded' : Rounded,
87 'subnormal' : Subnormal,
88 'underflow' : Underflow}
89
90
91def Nonfunction(*args):
92 """Doesn't do anything."""
93 return None
94
95RoundingDict = {'ceiling' : ROUND_CEILING, #Maps test-case names to roundings.
96 'down' : ROUND_DOWN,
97 'floor' : ROUND_FLOOR,
98 'half_down' : ROUND_HALF_DOWN,
99 'half_even' : ROUND_HALF_EVEN,
100 'half_up' : ROUND_HALF_UP,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000101 'up' : ROUND_UP,
102 '05up' : ROUND_05UP}
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000103
104# Name adapter to be able to change the Decimal and Context
105# interface without changing the test files from Cowlishaw
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000106nameAdapter = {'and':'logical_and',
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000107 'apply':'_apply',
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000108 'class':'number_class',
109 'comparesig':'compare_signal',
110 'comparetotal':'compare_total',
111 'comparetotmag':'compare_total_mag',
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000112 'copy':'copy_decimal',
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000113 'copyabs':'copy_abs',
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000114 'copynegate':'copy_negate',
115 'copysign':'copy_sign',
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000116 'divideint':'divide_int',
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000117 'invert':'logical_invert',
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000118 'iscanonical':'is_canonical',
119 'isfinite':'is_finite',
120 'isinfinite':'is_infinite',
121 'isnan':'is_nan',
122 'isnormal':'is_normal',
123 'isqnan':'is_qnan',
124 'issigned':'is_signed',
125 'issnan':'is_snan',
126 'issubnormal':'is_subnormal',
127 'iszero':'is_zero',
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000128 'maxmag':'max_mag',
129 'minmag':'min_mag',
130 'nextminus':'next_minus',
131 'nextplus':'next_plus',
132 'nexttoward':'next_toward',
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000133 'or':'logical_or',
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000134 'reduce':'normalize',
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000135 'remaindernear':'remainder_near',
136 'samequantum':'same_quantum',
137 'squareroot':'sqrt',
138 'toeng':'to_eng_string',
139 'tointegral':'to_integral_value',
140 'tointegralx':'to_integral_exact',
141 'tosci':'to_sci_string',
142 'xor':'logical_xor',
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000143 }
144
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000145# The following functions return True/False rather than a Decimal instance
146
147LOGICAL_FUNCTIONS = (
148 'is_canonical',
149 'is_finite',
150 'is_infinite',
151 'is_nan',
152 'is_normal',
153 'is_qnan',
154 'is_signed',
155 'is_snan',
156 'is_subnormal',
157 'is_zero',
158 'same_quantum',
159 )
160
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000161# For some operations (currently exp, ln, log10, power), the decNumber
162# reference implementation imposes additional restrictions on the
163# context and operands. These restrictions are not part of the
164# specification; however, the effect of these restrictions does show
165# up in some of the testcases. We skip testcases that violate these
166# restrictions, since Decimal behaves differently from decNumber for
167# these testcases so these testcases would otherwise fail.
168
169decNumberRestricted = ('power', 'ln', 'log10', 'exp')
170DEC_MAX_MATH = 999999
171def outside_decNumber_bounds(v, context):
172 if (context.prec > DEC_MAX_MATH or
173 context.Emax > DEC_MAX_MATH or
174 -context.Emin > DEC_MAX_MATH):
175 return True
176 if not v._is_special and v and (
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000177 v.adjusted() > DEC_MAX_MATH or
178 v.adjusted() < 1-2*DEC_MAX_MATH):
179 return True
180 return False
181
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000182class DecimalTest(unittest.TestCase):
183 """Class which tests the Decimal class against the test cases.
184
185 Changed for unittest.
186 """
187 def setUp(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000188 self.context = Context()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000189 self.ignore_list = ['#']
190 # Basically, a # means return NaN InvalidOperation.
191 # Different from a sNaN in trim
192
193 self.ChangeDict = {'precision' : self.change_precision,
194 'rounding' : self.change_rounding_method,
195 'maxexponent' : self.change_max_exponent,
196 'minexponent' : self.change_min_exponent,
197 'clamp' : self.change_clamp}
198
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000199 def eval_file(self, file):
200 global skip_expected
201 if skip_expected:
Benjamin Petersone549ead2009-03-28 21:42:05 +0000202 raise unittest.SkipTest
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000203 return
Neal Norwitz70967602006-03-17 08:29:44 +0000204 for line in open(file):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000205 line = line.replace('\r\n', '').replace('\n', '')
Raymond Hettinger5aa478b2004-07-09 10:02:53 +0000206 #print line
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000207 try:
208 t = self.eval_line(line)
Guido van Rossumb940e112007-01-10 16:19:56 +0000209 except DecimalException as exception:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000210 #Exception raised where there shoudn't have been one.
211 self.fail('Exception "'+exception.__class__.__name__ + '" raised on line '+line)
212
213 return
214
215 def eval_line(self, s):
216 if s.find(' -> ') >= 0 and s[:2] != '--' and not s.startswith(' --'):
217 s = (s.split('->')[0] + '->' +
218 s.split('->')[1].split('--')[0]).strip()
219 else:
220 s = s.split('--')[0].strip()
221
222 for ignore in self.ignore_list:
223 if s.find(ignore) >= 0:
224 #print s.split()[0], 'NotImplemented--', ignore
225 return
226 if not s:
227 return
228 elif ':' in s:
229 return self.eval_directive(s)
230 else:
231 return self.eval_equation(s)
232
233 def eval_directive(self, s):
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000234 funct, value = (x.strip().lower() for x in s.split(':'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000235 if funct == 'rounding':
236 value = RoundingDict[value]
237 else:
238 try:
239 value = int(value)
240 except ValueError:
241 pass
242
243 funct = self.ChangeDict.get(funct, Nonfunction)
244 funct(value)
245
246 def eval_equation(self, s):
247 #global DEFAULT_PRECISION
248 #print DEFAULT_PRECISION
Raymond Hettingered20ad82004-09-04 20:09:13 +0000249
250 if not TEST_ALL and random.random() < 0.90:
251 return
252
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000253 try:
254 Sides = s.split('->')
255 L = Sides[0].strip().split()
256 id = L[0]
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000257 if DEBUG:
258 print("Test ", id, end=" ")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000259 funct = L[1].lower()
260 valstemp = L[2:]
261 L = Sides[1].strip().split()
262 ans = L[0]
263 exceptions = L[1:]
264 except (TypeError, AttributeError, IndexError):
Raymond Hettingerd87ac8f2004-07-09 10:52:54 +0000265 raise InvalidOperation
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000266 def FixQuotes(val):
267 val = val.replace("''", 'SingleQuote').replace('""', 'DoubleQuote')
268 val = val.replace("'", '').replace('"', '')
269 val = val.replace('SingleQuote', "'").replace('DoubleQuote', '"')
270 return val
Mark Dickinson8a546532009-10-08 16:30:38 +0000271
272 if id in skipped_test_ids:
273 return
274
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000275 fname = nameAdapter.get(funct, funct)
276 if fname == 'rescale':
277 return
278 funct = getattr(self.context, fname)
279 vals = []
280 conglomerate = ''
281 quote = 0
282 theirexceptions = [ErrorNames[x.lower()] for x in exceptions]
283
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000284 for exception in Signals:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000285 self.context.traps[exception] = 1 #Catch these bugs...
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000286 for exception in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000287 self.context.traps[exception] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000288 for i, val in enumerate(valstemp):
289 if val.count("'") % 2 == 1:
290 quote = 1 - quote
291 if quote:
292 conglomerate = conglomerate + ' ' + val
293 continue
294 else:
295 val = conglomerate + val
296 conglomerate = ''
297 v = FixQuotes(val)
298 if fname in ('to_sci_string', 'to_eng_string'):
299 if EXTENDEDERRORTEST:
300 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000301 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000302 try:
303 funct(self.context.create_decimal(v))
304 except error:
305 pass
Guido van Rossumb940e112007-01-10 16:19:56 +0000306 except Signals as e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000307 self.fail("Raised %s in %s when %s disabled" % \
308 (e, s, error))
309 else:
310 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000311 self.context.traps[error] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000312 v = self.context.create_decimal(v)
313 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000314 v = Decimal(v, self.context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000315 vals.append(v)
316
317 ans = FixQuotes(ans)
318
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000319 # skip tests that are related to bounds imposed in the decNumber
320 # reference implementation
321 if fname in decNumberRestricted:
322 if fname == 'power':
323 if not (vals[1]._isinteger() and
324 -1999999997 <= vals[1] <= 999999999):
325 if outside_decNumber_bounds(vals[0], self.context) or \
326 outside_decNumber_bounds(vals[1], self.context):
327 #print "Skipping test %s" % s
328 return
329 else:
330 if outside_decNumber_bounds(vals[0], self.context):
331 #print "Skipping test %s" % s
332 return
333
334
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000335 if EXTENDEDERRORTEST and fname not in ('to_sci_string', 'to_eng_string'):
336 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000337 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000338 try:
339 funct(*vals)
340 except error:
341 pass
Guido van Rossumb940e112007-01-10 16:19:56 +0000342 except Signals as e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000343 self.fail("Raised %s in %s when %s disabled" % \
344 (e, s, error))
345 else:
346 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000347 self.context.traps[error] = 0
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000348 if DEBUG:
349 print("--", self.context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000350 try:
351 result = str(funct(*vals))
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000352 if fname in LOGICAL_FUNCTIONS:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000353 result = str(int(eval(result))) # 'True', 'False' -> '1', '0'
Guido van Rossumb940e112007-01-10 16:19:56 +0000354 except Signals as error:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000355 self.fail("Raised %s in %s" % (error, s))
356 except: #Catch any error long enough to state the test case.
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000357 print("ERROR:", s)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000358 raise
359
360 myexceptions = self.getexceptions()
Raymond Hettingerbf440692004-07-10 14:14:37 +0000361 self.context.clear_flags()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000362
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000363 myexceptions.sort(key=repr)
364 theirexceptions.sort(key=repr)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000365
366 self.assertEqual(result, ans,
367 'Incorrect answer for ' + s + ' -- got ' + result)
368 self.assertEqual(myexceptions, theirexceptions,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000369 'Incorrect flags set in ' + s + ' -- got ' + str(myexceptions))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000370 return
371
372 def getexceptions(self):
Raymond Hettingerf63ba432004-08-17 05:42:09 +0000373 return [e for e in Signals if self.context.flags[e]]
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000374
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000375 def change_precision(self, prec):
376 self.context.prec = prec
377 def change_rounding_method(self, rounding):
378 self.context.rounding = rounding
379 def change_min_exponent(self, exp):
380 self.context.Emin = exp
381 def change_max_exponent(self, exp):
382 self.context.Emax = exp
383 def change_clamp(self, clamp):
384 self.context._clamp = clamp
385
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000386
387
388# The following classes test the behaviour of Decimal according to PEP 327
389
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000390class DecimalExplicitConstructionTest(unittest.TestCase):
391 '''Unit tests for Explicit Construction cases of Decimal.'''
392
393 def test_explicit_empty(self):
394 self.assertEqual(Decimal(), Decimal("0"))
395
396 def test_explicit_from_None(self):
397 self.assertRaises(TypeError, Decimal, None)
398
399 def test_explicit_from_int(self):
400
401 #positive
402 d = Decimal(45)
403 self.assertEqual(str(d), '45')
404
405 #very large positive
406 d = Decimal(500000123)
407 self.assertEqual(str(d), '500000123')
408
409 #negative
410 d = Decimal(-45)
411 self.assertEqual(str(d), '-45')
412
413 #zero
414 d = Decimal(0)
415 self.assertEqual(str(d), '0')
416
417 def test_explicit_from_string(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000418
419 #empty
420 self.assertEqual(str(Decimal('')), 'NaN')
421
422 #int
423 self.assertEqual(str(Decimal('45')), '45')
424
425 #float
426 self.assertEqual(str(Decimal('45.34')), '45.34')
427
428 #engineer notation
429 self.assertEqual(str(Decimal('45e2')), '4.5E+3')
430
431 #just not a number
432 self.assertEqual(str(Decimal('ugly')), 'NaN')
433
Christian Heimesa62da1d2008-01-12 19:39:10 +0000434 #leading and trailing whitespace permitted
435 self.assertEqual(str(Decimal('1.3E4 \n')), '1.3E+4')
436 self.assertEqual(str(Decimal(' -7.89')), '-7.89')
437
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000438 def test_explicit_from_tuples(self):
439
440 #zero
441 d = Decimal( (0, (0,), 0) )
442 self.assertEqual(str(d), '0')
443
444 #int
445 d = Decimal( (1, (4, 5), 0) )
446 self.assertEqual(str(d), '-45')
447
448 #float
449 d = Decimal( (0, (4, 5, 3, 4), -2) )
450 self.assertEqual(str(d), '45.34')
451
452 #weird
453 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
454 self.assertEqual(str(d), '-4.34913534E-17')
455
456 #wrong number of items
457 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1)) )
458
459 #bad sign
460 self.assertRaises(ValueError, Decimal, (8, (4, 3, 4, 9, 1), 2) )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000461 self.assertRaises(ValueError, Decimal, (0., (4, 3, 4, 9, 1), 2) )
462 self.assertRaises(ValueError, Decimal, (Decimal(1), (4, 3, 4, 9, 1), 2))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000463
464 #bad exp
465 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 'wrong!') )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000466 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 0.) )
467 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), '1') )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000468
469 #bad coefficients
470 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, None, 1), 2) )
471 self.assertRaises(ValueError, Decimal, (1, (4, -3, 4, 9, 1), 2) )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000472 self.assertRaises(ValueError, Decimal, (1, (4, 10, 4, 9, 1), 2) )
Guido van Rossum0d3fb8a2007-11-26 23:23:18 +0000473 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 'a', 1), 2) )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000474
Antoine Pitrou503ab332010-03-30 18:56:19 +0000475 def test_explicit_from_bool(self):
476 self.assertIs(bool(Decimal(0)), False)
477 self.assertIs(bool(Decimal(1)), True)
478 self.assertEqual(Decimal(False), Decimal(0))
479 self.assertEqual(Decimal(True), Decimal(1))
480
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000481 def test_explicit_from_Decimal(self):
482
483 #positive
484 d = Decimal(45)
485 e = Decimal(d)
486 self.assertEqual(str(e), '45')
487 self.assertNotEqual(id(d), id(e))
488
489 #very large positive
490 d = Decimal(500000123)
491 e = Decimal(d)
492 self.assertEqual(str(e), '500000123')
493 self.assertNotEqual(id(d), id(e))
494
495 #negative
496 d = Decimal(-45)
497 e = Decimal(d)
498 self.assertEqual(str(e), '-45')
499 self.assertNotEqual(id(d), id(e))
500
501 #zero
502 d = Decimal(0)
503 e = Decimal(d)
504 self.assertEqual(str(e), '0')
505 self.assertNotEqual(id(d), id(e))
506
507 def test_explicit_context_create_decimal(self):
508
509 nc = copy.copy(getcontext())
510 nc.prec = 3
511
512 # empty
Raymond Hettingerfed52962004-07-14 15:41:57 +0000513 d = Decimal()
514 self.assertEqual(str(d), '0')
515 d = nc.create_decimal()
516 self.assertEqual(str(d), '0')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000517
518 # from None
519 self.assertRaises(TypeError, nc.create_decimal, None)
520
521 # from int
522 d = nc.create_decimal(456)
Ezio Melottie9615932010-01-24 19:26:24 +0000523 self.assertIsInstance(d, Decimal)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000524 self.assertEqual(nc.create_decimal(45678),
525 nc.create_decimal('457E+2'))
526
527 # from string
528 d = Decimal('456789')
529 self.assertEqual(str(d), '456789')
530 d = nc.create_decimal('456789')
531 self.assertEqual(str(d), '4.57E+5')
Christian Heimesa62da1d2008-01-12 19:39:10 +0000532 # leading and trailing whitespace should result in a NaN;
533 # spaces are already checked in Cowlishaw's test-suite, so
534 # here we just check that a trailing newline results in a NaN
535 self.assertEqual(str(nc.create_decimal('3.14\n')), 'NaN')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000536
537 # from tuples
538 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
539 self.assertEqual(str(d), '-4.34913534E-17')
540 d = nc.create_decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
541 self.assertEqual(str(d), '-4.35E-17')
542
543 # from Decimal
544 prevdec = Decimal(500000123)
545 d = Decimal(prevdec)
546 self.assertEqual(str(d), '500000123')
547 d = nc.create_decimal(prevdec)
548 self.assertEqual(str(d), '5.00E+8')
549
Mark Dickinson345adc42009-08-02 10:14:23 +0000550 def test_unicode_digits(self):
551 test_values = {
552 '\uff11': '1',
553 '\u0660.\u0660\u0663\u0667\u0662e-\u0663' : '0.0000372',
554 '-nan\u0c68\u0c6a\u0c66\u0c66' : '-NaN2400',
555 }
556 for input, expected in test_values.items():
557 self.assertEqual(str(Decimal(input)), expected)
558
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000559
560class DecimalImplicitConstructionTest(unittest.TestCase):
561 '''Unit tests for Implicit Construction cases of Decimal.'''
562
563 def test_implicit_from_None(self):
564 self.assertRaises(TypeError, eval, 'Decimal(5) + None', globals())
565
566 def test_implicit_from_int(self):
567 #normal
568 self.assertEqual(str(Decimal(5) + 45), '50')
569 #exceeding precision
570 self.assertEqual(Decimal(5) + 123456789000, Decimal(123456789000))
571
572 def test_implicit_from_string(self):
573 self.assertRaises(TypeError, eval, 'Decimal(5) + "3"', globals())
574
575 def test_implicit_from_float(self):
576 self.assertRaises(TypeError, eval, 'Decimal(5) + 2.2', globals())
577
578 def test_implicit_from_Decimal(self):
579 self.assertEqual(Decimal(5) + Decimal(45), Decimal(50))
580
Raymond Hettinger267b8682005-03-27 10:47:39 +0000581 def test_rop(self):
582 # Allow other classes to be trained to interact with Decimals
583 class E:
584 def __divmod__(self, other):
585 return 'divmod ' + str(other)
586 def __rdivmod__(self, other):
587 return str(other) + ' rdivmod'
588 def __lt__(self, other):
589 return 'lt ' + str(other)
590 def __gt__(self, other):
591 return 'gt ' + str(other)
592 def __le__(self, other):
593 return 'le ' + str(other)
594 def __ge__(self, other):
595 return 'ge ' + str(other)
596 def __eq__(self, other):
597 return 'eq ' + str(other)
598 def __ne__(self, other):
599 return 'ne ' + str(other)
600
601 self.assertEqual(divmod(E(), Decimal(10)), 'divmod 10')
602 self.assertEqual(divmod(Decimal(10), E()), '10 rdivmod')
603 self.assertEqual(eval('Decimal(10) < E()'), 'gt 10')
604 self.assertEqual(eval('Decimal(10) > E()'), 'lt 10')
605 self.assertEqual(eval('Decimal(10) <= E()'), 'ge 10')
606 self.assertEqual(eval('Decimal(10) >= E()'), 'le 10')
607 self.assertEqual(eval('Decimal(10) == E()'), 'eq 10')
608 self.assertEqual(eval('Decimal(10) != E()'), 'ne 10')
609
610 # insert operator methods and then exercise them
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000611 oplist = [
612 ('+', '__add__', '__radd__'),
613 ('-', '__sub__', '__rsub__'),
614 ('*', '__mul__', '__rmul__'),
Thomas Woutersdcc6d322006-04-21 11:30:52 +0000615 ('/', '__truediv__', '__rtruediv__'),
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000616 ('%', '__mod__', '__rmod__'),
617 ('//', '__floordiv__', '__rfloordiv__'),
618 ('**', '__pow__', '__rpow__')
619 ]
Raymond Hettinger267b8682005-03-27 10:47:39 +0000620
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000621 for sym, lop, rop in oplist:
Raymond Hettinger267b8682005-03-27 10:47:39 +0000622 setattr(E, lop, lambda self, other: 'str' + lop + str(other))
623 setattr(E, rop, lambda self, other: str(other) + rop + 'str')
624 self.assertEqual(eval('E()' + sym + 'Decimal(10)'),
625 'str' + lop + '10')
626 self.assertEqual(eval('Decimal(10)' + sym + 'E()'),
627 '10' + rop + 'str')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000628
Mark Dickinson79f52032009-03-17 23:12:51 +0000629
Christian Heimesf16baeb2008-02-29 14:57:44 +0000630class DecimalFormatTest(unittest.TestCase):
631 '''Unit tests for the format function.'''
632 def test_formatting(self):
633 # triples giving a format, a Decimal, and the expected result
634 test_values = [
635 ('e', '0E-15', '0e-15'),
636 ('e', '2.3E-15', '2.3e-15'),
637 ('e', '2.30E+2', '2.30e+2'), # preserve significant zeros
638 ('e', '2.30000E-15', '2.30000e-15'),
639 ('e', '1.23456789123456789e40', '1.23456789123456789e+40'),
640 ('e', '1.5', '1.5e+0'),
641 ('e', '0.15', '1.5e-1'),
642 ('e', '0.015', '1.5e-2'),
643 ('e', '0.0000000000015', '1.5e-12'),
644 ('e', '15.0', '1.50e+1'),
645 ('e', '-15', '-1.5e+1'),
646 ('e', '0', '0e+0'),
647 ('e', '0E1', '0e+1'),
648 ('e', '0.0', '0e-1'),
649 ('e', '0.00', '0e-2'),
650 ('.6e', '0E-15', '0.000000e-9'),
651 ('.6e', '0', '0.000000e+6'),
652 ('.6e', '9.999999', '9.999999e+0'),
653 ('.6e', '9.9999999', '1.000000e+1'),
654 ('.6e', '-1.23e5', '-1.230000e+5'),
655 ('.6e', '1.23456789e-3', '1.234568e-3'),
656 ('f', '0', '0'),
657 ('f', '0.0', '0.0'),
658 ('f', '0E-2', '0.00'),
659 ('f', '0.00E-8', '0.0000000000'),
660 ('f', '0E1', '0'), # loses exponent information
661 ('f', '3.2E1', '32'),
662 ('f', '3.2E2', '320'),
663 ('f', '3.20E2', '320'),
664 ('f', '3.200E2', '320.0'),
665 ('f', '3.2E-6', '0.0000032'),
666 ('.6f', '0E-15', '0.000000'), # all zeros treated equally
667 ('.6f', '0E1', '0.000000'),
668 ('.6f', '0', '0.000000'),
669 ('.0f', '0', '0'), # no decimal point
670 ('.0f', '0e-2', '0'),
671 ('.0f', '3.14159265', '3'),
672 ('.1f', '3.14159265', '3.1'),
673 ('.4f', '3.14159265', '3.1416'),
674 ('.6f', '3.14159265', '3.141593'),
675 ('.7f', '3.14159265', '3.1415926'), # round-half-even!
676 ('.8f', '3.14159265', '3.14159265'),
677 ('.9f', '3.14159265', '3.141592650'),
678
679 ('g', '0', '0'),
680 ('g', '0.0', '0.0'),
681 ('g', '0E1', '0e+1'),
682 ('G', '0E1', '0E+1'),
683 ('g', '0E-5', '0.00000'),
684 ('g', '0E-6', '0.000000'),
685 ('g', '0E-7', '0e-7'),
686 ('g', '-0E2', '-0e+2'),
687 ('.0g', '3.14159265', '3'), # 0 sig fig -> 1 sig fig
688 ('.1g', '3.14159265', '3'),
689 ('.2g', '3.14159265', '3.1'),
690 ('.5g', '3.14159265', '3.1416'),
691 ('.7g', '3.14159265', '3.141593'),
692 ('.8g', '3.14159265', '3.1415926'), # round-half-even!
693 ('.9g', '3.14159265', '3.14159265'),
694 ('.10g', '3.14159265', '3.14159265'), # don't pad
695
696 ('%', '0E1', '0%'),
697 ('%', '0E0', '0%'),
698 ('%', '0E-1', '0%'),
699 ('%', '0E-2', '0%'),
700 ('%', '0E-3', '0.0%'),
701 ('%', '0E-4', '0.00%'),
702
703 ('.3%', '0', '0.000%'), # all zeros treated equally
704 ('.3%', '0E10', '0.000%'),
705 ('.3%', '0E-10', '0.000%'),
706 ('.3%', '2.34', '234.000%'),
707 ('.3%', '1.234567', '123.457%'),
708 ('.0%', '1.23', '123%'),
709
710 ('e', 'NaN', 'NaN'),
711 ('f', '-NaN123', '-NaN123'),
712 ('+g', 'NaN456', '+NaN456'),
713 ('.3e', 'Inf', 'Infinity'),
714 ('.16f', '-Inf', '-Infinity'),
715 ('.0g', '-sNaN', '-sNaN'),
716
717 ('', '1.00', '1.00'),
Mark Dickinsonad416342009-03-17 18:10:15 +0000718
Mark Dickinson79f52032009-03-17 23:12:51 +0000719 # test alignment and padding
Mark Dickinson46ab5d02009-09-08 20:22:46 +0000720 ('6', '123', ' 123'),
Mark Dickinsonad416342009-03-17 18:10:15 +0000721 ('<6', '123', '123 '),
722 ('>6', '123', ' 123'),
723 ('^6', '123', ' 123 '),
724 ('=+6', '123', '+ 123'),
Mark Dickinson79f52032009-03-17 23:12:51 +0000725 ('#<10', 'NaN', 'NaN#######'),
726 ('#<10', '-4.3', '-4.3######'),
727 ('#<+10', '0.0130', '+0.0130###'),
728 ('#< 10', '0.0130', ' 0.0130###'),
729 ('@>10', '-Inf', '@-Infinity'),
730 ('#>5', '-Inf', '-Infinity'),
731 ('?^5', '123', '?123?'),
732 ('%^6', '123', '%123%%'),
733 (' ^6', '-45.6', '-45.6 '),
734 ('/=10', '-45.6', '-/////45.6'),
735 ('/=+10', '45.6', '+/////45.6'),
736 ('/= 10', '45.6', ' /////45.6'),
737
738 # thousands separator
739 (',', '1234567', '1,234,567'),
740 (',', '123456', '123,456'),
741 (',', '12345', '12,345'),
742 (',', '1234', '1,234'),
743 (',', '123', '123'),
744 (',', '12', '12'),
745 (',', '1', '1'),
746 (',', '0', '0'),
747 (',', '-1234567', '-1,234,567'),
748 (',', '-123456', '-123,456'),
749 ('7,', '123456', '123,456'),
Mark Dickinson46ab5d02009-09-08 20:22:46 +0000750 ('8,', '123456', ' 123,456'),
Mark Dickinson79f52032009-03-17 23:12:51 +0000751 ('08,', '123456', '0,123,456'), # special case: extra 0 needed
752 ('+08,', '123456', '+123,456'), # but not if there's a sign
753 (' 08,', '123456', ' 123,456'),
754 ('08,', '-123456', '-123,456'),
755 ('+09,', '123456', '+0,123,456'),
756 # ... with fractional part...
757 ('07,', '1234.56', '1,234.56'),
758 ('08,', '1234.56', '1,234.56'),
759 ('09,', '1234.56', '01,234.56'),
760 ('010,', '1234.56', '001,234.56'),
761 ('011,', '1234.56', '0,001,234.56'),
762 ('012,', '1234.56', '0,001,234.56'),
763 ('08,.1f', '1234.5', '01,234.5'),
764 # no thousands separators in fraction part
765 (',', '1.23456789', '1.23456789'),
766 (',%', '123.456789', '12,345.6789%'),
767 (',e', '123456', '1.23456e+5'),
768 (',E', '123456', '1.23456E+5'),
Mark Dickinson7718d2b2009-09-07 16:21:56 +0000769
770 # issue 6850
771 ('a=-7.0', '0.12345', 'aaaa0.1'),
Christian Heimesf16baeb2008-02-29 14:57:44 +0000772 ]
773 for fmt, d, result in test_values:
774 self.assertEqual(format(Decimal(d), fmt), result)
775
Mark Dickinson79f52032009-03-17 23:12:51 +0000776 def test_n_format(self):
777 try:
778 from locale import CHAR_MAX
779 except ImportError:
780 return
781
782 # Set up some localeconv-like dictionaries
783 en_US = {
784 'decimal_point' : '.',
785 'grouping' : [3, 3, 0],
786 'thousands_sep': ','
787 }
788
789 fr_FR = {
790 'decimal_point' : ',',
791 'grouping' : [CHAR_MAX],
792 'thousands_sep' : ''
793 }
794
795 ru_RU = {
796 'decimal_point' : ',',
797 'grouping' : [3, 3, 0],
798 'thousands_sep' : ' '
799 }
800
801 crazy = {
802 'decimal_point' : '&',
803 'grouping' : [1, 4, 2, CHAR_MAX],
804 'thousands_sep' : '-'
805 }
806
807
808 def get_fmt(x, locale, fmt='n'):
809 return Decimal.__format__(Decimal(x), fmt, _localeconv=locale)
810
811 self.assertEqual(get_fmt(Decimal('12.7'), en_US), '12.7')
812 self.assertEqual(get_fmt(Decimal('12.7'), fr_FR), '12,7')
813 self.assertEqual(get_fmt(Decimal('12.7'), ru_RU), '12,7')
814 self.assertEqual(get_fmt(Decimal('12.7'), crazy), '1-2&7')
815
816 self.assertEqual(get_fmt(123456789, en_US), '123,456,789')
817 self.assertEqual(get_fmt(123456789, fr_FR), '123456789')
818 self.assertEqual(get_fmt(123456789, ru_RU), '123 456 789')
819 self.assertEqual(get_fmt(1234567890123, crazy), '123456-78-9012-3')
820
821 self.assertEqual(get_fmt(123456789, en_US, '.6n'), '1.23457e+8')
822 self.assertEqual(get_fmt(123456789, fr_FR, '.6n'), '1,23457e+8')
823 self.assertEqual(get_fmt(123456789, ru_RU, '.6n'), '1,23457e+8')
824 self.assertEqual(get_fmt(123456789, crazy, '.6n'), '1&23457e+8')
825
Mark Dickinson7303b592009-03-18 08:25:36 +0000826 # zero padding
827 self.assertEqual(get_fmt(1234, fr_FR, '03n'), '1234')
828 self.assertEqual(get_fmt(1234, fr_FR, '04n'), '1234')
829 self.assertEqual(get_fmt(1234, fr_FR, '05n'), '01234')
830 self.assertEqual(get_fmt(1234, fr_FR, '06n'), '001234')
831
832 self.assertEqual(get_fmt(12345, en_US, '05n'), '12,345')
833 self.assertEqual(get_fmt(12345, en_US, '06n'), '12,345')
834 self.assertEqual(get_fmt(12345, en_US, '07n'), '012,345')
835 self.assertEqual(get_fmt(12345, en_US, '08n'), '0,012,345')
836 self.assertEqual(get_fmt(12345, en_US, '09n'), '0,012,345')
837 self.assertEqual(get_fmt(12345, en_US, '010n'), '00,012,345')
838
839 self.assertEqual(get_fmt(123456, crazy, '06n'), '1-2345-6')
840 self.assertEqual(get_fmt(123456, crazy, '07n'), '1-2345-6')
841 self.assertEqual(get_fmt(123456, crazy, '08n'), '1-2345-6')
842 self.assertEqual(get_fmt(123456, crazy, '09n'), '01-2345-6')
843 self.assertEqual(get_fmt(123456, crazy, '010n'), '0-01-2345-6')
844 self.assertEqual(get_fmt(123456, crazy, '011n'), '0-01-2345-6')
845 self.assertEqual(get_fmt(123456, crazy, '012n'), '00-01-2345-6')
846 self.assertEqual(get_fmt(123456, crazy, '013n'), '000-01-2345-6')
847
Mark Dickinson79f52032009-03-17 23:12:51 +0000848
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000849class DecimalArithmeticOperatorsTest(unittest.TestCase):
850 '''Unit tests for all arithmetic operators, binary and unary.'''
851
852 def test_addition(self):
853
854 d1 = Decimal('-11.1')
855 d2 = Decimal('22.2')
856
857 #two Decimals
858 self.assertEqual(d1+d2, Decimal('11.1'))
859 self.assertEqual(d2+d1, Decimal('11.1'))
860
861 #with other type, left
862 c = d1 + 5
863 self.assertEqual(c, Decimal('-6.1'))
864 self.assertEqual(type(c), type(d1))
865
866 #with other type, right
867 c = 5 + d1
868 self.assertEqual(c, Decimal('-6.1'))
869 self.assertEqual(type(c), type(d1))
870
871 #inline with decimal
872 d1 += d2
873 self.assertEqual(d1, Decimal('11.1'))
874
875 #inline with other type
876 d1 += 5
877 self.assertEqual(d1, Decimal('16.1'))
878
879 def test_subtraction(self):
880
881 d1 = Decimal('-11.1')
882 d2 = Decimal('22.2')
883
884 #two Decimals
885 self.assertEqual(d1-d2, Decimal('-33.3'))
886 self.assertEqual(d2-d1, Decimal('33.3'))
887
888 #with other type, left
889 c = d1 - 5
890 self.assertEqual(c, Decimal('-16.1'))
891 self.assertEqual(type(c), type(d1))
892
893 #with other type, right
894 c = 5 - d1
895 self.assertEqual(c, Decimal('16.1'))
896 self.assertEqual(type(c), type(d1))
897
898 #inline with decimal
899 d1 -= d2
900 self.assertEqual(d1, Decimal('-33.3'))
901
902 #inline with other type
903 d1 -= 5
904 self.assertEqual(d1, Decimal('-38.3'))
905
906 def test_multiplication(self):
907
908 d1 = Decimal('-5')
909 d2 = Decimal('3')
910
911 #two Decimals
912 self.assertEqual(d1*d2, Decimal('-15'))
913 self.assertEqual(d2*d1, Decimal('-15'))
914
915 #with other type, left
916 c = d1 * 5
917 self.assertEqual(c, Decimal('-25'))
918 self.assertEqual(type(c), type(d1))
919
920 #with other type, right
921 c = 5 * d1
922 self.assertEqual(c, Decimal('-25'))
923 self.assertEqual(type(c), type(d1))
924
925 #inline with decimal
926 d1 *= d2
927 self.assertEqual(d1, Decimal('-15'))
928
929 #inline with other type
930 d1 *= 5
931 self.assertEqual(d1, Decimal('-75'))
932
933 def test_division(self):
934
935 d1 = Decimal('-5')
936 d2 = Decimal('2')
937
938 #two Decimals
939 self.assertEqual(d1/d2, Decimal('-2.5'))
940 self.assertEqual(d2/d1, Decimal('-0.4'))
941
942 #with other type, left
943 c = d1 / 4
944 self.assertEqual(c, Decimal('-1.25'))
945 self.assertEqual(type(c), type(d1))
946
947 #with other type, right
948 c = 4 / d1
949 self.assertEqual(c, Decimal('-0.8'))
950 self.assertEqual(type(c), type(d1))
951
952 #inline with decimal
953 d1 /= d2
954 self.assertEqual(d1, Decimal('-2.5'))
955
956 #inline with other type
957 d1 /= 4
958 self.assertEqual(d1, Decimal('-0.625'))
959
960 def test_floor_division(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000961
962 d1 = Decimal('5')
963 d2 = Decimal('2')
964
965 #two Decimals
966 self.assertEqual(d1//d2, Decimal('2'))
967 self.assertEqual(d2//d1, Decimal('0'))
968
969 #with other type, left
970 c = d1 // 4
971 self.assertEqual(c, Decimal('1'))
972 self.assertEqual(type(c), type(d1))
973
974 #with other type, right
975 c = 7 // d1
976 self.assertEqual(c, Decimal('1'))
977 self.assertEqual(type(c), type(d1))
978
979 #inline with decimal
980 d1 //= d2
981 self.assertEqual(d1, Decimal('2'))
982
983 #inline with other type
984 d1 //= 2
985 self.assertEqual(d1, Decimal('1'))
986
987 def test_powering(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('25'))
994 self.assertEqual(d2**d1, Decimal('32'))
995
996 #with other type, left
997 c = d1 ** 4
998 self.assertEqual(c, Decimal('625'))
999 self.assertEqual(type(c), type(d1))
1000
1001 #with other type, right
1002 c = 7 ** d1
1003 self.assertEqual(c, Decimal('16807'))
1004 self.assertEqual(type(c), type(d1))
1005
1006 #inline with decimal
1007 d1 **= d2
1008 self.assertEqual(d1, Decimal('25'))
1009
1010 #inline with other type
1011 d1 **= 4
1012 self.assertEqual(d1, Decimal('390625'))
1013
1014 def test_module(self):
1015
1016 d1 = Decimal('5')
1017 d2 = Decimal('2')
1018
1019 #two Decimals
1020 self.assertEqual(d1%d2, Decimal('1'))
1021 self.assertEqual(d2%d1, Decimal('2'))
1022
1023 #with other type, left
1024 c = d1 % 4
1025 self.assertEqual(c, Decimal('1'))
1026 self.assertEqual(type(c), type(d1))
1027
1028 #with other type, right
1029 c = 7 % d1
1030 self.assertEqual(c, Decimal('2'))
1031 self.assertEqual(type(c), type(d1))
1032
1033 #inline with decimal
1034 d1 %= d2
1035 self.assertEqual(d1, Decimal('1'))
1036
1037 #inline with other type
1038 d1 %= 4
1039 self.assertEqual(d1, Decimal('1'))
1040
1041 def test_floor_div_module(self):
1042
1043 d1 = Decimal('5')
1044 d2 = Decimal('2')
1045
1046 #two Decimals
1047 (p, q) = divmod(d1, d2)
1048 self.assertEqual(p, Decimal('2'))
1049 self.assertEqual(q, Decimal('1'))
1050 self.assertEqual(type(p), type(d1))
1051 self.assertEqual(type(q), type(d1))
1052
1053 #with other type, left
1054 (p, q) = divmod(d1, 4)
1055 self.assertEqual(p, Decimal('1'))
1056 self.assertEqual(q, Decimal('1'))
1057 self.assertEqual(type(p), type(d1))
1058 self.assertEqual(type(q), type(d1))
1059
1060 #with other type, right
1061 (p, q) = divmod(7, d1)
1062 self.assertEqual(p, Decimal('1'))
1063 self.assertEqual(q, Decimal('2'))
1064 self.assertEqual(type(p), type(d1))
1065 self.assertEqual(type(q), type(d1))
1066
1067 def test_unary_operators(self):
1068 self.assertEqual(+Decimal(45), Decimal(+45)) # +
1069 self.assertEqual(-Decimal(45), Decimal(-45)) # -
1070 self.assertEqual(abs(Decimal(45)), abs(Decimal(-45))) # abs
1071
Christian Heimes77c02eb2008-02-09 02:18:51 +00001072 def test_nan_comparisons(self):
1073 n = Decimal('NaN')
1074 s = Decimal('sNaN')
1075 i = Decimal('Inf')
1076 f = Decimal('2')
1077 for x, y in [(n, n), (n, i), (i, n), (n, f), (f, n),
1078 (s, n), (n, s), (s, i), (i, s), (s, f), (f, s), (s, s)]:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001079 self.assertTrue(x != y)
1080 self.assertTrue(not (x == y))
1081 self.assertTrue(not (x < y))
1082 self.assertTrue(not (x <= y))
1083 self.assertTrue(not (x > y))
1084 self.assertTrue(not (x >= y))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001085
Mark Dickinson84230a12010-02-18 14:49:50 +00001086 def test_copy_sign(self):
1087 d = Decimal(1).copy_sign(Decimal(-2))
1088
1089 self.assertEqual(Decimal(1).copy_sign(-2), d)
1090 self.assertRaises(TypeError, Decimal(1).copy_sign, '-2')
1091
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001092# The following are two functions used to test threading in the next class
1093
1094def thfunc1(cls):
1095 d1 = Decimal(1)
1096 d3 = Decimal(3)
Christian Heimesfe337bf2008-03-23 21:54:12 +00001097 test1 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001098 cls.synchro.wait()
Christian Heimesfe337bf2008-03-23 21:54:12 +00001099 test2 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001100 cls.finish1.set()
Christian Heimesfe337bf2008-03-23 21:54:12 +00001101
Christian Heimes81ee3ef2008-05-04 22:42:01 +00001102 cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
1103 cls.assertEqual(test2, Decimal('0.3333333333333333333333333333'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001104 return
1105
1106def thfunc2(cls):
1107 d1 = Decimal(1)
1108 d3 = Decimal(3)
Christian Heimesfe337bf2008-03-23 21:54:12 +00001109 test1 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001110 thiscontext = getcontext()
1111 thiscontext.prec = 18
Christian Heimesfe337bf2008-03-23 21:54:12 +00001112 test2 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001113 cls.synchro.set()
1114 cls.finish2.set()
Christian Heimesfe337bf2008-03-23 21:54:12 +00001115
Christian Heimes81ee3ef2008-05-04 22:42:01 +00001116 cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
Christian Heimesfe337bf2008-03-23 21:54:12 +00001117 cls.assertEqual(test2, Decimal('0.333333333333333333'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001118 return
1119
1120
1121class DecimalUseOfContextTest(unittest.TestCase):
1122 '''Unit tests for Use of Context cases in Decimal.'''
1123
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001124 try:
1125 import threading
1126 except ImportError:
1127 threading = None
1128
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001129 # Take care executing this test from IDLE, there's an issue in threading
1130 # that hangs IDLE and I couldn't find it
1131
1132 def test_threading(self):
1133 #Test the "threading isolation" of a Context.
1134
1135 self.synchro = threading.Event()
1136 self.finish1 = threading.Event()
1137 self.finish2 = threading.Event()
1138
1139 th1 = threading.Thread(target=thfunc1, args=(self,))
1140 th2 = threading.Thread(target=thfunc2, args=(self,))
1141
1142 th1.start()
1143 th2.start()
1144
1145 self.finish1.wait()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001146 self.finish2.wait()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001147 return
1148
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001149 if threading is None:
1150 del test_threading
1151
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001152
1153class DecimalUsabilityTest(unittest.TestCase):
1154 '''Unit tests for Usability cases of Decimal.'''
1155
1156 def test_comparison_operators(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001157
1158 da = Decimal('23.42')
1159 db = Decimal('23.42')
1160 dc = Decimal('45')
1161
1162 #two Decimals
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001163 self.assertTrue(dc > da)
1164 self.assertTrue(dc >= da)
1165 self.assertTrue(da < dc)
1166 self.assertTrue(da <= dc)
Guido van Rossume61fd5b2007-07-11 12:20:59 +00001167 self.assertEqual(da, db)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001168 self.assertTrue(da != dc)
1169 self.assertTrue(da <= db)
1170 self.assertTrue(da >= db)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001171
1172 #a Decimal and an int
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001173 self.assertTrue(dc > 23)
1174 self.assertTrue(23 < dc)
Guido van Rossume61fd5b2007-07-11 12:20:59 +00001175 self.assertEqual(dc, 45)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001176
1177 #a Decimal and uncomparable
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001178 self.assertNotEqual(da, 'ugly')
1179 self.assertNotEqual(da, 32.7)
1180 self.assertNotEqual(da, object())
1181 self.assertNotEqual(da, object)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001182
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001183 # sortable
Guido van Rossumc1f779c2007-07-03 08:25:58 +00001184 a = list(map(Decimal, range(100)))
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001185 b = a[:]
1186 random.shuffle(a)
1187 a.sort()
1188 self.assertEqual(a, b)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001189
1190 def test_copy_and_deepcopy_methods(self):
1191 d = Decimal('43.24')
1192 c = copy.copy(d)
1193 self.assertEqual(id(c), id(d))
1194 dc = copy.deepcopy(d)
1195 self.assertEqual(id(dc), id(d))
1196
1197 def test_hash_method(self):
1198 #just that it's hashable
1199 hash(Decimal(23))
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001200
1201 test_values = [Decimal(sign*(2**m + n))
1202 for m in [0, 14, 15, 16, 17, 30, 31,
1203 32, 33, 62, 63, 64, 65, 66]
1204 for n in range(-10, 10)
1205 for sign in [-1, 1]]
1206 test_values.extend([
1207 Decimal("-0"), # zeros
1208 Decimal("0.00"),
1209 Decimal("-0.000"),
1210 Decimal("0E10"),
1211 Decimal("-0E12"),
1212 Decimal("10.0"), # negative exponent
1213 Decimal("-23.00000"),
1214 Decimal("1230E100"), # positive exponent
1215 Decimal("-4.5678E50"),
1216 # a value for which hash(n) != hash(n % (2**64-1))
1217 # in Python pre-2.6
1218 Decimal(2**64 + 2**32 - 1),
1219 # selection of values which fail with the old (before
1220 # version 2.6) long.__hash__
1221 Decimal("1.634E100"),
1222 Decimal("90.697E100"),
1223 Decimal("188.83E100"),
1224 Decimal("1652.9E100"),
1225 Decimal("56531E100"),
1226 ])
1227
1228 # check that hash(d) == hash(int(d)) for integral values
1229 for value in test_values:
1230 self.assertEqual(hash(value), hash(int(value)))
1231
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001232 #the same hash that to an int
1233 self.assertEqual(hash(Decimal(23)), hash(23))
Raymond Hettingerbea3f6f2005-03-15 04:59:17 +00001234 self.assertRaises(TypeError, hash, Decimal('NaN'))
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001235 self.assertTrue(hash(Decimal('Inf')))
1236 self.assertTrue(hash(Decimal('-Inf')))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001237
Christian Heimes2380ac72008-01-09 00:17:24 +00001238 # check that the value of the hash doesn't depend on the
1239 # current context (issue #1757)
1240 c = getcontext()
1241 old_precision = c.prec
1242 x = Decimal("123456789.1")
1243
1244 c.prec = 6
1245 h1 = hash(x)
1246 c.prec = 10
1247 h2 = hash(x)
1248 c.prec = 16
1249 h3 = hash(x)
1250
1251 self.assertEqual(h1, h2)
1252 self.assertEqual(h1, h3)
1253 c.prec = old_precision
1254
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001255 def test_min_and_max_methods(self):
1256
1257 d1 = Decimal('15.32')
1258 d2 = Decimal('28.5')
1259 l1 = 15
1260 l2 = 28
1261
1262 #between Decimals
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001263 self.assertTrue(min(d1,d2) is d1)
1264 self.assertTrue(min(d2,d1) is d1)
1265 self.assertTrue(max(d1,d2) is d2)
1266 self.assertTrue(max(d2,d1) is d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001267
1268 #between Decimal and long
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001269 self.assertTrue(min(d1,l2) is d1)
1270 self.assertTrue(min(l2,d1) is d1)
1271 self.assertTrue(max(l1,d2) is d2)
1272 self.assertTrue(max(d2,l1) is d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001273
1274 def test_as_nonzero(self):
1275 #as false
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001276 self.assertFalse(Decimal(0))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001277 #as true
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001278 self.assertTrue(Decimal('0.372'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001279
1280 def test_tostring_methods(self):
1281 #Test str and repr methods.
1282
1283 d = Decimal('15.32')
1284 self.assertEqual(str(d), '15.32') # str
Christian Heimes68f5fbe2008-02-14 08:27:37 +00001285 self.assertEqual(repr(d), "Decimal('15.32')") # repr
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001286
1287 def test_tonum_methods(self):
Mark Dickinson5c2db372009-12-05 20:28:34 +00001288 #Test float and int methods.
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001289
1290 d1 = Decimal('66')
1291 d2 = Decimal('15.32')
1292
1293 #int
1294 self.assertEqual(int(d1), 66)
1295 self.assertEqual(int(d2), 15)
1296
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001297 #float
1298 self.assertEqual(float(d1), 66)
1299 self.assertEqual(float(d2), 15.32)
1300
Mark Dickinsonb27406c2008-05-09 13:42:33 +00001301 #floor
1302 test_pairs = [
1303 ('123.00', 123),
1304 ('3.2', 3),
1305 ('3.54', 3),
1306 ('3.899', 3),
1307 ('-2.3', -3),
1308 ('-11.0', -11),
1309 ('0.0', 0),
1310 ('-0E3', 0),
1311 ]
1312 for d, i in test_pairs:
1313 self.assertEqual(math.floor(Decimal(d)), i)
1314 self.assertRaises(ValueError, math.floor, Decimal('-NaN'))
1315 self.assertRaises(ValueError, math.floor, Decimal('sNaN'))
1316 self.assertRaises(ValueError, math.floor, Decimal('NaN123'))
1317 self.assertRaises(OverflowError, math.floor, Decimal('Inf'))
1318 self.assertRaises(OverflowError, math.floor, Decimal('-Inf'))
1319
1320 #ceiling
1321 test_pairs = [
1322 ('123.00', 123),
1323 ('3.2', 4),
1324 ('3.54', 4),
1325 ('3.899', 4),
1326 ('-2.3', -2),
1327 ('-11.0', -11),
1328 ('0.0', 0),
1329 ('-0E3', 0),
1330 ]
1331 for d, i in test_pairs:
1332 self.assertEqual(math.ceil(Decimal(d)), i)
1333 self.assertRaises(ValueError, math.ceil, Decimal('-NaN'))
1334 self.assertRaises(ValueError, math.ceil, Decimal('sNaN'))
1335 self.assertRaises(ValueError, math.ceil, Decimal('NaN123'))
1336 self.assertRaises(OverflowError, math.ceil, Decimal('Inf'))
1337 self.assertRaises(OverflowError, math.ceil, Decimal('-Inf'))
1338
1339 #round, single argument
1340 test_pairs = [
1341 ('123.00', 123),
1342 ('3.2', 3),
1343 ('3.54', 4),
1344 ('3.899', 4),
1345 ('-2.3', -2),
1346 ('-11.0', -11),
1347 ('0.0', 0),
1348 ('-0E3', 0),
1349 ('-3.5', -4),
1350 ('-2.5', -2),
1351 ('-1.5', -2),
1352 ('-0.5', 0),
1353 ('0.5', 0),
1354 ('1.5', 2),
1355 ('2.5', 2),
1356 ('3.5', 4),
1357 ]
1358 for d, i in test_pairs:
1359 self.assertEqual(round(Decimal(d)), i)
1360 self.assertRaises(ValueError, round, Decimal('-NaN'))
1361 self.assertRaises(ValueError, round, Decimal('sNaN'))
1362 self.assertRaises(ValueError, round, Decimal('NaN123'))
1363 self.assertRaises(OverflowError, round, Decimal('Inf'))
1364 self.assertRaises(OverflowError, round, Decimal('-Inf'))
1365
1366 #round, two arguments; this is essentially equivalent
1367 #to quantize, which is already extensively tested
1368 test_triples = [
1369 ('123.456', -4, '0E+4'),
1370 ('123.456', -3, '0E+3'),
1371 ('123.456', -2, '1E+2'),
1372 ('123.456', -1, '1.2E+2'),
1373 ('123.456', 0, '123'),
1374 ('123.456', 1, '123.5'),
1375 ('123.456', 2, '123.46'),
1376 ('123.456', 3, '123.456'),
1377 ('123.456', 4, '123.4560'),
1378 ('123.455', 2, '123.46'),
1379 ('123.445', 2, '123.44'),
1380 ('Inf', 4, 'NaN'),
1381 ('-Inf', -23, 'NaN'),
1382 ('sNaN314', 3, 'NaN314'),
1383 ]
1384 for d, n, r in test_triples:
1385 self.assertEqual(str(round(Decimal(d), n)), r)
1386
1387
1388
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001389 def test_eval_round_trip(self):
1390
1391 #with zero
1392 d = Decimal( (0, (0,), 0) )
1393 self.assertEqual(d, eval(repr(d)))
1394
1395 #int
1396 d = Decimal( (1, (4, 5), 0) )
1397 self.assertEqual(d, eval(repr(d)))
1398
1399 #float
1400 d = Decimal( (0, (4, 5, 3, 4), -2) )
1401 self.assertEqual(d, eval(repr(d)))
1402
1403 #weird
1404 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1405 self.assertEqual(d, eval(repr(d)))
1406
1407 def test_as_tuple(self):
1408
1409 #with zero
1410 d = Decimal(0)
1411 self.assertEqual(d.as_tuple(), (0, (0,), 0) )
1412
1413 #int
1414 d = Decimal(-45)
1415 self.assertEqual(d.as_tuple(), (1, (4, 5), 0) )
1416
1417 #complicated string
1418 d = Decimal("-4.34913534E-17")
1419 self.assertEqual(d.as_tuple(), (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1420
1421 #inf
1422 d = Decimal("Infinity")
1423 self.assertEqual(d.as_tuple(), (0, (0,), 'F') )
1424
Guido van Rossum8ce8a782007-11-01 19:42:39 +00001425 #leading zeros in coefficient should be stripped
1426 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), -2) )
1427 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), -2) )
1428 d = Decimal( (1, (0, 0, 0), 37) )
1429 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1430 d = Decimal( (1, (), 37) )
1431 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1432
1433 #leading zeros in NaN diagnostic info should be stripped
1434 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), 'n') )
1435 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), 'n') )
1436 d = Decimal( (1, (0, 0, 0), 'N') )
1437 self.assertEqual(d.as_tuple(), (1, (), 'N') )
1438 d = Decimal( (1, (), 'n') )
1439 self.assertEqual(d.as_tuple(), (1, (), 'n') )
1440
1441 #coefficient in infinity should be ignored
1442 d = Decimal( (0, (4, 5, 3, 4), 'F') )
1443 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
1444 d = Decimal( (1, (0, 2, 7, 1), 'F') )
1445 self.assertEqual(d.as_tuple(), (1, (0,), 'F'))
1446
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001447 def test_immutability_operations(self):
1448 # Do operations and check that it didn't change change internal objects.
1449
1450 d1 = Decimal('-25e55')
1451 b1 = Decimal('-25e55')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001452 d2 = Decimal('33e+33')
1453 b2 = Decimal('33e+33')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001454
1455 def checkSameDec(operation, useOther=False):
1456 if useOther:
1457 eval("d1." + operation + "(d2)")
1458 self.assertEqual(d1._sign, b1._sign)
1459 self.assertEqual(d1._int, b1._int)
1460 self.assertEqual(d1._exp, b1._exp)
1461 self.assertEqual(d2._sign, b2._sign)
1462 self.assertEqual(d2._int, b2._int)
1463 self.assertEqual(d2._exp, b2._exp)
1464 else:
1465 eval("d1." + operation + "()")
1466 self.assertEqual(d1._sign, b1._sign)
1467 self.assertEqual(d1._int, b1._int)
1468 self.assertEqual(d1._exp, b1._exp)
1469 return
1470
1471 Decimal(d1)
1472 self.assertEqual(d1._sign, b1._sign)
1473 self.assertEqual(d1._int, b1._int)
1474 self.assertEqual(d1._exp, b1._exp)
1475
1476 checkSameDec("__abs__")
1477 checkSameDec("__add__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001478 checkSameDec("__divmod__", True)
Christian Heimes77c02eb2008-02-09 02:18:51 +00001479 checkSameDec("__eq__", True)
1480 checkSameDec("__ne__", True)
1481 checkSameDec("__le__", True)
1482 checkSameDec("__lt__", True)
1483 checkSameDec("__ge__", True)
1484 checkSameDec("__gt__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001485 checkSameDec("__float__")
1486 checkSameDec("__floordiv__", True)
1487 checkSameDec("__hash__")
1488 checkSameDec("__int__")
Christian Heimes969fe572008-01-25 11:23:10 +00001489 checkSameDec("__trunc__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001490 checkSameDec("__mod__", True)
1491 checkSameDec("__mul__", True)
1492 checkSameDec("__neg__")
Jack Diederich4dafcc42006-11-28 19:15:13 +00001493 checkSameDec("__bool__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001494 checkSameDec("__pos__")
1495 checkSameDec("__pow__", True)
1496 checkSameDec("__radd__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001497 checkSameDec("__rdivmod__", True)
1498 checkSameDec("__repr__")
1499 checkSameDec("__rfloordiv__", True)
1500 checkSameDec("__rmod__", True)
1501 checkSameDec("__rmul__", True)
1502 checkSameDec("__rpow__", True)
1503 checkSameDec("__rsub__", True)
1504 checkSameDec("__str__")
1505 checkSameDec("__sub__", True)
1506 checkSameDec("__truediv__", True)
1507 checkSameDec("adjusted")
1508 checkSameDec("as_tuple")
1509 checkSameDec("compare", True)
1510 checkSameDec("max", True)
1511 checkSameDec("min", True)
1512 checkSameDec("normalize")
1513 checkSameDec("quantize", True)
1514 checkSameDec("remainder_near", True)
1515 checkSameDec("same_quantum", True)
1516 checkSameDec("sqrt")
1517 checkSameDec("to_eng_string")
1518 checkSameDec("to_integral")
1519
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001520 def test_subclassing(self):
1521 # Different behaviours when subclassing Decimal
1522
1523 class MyDecimal(Decimal):
1524 pass
1525
1526 d1 = MyDecimal(1)
1527 d2 = MyDecimal(2)
1528 d = d1 + d2
1529 self.assertTrue(type(d) is Decimal)
1530
1531 d = d1.max(d2)
1532 self.assertTrue(type(d) is Decimal)
1533
Christian Heimes0348fb62008-03-26 12:55:56 +00001534 def test_implicit_context(self):
1535 # Check results when context given implicitly. (Issue 2478)
1536 c = getcontext()
1537 self.assertEqual(str(Decimal(0).sqrt()),
1538 str(c.sqrt(Decimal(0))))
1539
Mark Dickinsona2d1fe02009-10-29 12:23:02 +00001540 def test_conversions_from_int(self):
1541 # Check that methods taking a second Decimal argument will
1542 # always accept an integer in place of a Decimal.
1543 self.assertEqual(Decimal(4).compare(3),
1544 Decimal(4).compare(Decimal(3)))
1545 self.assertEqual(Decimal(4).compare_signal(3),
1546 Decimal(4).compare_signal(Decimal(3)))
1547 self.assertEqual(Decimal(4).compare_total(3),
1548 Decimal(4).compare_total(Decimal(3)))
1549 self.assertEqual(Decimal(4).compare_total_mag(3),
1550 Decimal(4).compare_total_mag(Decimal(3)))
1551 self.assertEqual(Decimal(10101).logical_and(1001),
1552 Decimal(10101).logical_and(Decimal(1001)))
1553 self.assertEqual(Decimal(10101).logical_or(1001),
1554 Decimal(10101).logical_or(Decimal(1001)))
1555 self.assertEqual(Decimal(10101).logical_xor(1001),
1556 Decimal(10101).logical_xor(Decimal(1001)))
1557 self.assertEqual(Decimal(567).max(123),
1558 Decimal(567).max(Decimal(123)))
1559 self.assertEqual(Decimal(567).max_mag(123),
1560 Decimal(567).max_mag(Decimal(123)))
1561 self.assertEqual(Decimal(567).min(123),
1562 Decimal(567).min(Decimal(123)))
1563 self.assertEqual(Decimal(567).min_mag(123),
1564 Decimal(567).min_mag(Decimal(123)))
1565 self.assertEqual(Decimal(567).next_toward(123),
1566 Decimal(567).next_toward(Decimal(123)))
1567 self.assertEqual(Decimal(1234).quantize(100),
1568 Decimal(1234).quantize(Decimal(100)))
1569 self.assertEqual(Decimal(768).remainder_near(1234),
1570 Decimal(768).remainder_near(Decimal(1234)))
1571 self.assertEqual(Decimal(123).rotate(1),
1572 Decimal(123).rotate(Decimal(1)))
1573 self.assertEqual(Decimal(1234).same_quantum(1000),
1574 Decimal(1234).same_quantum(Decimal(1000)))
1575 self.assertEqual(Decimal('9.123').scaleb(-100),
1576 Decimal('9.123').scaleb(Decimal(-100)))
1577 self.assertEqual(Decimal(456).shift(-1),
1578 Decimal(456).shift(Decimal(-1)))
1579
1580 self.assertEqual(Decimal(-12).fma(Decimal(45), 67),
1581 Decimal(-12).fma(Decimal(45), Decimal(67)))
1582 self.assertEqual(Decimal(-12).fma(45, 67),
1583 Decimal(-12).fma(Decimal(45), Decimal(67)))
1584 self.assertEqual(Decimal(-12).fma(45, Decimal(67)),
1585 Decimal(-12).fma(Decimal(45), Decimal(67)))
1586
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001587
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001588class DecimalPythonAPItests(unittest.TestCase):
1589
Raymond Hettinger82417ca2009-02-03 03:54:28 +00001590 def test_abc(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001591 self.assertTrue(issubclass(Decimal, numbers.Number))
1592 self.assertTrue(not issubclass(Decimal, numbers.Real))
Ezio Melottie9615932010-01-24 19:26:24 +00001593 self.assertIsInstance(Decimal(0), numbers.Number)
1594 self.assertNotIsInstance(Decimal(0), numbers.Real)
Raymond Hettinger82417ca2009-02-03 03:54:28 +00001595
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001596 def test_pickle(self):
1597 d = Decimal('-3.141590000')
1598 p = pickle.dumps(d)
1599 e = pickle.loads(p)
1600 self.assertEqual(d, e)
1601
Raymond Hettinger5548be22004-07-05 18:49:38 +00001602 def test_int(self):
Raymond Hettinger605ed022004-11-24 07:28:48 +00001603 for x in range(-250, 250):
1604 s = '%0.2f' % (x / 100.0)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001605 # should work the same as for floats
1606 self.assertEqual(int(Decimal(s)), int(float(s)))
Raymond Hettinger605ed022004-11-24 07:28:48 +00001607 # should work the same as to_integral in the ROUND_DOWN mode
Raymond Hettinger5548be22004-07-05 18:49:38 +00001608 d = Decimal(s)
Raymond Hettinger605ed022004-11-24 07:28:48 +00001609 r = d.to_integral(ROUND_DOWN)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001610 self.assertEqual(Decimal(int(d)), r)
1611
Mark Dickinson825fce32009-09-07 18:08:12 +00001612 self.assertRaises(ValueError, int, Decimal('-nan'))
1613 self.assertRaises(ValueError, int, Decimal('snan'))
1614 self.assertRaises(OverflowError, int, Decimal('inf'))
1615 self.assertRaises(OverflowError, int, Decimal('-inf'))
1616
Christian Heimes969fe572008-01-25 11:23:10 +00001617 def test_trunc(self):
1618 for x in range(-250, 250):
1619 s = '%0.2f' % (x / 100.0)
1620 # should work the same as for floats
1621 self.assertEqual(int(Decimal(s)), int(float(s)))
1622 # should work the same as to_integral in the ROUND_DOWN mode
1623 d = Decimal(s)
1624 r = d.to_integral(ROUND_DOWN)
Christian Heimes400adb02008-02-01 08:12:03 +00001625 self.assertEqual(Decimal(math.trunc(d)), r)
Christian Heimes969fe572008-01-25 11:23:10 +00001626
Raymond Hettinger771ed762009-01-03 19:20:32 +00001627 def test_from_float(self):
1628
1629 class MyDecimal(Decimal):
1630 pass
1631
1632 r = MyDecimal.from_float(0.1)
1633 self.assertEqual(type(r), MyDecimal)
1634 self.assertEqual(str(r),
1635 '0.1000000000000000055511151231257827021181583404541015625')
1636 bigint = 12345678901234567890123456789
1637 self.assertEqual(MyDecimal.from_float(bigint), MyDecimal(bigint))
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001638 self.assertTrue(MyDecimal.from_float(float('nan')).is_qnan())
1639 self.assertTrue(MyDecimal.from_float(float('inf')).is_infinite())
1640 self.assertTrue(MyDecimal.from_float(float('-inf')).is_infinite())
Raymond Hettinger771ed762009-01-03 19:20:32 +00001641 self.assertEqual(str(MyDecimal.from_float(float('nan'))),
1642 str(Decimal('NaN')))
1643 self.assertEqual(str(MyDecimal.from_float(float('inf'))),
1644 str(Decimal('Infinity')))
1645 self.assertEqual(str(MyDecimal.from_float(float('-inf'))),
1646 str(Decimal('-Infinity')))
1647 self.assertRaises(TypeError, MyDecimal.from_float, 'abc')
1648 for i in range(200):
1649 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
1650 self.assertEqual(x, float(MyDecimal.from_float(x))) # roundtrip
1651
1652 def test_create_decimal_from_float(self):
1653 context = Context(prec=5, rounding=ROUND_DOWN)
1654 self.assertEqual(
1655 context.create_decimal_from_float(math.pi),
1656 Decimal('3.1415')
1657 )
1658 context = Context(prec=5, rounding=ROUND_UP)
1659 self.assertEqual(
1660 context.create_decimal_from_float(math.pi),
1661 Decimal('3.1416')
1662 )
1663 context = Context(prec=5, traps=[Inexact])
1664 self.assertRaises(
1665 Inexact,
1666 context.create_decimal_from_float,
1667 math.pi
1668 )
1669 self.assertEqual(repr(context.create_decimal_from_float(-0.0)),
1670 "Decimal('-0')")
1671 self.assertEqual(repr(context.create_decimal_from_float(1.0)),
1672 "Decimal('1')")
1673 self.assertEqual(repr(context.create_decimal_from_float(10)),
1674 "Decimal('10')")
1675
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00001676class ContextAPItests(unittest.TestCase):
1677
1678 def test_pickle(self):
1679 c = Context()
1680 e = pickle.loads(pickle.dumps(c))
1681 for k in vars(c):
1682 v1 = vars(c)[k]
1683 v2 = vars(e)[k]
1684 self.assertEqual(v1, v2)
1685
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001686 def test_equality_with_other_types(self):
Benjamin Peterson577473f2010-01-19 00:09:57 +00001687 self.assertIn(Decimal(10), ['a', 1.0, Decimal(10), (1,2), {}])
1688 self.assertNotIn(Decimal(10), ['a', 1.0, (1,2), {}])
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001689
Raymond Hettinger955d2b22004-08-08 20:17:45 +00001690 def test_copy(self):
1691 # All copies should be deep
1692 c = Context()
1693 d = c.copy()
1694 self.assertNotEqual(id(c), id(d))
1695 self.assertNotEqual(id(c.flags), id(d.flags))
1696 self.assertNotEqual(id(c.traps), id(d.traps))
1697
Mark Dickinson84230a12010-02-18 14:49:50 +00001698 def test_abs(self):
1699 c = Context()
1700 d = c.abs(Decimal(-1))
1701 self.assertEqual(c.abs(-1), d)
1702 self.assertRaises(TypeError, c.abs, '-1')
1703
1704 def test_add(self):
1705 c = Context()
1706 d = c.add(Decimal(1), Decimal(1))
1707 self.assertEqual(c.add(1, 1), d)
1708 self.assertEqual(c.add(Decimal(1), 1), d)
1709 self.assertEqual(c.add(1, Decimal(1)), d)
1710 self.assertRaises(TypeError, c.add, '1', 1)
1711 self.assertRaises(TypeError, c.add, 1, '1')
1712
1713 def test_compare(self):
1714 c = Context()
1715 d = c.compare(Decimal(1), Decimal(1))
1716 self.assertEqual(c.compare(1, 1), d)
1717 self.assertEqual(c.compare(Decimal(1), 1), d)
1718 self.assertEqual(c.compare(1, Decimal(1)), d)
1719 self.assertRaises(TypeError, c.compare, '1', 1)
1720 self.assertRaises(TypeError, c.compare, 1, '1')
1721
1722 def test_compare_signal(self):
1723 c = Context()
1724 d = c.compare_signal(Decimal(1), Decimal(1))
1725 self.assertEqual(c.compare_signal(1, 1), d)
1726 self.assertEqual(c.compare_signal(Decimal(1), 1), d)
1727 self.assertEqual(c.compare_signal(1, Decimal(1)), d)
1728 self.assertRaises(TypeError, c.compare_signal, '1', 1)
1729 self.assertRaises(TypeError, c.compare_signal, 1, '1')
1730
1731 def test_compare_total(self):
1732 c = Context()
1733 d = c.compare_total(Decimal(1), Decimal(1))
1734 self.assertEqual(c.compare_total(1, 1), d)
1735 self.assertEqual(c.compare_total(Decimal(1), 1), d)
1736 self.assertEqual(c.compare_total(1, Decimal(1)), d)
1737 self.assertRaises(TypeError, c.compare_total, '1', 1)
1738 self.assertRaises(TypeError, c.compare_total, 1, '1')
1739
1740 def test_compare_total_mag(self):
1741 c = Context()
1742 d = c.compare_total_mag(Decimal(1), Decimal(1))
1743 self.assertEqual(c.compare_total_mag(1, 1), d)
1744 self.assertEqual(c.compare_total_mag(Decimal(1), 1), d)
1745 self.assertEqual(c.compare_total_mag(1, Decimal(1)), d)
1746 self.assertRaises(TypeError, c.compare_total_mag, '1', 1)
1747 self.assertRaises(TypeError, c.compare_total_mag, 1, '1')
1748
1749 def test_copy_abs(self):
1750 c = Context()
1751 d = c.copy_abs(Decimal(-1))
1752 self.assertEqual(c.copy_abs(-1), d)
1753 self.assertRaises(TypeError, c.copy_abs, '-1')
1754
1755 def test_copy_decimal(self):
1756 c = Context()
1757 d = c.copy_decimal(Decimal(-1))
1758 self.assertEqual(c.copy_decimal(-1), d)
1759 self.assertRaises(TypeError, c.copy_decimal, '-1')
1760
1761 def test_copy_negate(self):
1762 c = Context()
1763 d = c.copy_negate(Decimal(-1))
1764 self.assertEqual(c.copy_negate(-1), d)
1765 self.assertRaises(TypeError, c.copy_negate, '-1')
1766
1767 def test_copy_sign(self):
1768 c = Context()
1769 d = c.copy_sign(Decimal(1), Decimal(-2))
1770 self.assertEqual(c.copy_sign(1, -2), d)
1771 self.assertEqual(c.copy_sign(Decimal(1), -2), d)
1772 self.assertEqual(c.copy_sign(1, Decimal(-2)), d)
1773 self.assertRaises(TypeError, c.copy_sign, '1', -2)
1774 self.assertRaises(TypeError, c.copy_sign, 1, '-2')
1775
1776 def test_divide(self):
1777 c = Context()
1778 d = c.divide(Decimal(1), Decimal(2))
1779 self.assertEqual(c.divide(1, 2), d)
1780 self.assertEqual(c.divide(Decimal(1), 2), d)
1781 self.assertEqual(c.divide(1, Decimal(2)), d)
1782 self.assertRaises(TypeError, c.divide, '1', 2)
1783 self.assertRaises(TypeError, c.divide, 1, '2')
1784
1785 def test_divide_int(self):
1786 c = Context()
1787 d = c.divide_int(Decimal(1), Decimal(2))
1788 self.assertEqual(c.divide_int(1, 2), d)
1789 self.assertEqual(c.divide_int(Decimal(1), 2), d)
1790 self.assertEqual(c.divide_int(1, Decimal(2)), d)
1791 self.assertRaises(TypeError, c.divide_int, '1', 2)
1792 self.assertRaises(TypeError, c.divide_int, 1, '2')
1793
1794 def test_divmod(self):
1795 c = Context()
1796 d = c.divmod(Decimal(1), Decimal(2))
1797 self.assertEqual(c.divmod(1, 2), d)
1798 self.assertEqual(c.divmod(Decimal(1), 2), d)
1799 self.assertEqual(c.divmod(1, Decimal(2)), d)
1800 self.assertRaises(TypeError, c.divmod, '1', 2)
1801 self.assertRaises(TypeError, c.divmod, 1, '2')
1802
1803 def test_exp(self):
1804 c = Context()
1805 d = c.exp(Decimal(10))
1806 self.assertEqual(c.exp(10), d)
1807 self.assertRaises(TypeError, c.exp, '10')
1808
1809 def test_fma(self):
1810 c = Context()
1811 d = c.fma(Decimal(2), Decimal(3), Decimal(4))
1812 self.assertEqual(c.fma(2, 3, 4), d)
1813 self.assertEqual(c.fma(Decimal(2), 3, 4), d)
1814 self.assertEqual(c.fma(2, Decimal(3), 4), d)
1815 self.assertEqual(c.fma(2, 3, Decimal(4)), d)
1816 self.assertEqual(c.fma(Decimal(2), Decimal(3), 4), d)
1817 self.assertRaises(TypeError, c.fma, '2', 3, 4)
1818 self.assertRaises(TypeError, c.fma, 2, '3', 4)
1819 self.assertRaises(TypeError, c.fma, 2, 3, '4')
1820
1821 def test_is_finite(self):
1822 c = Context()
1823 d = c.is_finite(Decimal(10))
1824 self.assertEqual(c.is_finite(10), d)
1825 self.assertRaises(TypeError, c.is_finite, '10')
1826
1827 def test_is_infinite(self):
1828 c = Context()
1829 d = c.is_infinite(Decimal(10))
1830 self.assertEqual(c.is_infinite(10), d)
1831 self.assertRaises(TypeError, c.is_infinite, '10')
1832
1833 def test_is_nan(self):
1834 c = Context()
1835 d = c.is_nan(Decimal(10))
1836 self.assertEqual(c.is_nan(10), d)
1837 self.assertRaises(TypeError, c.is_nan, '10')
1838
1839 def test_is_normal(self):
1840 c = Context()
1841 d = c.is_normal(Decimal(10))
1842 self.assertEqual(c.is_normal(10), d)
1843 self.assertRaises(TypeError, c.is_normal, '10')
1844
1845 def test_is_qnan(self):
1846 c = Context()
1847 d = c.is_qnan(Decimal(10))
1848 self.assertEqual(c.is_qnan(10), d)
1849 self.assertRaises(TypeError, c.is_qnan, '10')
1850
1851 def test_is_signed(self):
1852 c = Context()
1853 d = c.is_signed(Decimal(10))
1854 self.assertEqual(c.is_signed(10), d)
1855 self.assertRaises(TypeError, c.is_signed, '10')
1856
1857 def test_is_snan(self):
1858 c = Context()
1859 d = c.is_snan(Decimal(10))
1860 self.assertEqual(c.is_snan(10), d)
1861 self.assertRaises(TypeError, c.is_snan, '10')
1862
1863 def test_is_subnormal(self):
1864 c = Context()
1865 d = c.is_subnormal(Decimal(10))
1866 self.assertEqual(c.is_subnormal(10), d)
1867 self.assertRaises(TypeError, c.is_subnormal, '10')
1868
1869 def test_is_zero(self):
1870 c = Context()
1871 d = c.is_zero(Decimal(10))
1872 self.assertEqual(c.is_zero(10), d)
1873 self.assertRaises(TypeError, c.is_zero, '10')
1874
1875 def test_ln(self):
1876 c = Context()
1877 d = c.ln(Decimal(10))
1878 self.assertEqual(c.ln(10), d)
1879 self.assertRaises(TypeError, c.ln, '10')
1880
1881 def test_log10(self):
1882 c = Context()
1883 d = c.log10(Decimal(10))
1884 self.assertEqual(c.log10(10), d)
1885 self.assertRaises(TypeError, c.log10, '10')
1886
1887 def test_logb(self):
1888 c = Context()
1889 d = c.logb(Decimal(10))
1890 self.assertEqual(c.logb(10), d)
1891 self.assertRaises(TypeError, c.logb, '10')
1892
1893 def test_logical_and(self):
1894 c = Context()
1895 d = c.logical_and(Decimal(1), Decimal(1))
1896 self.assertEqual(c.logical_and(1, 1), d)
1897 self.assertEqual(c.logical_and(Decimal(1), 1), d)
1898 self.assertEqual(c.logical_and(1, Decimal(1)), d)
1899 self.assertRaises(TypeError, c.logical_and, '1', 1)
1900 self.assertRaises(TypeError, c.logical_and, 1, '1')
1901
1902 def test_logical_invert(self):
1903 c = Context()
1904 d = c.logical_invert(Decimal(1000))
1905 self.assertEqual(c.logical_invert(1000), d)
1906 self.assertRaises(TypeError, c.logical_invert, '1000')
1907
1908 def test_logical_or(self):
1909 c = Context()
1910 d = c.logical_or(Decimal(1), Decimal(1))
1911 self.assertEqual(c.logical_or(1, 1), d)
1912 self.assertEqual(c.logical_or(Decimal(1), 1), d)
1913 self.assertEqual(c.logical_or(1, Decimal(1)), d)
1914 self.assertRaises(TypeError, c.logical_or, '1', 1)
1915 self.assertRaises(TypeError, c.logical_or, 1, '1')
1916
1917 def test_logical_xor(self):
1918 c = Context()
1919 d = c.logical_xor(Decimal(1), Decimal(1))
1920 self.assertEqual(c.logical_xor(1, 1), d)
1921 self.assertEqual(c.logical_xor(Decimal(1), 1), d)
1922 self.assertEqual(c.logical_xor(1, Decimal(1)), d)
1923 self.assertRaises(TypeError, c.logical_xor, '1', 1)
1924 self.assertRaises(TypeError, c.logical_xor, 1, '1')
1925
1926 def test_max(self):
1927 c = Context()
1928 d = c.max(Decimal(1), Decimal(2))
1929 self.assertEqual(c.max(1, 2), d)
1930 self.assertEqual(c.max(Decimal(1), 2), d)
1931 self.assertEqual(c.max(1, Decimal(2)), d)
1932 self.assertRaises(TypeError, c.max, '1', 2)
1933 self.assertRaises(TypeError, c.max, 1, '2')
1934
1935 def test_max_mag(self):
1936 c = Context()
1937 d = c.max_mag(Decimal(1), Decimal(2))
1938 self.assertEqual(c.max_mag(1, 2), d)
1939 self.assertEqual(c.max_mag(Decimal(1), 2), d)
1940 self.assertEqual(c.max_mag(1, Decimal(2)), d)
1941 self.assertRaises(TypeError, c.max_mag, '1', 2)
1942 self.assertRaises(TypeError, c.max_mag, 1, '2')
1943
1944 def test_min(self):
1945 c = Context()
1946 d = c.min(Decimal(1), Decimal(2))
1947 self.assertEqual(c.min(1, 2), d)
1948 self.assertEqual(c.min(Decimal(1), 2), d)
1949 self.assertEqual(c.min(1, Decimal(2)), d)
1950 self.assertRaises(TypeError, c.min, '1', 2)
1951 self.assertRaises(TypeError, c.min, 1, '2')
1952
1953 def test_min_mag(self):
1954 c = Context()
1955 d = c.min_mag(Decimal(1), Decimal(2))
1956 self.assertEqual(c.min_mag(1, 2), d)
1957 self.assertEqual(c.min_mag(Decimal(1), 2), d)
1958 self.assertEqual(c.min_mag(1, Decimal(2)), d)
1959 self.assertRaises(TypeError, c.min_mag, '1', 2)
1960 self.assertRaises(TypeError, c.min_mag, 1, '2')
1961
1962 def test_minus(self):
1963 c = Context()
1964 d = c.minus(Decimal(10))
1965 self.assertEqual(c.minus(10), d)
1966 self.assertRaises(TypeError, c.minus, '10')
1967
1968 def test_multiply(self):
1969 c = Context()
1970 d = c.multiply(Decimal(1), Decimal(2))
1971 self.assertEqual(c.multiply(1, 2), d)
1972 self.assertEqual(c.multiply(Decimal(1), 2), d)
1973 self.assertEqual(c.multiply(1, Decimal(2)), d)
1974 self.assertRaises(TypeError, c.multiply, '1', 2)
1975 self.assertRaises(TypeError, c.multiply, 1, '2')
1976
1977 def test_next_minus(self):
1978 c = Context()
1979 d = c.next_minus(Decimal(10))
1980 self.assertEqual(c.next_minus(10), d)
1981 self.assertRaises(TypeError, c.next_minus, '10')
1982
1983 def test_next_plus(self):
1984 c = Context()
1985 d = c.next_plus(Decimal(10))
1986 self.assertEqual(c.next_plus(10), d)
1987 self.assertRaises(TypeError, c.next_plus, '10')
1988
1989 def test_next_toward(self):
1990 c = Context()
1991 d = c.next_toward(Decimal(1), Decimal(2))
1992 self.assertEqual(c.next_toward(1, 2), d)
1993 self.assertEqual(c.next_toward(Decimal(1), 2), d)
1994 self.assertEqual(c.next_toward(1, Decimal(2)), d)
1995 self.assertRaises(TypeError, c.next_toward, '1', 2)
1996 self.assertRaises(TypeError, c.next_toward, 1, '2')
1997
1998 def test_normalize(self):
1999 c = Context()
2000 d = c.normalize(Decimal(10))
2001 self.assertEqual(c.normalize(10), d)
2002 self.assertRaises(TypeError, c.normalize, '10')
2003
2004 def test_number_class(self):
2005 c = Context()
2006 self.assertEqual(c.number_class(123), c.number_class(Decimal(123)))
2007 self.assertEqual(c.number_class(0), c.number_class(Decimal(0)))
2008 self.assertEqual(c.number_class(-45), c.number_class(Decimal(-45)))
2009
2010 def test_power(self):
2011 c = Context()
2012 d = c.power(Decimal(1), Decimal(4), Decimal(2))
2013 self.assertEqual(c.power(1, 4, 2), d)
2014 self.assertEqual(c.power(Decimal(1), 4, 2), d)
2015 self.assertEqual(c.power(1, Decimal(4), 2), d)
2016 self.assertEqual(c.power(1, 4, Decimal(2)), d)
2017 self.assertEqual(c.power(Decimal(1), Decimal(4), 2), d)
2018 self.assertRaises(TypeError, c.power, '1', 4, 2)
2019 self.assertRaises(TypeError, c.power, 1, '4', 2)
2020 self.assertRaises(TypeError, c.power, 1, 4, '2')
2021
2022 def test_plus(self):
2023 c = Context()
2024 d = c.plus(Decimal(10))
2025 self.assertEqual(c.plus(10), d)
2026 self.assertRaises(TypeError, c.plus, '10')
2027
2028 def test_quantize(self):
2029 c = Context()
2030 d = c.quantize(Decimal(1), Decimal(2))
2031 self.assertEqual(c.quantize(1, 2), d)
2032 self.assertEqual(c.quantize(Decimal(1), 2), d)
2033 self.assertEqual(c.quantize(1, Decimal(2)), d)
2034 self.assertRaises(TypeError, c.quantize, '1', 2)
2035 self.assertRaises(TypeError, c.quantize, 1, '2')
2036
2037 def test_remainder(self):
2038 c = Context()
2039 d = c.remainder(Decimal(1), Decimal(2))
2040 self.assertEqual(c.remainder(1, 2), d)
2041 self.assertEqual(c.remainder(Decimal(1), 2), d)
2042 self.assertEqual(c.remainder(1, Decimal(2)), d)
2043 self.assertRaises(TypeError, c.remainder, '1', 2)
2044 self.assertRaises(TypeError, c.remainder, 1, '2')
2045
2046 def test_remainder_near(self):
2047 c = Context()
2048 d = c.remainder_near(Decimal(1), Decimal(2))
2049 self.assertEqual(c.remainder_near(1, 2), d)
2050 self.assertEqual(c.remainder_near(Decimal(1), 2), d)
2051 self.assertEqual(c.remainder_near(1, Decimal(2)), d)
2052 self.assertRaises(TypeError, c.remainder_near, '1', 2)
2053 self.assertRaises(TypeError, c.remainder_near, 1, '2')
2054
2055 def test_rotate(self):
2056 c = Context()
2057 d = c.rotate(Decimal(1), Decimal(2))
2058 self.assertEqual(c.rotate(1, 2), d)
2059 self.assertEqual(c.rotate(Decimal(1), 2), d)
2060 self.assertEqual(c.rotate(1, Decimal(2)), d)
2061 self.assertRaises(TypeError, c.rotate, '1', 2)
2062 self.assertRaises(TypeError, c.rotate, 1, '2')
2063
2064 def test_sqrt(self):
2065 c = Context()
2066 d = c.sqrt(Decimal(10))
2067 self.assertEqual(c.sqrt(10), d)
2068 self.assertRaises(TypeError, c.sqrt, '10')
2069
2070 def test_same_quantum(self):
2071 c = Context()
2072 d = c.same_quantum(Decimal(1), Decimal(2))
2073 self.assertEqual(c.same_quantum(1, 2), d)
2074 self.assertEqual(c.same_quantum(Decimal(1), 2), d)
2075 self.assertEqual(c.same_quantum(1, Decimal(2)), d)
2076 self.assertRaises(TypeError, c.same_quantum, '1', 2)
2077 self.assertRaises(TypeError, c.same_quantum, 1, '2')
2078
2079 def test_scaleb(self):
2080 c = Context()
2081 d = c.scaleb(Decimal(1), Decimal(2))
2082 self.assertEqual(c.scaleb(1, 2), d)
2083 self.assertEqual(c.scaleb(Decimal(1), 2), d)
2084 self.assertEqual(c.scaleb(1, Decimal(2)), d)
2085 self.assertRaises(TypeError, c.scaleb, '1', 2)
2086 self.assertRaises(TypeError, c.scaleb, 1, '2')
2087
2088 def test_shift(self):
2089 c = Context()
2090 d = c.shift(Decimal(1), Decimal(2))
2091 self.assertEqual(c.shift(1, 2), d)
2092 self.assertEqual(c.shift(Decimal(1), 2), d)
2093 self.assertEqual(c.shift(1, Decimal(2)), d)
2094 self.assertRaises(TypeError, c.shift, '1', 2)
2095 self.assertRaises(TypeError, c.shift, 1, '2')
2096
2097 def test_subtract(self):
2098 c = Context()
2099 d = c.subtract(Decimal(1), Decimal(2))
2100 self.assertEqual(c.subtract(1, 2), d)
2101 self.assertEqual(c.subtract(Decimal(1), 2), d)
2102 self.assertEqual(c.subtract(1, Decimal(2)), d)
2103 self.assertRaises(TypeError, c.subtract, '1', 2)
2104 self.assertRaises(TypeError, c.subtract, 1, '2')
2105
2106 def test_to_eng_string(self):
2107 c = Context()
2108 d = c.to_eng_string(Decimal(10))
2109 self.assertEqual(c.to_eng_string(10), d)
2110 self.assertRaises(TypeError, c.to_eng_string, '10')
2111
2112 def test_to_sci_string(self):
2113 c = Context()
2114 d = c.to_sci_string(Decimal(10))
2115 self.assertEqual(c.to_sci_string(10), d)
2116 self.assertRaises(TypeError, c.to_sci_string, '10')
2117
2118 def test_to_integral_exact(self):
2119 c = Context()
2120 d = c.to_integral_exact(Decimal(10))
2121 self.assertEqual(c.to_integral_exact(10), d)
2122 self.assertRaises(TypeError, c.to_integral_exact, '10')
2123
2124 def test_to_integral_value(self):
2125 c = Context()
2126 d = c.to_integral_value(Decimal(10))
2127 self.assertEqual(c.to_integral_value(10), d)
2128 self.assertRaises(TypeError, c.to_integral_value, '10')
2129
Thomas Wouters89f507f2006-12-13 04:49:30 +00002130class WithStatementTest(unittest.TestCase):
2131 # Can't do these as docstrings until Python 2.6
2132 # as doctest can't handle __future__ statements
2133
2134 def test_localcontext(self):
2135 # Use a copy of the current context in the block
2136 orig_ctx = getcontext()
2137 with localcontext() as enter_ctx:
2138 set_ctx = getcontext()
2139 final_ctx = getcontext()
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00002140 self.assertTrue(orig_ctx is final_ctx, 'did not restore context correctly')
2141 self.assertTrue(orig_ctx is not set_ctx, 'did not copy the context')
2142 self.assertTrue(set_ctx is enter_ctx, '__enter__ returned wrong context')
Thomas Wouters89f507f2006-12-13 04:49:30 +00002143
2144 def test_localcontextarg(self):
2145 # Use a copy of the supplied context in the block
2146 orig_ctx = getcontext()
2147 new_ctx = Context(prec=42)
2148 with localcontext(new_ctx) as enter_ctx:
2149 set_ctx = getcontext()
2150 final_ctx = getcontext()
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00002151 self.assertTrue(orig_ctx is final_ctx, 'did not restore context correctly')
2152 self.assertTrue(set_ctx.prec == new_ctx.prec, 'did not set correct context')
2153 self.assertTrue(new_ctx is not set_ctx, 'did not copy the context')
2154 self.assertTrue(set_ctx is enter_ctx, '__enter__ returned wrong context')
Thomas Wouters89f507f2006-12-13 04:49:30 +00002155
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002156class ContextFlags(unittest.TestCase):
2157 def test_flags_irrelevant(self):
2158 # check that the result (numeric result + flags raised) of an
2159 # arithmetic operation doesn't depend on the current flags
2160
2161 context = Context(prec=9, Emin = -999999999, Emax = 999999999,
2162 rounding=ROUND_HALF_EVEN, traps=[], flags=[])
2163
2164 # operations that raise various flags, in the form (function, arglist)
2165 operations = [
2166 (context._apply, [Decimal("100E-1000000009")]),
2167 (context.sqrt, [Decimal(2)]),
2168 (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]),
2169 (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]),
2170 (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]),
2171 ]
2172
2173 # try various flags individually, then a whole lot at once
2174 flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal],
2175 [Inexact, Rounded, Underflow, Clamped, Subnormal]]
2176
2177 for fn, args in operations:
2178 # find answer and flags raised using a clean context
2179 context.clear_flags()
2180 ans = fn(*args)
2181 flags = [k for k, v in context.flags.items() if v]
2182
2183 for extra_flags in flagsets:
2184 # set flags, before calling operation
2185 context.clear_flags()
2186 for flag in extra_flags:
2187 context._raise_error(flag)
2188 new_ans = fn(*args)
2189
2190 # flags that we expect to be set after the operation
2191 expected_flags = list(flags)
2192 for flag in extra_flags:
2193 if flag not in expected_flags:
2194 expected_flags.append(flag)
2195 expected_flags.sort(key=id)
2196
2197 # flags we actually got
2198 new_flags = [k for k,v in context.flags.items() if v]
2199 new_flags.sort(key=id)
2200
2201 self.assertEqual(ans, new_ans,
2202 "operation produces different answers depending on flags set: " +
2203 "expected %s, got %s." % (ans, new_ans))
2204 self.assertEqual(new_flags, expected_flags,
2205 "operation raises different flags depending on flags set: " +
2206 "expected %s, got %s" % (expected_flags, new_flags))
2207
2208def test_main(arith=False, verbose=None, todo_tests=None, debug=None):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002209 """ Execute the tests.
2210
Raymond Hettingered20ad82004-09-04 20:09:13 +00002211 Runs all arithmetic tests if arith is True or if the "decimal" resource
2212 is enabled in regrtest.py
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002213 """
Raymond Hettingered20ad82004-09-04 20:09:13 +00002214
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002215 init()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002216 global TEST_ALL, DEBUG
Raymond Hettingered20ad82004-09-04 20:09:13 +00002217 TEST_ALL = arith or is_resource_enabled('decimal')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002218 DEBUG = debug
Raymond Hettingered20ad82004-09-04 20:09:13 +00002219
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002220 if todo_tests is None:
2221 test_classes = [
2222 DecimalExplicitConstructionTest,
2223 DecimalImplicitConstructionTest,
2224 DecimalArithmeticOperatorsTest,
Christian Heimesf16baeb2008-02-29 14:57:44 +00002225 DecimalFormatTest,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002226 DecimalUseOfContextTest,
2227 DecimalUsabilityTest,
2228 DecimalPythonAPItests,
2229 ContextAPItests,
2230 DecimalTest,
2231 WithStatementTest,
2232 ContextFlags
2233 ]
2234 else:
2235 test_classes = [DecimalTest]
2236
2237 # Dynamically build custom test definition for each file in the test
2238 # directory and add the definitions to the DecimalTest class. This
2239 # procedure insures that new files do not get skipped.
2240 for filename in os.listdir(directory):
2241 if '.decTest' not in filename or filename.startswith("."):
2242 continue
2243 head, tail = filename.split('.')
2244 if todo_tests is not None and head not in todo_tests:
2245 continue
2246 tester = lambda self, f=filename: self.eval_file(directory + f)
2247 setattr(DecimalTest, 'test_' + head, tester)
2248 del filename, head, tail, tester
2249
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002250
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002251 try:
2252 run_unittest(*test_classes)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002253 if todo_tests is None:
2254 import decimal as DecimalModule
2255 run_doctest(DecimalModule, verbose)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002256 finally:
2257 setcontext(ORIGINAL_CONTEXT)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002258
2259if __name__ == '__main__':
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002260 import optparse
2261 p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]")
2262 p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test')
2263 p.add_option('--skip', '-s', action='store_true', help='skip over 90% of the arithmetic tests')
2264 (opt, args) = p.parse_args()
2265
2266 if opt.skip:
2267 test_main(arith=False, verbose=True)
2268 elif args:
2269 test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002270 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002271 test_main(arith=True, verbose=True)