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