blob: dada7332bf87f80cfe1fab1fc239d71f3be9dc46 [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
475 def test_explicit_from_Decimal(self):
476
477 #positive
478 d = Decimal(45)
479 e = Decimal(d)
480 self.assertEqual(str(e), '45')
481 self.assertNotEqual(id(d), id(e))
482
483 #very large positive
484 d = Decimal(500000123)
485 e = Decimal(d)
486 self.assertEqual(str(e), '500000123')
487 self.assertNotEqual(id(d), id(e))
488
489 #negative
490 d = Decimal(-45)
491 e = Decimal(d)
492 self.assertEqual(str(e), '-45')
493 self.assertNotEqual(id(d), id(e))
494
495 #zero
496 d = Decimal(0)
497 e = Decimal(d)
498 self.assertEqual(str(e), '0')
499 self.assertNotEqual(id(d), id(e))
500
501 def test_explicit_context_create_decimal(self):
502
503 nc = copy.copy(getcontext())
504 nc.prec = 3
505
506 # empty
Raymond Hettingerfed52962004-07-14 15:41:57 +0000507 d = Decimal()
508 self.assertEqual(str(d), '0')
509 d = nc.create_decimal()
510 self.assertEqual(str(d), '0')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000511
512 # from None
513 self.assertRaises(TypeError, nc.create_decimal, None)
514
515 # from int
516 d = nc.create_decimal(456)
Ezio Melottie9615932010-01-24 19:26:24 +0000517 self.assertIsInstance(d, Decimal)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000518 self.assertEqual(nc.create_decimal(45678),
519 nc.create_decimal('457E+2'))
520
521 # from string
522 d = Decimal('456789')
523 self.assertEqual(str(d), '456789')
524 d = nc.create_decimal('456789')
525 self.assertEqual(str(d), '4.57E+5')
Christian Heimesa62da1d2008-01-12 19:39:10 +0000526 # leading and trailing whitespace should result in a NaN;
527 # spaces are already checked in Cowlishaw's test-suite, so
528 # here we just check that a trailing newline results in a NaN
529 self.assertEqual(str(nc.create_decimal('3.14\n')), 'NaN')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000530
531 # from tuples
532 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
533 self.assertEqual(str(d), '-4.34913534E-17')
534 d = nc.create_decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
535 self.assertEqual(str(d), '-4.35E-17')
536
537 # from Decimal
538 prevdec = Decimal(500000123)
539 d = Decimal(prevdec)
540 self.assertEqual(str(d), '500000123')
541 d = nc.create_decimal(prevdec)
542 self.assertEqual(str(d), '5.00E+8')
543
Mark Dickinson345adc42009-08-02 10:14:23 +0000544 def test_unicode_digits(self):
545 test_values = {
546 '\uff11': '1',
547 '\u0660.\u0660\u0663\u0667\u0662e-\u0663' : '0.0000372',
548 '-nan\u0c68\u0c6a\u0c66\u0c66' : '-NaN2400',
549 }
550 for input, expected in test_values.items():
551 self.assertEqual(str(Decimal(input)), expected)
552
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000553
554class DecimalImplicitConstructionTest(unittest.TestCase):
555 '''Unit tests for Implicit Construction cases of Decimal.'''
556
557 def test_implicit_from_None(self):
558 self.assertRaises(TypeError, eval, 'Decimal(5) + None', globals())
559
560 def test_implicit_from_int(self):
561 #normal
562 self.assertEqual(str(Decimal(5) + 45), '50')
563 #exceeding precision
564 self.assertEqual(Decimal(5) + 123456789000, Decimal(123456789000))
565
566 def test_implicit_from_string(self):
567 self.assertRaises(TypeError, eval, 'Decimal(5) + "3"', globals())
568
569 def test_implicit_from_float(self):
570 self.assertRaises(TypeError, eval, 'Decimal(5) + 2.2', globals())
571
572 def test_implicit_from_Decimal(self):
573 self.assertEqual(Decimal(5) + Decimal(45), Decimal(50))
574
Raymond Hettinger267b8682005-03-27 10:47:39 +0000575 def test_rop(self):
576 # Allow other classes to be trained to interact with Decimals
577 class E:
578 def __divmod__(self, other):
579 return 'divmod ' + str(other)
580 def __rdivmod__(self, other):
581 return str(other) + ' rdivmod'
582 def __lt__(self, other):
583 return 'lt ' + str(other)
584 def __gt__(self, other):
585 return 'gt ' + str(other)
586 def __le__(self, other):
587 return 'le ' + str(other)
588 def __ge__(self, other):
589 return 'ge ' + str(other)
590 def __eq__(self, other):
591 return 'eq ' + str(other)
592 def __ne__(self, other):
593 return 'ne ' + str(other)
594
595 self.assertEqual(divmod(E(), Decimal(10)), 'divmod 10')
596 self.assertEqual(divmod(Decimal(10), E()), '10 rdivmod')
597 self.assertEqual(eval('Decimal(10) < E()'), 'gt 10')
598 self.assertEqual(eval('Decimal(10) > E()'), 'lt 10')
599 self.assertEqual(eval('Decimal(10) <= E()'), 'ge 10')
600 self.assertEqual(eval('Decimal(10) >= E()'), 'le 10')
601 self.assertEqual(eval('Decimal(10) == E()'), 'eq 10')
602 self.assertEqual(eval('Decimal(10) != E()'), 'ne 10')
603
604 # insert operator methods and then exercise them
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000605 oplist = [
606 ('+', '__add__', '__radd__'),
607 ('-', '__sub__', '__rsub__'),
608 ('*', '__mul__', '__rmul__'),
Thomas Woutersdcc6d322006-04-21 11:30:52 +0000609 ('/', '__truediv__', '__rtruediv__'),
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000610 ('%', '__mod__', '__rmod__'),
611 ('//', '__floordiv__', '__rfloordiv__'),
612 ('**', '__pow__', '__rpow__')
613 ]
Raymond Hettinger267b8682005-03-27 10:47:39 +0000614
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000615 for sym, lop, rop in oplist:
Raymond Hettinger267b8682005-03-27 10:47:39 +0000616 setattr(E, lop, lambda self, other: 'str' + lop + str(other))
617 setattr(E, rop, lambda self, other: str(other) + rop + 'str')
618 self.assertEqual(eval('E()' + sym + 'Decimal(10)'),
619 'str' + lop + '10')
620 self.assertEqual(eval('Decimal(10)' + sym + 'E()'),
621 '10' + rop + 'str')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000622
Mark Dickinson79f52032009-03-17 23:12:51 +0000623
Christian Heimesf16baeb2008-02-29 14:57:44 +0000624class DecimalFormatTest(unittest.TestCase):
625 '''Unit tests for the format function.'''
626 def test_formatting(self):
627 # triples giving a format, a Decimal, and the expected result
628 test_values = [
629 ('e', '0E-15', '0e-15'),
630 ('e', '2.3E-15', '2.3e-15'),
631 ('e', '2.30E+2', '2.30e+2'), # preserve significant zeros
632 ('e', '2.30000E-15', '2.30000e-15'),
633 ('e', '1.23456789123456789e40', '1.23456789123456789e+40'),
634 ('e', '1.5', '1.5e+0'),
635 ('e', '0.15', '1.5e-1'),
636 ('e', '0.015', '1.5e-2'),
637 ('e', '0.0000000000015', '1.5e-12'),
638 ('e', '15.0', '1.50e+1'),
639 ('e', '-15', '-1.5e+1'),
640 ('e', '0', '0e+0'),
641 ('e', '0E1', '0e+1'),
642 ('e', '0.0', '0e-1'),
643 ('e', '0.00', '0e-2'),
644 ('.6e', '0E-15', '0.000000e-9'),
645 ('.6e', '0', '0.000000e+6'),
646 ('.6e', '9.999999', '9.999999e+0'),
647 ('.6e', '9.9999999', '1.000000e+1'),
648 ('.6e', '-1.23e5', '-1.230000e+5'),
649 ('.6e', '1.23456789e-3', '1.234568e-3'),
650 ('f', '0', '0'),
651 ('f', '0.0', '0.0'),
652 ('f', '0E-2', '0.00'),
653 ('f', '0.00E-8', '0.0000000000'),
654 ('f', '0E1', '0'), # loses exponent information
655 ('f', '3.2E1', '32'),
656 ('f', '3.2E2', '320'),
657 ('f', '3.20E2', '320'),
658 ('f', '3.200E2', '320.0'),
659 ('f', '3.2E-6', '0.0000032'),
660 ('.6f', '0E-15', '0.000000'), # all zeros treated equally
661 ('.6f', '0E1', '0.000000'),
662 ('.6f', '0', '0.000000'),
663 ('.0f', '0', '0'), # no decimal point
664 ('.0f', '0e-2', '0'),
665 ('.0f', '3.14159265', '3'),
666 ('.1f', '3.14159265', '3.1'),
667 ('.4f', '3.14159265', '3.1416'),
668 ('.6f', '3.14159265', '3.141593'),
669 ('.7f', '3.14159265', '3.1415926'), # round-half-even!
670 ('.8f', '3.14159265', '3.14159265'),
671 ('.9f', '3.14159265', '3.141592650'),
672
673 ('g', '0', '0'),
674 ('g', '0.0', '0.0'),
675 ('g', '0E1', '0e+1'),
676 ('G', '0E1', '0E+1'),
677 ('g', '0E-5', '0.00000'),
678 ('g', '0E-6', '0.000000'),
679 ('g', '0E-7', '0e-7'),
680 ('g', '-0E2', '-0e+2'),
681 ('.0g', '3.14159265', '3'), # 0 sig fig -> 1 sig fig
682 ('.1g', '3.14159265', '3'),
683 ('.2g', '3.14159265', '3.1'),
684 ('.5g', '3.14159265', '3.1416'),
685 ('.7g', '3.14159265', '3.141593'),
686 ('.8g', '3.14159265', '3.1415926'), # round-half-even!
687 ('.9g', '3.14159265', '3.14159265'),
688 ('.10g', '3.14159265', '3.14159265'), # don't pad
689
690 ('%', '0E1', '0%'),
691 ('%', '0E0', '0%'),
692 ('%', '0E-1', '0%'),
693 ('%', '0E-2', '0%'),
694 ('%', '0E-3', '0.0%'),
695 ('%', '0E-4', '0.00%'),
696
697 ('.3%', '0', '0.000%'), # all zeros treated equally
698 ('.3%', '0E10', '0.000%'),
699 ('.3%', '0E-10', '0.000%'),
700 ('.3%', '2.34', '234.000%'),
701 ('.3%', '1.234567', '123.457%'),
702 ('.0%', '1.23', '123%'),
703
704 ('e', 'NaN', 'NaN'),
705 ('f', '-NaN123', '-NaN123'),
706 ('+g', 'NaN456', '+NaN456'),
707 ('.3e', 'Inf', 'Infinity'),
708 ('.16f', '-Inf', '-Infinity'),
709 ('.0g', '-sNaN', '-sNaN'),
710
711 ('', '1.00', '1.00'),
Mark Dickinsonad416342009-03-17 18:10:15 +0000712
Mark Dickinson79f52032009-03-17 23:12:51 +0000713 # test alignment and padding
Mark Dickinson46ab5d02009-09-08 20:22:46 +0000714 ('6', '123', ' 123'),
Mark Dickinsonad416342009-03-17 18:10:15 +0000715 ('<6', '123', '123 '),
716 ('>6', '123', ' 123'),
717 ('^6', '123', ' 123 '),
718 ('=+6', '123', '+ 123'),
Mark Dickinson79f52032009-03-17 23:12:51 +0000719 ('#<10', 'NaN', 'NaN#######'),
720 ('#<10', '-4.3', '-4.3######'),
721 ('#<+10', '0.0130', '+0.0130###'),
722 ('#< 10', '0.0130', ' 0.0130###'),
723 ('@>10', '-Inf', '@-Infinity'),
724 ('#>5', '-Inf', '-Infinity'),
725 ('?^5', '123', '?123?'),
726 ('%^6', '123', '%123%%'),
727 (' ^6', '-45.6', '-45.6 '),
728 ('/=10', '-45.6', '-/////45.6'),
729 ('/=+10', '45.6', '+/////45.6'),
730 ('/= 10', '45.6', ' /////45.6'),
731
732 # thousands separator
733 (',', '1234567', '1,234,567'),
734 (',', '123456', '123,456'),
735 (',', '12345', '12,345'),
736 (',', '1234', '1,234'),
737 (',', '123', '123'),
738 (',', '12', '12'),
739 (',', '1', '1'),
740 (',', '0', '0'),
741 (',', '-1234567', '-1,234,567'),
742 (',', '-123456', '-123,456'),
743 ('7,', '123456', '123,456'),
Mark Dickinson46ab5d02009-09-08 20:22:46 +0000744 ('8,', '123456', ' 123,456'),
Mark Dickinson79f52032009-03-17 23:12:51 +0000745 ('08,', '123456', '0,123,456'), # special case: extra 0 needed
746 ('+08,', '123456', '+123,456'), # but not if there's a sign
747 (' 08,', '123456', ' 123,456'),
748 ('08,', '-123456', '-123,456'),
749 ('+09,', '123456', '+0,123,456'),
750 # ... with fractional part...
751 ('07,', '1234.56', '1,234.56'),
752 ('08,', '1234.56', '1,234.56'),
753 ('09,', '1234.56', '01,234.56'),
754 ('010,', '1234.56', '001,234.56'),
755 ('011,', '1234.56', '0,001,234.56'),
756 ('012,', '1234.56', '0,001,234.56'),
757 ('08,.1f', '1234.5', '01,234.5'),
758 # no thousands separators in fraction part
759 (',', '1.23456789', '1.23456789'),
760 (',%', '123.456789', '12,345.6789%'),
761 (',e', '123456', '1.23456e+5'),
762 (',E', '123456', '1.23456E+5'),
Mark Dickinson7718d2b2009-09-07 16:21:56 +0000763
764 # issue 6850
765 ('a=-7.0', '0.12345', 'aaaa0.1'),
Christian Heimesf16baeb2008-02-29 14:57:44 +0000766 ]
767 for fmt, d, result in test_values:
768 self.assertEqual(format(Decimal(d), fmt), result)
769
Mark Dickinson79f52032009-03-17 23:12:51 +0000770 def test_n_format(self):
771 try:
772 from locale import CHAR_MAX
773 except ImportError:
774 return
775
776 # Set up some localeconv-like dictionaries
777 en_US = {
778 'decimal_point' : '.',
779 'grouping' : [3, 3, 0],
780 'thousands_sep': ','
781 }
782
783 fr_FR = {
784 'decimal_point' : ',',
785 'grouping' : [CHAR_MAX],
786 'thousands_sep' : ''
787 }
788
789 ru_RU = {
790 'decimal_point' : ',',
791 'grouping' : [3, 3, 0],
792 'thousands_sep' : ' '
793 }
794
795 crazy = {
796 'decimal_point' : '&',
797 'grouping' : [1, 4, 2, CHAR_MAX],
798 'thousands_sep' : '-'
799 }
800
801
802 def get_fmt(x, locale, fmt='n'):
803 return Decimal.__format__(Decimal(x), fmt, _localeconv=locale)
804
805 self.assertEqual(get_fmt(Decimal('12.7'), en_US), '12.7')
806 self.assertEqual(get_fmt(Decimal('12.7'), fr_FR), '12,7')
807 self.assertEqual(get_fmt(Decimal('12.7'), ru_RU), '12,7')
808 self.assertEqual(get_fmt(Decimal('12.7'), crazy), '1-2&7')
809
810 self.assertEqual(get_fmt(123456789, en_US), '123,456,789')
811 self.assertEqual(get_fmt(123456789, fr_FR), '123456789')
812 self.assertEqual(get_fmt(123456789, ru_RU), '123 456 789')
813 self.assertEqual(get_fmt(1234567890123, crazy), '123456-78-9012-3')
814
815 self.assertEqual(get_fmt(123456789, en_US, '.6n'), '1.23457e+8')
816 self.assertEqual(get_fmt(123456789, fr_FR, '.6n'), '1,23457e+8')
817 self.assertEqual(get_fmt(123456789, ru_RU, '.6n'), '1,23457e+8')
818 self.assertEqual(get_fmt(123456789, crazy, '.6n'), '1&23457e+8')
819
Mark Dickinson7303b592009-03-18 08:25:36 +0000820 # zero padding
821 self.assertEqual(get_fmt(1234, fr_FR, '03n'), '1234')
822 self.assertEqual(get_fmt(1234, fr_FR, '04n'), '1234')
823 self.assertEqual(get_fmt(1234, fr_FR, '05n'), '01234')
824 self.assertEqual(get_fmt(1234, fr_FR, '06n'), '001234')
825
826 self.assertEqual(get_fmt(12345, en_US, '05n'), '12,345')
827 self.assertEqual(get_fmt(12345, en_US, '06n'), '12,345')
828 self.assertEqual(get_fmt(12345, en_US, '07n'), '012,345')
829 self.assertEqual(get_fmt(12345, en_US, '08n'), '0,012,345')
830 self.assertEqual(get_fmt(12345, en_US, '09n'), '0,012,345')
831 self.assertEqual(get_fmt(12345, en_US, '010n'), '00,012,345')
832
833 self.assertEqual(get_fmt(123456, crazy, '06n'), '1-2345-6')
834 self.assertEqual(get_fmt(123456, crazy, '07n'), '1-2345-6')
835 self.assertEqual(get_fmt(123456, crazy, '08n'), '1-2345-6')
836 self.assertEqual(get_fmt(123456, crazy, '09n'), '01-2345-6')
837 self.assertEqual(get_fmt(123456, crazy, '010n'), '0-01-2345-6')
838 self.assertEqual(get_fmt(123456, crazy, '011n'), '0-01-2345-6')
839 self.assertEqual(get_fmt(123456, crazy, '012n'), '00-01-2345-6')
840 self.assertEqual(get_fmt(123456, crazy, '013n'), '000-01-2345-6')
841
Mark Dickinson79f52032009-03-17 23:12:51 +0000842
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000843class DecimalArithmeticOperatorsTest(unittest.TestCase):
844 '''Unit tests for all arithmetic operators, binary and unary.'''
845
846 def test_addition(self):
847
848 d1 = Decimal('-11.1')
849 d2 = Decimal('22.2')
850
851 #two Decimals
852 self.assertEqual(d1+d2, Decimal('11.1'))
853 self.assertEqual(d2+d1, Decimal('11.1'))
854
855 #with other type, left
856 c = d1 + 5
857 self.assertEqual(c, Decimal('-6.1'))
858 self.assertEqual(type(c), type(d1))
859
860 #with other type, right
861 c = 5 + d1
862 self.assertEqual(c, Decimal('-6.1'))
863 self.assertEqual(type(c), type(d1))
864
865 #inline with decimal
866 d1 += d2
867 self.assertEqual(d1, Decimal('11.1'))
868
869 #inline with other type
870 d1 += 5
871 self.assertEqual(d1, Decimal('16.1'))
872
873 def test_subtraction(self):
874
875 d1 = Decimal('-11.1')
876 d2 = Decimal('22.2')
877
878 #two Decimals
879 self.assertEqual(d1-d2, Decimal('-33.3'))
880 self.assertEqual(d2-d1, Decimal('33.3'))
881
882 #with other type, left
883 c = d1 - 5
884 self.assertEqual(c, Decimal('-16.1'))
885 self.assertEqual(type(c), type(d1))
886
887 #with other type, right
888 c = 5 - d1
889 self.assertEqual(c, Decimal('16.1'))
890 self.assertEqual(type(c), type(d1))
891
892 #inline with decimal
893 d1 -= d2
894 self.assertEqual(d1, Decimal('-33.3'))
895
896 #inline with other type
897 d1 -= 5
898 self.assertEqual(d1, Decimal('-38.3'))
899
900 def test_multiplication(self):
901
902 d1 = Decimal('-5')
903 d2 = Decimal('3')
904
905 #two Decimals
906 self.assertEqual(d1*d2, Decimal('-15'))
907 self.assertEqual(d2*d1, Decimal('-15'))
908
909 #with other type, left
910 c = d1 * 5
911 self.assertEqual(c, Decimal('-25'))
912 self.assertEqual(type(c), type(d1))
913
914 #with other type, right
915 c = 5 * d1
916 self.assertEqual(c, Decimal('-25'))
917 self.assertEqual(type(c), type(d1))
918
919 #inline with decimal
920 d1 *= d2
921 self.assertEqual(d1, Decimal('-15'))
922
923 #inline with other type
924 d1 *= 5
925 self.assertEqual(d1, Decimal('-75'))
926
927 def test_division(self):
928
929 d1 = Decimal('-5')
930 d2 = Decimal('2')
931
932 #two Decimals
933 self.assertEqual(d1/d2, Decimal('-2.5'))
934 self.assertEqual(d2/d1, Decimal('-0.4'))
935
936 #with other type, left
937 c = d1 / 4
938 self.assertEqual(c, Decimal('-1.25'))
939 self.assertEqual(type(c), type(d1))
940
941 #with other type, right
942 c = 4 / d1
943 self.assertEqual(c, Decimal('-0.8'))
944 self.assertEqual(type(c), type(d1))
945
946 #inline with decimal
947 d1 /= d2
948 self.assertEqual(d1, Decimal('-2.5'))
949
950 #inline with other type
951 d1 /= 4
952 self.assertEqual(d1, Decimal('-0.625'))
953
954 def test_floor_division(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000955
956 d1 = Decimal('5')
957 d2 = Decimal('2')
958
959 #two Decimals
960 self.assertEqual(d1//d2, Decimal('2'))
961 self.assertEqual(d2//d1, Decimal('0'))
962
963 #with other type, left
964 c = d1 // 4
965 self.assertEqual(c, Decimal('1'))
966 self.assertEqual(type(c), type(d1))
967
968 #with other type, right
969 c = 7 // d1
970 self.assertEqual(c, Decimal('1'))
971 self.assertEqual(type(c), type(d1))
972
973 #inline with decimal
974 d1 //= d2
975 self.assertEqual(d1, Decimal('2'))
976
977 #inline with other type
978 d1 //= 2
979 self.assertEqual(d1, Decimal('1'))
980
981 def test_powering(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000982
983 d1 = Decimal('5')
984 d2 = Decimal('2')
985
986 #two Decimals
987 self.assertEqual(d1**d2, Decimal('25'))
988 self.assertEqual(d2**d1, Decimal('32'))
989
990 #with other type, left
991 c = d1 ** 4
992 self.assertEqual(c, Decimal('625'))
993 self.assertEqual(type(c), type(d1))
994
995 #with other type, right
996 c = 7 ** d1
997 self.assertEqual(c, Decimal('16807'))
998 self.assertEqual(type(c), type(d1))
999
1000 #inline with decimal
1001 d1 **= d2
1002 self.assertEqual(d1, Decimal('25'))
1003
1004 #inline with other type
1005 d1 **= 4
1006 self.assertEqual(d1, Decimal('390625'))
1007
1008 def test_module(self):
1009
1010 d1 = Decimal('5')
1011 d2 = Decimal('2')
1012
1013 #two Decimals
1014 self.assertEqual(d1%d2, Decimal('1'))
1015 self.assertEqual(d2%d1, Decimal('2'))
1016
1017 #with other type, left
1018 c = d1 % 4
1019 self.assertEqual(c, Decimal('1'))
1020 self.assertEqual(type(c), type(d1))
1021
1022 #with other type, right
1023 c = 7 % d1
1024 self.assertEqual(c, Decimal('2'))
1025 self.assertEqual(type(c), type(d1))
1026
1027 #inline with decimal
1028 d1 %= d2
1029 self.assertEqual(d1, Decimal('1'))
1030
1031 #inline with other type
1032 d1 %= 4
1033 self.assertEqual(d1, Decimal('1'))
1034
1035 def test_floor_div_module(self):
1036
1037 d1 = Decimal('5')
1038 d2 = Decimal('2')
1039
1040 #two Decimals
1041 (p, q) = divmod(d1, d2)
1042 self.assertEqual(p, Decimal('2'))
1043 self.assertEqual(q, Decimal('1'))
1044 self.assertEqual(type(p), type(d1))
1045 self.assertEqual(type(q), type(d1))
1046
1047 #with other type, left
1048 (p, q) = divmod(d1, 4)
1049 self.assertEqual(p, Decimal('1'))
1050 self.assertEqual(q, Decimal('1'))
1051 self.assertEqual(type(p), type(d1))
1052 self.assertEqual(type(q), type(d1))
1053
1054 #with other type, right
1055 (p, q) = divmod(7, d1)
1056 self.assertEqual(p, Decimal('1'))
1057 self.assertEqual(q, Decimal('2'))
1058 self.assertEqual(type(p), type(d1))
1059 self.assertEqual(type(q), type(d1))
1060
1061 def test_unary_operators(self):
1062 self.assertEqual(+Decimal(45), Decimal(+45)) # +
1063 self.assertEqual(-Decimal(45), Decimal(-45)) # -
1064 self.assertEqual(abs(Decimal(45)), abs(Decimal(-45))) # abs
1065
Christian Heimes77c02eb2008-02-09 02:18:51 +00001066 def test_nan_comparisons(self):
1067 n = Decimal('NaN')
1068 s = Decimal('sNaN')
1069 i = Decimal('Inf')
1070 f = Decimal('2')
1071 for x, y in [(n, n), (n, i), (i, n), (n, f), (f, n),
1072 (s, n), (n, s), (s, i), (i, s), (s, f), (f, s), (s, s)]:
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001073 self.assertTrue(x != y)
1074 self.assertTrue(not (x == y))
1075 self.assertTrue(not (x < y))
1076 self.assertTrue(not (x <= y))
1077 self.assertTrue(not (x > y))
1078 self.assertTrue(not (x >= y))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001079
Mark Dickinson84230a12010-02-18 14:49:50 +00001080 def test_copy_sign(self):
1081 d = Decimal(1).copy_sign(Decimal(-2))
1082
1083 self.assertEqual(Decimal(1).copy_sign(-2), d)
1084 self.assertRaises(TypeError, Decimal(1).copy_sign, '-2')
1085
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001086# The following are two functions used to test threading in the next class
1087
1088def thfunc1(cls):
1089 d1 = Decimal(1)
1090 d3 = Decimal(3)
Christian Heimesfe337bf2008-03-23 21:54:12 +00001091 test1 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001092 cls.synchro.wait()
Christian Heimesfe337bf2008-03-23 21:54:12 +00001093 test2 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001094 cls.finish1.set()
Christian Heimesfe337bf2008-03-23 21:54:12 +00001095
Christian Heimes81ee3ef2008-05-04 22:42:01 +00001096 cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
1097 cls.assertEqual(test2, Decimal('0.3333333333333333333333333333'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001098 return
1099
1100def thfunc2(cls):
1101 d1 = Decimal(1)
1102 d3 = Decimal(3)
Christian Heimesfe337bf2008-03-23 21:54:12 +00001103 test1 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001104 thiscontext = getcontext()
1105 thiscontext.prec = 18
Christian Heimesfe337bf2008-03-23 21:54:12 +00001106 test2 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001107 cls.synchro.set()
1108 cls.finish2.set()
Christian Heimesfe337bf2008-03-23 21:54:12 +00001109
Christian Heimes81ee3ef2008-05-04 22:42:01 +00001110 cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
Christian Heimesfe337bf2008-03-23 21:54:12 +00001111 cls.assertEqual(test2, Decimal('0.333333333333333333'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001112 return
1113
1114
1115class DecimalUseOfContextTest(unittest.TestCase):
1116 '''Unit tests for Use of Context cases in Decimal.'''
1117
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001118 try:
1119 import threading
1120 except ImportError:
1121 threading = None
1122
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001123 # Take care executing this test from IDLE, there's an issue in threading
1124 # that hangs IDLE and I couldn't find it
1125
1126 def test_threading(self):
1127 #Test the "threading isolation" of a Context.
1128
1129 self.synchro = threading.Event()
1130 self.finish1 = threading.Event()
1131 self.finish2 = threading.Event()
1132
1133 th1 = threading.Thread(target=thfunc1, args=(self,))
1134 th2 = threading.Thread(target=thfunc2, args=(self,))
1135
1136 th1.start()
1137 th2.start()
1138
1139 self.finish1.wait()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001140 self.finish2.wait()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001141 return
1142
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001143 if threading is None:
1144 del test_threading
1145
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001146
1147class DecimalUsabilityTest(unittest.TestCase):
1148 '''Unit tests for Usability cases of Decimal.'''
1149
1150 def test_comparison_operators(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001151
1152 da = Decimal('23.42')
1153 db = Decimal('23.42')
1154 dc = Decimal('45')
1155
1156 #two Decimals
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001157 self.assertTrue(dc > da)
1158 self.assertTrue(dc >= da)
1159 self.assertTrue(da < dc)
1160 self.assertTrue(da <= dc)
Guido van Rossume61fd5b2007-07-11 12:20:59 +00001161 self.assertEqual(da, db)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001162 self.assertTrue(da != dc)
1163 self.assertTrue(da <= db)
1164 self.assertTrue(da >= db)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001165
1166 #a Decimal and an int
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001167 self.assertTrue(dc > 23)
1168 self.assertTrue(23 < dc)
Guido van Rossume61fd5b2007-07-11 12:20:59 +00001169 self.assertEqual(dc, 45)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001170
1171 #a Decimal and uncomparable
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001172 self.assertNotEqual(da, 'ugly')
1173 self.assertNotEqual(da, 32.7)
1174 self.assertNotEqual(da, object())
1175 self.assertNotEqual(da, object)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001176
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001177 # sortable
Guido van Rossumc1f779c2007-07-03 08:25:58 +00001178 a = list(map(Decimal, range(100)))
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001179 b = a[:]
1180 random.shuffle(a)
1181 a.sort()
1182 self.assertEqual(a, b)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001183
1184 def test_copy_and_deepcopy_methods(self):
1185 d = Decimal('43.24')
1186 c = copy.copy(d)
1187 self.assertEqual(id(c), id(d))
1188 dc = copy.deepcopy(d)
1189 self.assertEqual(id(dc), id(d))
1190
1191 def test_hash_method(self):
1192 #just that it's hashable
1193 hash(Decimal(23))
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001194
1195 test_values = [Decimal(sign*(2**m + n))
1196 for m in [0, 14, 15, 16, 17, 30, 31,
1197 32, 33, 62, 63, 64, 65, 66]
1198 for n in range(-10, 10)
1199 for sign in [-1, 1]]
1200 test_values.extend([
1201 Decimal("-0"), # zeros
1202 Decimal("0.00"),
1203 Decimal("-0.000"),
1204 Decimal("0E10"),
1205 Decimal("-0E12"),
1206 Decimal("10.0"), # negative exponent
1207 Decimal("-23.00000"),
1208 Decimal("1230E100"), # positive exponent
1209 Decimal("-4.5678E50"),
1210 # a value for which hash(n) != hash(n % (2**64-1))
1211 # in Python pre-2.6
1212 Decimal(2**64 + 2**32 - 1),
1213 # selection of values which fail with the old (before
1214 # version 2.6) long.__hash__
1215 Decimal("1.634E100"),
1216 Decimal("90.697E100"),
1217 Decimal("188.83E100"),
1218 Decimal("1652.9E100"),
1219 Decimal("56531E100"),
1220 ])
1221
1222 # check that hash(d) == hash(int(d)) for integral values
1223 for value in test_values:
1224 self.assertEqual(hash(value), hash(int(value)))
1225
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001226 #the same hash that to an int
1227 self.assertEqual(hash(Decimal(23)), hash(23))
Raymond Hettingerbea3f6f2005-03-15 04:59:17 +00001228 self.assertRaises(TypeError, hash, Decimal('NaN'))
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001229 self.assertTrue(hash(Decimal('Inf')))
1230 self.assertTrue(hash(Decimal('-Inf')))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001231
Christian Heimes2380ac72008-01-09 00:17:24 +00001232 # check that the value of the hash doesn't depend on the
1233 # current context (issue #1757)
1234 c = getcontext()
1235 old_precision = c.prec
1236 x = Decimal("123456789.1")
1237
1238 c.prec = 6
1239 h1 = hash(x)
1240 c.prec = 10
1241 h2 = hash(x)
1242 c.prec = 16
1243 h3 = hash(x)
1244
1245 self.assertEqual(h1, h2)
1246 self.assertEqual(h1, h3)
1247 c.prec = old_precision
1248
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001249 def test_min_and_max_methods(self):
1250
1251 d1 = Decimal('15.32')
1252 d2 = Decimal('28.5')
1253 l1 = 15
1254 l2 = 28
1255
1256 #between Decimals
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001257 self.assertTrue(min(d1,d2) is d1)
1258 self.assertTrue(min(d2,d1) is d1)
1259 self.assertTrue(max(d1,d2) is d2)
1260 self.assertTrue(max(d2,d1) is d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001261
1262 #between Decimal and long
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001263 self.assertTrue(min(d1,l2) is d1)
1264 self.assertTrue(min(l2,d1) is d1)
1265 self.assertTrue(max(l1,d2) is d2)
1266 self.assertTrue(max(d2,l1) is d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001267
1268 def test_as_nonzero(self):
1269 #as false
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001270 self.assertFalse(Decimal(0))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001271 #as true
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001272 self.assertTrue(Decimal('0.372'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001273
1274 def test_tostring_methods(self):
1275 #Test str and repr methods.
1276
1277 d = Decimal('15.32')
1278 self.assertEqual(str(d), '15.32') # str
Christian Heimes68f5fbe2008-02-14 08:27:37 +00001279 self.assertEqual(repr(d), "Decimal('15.32')") # repr
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001280
1281 def test_tonum_methods(self):
Mark Dickinson5c2db372009-12-05 20:28:34 +00001282 #Test float and int methods.
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001283
1284 d1 = Decimal('66')
1285 d2 = Decimal('15.32')
1286
1287 #int
1288 self.assertEqual(int(d1), 66)
1289 self.assertEqual(int(d2), 15)
1290
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001291 #float
1292 self.assertEqual(float(d1), 66)
1293 self.assertEqual(float(d2), 15.32)
1294
Mark Dickinsonb27406c2008-05-09 13:42:33 +00001295 #floor
1296 test_pairs = [
1297 ('123.00', 123),
1298 ('3.2', 3),
1299 ('3.54', 3),
1300 ('3.899', 3),
1301 ('-2.3', -3),
1302 ('-11.0', -11),
1303 ('0.0', 0),
1304 ('-0E3', 0),
1305 ]
1306 for d, i in test_pairs:
1307 self.assertEqual(math.floor(Decimal(d)), i)
1308 self.assertRaises(ValueError, math.floor, Decimal('-NaN'))
1309 self.assertRaises(ValueError, math.floor, Decimal('sNaN'))
1310 self.assertRaises(ValueError, math.floor, Decimal('NaN123'))
1311 self.assertRaises(OverflowError, math.floor, Decimal('Inf'))
1312 self.assertRaises(OverflowError, math.floor, Decimal('-Inf'))
1313
1314 #ceiling
1315 test_pairs = [
1316 ('123.00', 123),
1317 ('3.2', 4),
1318 ('3.54', 4),
1319 ('3.899', 4),
1320 ('-2.3', -2),
1321 ('-11.0', -11),
1322 ('0.0', 0),
1323 ('-0E3', 0),
1324 ]
1325 for d, i in test_pairs:
1326 self.assertEqual(math.ceil(Decimal(d)), i)
1327 self.assertRaises(ValueError, math.ceil, Decimal('-NaN'))
1328 self.assertRaises(ValueError, math.ceil, Decimal('sNaN'))
1329 self.assertRaises(ValueError, math.ceil, Decimal('NaN123'))
1330 self.assertRaises(OverflowError, math.ceil, Decimal('Inf'))
1331 self.assertRaises(OverflowError, math.ceil, Decimal('-Inf'))
1332
1333 #round, single argument
1334 test_pairs = [
1335 ('123.00', 123),
1336 ('3.2', 3),
1337 ('3.54', 4),
1338 ('3.899', 4),
1339 ('-2.3', -2),
1340 ('-11.0', -11),
1341 ('0.0', 0),
1342 ('-0E3', 0),
1343 ('-3.5', -4),
1344 ('-2.5', -2),
1345 ('-1.5', -2),
1346 ('-0.5', 0),
1347 ('0.5', 0),
1348 ('1.5', 2),
1349 ('2.5', 2),
1350 ('3.5', 4),
1351 ]
1352 for d, i in test_pairs:
1353 self.assertEqual(round(Decimal(d)), i)
1354 self.assertRaises(ValueError, round, Decimal('-NaN'))
1355 self.assertRaises(ValueError, round, Decimal('sNaN'))
1356 self.assertRaises(ValueError, round, Decimal('NaN123'))
1357 self.assertRaises(OverflowError, round, Decimal('Inf'))
1358 self.assertRaises(OverflowError, round, Decimal('-Inf'))
1359
1360 #round, two arguments; this is essentially equivalent
1361 #to quantize, which is already extensively tested
1362 test_triples = [
1363 ('123.456', -4, '0E+4'),
1364 ('123.456', -3, '0E+3'),
1365 ('123.456', -2, '1E+2'),
1366 ('123.456', -1, '1.2E+2'),
1367 ('123.456', 0, '123'),
1368 ('123.456', 1, '123.5'),
1369 ('123.456', 2, '123.46'),
1370 ('123.456', 3, '123.456'),
1371 ('123.456', 4, '123.4560'),
1372 ('123.455', 2, '123.46'),
1373 ('123.445', 2, '123.44'),
1374 ('Inf', 4, 'NaN'),
1375 ('-Inf', -23, 'NaN'),
1376 ('sNaN314', 3, 'NaN314'),
1377 ]
1378 for d, n, r in test_triples:
1379 self.assertEqual(str(round(Decimal(d), n)), r)
1380
1381
1382
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001383 def test_eval_round_trip(self):
1384
1385 #with zero
1386 d = Decimal( (0, (0,), 0) )
1387 self.assertEqual(d, eval(repr(d)))
1388
1389 #int
1390 d = Decimal( (1, (4, 5), 0) )
1391 self.assertEqual(d, eval(repr(d)))
1392
1393 #float
1394 d = Decimal( (0, (4, 5, 3, 4), -2) )
1395 self.assertEqual(d, eval(repr(d)))
1396
1397 #weird
1398 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1399 self.assertEqual(d, eval(repr(d)))
1400
1401 def test_as_tuple(self):
1402
1403 #with zero
1404 d = Decimal(0)
1405 self.assertEqual(d.as_tuple(), (0, (0,), 0) )
1406
1407 #int
1408 d = Decimal(-45)
1409 self.assertEqual(d.as_tuple(), (1, (4, 5), 0) )
1410
1411 #complicated string
1412 d = Decimal("-4.34913534E-17")
1413 self.assertEqual(d.as_tuple(), (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1414
1415 #inf
1416 d = Decimal("Infinity")
1417 self.assertEqual(d.as_tuple(), (0, (0,), 'F') )
1418
Guido van Rossum8ce8a782007-11-01 19:42:39 +00001419 #leading zeros in coefficient should be stripped
1420 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), -2) )
1421 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), -2) )
1422 d = Decimal( (1, (0, 0, 0), 37) )
1423 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1424 d = Decimal( (1, (), 37) )
1425 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1426
1427 #leading zeros in NaN diagnostic info should be stripped
1428 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), 'n') )
1429 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), 'n') )
1430 d = Decimal( (1, (0, 0, 0), 'N') )
1431 self.assertEqual(d.as_tuple(), (1, (), 'N') )
1432 d = Decimal( (1, (), 'n') )
1433 self.assertEqual(d.as_tuple(), (1, (), 'n') )
1434
1435 #coefficient in infinity should be ignored
1436 d = Decimal( (0, (4, 5, 3, 4), 'F') )
1437 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
1438 d = Decimal( (1, (0, 2, 7, 1), 'F') )
1439 self.assertEqual(d.as_tuple(), (1, (0,), 'F'))
1440
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001441 def test_immutability_operations(self):
1442 # Do operations and check that it didn't change change internal objects.
1443
1444 d1 = Decimal('-25e55')
1445 b1 = Decimal('-25e55')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001446 d2 = Decimal('33e+33')
1447 b2 = Decimal('33e+33')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001448
1449 def checkSameDec(operation, useOther=False):
1450 if useOther:
1451 eval("d1." + operation + "(d2)")
1452 self.assertEqual(d1._sign, b1._sign)
1453 self.assertEqual(d1._int, b1._int)
1454 self.assertEqual(d1._exp, b1._exp)
1455 self.assertEqual(d2._sign, b2._sign)
1456 self.assertEqual(d2._int, b2._int)
1457 self.assertEqual(d2._exp, b2._exp)
1458 else:
1459 eval("d1." + operation + "()")
1460 self.assertEqual(d1._sign, b1._sign)
1461 self.assertEqual(d1._int, b1._int)
1462 self.assertEqual(d1._exp, b1._exp)
1463 return
1464
1465 Decimal(d1)
1466 self.assertEqual(d1._sign, b1._sign)
1467 self.assertEqual(d1._int, b1._int)
1468 self.assertEqual(d1._exp, b1._exp)
1469
1470 checkSameDec("__abs__")
1471 checkSameDec("__add__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001472 checkSameDec("__divmod__", True)
Christian Heimes77c02eb2008-02-09 02:18:51 +00001473 checkSameDec("__eq__", True)
1474 checkSameDec("__ne__", True)
1475 checkSameDec("__le__", True)
1476 checkSameDec("__lt__", True)
1477 checkSameDec("__ge__", True)
1478 checkSameDec("__gt__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001479 checkSameDec("__float__")
1480 checkSameDec("__floordiv__", True)
1481 checkSameDec("__hash__")
1482 checkSameDec("__int__")
Christian Heimes969fe572008-01-25 11:23:10 +00001483 checkSameDec("__trunc__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001484 checkSameDec("__mod__", True)
1485 checkSameDec("__mul__", True)
1486 checkSameDec("__neg__")
Jack Diederich4dafcc42006-11-28 19:15:13 +00001487 checkSameDec("__bool__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001488 checkSameDec("__pos__")
1489 checkSameDec("__pow__", True)
1490 checkSameDec("__radd__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001491 checkSameDec("__rdivmod__", True)
1492 checkSameDec("__repr__")
1493 checkSameDec("__rfloordiv__", True)
1494 checkSameDec("__rmod__", True)
1495 checkSameDec("__rmul__", True)
1496 checkSameDec("__rpow__", True)
1497 checkSameDec("__rsub__", True)
1498 checkSameDec("__str__")
1499 checkSameDec("__sub__", True)
1500 checkSameDec("__truediv__", True)
1501 checkSameDec("adjusted")
1502 checkSameDec("as_tuple")
1503 checkSameDec("compare", True)
1504 checkSameDec("max", True)
1505 checkSameDec("min", True)
1506 checkSameDec("normalize")
1507 checkSameDec("quantize", True)
1508 checkSameDec("remainder_near", True)
1509 checkSameDec("same_quantum", True)
1510 checkSameDec("sqrt")
1511 checkSameDec("to_eng_string")
1512 checkSameDec("to_integral")
1513
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001514 def test_subclassing(self):
1515 # Different behaviours when subclassing Decimal
1516
1517 class MyDecimal(Decimal):
1518 pass
1519
1520 d1 = MyDecimal(1)
1521 d2 = MyDecimal(2)
1522 d = d1 + d2
1523 self.assertTrue(type(d) is Decimal)
1524
1525 d = d1.max(d2)
1526 self.assertTrue(type(d) is Decimal)
1527
Christian Heimes0348fb62008-03-26 12:55:56 +00001528 def test_implicit_context(self):
1529 # Check results when context given implicitly. (Issue 2478)
1530 c = getcontext()
1531 self.assertEqual(str(Decimal(0).sqrt()),
1532 str(c.sqrt(Decimal(0))))
1533
Mark Dickinsona2d1fe02009-10-29 12:23:02 +00001534 def test_conversions_from_int(self):
1535 # Check that methods taking a second Decimal argument will
1536 # always accept an integer in place of a Decimal.
1537 self.assertEqual(Decimal(4).compare(3),
1538 Decimal(4).compare(Decimal(3)))
1539 self.assertEqual(Decimal(4).compare_signal(3),
1540 Decimal(4).compare_signal(Decimal(3)))
1541 self.assertEqual(Decimal(4).compare_total(3),
1542 Decimal(4).compare_total(Decimal(3)))
1543 self.assertEqual(Decimal(4).compare_total_mag(3),
1544 Decimal(4).compare_total_mag(Decimal(3)))
1545 self.assertEqual(Decimal(10101).logical_and(1001),
1546 Decimal(10101).logical_and(Decimal(1001)))
1547 self.assertEqual(Decimal(10101).logical_or(1001),
1548 Decimal(10101).logical_or(Decimal(1001)))
1549 self.assertEqual(Decimal(10101).logical_xor(1001),
1550 Decimal(10101).logical_xor(Decimal(1001)))
1551 self.assertEqual(Decimal(567).max(123),
1552 Decimal(567).max(Decimal(123)))
1553 self.assertEqual(Decimal(567).max_mag(123),
1554 Decimal(567).max_mag(Decimal(123)))
1555 self.assertEqual(Decimal(567).min(123),
1556 Decimal(567).min(Decimal(123)))
1557 self.assertEqual(Decimal(567).min_mag(123),
1558 Decimal(567).min_mag(Decimal(123)))
1559 self.assertEqual(Decimal(567).next_toward(123),
1560 Decimal(567).next_toward(Decimal(123)))
1561 self.assertEqual(Decimal(1234).quantize(100),
1562 Decimal(1234).quantize(Decimal(100)))
1563 self.assertEqual(Decimal(768).remainder_near(1234),
1564 Decimal(768).remainder_near(Decimal(1234)))
1565 self.assertEqual(Decimal(123).rotate(1),
1566 Decimal(123).rotate(Decimal(1)))
1567 self.assertEqual(Decimal(1234).same_quantum(1000),
1568 Decimal(1234).same_quantum(Decimal(1000)))
1569 self.assertEqual(Decimal('9.123').scaleb(-100),
1570 Decimal('9.123').scaleb(Decimal(-100)))
1571 self.assertEqual(Decimal(456).shift(-1),
1572 Decimal(456).shift(Decimal(-1)))
1573
1574 self.assertEqual(Decimal(-12).fma(Decimal(45), 67),
1575 Decimal(-12).fma(Decimal(45), Decimal(67)))
1576 self.assertEqual(Decimal(-12).fma(45, 67),
1577 Decimal(-12).fma(Decimal(45), Decimal(67)))
1578 self.assertEqual(Decimal(-12).fma(45, Decimal(67)),
1579 Decimal(-12).fma(Decimal(45), Decimal(67)))
1580
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001581
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001582class DecimalPythonAPItests(unittest.TestCase):
1583
Raymond Hettinger82417ca2009-02-03 03:54:28 +00001584 def test_abc(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001585 self.assertTrue(issubclass(Decimal, numbers.Number))
1586 self.assertTrue(not issubclass(Decimal, numbers.Real))
Ezio Melottie9615932010-01-24 19:26:24 +00001587 self.assertIsInstance(Decimal(0), numbers.Number)
1588 self.assertNotIsInstance(Decimal(0), numbers.Real)
Raymond Hettinger82417ca2009-02-03 03:54:28 +00001589
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001590 def test_pickle(self):
1591 d = Decimal('-3.141590000')
1592 p = pickle.dumps(d)
1593 e = pickle.loads(p)
1594 self.assertEqual(d, e)
1595
Raymond Hettinger5548be22004-07-05 18:49:38 +00001596 def test_int(self):
Raymond Hettinger605ed022004-11-24 07:28:48 +00001597 for x in range(-250, 250):
1598 s = '%0.2f' % (x / 100.0)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001599 # should work the same as for floats
1600 self.assertEqual(int(Decimal(s)), int(float(s)))
Raymond Hettinger605ed022004-11-24 07:28:48 +00001601 # should work the same as to_integral in the ROUND_DOWN mode
Raymond Hettinger5548be22004-07-05 18:49:38 +00001602 d = Decimal(s)
Raymond Hettinger605ed022004-11-24 07:28:48 +00001603 r = d.to_integral(ROUND_DOWN)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001604 self.assertEqual(Decimal(int(d)), r)
1605
Mark Dickinson825fce32009-09-07 18:08:12 +00001606 self.assertRaises(ValueError, int, Decimal('-nan'))
1607 self.assertRaises(ValueError, int, Decimal('snan'))
1608 self.assertRaises(OverflowError, int, Decimal('inf'))
1609 self.assertRaises(OverflowError, int, Decimal('-inf'))
1610
Christian Heimes969fe572008-01-25 11:23:10 +00001611 def test_trunc(self):
1612 for x in range(-250, 250):
1613 s = '%0.2f' % (x / 100.0)
1614 # should work the same as for floats
1615 self.assertEqual(int(Decimal(s)), int(float(s)))
1616 # should work the same as to_integral in the ROUND_DOWN mode
1617 d = Decimal(s)
1618 r = d.to_integral(ROUND_DOWN)
Christian Heimes400adb02008-02-01 08:12:03 +00001619 self.assertEqual(Decimal(math.trunc(d)), r)
Christian Heimes969fe572008-01-25 11:23:10 +00001620
Raymond Hettinger771ed762009-01-03 19:20:32 +00001621 def test_from_float(self):
1622
1623 class MyDecimal(Decimal):
1624 pass
1625
1626 r = MyDecimal.from_float(0.1)
1627 self.assertEqual(type(r), MyDecimal)
1628 self.assertEqual(str(r),
1629 '0.1000000000000000055511151231257827021181583404541015625')
1630 bigint = 12345678901234567890123456789
1631 self.assertEqual(MyDecimal.from_float(bigint), MyDecimal(bigint))
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001632 self.assertTrue(MyDecimal.from_float(float('nan')).is_qnan())
1633 self.assertTrue(MyDecimal.from_float(float('inf')).is_infinite())
1634 self.assertTrue(MyDecimal.from_float(float('-inf')).is_infinite())
Raymond Hettinger771ed762009-01-03 19:20:32 +00001635 self.assertEqual(str(MyDecimal.from_float(float('nan'))),
1636 str(Decimal('NaN')))
1637 self.assertEqual(str(MyDecimal.from_float(float('inf'))),
1638 str(Decimal('Infinity')))
1639 self.assertEqual(str(MyDecimal.from_float(float('-inf'))),
1640 str(Decimal('-Infinity')))
1641 self.assertRaises(TypeError, MyDecimal.from_float, 'abc')
1642 for i in range(200):
1643 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
1644 self.assertEqual(x, float(MyDecimal.from_float(x))) # roundtrip
1645
1646 def test_create_decimal_from_float(self):
1647 context = Context(prec=5, rounding=ROUND_DOWN)
1648 self.assertEqual(
1649 context.create_decimal_from_float(math.pi),
1650 Decimal('3.1415')
1651 )
1652 context = Context(prec=5, rounding=ROUND_UP)
1653 self.assertEqual(
1654 context.create_decimal_from_float(math.pi),
1655 Decimal('3.1416')
1656 )
1657 context = Context(prec=5, traps=[Inexact])
1658 self.assertRaises(
1659 Inexact,
1660 context.create_decimal_from_float,
1661 math.pi
1662 )
1663 self.assertEqual(repr(context.create_decimal_from_float(-0.0)),
1664 "Decimal('-0')")
1665 self.assertEqual(repr(context.create_decimal_from_float(1.0)),
1666 "Decimal('1')")
1667 self.assertEqual(repr(context.create_decimal_from_float(10)),
1668 "Decimal('10')")
1669
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00001670class ContextAPItests(unittest.TestCase):
1671
1672 def test_pickle(self):
1673 c = Context()
1674 e = pickle.loads(pickle.dumps(c))
1675 for k in vars(c):
1676 v1 = vars(c)[k]
1677 v2 = vars(e)[k]
1678 self.assertEqual(v1, v2)
1679
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001680 def test_equality_with_other_types(self):
Benjamin Peterson577473f2010-01-19 00:09:57 +00001681 self.assertIn(Decimal(10), ['a', 1.0, Decimal(10), (1,2), {}])
1682 self.assertNotIn(Decimal(10), ['a', 1.0, (1,2), {}])
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001683
Raymond Hettinger955d2b22004-08-08 20:17:45 +00001684 def test_copy(self):
1685 # All copies should be deep
1686 c = Context()
1687 d = c.copy()
1688 self.assertNotEqual(id(c), id(d))
1689 self.assertNotEqual(id(c.flags), id(d.flags))
1690 self.assertNotEqual(id(c.traps), id(d.traps))
1691
Mark Dickinson84230a12010-02-18 14:49:50 +00001692 def test_abs(self):
1693 c = Context()
1694 d = c.abs(Decimal(-1))
1695 self.assertEqual(c.abs(-1), d)
1696 self.assertRaises(TypeError, c.abs, '-1')
1697
1698 def test_add(self):
1699 c = Context()
1700 d = c.add(Decimal(1), Decimal(1))
1701 self.assertEqual(c.add(1, 1), d)
1702 self.assertEqual(c.add(Decimal(1), 1), d)
1703 self.assertEqual(c.add(1, Decimal(1)), d)
1704 self.assertRaises(TypeError, c.add, '1', 1)
1705 self.assertRaises(TypeError, c.add, 1, '1')
1706
1707 def test_compare(self):
1708 c = Context()
1709 d = c.compare(Decimal(1), Decimal(1))
1710 self.assertEqual(c.compare(1, 1), d)
1711 self.assertEqual(c.compare(Decimal(1), 1), d)
1712 self.assertEqual(c.compare(1, Decimal(1)), d)
1713 self.assertRaises(TypeError, c.compare, '1', 1)
1714 self.assertRaises(TypeError, c.compare, 1, '1')
1715
1716 def test_compare_signal(self):
1717 c = Context()
1718 d = c.compare_signal(Decimal(1), Decimal(1))
1719 self.assertEqual(c.compare_signal(1, 1), d)
1720 self.assertEqual(c.compare_signal(Decimal(1), 1), d)
1721 self.assertEqual(c.compare_signal(1, Decimal(1)), d)
1722 self.assertRaises(TypeError, c.compare_signal, '1', 1)
1723 self.assertRaises(TypeError, c.compare_signal, 1, '1')
1724
1725 def test_compare_total(self):
1726 c = Context()
1727 d = c.compare_total(Decimal(1), Decimal(1))
1728 self.assertEqual(c.compare_total(1, 1), d)
1729 self.assertEqual(c.compare_total(Decimal(1), 1), d)
1730 self.assertEqual(c.compare_total(1, Decimal(1)), d)
1731 self.assertRaises(TypeError, c.compare_total, '1', 1)
1732 self.assertRaises(TypeError, c.compare_total, 1, '1')
1733
1734 def test_compare_total_mag(self):
1735 c = Context()
1736 d = c.compare_total_mag(Decimal(1), Decimal(1))
1737 self.assertEqual(c.compare_total_mag(1, 1), d)
1738 self.assertEqual(c.compare_total_mag(Decimal(1), 1), d)
1739 self.assertEqual(c.compare_total_mag(1, Decimal(1)), d)
1740 self.assertRaises(TypeError, c.compare_total_mag, '1', 1)
1741 self.assertRaises(TypeError, c.compare_total_mag, 1, '1')
1742
1743 def test_copy_abs(self):
1744 c = Context()
1745 d = c.copy_abs(Decimal(-1))
1746 self.assertEqual(c.copy_abs(-1), d)
1747 self.assertRaises(TypeError, c.copy_abs, '-1')
1748
1749 def test_copy_decimal(self):
1750 c = Context()
1751 d = c.copy_decimal(Decimal(-1))
1752 self.assertEqual(c.copy_decimal(-1), d)
1753 self.assertRaises(TypeError, c.copy_decimal, '-1')
1754
1755 def test_copy_negate(self):
1756 c = Context()
1757 d = c.copy_negate(Decimal(-1))
1758 self.assertEqual(c.copy_negate(-1), d)
1759 self.assertRaises(TypeError, c.copy_negate, '-1')
1760
1761 def test_copy_sign(self):
1762 c = Context()
1763 d = c.copy_sign(Decimal(1), Decimal(-2))
1764 self.assertEqual(c.copy_sign(1, -2), d)
1765 self.assertEqual(c.copy_sign(Decimal(1), -2), d)
1766 self.assertEqual(c.copy_sign(1, Decimal(-2)), d)
1767 self.assertRaises(TypeError, c.copy_sign, '1', -2)
1768 self.assertRaises(TypeError, c.copy_sign, 1, '-2')
1769
1770 def test_divide(self):
1771 c = Context()
1772 d = c.divide(Decimal(1), Decimal(2))
1773 self.assertEqual(c.divide(1, 2), d)
1774 self.assertEqual(c.divide(Decimal(1), 2), d)
1775 self.assertEqual(c.divide(1, Decimal(2)), d)
1776 self.assertRaises(TypeError, c.divide, '1', 2)
1777 self.assertRaises(TypeError, c.divide, 1, '2')
1778
1779 def test_divide_int(self):
1780 c = Context()
1781 d = c.divide_int(Decimal(1), Decimal(2))
1782 self.assertEqual(c.divide_int(1, 2), d)
1783 self.assertEqual(c.divide_int(Decimal(1), 2), d)
1784 self.assertEqual(c.divide_int(1, Decimal(2)), d)
1785 self.assertRaises(TypeError, c.divide_int, '1', 2)
1786 self.assertRaises(TypeError, c.divide_int, 1, '2')
1787
1788 def test_divmod(self):
1789 c = Context()
1790 d = c.divmod(Decimal(1), Decimal(2))
1791 self.assertEqual(c.divmod(1, 2), d)
1792 self.assertEqual(c.divmod(Decimal(1), 2), d)
1793 self.assertEqual(c.divmod(1, Decimal(2)), d)
1794 self.assertRaises(TypeError, c.divmod, '1', 2)
1795 self.assertRaises(TypeError, c.divmod, 1, '2')
1796
1797 def test_exp(self):
1798 c = Context()
1799 d = c.exp(Decimal(10))
1800 self.assertEqual(c.exp(10), d)
1801 self.assertRaises(TypeError, c.exp, '10')
1802
1803 def test_fma(self):
1804 c = Context()
1805 d = c.fma(Decimal(2), Decimal(3), Decimal(4))
1806 self.assertEqual(c.fma(2, 3, 4), d)
1807 self.assertEqual(c.fma(Decimal(2), 3, 4), d)
1808 self.assertEqual(c.fma(2, Decimal(3), 4), d)
1809 self.assertEqual(c.fma(2, 3, Decimal(4)), d)
1810 self.assertEqual(c.fma(Decimal(2), Decimal(3), 4), d)
1811 self.assertRaises(TypeError, c.fma, '2', 3, 4)
1812 self.assertRaises(TypeError, c.fma, 2, '3', 4)
1813 self.assertRaises(TypeError, c.fma, 2, 3, '4')
1814
1815 def test_is_finite(self):
1816 c = Context()
1817 d = c.is_finite(Decimal(10))
1818 self.assertEqual(c.is_finite(10), d)
1819 self.assertRaises(TypeError, c.is_finite, '10')
1820
1821 def test_is_infinite(self):
1822 c = Context()
1823 d = c.is_infinite(Decimal(10))
1824 self.assertEqual(c.is_infinite(10), d)
1825 self.assertRaises(TypeError, c.is_infinite, '10')
1826
1827 def test_is_nan(self):
1828 c = Context()
1829 d = c.is_nan(Decimal(10))
1830 self.assertEqual(c.is_nan(10), d)
1831 self.assertRaises(TypeError, c.is_nan, '10')
1832
1833 def test_is_normal(self):
1834 c = Context()
1835 d = c.is_normal(Decimal(10))
1836 self.assertEqual(c.is_normal(10), d)
1837 self.assertRaises(TypeError, c.is_normal, '10')
1838
1839 def test_is_qnan(self):
1840 c = Context()
1841 d = c.is_qnan(Decimal(10))
1842 self.assertEqual(c.is_qnan(10), d)
1843 self.assertRaises(TypeError, c.is_qnan, '10')
1844
1845 def test_is_signed(self):
1846 c = Context()
1847 d = c.is_signed(Decimal(10))
1848 self.assertEqual(c.is_signed(10), d)
1849 self.assertRaises(TypeError, c.is_signed, '10')
1850
1851 def test_is_snan(self):
1852 c = Context()
1853 d = c.is_snan(Decimal(10))
1854 self.assertEqual(c.is_snan(10), d)
1855 self.assertRaises(TypeError, c.is_snan, '10')
1856
1857 def test_is_subnormal(self):
1858 c = Context()
1859 d = c.is_subnormal(Decimal(10))
1860 self.assertEqual(c.is_subnormal(10), d)
1861 self.assertRaises(TypeError, c.is_subnormal, '10')
1862
1863 def test_is_zero(self):
1864 c = Context()
1865 d = c.is_zero(Decimal(10))
1866 self.assertEqual(c.is_zero(10), d)
1867 self.assertRaises(TypeError, c.is_zero, '10')
1868
1869 def test_ln(self):
1870 c = Context()
1871 d = c.ln(Decimal(10))
1872 self.assertEqual(c.ln(10), d)
1873 self.assertRaises(TypeError, c.ln, '10')
1874
1875 def test_log10(self):
1876 c = Context()
1877 d = c.log10(Decimal(10))
1878 self.assertEqual(c.log10(10), d)
1879 self.assertRaises(TypeError, c.log10, '10')
1880
1881 def test_logb(self):
1882 c = Context()
1883 d = c.logb(Decimal(10))
1884 self.assertEqual(c.logb(10), d)
1885 self.assertRaises(TypeError, c.logb, '10')
1886
1887 def test_logical_and(self):
1888 c = Context()
1889 d = c.logical_and(Decimal(1), Decimal(1))
1890 self.assertEqual(c.logical_and(1, 1), d)
1891 self.assertEqual(c.logical_and(Decimal(1), 1), d)
1892 self.assertEqual(c.logical_and(1, Decimal(1)), d)
1893 self.assertRaises(TypeError, c.logical_and, '1', 1)
1894 self.assertRaises(TypeError, c.logical_and, 1, '1')
1895
1896 def test_logical_invert(self):
1897 c = Context()
1898 d = c.logical_invert(Decimal(1000))
1899 self.assertEqual(c.logical_invert(1000), d)
1900 self.assertRaises(TypeError, c.logical_invert, '1000')
1901
1902 def test_logical_or(self):
1903 c = Context()
1904 d = c.logical_or(Decimal(1), Decimal(1))
1905 self.assertEqual(c.logical_or(1, 1), d)
1906 self.assertEqual(c.logical_or(Decimal(1), 1), d)
1907 self.assertEqual(c.logical_or(1, Decimal(1)), d)
1908 self.assertRaises(TypeError, c.logical_or, '1', 1)
1909 self.assertRaises(TypeError, c.logical_or, 1, '1')
1910
1911 def test_logical_xor(self):
1912 c = Context()
1913 d = c.logical_xor(Decimal(1), Decimal(1))
1914 self.assertEqual(c.logical_xor(1, 1), d)
1915 self.assertEqual(c.logical_xor(Decimal(1), 1), d)
1916 self.assertEqual(c.logical_xor(1, Decimal(1)), d)
1917 self.assertRaises(TypeError, c.logical_xor, '1', 1)
1918 self.assertRaises(TypeError, c.logical_xor, 1, '1')
1919
1920 def test_max(self):
1921 c = Context()
1922 d = c.max(Decimal(1), Decimal(2))
1923 self.assertEqual(c.max(1, 2), d)
1924 self.assertEqual(c.max(Decimal(1), 2), d)
1925 self.assertEqual(c.max(1, Decimal(2)), d)
1926 self.assertRaises(TypeError, c.max, '1', 2)
1927 self.assertRaises(TypeError, c.max, 1, '2')
1928
1929 def test_max_mag(self):
1930 c = Context()
1931 d = c.max_mag(Decimal(1), Decimal(2))
1932 self.assertEqual(c.max_mag(1, 2), d)
1933 self.assertEqual(c.max_mag(Decimal(1), 2), d)
1934 self.assertEqual(c.max_mag(1, Decimal(2)), d)
1935 self.assertRaises(TypeError, c.max_mag, '1', 2)
1936 self.assertRaises(TypeError, c.max_mag, 1, '2')
1937
1938 def test_min(self):
1939 c = Context()
1940 d = c.min(Decimal(1), Decimal(2))
1941 self.assertEqual(c.min(1, 2), d)
1942 self.assertEqual(c.min(Decimal(1), 2), d)
1943 self.assertEqual(c.min(1, Decimal(2)), d)
1944 self.assertRaises(TypeError, c.min, '1', 2)
1945 self.assertRaises(TypeError, c.min, 1, '2')
1946
1947 def test_min_mag(self):
1948 c = Context()
1949 d = c.min_mag(Decimal(1), Decimal(2))
1950 self.assertEqual(c.min_mag(1, 2), d)
1951 self.assertEqual(c.min_mag(Decimal(1), 2), d)
1952 self.assertEqual(c.min_mag(1, Decimal(2)), d)
1953 self.assertRaises(TypeError, c.min_mag, '1', 2)
1954 self.assertRaises(TypeError, c.min_mag, 1, '2')
1955
1956 def test_minus(self):
1957 c = Context()
1958 d = c.minus(Decimal(10))
1959 self.assertEqual(c.minus(10), d)
1960 self.assertRaises(TypeError, c.minus, '10')
1961
1962 def test_multiply(self):
1963 c = Context()
1964 d = c.multiply(Decimal(1), Decimal(2))
1965 self.assertEqual(c.multiply(1, 2), d)
1966 self.assertEqual(c.multiply(Decimal(1), 2), d)
1967 self.assertEqual(c.multiply(1, Decimal(2)), d)
1968 self.assertRaises(TypeError, c.multiply, '1', 2)
1969 self.assertRaises(TypeError, c.multiply, 1, '2')
1970
1971 def test_next_minus(self):
1972 c = Context()
1973 d = c.next_minus(Decimal(10))
1974 self.assertEqual(c.next_minus(10), d)
1975 self.assertRaises(TypeError, c.next_minus, '10')
1976
1977 def test_next_plus(self):
1978 c = Context()
1979 d = c.next_plus(Decimal(10))
1980 self.assertEqual(c.next_plus(10), d)
1981 self.assertRaises(TypeError, c.next_plus, '10')
1982
1983 def test_next_toward(self):
1984 c = Context()
1985 d = c.next_toward(Decimal(1), Decimal(2))
1986 self.assertEqual(c.next_toward(1, 2), d)
1987 self.assertEqual(c.next_toward(Decimal(1), 2), d)
1988 self.assertEqual(c.next_toward(1, Decimal(2)), d)
1989 self.assertRaises(TypeError, c.next_toward, '1', 2)
1990 self.assertRaises(TypeError, c.next_toward, 1, '2')
1991
1992 def test_normalize(self):
1993 c = Context()
1994 d = c.normalize(Decimal(10))
1995 self.assertEqual(c.normalize(10), d)
1996 self.assertRaises(TypeError, c.normalize, '10')
1997
1998 def test_number_class(self):
1999 c = Context()
2000 self.assertEqual(c.number_class(123), c.number_class(Decimal(123)))
2001 self.assertEqual(c.number_class(0), c.number_class(Decimal(0)))
2002 self.assertEqual(c.number_class(-45), c.number_class(Decimal(-45)))
2003
2004 def test_power(self):
2005 c = Context()
2006 d = c.power(Decimal(1), Decimal(4), Decimal(2))
2007 self.assertEqual(c.power(1, 4, 2), d)
2008 self.assertEqual(c.power(Decimal(1), 4, 2), d)
2009 self.assertEqual(c.power(1, Decimal(4), 2), d)
2010 self.assertEqual(c.power(1, 4, Decimal(2)), d)
2011 self.assertEqual(c.power(Decimal(1), Decimal(4), 2), d)
2012 self.assertRaises(TypeError, c.power, '1', 4, 2)
2013 self.assertRaises(TypeError, c.power, 1, '4', 2)
2014 self.assertRaises(TypeError, c.power, 1, 4, '2')
2015
2016 def test_plus(self):
2017 c = Context()
2018 d = c.plus(Decimal(10))
2019 self.assertEqual(c.plus(10), d)
2020 self.assertRaises(TypeError, c.plus, '10')
2021
2022 def test_quantize(self):
2023 c = Context()
2024 d = c.quantize(Decimal(1), Decimal(2))
2025 self.assertEqual(c.quantize(1, 2), d)
2026 self.assertEqual(c.quantize(Decimal(1), 2), d)
2027 self.assertEqual(c.quantize(1, Decimal(2)), d)
2028 self.assertRaises(TypeError, c.quantize, '1', 2)
2029 self.assertRaises(TypeError, c.quantize, 1, '2')
2030
2031 def test_remainder(self):
2032 c = Context()
2033 d = c.remainder(Decimal(1), Decimal(2))
2034 self.assertEqual(c.remainder(1, 2), d)
2035 self.assertEqual(c.remainder(Decimal(1), 2), d)
2036 self.assertEqual(c.remainder(1, Decimal(2)), d)
2037 self.assertRaises(TypeError, c.remainder, '1', 2)
2038 self.assertRaises(TypeError, c.remainder, 1, '2')
2039
2040 def test_remainder_near(self):
2041 c = Context()
2042 d = c.remainder_near(Decimal(1), Decimal(2))
2043 self.assertEqual(c.remainder_near(1, 2), d)
2044 self.assertEqual(c.remainder_near(Decimal(1), 2), d)
2045 self.assertEqual(c.remainder_near(1, Decimal(2)), d)
2046 self.assertRaises(TypeError, c.remainder_near, '1', 2)
2047 self.assertRaises(TypeError, c.remainder_near, 1, '2')
2048
2049 def test_rotate(self):
2050 c = Context()
2051 d = c.rotate(Decimal(1), Decimal(2))
2052 self.assertEqual(c.rotate(1, 2), d)
2053 self.assertEqual(c.rotate(Decimal(1), 2), d)
2054 self.assertEqual(c.rotate(1, Decimal(2)), d)
2055 self.assertRaises(TypeError, c.rotate, '1', 2)
2056 self.assertRaises(TypeError, c.rotate, 1, '2')
2057
2058 def test_sqrt(self):
2059 c = Context()
2060 d = c.sqrt(Decimal(10))
2061 self.assertEqual(c.sqrt(10), d)
2062 self.assertRaises(TypeError, c.sqrt, '10')
2063
2064 def test_same_quantum(self):
2065 c = Context()
2066 d = c.same_quantum(Decimal(1), Decimal(2))
2067 self.assertEqual(c.same_quantum(1, 2), d)
2068 self.assertEqual(c.same_quantum(Decimal(1), 2), d)
2069 self.assertEqual(c.same_quantum(1, Decimal(2)), d)
2070 self.assertRaises(TypeError, c.same_quantum, '1', 2)
2071 self.assertRaises(TypeError, c.same_quantum, 1, '2')
2072
2073 def test_scaleb(self):
2074 c = Context()
2075 d = c.scaleb(Decimal(1), Decimal(2))
2076 self.assertEqual(c.scaleb(1, 2), d)
2077 self.assertEqual(c.scaleb(Decimal(1), 2), d)
2078 self.assertEqual(c.scaleb(1, Decimal(2)), d)
2079 self.assertRaises(TypeError, c.scaleb, '1', 2)
2080 self.assertRaises(TypeError, c.scaleb, 1, '2')
2081
2082 def test_shift(self):
2083 c = Context()
2084 d = c.shift(Decimal(1), Decimal(2))
2085 self.assertEqual(c.shift(1, 2), d)
2086 self.assertEqual(c.shift(Decimal(1), 2), d)
2087 self.assertEqual(c.shift(1, Decimal(2)), d)
2088 self.assertRaises(TypeError, c.shift, '1', 2)
2089 self.assertRaises(TypeError, c.shift, 1, '2')
2090
2091 def test_subtract(self):
2092 c = Context()
2093 d = c.subtract(Decimal(1), Decimal(2))
2094 self.assertEqual(c.subtract(1, 2), d)
2095 self.assertEqual(c.subtract(Decimal(1), 2), d)
2096 self.assertEqual(c.subtract(1, Decimal(2)), d)
2097 self.assertRaises(TypeError, c.subtract, '1', 2)
2098 self.assertRaises(TypeError, c.subtract, 1, '2')
2099
2100 def test_to_eng_string(self):
2101 c = Context()
2102 d = c.to_eng_string(Decimal(10))
2103 self.assertEqual(c.to_eng_string(10), d)
2104 self.assertRaises(TypeError, c.to_eng_string, '10')
2105
2106 def test_to_sci_string(self):
2107 c = Context()
2108 d = c.to_sci_string(Decimal(10))
2109 self.assertEqual(c.to_sci_string(10), d)
2110 self.assertRaises(TypeError, c.to_sci_string, '10')
2111
2112 def test_to_integral_exact(self):
2113 c = Context()
2114 d = c.to_integral_exact(Decimal(10))
2115 self.assertEqual(c.to_integral_exact(10), d)
2116 self.assertRaises(TypeError, c.to_integral_exact, '10')
2117
2118 def test_to_integral_value(self):
2119 c = Context()
2120 d = c.to_integral_value(Decimal(10))
2121 self.assertEqual(c.to_integral_value(10), d)
2122 self.assertRaises(TypeError, c.to_integral_value, '10')
2123
Thomas Wouters89f507f2006-12-13 04:49:30 +00002124class WithStatementTest(unittest.TestCase):
2125 # Can't do these as docstrings until Python 2.6
2126 # as doctest can't handle __future__ statements
2127
2128 def test_localcontext(self):
2129 # Use a copy of the current context in the block
2130 orig_ctx = getcontext()
2131 with localcontext() as enter_ctx:
2132 set_ctx = getcontext()
2133 final_ctx = getcontext()
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00002134 self.assertTrue(orig_ctx is final_ctx, 'did not restore context correctly')
2135 self.assertTrue(orig_ctx is not set_ctx, 'did not copy the context')
2136 self.assertTrue(set_ctx is enter_ctx, '__enter__ returned wrong context')
Thomas Wouters89f507f2006-12-13 04:49:30 +00002137
2138 def test_localcontextarg(self):
2139 # Use a copy of the supplied context in the block
2140 orig_ctx = getcontext()
2141 new_ctx = Context(prec=42)
2142 with localcontext(new_ctx) as enter_ctx:
2143 set_ctx = getcontext()
2144 final_ctx = getcontext()
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00002145 self.assertTrue(orig_ctx is final_ctx, 'did not restore context correctly')
2146 self.assertTrue(set_ctx.prec == new_ctx.prec, 'did not set correct context')
2147 self.assertTrue(new_ctx is not set_ctx, 'did not copy the context')
2148 self.assertTrue(set_ctx is enter_ctx, '__enter__ returned wrong context')
Thomas Wouters89f507f2006-12-13 04:49:30 +00002149
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002150class ContextFlags(unittest.TestCase):
2151 def test_flags_irrelevant(self):
2152 # check that the result (numeric result + flags raised) of an
2153 # arithmetic operation doesn't depend on the current flags
2154
2155 context = Context(prec=9, Emin = -999999999, Emax = 999999999,
2156 rounding=ROUND_HALF_EVEN, traps=[], flags=[])
2157
2158 # operations that raise various flags, in the form (function, arglist)
2159 operations = [
2160 (context._apply, [Decimal("100E-1000000009")]),
2161 (context.sqrt, [Decimal(2)]),
2162 (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]),
2163 (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]),
2164 (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]),
2165 ]
2166
2167 # try various flags individually, then a whole lot at once
2168 flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal],
2169 [Inexact, Rounded, Underflow, Clamped, Subnormal]]
2170
2171 for fn, args in operations:
2172 # find answer and flags raised using a clean context
2173 context.clear_flags()
2174 ans = fn(*args)
2175 flags = [k for k, v in context.flags.items() if v]
2176
2177 for extra_flags in flagsets:
2178 # set flags, before calling operation
2179 context.clear_flags()
2180 for flag in extra_flags:
2181 context._raise_error(flag)
2182 new_ans = fn(*args)
2183
2184 # flags that we expect to be set after the operation
2185 expected_flags = list(flags)
2186 for flag in extra_flags:
2187 if flag not in expected_flags:
2188 expected_flags.append(flag)
2189 expected_flags.sort(key=id)
2190
2191 # flags we actually got
2192 new_flags = [k for k,v in context.flags.items() if v]
2193 new_flags.sort(key=id)
2194
2195 self.assertEqual(ans, new_ans,
2196 "operation produces different answers depending on flags set: " +
2197 "expected %s, got %s." % (ans, new_ans))
2198 self.assertEqual(new_flags, expected_flags,
2199 "operation raises different flags depending on flags set: " +
2200 "expected %s, got %s" % (expected_flags, new_flags))
2201
2202def test_main(arith=False, verbose=None, todo_tests=None, debug=None):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002203 """ Execute the tests.
2204
Raymond Hettingered20ad82004-09-04 20:09:13 +00002205 Runs all arithmetic tests if arith is True or if the "decimal" resource
2206 is enabled in regrtest.py
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002207 """
Raymond Hettingered20ad82004-09-04 20:09:13 +00002208
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002209 init()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002210 global TEST_ALL, DEBUG
Raymond Hettingered20ad82004-09-04 20:09:13 +00002211 TEST_ALL = arith or is_resource_enabled('decimal')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002212 DEBUG = debug
Raymond Hettingered20ad82004-09-04 20:09:13 +00002213
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002214 if todo_tests is None:
2215 test_classes = [
2216 DecimalExplicitConstructionTest,
2217 DecimalImplicitConstructionTest,
2218 DecimalArithmeticOperatorsTest,
Christian Heimesf16baeb2008-02-29 14:57:44 +00002219 DecimalFormatTest,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002220 DecimalUseOfContextTest,
2221 DecimalUsabilityTest,
2222 DecimalPythonAPItests,
2223 ContextAPItests,
2224 DecimalTest,
2225 WithStatementTest,
2226 ContextFlags
2227 ]
2228 else:
2229 test_classes = [DecimalTest]
2230
2231 # Dynamically build custom test definition for each file in the test
2232 # directory and add the definitions to the DecimalTest class. This
2233 # procedure insures that new files do not get skipped.
2234 for filename in os.listdir(directory):
2235 if '.decTest' not in filename or filename.startswith("."):
2236 continue
2237 head, tail = filename.split('.')
2238 if todo_tests is not None and head not in todo_tests:
2239 continue
2240 tester = lambda self, f=filename: self.eval_file(directory + f)
2241 setattr(DecimalTest, 'test_' + head, tester)
2242 del filename, head, tail, tester
2243
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002244
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002245 try:
2246 run_unittest(*test_classes)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002247 if todo_tests is None:
2248 import decimal as DecimalModule
2249 run_doctest(DecimalModule, verbose)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002250 finally:
2251 setcontext(ORIGINAL_CONTEXT)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002252
2253if __name__ == '__main__':
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002254 import optparse
2255 p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]")
2256 p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test')
2257 p.add_option('--skip', '-s', action='store_true', help='skip over 90% of the arithmetic tests')
2258 (opt, args) = p.parse_args()
2259
2260 if opt.skip:
2261 test_main(arith=False, verbose=True)
2262 elif args:
2263 test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002264 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002265 test_main(arith=True, verbose=True)