blob: 21590880b08dd2a547b06e1489b67754da8faddc [file] [log] [blame]
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001# Copyright (c) 2004 Python Software Foundation.
2# All rights reserved.
3
4# Written by Eric Price <eprice at tjhsst.edu>
5# and Facundo Batista <facundo at taniquetil.com.ar>
6# and Raymond Hettinger <python at rcn.com>
7# and Aahz (aahz at pobox.com)
8# and Tim Peters
9
10"""
11These are the test cases for the Decimal module.
12
13There are two groups of tests, Arithmetic and Behaviour. The former test
14the Decimal arithmetic using the tests provided by Mike Cowlishaw. The latter
15test the pythonic behaviour according to PEP 327.
16
17Cowlishaw's tests can be downloaded from:
18
19 www2.hursley.ibm.com/decimal/dectest.zip
20
21This test module can be called from command line with one parameter (Arithmetic
22or Behaviour) to test each part, or without parameter to test both parts. If
23you're working through IDLE, you can import this test module and call test_main()
24with the corresponding argument.
25"""
26
Christian Heimes400adb02008-02-01 08:12:03 +000027import math
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000028import os, sys
Mark Dickinsonac256ab2010-04-03 11:08:14 +000029import operator
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000030import pickle, copy
Christian Heimes400adb02008-02-01 08:12:03 +000031import unittest
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000032from decimal import *
Raymond Hettinger82417ca2009-02-03 03:54:28 +000033import numbers
Benjamin Petersone549ead2009-03-28 21:42:05 +000034from test.support import run_unittest, run_doctest, is_resource_enabled
Raymond Hettinger0aeac102004-07-05 22:53:03 +000035import random
Raymond Hettinger7e71fa52004-12-18 19:07:19 +000036try:
37 import threading
38except ImportError:
39 threading = None
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000040
Raymond Hettingerfed52962004-07-14 15:41:57 +000041# Useful Test Constant
Guido van Rossumc1f779c2007-07-03 08:25:58 +000042Signals = tuple(getcontext().flags.keys())
Raymond Hettingerfed52962004-07-14 15:41:57 +000043
Mark Dickinsonc69160e2010-05-04 14:35:33 +000044# Signals ordered with respect to precedence: when an operation
45# produces multiple signals, signals occurring later in the list
46# should be handled before those occurring earlier in the list.
47OrderedSignals = (Clamped, Rounded, Inexact, Subnormal,
48 Underflow, Overflow, DivisionByZero, InvalidOperation)
49
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000050# Tests are built around these assumed context defaults.
51# test_main() restores the original context.
52def init():
53 global ORIGINAL_CONTEXT
54 ORIGINAL_CONTEXT = getcontext().copy()
Christian Heimes81ee3ef2008-05-04 22:42:01 +000055 DefaultTestContext = Context(
56 prec = 9,
57 rounding = ROUND_HALF_EVEN,
58 traps = dict.fromkeys(Signals, 0)
59 )
60 setcontext(DefaultTestContext)
Raymond Hettinger6ea48452004-07-03 12:26:21 +000061
Raymond Hettinger96798592010-04-02 16:58:27 +000062# decorator for skipping tests on non-IEEE 754 platforms
63requires_IEEE_754 = unittest.skipUnless(
64 float.__getformat__("double").startswith("IEEE"),
65 "test requires IEEE 754 doubles")
66
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000067TESTDATADIR = 'decimaltestdata'
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +000068if __name__ == '__main__':
69 file = sys.argv[0]
70else:
71 file = __file__
72testdir = os.path.dirname(file) or os.curdir
Raymond Hettinger267b8682005-03-27 10:47:39 +000073directory = testdir + os.sep + TESTDATADIR + os.sep
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000074
Raymond Hettinger267b8682005-03-27 10:47:39 +000075skip_expected = not os.path.isdir(directory)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000076
Mark Dickinson8a546532009-10-08 16:30:38 +000077# list of individual .decTest test ids that correspond to tests that
78# we're skipping for one reason or another.
79skipped_test_ids = [
80 'scbx164', # skipping apparently implementation-specific scaleb
81 'scbx165', # tests, pending clarification of scaleb rules.
82]
83
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000084# Make sure it actually raises errors when not expected and caught in flags
85# Slower, since it runs some things several times.
86EXTENDEDERRORTEST = False
87
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000088#Map the test cases' error names to the actual errors
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000089ErrorNames = {'clamped' : Clamped,
Raymond Hettinger5aa478b2004-07-09 10:02:53 +000090 'conversion_syntax' : InvalidOperation,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000091 'division_by_zero' : DivisionByZero,
Raymond Hettinger5aa478b2004-07-09 10:02:53 +000092 'division_impossible' : InvalidOperation,
93 'division_undefined' : InvalidOperation,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000094 'inexact' : Inexact,
Raymond Hettinger5aa478b2004-07-09 10:02:53 +000095 'invalid_context' : InvalidOperation,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000096 'invalid_operation' : InvalidOperation,
97 'overflow' : Overflow,
98 'rounded' : Rounded,
99 'subnormal' : Subnormal,
100 'underflow' : Underflow}
101
102
103def Nonfunction(*args):
104 """Doesn't do anything."""
105 return None
106
107RoundingDict = {'ceiling' : ROUND_CEILING, #Maps test-case names to roundings.
108 'down' : ROUND_DOWN,
109 'floor' : ROUND_FLOOR,
110 'half_down' : ROUND_HALF_DOWN,
111 'half_even' : ROUND_HALF_EVEN,
112 'half_up' : ROUND_HALF_UP,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000113 'up' : ROUND_UP,
114 '05up' : ROUND_05UP}
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000115
116# Name adapter to be able to change the Decimal and Context
117# interface without changing the test files from Cowlishaw
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000118nameAdapter = {'and':'logical_and',
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000119 'apply':'_apply',
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000120 'class':'number_class',
121 'comparesig':'compare_signal',
122 'comparetotal':'compare_total',
123 'comparetotmag':'compare_total_mag',
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000124 'copy':'copy_decimal',
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000125 'copyabs':'copy_abs',
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000126 'copynegate':'copy_negate',
127 'copysign':'copy_sign',
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000128 'divideint':'divide_int',
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000129 'invert':'logical_invert',
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000130 'iscanonical':'is_canonical',
131 'isfinite':'is_finite',
132 'isinfinite':'is_infinite',
133 'isnan':'is_nan',
134 'isnormal':'is_normal',
135 'isqnan':'is_qnan',
136 'issigned':'is_signed',
137 'issnan':'is_snan',
138 'issubnormal':'is_subnormal',
139 'iszero':'is_zero',
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000140 'maxmag':'max_mag',
141 'minmag':'min_mag',
142 'nextminus':'next_minus',
143 'nextplus':'next_plus',
144 'nexttoward':'next_toward',
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000145 'or':'logical_or',
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000146 'reduce':'normalize',
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000147 'remaindernear':'remainder_near',
148 'samequantum':'same_quantum',
149 'squareroot':'sqrt',
150 'toeng':'to_eng_string',
151 'tointegral':'to_integral_value',
152 'tointegralx':'to_integral_exact',
153 'tosci':'to_sci_string',
154 'xor':'logical_xor',
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000155 }
156
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000157# The following functions return True/False rather than a Decimal instance
158
159LOGICAL_FUNCTIONS = (
160 'is_canonical',
161 'is_finite',
162 'is_infinite',
163 'is_nan',
164 'is_normal',
165 'is_qnan',
166 'is_signed',
167 'is_snan',
168 'is_subnormal',
169 'is_zero',
170 'same_quantum',
171 )
172
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000173# For some operations (currently exp, ln, log10, power), the decNumber
174# reference implementation imposes additional restrictions on the
175# context and operands. These restrictions are not part of the
176# specification; however, the effect of these restrictions does show
177# up in some of the testcases. We skip testcases that violate these
178# restrictions, since Decimal behaves differently from decNumber for
179# these testcases so these testcases would otherwise fail.
180
181decNumberRestricted = ('power', 'ln', 'log10', 'exp')
182DEC_MAX_MATH = 999999
183def outside_decNumber_bounds(v, context):
184 if (context.prec > DEC_MAX_MATH or
185 context.Emax > DEC_MAX_MATH or
186 -context.Emin > DEC_MAX_MATH):
187 return True
188 if not v._is_special and v and (
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000189 v.adjusted() > DEC_MAX_MATH or
190 v.adjusted() < 1-2*DEC_MAX_MATH):
191 return True
192 return False
193
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000194class DecimalTest(unittest.TestCase):
195 """Class which tests the Decimal class against the test cases.
196
197 Changed for unittest.
198 """
199 def setUp(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000200 self.context = Context()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000201 self.ignore_list = ['#']
202 # Basically, a # means return NaN InvalidOperation.
203 # Different from a sNaN in trim
204
205 self.ChangeDict = {'precision' : self.change_precision,
206 'rounding' : self.change_rounding_method,
207 'maxexponent' : self.change_max_exponent,
208 'minexponent' : self.change_min_exponent,
209 'clamp' : self.change_clamp}
210
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000211 def eval_file(self, file):
212 global skip_expected
213 if skip_expected:
Benjamin Petersone549ead2009-03-28 21:42:05 +0000214 raise unittest.SkipTest
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000215 return
Neal Norwitz70967602006-03-17 08:29:44 +0000216 for line in open(file):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000217 line = line.replace('\r\n', '').replace('\n', '')
Raymond Hettinger5aa478b2004-07-09 10:02:53 +0000218 #print line
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000219 try:
220 t = self.eval_line(line)
Guido van Rossumb940e112007-01-10 16:19:56 +0000221 except DecimalException as exception:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000222 #Exception raised where there shoudn't have been one.
223 self.fail('Exception "'+exception.__class__.__name__ + '" raised on line '+line)
224
225 return
226
227 def eval_line(self, s):
228 if s.find(' -> ') >= 0 and s[:2] != '--' and not s.startswith(' --'):
229 s = (s.split('->')[0] + '->' +
230 s.split('->')[1].split('--')[0]).strip()
231 else:
232 s = s.split('--')[0].strip()
233
234 for ignore in self.ignore_list:
235 if s.find(ignore) >= 0:
236 #print s.split()[0], 'NotImplemented--', ignore
237 return
238 if not s:
239 return
240 elif ':' in s:
241 return self.eval_directive(s)
242 else:
243 return self.eval_equation(s)
244
245 def eval_directive(self, s):
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000246 funct, value = (x.strip().lower() for x in s.split(':'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000247 if funct == 'rounding':
248 value = RoundingDict[value]
249 else:
250 try:
251 value = int(value)
252 except ValueError:
253 pass
254
255 funct = self.ChangeDict.get(funct, Nonfunction)
256 funct(value)
257
258 def eval_equation(self, s):
259 #global DEFAULT_PRECISION
260 #print DEFAULT_PRECISION
Raymond Hettingered20ad82004-09-04 20:09:13 +0000261
262 if not TEST_ALL and random.random() < 0.90:
263 return
264
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000265 try:
266 Sides = s.split('->')
267 L = Sides[0].strip().split()
268 id = L[0]
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000269 if DEBUG:
270 print("Test ", id, end=" ")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000271 funct = L[1].lower()
272 valstemp = L[2:]
273 L = Sides[1].strip().split()
274 ans = L[0]
275 exceptions = L[1:]
276 except (TypeError, AttributeError, IndexError):
Raymond Hettingerd87ac8f2004-07-09 10:52:54 +0000277 raise InvalidOperation
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000278 def FixQuotes(val):
279 val = val.replace("''", 'SingleQuote').replace('""', 'DoubleQuote')
280 val = val.replace("'", '').replace('"', '')
281 val = val.replace('SingleQuote', "'").replace('DoubleQuote', '"')
282 return val
Mark Dickinson8a546532009-10-08 16:30:38 +0000283
284 if id in skipped_test_ids:
285 return
286
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000287 fname = nameAdapter.get(funct, funct)
288 if fname == 'rescale':
289 return
290 funct = getattr(self.context, fname)
291 vals = []
292 conglomerate = ''
293 quote = 0
294 theirexceptions = [ErrorNames[x.lower()] for x in exceptions]
295
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000296 for exception in Signals:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000297 self.context.traps[exception] = 1 #Catch these bugs...
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000298 for exception in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000299 self.context.traps[exception] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000300 for i, val in enumerate(valstemp):
301 if val.count("'") % 2 == 1:
302 quote = 1 - quote
303 if quote:
304 conglomerate = conglomerate + ' ' + val
305 continue
306 else:
307 val = conglomerate + val
308 conglomerate = ''
309 v = FixQuotes(val)
310 if fname in ('to_sci_string', 'to_eng_string'):
311 if EXTENDEDERRORTEST:
312 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000313 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000314 try:
315 funct(self.context.create_decimal(v))
316 except error:
317 pass
Guido van Rossumb940e112007-01-10 16:19:56 +0000318 except Signals as e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000319 self.fail("Raised %s in %s when %s disabled" % \
320 (e, s, error))
321 else:
322 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000323 self.context.traps[error] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000324 v = self.context.create_decimal(v)
325 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000326 v = Decimal(v, self.context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000327 vals.append(v)
328
329 ans = FixQuotes(ans)
330
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000331 # skip tests that are related to bounds imposed in the decNumber
332 # reference implementation
333 if fname in decNumberRestricted:
334 if fname == 'power':
335 if not (vals[1]._isinteger() and
336 -1999999997 <= vals[1] <= 999999999):
337 if outside_decNumber_bounds(vals[0], self.context) or \
338 outside_decNumber_bounds(vals[1], self.context):
339 #print "Skipping test %s" % s
340 return
341 else:
342 if outside_decNumber_bounds(vals[0], self.context):
343 #print "Skipping test %s" % s
344 return
345
346
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000347 if EXTENDEDERRORTEST and fname not in ('to_sci_string', 'to_eng_string'):
348 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000349 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000350 try:
351 funct(*vals)
352 except error:
353 pass
Guido van Rossumb940e112007-01-10 16:19:56 +0000354 except Signals as e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000355 self.fail("Raised %s in %s when %s disabled" % \
356 (e, s, error))
357 else:
358 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000359 self.context.traps[error] = 0
Mark Dickinsonc69160e2010-05-04 14:35:33 +0000360
361 # as above, but add traps cumulatively, to check precedence
362 ordered_errors = [e for e in OrderedSignals if e in theirexceptions]
363 for error in ordered_errors:
364 self.context.traps[error] = 1
365 try:
366 funct(*vals)
367 except error:
368 pass
369 except Signals as e:
370 self.fail("Raised %s in %s; expected %s" %
371 (type(e), s, error))
372 else:
373 self.fail("Did not raise %s in %s" % (error, s))
374 # reset traps
375 for error in ordered_errors:
376 self.context.traps[error] = 0
377
378
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000379 if DEBUG:
380 print("--", self.context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000381 try:
382 result = str(funct(*vals))
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000383 if fname in LOGICAL_FUNCTIONS:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000384 result = str(int(eval(result))) # 'True', 'False' -> '1', '0'
Guido van Rossumb940e112007-01-10 16:19:56 +0000385 except Signals as error:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000386 self.fail("Raised %s in %s" % (error, s))
387 except: #Catch any error long enough to state the test case.
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000388 print("ERROR:", s)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000389 raise
390
391 myexceptions = self.getexceptions()
Raymond Hettingerbf440692004-07-10 14:14:37 +0000392 self.context.clear_flags()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000393
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000394 myexceptions.sort(key=repr)
395 theirexceptions.sort(key=repr)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000396
397 self.assertEqual(result, ans,
398 'Incorrect answer for ' + s + ' -- got ' + result)
399 self.assertEqual(myexceptions, theirexceptions,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000400 'Incorrect flags set in ' + s + ' -- got ' + str(myexceptions))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000401 return
402
403 def getexceptions(self):
Raymond Hettingerf63ba432004-08-17 05:42:09 +0000404 return [e for e in Signals if self.context.flags[e]]
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000405
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000406 def change_precision(self, prec):
407 self.context.prec = prec
408 def change_rounding_method(self, rounding):
409 self.context.rounding = rounding
410 def change_min_exponent(self, exp):
411 self.context.Emin = exp
412 def change_max_exponent(self, exp):
413 self.context.Emax = exp
414 def change_clamp(self, clamp):
415 self.context._clamp = clamp
416
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000417
418
419# The following classes test the behaviour of Decimal according to PEP 327
420
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000421class DecimalExplicitConstructionTest(unittest.TestCase):
422 '''Unit tests for Explicit Construction cases of Decimal.'''
423
424 def test_explicit_empty(self):
425 self.assertEqual(Decimal(), Decimal("0"))
426
427 def test_explicit_from_None(self):
428 self.assertRaises(TypeError, Decimal, None)
429
430 def test_explicit_from_int(self):
431
432 #positive
433 d = Decimal(45)
434 self.assertEqual(str(d), '45')
435
436 #very large positive
437 d = Decimal(500000123)
438 self.assertEqual(str(d), '500000123')
439
440 #negative
441 d = Decimal(-45)
442 self.assertEqual(str(d), '-45')
443
444 #zero
445 d = Decimal(0)
446 self.assertEqual(str(d), '0')
447
448 def test_explicit_from_string(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000449
450 #empty
451 self.assertEqual(str(Decimal('')), 'NaN')
452
453 #int
454 self.assertEqual(str(Decimal('45')), '45')
455
456 #float
457 self.assertEqual(str(Decimal('45.34')), '45.34')
458
459 #engineer notation
460 self.assertEqual(str(Decimal('45e2')), '4.5E+3')
461
462 #just not a number
463 self.assertEqual(str(Decimal('ugly')), 'NaN')
464
Christian Heimesa62da1d2008-01-12 19:39:10 +0000465 #leading and trailing whitespace permitted
466 self.assertEqual(str(Decimal('1.3E4 \n')), '1.3E+4')
467 self.assertEqual(str(Decimal(' -7.89')), '-7.89')
468
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000469 def test_explicit_from_tuples(self):
470
471 #zero
472 d = Decimal( (0, (0,), 0) )
473 self.assertEqual(str(d), '0')
474
475 #int
476 d = Decimal( (1, (4, 5), 0) )
477 self.assertEqual(str(d), '-45')
478
479 #float
480 d = Decimal( (0, (4, 5, 3, 4), -2) )
481 self.assertEqual(str(d), '45.34')
482
483 #weird
484 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
485 self.assertEqual(str(d), '-4.34913534E-17')
486
487 #wrong number of items
488 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1)) )
489
490 #bad sign
491 self.assertRaises(ValueError, Decimal, (8, (4, 3, 4, 9, 1), 2) )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000492 self.assertRaises(ValueError, Decimal, (0., (4, 3, 4, 9, 1), 2) )
493 self.assertRaises(ValueError, Decimal, (Decimal(1), (4, 3, 4, 9, 1), 2))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000494
495 #bad exp
496 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 'wrong!') )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000497 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 0.) )
498 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), '1') )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000499
500 #bad coefficients
501 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, None, 1), 2) )
502 self.assertRaises(ValueError, Decimal, (1, (4, -3, 4, 9, 1), 2) )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000503 self.assertRaises(ValueError, Decimal, (1, (4, 10, 4, 9, 1), 2) )
Guido van Rossum0d3fb8a2007-11-26 23:23:18 +0000504 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 'a', 1), 2) )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000505
Antoine Pitrou503ab332010-03-30 18:56:19 +0000506 def test_explicit_from_bool(self):
507 self.assertIs(bool(Decimal(0)), False)
508 self.assertIs(bool(Decimal(1)), True)
509 self.assertEqual(Decimal(False), Decimal(0))
510 self.assertEqual(Decimal(True), Decimal(1))
511
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000512 def test_explicit_from_Decimal(self):
513
514 #positive
515 d = Decimal(45)
516 e = Decimal(d)
517 self.assertEqual(str(e), '45')
518 self.assertNotEqual(id(d), id(e))
519
520 #very large positive
521 d = Decimal(500000123)
522 e = Decimal(d)
523 self.assertEqual(str(e), '500000123')
524 self.assertNotEqual(id(d), id(e))
525
526 #negative
527 d = Decimal(-45)
528 e = Decimal(d)
529 self.assertEqual(str(e), '-45')
530 self.assertNotEqual(id(d), id(e))
531
532 #zero
533 d = Decimal(0)
534 e = Decimal(d)
535 self.assertEqual(str(e), '0')
536 self.assertNotEqual(id(d), id(e))
537
Raymond Hettinger96798592010-04-02 16:58:27 +0000538 @requires_IEEE_754
539 def test_explicit_from_float(self):
540 r = Decimal(0.1)
541 self.assertEqual(type(r), Decimal)
542 self.assertEqual(str(r),
543 '0.1000000000000000055511151231257827021181583404541015625')
544 self.assertTrue(Decimal(float('nan')).is_qnan())
545 self.assertTrue(Decimal(float('inf')).is_infinite())
546 self.assertTrue(Decimal(float('-inf')).is_infinite())
547 self.assertEqual(str(Decimal(float('nan'))),
548 str(Decimal('NaN')))
549 self.assertEqual(str(Decimal(float('inf'))),
550 str(Decimal('Infinity')))
551 self.assertEqual(str(Decimal(float('-inf'))),
552 str(Decimal('-Infinity')))
553 self.assertEqual(str(Decimal(float('-0.0'))),
554 str(Decimal('-0')))
555 for i in range(200):
556 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
557 self.assertEqual(x, float(Decimal(x))) # roundtrip
558
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000559 def test_explicit_context_create_decimal(self):
560
561 nc = copy.copy(getcontext())
562 nc.prec = 3
563
564 # empty
Raymond Hettingerfed52962004-07-14 15:41:57 +0000565 d = Decimal()
566 self.assertEqual(str(d), '0')
567 d = nc.create_decimal()
568 self.assertEqual(str(d), '0')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000569
570 # from None
571 self.assertRaises(TypeError, nc.create_decimal, None)
572
573 # from int
574 d = nc.create_decimal(456)
Ezio Melottie9615932010-01-24 19:26:24 +0000575 self.assertIsInstance(d, Decimal)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000576 self.assertEqual(nc.create_decimal(45678),
577 nc.create_decimal('457E+2'))
578
579 # from string
580 d = Decimal('456789')
581 self.assertEqual(str(d), '456789')
582 d = nc.create_decimal('456789')
583 self.assertEqual(str(d), '4.57E+5')
Christian Heimesa62da1d2008-01-12 19:39:10 +0000584 # leading and trailing whitespace should result in a NaN;
585 # spaces are already checked in Cowlishaw's test-suite, so
586 # here we just check that a trailing newline results in a NaN
587 self.assertEqual(str(nc.create_decimal('3.14\n')), 'NaN')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000588
589 # from tuples
590 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
591 self.assertEqual(str(d), '-4.34913534E-17')
592 d = nc.create_decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
593 self.assertEqual(str(d), '-4.35E-17')
594
595 # from Decimal
596 prevdec = Decimal(500000123)
597 d = Decimal(prevdec)
598 self.assertEqual(str(d), '500000123')
599 d = nc.create_decimal(prevdec)
600 self.assertEqual(str(d), '5.00E+8')
601
Mark Dickinson345adc42009-08-02 10:14:23 +0000602 def test_unicode_digits(self):
603 test_values = {
604 '\uff11': '1',
605 '\u0660.\u0660\u0663\u0667\u0662e-\u0663' : '0.0000372',
606 '-nan\u0c68\u0c6a\u0c66\u0c66' : '-NaN2400',
607 }
608 for input, expected in test_values.items():
609 self.assertEqual(str(Decimal(input)), expected)
610
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000611
612class DecimalImplicitConstructionTest(unittest.TestCase):
613 '''Unit tests for Implicit Construction cases of Decimal.'''
614
615 def test_implicit_from_None(self):
616 self.assertRaises(TypeError, eval, 'Decimal(5) + None', globals())
617
618 def test_implicit_from_int(self):
619 #normal
620 self.assertEqual(str(Decimal(5) + 45), '50')
621 #exceeding precision
622 self.assertEqual(Decimal(5) + 123456789000, Decimal(123456789000))
623
624 def test_implicit_from_string(self):
625 self.assertRaises(TypeError, eval, 'Decimal(5) + "3"', globals())
626
627 def test_implicit_from_float(self):
628 self.assertRaises(TypeError, eval, 'Decimal(5) + 2.2', globals())
629
630 def test_implicit_from_Decimal(self):
631 self.assertEqual(Decimal(5) + Decimal(45), Decimal(50))
632
Raymond Hettinger267b8682005-03-27 10:47:39 +0000633 def test_rop(self):
634 # Allow other classes to be trained to interact with Decimals
635 class E:
636 def __divmod__(self, other):
637 return 'divmod ' + str(other)
638 def __rdivmod__(self, other):
639 return str(other) + ' rdivmod'
640 def __lt__(self, other):
641 return 'lt ' + str(other)
642 def __gt__(self, other):
643 return 'gt ' + str(other)
644 def __le__(self, other):
645 return 'le ' + str(other)
646 def __ge__(self, other):
647 return 'ge ' + str(other)
648 def __eq__(self, other):
649 return 'eq ' + str(other)
650 def __ne__(self, other):
651 return 'ne ' + str(other)
652
653 self.assertEqual(divmod(E(), Decimal(10)), 'divmod 10')
654 self.assertEqual(divmod(Decimal(10), E()), '10 rdivmod')
655 self.assertEqual(eval('Decimal(10) < E()'), 'gt 10')
656 self.assertEqual(eval('Decimal(10) > E()'), 'lt 10')
657 self.assertEqual(eval('Decimal(10) <= E()'), 'ge 10')
658 self.assertEqual(eval('Decimal(10) >= E()'), 'le 10')
659 self.assertEqual(eval('Decimal(10) == E()'), 'eq 10')
660 self.assertEqual(eval('Decimal(10) != E()'), 'ne 10')
661
662 # insert operator methods and then exercise them
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000663 oplist = [
664 ('+', '__add__', '__radd__'),
665 ('-', '__sub__', '__rsub__'),
666 ('*', '__mul__', '__rmul__'),
Thomas Woutersdcc6d322006-04-21 11:30:52 +0000667 ('/', '__truediv__', '__rtruediv__'),
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000668 ('%', '__mod__', '__rmod__'),
669 ('//', '__floordiv__', '__rfloordiv__'),
670 ('**', '__pow__', '__rpow__')
671 ]
Raymond Hettinger267b8682005-03-27 10:47:39 +0000672
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000673 for sym, lop, rop in oplist:
Raymond Hettinger267b8682005-03-27 10:47:39 +0000674 setattr(E, lop, lambda self, other: 'str' + lop + str(other))
675 setattr(E, rop, lambda self, other: str(other) + rop + 'str')
676 self.assertEqual(eval('E()' + sym + 'Decimal(10)'),
677 'str' + lop + '10')
678 self.assertEqual(eval('Decimal(10)' + sym + 'E()'),
679 '10' + rop + 'str')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000680
Mark Dickinson79f52032009-03-17 23:12:51 +0000681
Christian Heimesf16baeb2008-02-29 14:57:44 +0000682class DecimalFormatTest(unittest.TestCase):
683 '''Unit tests for the format function.'''
684 def test_formatting(self):
685 # triples giving a format, a Decimal, and the expected result
686 test_values = [
687 ('e', '0E-15', '0e-15'),
688 ('e', '2.3E-15', '2.3e-15'),
689 ('e', '2.30E+2', '2.30e+2'), # preserve significant zeros
690 ('e', '2.30000E-15', '2.30000e-15'),
691 ('e', '1.23456789123456789e40', '1.23456789123456789e+40'),
692 ('e', '1.5', '1.5e+0'),
693 ('e', '0.15', '1.5e-1'),
694 ('e', '0.015', '1.5e-2'),
695 ('e', '0.0000000000015', '1.5e-12'),
696 ('e', '15.0', '1.50e+1'),
697 ('e', '-15', '-1.5e+1'),
698 ('e', '0', '0e+0'),
699 ('e', '0E1', '0e+1'),
700 ('e', '0.0', '0e-1'),
701 ('e', '0.00', '0e-2'),
702 ('.6e', '0E-15', '0.000000e-9'),
703 ('.6e', '0', '0.000000e+6'),
704 ('.6e', '9.999999', '9.999999e+0'),
705 ('.6e', '9.9999999', '1.000000e+1'),
706 ('.6e', '-1.23e5', '-1.230000e+5'),
707 ('.6e', '1.23456789e-3', '1.234568e-3'),
708 ('f', '0', '0'),
709 ('f', '0.0', '0.0'),
710 ('f', '0E-2', '0.00'),
711 ('f', '0.00E-8', '0.0000000000'),
712 ('f', '0E1', '0'), # loses exponent information
713 ('f', '3.2E1', '32'),
714 ('f', '3.2E2', '320'),
715 ('f', '3.20E2', '320'),
716 ('f', '3.200E2', '320.0'),
717 ('f', '3.2E-6', '0.0000032'),
718 ('.6f', '0E-15', '0.000000'), # all zeros treated equally
719 ('.6f', '0E1', '0.000000'),
720 ('.6f', '0', '0.000000'),
721 ('.0f', '0', '0'), # no decimal point
722 ('.0f', '0e-2', '0'),
723 ('.0f', '3.14159265', '3'),
724 ('.1f', '3.14159265', '3.1'),
725 ('.4f', '3.14159265', '3.1416'),
726 ('.6f', '3.14159265', '3.141593'),
727 ('.7f', '3.14159265', '3.1415926'), # round-half-even!
728 ('.8f', '3.14159265', '3.14159265'),
729 ('.9f', '3.14159265', '3.141592650'),
730
731 ('g', '0', '0'),
732 ('g', '0.0', '0.0'),
733 ('g', '0E1', '0e+1'),
734 ('G', '0E1', '0E+1'),
735 ('g', '0E-5', '0.00000'),
736 ('g', '0E-6', '0.000000'),
737 ('g', '0E-7', '0e-7'),
738 ('g', '-0E2', '-0e+2'),
739 ('.0g', '3.14159265', '3'), # 0 sig fig -> 1 sig fig
740 ('.1g', '3.14159265', '3'),
741 ('.2g', '3.14159265', '3.1'),
742 ('.5g', '3.14159265', '3.1416'),
743 ('.7g', '3.14159265', '3.141593'),
744 ('.8g', '3.14159265', '3.1415926'), # round-half-even!
745 ('.9g', '3.14159265', '3.14159265'),
746 ('.10g', '3.14159265', '3.14159265'), # don't pad
747
748 ('%', '0E1', '0%'),
749 ('%', '0E0', '0%'),
750 ('%', '0E-1', '0%'),
751 ('%', '0E-2', '0%'),
752 ('%', '0E-3', '0.0%'),
753 ('%', '0E-4', '0.00%'),
754
755 ('.3%', '0', '0.000%'), # all zeros treated equally
756 ('.3%', '0E10', '0.000%'),
757 ('.3%', '0E-10', '0.000%'),
758 ('.3%', '2.34', '234.000%'),
759 ('.3%', '1.234567', '123.457%'),
760 ('.0%', '1.23', '123%'),
761
762 ('e', 'NaN', 'NaN'),
763 ('f', '-NaN123', '-NaN123'),
764 ('+g', 'NaN456', '+NaN456'),
765 ('.3e', 'Inf', 'Infinity'),
766 ('.16f', '-Inf', '-Infinity'),
767 ('.0g', '-sNaN', '-sNaN'),
768
769 ('', '1.00', '1.00'),
Mark Dickinsonad416342009-03-17 18:10:15 +0000770
Mark Dickinson79f52032009-03-17 23:12:51 +0000771 # test alignment and padding
Mark Dickinson46ab5d02009-09-08 20:22:46 +0000772 ('6', '123', ' 123'),
Mark Dickinsonad416342009-03-17 18:10:15 +0000773 ('<6', '123', '123 '),
774 ('>6', '123', ' 123'),
775 ('^6', '123', ' 123 '),
776 ('=+6', '123', '+ 123'),
Mark Dickinson79f52032009-03-17 23:12:51 +0000777 ('#<10', 'NaN', 'NaN#######'),
778 ('#<10', '-4.3', '-4.3######'),
779 ('#<+10', '0.0130', '+0.0130###'),
780 ('#< 10', '0.0130', ' 0.0130###'),
781 ('@>10', '-Inf', '@-Infinity'),
782 ('#>5', '-Inf', '-Infinity'),
783 ('?^5', '123', '?123?'),
784 ('%^6', '123', '%123%%'),
785 (' ^6', '-45.6', '-45.6 '),
786 ('/=10', '-45.6', '-/////45.6'),
787 ('/=+10', '45.6', '+/////45.6'),
788 ('/= 10', '45.6', ' /////45.6'),
789
790 # thousands separator
791 (',', '1234567', '1,234,567'),
792 (',', '123456', '123,456'),
793 (',', '12345', '12,345'),
794 (',', '1234', '1,234'),
795 (',', '123', '123'),
796 (',', '12', '12'),
797 (',', '1', '1'),
798 (',', '0', '0'),
799 (',', '-1234567', '-1,234,567'),
800 (',', '-123456', '-123,456'),
801 ('7,', '123456', '123,456'),
Mark Dickinson46ab5d02009-09-08 20:22:46 +0000802 ('8,', '123456', ' 123,456'),
Mark Dickinson79f52032009-03-17 23:12:51 +0000803 ('08,', '123456', '0,123,456'), # special case: extra 0 needed
804 ('+08,', '123456', '+123,456'), # but not if there's a sign
805 (' 08,', '123456', ' 123,456'),
806 ('08,', '-123456', '-123,456'),
807 ('+09,', '123456', '+0,123,456'),
808 # ... with fractional part...
809 ('07,', '1234.56', '1,234.56'),
810 ('08,', '1234.56', '1,234.56'),
811 ('09,', '1234.56', '01,234.56'),
812 ('010,', '1234.56', '001,234.56'),
813 ('011,', '1234.56', '0,001,234.56'),
814 ('012,', '1234.56', '0,001,234.56'),
815 ('08,.1f', '1234.5', '01,234.5'),
816 # no thousands separators in fraction part
817 (',', '1.23456789', '1.23456789'),
818 (',%', '123.456789', '12,345.6789%'),
819 (',e', '123456', '1.23456e+5'),
820 (',E', '123456', '1.23456E+5'),
Mark Dickinson7718d2b2009-09-07 16:21:56 +0000821
822 # issue 6850
823 ('a=-7.0', '0.12345', 'aaaa0.1'),
Christian Heimesf16baeb2008-02-29 14:57:44 +0000824 ]
825 for fmt, d, result in test_values:
826 self.assertEqual(format(Decimal(d), fmt), result)
827
Mark Dickinson79f52032009-03-17 23:12:51 +0000828 def test_n_format(self):
829 try:
830 from locale import CHAR_MAX
831 except ImportError:
832 return
833
834 # Set up some localeconv-like dictionaries
835 en_US = {
836 'decimal_point' : '.',
837 'grouping' : [3, 3, 0],
838 'thousands_sep': ','
839 }
840
841 fr_FR = {
842 'decimal_point' : ',',
843 'grouping' : [CHAR_MAX],
844 'thousands_sep' : ''
845 }
846
847 ru_RU = {
848 'decimal_point' : ',',
849 'grouping' : [3, 3, 0],
850 'thousands_sep' : ' '
851 }
852
853 crazy = {
854 'decimal_point' : '&',
855 'grouping' : [1, 4, 2, CHAR_MAX],
856 'thousands_sep' : '-'
857 }
858
859
860 def get_fmt(x, locale, fmt='n'):
861 return Decimal.__format__(Decimal(x), fmt, _localeconv=locale)
862
863 self.assertEqual(get_fmt(Decimal('12.7'), en_US), '12.7')
864 self.assertEqual(get_fmt(Decimal('12.7'), fr_FR), '12,7')
865 self.assertEqual(get_fmt(Decimal('12.7'), ru_RU), '12,7')
866 self.assertEqual(get_fmt(Decimal('12.7'), crazy), '1-2&7')
867
868 self.assertEqual(get_fmt(123456789, en_US), '123,456,789')
869 self.assertEqual(get_fmt(123456789, fr_FR), '123456789')
870 self.assertEqual(get_fmt(123456789, ru_RU), '123 456 789')
871 self.assertEqual(get_fmt(1234567890123, crazy), '123456-78-9012-3')
872
873 self.assertEqual(get_fmt(123456789, en_US, '.6n'), '1.23457e+8')
874 self.assertEqual(get_fmt(123456789, fr_FR, '.6n'), '1,23457e+8')
875 self.assertEqual(get_fmt(123456789, ru_RU, '.6n'), '1,23457e+8')
876 self.assertEqual(get_fmt(123456789, crazy, '.6n'), '1&23457e+8')
877
Mark Dickinson7303b592009-03-18 08:25:36 +0000878 # zero padding
879 self.assertEqual(get_fmt(1234, fr_FR, '03n'), '1234')
880 self.assertEqual(get_fmt(1234, fr_FR, '04n'), '1234')
881 self.assertEqual(get_fmt(1234, fr_FR, '05n'), '01234')
882 self.assertEqual(get_fmt(1234, fr_FR, '06n'), '001234')
883
884 self.assertEqual(get_fmt(12345, en_US, '05n'), '12,345')
885 self.assertEqual(get_fmt(12345, en_US, '06n'), '12,345')
886 self.assertEqual(get_fmt(12345, en_US, '07n'), '012,345')
887 self.assertEqual(get_fmt(12345, en_US, '08n'), '0,012,345')
888 self.assertEqual(get_fmt(12345, en_US, '09n'), '0,012,345')
889 self.assertEqual(get_fmt(12345, en_US, '010n'), '00,012,345')
890
891 self.assertEqual(get_fmt(123456, crazy, '06n'), '1-2345-6')
892 self.assertEqual(get_fmt(123456, crazy, '07n'), '1-2345-6')
893 self.assertEqual(get_fmt(123456, crazy, '08n'), '1-2345-6')
894 self.assertEqual(get_fmt(123456, crazy, '09n'), '01-2345-6')
895 self.assertEqual(get_fmt(123456, crazy, '010n'), '0-01-2345-6')
896 self.assertEqual(get_fmt(123456, crazy, '011n'), '0-01-2345-6')
897 self.assertEqual(get_fmt(123456, crazy, '012n'), '00-01-2345-6')
898 self.assertEqual(get_fmt(123456, crazy, '013n'), '000-01-2345-6')
899
Mark Dickinson79f52032009-03-17 23:12:51 +0000900
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000901class DecimalArithmeticOperatorsTest(unittest.TestCase):
902 '''Unit tests for all arithmetic operators, binary and unary.'''
903
904 def test_addition(self):
905
906 d1 = Decimal('-11.1')
907 d2 = Decimal('22.2')
908
909 #two Decimals
910 self.assertEqual(d1+d2, Decimal('11.1'))
911 self.assertEqual(d2+d1, Decimal('11.1'))
912
913 #with other type, left
914 c = d1 + 5
915 self.assertEqual(c, Decimal('-6.1'))
916 self.assertEqual(type(c), type(d1))
917
918 #with other type, right
919 c = 5 + d1
920 self.assertEqual(c, Decimal('-6.1'))
921 self.assertEqual(type(c), type(d1))
922
923 #inline with decimal
924 d1 += d2
925 self.assertEqual(d1, Decimal('11.1'))
926
927 #inline with other type
928 d1 += 5
929 self.assertEqual(d1, Decimal('16.1'))
930
931 def test_subtraction(self):
932
933 d1 = Decimal('-11.1')
934 d2 = Decimal('22.2')
935
936 #two Decimals
937 self.assertEqual(d1-d2, Decimal('-33.3'))
938 self.assertEqual(d2-d1, Decimal('33.3'))
939
940 #with other type, left
941 c = d1 - 5
942 self.assertEqual(c, Decimal('-16.1'))
943 self.assertEqual(type(c), type(d1))
944
945 #with other type, right
946 c = 5 - d1
947 self.assertEqual(c, Decimal('16.1'))
948 self.assertEqual(type(c), type(d1))
949
950 #inline with decimal
951 d1 -= d2
952 self.assertEqual(d1, Decimal('-33.3'))
953
954 #inline with other type
955 d1 -= 5
956 self.assertEqual(d1, Decimal('-38.3'))
957
958 def test_multiplication(self):
959
960 d1 = Decimal('-5')
961 d2 = Decimal('3')
962
963 #two Decimals
964 self.assertEqual(d1*d2, Decimal('-15'))
965 self.assertEqual(d2*d1, Decimal('-15'))
966
967 #with other type, left
968 c = d1 * 5
969 self.assertEqual(c, Decimal('-25'))
970 self.assertEqual(type(c), type(d1))
971
972 #with other type, right
973 c = 5 * d1
974 self.assertEqual(c, Decimal('-25'))
975 self.assertEqual(type(c), type(d1))
976
977 #inline with decimal
978 d1 *= d2
979 self.assertEqual(d1, Decimal('-15'))
980
981 #inline with other type
982 d1 *= 5
983 self.assertEqual(d1, Decimal('-75'))
984
985 def test_division(self):
986
987 d1 = Decimal('-5')
988 d2 = Decimal('2')
989
990 #two Decimals
991 self.assertEqual(d1/d2, Decimal('-2.5'))
992 self.assertEqual(d2/d1, Decimal('-0.4'))
993
994 #with other type, left
995 c = d1 / 4
996 self.assertEqual(c, Decimal('-1.25'))
997 self.assertEqual(type(c), type(d1))
998
999 #with other type, right
1000 c = 4 / d1
1001 self.assertEqual(c, Decimal('-0.8'))
1002 self.assertEqual(type(c), type(d1))
1003
1004 #inline with decimal
1005 d1 /= d2
1006 self.assertEqual(d1, Decimal('-2.5'))
1007
1008 #inline with other type
1009 d1 /= 4
1010 self.assertEqual(d1, Decimal('-0.625'))
1011
1012 def test_floor_division(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001013
1014 d1 = Decimal('5')
1015 d2 = Decimal('2')
1016
1017 #two Decimals
1018 self.assertEqual(d1//d2, Decimal('2'))
1019 self.assertEqual(d2//d1, Decimal('0'))
1020
1021 #with other type, left
1022 c = d1 // 4
1023 self.assertEqual(c, Decimal('1'))
1024 self.assertEqual(type(c), type(d1))
1025
1026 #with other type, right
1027 c = 7 // d1
1028 self.assertEqual(c, Decimal('1'))
1029 self.assertEqual(type(c), type(d1))
1030
1031 #inline with decimal
1032 d1 //= d2
1033 self.assertEqual(d1, Decimal('2'))
1034
1035 #inline with other type
1036 d1 //= 2
1037 self.assertEqual(d1, Decimal('1'))
1038
1039 def test_powering(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001040
1041 d1 = Decimal('5')
1042 d2 = Decimal('2')
1043
1044 #two Decimals
1045 self.assertEqual(d1**d2, Decimal('25'))
1046 self.assertEqual(d2**d1, Decimal('32'))
1047
1048 #with other type, left
1049 c = d1 ** 4
1050 self.assertEqual(c, Decimal('625'))
1051 self.assertEqual(type(c), type(d1))
1052
1053 #with other type, right
1054 c = 7 ** d1
1055 self.assertEqual(c, Decimal('16807'))
1056 self.assertEqual(type(c), type(d1))
1057
1058 #inline with decimal
1059 d1 **= d2
1060 self.assertEqual(d1, Decimal('25'))
1061
1062 #inline with other type
1063 d1 **= 4
1064 self.assertEqual(d1, Decimal('390625'))
1065
1066 def test_module(self):
1067
1068 d1 = Decimal('5')
1069 d2 = Decimal('2')
1070
1071 #two Decimals
1072 self.assertEqual(d1%d2, Decimal('1'))
1073 self.assertEqual(d2%d1, Decimal('2'))
1074
1075 #with other type, left
1076 c = d1 % 4
1077 self.assertEqual(c, Decimal('1'))
1078 self.assertEqual(type(c), type(d1))
1079
1080 #with other type, right
1081 c = 7 % d1
1082 self.assertEqual(c, Decimal('2'))
1083 self.assertEqual(type(c), type(d1))
1084
1085 #inline with decimal
1086 d1 %= d2
1087 self.assertEqual(d1, Decimal('1'))
1088
1089 #inline with other type
1090 d1 %= 4
1091 self.assertEqual(d1, Decimal('1'))
1092
1093 def test_floor_div_module(self):
1094
1095 d1 = Decimal('5')
1096 d2 = Decimal('2')
1097
1098 #two Decimals
1099 (p, q) = divmod(d1, d2)
1100 self.assertEqual(p, Decimal('2'))
1101 self.assertEqual(q, Decimal('1'))
1102 self.assertEqual(type(p), type(d1))
1103 self.assertEqual(type(q), type(d1))
1104
1105 #with other type, left
1106 (p, q) = divmod(d1, 4)
1107 self.assertEqual(p, Decimal('1'))
1108 self.assertEqual(q, Decimal('1'))
1109 self.assertEqual(type(p), type(d1))
1110 self.assertEqual(type(q), type(d1))
1111
1112 #with other type, right
1113 (p, q) = divmod(7, d1)
1114 self.assertEqual(p, Decimal('1'))
1115 self.assertEqual(q, Decimal('2'))
1116 self.assertEqual(type(p), type(d1))
1117 self.assertEqual(type(q), type(d1))
1118
1119 def test_unary_operators(self):
1120 self.assertEqual(+Decimal(45), Decimal(+45)) # +
1121 self.assertEqual(-Decimal(45), Decimal(-45)) # -
1122 self.assertEqual(abs(Decimal(45)), abs(Decimal(-45))) # abs
1123
Christian Heimes77c02eb2008-02-09 02:18:51 +00001124 def test_nan_comparisons(self):
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001125 # comparisons involving signaling nans signal InvalidOperation
1126
1127 # order comparisons (<, <=, >, >=) involving only quiet nans
1128 # also signal InvalidOperation
1129
1130 # equality comparisons (==, !=) involving only quiet nans
1131 # don't signal, but return False or True respectively.
1132
Christian Heimes77c02eb2008-02-09 02:18:51 +00001133 n = Decimal('NaN')
1134 s = Decimal('sNaN')
1135 i = Decimal('Inf')
1136 f = Decimal('2')
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001137
1138 qnan_pairs = (n, n), (n, i), (i, n), (n, f), (f, n)
1139 snan_pairs = (s, n), (n, s), (s, i), (i, s), (s, f), (f, s), (s, s)
1140 order_ops = operator.lt, operator.le, operator.gt, operator.ge
1141 equality_ops = operator.eq, operator.ne
1142
1143 # results when InvalidOperation is not trapped
1144 for x, y in qnan_pairs + snan_pairs:
1145 for op in order_ops + equality_ops:
1146 got = op(x, y)
1147 expected = True if op is operator.ne else False
1148 self.assertIs(expected, got,
1149 "expected {0!r} for operator.{1}({2!r}, {3!r}); "
1150 "got {4!r}".format(
1151 expected, op.__name__, x, y, got))
1152
1153 # repeat the above, but this time trap the InvalidOperation
1154 with localcontext() as ctx:
1155 ctx.traps[InvalidOperation] = 1
1156
1157 for x, y in qnan_pairs:
1158 for op in equality_ops:
1159 got = op(x, y)
1160 expected = True if op is operator.ne else False
1161 self.assertIs(expected, got,
1162 "expected {0!r} for "
1163 "operator.{1}({2!r}, {3!r}); "
1164 "got {4!r}".format(
1165 expected, op.__name__, x, y, got))
1166
1167 for x, y in snan_pairs:
1168 for op in equality_ops:
1169 self.assertRaises(InvalidOperation, operator.eq, x, y)
1170 self.assertRaises(InvalidOperation, operator.ne, x, y)
1171
1172 for x, y in qnan_pairs + snan_pairs:
1173 for op in order_ops:
1174 self.assertRaises(InvalidOperation, op, x, y)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001175
Mark Dickinson84230a12010-02-18 14:49:50 +00001176 def test_copy_sign(self):
1177 d = Decimal(1).copy_sign(Decimal(-2))
1178
1179 self.assertEqual(Decimal(1).copy_sign(-2), d)
1180 self.assertRaises(TypeError, Decimal(1).copy_sign, '-2')
1181
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001182# The following are two functions used to test threading in the next class
1183
1184def thfunc1(cls):
1185 d1 = Decimal(1)
1186 d3 = Decimal(3)
Christian Heimesfe337bf2008-03-23 21:54:12 +00001187 test1 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001188 cls.synchro.wait()
Christian Heimesfe337bf2008-03-23 21:54:12 +00001189 test2 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001190 cls.finish1.set()
Christian Heimesfe337bf2008-03-23 21:54:12 +00001191
Christian Heimes81ee3ef2008-05-04 22:42:01 +00001192 cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
1193 cls.assertEqual(test2, Decimal('0.3333333333333333333333333333'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001194 return
1195
1196def thfunc2(cls):
1197 d1 = Decimal(1)
1198 d3 = Decimal(3)
Christian Heimesfe337bf2008-03-23 21:54:12 +00001199 test1 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001200 thiscontext = getcontext()
1201 thiscontext.prec = 18
Christian Heimesfe337bf2008-03-23 21:54:12 +00001202 test2 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001203 cls.synchro.set()
1204 cls.finish2.set()
Christian Heimesfe337bf2008-03-23 21:54:12 +00001205
Christian Heimes81ee3ef2008-05-04 22:42:01 +00001206 cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
Christian Heimesfe337bf2008-03-23 21:54:12 +00001207 cls.assertEqual(test2, Decimal('0.333333333333333333'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001208 return
1209
1210
1211class DecimalUseOfContextTest(unittest.TestCase):
1212 '''Unit tests for Use of Context cases in Decimal.'''
1213
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001214 try:
1215 import threading
1216 except ImportError:
1217 threading = None
1218
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001219 # Take care executing this test from IDLE, there's an issue in threading
1220 # that hangs IDLE and I couldn't find it
1221
1222 def test_threading(self):
1223 #Test the "threading isolation" of a Context.
1224
1225 self.synchro = threading.Event()
1226 self.finish1 = threading.Event()
1227 self.finish2 = threading.Event()
1228
1229 th1 = threading.Thread(target=thfunc1, args=(self,))
1230 th2 = threading.Thread(target=thfunc2, args=(self,))
1231
1232 th1.start()
1233 th2.start()
1234
1235 self.finish1.wait()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001236 self.finish2.wait()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001237 return
1238
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001239 if threading is None:
1240 del test_threading
1241
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001242
1243class DecimalUsabilityTest(unittest.TestCase):
1244 '''Unit tests for Usability cases of Decimal.'''
1245
1246 def test_comparison_operators(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001247
1248 da = Decimal('23.42')
1249 db = Decimal('23.42')
1250 dc = Decimal('45')
1251
1252 #two Decimals
Ezio Melotti6607d512010-04-03 14:59:49 +00001253 self.assertGreater(dc, da)
1254 self.assertGreaterEqual(dc, da)
1255 self.assertLess(da, dc)
1256 self.assertLessEqual(da, dc)
Guido van Rossume61fd5b2007-07-11 12:20:59 +00001257 self.assertEqual(da, db)
Ezio Melotti6607d512010-04-03 14:59:49 +00001258 self.assertNotEqual(da, dc)
1259 self.assertLessEqual(da, db)
1260 self.assertGreaterEqual(da, db)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001261
1262 #a Decimal and an int
Ezio Melotti6607d512010-04-03 14:59:49 +00001263 self.assertGreater(dc, 23)
1264 self.assertLess(23, dc)
Guido van Rossume61fd5b2007-07-11 12:20:59 +00001265 self.assertEqual(dc, 45)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001266
1267 #a Decimal and uncomparable
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001268 self.assertNotEqual(da, 'ugly')
1269 self.assertNotEqual(da, 32.7)
1270 self.assertNotEqual(da, object())
1271 self.assertNotEqual(da, object)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001272
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001273 # sortable
Guido van Rossumc1f779c2007-07-03 08:25:58 +00001274 a = list(map(Decimal, range(100)))
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001275 b = a[:]
1276 random.shuffle(a)
1277 a.sort()
1278 self.assertEqual(a, b)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001279
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001280 def test_decimal_float_comparison(self):
1281 da = Decimal('0.25')
1282 db = Decimal('3.0')
Ezio Melotti6607d512010-04-03 14:59:49 +00001283 self.assertLess(da, 3.0)
1284 self.assertLessEqual(da, 3.0)
1285 self.assertGreater(db, 0.25)
1286 self.assertGreaterEqual(db, 0.25)
1287 self.assertNotEqual(da, 1.5)
1288 self.assertEqual(da, 0.25)
1289 self.assertGreater(3.0, da)
1290 self.assertGreaterEqual(3.0, da)
1291 self.assertLess(0.25, db)
1292 self.assertLessEqual(0.25, db)
1293 self.assertNotEqual(0.25, db)
1294 self.assertEqual(3.0, db)
1295 self.assertNotEqual(0.1, Decimal('0.1'))
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001296
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001297 def test_copy_and_deepcopy_methods(self):
1298 d = Decimal('43.24')
1299 c = copy.copy(d)
1300 self.assertEqual(id(c), id(d))
1301 dc = copy.deepcopy(d)
1302 self.assertEqual(id(dc), id(d))
1303
1304 def test_hash_method(self):
1305 #just that it's hashable
1306 hash(Decimal(23))
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001307 hash(Decimal('Infinity'))
1308 hash(Decimal('-Infinity'))
1309 hash(Decimal('nan123'))
1310 hash(Decimal('-NaN'))
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001311
1312 test_values = [Decimal(sign*(2**m + n))
1313 for m in [0, 14, 15, 16, 17, 30, 31,
1314 32, 33, 62, 63, 64, 65, 66]
1315 for n in range(-10, 10)
1316 for sign in [-1, 1]]
1317 test_values.extend([
1318 Decimal("-0"), # zeros
1319 Decimal("0.00"),
1320 Decimal("-0.000"),
1321 Decimal("0E10"),
1322 Decimal("-0E12"),
1323 Decimal("10.0"), # negative exponent
1324 Decimal("-23.00000"),
1325 Decimal("1230E100"), # positive exponent
1326 Decimal("-4.5678E50"),
1327 # a value for which hash(n) != hash(n % (2**64-1))
1328 # in Python pre-2.6
1329 Decimal(2**64 + 2**32 - 1),
1330 # selection of values which fail with the old (before
1331 # version 2.6) long.__hash__
1332 Decimal("1.634E100"),
1333 Decimal("90.697E100"),
1334 Decimal("188.83E100"),
1335 Decimal("1652.9E100"),
1336 Decimal("56531E100"),
1337 ])
1338
1339 # check that hash(d) == hash(int(d)) for integral values
1340 for value in test_values:
1341 self.assertEqual(hash(value), hash(int(value)))
1342
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001343 #the same hash that to an int
1344 self.assertEqual(hash(Decimal(23)), hash(23))
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001345 self.assertRaises(TypeError, hash, Decimal('sNaN'))
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001346 self.assertTrue(hash(Decimal('Inf')))
1347 self.assertTrue(hash(Decimal('-Inf')))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001348
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001349 # check that the hashes of a Decimal float match when they
1350 # represent exactly the same values
1351 test_strings = ['inf', '-Inf', '0.0', '-.0e1',
1352 '34.0', '2.5', '112390.625', '-0.515625']
1353 for s in test_strings:
1354 f = float(s)
1355 d = Decimal(s)
1356 self.assertEqual(hash(f), hash(d))
1357
Christian Heimes2380ac72008-01-09 00:17:24 +00001358 # check that the value of the hash doesn't depend on the
1359 # current context (issue #1757)
1360 c = getcontext()
1361 old_precision = c.prec
1362 x = Decimal("123456789.1")
1363
1364 c.prec = 6
1365 h1 = hash(x)
1366 c.prec = 10
1367 h2 = hash(x)
1368 c.prec = 16
1369 h3 = hash(x)
1370
1371 self.assertEqual(h1, h2)
1372 self.assertEqual(h1, h3)
1373 c.prec = old_precision
1374
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001375 def test_min_and_max_methods(self):
1376
1377 d1 = Decimal('15.32')
1378 d2 = Decimal('28.5')
1379 l1 = 15
1380 l2 = 28
1381
1382 #between Decimals
Ezio Melotti6607d512010-04-03 14:59:49 +00001383 self.assertIs(min(d1,d2), d1)
1384 self.assertIs(min(d2,d1), d1)
1385 self.assertIs(max(d1,d2), d2)
1386 self.assertIs(max(d2,d1), d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001387
1388 #between Decimal and long
Ezio Melotti6607d512010-04-03 14:59:49 +00001389 self.assertIs(min(d1,l2), d1)
1390 self.assertIs(min(l2,d1), d1)
1391 self.assertIs(max(l1,d2), d2)
1392 self.assertIs(max(d2,l1), d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001393
1394 def test_as_nonzero(self):
1395 #as false
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001396 self.assertFalse(Decimal(0))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001397 #as true
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001398 self.assertTrue(Decimal('0.372'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001399
1400 def test_tostring_methods(self):
1401 #Test str and repr methods.
1402
1403 d = Decimal('15.32')
1404 self.assertEqual(str(d), '15.32') # str
Christian Heimes68f5fbe2008-02-14 08:27:37 +00001405 self.assertEqual(repr(d), "Decimal('15.32')") # repr
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001406
1407 def test_tonum_methods(self):
Mark Dickinson5c2db372009-12-05 20:28:34 +00001408 #Test float and int methods.
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001409
1410 d1 = Decimal('66')
1411 d2 = Decimal('15.32')
1412
1413 #int
1414 self.assertEqual(int(d1), 66)
1415 self.assertEqual(int(d2), 15)
1416
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001417 #float
1418 self.assertEqual(float(d1), 66)
1419 self.assertEqual(float(d2), 15.32)
1420
Mark Dickinsonb27406c2008-05-09 13:42:33 +00001421 #floor
1422 test_pairs = [
1423 ('123.00', 123),
1424 ('3.2', 3),
1425 ('3.54', 3),
1426 ('3.899', 3),
1427 ('-2.3', -3),
1428 ('-11.0', -11),
1429 ('0.0', 0),
1430 ('-0E3', 0),
1431 ]
1432 for d, i in test_pairs:
1433 self.assertEqual(math.floor(Decimal(d)), i)
1434 self.assertRaises(ValueError, math.floor, Decimal('-NaN'))
1435 self.assertRaises(ValueError, math.floor, Decimal('sNaN'))
1436 self.assertRaises(ValueError, math.floor, Decimal('NaN123'))
1437 self.assertRaises(OverflowError, math.floor, Decimal('Inf'))
1438 self.assertRaises(OverflowError, math.floor, Decimal('-Inf'))
1439
1440 #ceiling
1441 test_pairs = [
1442 ('123.00', 123),
1443 ('3.2', 4),
1444 ('3.54', 4),
1445 ('3.899', 4),
1446 ('-2.3', -2),
1447 ('-11.0', -11),
1448 ('0.0', 0),
1449 ('-0E3', 0),
1450 ]
1451 for d, i in test_pairs:
1452 self.assertEqual(math.ceil(Decimal(d)), i)
1453 self.assertRaises(ValueError, math.ceil, Decimal('-NaN'))
1454 self.assertRaises(ValueError, math.ceil, Decimal('sNaN'))
1455 self.assertRaises(ValueError, math.ceil, Decimal('NaN123'))
1456 self.assertRaises(OverflowError, math.ceil, Decimal('Inf'))
1457 self.assertRaises(OverflowError, math.ceil, Decimal('-Inf'))
1458
1459 #round, single argument
1460 test_pairs = [
1461 ('123.00', 123),
1462 ('3.2', 3),
1463 ('3.54', 4),
1464 ('3.899', 4),
1465 ('-2.3', -2),
1466 ('-11.0', -11),
1467 ('0.0', 0),
1468 ('-0E3', 0),
1469 ('-3.5', -4),
1470 ('-2.5', -2),
1471 ('-1.5', -2),
1472 ('-0.5', 0),
1473 ('0.5', 0),
1474 ('1.5', 2),
1475 ('2.5', 2),
1476 ('3.5', 4),
1477 ]
1478 for d, i in test_pairs:
1479 self.assertEqual(round(Decimal(d)), i)
1480 self.assertRaises(ValueError, round, Decimal('-NaN'))
1481 self.assertRaises(ValueError, round, Decimal('sNaN'))
1482 self.assertRaises(ValueError, round, Decimal('NaN123'))
1483 self.assertRaises(OverflowError, round, Decimal('Inf'))
1484 self.assertRaises(OverflowError, round, Decimal('-Inf'))
1485
1486 #round, two arguments; this is essentially equivalent
1487 #to quantize, which is already extensively tested
1488 test_triples = [
1489 ('123.456', -4, '0E+4'),
1490 ('123.456', -3, '0E+3'),
1491 ('123.456', -2, '1E+2'),
1492 ('123.456', -1, '1.2E+2'),
1493 ('123.456', 0, '123'),
1494 ('123.456', 1, '123.5'),
1495 ('123.456', 2, '123.46'),
1496 ('123.456', 3, '123.456'),
1497 ('123.456', 4, '123.4560'),
1498 ('123.455', 2, '123.46'),
1499 ('123.445', 2, '123.44'),
1500 ('Inf', 4, 'NaN'),
1501 ('-Inf', -23, 'NaN'),
1502 ('sNaN314', 3, 'NaN314'),
1503 ]
1504 for d, n, r in test_triples:
1505 self.assertEqual(str(round(Decimal(d), n)), r)
1506
1507
1508
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001509 def test_eval_round_trip(self):
1510
1511 #with zero
1512 d = Decimal( (0, (0,), 0) )
1513 self.assertEqual(d, eval(repr(d)))
1514
1515 #int
1516 d = Decimal( (1, (4, 5), 0) )
1517 self.assertEqual(d, eval(repr(d)))
1518
1519 #float
1520 d = Decimal( (0, (4, 5, 3, 4), -2) )
1521 self.assertEqual(d, eval(repr(d)))
1522
1523 #weird
1524 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1525 self.assertEqual(d, eval(repr(d)))
1526
1527 def test_as_tuple(self):
1528
1529 #with zero
1530 d = Decimal(0)
1531 self.assertEqual(d.as_tuple(), (0, (0,), 0) )
1532
1533 #int
1534 d = Decimal(-45)
1535 self.assertEqual(d.as_tuple(), (1, (4, 5), 0) )
1536
1537 #complicated string
1538 d = Decimal("-4.34913534E-17")
1539 self.assertEqual(d.as_tuple(), (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1540
1541 #inf
1542 d = Decimal("Infinity")
1543 self.assertEqual(d.as_tuple(), (0, (0,), 'F') )
1544
Guido van Rossum8ce8a782007-11-01 19:42:39 +00001545 #leading zeros in coefficient should be stripped
1546 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), -2) )
1547 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), -2) )
1548 d = Decimal( (1, (0, 0, 0), 37) )
1549 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1550 d = Decimal( (1, (), 37) )
1551 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1552
1553 #leading zeros in NaN diagnostic info should be stripped
1554 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), 'n') )
1555 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), 'n') )
1556 d = Decimal( (1, (0, 0, 0), 'N') )
1557 self.assertEqual(d.as_tuple(), (1, (), 'N') )
1558 d = Decimal( (1, (), 'n') )
1559 self.assertEqual(d.as_tuple(), (1, (), 'n') )
1560
1561 #coefficient in infinity should be ignored
1562 d = Decimal( (0, (4, 5, 3, 4), 'F') )
1563 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
1564 d = Decimal( (1, (0, 2, 7, 1), 'F') )
1565 self.assertEqual(d.as_tuple(), (1, (0,), 'F'))
1566
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001567 def test_immutability_operations(self):
1568 # Do operations and check that it didn't change change internal objects.
1569
1570 d1 = Decimal('-25e55')
1571 b1 = Decimal('-25e55')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001572 d2 = Decimal('33e+33')
1573 b2 = Decimal('33e+33')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001574
1575 def checkSameDec(operation, useOther=False):
1576 if useOther:
1577 eval("d1." + operation + "(d2)")
1578 self.assertEqual(d1._sign, b1._sign)
1579 self.assertEqual(d1._int, b1._int)
1580 self.assertEqual(d1._exp, b1._exp)
1581 self.assertEqual(d2._sign, b2._sign)
1582 self.assertEqual(d2._int, b2._int)
1583 self.assertEqual(d2._exp, b2._exp)
1584 else:
1585 eval("d1." + operation + "()")
1586 self.assertEqual(d1._sign, b1._sign)
1587 self.assertEqual(d1._int, b1._int)
1588 self.assertEqual(d1._exp, b1._exp)
1589 return
1590
1591 Decimal(d1)
1592 self.assertEqual(d1._sign, b1._sign)
1593 self.assertEqual(d1._int, b1._int)
1594 self.assertEqual(d1._exp, b1._exp)
1595
1596 checkSameDec("__abs__")
1597 checkSameDec("__add__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001598 checkSameDec("__divmod__", True)
Christian Heimes77c02eb2008-02-09 02:18:51 +00001599 checkSameDec("__eq__", True)
1600 checkSameDec("__ne__", True)
1601 checkSameDec("__le__", True)
1602 checkSameDec("__lt__", True)
1603 checkSameDec("__ge__", True)
1604 checkSameDec("__gt__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001605 checkSameDec("__float__")
1606 checkSameDec("__floordiv__", True)
1607 checkSameDec("__hash__")
1608 checkSameDec("__int__")
Christian Heimes969fe572008-01-25 11:23:10 +00001609 checkSameDec("__trunc__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001610 checkSameDec("__mod__", True)
1611 checkSameDec("__mul__", True)
1612 checkSameDec("__neg__")
Jack Diederich4dafcc42006-11-28 19:15:13 +00001613 checkSameDec("__bool__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001614 checkSameDec("__pos__")
1615 checkSameDec("__pow__", True)
1616 checkSameDec("__radd__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001617 checkSameDec("__rdivmod__", True)
1618 checkSameDec("__repr__")
1619 checkSameDec("__rfloordiv__", True)
1620 checkSameDec("__rmod__", True)
1621 checkSameDec("__rmul__", True)
1622 checkSameDec("__rpow__", True)
1623 checkSameDec("__rsub__", True)
1624 checkSameDec("__str__")
1625 checkSameDec("__sub__", True)
1626 checkSameDec("__truediv__", True)
1627 checkSameDec("adjusted")
1628 checkSameDec("as_tuple")
1629 checkSameDec("compare", True)
1630 checkSameDec("max", True)
1631 checkSameDec("min", True)
1632 checkSameDec("normalize")
1633 checkSameDec("quantize", True)
1634 checkSameDec("remainder_near", True)
1635 checkSameDec("same_quantum", True)
1636 checkSameDec("sqrt")
1637 checkSameDec("to_eng_string")
1638 checkSameDec("to_integral")
1639
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001640 def test_subclassing(self):
1641 # Different behaviours when subclassing Decimal
1642
1643 class MyDecimal(Decimal):
1644 pass
1645
1646 d1 = MyDecimal(1)
1647 d2 = MyDecimal(2)
1648 d = d1 + d2
Ezio Melotti6607d512010-04-03 14:59:49 +00001649 self.assertIs(type(d), Decimal)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001650
1651 d = d1.max(d2)
Ezio Melotti6607d512010-04-03 14:59:49 +00001652 self.assertIs(type(d), Decimal)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001653
Christian Heimes0348fb62008-03-26 12:55:56 +00001654 def test_implicit_context(self):
1655 # Check results when context given implicitly. (Issue 2478)
1656 c = getcontext()
1657 self.assertEqual(str(Decimal(0).sqrt()),
1658 str(c.sqrt(Decimal(0))))
1659
Mark Dickinsona2d1fe02009-10-29 12:23:02 +00001660 def test_conversions_from_int(self):
1661 # Check that methods taking a second Decimal argument will
1662 # always accept an integer in place of a Decimal.
1663 self.assertEqual(Decimal(4).compare(3),
1664 Decimal(4).compare(Decimal(3)))
1665 self.assertEqual(Decimal(4).compare_signal(3),
1666 Decimal(4).compare_signal(Decimal(3)))
1667 self.assertEqual(Decimal(4).compare_total(3),
1668 Decimal(4).compare_total(Decimal(3)))
1669 self.assertEqual(Decimal(4).compare_total_mag(3),
1670 Decimal(4).compare_total_mag(Decimal(3)))
1671 self.assertEqual(Decimal(10101).logical_and(1001),
1672 Decimal(10101).logical_and(Decimal(1001)))
1673 self.assertEqual(Decimal(10101).logical_or(1001),
1674 Decimal(10101).logical_or(Decimal(1001)))
1675 self.assertEqual(Decimal(10101).logical_xor(1001),
1676 Decimal(10101).logical_xor(Decimal(1001)))
1677 self.assertEqual(Decimal(567).max(123),
1678 Decimal(567).max(Decimal(123)))
1679 self.assertEqual(Decimal(567).max_mag(123),
1680 Decimal(567).max_mag(Decimal(123)))
1681 self.assertEqual(Decimal(567).min(123),
1682 Decimal(567).min(Decimal(123)))
1683 self.assertEqual(Decimal(567).min_mag(123),
1684 Decimal(567).min_mag(Decimal(123)))
1685 self.assertEqual(Decimal(567).next_toward(123),
1686 Decimal(567).next_toward(Decimal(123)))
1687 self.assertEqual(Decimal(1234).quantize(100),
1688 Decimal(1234).quantize(Decimal(100)))
1689 self.assertEqual(Decimal(768).remainder_near(1234),
1690 Decimal(768).remainder_near(Decimal(1234)))
1691 self.assertEqual(Decimal(123).rotate(1),
1692 Decimal(123).rotate(Decimal(1)))
1693 self.assertEqual(Decimal(1234).same_quantum(1000),
1694 Decimal(1234).same_quantum(Decimal(1000)))
1695 self.assertEqual(Decimal('9.123').scaleb(-100),
1696 Decimal('9.123').scaleb(Decimal(-100)))
1697 self.assertEqual(Decimal(456).shift(-1),
1698 Decimal(456).shift(Decimal(-1)))
1699
1700 self.assertEqual(Decimal(-12).fma(Decimal(45), 67),
1701 Decimal(-12).fma(Decimal(45), Decimal(67)))
1702 self.assertEqual(Decimal(-12).fma(45, 67),
1703 Decimal(-12).fma(Decimal(45), Decimal(67)))
1704 self.assertEqual(Decimal(-12).fma(45, Decimal(67)),
1705 Decimal(-12).fma(Decimal(45), Decimal(67)))
1706
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001707
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001708class DecimalPythonAPItests(unittest.TestCase):
1709
Raymond Hettinger82417ca2009-02-03 03:54:28 +00001710 def test_abc(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001711 self.assertTrue(issubclass(Decimal, numbers.Number))
Ezio Melotti6607d512010-04-03 14:59:49 +00001712 self.assertFalse(issubclass(Decimal, numbers.Real))
Ezio Melottie9615932010-01-24 19:26:24 +00001713 self.assertIsInstance(Decimal(0), numbers.Number)
1714 self.assertNotIsInstance(Decimal(0), numbers.Real)
Raymond Hettinger82417ca2009-02-03 03:54:28 +00001715
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001716 def test_pickle(self):
1717 d = Decimal('-3.141590000')
1718 p = pickle.dumps(d)
1719 e = pickle.loads(p)
1720 self.assertEqual(d, e)
1721
Raymond Hettinger5548be22004-07-05 18:49:38 +00001722 def test_int(self):
Raymond Hettinger605ed022004-11-24 07:28:48 +00001723 for x in range(-250, 250):
1724 s = '%0.2f' % (x / 100.0)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001725 # should work the same as for floats
1726 self.assertEqual(int(Decimal(s)), int(float(s)))
Raymond Hettinger605ed022004-11-24 07:28:48 +00001727 # should work the same as to_integral in the ROUND_DOWN mode
Raymond Hettinger5548be22004-07-05 18:49:38 +00001728 d = Decimal(s)
Raymond Hettinger605ed022004-11-24 07:28:48 +00001729 r = d.to_integral(ROUND_DOWN)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001730 self.assertEqual(Decimal(int(d)), r)
1731
Mark Dickinson825fce32009-09-07 18:08:12 +00001732 self.assertRaises(ValueError, int, Decimal('-nan'))
1733 self.assertRaises(ValueError, int, Decimal('snan'))
1734 self.assertRaises(OverflowError, int, Decimal('inf'))
1735 self.assertRaises(OverflowError, int, Decimal('-inf'))
1736
Christian Heimes969fe572008-01-25 11:23:10 +00001737 def test_trunc(self):
1738 for x in range(-250, 250):
1739 s = '%0.2f' % (x / 100.0)
1740 # should work the same as for floats
1741 self.assertEqual(int(Decimal(s)), int(float(s)))
1742 # should work the same as to_integral in the ROUND_DOWN mode
1743 d = Decimal(s)
1744 r = d.to_integral(ROUND_DOWN)
Christian Heimes400adb02008-02-01 08:12:03 +00001745 self.assertEqual(Decimal(math.trunc(d)), r)
Christian Heimes969fe572008-01-25 11:23:10 +00001746
Raymond Hettinger771ed762009-01-03 19:20:32 +00001747 def test_from_float(self):
1748
1749 class MyDecimal(Decimal):
1750 pass
1751
1752 r = MyDecimal.from_float(0.1)
1753 self.assertEqual(type(r), MyDecimal)
1754 self.assertEqual(str(r),
1755 '0.1000000000000000055511151231257827021181583404541015625')
1756 bigint = 12345678901234567890123456789
1757 self.assertEqual(MyDecimal.from_float(bigint), MyDecimal(bigint))
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001758 self.assertTrue(MyDecimal.from_float(float('nan')).is_qnan())
1759 self.assertTrue(MyDecimal.from_float(float('inf')).is_infinite())
1760 self.assertTrue(MyDecimal.from_float(float('-inf')).is_infinite())
Raymond Hettinger771ed762009-01-03 19:20:32 +00001761 self.assertEqual(str(MyDecimal.from_float(float('nan'))),
1762 str(Decimal('NaN')))
1763 self.assertEqual(str(MyDecimal.from_float(float('inf'))),
1764 str(Decimal('Infinity')))
1765 self.assertEqual(str(MyDecimal.from_float(float('-inf'))),
1766 str(Decimal('-Infinity')))
1767 self.assertRaises(TypeError, MyDecimal.from_float, 'abc')
1768 for i in range(200):
1769 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
1770 self.assertEqual(x, float(MyDecimal.from_float(x))) # roundtrip
1771
1772 def test_create_decimal_from_float(self):
1773 context = Context(prec=5, rounding=ROUND_DOWN)
1774 self.assertEqual(
1775 context.create_decimal_from_float(math.pi),
1776 Decimal('3.1415')
1777 )
1778 context = Context(prec=5, rounding=ROUND_UP)
1779 self.assertEqual(
1780 context.create_decimal_from_float(math.pi),
1781 Decimal('3.1416')
1782 )
1783 context = Context(prec=5, traps=[Inexact])
1784 self.assertRaises(
1785 Inexact,
1786 context.create_decimal_from_float,
1787 math.pi
1788 )
1789 self.assertEqual(repr(context.create_decimal_from_float(-0.0)),
1790 "Decimal('-0')")
1791 self.assertEqual(repr(context.create_decimal_from_float(1.0)),
1792 "Decimal('1')")
1793 self.assertEqual(repr(context.create_decimal_from_float(10)),
1794 "Decimal('10')")
1795
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00001796class ContextAPItests(unittest.TestCase):
1797
1798 def test_pickle(self):
1799 c = Context()
1800 e = pickle.loads(pickle.dumps(c))
1801 for k in vars(c):
1802 v1 = vars(c)[k]
1803 v2 = vars(e)[k]
1804 self.assertEqual(v1, v2)
1805
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001806 def test_equality_with_other_types(self):
Benjamin Peterson577473f2010-01-19 00:09:57 +00001807 self.assertIn(Decimal(10), ['a', 1.0, Decimal(10), (1,2), {}])
1808 self.assertNotIn(Decimal(10), ['a', 1.0, (1,2), {}])
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001809
Raymond Hettinger955d2b22004-08-08 20:17:45 +00001810 def test_copy(self):
1811 # All copies should be deep
1812 c = Context()
1813 d = c.copy()
1814 self.assertNotEqual(id(c), id(d))
1815 self.assertNotEqual(id(c.flags), id(d.flags))
1816 self.assertNotEqual(id(c.traps), id(d.traps))
1817
Mark Dickinson84230a12010-02-18 14:49:50 +00001818 def test_abs(self):
1819 c = Context()
1820 d = c.abs(Decimal(-1))
1821 self.assertEqual(c.abs(-1), d)
1822 self.assertRaises(TypeError, c.abs, '-1')
1823
1824 def test_add(self):
1825 c = Context()
1826 d = c.add(Decimal(1), Decimal(1))
1827 self.assertEqual(c.add(1, 1), d)
1828 self.assertEqual(c.add(Decimal(1), 1), d)
1829 self.assertEqual(c.add(1, Decimal(1)), d)
1830 self.assertRaises(TypeError, c.add, '1', 1)
1831 self.assertRaises(TypeError, c.add, 1, '1')
1832
1833 def test_compare(self):
1834 c = Context()
1835 d = c.compare(Decimal(1), Decimal(1))
1836 self.assertEqual(c.compare(1, 1), d)
1837 self.assertEqual(c.compare(Decimal(1), 1), d)
1838 self.assertEqual(c.compare(1, Decimal(1)), d)
1839 self.assertRaises(TypeError, c.compare, '1', 1)
1840 self.assertRaises(TypeError, c.compare, 1, '1')
1841
1842 def test_compare_signal(self):
1843 c = Context()
1844 d = c.compare_signal(Decimal(1), Decimal(1))
1845 self.assertEqual(c.compare_signal(1, 1), d)
1846 self.assertEqual(c.compare_signal(Decimal(1), 1), d)
1847 self.assertEqual(c.compare_signal(1, Decimal(1)), d)
1848 self.assertRaises(TypeError, c.compare_signal, '1', 1)
1849 self.assertRaises(TypeError, c.compare_signal, 1, '1')
1850
1851 def test_compare_total(self):
1852 c = Context()
1853 d = c.compare_total(Decimal(1), Decimal(1))
1854 self.assertEqual(c.compare_total(1, 1), d)
1855 self.assertEqual(c.compare_total(Decimal(1), 1), d)
1856 self.assertEqual(c.compare_total(1, Decimal(1)), d)
1857 self.assertRaises(TypeError, c.compare_total, '1', 1)
1858 self.assertRaises(TypeError, c.compare_total, 1, '1')
1859
1860 def test_compare_total_mag(self):
1861 c = Context()
1862 d = c.compare_total_mag(Decimal(1), Decimal(1))
1863 self.assertEqual(c.compare_total_mag(1, 1), d)
1864 self.assertEqual(c.compare_total_mag(Decimal(1), 1), d)
1865 self.assertEqual(c.compare_total_mag(1, Decimal(1)), d)
1866 self.assertRaises(TypeError, c.compare_total_mag, '1', 1)
1867 self.assertRaises(TypeError, c.compare_total_mag, 1, '1')
1868
1869 def test_copy_abs(self):
1870 c = Context()
1871 d = c.copy_abs(Decimal(-1))
1872 self.assertEqual(c.copy_abs(-1), d)
1873 self.assertRaises(TypeError, c.copy_abs, '-1')
1874
1875 def test_copy_decimal(self):
1876 c = Context()
1877 d = c.copy_decimal(Decimal(-1))
1878 self.assertEqual(c.copy_decimal(-1), d)
1879 self.assertRaises(TypeError, c.copy_decimal, '-1')
1880
1881 def test_copy_negate(self):
1882 c = Context()
1883 d = c.copy_negate(Decimal(-1))
1884 self.assertEqual(c.copy_negate(-1), d)
1885 self.assertRaises(TypeError, c.copy_negate, '-1')
1886
1887 def test_copy_sign(self):
1888 c = Context()
1889 d = c.copy_sign(Decimal(1), Decimal(-2))
1890 self.assertEqual(c.copy_sign(1, -2), d)
1891 self.assertEqual(c.copy_sign(Decimal(1), -2), d)
1892 self.assertEqual(c.copy_sign(1, Decimal(-2)), d)
1893 self.assertRaises(TypeError, c.copy_sign, '1', -2)
1894 self.assertRaises(TypeError, c.copy_sign, 1, '-2')
1895
1896 def test_divide(self):
1897 c = Context()
1898 d = c.divide(Decimal(1), Decimal(2))
1899 self.assertEqual(c.divide(1, 2), d)
1900 self.assertEqual(c.divide(Decimal(1), 2), d)
1901 self.assertEqual(c.divide(1, Decimal(2)), d)
1902 self.assertRaises(TypeError, c.divide, '1', 2)
1903 self.assertRaises(TypeError, c.divide, 1, '2')
1904
1905 def test_divide_int(self):
1906 c = Context()
1907 d = c.divide_int(Decimal(1), Decimal(2))
1908 self.assertEqual(c.divide_int(1, 2), d)
1909 self.assertEqual(c.divide_int(Decimal(1), 2), d)
1910 self.assertEqual(c.divide_int(1, Decimal(2)), d)
1911 self.assertRaises(TypeError, c.divide_int, '1', 2)
1912 self.assertRaises(TypeError, c.divide_int, 1, '2')
1913
1914 def test_divmod(self):
1915 c = Context()
1916 d = c.divmod(Decimal(1), Decimal(2))
1917 self.assertEqual(c.divmod(1, 2), d)
1918 self.assertEqual(c.divmod(Decimal(1), 2), d)
1919 self.assertEqual(c.divmod(1, Decimal(2)), d)
1920 self.assertRaises(TypeError, c.divmod, '1', 2)
1921 self.assertRaises(TypeError, c.divmod, 1, '2')
1922
1923 def test_exp(self):
1924 c = Context()
1925 d = c.exp(Decimal(10))
1926 self.assertEqual(c.exp(10), d)
1927 self.assertRaises(TypeError, c.exp, '10')
1928
1929 def test_fma(self):
1930 c = Context()
1931 d = c.fma(Decimal(2), Decimal(3), Decimal(4))
1932 self.assertEqual(c.fma(2, 3, 4), d)
1933 self.assertEqual(c.fma(Decimal(2), 3, 4), d)
1934 self.assertEqual(c.fma(2, Decimal(3), 4), d)
1935 self.assertEqual(c.fma(2, 3, Decimal(4)), d)
1936 self.assertEqual(c.fma(Decimal(2), Decimal(3), 4), d)
1937 self.assertRaises(TypeError, c.fma, '2', 3, 4)
1938 self.assertRaises(TypeError, c.fma, 2, '3', 4)
1939 self.assertRaises(TypeError, c.fma, 2, 3, '4')
1940
1941 def test_is_finite(self):
1942 c = Context()
1943 d = c.is_finite(Decimal(10))
1944 self.assertEqual(c.is_finite(10), d)
1945 self.assertRaises(TypeError, c.is_finite, '10')
1946
1947 def test_is_infinite(self):
1948 c = Context()
1949 d = c.is_infinite(Decimal(10))
1950 self.assertEqual(c.is_infinite(10), d)
1951 self.assertRaises(TypeError, c.is_infinite, '10')
1952
1953 def test_is_nan(self):
1954 c = Context()
1955 d = c.is_nan(Decimal(10))
1956 self.assertEqual(c.is_nan(10), d)
1957 self.assertRaises(TypeError, c.is_nan, '10')
1958
1959 def test_is_normal(self):
1960 c = Context()
1961 d = c.is_normal(Decimal(10))
1962 self.assertEqual(c.is_normal(10), d)
1963 self.assertRaises(TypeError, c.is_normal, '10')
1964
1965 def test_is_qnan(self):
1966 c = Context()
1967 d = c.is_qnan(Decimal(10))
1968 self.assertEqual(c.is_qnan(10), d)
1969 self.assertRaises(TypeError, c.is_qnan, '10')
1970
1971 def test_is_signed(self):
1972 c = Context()
1973 d = c.is_signed(Decimal(10))
1974 self.assertEqual(c.is_signed(10), d)
1975 self.assertRaises(TypeError, c.is_signed, '10')
1976
1977 def test_is_snan(self):
1978 c = Context()
1979 d = c.is_snan(Decimal(10))
1980 self.assertEqual(c.is_snan(10), d)
1981 self.assertRaises(TypeError, c.is_snan, '10')
1982
1983 def test_is_subnormal(self):
1984 c = Context()
1985 d = c.is_subnormal(Decimal(10))
1986 self.assertEqual(c.is_subnormal(10), d)
1987 self.assertRaises(TypeError, c.is_subnormal, '10')
1988
1989 def test_is_zero(self):
1990 c = Context()
1991 d = c.is_zero(Decimal(10))
1992 self.assertEqual(c.is_zero(10), d)
1993 self.assertRaises(TypeError, c.is_zero, '10')
1994
1995 def test_ln(self):
1996 c = Context()
1997 d = c.ln(Decimal(10))
1998 self.assertEqual(c.ln(10), d)
1999 self.assertRaises(TypeError, c.ln, '10')
2000
2001 def test_log10(self):
2002 c = Context()
2003 d = c.log10(Decimal(10))
2004 self.assertEqual(c.log10(10), d)
2005 self.assertRaises(TypeError, c.log10, '10')
2006
2007 def test_logb(self):
2008 c = Context()
2009 d = c.logb(Decimal(10))
2010 self.assertEqual(c.logb(10), d)
2011 self.assertRaises(TypeError, c.logb, '10')
2012
2013 def test_logical_and(self):
2014 c = Context()
2015 d = c.logical_and(Decimal(1), Decimal(1))
2016 self.assertEqual(c.logical_and(1, 1), d)
2017 self.assertEqual(c.logical_and(Decimal(1), 1), d)
2018 self.assertEqual(c.logical_and(1, Decimal(1)), d)
2019 self.assertRaises(TypeError, c.logical_and, '1', 1)
2020 self.assertRaises(TypeError, c.logical_and, 1, '1')
2021
2022 def test_logical_invert(self):
2023 c = Context()
2024 d = c.logical_invert(Decimal(1000))
2025 self.assertEqual(c.logical_invert(1000), d)
2026 self.assertRaises(TypeError, c.logical_invert, '1000')
2027
2028 def test_logical_or(self):
2029 c = Context()
2030 d = c.logical_or(Decimal(1), Decimal(1))
2031 self.assertEqual(c.logical_or(1, 1), d)
2032 self.assertEqual(c.logical_or(Decimal(1), 1), d)
2033 self.assertEqual(c.logical_or(1, Decimal(1)), d)
2034 self.assertRaises(TypeError, c.logical_or, '1', 1)
2035 self.assertRaises(TypeError, c.logical_or, 1, '1')
2036
2037 def test_logical_xor(self):
2038 c = Context()
2039 d = c.logical_xor(Decimal(1), Decimal(1))
2040 self.assertEqual(c.logical_xor(1, 1), d)
2041 self.assertEqual(c.logical_xor(Decimal(1), 1), d)
2042 self.assertEqual(c.logical_xor(1, Decimal(1)), d)
2043 self.assertRaises(TypeError, c.logical_xor, '1', 1)
2044 self.assertRaises(TypeError, c.logical_xor, 1, '1')
2045
2046 def test_max(self):
2047 c = Context()
2048 d = c.max(Decimal(1), Decimal(2))
2049 self.assertEqual(c.max(1, 2), d)
2050 self.assertEqual(c.max(Decimal(1), 2), d)
2051 self.assertEqual(c.max(1, Decimal(2)), d)
2052 self.assertRaises(TypeError, c.max, '1', 2)
2053 self.assertRaises(TypeError, c.max, 1, '2')
2054
2055 def test_max_mag(self):
2056 c = Context()
2057 d = c.max_mag(Decimal(1), Decimal(2))
2058 self.assertEqual(c.max_mag(1, 2), d)
2059 self.assertEqual(c.max_mag(Decimal(1), 2), d)
2060 self.assertEqual(c.max_mag(1, Decimal(2)), d)
2061 self.assertRaises(TypeError, c.max_mag, '1', 2)
2062 self.assertRaises(TypeError, c.max_mag, 1, '2')
2063
2064 def test_min(self):
2065 c = Context()
2066 d = c.min(Decimal(1), Decimal(2))
2067 self.assertEqual(c.min(1, 2), d)
2068 self.assertEqual(c.min(Decimal(1), 2), d)
2069 self.assertEqual(c.min(1, Decimal(2)), d)
2070 self.assertRaises(TypeError, c.min, '1', 2)
2071 self.assertRaises(TypeError, c.min, 1, '2')
2072
2073 def test_min_mag(self):
2074 c = Context()
2075 d = c.min_mag(Decimal(1), Decimal(2))
2076 self.assertEqual(c.min_mag(1, 2), d)
2077 self.assertEqual(c.min_mag(Decimal(1), 2), d)
2078 self.assertEqual(c.min_mag(1, Decimal(2)), d)
2079 self.assertRaises(TypeError, c.min_mag, '1', 2)
2080 self.assertRaises(TypeError, c.min_mag, 1, '2')
2081
2082 def test_minus(self):
2083 c = Context()
2084 d = c.minus(Decimal(10))
2085 self.assertEqual(c.minus(10), d)
2086 self.assertRaises(TypeError, c.minus, '10')
2087
2088 def test_multiply(self):
2089 c = Context()
2090 d = c.multiply(Decimal(1), Decimal(2))
2091 self.assertEqual(c.multiply(1, 2), d)
2092 self.assertEqual(c.multiply(Decimal(1), 2), d)
2093 self.assertEqual(c.multiply(1, Decimal(2)), d)
2094 self.assertRaises(TypeError, c.multiply, '1', 2)
2095 self.assertRaises(TypeError, c.multiply, 1, '2')
2096
2097 def test_next_minus(self):
2098 c = Context()
2099 d = c.next_minus(Decimal(10))
2100 self.assertEqual(c.next_minus(10), d)
2101 self.assertRaises(TypeError, c.next_minus, '10')
2102
2103 def test_next_plus(self):
2104 c = Context()
2105 d = c.next_plus(Decimal(10))
2106 self.assertEqual(c.next_plus(10), d)
2107 self.assertRaises(TypeError, c.next_plus, '10')
2108
2109 def test_next_toward(self):
2110 c = Context()
2111 d = c.next_toward(Decimal(1), Decimal(2))
2112 self.assertEqual(c.next_toward(1, 2), d)
2113 self.assertEqual(c.next_toward(Decimal(1), 2), d)
2114 self.assertEqual(c.next_toward(1, Decimal(2)), d)
2115 self.assertRaises(TypeError, c.next_toward, '1', 2)
2116 self.assertRaises(TypeError, c.next_toward, 1, '2')
2117
2118 def test_normalize(self):
2119 c = Context()
2120 d = c.normalize(Decimal(10))
2121 self.assertEqual(c.normalize(10), d)
2122 self.assertRaises(TypeError, c.normalize, '10')
2123
2124 def test_number_class(self):
2125 c = Context()
2126 self.assertEqual(c.number_class(123), c.number_class(Decimal(123)))
2127 self.assertEqual(c.number_class(0), c.number_class(Decimal(0)))
2128 self.assertEqual(c.number_class(-45), c.number_class(Decimal(-45)))
2129
2130 def test_power(self):
2131 c = Context()
2132 d = c.power(Decimal(1), Decimal(4), Decimal(2))
2133 self.assertEqual(c.power(1, 4, 2), d)
2134 self.assertEqual(c.power(Decimal(1), 4, 2), d)
2135 self.assertEqual(c.power(1, Decimal(4), 2), d)
2136 self.assertEqual(c.power(1, 4, Decimal(2)), d)
2137 self.assertEqual(c.power(Decimal(1), Decimal(4), 2), d)
2138 self.assertRaises(TypeError, c.power, '1', 4, 2)
2139 self.assertRaises(TypeError, c.power, 1, '4', 2)
2140 self.assertRaises(TypeError, c.power, 1, 4, '2')
2141
2142 def test_plus(self):
2143 c = Context()
2144 d = c.plus(Decimal(10))
2145 self.assertEqual(c.plus(10), d)
2146 self.assertRaises(TypeError, c.plus, '10')
2147
2148 def test_quantize(self):
2149 c = Context()
2150 d = c.quantize(Decimal(1), Decimal(2))
2151 self.assertEqual(c.quantize(1, 2), d)
2152 self.assertEqual(c.quantize(Decimal(1), 2), d)
2153 self.assertEqual(c.quantize(1, Decimal(2)), d)
2154 self.assertRaises(TypeError, c.quantize, '1', 2)
2155 self.assertRaises(TypeError, c.quantize, 1, '2')
2156
2157 def test_remainder(self):
2158 c = Context()
2159 d = c.remainder(Decimal(1), Decimal(2))
2160 self.assertEqual(c.remainder(1, 2), d)
2161 self.assertEqual(c.remainder(Decimal(1), 2), d)
2162 self.assertEqual(c.remainder(1, Decimal(2)), d)
2163 self.assertRaises(TypeError, c.remainder, '1', 2)
2164 self.assertRaises(TypeError, c.remainder, 1, '2')
2165
2166 def test_remainder_near(self):
2167 c = Context()
2168 d = c.remainder_near(Decimal(1), Decimal(2))
2169 self.assertEqual(c.remainder_near(1, 2), d)
2170 self.assertEqual(c.remainder_near(Decimal(1), 2), d)
2171 self.assertEqual(c.remainder_near(1, Decimal(2)), d)
2172 self.assertRaises(TypeError, c.remainder_near, '1', 2)
2173 self.assertRaises(TypeError, c.remainder_near, 1, '2')
2174
2175 def test_rotate(self):
2176 c = Context()
2177 d = c.rotate(Decimal(1), Decimal(2))
2178 self.assertEqual(c.rotate(1, 2), d)
2179 self.assertEqual(c.rotate(Decimal(1), 2), d)
2180 self.assertEqual(c.rotate(1, Decimal(2)), d)
2181 self.assertRaises(TypeError, c.rotate, '1', 2)
2182 self.assertRaises(TypeError, c.rotate, 1, '2')
2183
2184 def test_sqrt(self):
2185 c = Context()
2186 d = c.sqrt(Decimal(10))
2187 self.assertEqual(c.sqrt(10), d)
2188 self.assertRaises(TypeError, c.sqrt, '10')
2189
2190 def test_same_quantum(self):
2191 c = Context()
2192 d = c.same_quantum(Decimal(1), Decimal(2))
2193 self.assertEqual(c.same_quantum(1, 2), d)
2194 self.assertEqual(c.same_quantum(Decimal(1), 2), d)
2195 self.assertEqual(c.same_quantum(1, Decimal(2)), d)
2196 self.assertRaises(TypeError, c.same_quantum, '1', 2)
2197 self.assertRaises(TypeError, c.same_quantum, 1, '2')
2198
2199 def test_scaleb(self):
2200 c = Context()
2201 d = c.scaleb(Decimal(1), Decimal(2))
2202 self.assertEqual(c.scaleb(1, 2), d)
2203 self.assertEqual(c.scaleb(Decimal(1), 2), d)
2204 self.assertEqual(c.scaleb(1, Decimal(2)), d)
2205 self.assertRaises(TypeError, c.scaleb, '1', 2)
2206 self.assertRaises(TypeError, c.scaleb, 1, '2')
2207
2208 def test_shift(self):
2209 c = Context()
2210 d = c.shift(Decimal(1), Decimal(2))
2211 self.assertEqual(c.shift(1, 2), d)
2212 self.assertEqual(c.shift(Decimal(1), 2), d)
2213 self.assertEqual(c.shift(1, Decimal(2)), d)
2214 self.assertRaises(TypeError, c.shift, '1', 2)
2215 self.assertRaises(TypeError, c.shift, 1, '2')
2216
2217 def test_subtract(self):
2218 c = Context()
2219 d = c.subtract(Decimal(1), Decimal(2))
2220 self.assertEqual(c.subtract(1, 2), d)
2221 self.assertEqual(c.subtract(Decimal(1), 2), d)
2222 self.assertEqual(c.subtract(1, Decimal(2)), d)
2223 self.assertRaises(TypeError, c.subtract, '1', 2)
2224 self.assertRaises(TypeError, c.subtract, 1, '2')
2225
2226 def test_to_eng_string(self):
2227 c = Context()
2228 d = c.to_eng_string(Decimal(10))
2229 self.assertEqual(c.to_eng_string(10), d)
2230 self.assertRaises(TypeError, c.to_eng_string, '10')
2231
2232 def test_to_sci_string(self):
2233 c = Context()
2234 d = c.to_sci_string(Decimal(10))
2235 self.assertEqual(c.to_sci_string(10), d)
2236 self.assertRaises(TypeError, c.to_sci_string, '10')
2237
2238 def test_to_integral_exact(self):
2239 c = Context()
2240 d = c.to_integral_exact(Decimal(10))
2241 self.assertEqual(c.to_integral_exact(10), d)
2242 self.assertRaises(TypeError, c.to_integral_exact, '10')
2243
2244 def test_to_integral_value(self):
2245 c = Context()
2246 d = c.to_integral_value(Decimal(10))
2247 self.assertEqual(c.to_integral_value(10), d)
2248 self.assertRaises(TypeError, c.to_integral_value, '10')
2249
Thomas Wouters89f507f2006-12-13 04:49:30 +00002250class WithStatementTest(unittest.TestCase):
2251 # Can't do these as docstrings until Python 2.6
2252 # as doctest can't handle __future__ statements
2253
2254 def test_localcontext(self):
2255 # Use a copy of the current context in the block
2256 orig_ctx = getcontext()
2257 with localcontext() as enter_ctx:
2258 set_ctx = getcontext()
2259 final_ctx = getcontext()
Ezio Melotti6607d512010-04-03 14:59:49 +00002260 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
2261 self.assertIsNot(orig_ctx, set_ctx, 'did not copy the context')
2262 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
Thomas Wouters89f507f2006-12-13 04:49:30 +00002263
2264 def test_localcontextarg(self):
2265 # Use a copy of the supplied context in the block
2266 orig_ctx = getcontext()
2267 new_ctx = Context(prec=42)
2268 with localcontext(new_ctx) as enter_ctx:
2269 set_ctx = getcontext()
2270 final_ctx = getcontext()
Ezio Melotti6607d512010-04-03 14:59:49 +00002271 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
2272 self.assertEqual(set_ctx.prec, new_ctx.prec, 'did not set correct context')
2273 self.assertIsNot(new_ctx, set_ctx, 'did not copy the context')
2274 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
Thomas Wouters89f507f2006-12-13 04:49:30 +00002275
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002276class ContextFlags(unittest.TestCase):
2277 def test_flags_irrelevant(self):
2278 # check that the result (numeric result + flags raised) of an
2279 # arithmetic operation doesn't depend on the current flags
2280
2281 context = Context(prec=9, Emin = -999999999, Emax = 999999999,
2282 rounding=ROUND_HALF_EVEN, traps=[], flags=[])
2283
2284 # operations that raise various flags, in the form (function, arglist)
2285 operations = [
2286 (context._apply, [Decimal("100E-1000000009")]),
2287 (context.sqrt, [Decimal(2)]),
2288 (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]),
2289 (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]),
2290 (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]),
2291 ]
2292
2293 # try various flags individually, then a whole lot at once
2294 flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal],
2295 [Inexact, Rounded, Underflow, Clamped, Subnormal]]
2296
2297 for fn, args in operations:
2298 # find answer and flags raised using a clean context
2299 context.clear_flags()
2300 ans = fn(*args)
2301 flags = [k for k, v in context.flags.items() if v]
2302
2303 for extra_flags in flagsets:
2304 # set flags, before calling operation
2305 context.clear_flags()
2306 for flag in extra_flags:
2307 context._raise_error(flag)
2308 new_ans = fn(*args)
2309
2310 # flags that we expect to be set after the operation
2311 expected_flags = list(flags)
2312 for flag in extra_flags:
2313 if flag not in expected_flags:
2314 expected_flags.append(flag)
2315 expected_flags.sort(key=id)
2316
2317 # flags we actually got
2318 new_flags = [k for k,v in context.flags.items() if v]
2319 new_flags.sort(key=id)
2320
2321 self.assertEqual(ans, new_ans,
2322 "operation produces different answers depending on flags set: " +
2323 "expected %s, got %s." % (ans, new_ans))
2324 self.assertEqual(new_flags, expected_flags,
2325 "operation raises different flags depending on flags set: " +
2326 "expected %s, got %s" % (expected_flags, new_flags))
2327
2328def test_main(arith=False, verbose=None, todo_tests=None, debug=None):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002329 """ Execute the tests.
2330
Raymond Hettingered20ad82004-09-04 20:09:13 +00002331 Runs all arithmetic tests if arith is True or if the "decimal" resource
2332 is enabled in regrtest.py
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002333 """
Raymond Hettingered20ad82004-09-04 20:09:13 +00002334
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002335 init()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002336 global TEST_ALL, DEBUG
Raymond Hettingered20ad82004-09-04 20:09:13 +00002337 TEST_ALL = arith or is_resource_enabled('decimal')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002338 DEBUG = debug
Raymond Hettingered20ad82004-09-04 20:09:13 +00002339
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002340 if todo_tests is None:
2341 test_classes = [
2342 DecimalExplicitConstructionTest,
2343 DecimalImplicitConstructionTest,
2344 DecimalArithmeticOperatorsTest,
Christian Heimesf16baeb2008-02-29 14:57:44 +00002345 DecimalFormatTest,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002346 DecimalUseOfContextTest,
2347 DecimalUsabilityTest,
2348 DecimalPythonAPItests,
2349 ContextAPItests,
2350 DecimalTest,
2351 WithStatementTest,
2352 ContextFlags
2353 ]
2354 else:
2355 test_classes = [DecimalTest]
2356
2357 # Dynamically build custom test definition for each file in the test
2358 # directory and add the definitions to the DecimalTest class. This
2359 # procedure insures that new files do not get skipped.
2360 for filename in os.listdir(directory):
2361 if '.decTest' not in filename or filename.startswith("."):
2362 continue
2363 head, tail = filename.split('.')
2364 if todo_tests is not None and head not in todo_tests:
2365 continue
2366 tester = lambda self, f=filename: self.eval_file(directory + f)
2367 setattr(DecimalTest, 'test_' + head, tester)
2368 del filename, head, tail, tester
2369
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002370
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002371 try:
2372 run_unittest(*test_classes)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002373 if todo_tests is None:
2374 import decimal as DecimalModule
2375 run_doctest(DecimalModule, verbose)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002376 finally:
2377 setcontext(ORIGINAL_CONTEXT)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002378
2379if __name__ == '__main__':
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002380 import optparse
2381 p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]")
2382 p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test')
2383 p.add_option('--skip', '-s', action='store_true', help='skip over 90% of the arithmetic tests')
2384 (opt, args) = p.parse_args()
2385
2386 if opt.skip:
2387 test_main(arith=False, verbose=True)
2388 elif args:
2389 test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002390 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002391 test_main(arith=True, verbose=True)