blob: 9f3d104e5dbec3f8acf0feea09432c83004d95b4 [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
Jeffrey Yasskinca2b69f2008-02-01 06:22:46 +000027import math
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000028import os, sys
Mark Dickinsone096e822010-04-02 10:17:07 +000029import operator
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000030import pickle, copy
Jeffrey Yasskinca2b69f2008-02-01 06:22:46 +000031import unittest
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000032from decimal import *
Raymond Hettinger2c8585b2009-02-03 03:37:03 +000033import numbers
Florent Xicluna8f43cec2010-03-21 10:51:40 +000034from test.test_support import (run_unittest, run_doctest,
35 is_resource_enabled, check_py3k_warnings)
Raymond Hettinger0aeac102004-07-05 22:53:03 +000036import random
Raymond Hettinger7e71fa52004-12-18 19:07:19 +000037try:
38 import threading
39except ImportError:
40 threading = None
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000041
Raymond Hettingerfed52962004-07-14 15:41:57 +000042# Useful Test Constant
Mark Dickinson16cd2be2010-05-01 11:46:20 +000043Signals = tuple(getcontext().flags.keys())
Raymond Hettingerfed52962004-07-14 15:41:57 +000044
Tim Peters46cc7022006-03-31 04:11:16 +000045# Tests are built around these assumed context defaults.
46# test_main() restores the original context.
Neal Norwitzce4a9c92006-04-09 08:36:46 +000047def init():
48 global ORIGINAL_CONTEXT
49 ORIGINAL_CONTEXT = getcontext().copy()
Facundo Batistaee340e52008-05-02 17:39:00 +000050 DefaultTestContext = Context(
51 prec = 9,
52 rounding = ROUND_HALF_EVEN,
53 traps = dict.fromkeys(Signals, 0)
54 )
55 setcontext(DefaultTestContext)
Raymond Hettinger6ea48452004-07-03 12:26:21 +000056
Raymond Hettingered171ab2010-04-02 18:39:24 +000057# decorator for skipping tests on non-IEEE 754 platforms
58requires_IEEE_754 = unittest.skipUnless(
59 float.__getformat__("double").startswith("IEEE"),
60 "test requires IEEE 754 doubles")
61
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000062TESTDATADIR = 'decimaltestdata'
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +000063if __name__ == '__main__':
64 file = sys.argv[0]
65else:
66 file = __file__
67testdir = os.path.dirname(file) or os.curdir
Raymond Hettinger267b8682005-03-27 10:47:39 +000068directory = testdir + os.sep + TESTDATADIR + os.sep
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000069
Raymond Hettinger267b8682005-03-27 10:47:39 +000070skip_expected = not os.path.isdir(directory)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000071
Mark Dickinson539bff42009-10-08 16:28:39 +000072# list of individual .decTest test ids that correspond to tests that
73# we're skipping for one reason or another.
74skipped_test_ids = [
75 'scbx164', # skipping apparently implementation-specific scaleb
76 'scbx165', # tests, pending clarification of scaleb rules.
77]
78
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000079# Make sure it actually raises errors when not expected and caught in flags
80# Slower, since it runs some things several times.
81EXTENDEDERRORTEST = False
82
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000083#Map the test cases' error names to the actual errors
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000084ErrorNames = {'clamped' : Clamped,
Raymond Hettinger5aa478b2004-07-09 10:02:53 +000085 'conversion_syntax' : InvalidOperation,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000086 'division_by_zero' : DivisionByZero,
Raymond Hettinger5aa478b2004-07-09 10:02:53 +000087 'division_impossible' : InvalidOperation,
88 'division_undefined' : InvalidOperation,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000089 'inexact' : Inexact,
Raymond Hettinger5aa478b2004-07-09 10:02:53 +000090 'invalid_context' : InvalidOperation,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000091 'invalid_operation' : InvalidOperation,
92 'overflow' : Overflow,
93 'rounded' : Rounded,
94 'subnormal' : Subnormal,
95 'underflow' : Underflow}
96
97
98def Nonfunction(*args):
99 """Doesn't do anything."""
100 return None
101
102RoundingDict = {'ceiling' : ROUND_CEILING, #Maps test-case names to roundings.
103 'down' : ROUND_DOWN,
104 'floor' : ROUND_FLOOR,
105 'half_down' : ROUND_HALF_DOWN,
106 'half_even' : ROUND_HALF_EVEN,
107 'half_up' : ROUND_HALF_UP,
Facundo Batista353750c2007-09-13 18:13:15 +0000108 'up' : ROUND_UP,
109 '05up' : ROUND_05UP}
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000110
111# Name adapter to be able to change the Decimal and Context
112# interface without changing the test files from Cowlishaw
Facundo Batista1a191df2007-10-02 17:01:24 +0000113nameAdapter = {'and':'logical_and',
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000114 'apply':'_apply',
Facundo Batista353750c2007-09-13 18:13:15 +0000115 'class':'number_class',
116 'comparesig':'compare_signal',
117 'comparetotal':'compare_total',
118 'comparetotmag':'compare_total_mag',
Facundo Batista353750c2007-09-13 18:13:15 +0000119 'copy':'copy_decimal',
Facundo Batista1a191df2007-10-02 17:01:24 +0000120 'copyabs':'copy_abs',
Facundo Batista353750c2007-09-13 18:13:15 +0000121 'copynegate':'copy_negate',
122 'copysign':'copy_sign',
Facundo Batista1a191df2007-10-02 17:01:24 +0000123 'divideint':'divide_int',
Facundo Batista353750c2007-09-13 18:13:15 +0000124 'invert':'logical_invert',
Facundo Batista1a191df2007-10-02 17:01:24 +0000125 'iscanonical':'is_canonical',
126 'isfinite':'is_finite',
127 'isinfinite':'is_infinite',
128 'isnan':'is_nan',
129 'isnormal':'is_normal',
130 'isqnan':'is_qnan',
131 'issigned':'is_signed',
132 'issnan':'is_snan',
133 'issubnormal':'is_subnormal',
134 'iszero':'is_zero',
Facundo Batista353750c2007-09-13 18:13:15 +0000135 'maxmag':'max_mag',
136 'minmag':'min_mag',
137 'nextminus':'next_minus',
138 'nextplus':'next_plus',
139 'nexttoward':'next_toward',
Facundo Batista1a191df2007-10-02 17:01:24 +0000140 'or':'logical_or',
Facundo Batista353750c2007-09-13 18:13:15 +0000141 'reduce':'normalize',
Facundo Batista1a191df2007-10-02 17:01:24 +0000142 'remaindernear':'remainder_near',
143 'samequantum':'same_quantum',
144 'squareroot':'sqrt',
145 'toeng':'to_eng_string',
146 'tointegral':'to_integral_value',
147 'tointegralx':'to_integral_exact',
148 'tosci':'to_sci_string',
149 'xor':'logical_xor',
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000150 }
151
Facundo Batista1a191df2007-10-02 17:01:24 +0000152# The following functions return True/False rather than a Decimal instance
153
154LOGICAL_FUNCTIONS = (
155 'is_canonical',
156 'is_finite',
157 'is_infinite',
158 'is_nan',
159 'is_normal',
160 'is_qnan',
161 'is_signed',
162 'is_snan',
163 'is_subnormal',
164 'is_zero',
165 'same_quantum',
166 )
167
Facundo Batista353750c2007-09-13 18:13:15 +0000168# For some operations (currently exp, ln, log10, power), the decNumber
169# reference implementation imposes additional restrictions on the
170# context and operands. These restrictions are not part of the
171# specification; however, the effect of these restrictions does show
172# up in some of the testcases. We skip testcases that violate these
173# restrictions, since Decimal behaves differently from decNumber for
174# these testcases so these testcases would otherwise fail.
175
176decNumberRestricted = ('power', 'ln', 'log10', 'exp')
177DEC_MAX_MATH = 999999
178def outside_decNumber_bounds(v, context):
179 if (context.prec > DEC_MAX_MATH or
180 context.Emax > DEC_MAX_MATH or
181 -context.Emin > DEC_MAX_MATH):
182 return True
183 if not v._is_special and v and (
Facundo Batista353750c2007-09-13 18:13:15 +0000184 v.adjusted() > DEC_MAX_MATH or
185 v.adjusted() < 1-2*DEC_MAX_MATH):
186 return True
187 return False
188
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000189class DecimalTest(unittest.TestCase):
190 """Class which tests the Decimal class against the test cases.
191
192 Changed for unittest.
193 """
194 def setUp(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000195 self.context = Context()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000196 self.ignore_list = ['#']
197 # Basically, a # means return NaN InvalidOperation.
198 # Different from a sNaN in trim
199
200 self.ChangeDict = {'precision' : self.change_precision,
201 'rounding' : self.change_rounding_method,
202 'maxexponent' : self.change_max_exponent,
203 'minexponent' : self.change_min_exponent,
204 'clamp' : self.change_clamp}
205
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000206 def eval_file(self, file):
207 global skip_expected
208 if skip_expected:
Benjamin Petersonbec087f2009-03-26 21:10:30 +0000209 raise unittest.SkipTest
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000210 return
Florent Xicluna8f43cec2010-03-21 10:51:40 +0000211 for line in open(file):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000212 line = line.replace('\r\n', '').replace('\n', '')
Raymond Hettinger5aa478b2004-07-09 10:02:53 +0000213 #print line
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000214 try:
215 t = self.eval_line(line)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000216 except DecimalException, exception:
217 #Exception raised where there shoudn't have been one.
218 self.fail('Exception "'+exception.__class__.__name__ + '" raised on line '+line)
219
220 return
221
222 def eval_line(self, s):
223 if s.find(' -> ') >= 0 and s[:2] != '--' and not s.startswith(' --'):
224 s = (s.split('->')[0] + '->' +
225 s.split('->')[1].split('--')[0]).strip()
226 else:
227 s = s.split('--')[0].strip()
228
229 for ignore in self.ignore_list:
230 if s.find(ignore) >= 0:
231 #print s.split()[0], 'NotImplemented--', ignore
232 return
233 if not s:
234 return
235 elif ':' in s:
236 return self.eval_directive(s)
237 else:
238 return self.eval_equation(s)
239
240 def eval_directive(self, s):
241 funct, value = map(lambda x: x.strip().lower(), s.split(':'))
242 if funct == 'rounding':
243 value = RoundingDict[value]
244 else:
245 try:
246 value = int(value)
247 except ValueError:
248 pass
249
250 funct = self.ChangeDict.get(funct, Nonfunction)
251 funct(value)
252
253 def eval_equation(self, s):
254 #global DEFAULT_PRECISION
255 #print DEFAULT_PRECISION
Raymond Hettingered20ad82004-09-04 20:09:13 +0000256
257 if not TEST_ALL and random.random() < 0.90:
258 return
259
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000260 try:
261 Sides = s.split('->')
262 L = Sides[0].strip().split()
263 id = L[0]
Facundo Batista353750c2007-09-13 18:13:15 +0000264 if DEBUG:
265 print "Test ", id,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000266 funct = L[1].lower()
267 valstemp = L[2:]
268 L = Sides[1].strip().split()
269 ans = L[0]
270 exceptions = L[1:]
271 except (TypeError, AttributeError, IndexError):
Raymond Hettingerd87ac8f2004-07-09 10:52:54 +0000272 raise InvalidOperation
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000273 def FixQuotes(val):
274 val = val.replace("''", 'SingleQuote').replace('""', 'DoubleQuote')
275 val = val.replace("'", '').replace('"', '')
276 val = val.replace('SingleQuote', "'").replace('DoubleQuote', '"')
277 return val
Mark Dickinson539bff42009-10-08 16:28:39 +0000278
279 if id in skipped_test_ids:
280 return
281
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000282 fname = nameAdapter.get(funct, funct)
283 if fname == 'rescale':
284 return
285 funct = getattr(self.context, fname)
286 vals = []
287 conglomerate = ''
288 quote = 0
289 theirexceptions = [ErrorNames[x.lower()] for x in exceptions]
290
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000291 for exception in Signals:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000292 self.context.traps[exception] = 1 #Catch these bugs...
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000293 for exception in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000294 self.context.traps[exception] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000295 for i, val in enumerate(valstemp):
296 if val.count("'") % 2 == 1:
297 quote = 1 - quote
298 if quote:
299 conglomerate = conglomerate + ' ' + val
300 continue
301 else:
302 val = conglomerate + val
303 conglomerate = ''
304 v = FixQuotes(val)
305 if fname in ('to_sci_string', 'to_eng_string'):
306 if EXTENDEDERRORTEST:
307 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000308 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000309 try:
310 funct(self.context.create_decimal(v))
311 except error:
312 pass
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000313 except Signals, e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000314 self.fail("Raised %s in %s when %s disabled" % \
315 (e, s, error))
316 else:
317 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000318 self.context.traps[error] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000319 v = self.context.create_decimal(v)
320 else:
Facundo Batista353750c2007-09-13 18:13:15 +0000321 v = Decimal(v, self.context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000322 vals.append(v)
323
324 ans = FixQuotes(ans)
325
Facundo Batista353750c2007-09-13 18:13:15 +0000326 # skip tests that are related to bounds imposed in the decNumber
327 # reference implementation
328 if fname in decNumberRestricted:
329 if fname == 'power':
330 if not (vals[1]._isinteger() and
331 -1999999997 <= vals[1] <= 999999999):
332 if outside_decNumber_bounds(vals[0], self.context) or \
333 outside_decNumber_bounds(vals[1], self.context):
334 #print "Skipping test %s" % s
335 return
336 else:
337 if outside_decNumber_bounds(vals[0], self.context):
338 #print "Skipping test %s" % s
339 return
340
341
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000342 if EXTENDEDERRORTEST and fname not in ('to_sci_string', 'to_eng_string'):
343 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000344 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000345 try:
346 funct(*vals)
347 except error:
348 pass
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000349 except Signals, e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000350 self.fail("Raised %s in %s when %s disabled" % \
351 (e, s, error))
352 else:
353 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000354 self.context.traps[error] = 0
Facundo Batista353750c2007-09-13 18:13:15 +0000355 if DEBUG:
356 print "--", self.context
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000357 try:
358 result = str(funct(*vals))
Facundo Batista1a191df2007-10-02 17:01:24 +0000359 if fname in LOGICAL_FUNCTIONS:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000360 result = str(int(eval(result))) # 'True', 'False' -> '1', '0'
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000361 except Signals, error:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000362 self.fail("Raised %s in %s" % (error, s))
363 except: #Catch any error long enough to state the test case.
364 print "ERROR:", s
365 raise
366
367 myexceptions = self.getexceptions()
Raymond Hettingerbf440692004-07-10 14:14:37 +0000368 self.context.clear_flags()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000369
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000370 self.assertEqual(result, ans,
371 'Incorrect answer for ' + s + ' -- got ' + result)
Florent Xicluna8f43cec2010-03-21 10:51:40 +0000372 self.assertItemsEqual(myexceptions, theirexceptions,
Facundo Batista353750c2007-09-13 18:13:15 +0000373 'Incorrect flags set in ' + s + ' -- got ' + str(myexceptions))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000374 return
375
376 def getexceptions(self):
Raymond Hettingerf63ba432004-08-17 05:42:09 +0000377 return [e for e in Signals if self.context.flags[e]]
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000378
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000379 def change_precision(self, prec):
380 self.context.prec = prec
381 def change_rounding_method(self, rounding):
382 self.context.rounding = rounding
383 def change_min_exponent(self, exp):
384 self.context.Emin = exp
385 def change_max_exponent(self, exp):
386 self.context.Emax = exp
387 def change_clamp(self, clamp):
388 self.context._clamp = clamp
389
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000390
391
392# The following classes test the behaviour of Decimal according to PEP 327
393
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000394class DecimalExplicitConstructionTest(unittest.TestCase):
395 '''Unit tests for Explicit Construction cases of Decimal.'''
396
397 def test_explicit_empty(self):
398 self.assertEqual(Decimal(), Decimal("0"))
399
400 def test_explicit_from_None(self):
401 self.assertRaises(TypeError, Decimal, None)
402
403 def test_explicit_from_int(self):
404
405 #positive
406 d = Decimal(45)
407 self.assertEqual(str(d), '45')
408
409 #very large positive
410 d = Decimal(500000123)
411 self.assertEqual(str(d), '500000123')
412
413 #negative
414 d = Decimal(-45)
415 self.assertEqual(str(d), '-45')
416
417 #zero
418 d = Decimal(0)
419 self.assertEqual(str(d), '0')
420
421 def test_explicit_from_string(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000422
423 #empty
424 self.assertEqual(str(Decimal('')), 'NaN')
425
426 #int
427 self.assertEqual(str(Decimal('45')), '45')
428
429 #float
430 self.assertEqual(str(Decimal('45.34')), '45.34')
431
432 #engineer notation
433 self.assertEqual(str(Decimal('45e2')), '4.5E+3')
434
435 #just not a number
436 self.assertEqual(str(Decimal('ugly')), 'NaN')
437
Mark Dickinson59bc20b2008-01-12 01:56:00 +0000438 #leading and trailing whitespace permitted
439 self.assertEqual(str(Decimal('1.3E4 \n')), '1.3E+4')
440 self.assertEqual(str(Decimal(' -7.89')), '-7.89')
441
Mark Dickinson8e85ffa2008-03-25 18:47:59 +0000442 #unicode strings should be permitted
443 self.assertEqual(str(Decimal(u'0E-017')), '0E-17')
444 self.assertEqual(str(Decimal(u'45')), '45')
445 self.assertEqual(str(Decimal(u'-Inf')), '-Infinity')
446 self.assertEqual(str(Decimal(u'NaN123')), 'NaN123')
447
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000448 def test_explicit_from_tuples(self):
449
450 #zero
451 d = Decimal( (0, (0,), 0) )
452 self.assertEqual(str(d), '0')
453
454 #int
455 d = Decimal( (1, (4, 5), 0) )
456 self.assertEqual(str(d), '-45')
457
458 #float
459 d = Decimal( (0, (4, 5, 3, 4), -2) )
460 self.assertEqual(str(d), '45.34')
461
462 #weird
463 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
464 self.assertEqual(str(d), '-4.34913534E-17')
465
466 #wrong number of items
467 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1)) )
468
469 #bad sign
470 self.assertRaises(ValueError, Decimal, (8, (4, 3, 4, 9, 1), 2) )
Facundo Batista9b5e2312007-10-19 19:25:57 +0000471 self.assertRaises(ValueError, Decimal, (0., (4, 3, 4, 9, 1), 2) )
472 self.assertRaises(ValueError, Decimal, (Decimal(1), (4, 3, 4, 9, 1), 2))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000473
474 #bad exp
475 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 'wrong!') )
Facundo Batista9b5e2312007-10-19 19:25:57 +0000476 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 0.) )
477 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), '1') )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000478
479 #bad coefficients
480 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, None, 1), 2) )
481 self.assertRaises(ValueError, Decimal, (1, (4, -3, 4, 9, 1), 2) )
Facundo Batista9b5e2312007-10-19 19:25:57 +0000482 self.assertRaises(ValueError, Decimal, (1, (4, 10, 4, 9, 1), 2) )
Facundo Batista72bc54f2007-11-23 17:59:00 +0000483 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 'a', 1), 2) )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000484
Antoine Pitrou6032c252010-03-30 18:49:45 +0000485 def test_explicit_from_bool(self):
486 self.assertIs(bool(Decimal(0)), False)
487 self.assertIs(bool(Decimal(1)), True)
488 self.assertEqual(Decimal(False), Decimal(0))
489 self.assertEqual(Decimal(True), Decimal(1))
490
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000491 def test_explicit_from_Decimal(self):
492
493 #positive
494 d = Decimal(45)
495 e = Decimal(d)
496 self.assertEqual(str(e), '45')
497 self.assertNotEqual(id(d), id(e))
498
499 #very large positive
500 d = Decimal(500000123)
501 e = Decimal(d)
502 self.assertEqual(str(e), '500000123')
503 self.assertNotEqual(id(d), id(e))
504
505 #negative
506 d = Decimal(-45)
507 e = Decimal(d)
508 self.assertEqual(str(e), '-45')
509 self.assertNotEqual(id(d), id(e))
510
511 #zero
512 d = Decimal(0)
513 e = Decimal(d)
514 self.assertEqual(str(e), '0')
515 self.assertNotEqual(id(d), id(e))
516
Raymond Hettingered171ab2010-04-02 18:39:24 +0000517 @requires_IEEE_754
518 def test_explicit_from_float(self):
519 r = Decimal(0.1)
520 self.assertEqual(type(r), Decimal)
521 self.assertEqual(str(r),
522 '0.1000000000000000055511151231257827021181583404541015625')
523 self.assertTrue(Decimal(float('nan')).is_qnan())
524 self.assertTrue(Decimal(float('inf')).is_infinite())
525 self.assertTrue(Decimal(float('-inf')).is_infinite())
526 self.assertEqual(str(Decimal(float('nan'))),
527 str(Decimal('NaN')))
528 self.assertEqual(str(Decimal(float('inf'))),
529 str(Decimal('Infinity')))
530 self.assertEqual(str(Decimal(float('-inf'))),
531 str(Decimal('-Infinity')))
532 self.assertEqual(str(Decimal(float('-0.0'))),
533 str(Decimal('-0')))
534 for i in range(200):
535 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
536 self.assertEqual(x, float(Decimal(x))) # roundtrip
537
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000538 def test_explicit_context_create_decimal(self):
539
540 nc = copy.copy(getcontext())
541 nc.prec = 3
542
543 # empty
Raymond Hettingerfed52962004-07-14 15:41:57 +0000544 d = Decimal()
545 self.assertEqual(str(d), '0')
546 d = nc.create_decimal()
547 self.assertEqual(str(d), '0')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000548
549 # from None
550 self.assertRaises(TypeError, nc.create_decimal, None)
551
552 # from int
553 d = nc.create_decimal(456)
Ezio Melottib0f5adc2010-01-24 16:58:36 +0000554 self.assertIsInstance(d, Decimal)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000555 self.assertEqual(nc.create_decimal(45678),
556 nc.create_decimal('457E+2'))
557
558 # from string
559 d = Decimal('456789')
560 self.assertEqual(str(d), '456789')
561 d = nc.create_decimal('456789')
562 self.assertEqual(str(d), '4.57E+5')
Mark Dickinson59bc20b2008-01-12 01:56:00 +0000563 # leading and trailing whitespace should result in a NaN;
564 # spaces are already checked in Cowlishaw's test-suite, so
565 # here we just check that a trailing newline results in a NaN
566 self.assertEqual(str(nc.create_decimal('3.14\n')), 'NaN')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000567
568 # from tuples
569 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
570 self.assertEqual(str(d), '-4.34913534E-17')
571 d = nc.create_decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
572 self.assertEqual(str(d), '-4.35E-17')
573
574 # from Decimal
575 prevdec = Decimal(500000123)
576 d = Decimal(prevdec)
577 self.assertEqual(str(d), '500000123')
578 d = nc.create_decimal(prevdec)
579 self.assertEqual(str(d), '5.00E+8')
580
Mark Dickinson4326ad82009-08-02 10:59:36 +0000581 def test_unicode_digits(self):
582 test_values = {
583 u'\uff11': '1',
584 u'\u0660.\u0660\u0663\u0667\u0662e-\u0663' : '0.0000372',
585 u'-nan\u0c68\u0c6a\u0c66\u0c66' : '-NaN2400',
586 }
587 for input, expected in test_values.items():
588 self.assertEqual(str(Decimal(input)), expected)
589
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000590
591class DecimalImplicitConstructionTest(unittest.TestCase):
592 '''Unit tests for Implicit Construction cases of Decimal.'''
593
594 def test_implicit_from_None(self):
595 self.assertRaises(TypeError, eval, 'Decimal(5) + None', globals())
596
597 def test_implicit_from_int(self):
598 #normal
599 self.assertEqual(str(Decimal(5) + 45), '50')
600 #exceeding precision
601 self.assertEqual(Decimal(5) + 123456789000, Decimal(123456789000))
602
603 def test_implicit_from_string(self):
604 self.assertRaises(TypeError, eval, 'Decimal(5) + "3"', globals())
605
606 def test_implicit_from_float(self):
607 self.assertRaises(TypeError, eval, 'Decimal(5) + 2.2', globals())
608
609 def test_implicit_from_Decimal(self):
610 self.assertEqual(Decimal(5) + Decimal(45), Decimal(50))
611
Raymond Hettinger267b8682005-03-27 10:47:39 +0000612 def test_rop(self):
613 # Allow other classes to be trained to interact with Decimals
614 class E:
615 def __divmod__(self, other):
616 return 'divmod ' + str(other)
617 def __rdivmod__(self, other):
618 return str(other) + ' rdivmod'
619 def __lt__(self, other):
620 return 'lt ' + str(other)
621 def __gt__(self, other):
622 return 'gt ' + str(other)
623 def __le__(self, other):
624 return 'le ' + str(other)
625 def __ge__(self, other):
626 return 'ge ' + str(other)
627 def __eq__(self, other):
628 return 'eq ' + str(other)
629 def __ne__(self, other):
630 return 'ne ' + str(other)
631
632 self.assertEqual(divmod(E(), Decimal(10)), 'divmod 10')
633 self.assertEqual(divmod(Decimal(10), E()), '10 rdivmod')
634 self.assertEqual(eval('Decimal(10) < E()'), 'gt 10')
635 self.assertEqual(eval('Decimal(10) > E()'), 'lt 10')
636 self.assertEqual(eval('Decimal(10) <= E()'), 'ge 10')
637 self.assertEqual(eval('Decimal(10) >= E()'), 'le 10')
638 self.assertEqual(eval('Decimal(10) == E()'), 'eq 10')
639 self.assertEqual(eval('Decimal(10) != E()'), 'ne 10')
640
641 # insert operator methods and then exercise them
Georg Brandl96c3f7f2006-03-28 08:06:35 +0000642 oplist = [
643 ('+', '__add__', '__radd__'),
644 ('-', '__sub__', '__rsub__'),
645 ('*', '__mul__', '__rmul__'),
646 ('%', '__mod__', '__rmod__'),
647 ('//', '__floordiv__', '__rfloordiv__'),
648 ('**', '__pow__', '__rpow__')
649 ]
Florent Xicluna8f43cec2010-03-21 10:51:40 +0000650 with check_py3k_warnings():
651 if 1 / 2 == 0:
652 # testing with classic division, so add __div__
653 oplist.append(('/', '__div__', '__rdiv__'))
654 else:
655 # testing with -Qnew, so add __truediv__
656 oplist.append(('/', '__truediv__', '__rtruediv__'))
Anthony Baxter4ef3a232006-03-30 12:59:11 +0000657
Georg Brandl96c3f7f2006-03-28 08:06:35 +0000658 for sym, lop, rop in oplist:
Raymond Hettinger267b8682005-03-27 10:47:39 +0000659 setattr(E, lop, lambda self, other: 'str' + lop + str(other))
660 setattr(E, rop, lambda self, other: str(other) + rop + 'str')
661 self.assertEqual(eval('E()' + sym + 'Decimal(10)'),
662 'str' + lop + '10')
663 self.assertEqual(eval('Decimal(10)' + sym + 'E()'),
664 '10' + rop + 'str')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000665
Mark Dickinson277859d2009-03-17 23:03:46 +0000666
Mark Dickinson1ddf1d82008-02-29 02:16:37 +0000667class DecimalFormatTest(unittest.TestCase):
668 '''Unit tests for the format function.'''
669 def test_formatting(self):
670 # triples giving a format, a Decimal, and the expected result
671 test_values = [
672 ('e', '0E-15', '0e-15'),
673 ('e', '2.3E-15', '2.3e-15'),
674 ('e', '2.30E+2', '2.30e+2'), # preserve significant zeros
675 ('e', '2.30000E-15', '2.30000e-15'),
676 ('e', '1.23456789123456789e40', '1.23456789123456789e+40'),
677 ('e', '1.5', '1.5e+0'),
678 ('e', '0.15', '1.5e-1'),
679 ('e', '0.015', '1.5e-2'),
680 ('e', '0.0000000000015', '1.5e-12'),
681 ('e', '15.0', '1.50e+1'),
682 ('e', '-15', '-1.5e+1'),
683 ('e', '0', '0e+0'),
684 ('e', '0E1', '0e+1'),
685 ('e', '0.0', '0e-1'),
686 ('e', '0.00', '0e-2'),
687 ('.6e', '0E-15', '0.000000e-9'),
688 ('.6e', '0', '0.000000e+6'),
689 ('.6e', '9.999999', '9.999999e+0'),
690 ('.6e', '9.9999999', '1.000000e+1'),
691 ('.6e', '-1.23e5', '-1.230000e+5'),
692 ('.6e', '1.23456789e-3', '1.234568e-3'),
693 ('f', '0', '0'),
694 ('f', '0.0', '0.0'),
695 ('f', '0E-2', '0.00'),
696 ('f', '0.00E-8', '0.0000000000'),
697 ('f', '0E1', '0'), # loses exponent information
698 ('f', '3.2E1', '32'),
699 ('f', '3.2E2', '320'),
700 ('f', '3.20E2', '320'),
701 ('f', '3.200E2', '320.0'),
702 ('f', '3.2E-6', '0.0000032'),
703 ('.6f', '0E-15', '0.000000'), # all zeros treated equally
704 ('.6f', '0E1', '0.000000'),
705 ('.6f', '0', '0.000000'),
706 ('.0f', '0', '0'), # no decimal point
707 ('.0f', '0e-2', '0'),
708 ('.0f', '3.14159265', '3'),
709 ('.1f', '3.14159265', '3.1'),
710 ('.4f', '3.14159265', '3.1416'),
711 ('.6f', '3.14159265', '3.141593'),
712 ('.7f', '3.14159265', '3.1415926'), # round-half-even!
713 ('.8f', '3.14159265', '3.14159265'),
714 ('.9f', '3.14159265', '3.141592650'),
715
716 ('g', '0', '0'),
717 ('g', '0.0', '0.0'),
718 ('g', '0E1', '0e+1'),
719 ('G', '0E1', '0E+1'),
720 ('g', '0E-5', '0.00000'),
721 ('g', '0E-6', '0.000000'),
722 ('g', '0E-7', '0e-7'),
723 ('g', '-0E2', '-0e+2'),
724 ('.0g', '3.14159265', '3'), # 0 sig fig -> 1 sig fig
725 ('.1g', '3.14159265', '3'),
726 ('.2g', '3.14159265', '3.1'),
727 ('.5g', '3.14159265', '3.1416'),
728 ('.7g', '3.14159265', '3.141593'),
729 ('.8g', '3.14159265', '3.1415926'), # round-half-even!
730 ('.9g', '3.14159265', '3.14159265'),
731 ('.10g', '3.14159265', '3.14159265'), # don't pad
732
733 ('%', '0E1', '0%'),
734 ('%', '0E0', '0%'),
735 ('%', '0E-1', '0%'),
736 ('%', '0E-2', '0%'),
737 ('%', '0E-3', '0.0%'),
738 ('%', '0E-4', '0.00%'),
739
740 ('.3%', '0', '0.000%'), # all zeros treated equally
741 ('.3%', '0E10', '0.000%'),
742 ('.3%', '0E-10', '0.000%'),
743 ('.3%', '2.34', '234.000%'),
744 ('.3%', '1.234567', '123.457%'),
745 ('.0%', '1.23', '123%'),
746
747 ('e', 'NaN', 'NaN'),
748 ('f', '-NaN123', '-NaN123'),
749 ('+g', 'NaN456', '+NaN456'),
750 ('.3e', 'Inf', 'Infinity'),
751 ('.16f', '-Inf', '-Infinity'),
752 ('.0g', '-sNaN', '-sNaN'),
753
754 ('', '1.00', '1.00'),
Mark Dickinsonb065e522009-03-17 18:01:03 +0000755
Mark Dickinson277859d2009-03-17 23:03:46 +0000756 # test alignment and padding
Mark Dickinson5cfa8042009-09-08 20:20:19 +0000757 ('6', '123', ' 123'),
Mark Dickinsonb065e522009-03-17 18:01:03 +0000758 ('<6', '123', '123 '),
759 ('>6', '123', ' 123'),
760 ('^6', '123', ' 123 '),
761 ('=+6', '123', '+ 123'),
Mark Dickinson277859d2009-03-17 23:03:46 +0000762 ('#<10', 'NaN', 'NaN#######'),
763 ('#<10', '-4.3', '-4.3######'),
764 ('#<+10', '0.0130', '+0.0130###'),
765 ('#< 10', '0.0130', ' 0.0130###'),
766 ('@>10', '-Inf', '@-Infinity'),
767 ('#>5', '-Inf', '-Infinity'),
768 ('?^5', '123', '?123?'),
769 ('%^6', '123', '%123%%'),
770 (' ^6', '-45.6', '-45.6 '),
771 ('/=10', '-45.6', '-/////45.6'),
772 ('/=+10', '45.6', '+/////45.6'),
773 ('/= 10', '45.6', ' /////45.6'),
774
775 # thousands separator
776 (',', '1234567', '1,234,567'),
777 (',', '123456', '123,456'),
778 (',', '12345', '12,345'),
779 (',', '1234', '1,234'),
780 (',', '123', '123'),
781 (',', '12', '12'),
782 (',', '1', '1'),
783 (',', '0', '0'),
784 (',', '-1234567', '-1,234,567'),
785 (',', '-123456', '-123,456'),
786 ('7,', '123456', '123,456'),
Mark Dickinson5cfa8042009-09-08 20:20:19 +0000787 ('8,', '123456', ' 123,456'),
Mark Dickinson277859d2009-03-17 23:03:46 +0000788 ('08,', '123456', '0,123,456'), # special case: extra 0 needed
789 ('+08,', '123456', '+123,456'), # but not if there's a sign
790 (' 08,', '123456', ' 123,456'),
791 ('08,', '-123456', '-123,456'),
792 ('+09,', '123456', '+0,123,456'),
793 # ... with fractional part...
794 ('07,', '1234.56', '1,234.56'),
795 ('08,', '1234.56', '1,234.56'),
796 ('09,', '1234.56', '01,234.56'),
797 ('010,', '1234.56', '001,234.56'),
798 ('011,', '1234.56', '0,001,234.56'),
799 ('012,', '1234.56', '0,001,234.56'),
800 ('08,.1f', '1234.5', '01,234.5'),
801 # no thousands separators in fraction part
802 (',', '1.23456789', '1.23456789'),
803 (',%', '123.456789', '12,345.6789%'),
804 (',e', '123456', '1.23456e+5'),
805 (',E', '123456', '1.23456E+5'),
Mark Dickinson491ea552009-09-07 16:17:41 +0000806
807 # issue 6850
808 ('a=-7.0', '0.12345', 'aaaa0.1'),
Mark Dickinson1ddf1d82008-02-29 02:16:37 +0000809 ]
810 for fmt, d, result in test_values:
811 self.assertEqual(format(Decimal(d), fmt), result)
812
Mark Dickinson277859d2009-03-17 23:03:46 +0000813 def test_n_format(self):
814 try:
815 from locale import CHAR_MAX
816 except ImportError:
817 return
818
819 # Set up some localeconv-like dictionaries
820 en_US = {
821 'decimal_point' : '.',
822 'grouping' : [3, 3, 0],
823 'thousands_sep': ','
824 }
825
826 fr_FR = {
827 'decimal_point' : ',',
828 'grouping' : [CHAR_MAX],
829 'thousands_sep' : ''
830 }
831
832 ru_RU = {
833 'decimal_point' : ',',
834 'grouping' : [3, 3, 0],
835 'thousands_sep' : ' '
836 }
837
838 crazy = {
839 'decimal_point' : '&',
840 'grouping' : [1, 4, 2, CHAR_MAX],
841 'thousands_sep' : '-'
842 }
843
844
845 def get_fmt(x, locale, fmt='n'):
846 return Decimal.__format__(Decimal(x), fmt, _localeconv=locale)
847
848 self.assertEqual(get_fmt(Decimal('12.7'), en_US), '12.7')
849 self.assertEqual(get_fmt(Decimal('12.7'), fr_FR), '12,7')
850 self.assertEqual(get_fmt(Decimal('12.7'), ru_RU), '12,7')
851 self.assertEqual(get_fmt(Decimal('12.7'), crazy), '1-2&7')
852
853 self.assertEqual(get_fmt(123456789, en_US), '123,456,789')
854 self.assertEqual(get_fmt(123456789, fr_FR), '123456789')
855 self.assertEqual(get_fmt(123456789, ru_RU), '123 456 789')
856 self.assertEqual(get_fmt(1234567890123, crazy), '123456-78-9012-3')
857
858 self.assertEqual(get_fmt(123456789, en_US, '.6n'), '1.23457e+8')
859 self.assertEqual(get_fmt(123456789, fr_FR, '.6n'), '1,23457e+8')
860 self.assertEqual(get_fmt(123456789, ru_RU, '.6n'), '1,23457e+8')
861 self.assertEqual(get_fmt(123456789, crazy, '.6n'), '1&23457e+8')
862
Mark Dickinsonb14514a2009-03-18 08:22:51 +0000863 # zero padding
864 self.assertEqual(get_fmt(1234, fr_FR, '03n'), '1234')
865 self.assertEqual(get_fmt(1234, fr_FR, '04n'), '1234')
866 self.assertEqual(get_fmt(1234, fr_FR, '05n'), '01234')
867 self.assertEqual(get_fmt(1234, fr_FR, '06n'), '001234')
868
869 self.assertEqual(get_fmt(12345, en_US, '05n'), '12,345')
870 self.assertEqual(get_fmt(12345, en_US, '06n'), '12,345')
871 self.assertEqual(get_fmt(12345, en_US, '07n'), '012,345')
872 self.assertEqual(get_fmt(12345, en_US, '08n'), '0,012,345')
873 self.assertEqual(get_fmt(12345, en_US, '09n'), '0,012,345')
874 self.assertEqual(get_fmt(12345, en_US, '010n'), '00,012,345')
875
876 self.assertEqual(get_fmt(123456, crazy, '06n'), '1-2345-6')
877 self.assertEqual(get_fmt(123456, crazy, '07n'), '1-2345-6')
878 self.assertEqual(get_fmt(123456, crazy, '08n'), '1-2345-6')
879 self.assertEqual(get_fmt(123456, crazy, '09n'), '01-2345-6')
880 self.assertEqual(get_fmt(123456, crazy, '010n'), '0-01-2345-6')
881 self.assertEqual(get_fmt(123456, crazy, '011n'), '0-01-2345-6')
882 self.assertEqual(get_fmt(123456, crazy, '012n'), '00-01-2345-6')
883 self.assertEqual(get_fmt(123456, crazy, '013n'), '000-01-2345-6')
884
Mark Dickinson277859d2009-03-17 23:03:46 +0000885
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000886class DecimalArithmeticOperatorsTest(unittest.TestCase):
887 '''Unit tests for all arithmetic operators, binary and unary.'''
888
889 def test_addition(self):
890
891 d1 = Decimal('-11.1')
892 d2 = Decimal('22.2')
893
894 #two Decimals
895 self.assertEqual(d1+d2, Decimal('11.1'))
896 self.assertEqual(d2+d1, Decimal('11.1'))
897
898 #with other type, left
899 c = d1 + 5
900 self.assertEqual(c, Decimal('-6.1'))
901 self.assertEqual(type(c), type(d1))
902
903 #with other type, right
904 c = 5 + d1
905 self.assertEqual(c, Decimal('-6.1'))
906 self.assertEqual(type(c), type(d1))
907
908 #inline with decimal
909 d1 += d2
910 self.assertEqual(d1, Decimal('11.1'))
911
912 #inline with other type
913 d1 += 5
914 self.assertEqual(d1, Decimal('16.1'))
915
916 def test_subtraction(self):
917
918 d1 = Decimal('-11.1')
919 d2 = Decimal('22.2')
920
921 #two Decimals
922 self.assertEqual(d1-d2, Decimal('-33.3'))
923 self.assertEqual(d2-d1, Decimal('33.3'))
924
925 #with other type, left
926 c = d1 - 5
927 self.assertEqual(c, Decimal('-16.1'))
928 self.assertEqual(type(c), type(d1))
929
930 #with other type, right
931 c = 5 - d1
932 self.assertEqual(c, Decimal('16.1'))
933 self.assertEqual(type(c), type(d1))
934
935 #inline with decimal
936 d1 -= d2
937 self.assertEqual(d1, Decimal('-33.3'))
938
939 #inline with other type
940 d1 -= 5
941 self.assertEqual(d1, Decimal('-38.3'))
942
943 def test_multiplication(self):
944
945 d1 = Decimal('-5')
946 d2 = Decimal('3')
947
948 #two Decimals
949 self.assertEqual(d1*d2, Decimal('-15'))
950 self.assertEqual(d2*d1, Decimal('-15'))
951
952 #with other type, left
953 c = d1 * 5
954 self.assertEqual(c, Decimal('-25'))
955 self.assertEqual(type(c), type(d1))
956
957 #with other type, right
958 c = 5 * d1
959 self.assertEqual(c, Decimal('-25'))
960 self.assertEqual(type(c), type(d1))
961
962 #inline with decimal
963 d1 *= d2
964 self.assertEqual(d1, Decimal('-15'))
965
966 #inline with other type
967 d1 *= 5
968 self.assertEqual(d1, Decimal('-75'))
969
970 def test_division(self):
971
972 d1 = Decimal('-5')
973 d2 = Decimal('2')
974
975 #two Decimals
976 self.assertEqual(d1/d2, Decimal('-2.5'))
977 self.assertEqual(d2/d1, Decimal('-0.4'))
978
979 #with other type, left
980 c = d1 / 4
981 self.assertEqual(c, Decimal('-1.25'))
982 self.assertEqual(type(c), type(d1))
983
984 #with other type, right
985 c = 4 / d1
986 self.assertEqual(c, Decimal('-0.8'))
987 self.assertEqual(type(c), type(d1))
988
989 #inline with decimal
990 d1 /= d2
991 self.assertEqual(d1, Decimal('-2.5'))
992
993 #inline with other type
994 d1 /= 4
995 self.assertEqual(d1, Decimal('-0.625'))
996
997 def test_floor_division(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000998
999 d1 = Decimal('5')
1000 d2 = Decimal('2')
1001
1002 #two Decimals
1003 self.assertEqual(d1//d2, Decimal('2'))
1004 self.assertEqual(d2//d1, Decimal('0'))
1005
1006 #with other type, left
1007 c = d1 // 4
1008 self.assertEqual(c, Decimal('1'))
1009 self.assertEqual(type(c), type(d1))
1010
1011 #with other type, right
1012 c = 7 // d1
1013 self.assertEqual(c, Decimal('1'))
1014 self.assertEqual(type(c), type(d1))
1015
1016 #inline with decimal
1017 d1 //= d2
1018 self.assertEqual(d1, Decimal('2'))
1019
1020 #inline with other type
1021 d1 //= 2
1022 self.assertEqual(d1, Decimal('1'))
1023
1024 def test_powering(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001025
1026 d1 = Decimal('5')
1027 d2 = Decimal('2')
1028
1029 #two Decimals
1030 self.assertEqual(d1**d2, Decimal('25'))
1031 self.assertEqual(d2**d1, Decimal('32'))
1032
1033 #with other type, left
1034 c = d1 ** 4
1035 self.assertEqual(c, Decimal('625'))
1036 self.assertEqual(type(c), type(d1))
1037
1038 #with other type, right
1039 c = 7 ** d1
1040 self.assertEqual(c, Decimal('16807'))
1041 self.assertEqual(type(c), type(d1))
1042
1043 #inline with decimal
1044 d1 **= d2
1045 self.assertEqual(d1, Decimal('25'))
1046
1047 #inline with other type
1048 d1 **= 4
1049 self.assertEqual(d1, Decimal('390625'))
1050
1051 def test_module(self):
1052
1053 d1 = Decimal('5')
1054 d2 = Decimal('2')
1055
1056 #two Decimals
1057 self.assertEqual(d1%d2, Decimal('1'))
1058 self.assertEqual(d2%d1, Decimal('2'))
1059
1060 #with other type, left
1061 c = d1 % 4
1062 self.assertEqual(c, Decimal('1'))
1063 self.assertEqual(type(c), type(d1))
1064
1065 #with other type, right
1066 c = 7 % d1
1067 self.assertEqual(c, Decimal('2'))
1068 self.assertEqual(type(c), type(d1))
1069
1070 #inline with decimal
1071 d1 %= d2
1072 self.assertEqual(d1, Decimal('1'))
1073
1074 #inline with other type
1075 d1 %= 4
1076 self.assertEqual(d1, Decimal('1'))
1077
1078 def test_floor_div_module(self):
1079
1080 d1 = Decimal('5')
1081 d2 = Decimal('2')
1082
1083 #two Decimals
1084 (p, q) = divmod(d1, d2)
1085 self.assertEqual(p, Decimal('2'))
1086 self.assertEqual(q, Decimal('1'))
1087 self.assertEqual(type(p), type(d1))
1088 self.assertEqual(type(q), type(d1))
1089
1090 #with other type, left
1091 (p, q) = divmod(d1, 4)
1092 self.assertEqual(p, Decimal('1'))
1093 self.assertEqual(q, Decimal('1'))
1094 self.assertEqual(type(p), type(d1))
1095 self.assertEqual(type(q), type(d1))
1096
1097 #with other type, right
1098 (p, q) = divmod(7, d1)
1099 self.assertEqual(p, Decimal('1'))
1100 self.assertEqual(q, Decimal('2'))
1101 self.assertEqual(type(p), type(d1))
1102 self.assertEqual(type(q), type(d1))
1103
1104 def test_unary_operators(self):
1105 self.assertEqual(+Decimal(45), Decimal(+45)) # +
1106 self.assertEqual(-Decimal(45), Decimal(-45)) # -
1107 self.assertEqual(abs(Decimal(45)), abs(Decimal(-45))) # abs
1108
Mark Dickinson2fc92632008-02-06 22:10:50 +00001109 def test_nan_comparisons(self):
Mark Dickinsone096e822010-04-02 10:17:07 +00001110 # comparisons involving signaling nans signal InvalidOperation
1111
1112 # order comparisons (<, <=, >, >=) involving only quiet nans
1113 # also signal InvalidOperation
1114
1115 # equality comparisons (==, !=) involving only quiet nans
1116 # don't signal, but return False or True respectively.
1117
Mark Dickinson2fc92632008-02-06 22:10:50 +00001118 n = Decimal('NaN')
1119 s = Decimal('sNaN')
1120 i = Decimal('Inf')
1121 f = Decimal('2')
Mark Dickinsone096e822010-04-02 10:17:07 +00001122
1123 qnan_pairs = (n, n), (n, i), (i, n), (n, f), (f, n)
1124 snan_pairs = (s, n), (n, s), (s, i), (i, s), (s, f), (f, s), (s, s)
1125 order_ops = operator.lt, operator.le, operator.gt, operator.ge
1126 equality_ops = operator.eq, operator.ne
1127
1128 # results when InvalidOperation is not trapped
1129 for x, y in qnan_pairs + snan_pairs:
1130 for op in order_ops + equality_ops:
1131 got = op(x, y)
1132 expected = True if op is operator.ne else False
1133 self.assertIs(expected, got,
1134 "expected {0!r} for operator.{1}({2!r}, {3!r}); "
1135 "got {4!r}".format(
1136 expected, op.__name__, x, y, got))
1137
1138 # repeat the above, but this time trap the InvalidOperation
1139 with localcontext() as ctx:
1140 ctx.traps[InvalidOperation] = 1
1141
1142 for x, y in qnan_pairs:
1143 for op in equality_ops:
1144 got = op(x, y)
1145 expected = True if op is operator.ne else False
1146 self.assertIs(expected, got,
1147 "expected {0!r} for "
1148 "operator.{1}({2!r}, {3!r}); "
1149 "got {4!r}".format(
1150 expected, op.__name__, x, y, got))
1151
1152 for x, y in snan_pairs:
1153 for op in equality_ops:
1154 self.assertRaises(InvalidOperation, operator.eq, x, y)
1155 self.assertRaises(InvalidOperation, operator.ne, x, y)
1156
1157 for x, y in qnan_pairs + snan_pairs:
1158 for op in order_ops:
1159 self.assertRaises(InvalidOperation, op, x, y)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001160
Mark Dickinson6d8effb2010-02-18 14:27:02 +00001161 def test_copy_sign(self):
1162 d = Decimal(1).copy_sign(Decimal(-2))
1163
1164 self.assertEqual(Decimal(1).copy_sign(-2), d)
1165 self.assertRaises(TypeError, Decimal(1).copy_sign, '-2')
1166
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001167# The following are two functions used to test threading in the next class
1168
1169def thfunc1(cls):
1170 d1 = Decimal(1)
1171 d3 = Decimal(3)
Facundo Batista64156672008-03-22 02:45:37 +00001172 test1 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001173 cls.synchro.wait()
Facundo Batista64156672008-03-22 02:45:37 +00001174 test2 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001175 cls.finish1.set()
Facundo Batista64156672008-03-22 02:45:37 +00001176
Facundo Batistaee340e52008-05-02 17:39:00 +00001177 cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
1178 cls.assertEqual(test2, Decimal('0.3333333333333333333333333333'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001179 return
1180
1181def thfunc2(cls):
1182 d1 = Decimal(1)
1183 d3 = Decimal(3)
Facundo Batista64156672008-03-22 02:45:37 +00001184 test1 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001185 thiscontext = getcontext()
1186 thiscontext.prec = 18
Facundo Batista64156672008-03-22 02:45:37 +00001187 test2 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001188 cls.synchro.set()
1189 cls.finish2.set()
Facundo Batista64156672008-03-22 02:45:37 +00001190
Facundo Batistaee340e52008-05-02 17:39:00 +00001191 cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
Facundo Batista64156672008-03-22 02:45:37 +00001192 cls.assertEqual(test2, Decimal('0.333333333333333333'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001193 return
1194
1195
1196class DecimalUseOfContextTest(unittest.TestCase):
1197 '''Unit tests for Use of Context cases in Decimal.'''
1198
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001199 try:
1200 import threading
1201 except ImportError:
1202 threading = None
1203
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001204 # Take care executing this test from IDLE, there's an issue in threading
1205 # that hangs IDLE and I couldn't find it
1206
1207 def test_threading(self):
1208 #Test the "threading isolation" of a Context.
1209
1210 self.synchro = threading.Event()
1211 self.finish1 = threading.Event()
1212 self.finish2 = threading.Event()
1213
1214 th1 = threading.Thread(target=thfunc1, args=(self,))
1215 th2 = threading.Thread(target=thfunc2, args=(self,))
1216
1217 th1.start()
1218 th2.start()
1219
1220 self.finish1.wait()
Thomas Woutersb3e6e8c2007-09-19 17:27:29 +00001221 self.finish2.wait()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001222 return
1223
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001224 if threading is None:
1225 del test_threading
1226
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001227
1228class DecimalUsabilityTest(unittest.TestCase):
1229 '''Unit tests for Usability cases of Decimal.'''
1230
1231 def test_comparison_operators(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001232
1233 da = Decimal('23.42')
1234 db = Decimal('23.42')
1235 dc = Decimal('45')
1236
1237 #two Decimals
Ezio Melotti856a3be2010-04-03 14:51:00 +00001238 self.assertGreater(dc, da)
1239 self.assertGreaterEqual(dc, da)
1240 self.assertLess(da, dc)
1241 self.assertLessEqual(da, dc)
1242 self.assertEqual(da, db)
1243 self.assertNotEqual(da, dc)
1244 self.assertLessEqual(da, db)
1245 self.assertGreaterEqual(da, db)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001246 self.assertEqual(cmp(dc,da), 1)
1247 self.assertEqual(cmp(da,dc), -1)
1248 self.assertEqual(cmp(da,db), 0)
1249
1250 #a Decimal and an int
Ezio Melotti856a3be2010-04-03 14:51:00 +00001251 self.assertGreater(dc, 23)
1252 self.assertLess(23, dc)
1253 self.assertEqual(dc, 45)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001254 self.assertEqual(cmp(dc,23), 1)
1255 self.assertEqual(cmp(23,dc), -1)
1256 self.assertEqual(cmp(dc,45), 0)
1257
1258 #a Decimal and uncomparable
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001259 self.assertNotEqual(da, 'ugly')
1260 self.assertNotEqual(da, 32.7)
1261 self.assertNotEqual(da, object())
1262 self.assertNotEqual(da, object)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001263
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001264 # sortable
1265 a = map(Decimal, xrange(100))
1266 b = a[:]
1267 random.shuffle(a)
1268 a.sort()
1269 self.assertEqual(a, b)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001270
Facundo Batista353750c2007-09-13 18:13:15 +00001271 # with None
Florent Xicluna8f43cec2010-03-21 10:51:40 +00001272 with check_py3k_warnings():
1273 self.assertFalse(Decimal(1) < None)
1274 self.assertTrue(Decimal(1) > None)
Facundo Batista353750c2007-09-13 18:13:15 +00001275
Mark Dickinson99d80962010-04-02 08:53:22 +00001276 def test_decimal_float_comparison(self):
1277 da = Decimal('0.25')
1278 db = Decimal('3.0')
Ezio Melotti856a3be2010-04-03 14:51:00 +00001279 self.assertLess(da, 3.0)
1280 self.assertLessEqual(da, 3.0)
1281 self.assertGreater(db, 0.25)
1282 self.assertGreaterEqual(db, 0.25)
1283 self.assertNotEqual(da, 1.5)
1284 self.assertEqual(da, 0.25)
1285 self.assertGreater(3.0, da)
1286 self.assertGreaterEqual(3.0, da)
1287 self.assertLess(0.25, db)
1288 self.assertLessEqual(0.25, db)
1289 self.assertNotEqual(0.25, db)
1290 self.assertEqual(3.0, db)
1291 self.assertNotEqual(0.1, Decimal('0.1'))
Mark Dickinson99d80962010-04-02 08:53:22 +00001292
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001293 def test_copy_and_deepcopy_methods(self):
1294 d = Decimal('43.24')
1295 c = copy.copy(d)
1296 self.assertEqual(id(c), id(d))
1297 dc = copy.deepcopy(d)
1298 self.assertEqual(id(dc), id(d))
1299
1300 def test_hash_method(self):
1301 #just that it's hashable
1302 hash(Decimal(23))
Mark Dickinsonf3eeca12010-04-02 10:35:12 +00001303 hash(Decimal('Infinity'))
1304 hash(Decimal('-Infinity'))
1305 hash(Decimal('nan123'))
1306 hash(Decimal('-NaN'))
Facundo Batista8c202442007-09-19 17:53:25 +00001307
1308 test_values = [Decimal(sign*(2**m + n))
1309 for m in [0, 14, 15, 16, 17, 30, 31,
1310 32, 33, 62, 63, 64, 65, 66]
1311 for n in range(-10, 10)
1312 for sign in [-1, 1]]
1313 test_values.extend([
1314 Decimal("-0"), # zeros
1315 Decimal("0.00"),
1316 Decimal("-0.000"),
1317 Decimal("0E10"),
1318 Decimal("-0E12"),
1319 Decimal("10.0"), # negative exponent
1320 Decimal("-23.00000"),
1321 Decimal("1230E100"), # positive exponent
1322 Decimal("-4.5678E50"),
1323 # a value for which hash(n) != hash(n % (2**64-1))
1324 # in Python pre-2.6
1325 Decimal(2**64 + 2**32 - 1),
1326 # selection of values which fail with the old (before
1327 # version 2.6) long.__hash__
1328 Decimal("1.634E100"),
1329 Decimal("90.697E100"),
1330 Decimal("188.83E100"),
1331 Decimal("1652.9E100"),
1332 Decimal("56531E100"),
1333 ])
1334
1335 # check that hash(d) == hash(int(d)) for integral values
1336 for value in test_values:
1337 self.assertEqual(hash(value), hash(int(value)))
1338
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001339 #the same hash that to an int
1340 self.assertEqual(hash(Decimal(23)), hash(23))
Mark Dickinsonf3eeca12010-04-02 10:35:12 +00001341 self.assertRaises(TypeError, hash, Decimal('sNaN'))
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001342 self.assertTrue(hash(Decimal('Inf')))
1343 self.assertTrue(hash(Decimal('-Inf')))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001344
Mark Dickinson99d80962010-04-02 08:53:22 +00001345 # check that the hashes of a Decimal float match when they
1346 # represent exactly the same values
1347 test_strings = ['inf', '-Inf', '0.0', '-.0e1',
1348 '34.0', '2.5', '112390.625', '-0.515625']
1349 for s in test_strings:
1350 f = float(s)
1351 d = Decimal(s)
1352 self.assertEqual(hash(f), hash(d))
1353
Facundo Batista52b25792008-01-08 12:25:20 +00001354 # check that the value of the hash doesn't depend on the
1355 # current context (issue #1757)
1356 c = getcontext()
1357 old_precision = c.prec
1358 x = Decimal("123456789.1")
1359
1360 c.prec = 6
1361 h1 = hash(x)
1362 c.prec = 10
1363 h2 = hash(x)
1364 c.prec = 16
1365 h3 = hash(x)
1366
1367 self.assertEqual(h1, h2)
1368 self.assertEqual(h1, h3)
1369 c.prec = old_precision
1370
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001371 def test_min_and_max_methods(self):
1372
1373 d1 = Decimal('15.32')
1374 d2 = Decimal('28.5')
1375 l1 = 15
1376 l2 = 28
1377
1378 #between Decimals
Ezio Melotti856a3be2010-04-03 14:51:00 +00001379 self.assertIs(min(d1,d2), d1)
1380 self.assertIs(min(d2,d1), d1)
1381 self.assertIs(max(d1,d2), d2)
1382 self.assertIs(max(d2,d1), d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001383
1384 #between Decimal and long
Ezio Melotti856a3be2010-04-03 14:51:00 +00001385 self.assertIs(min(d1,l2), d1)
1386 self.assertIs(min(l2,d1), d1)
1387 self.assertIs(max(l1,d2), d2)
1388 self.assertIs(max(d2,l1), d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001389
1390 def test_as_nonzero(self):
1391 #as false
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001392 self.assertFalse(Decimal(0))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001393 #as true
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001394 self.assertTrue(Decimal('0.372'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001395
1396 def test_tostring_methods(self):
1397 #Test str and repr methods.
1398
1399 d = Decimal('15.32')
1400 self.assertEqual(str(d), '15.32') # str
Raymond Hettingerabe32372008-02-14 02:41:22 +00001401 self.assertEqual(repr(d), "Decimal('15.32')") # repr
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001402
Mark Dickinson8e85ffa2008-03-25 18:47:59 +00001403 # result type of string methods should be str, not unicode
1404 unicode_inputs = [u'123.4', u'0.5E2', u'Infinity', u'sNaN',
1405 u'-0.0E100', u'-NaN001', u'-Inf']
1406
1407 for u in unicode_inputs:
1408 d = Decimal(u)
1409 self.assertEqual(type(str(d)), str)
1410 self.assertEqual(type(repr(d)), str)
1411 self.assertEqual(type(d.to_eng_string()), str)
1412
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001413 def test_tonum_methods(self):
1414 #Test float, int and long methods.
1415
1416 d1 = Decimal('66')
1417 d2 = Decimal('15.32')
1418
1419 #int
1420 self.assertEqual(int(d1), 66)
1421 self.assertEqual(int(d2), 15)
1422
1423 #long
1424 self.assertEqual(long(d1), 66)
1425 self.assertEqual(long(d2), 15)
1426
1427 #float
1428 self.assertEqual(float(d1), 66)
1429 self.assertEqual(float(d2), 15.32)
1430
1431 def test_eval_round_trip(self):
1432
1433 #with zero
1434 d = Decimal( (0, (0,), 0) )
1435 self.assertEqual(d, eval(repr(d)))
1436
1437 #int
1438 d = Decimal( (1, (4, 5), 0) )
1439 self.assertEqual(d, eval(repr(d)))
1440
1441 #float
1442 d = Decimal( (0, (4, 5, 3, 4), -2) )
1443 self.assertEqual(d, eval(repr(d)))
1444
1445 #weird
1446 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1447 self.assertEqual(d, eval(repr(d)))
1448
1449 def test_as_tuple(self):
1450
1451 #with zero
1452 d = Decimal(0)
1453 self.assertEqual(d.as_tuple(), (0, (0,), 0) )
1454
1455 #int
1456 d = Decimal(-45)
1457 self.assertEqual(d.as_tuple(), (1, (4, 5), 0) )
1458
1459 #complicated string
1460 d = Decimal("-4.34913534E-17")
1461 self.assertEqual(d.as_tuple(), (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1462
1463 #inf
1464 d = Decimal("Infinity")
1465 self.assertEqual(d.as_tuple(), (0, (0,), 'F') )
1466
Facundo Batista9b5e2312007-10-19 19:25:57 +00001467 #leading zeros in coefficient should be stripped
1468 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), -2) )
1469 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), -2) )
1470 d = Decimal( (1, (0, 0, 0), 37) )
1471 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1472 d = Decimal( (1, (), 37) )
1473 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1474
1475 #leading zeros in NaN diagnostic info should be stripped
1476 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), 'n') )
1477 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), 'n') )
1478 d = Decimal( (1, (0, 0, 0), 'N') )
1479 self.assertEqual(d.as_tuple(), (1, (), 'N') )
1480 d = Decimal( (1, (), 'n') )
1481 self.assertEqual(d.as_tuple(), (1, (), 'n') )
1482
1483 #coefficient in infinity should be ignored
1484 d = Decimal( (0, (4, 5, 3, 4), 'F') )
1485 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
1486 d = Decimal( (1, (0, 2, 7, 1), 'F') )
1487 self.assertEqual(d.as_tuple(), (1, (0,), 'F'))
1488
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001489 def test_immutability_operations(self):
1490 # Do operations and check that it didn't change change internal objects.
1491
1492 d1 = Decimal('-25e55')
1493 b1 = Decimal('-25e55')
Facundo Batista353750c2007-09-13 18:13:15 +00001494 d2 = Decimal('33e+33')
1495 b2 = Decimal('33e+33')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001496
1497 def checkSameDec(operation, useOther=False):
1498 if useOther:
1499 eval("d1." + operation + "(d2)")
1500 self.assertEqual(d1._sign, b1._sign)
1501 self.assertEqual(d1._int, b1._int)
1502 self.assertEqual(d1._exp, b1._exp)
1503 self.assertEqual(d2._sign, b2._sign)
1504 self.assertEqual(d2._int, b2._int)
1505 self.assertEqual(d2._exp, b2._exp)
1506 else:
1507 eval("d1." + operation + "()")
1508 self.assertEqual(d1._sign, b1._sign)
1509 self.assertEqual(d1._int, b1._int)
1510 self.assertEqual(d1._exp, b1._exp)
1511 return
1512
1513 Decimal(d1)
1514 self.assertEqual(d1._sign, b1._sign)
1515 self.assertEqual(d1._int, b1._int)
1516 self.assertEqual(d1._exp, b1._exp)
1517
1518 checkSameDec("__abs__")
1519 checkSameDec("__add__", True)
1520 checkSameDec("__div__", True)
1521 checkSameDec("__divmod__", True)
Mark Dickinson2fc92632008-02-06 22:10:50 +00001522 checkSameDec("__eq__", True)
1523 checkSameDec("__ne__", True)
1524 checkSameDec("__le__", True)
1525 checkSameDec("__lt__", True)
1526 checkSameDec("__ge__", True)
1527 checkSameDec("__gt__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001528 checkSameDec("__float__")
1529 checkSameDec("__floordiv__", True)
1530 checkSameDec("__hash__")
1531 checkSameDec("__int__")
Raymond Hettinger5a053642008-01-24 19:05:29 +00001532 checkSameDec("__trunc__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001533 checkSameDec("__long__")
1534 checkSameDec("__mod__", True)
1535 checkSameDec("__mul__", True)
1536 checkSameDec("__neg__")
1537 checkSameDec("__nonzero__")
1538 checkSameDec("__pos__")
1539 checkSameDec("__pow__", True)
1540 checkSameDec("__radd__", True)
1541 checkSameDec("__rdiv__", True)
1542 checkSameDec("__rdivmod__", True)
1543 checkSameDec("__repr__")
1544 checkSameDec("__rfloordiv__", True)
1545 checkSameDec("__rmod__", True)
1546 checkSameDec("__rmul__", True)
1547 checkSameDec("__rpow__", True)
1548 checkSameDec("__rsub__", True)
1549 checkSameDec("__str__")
1550 checkSameDec("__sub__", True)
1551 checkSameDec("__truediv__", True)
1552 checkSameDec("adjusted")
1553 checkSameDec("as_tuple")
1554 checkSameDec("compare", True)
1555 checkSameDec("max", True)
1556 checkSameDec("min", True)
1557 checkSameDec("normalize")
1558 checkSameDec("quantize", True)
1559 checkSameDec("remainder_near", True)
1560 checkSameDec("same_quantum", True)
1561 checkSameDec("sqrt")
1562 checkSameDec("to_eng_string")
1563 checkSameDec("to_integral")
1564
Facundo Batista6c398da2007-09-17 17:30:13 +00001565 def test_subclassing(self):
1566 # Different behaviours when subclassing Decimal
1567
1568 class MyDecimal(Decimal):
1569 pass
1570
1571 d1 = MyDecimal(1)
1572 d2 = MyDecimal(2)
1573 d = d1 + d2
Ezio Melotti856a3be2010-04-03 14:51:00 +00001574 self.assertIs(type(d), Decimal)
Facundo Batista6c398da2007-09-17 17:30:13 +00001575
1576 d = d1.max(d2)
Ezio Melotti856a3be2010-04-03 14:51:00 +00001577 self.assertIs(type(d), Decimal)
Facundo Batista6c398da2007-09-17 17:30:13 +00001578
Mark Dickinson3b24ccb2008-03-25 14:33:23 +00001579 def test_implicit_context(self):
1580 # Check results when context given implicitly. (Issue 2478)
1581 c = getcontext()
1582 self.assertEqual(str(Decimal(0).sqrt()),
1583 str(c.sqrt(Decimal(0))))
1584
Mark Dickinson0c673122009-10-29 12:04:00 +00001585 def test_conversions_from_int(self):
1586 # Check that methods taking a second Decimal argument will
1587 # always accept an integer in place of a Decimal.
1588 self.assertEqual(Decimal(4).compare(3),
1589 Decimal(4).compare(Decimal(3)))
1590 self.assertEqual(Decimal(4).compare_signal(3),
1591 Decimal(4).compare_signal(Decimal(3)))
1592 self.assertEqual(Decimal(4).compare_total(3),
1593 Decimal(4).compare_total(Decimal(3)))
1594 self.assertEqual(Decimal(4).compare_total_mag(3),
1595 Decimal(4).compare_total_mag(Decimal(3)))
1596 self.assertEqual(Decimal(10101).logical_and(1001),
1597 Decimal(10101).logical_and(Decimal(1001)))
1598 self.assertEqual(Decimal(10101).logical_or(1001),
1599 Decimal(10101).logical_or(Decimal(1001)))
1600 self.assertEqual(Decimal(10101).logical_xor(1001),
1601 Decimal(10101).logical_xor(Decimal(1001)))
1602 self.assertEqual(Decimal(567).max(123),
1603 Decimal(567).max(Decimal(123)))
1604 self.assertEqual(Decimal(567).max_mag(123),
1605 Decimal(567).max_mag(Decimal(123)))
1606 self.assertEqual(Decimal(567).min(123),
1607 Decimal(567).min(Decimal(123)))
1608 self.assertEqual(Decimal(567).min_mag(123),
1609 Decimal(567).min_mag(Decimal(123)))
1610 self.assertEqual(Decimal(567).next_toward(123),
1611 Decimal(567).next_toward(Decimal(123)))
1612 self.assertEqual(Decimal(1234).quantize(100),
1613 Decimal(1234).quantize(Decimal(100)))
1614 self.assertEqual(Decimal(768).remainder_near(1234),
1615 Decimal(768).remainder_near(Decimal(1234)))
1616 self.assertEqual(Decimal(123).rotate(1),
1617 Decimal(123).rotate(Decimal(1)))
1618 self.assertEqual(Decimal(1234).same_quantum(1000),
1619 Decimal(1234).same_quantum(Decimal(1000)))
1620 self.assertEqual(Decimal('9.123').scaleb(-100),
1621 Decimal('9.123').scaleb(Decimal(-100)))
1622 self.assertEqual(Decimal(456).shift(-1),
1623 Decimal(456).shift(Decimal(-1)))
1624
1625 self.assertEqual(Decimal(-12).fma(Decimal(45), 67),
1626 Decimal(-12).fma(Decimal(45), Decimal(67)))
1627 self.assertEqual(Decimal(-12).fma(45, 67),
1628 Decimal(-12).fma(Decimal(45), Decimal(67)))
1629 self.assertEqual(Decimal(-12).fma(45, Decimal(67)),
1630 Decimal(-12).fma(Decimal(45), Decimal(67)))
1631
Facundo Batista6c398da2007-09-17 17:30:13 +00001632
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001633class DecimalPythonAPItests(unittest.TestCase):
1634
Raymond Hettinger2c8585b2009-02-03 03:37:03 +00001635 def test_abc(self):
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001636 self.assertTrue(issubclass(Decimal, numbers.Number))
Ezio Melotti856a3be2010-04-03 14:51:00 +00001637 self.assertFalse(issubclass(Decimal, numbers.Real))
Ezio Melottib0f5adc2010-01-24 16:58:36 +00001638 self.assertIsInstance(Decimal(0), numbers.Number)
Ezio Melotti856a3be2010-04-03 14:51:00 +00001639 self.assertNotIsInstance(Decimal(0), numbers.Real)
Raymond Hettinger2c8585b2009-02-03 03:37:03 +00001640
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001641 def test_pickle(self):
1642 d = Decimal('-3.141590000')
1643 p = pickle.dumps(d)
1644 e = pickle.loads(p)
1645 self.assertEqual(d, e)
1646
Raymond Hettinger5548be22004-07-05 18:49:38 +00001647 def test_int(self):
Raymond Hettinger605ed022004-11-24 07:28:48 +00001648 for x in range(-250, 250):
1649 s = '%0.2f' % (x / 100.0)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001650 # should work the same as for floats
1651 self.assertEqual(int(Decimal(s)), int(float(s)))
Raymond Hettinger605ed022004-11-24 07:28:48 +00001652 # should work the same as to_integral in the ROUND_DOWN mode
Raymond Hettinger5548be22004-07-05 18:49:38 +00001653 d = Decimal(s)
Raymond Hettinger605ed022004-11-24 07:28:48 +00001654 r = d.to_integral(ROUND_DOWN)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001655 self.assertEqual(Decimal(int(d)), r)
1656
Mark Dickinson968f1692009-09-07 18:04:58 +00001657 self.assertRaises(ValueError, int, Decimal('-nan'))
1658 self.assertRaises(ValueError, int, Decimal('snan'))
1659 self.assertRaises(OverflowError, int, Decimal('inf'))
1660 self.assertRaises(OverflowError, int, Decimal('-inf'))
1661
1662 self.assertRaises(ValueError, long, Decimal('-nan'))
1663 self.assertRaises(ValueError, long, Decimal('snan'))
1664 self.assertRaises(OverflowError, long, Decimal('inf'))
1665 self.assertRaises(OverflowError, long, Decimal('-inf'))
1666
Raymond Hettinger5a053642008-01-24 19:05:29 +00001667 def test_trunc(self):
1668 for x in range(-250, 250):
1669 s = '%0.2f' % (x / 100.0)
1670 # should work the same as for floats
1671 self.assertEqual(int(Decimal(s)), int(float(s)))
1672 # should work the same as to_integral in the ROUND_DOWN mode
1673 d = Decimal(s)
1674 r = d.to_integral(ROUND_DOWN)
Jeffrey Yasskinca2b69f2008-02-01 06:22:46 +00001675 self.assertEqual(Decimal(math.trunc(d)), r)
Raymond Hettinger5a053642008-01-24 19:05:29 +00001676
Raymond Hettingerf4d85972009-01-03 19:02:23 +00001677 def test_from_float(self):
1678
1679 class MyDecimal(Decimal):
1680 pass
1681
1682 r = MyDecimal.from_float(0.1)
1683 self.assertEqual(type(r), MyDecimal)
1684 self.assertEqual(str(r),
1685 '0.1000000000000000055511151231257827021181583404541015625')
1686 bigint = 12345678901234567890123456789
1687 self.assertEqual(MyDecimal.from_float(bigint), MyDecimal(bigint))
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001688 self.assertTrue(MyDecimal.from_float(float('nan')).is_qnan())
1689 self.assertTrue(MyDecimal.from_float(float('inf')).is_infinite())
1690 self.assertTrue(MyDecimal.from_float(float('-inf')).is_infinite())
Raymond Hettingerf4d85972009-01-03 19:02:23 +00001691 self.assertEqual(str(MyDecimal.from_float(float('nan'))),
1692 str(Decimal('NaN')))
1693 self.assertEqual(str(MyDecimal.from_float(float('inf'))),
1694 str(Decimal('Infinity')))
1695 self.assertEqual(str(MyDecimal.from_float(float('-inf'))),
1696 str(Decimal('-Infinity')))
1697 self.assertRaises(TypeError, MyDecimal.from_float, 'abc')
1698 for i in range(200):
1699 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
1700 self.assertEqual(x, float(MyDecimal.from_float(x))) # roundtrip
1701
1702 def test_create_decimal_from_float(self):
1703 context = Context(prec=5, rounding=ROUND_DOWN)
1704 self.assertEqual(
1705 context.create_decimal_from_float(math.pi),
1706 Decimal('3.1415')
1707 )
1708 context = Context(prec=5, rounding=ROUND_UP)
1709 self.assertEqual(
1710 context.create_decimal_from_float(math.pi),
1711 Decimal('3.1416')
1712 )
1713 context = Context(prec=5, traps=[Inexact])
1714 self.assertRaises(
1715 Inexact,
1716 context.create_decimal_from_float,
1717 math.pi
1718 )
1719 self.assertEqual(repr(context.create_decimal_from_float(-0.0)),
1720 "Decimal('-0')")
1721 self.assertEqual(repr(context.create_decimal_from_float(1.0)),
1722 "Decimal('1')")
1723 self.assertEqual(repr(context.create_decimal_from_float(10)),
1724 "Decimal('10')")
1725
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00001726class ContextAPItests(unittest.TestCase):
1727
1728 def test_pickle(self):
1729 c = Context()
1730 e = pickle.loads(pickle.dumps(c))
1731 for k in vars(c):
1732 v1 = vars(c)[k]
1733 v2 = vars(e)[k]
1734 self.assertEqual(v1, v2)
1735
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001736 def test_equality_with_other_types(self):
Ezio Melottiaa980582010-01-23 23:04:36 +00001737 self.assertIn(Decimal(10), ['a', 1.0, Decimal(10), (1,2), {}])
1738 self.assertNotIn(Decimal(10), ['a', 1.0, (1,2), {}])
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001739
Raymond Hettinger955d2b22004-08-08 20:17:45 +00001740 def test_copy(self):
1741 # All copies should be deep
1742 c = Context()
1743 d = c.copy()
1744 self.assertNotEqual(id(c), id(d))
1745 self.assertNotEqual(id(c.flags), id(d.flags))
1746 self.assertNotEqual(id(c.traps), id(d.traps))
1747
Mark Dickinson6d8effb2010-02-18 14:27:02 +00001748 def test_abs(self):
1749 c = Context()
1750 d = c.abs(Decimal(-1))
1751 self.assertEqual(c.abs(-1), d)
1752 self.assertRaises(TypeError, c.abs, '-1')
1753
1754 def test_add(self):
1755 c = Context()
1756 d = c.add(Decimal(1), Decimal(1))
1757 self.assertEqual(c.add(1, 1), d)
1758 self.assertEqual(c.add(Decimal(1), 1), d)
1759 self.assertEqual(c.add(1, Decimal(1)), d)
1760 self.assertRaises(TypeError, c.add, '1', 1)
1761 self.assertRaises(TypeError, c.add, 1, '1')
1762
1763 def test_compare(self):
1764 c = Context()
1765 d = c.compare(Decimal(1), Decimal(1))
1766 self.assertEqual(c.compare(1, 1), d)
1767 self.assertEqual(c.compare(Decimal(1), 1), d)
1768 self.assertEqual(c.compare(1, Decimal(1)), d)
1769 self.assertRaises(TypeError, c.compare, '1', 1)
1770 self.assertRaises(TypeError, c.compare, 1, '1')
1771
1772 def test_compare_signal(self):
1773 c = Context()
1774 d = c.compare_signal(Decimal(1), Decimal(1))
1775 self.assertEqual(c.compare_signal(1, 1), d)
1776 self.assertEqual(c.compare_signal(Decimal(1), 1), d)
1777 self.assertEqual(c.compare_signal(1, Decimal(1)), d)
1778 self.assertRaises(TypeError, c.compare_signal, '1', 1)
1779 self.assertRaises(TypeError, c.compare_signal, 1, '1')
1780
1781 def test_compare_total(self):
1782 c = Context()
1783 d = c.compare_total(Decimal(1), Decimal(1))
1784 self.assertEqual(c.compare_total(1, 1), d)
1785 self.assertEqual(c.compare_total(Decimal(1), 1), d)
1786 self.assertEqual(c.compare_total(1, Decimal(1)), d)
1787 self.assertRaises(TypeError, c.compare_total, '1', 1)
1788 self.assertRaises(TypeError, c.compare_total, 1, '1')
1789
1790 def test_compare_total_mag(self):
1791 c = Context()
1792 d = c.compare_total_mag(Decimal(1), Decimal(1))
1793 self.assertEqual(c.compare_total_mag(1, 1), d)
1794 self.assertEqual(c.compare_total_mag(Decimal(1), 1), d)
1795 self.assertEqual(c.compare_total_mag(1, Decimal(1)), d)
1796 self.assertRaises(TypeError, c.compare_total_mag, '1', 1)
1797 self.assertRaises(TypeError, c.compare_total_mag, 1, '1')
1798
1799 def test_copy_abs(self):
1800 c = Context()
1801 d = c.copy_abs(Decimal(-1))
1802 self.assertEqual(c.copy_abs(-1), d)
1803 self.assertRaises(TypeError, c.copy_abs, '-1')
1804
1805 def test_copy_decimal(self):
1806 c = Context()
1807 d = c.copy_decimal(Decimal(-1))
1808 self.assertEqual(c.copy_decimal(-1), d)
1809 self.assertRaises(TypeError, c.copy_decimal, '-1')
1810
1811 def test_copy_negate(self):
1812 c = Context()
1813 d = c.copy_negate(Decimal(-1))
1814 self.assertEqual(c.copy_negate(-1), d)
1815 self.assertRaises(TypeError, c.copy_negate, '-1')
1816
1817 def test_copy_sign(self):
1818 c = Context()
1819 d = c.copy_sign(Decimal(1), Decimal(-2))
1820 self.assertEqual(c.copy_sign(1, -2), d)
1821 self.assertEqual(c.copy_sign(Decimal(1), -2), d)
1822 self.assertEqual(c.copy_sign(1, Decimal(-2)), d)
1823 self.assertRaises(TypeError, c.copy_sign, '1', -2)
1824 self.assertRaises(TypeError, c.copy_sign, 1, '-2')
1825
1826 def test_divide(self):
1827 c = Context()
1828 d = c.divide(Decimal(1), Decimal(2))
1829 self.assertEqual(c.divide(1, 2), d)
1830 self.assertEqual(c.divide(Decimal(1), 2), d)
1831 self.assertEqual(c.divide(1, Decimal(2)), d)
1832 self.assertRaises(TypeError, c.divide, '1', 2)
1833 self.assertRaises(TypeError, c.divide, 1, '2')
1834
1835 def test_divide_int(self):
1836 c = Context()
1837 d = c.divide_int(Decimal(1), Decimal(2))
1838 self.assertEqual(c.divide_int(1, 2), d)
1839 self.assertEqual(c.divide_int(Decimal(1), 2), d)
1840 self.assertEqual(c.divide_int(1, Decimal(2)), d)
1841 self.assertRaises(TypeError, c.divide_int, '1', 2)
1842 self.assertRaises(TypeError, c.divide_int, 1, '2')
1843
1844 def test_divmod(self):
1845 c = Context()
1846 d = c.divmod(Decimal(1), Decimal(2))
1847 self.assertEqual(c.divmod(1, 2), d)
1848 self.assertEqual(c.divmod(Decimal(1), 2), d)
1849 self.assertEqual(c.divmod(1, Decimal(2)), d)
1850 self.assertRaises(TypeError, c.divmod, '1', 2)
1851 self.assertRaises(TypeError, c.divmod, 1, '2')
1852
1853 def test_exp(self):
1854 c = Context()
1855 d = c.exp(Decimal(10))
1856 self.assertEqual(c.exp(10), d)
1857 self.assertRaises(TypeError, c.exp, '10')
1858
1859 def test_fma(self):
1860 c = Context()
1861 d = c.fma(Decimal(2), Decimal(3), Decimal(4))
1862 self.assertEqual(c.fma(2, 3, 4), d)
1863 self.assertEqual(c.fma(Decimal(2), 3, 4), d)
1864 self.assertEqual(c.fma(2, Decimal(3), 4), d)
1865 self.assertEqual(c.fma(2, 3, Decimal(4)), d)
1866 self.assertEqual(c.fma(Decimal(2), Decimal(3), 4), d)
1867 self.assertRaises(TypeError, c.fma, '2', 3, 4)
1868 self.assertRaises(TypeError, c.fma, 2, '3', 4)
1869 self.assertRaises(TypeError, c.fma, 2, 3, '4')
1870
1871 def test_is_finite(self):
1872 c = Context()
1873 d = c.is_finite(Decimal(10))
1874 self.assertEqual(c.is_finite(10), d)
1875 self.assertRaises(TypeError, c.is_finite, '10')
1876
1877 def test_is_infinite(self):
1878 c = Context()
1879 d = c.is_infinite(Decimal(10))
1880 self.assertEqual(c.is_infinite(10), d)
1881 self.assertRaises(TypeError, c.is_infinite, '10')
1882
1883 def test_is_nan(self):
1884 c = Context()
1885 d = c.is_nan(Decimal(10))
1886 self.assertEqual(c.is_nan(10), d)
1887 self.assertRaises(TypeError, c.is_nan, '10')
1888
1889 def test_is_normal(self):
1890 c = Context()
1891 d = c.is_normal(Decimal(10))
1892 self.assertEqual(c.is_normal(10), d)
1893 self.assertRaises(TypeError, c.is_normal, '10')
1894
1895 def test_is_qnan(self):
1896 c = Context()
1897 d = c.is_qnan(Decimal(10))
1898 self.assertEqual(c.is_qnan(10), d)
1899 self.assertRaises(TypeError, c.is_qnan, '10')
1900
1901 def test_is_signed(self):
1902 c = Context()
1903 d = c.is_signed(Decimal(10))
1904 self.assertEqual(c.is_signed(10), d)
1905 self.assertRaises(TypeError, c.is_signed, '10')
1906
1907 def test_is_snan(self):
1908 c = Context()
1909 d = c.is_snan(Decimal(10))
1910 self.assertEqual(c.is_snan(10), d)
1911 self.assertRaises(TypeError, c.is_snan, '10')
1912
1913 def test_is_subnormal(self):
1914 c = Context()
1915 d = c.is_subnormal(Decimal(10))
1916 self.assertEqual(c.is_subnormal(10), d)
1917 self.assertRaises(TypeError, c.is_subnormal, '10')
1918
1919 def test_is_zero(self):
1920 c = Context()
1921 d = c.is_zero(Decimal(10))
1922 self.assertEqual(c.is_zero(10), d)
1923 self.assertRaises(TypeError, c.is_zero, '10')
1924
1925 def test_ln(self):
1926 c = Context()
1927 d = c.ln(Decimal(10))
1928 self.assertEqual(c.ln(10), d)
1929 self.assertRaises(TypeError, c.ln, '10')
1930
1931 def test_log10(self):
1932 c = Context()
1933 d = c.log10(Decimal(10))
1934 self.assertEqual(c.log10(10), d)
1935 self.assertRaises(TypeError, c.log10, '10')
1936
1937 def test_logb(self):
1938 c = Context()
1939 d = c.logb(Decimal(10))
1940 self.assertEqual(c.logb(10), d)
1941 self.assertRaises(TypeError, c.logb, '10')
1942
1943 def test_logical_and(self):
1944 c = Context()
1945 d = c.logical_and(Decimal(1), Decimal(1))
1946 self.assertEqual(c.logical_and(1, 1), d)
1947 self.assertEqual(c.logical_and(Decimal(1), 1), d)
1948 self.assertEqual(c.logical_and(1, Decimal(1)), d)
1949 self.assertRaises(TypeError, c.logical_and, '1', 1)
1950 self.assertRaises(TypeError, c.logical_and, 1, '1')
1951
1952 def test_logical_invert(self):
1953 c = Context()
1954 d = c.logical_invert(Decimal(1000))
1955 self.assertEqual(c.logical_invert(1000), d)
1956 self.assertRaises(TypeError, c.logical_invert, '1000')
1957
1958 def test_logical_or(self):
1959 c = Context()
1960 d = c.logical_or(Decimal(1), Decimal(1))
1961 self.assertEqual(c.logical_or(1, 1), d)
1962 self.assertEqual(c.logical_or(Decimal(1), 1), d)
1963 self.assertEqual(c.logical_or(1, Decimal(1)), d)
1964 self.assertRaises(TypeError, c.logical_or, '1', 1)
1965 self.assertRaises(TypeError, c.logical_or, 1, '1')
1966
1967 def test_logical_xor(self):
1968 c = Context()
1969 d = c.logical_xor(Decimal(1), Decimal(1))
1970 self.assertEqual(c.logical_xor(1, 1), d)
1971 self.assertEqual(c.logical_xor(Decimal(1), 1), d)
1972 self.assertEqual(c.logical_xor(1, Decimal(1)), d)
1973 self.assertRaises(TypeError, c.logical_xor, '1', 1)
1974 self.assertRaises(TypeError, c.logical_xor, 1, '1')
1975
1976 def test_max(self):
1977 c = Context()
1978 d = c.max(Decimal(1), Decimal(2))
1979 self.assertEqual(c.max(1, 2), d)
1980 self.assertEqual(c.max(Decimal(1), 2), d)
1981 self.assertEqual(c.max(1, Decimal(2)), d)
1982 self.assertRaises(TypeError, c.max, '1', 2)
1983 self.assertRaises(TypeError, c.max, 1, '2')
1984
1985 def test_max_mag(self):
1986 c = Context()
1987 d = c.max_mag(Decimal(1), Decimal(2))
1988 self.assertEqual(c.max_mag(1, 2), d)
1989 self.assertEqual(c.max_mag(Decimal(1), 2), d)
1990 self.assertEqual(c.max_mag(1, Decimal(2)), d)
1991 self.assertRaises(TypeError, c.max_mag, '1', 2)
1992 self.assertRaises(TypeError, c.max_mag, 1, '2')
1993
1994 def test_min(self):
1995 c = Context()
1996 d = c.min(Decimal(1), Decimal(2))
1997 self.assertEqual(c.min(1, 2), d)
1998 self.assertEqual(c.min(Decimal(1), 2), d)
1999 self.assertEqual(c.min(1, Decimal(2)), d)
2000 self.assertRaises(TypeError, c.min, '1', 2)
2001 self.assertRaises(TypeError, c.min, 1, '2')
2002
2003 def test_min_mag(self):
2004 c = Context()
2005 d = c.min_mag(Decimal(1), Decimal(2))
2006 self.assertEqual(c.min_mag(1, 2), d)
2007 self.assertEqual(c.min_mag(Decimal(1), 2), d)
2008 self.assertEqual(c.min_mag(1, Decimal(2)), d)
2009 self.assertRaises(TypeError, c.min_mag, '1', 2)
2010 self.assertRaises(TypeError, c.min_mag, 1, '2')
2011
2012 def test_minus(self):
2013 c = Context()
2014 d = c.minus(Decimal(10))
2015 self.assertEqual(c.minus(10), d)
2016 self.assertRaises(TypeError, c.minus, '10')
2017
2018 def test_multiply(self):
2019 c = Context()
2020 d = c.multiply(Decimal(1), Decimal(2))
2021 self.assertEqual(c.multiply(1, 2), d)
2022 self.assertEqual(c.multiply(Decimal(1), 2), d)
2023 self.assertEqual(c.multiply(1, Decimal(2)), d)
2024 self.assertRaises(TypeError, c.multiply, '1', 2)
2025 self.assertRaises(TypeError, c.multiply, 1, '2')
2026
2027 def test_next_minus(self):
2028 c = Context()
2029 d = c.next_minus(Decimal(10))
2030 self.assertEqual(c.next_minus(10), d)
2031 self.assertRaises(TypeError, c.next_minus, '10')
2032
2033 def test_next_plus(self):
2034 c = Context()
2035 d = c.next_plus(Decimal(10))
2036 self.assertEqual(c.next_plus(10), d)
2037 self.assertRaises(TypeError, c.next_plus, '10')
2038
2039 def test_next_toward(self):
2040 c = Context()
2041 d = c.next_toward(Decimal(1), Decimal(2))
2042 self.assertEqual(c.next_toward(1, 2), d)
2043 self.assertEqual(c.next_toward(Decimal(1), 2), d)
2044 self.assertEqual(c.next_toward(1, Decimal(2)), d)
2045 self.assertRaises(TypeError, c.next_toward, '1', 2)
2046 self.assertRaises(TypeError, c.next_toward, 1, '2')
2047
2048 def test_normalize(self):
2049 c = Context()
2050 d = c.normalize(Decimal(10))
2051 self.assertEqual(c.normalize(10), d)
2052 self.assertRaises(TypeError, c.normalize, '10')
2053
2054 def test_number_class(self):
2055 c = Context()
2056 self.assertEqual(c.number_class(123), c.number_class(Decimal(123)))
2057 self.assertEqual(c.number_class(0), c.number_class(Decimal(0)))
2058 self.assertEqual(c.number_class(-45), c.number_class(Decimal(-45)))
2059
2060 def test_power(self):
2061 c = Context()
2062 d = c.power(Decimal(1), Decimal(4), Decimal(2))
2063 self.assertEqual(c.power(1, 4, 2), d)
2064 self.assertEqual(c.power(Decimal(1), 4, 2), d)
2065 self.assertEqual(c.power(1, Decimal(4), 2), d)
2066 self.assertEqual(c.power(1, 4, Decimal(2)), d)
2067 self.assertEqual(c.power(Decimal(1), Decimal(4), 2), d)
2068 self.assertRaises(TypeError, c.power, '1', 4, 2)
2069 self.assertRaises(TypeError, c.power, 1, '4', 2)
2070 self.assertRaises(TypeError, c.power, 1, 4, '2')
2071
2072 def test_plus(self):
2073 c = Context()
2074 d = c.plus(Decimal(10))
2075 self.assertEqual(c.plus(10), d)
2076 self.assertRaises(TypeError, c.plus, '10')
2077
2078 def test_quantize(self):
2079 c = Context()
2080 d = c.quantize(Decimal(1), Decimal(2))
2081 self.assertEqual(c.quantize(1, 2), d)
2082 self.assertEqual(c.quantize(Decimal(1), 2), d)
2083 self.assertEqual(c.quantize(1, Decimal(2)), d)
2084 self.assertRaises(TypeError, c.quantize, '1', 2)
2085 self.assertRaises(TypeError, c.quantize, 1, '2')
2086
2087 def test_remainder(self):
2088 c = Context()
2089 d = c.remainder(Decimal(1), Decimal(2))
2090 self.assertEqual(c.remainder(1, 2), d)
2091 self.assertEqual(c.remainder(Decimal(1), 2), d)
2092 self.assertEqual(c.remainder(1, Decimal(2)), d)
2093 self.assertRaises(TypeError, c.remainder, '1', 2)
2094 self.assertRaises(TypeError, c.remainder, 1, '2')
2095
2096 def test_remainder_near(self):
2097 c = Context()
2098 d = c.remainder_near(Decimal(1), Decimal(2))
2099 self.assertEqual(c.remainder_near(1, 2), d)
2100 self.assertEqual(c.remainder_near(Decimal(1), 2), d)
2101 self.assertEqual(c.remainder_near(1, Decimal(2)), d)
2102 self.assertRaises(TypeError, c.remainder_near, '1', 2)
2103 self.assertRaises(TypeError, c.remainder_near, 1, '2')
2104
2105 def test_rotate(self):
2106 c = Context()
2107 d = c.rotate(Decimal(1), Decimal(2))
2108 self.assertEqual(c.rotate(1, 2), d)
2109 self.assertEqual(c.rotate(Decimal(1), 2), d)
2110 self.assertEqual(c.rotate(1, Decimal(2)), d)
2111 self.assertRaises(TypeError, c.rotate, '1', 2)
2112 self.assertRaises(TypeError, c.rotate, 1, '2')
2113
2114 def test_sqrt(self):
2115 c = Context()
2116 d = c.sqrt(Decimal(10))
2117 self.assertEqual(c.sqrt(10), d)
2118 self.assertRaises(TypeError, c.sqrt, '10')
2119
2120 def test_same_quantum(self):
2121 c = Context()
2122 d = c.same_quantum(Decimal(1), Decimal(2))
2123 self.assertEqual(c.same_quantum(1, 2), d)
2124 self.assertEqual(c.same_quantum(Decimal(1), 2), d)
2125 self.assertEqual(c.same_quantum(1, Decimal(2)), d)
2126 self.assertRaises(TypeError, c.same_quantum, '1', 2)
2127 self.assertRaises(TypeError, c.same_quantum, 1, '2')
2128
2129 def test_scaleb(self):
2130 c = Context()
2131 d = c.scaleb(Decimal(1), Decimal(2))
2132 self.assertEqual(c.scaleb(1, 2), d)
2133 self.assertEqual(c.scaleb(Decimal(1), 2), d)
2134 self.assertEqual(c.scaleb(1, Decimal(2)), d)
2135 self.assertRaises(TypeError, c.scaleb, '1', 2)
2136 self.assertRaises(TypeError, c.scaleb, 1, '2')
2137
2138 def test_shift(self):
2139 c = Context()
2140 d = c.shift(Decimal(1), Decimal(2))
2141 self.assertEqual(c.shift(1, 2), d)
2142 self.assertEqual(c.shift(Decimal(1), 2), d)
2143 self.assertEqual(c.shift(1, Decimal(2)), d)
2144 self.assertRaises(TypeError, c.shift, '1', 2)
2145 self.assertRaises(TypeError, c.shift, 1, '2')
2146
2147 def test_subtract(self):
2148 c = Context()
2149 d = c.subtract(Decimal(1), Decimal(2))
2150 self.assertEqual(c.subtract(1, 2), d)
2151 self.assertEqual(c.subtract(Decimal(1), 2), d)
2152 self.assertEqual(c.subtract(1, Decimal(2)), d)
2153 self.assertRaises(TypeError, c.subtract, '1', 2)
2154 self.assertRaises(TypeError, c.subtract, 1, '2')
2155
2156 def test_to_eng_string(self):
2157 c = Context()
2158 d = c.to_eng_string(Decimal(10))
2159 self.assertEqual(c.to_eng_string(10), d)
2160 self.assertRaises(TypeError, c.to_eng_string, '10')
2161
2162 def test_to_sci_string(self):
2163 c = Context()
2164 d = c.to_sci_string(Decimal(10))
2165 self.assertEqual(c.to_sci_string(10), d)
2166 self.assertRaises(TypeError, c.to_sci_string, '10')
2167
2168 def test_to_integral_exact(self):
2169 c = Context()
2170 d = c.to_integral_exact(Decimal(10))
2171 self.assertEqual(c.to_integral_exact(10), d)
2172 self.assertRaises(TypeError, c.to_integral_exact, '10')
2173
2174 def test_to_integral_value(self):
2175 c = Context()
2176 d = c.to_integral_value(Decimal(10))
2177 self.assertEqual(c.to_integral_value(10), d)
2178 self.assertRaises(TypeError, c.to_integral_value, '10')
2179
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002180class WithStatementTest(unittest.TestCase):
2181 # Can't do these as docstrings until Python 2.6
2182 # as doctest can't handle __future__ statements
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002183
2184 def test_localcontext(self):
Nick Coghlanced12182006-09-02 03:54:17 +00002185 # Use a copy of the current context in the block
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002186 orig_ctx = getcontext()
2187 with localcontext() as enter_ctx:
2188 set_ctx = getcontext()
2189 final_ctx = getcontext()
Ezio Melotti856a3be2010-04-03 14:51:00 +00002190 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
2191 self.assertIsNot(orig_ctx, set_ctx, 'did not copy the context')
2192 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002193
2194 def test_localcontextarg(self):
Nick Coghlanced12182006-09-02 03:54:17 +00002195 # Use a copy of the supplied context in the block
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002196 orig_ctx = getcontext()
2197 new_ctx = Context(prec=42)
2198 with localcontext(new_ctx) as enter_ctx:
2199 set_ctx = getcontext()
2200 final_ctx = getcontext()
Ezio Melotti856a3be2010-04-03 14:51:00 +00002201 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
2202 self.assertEqual(set_ctx.prec, new_ctx.prec, 'did not set correct context')
2203 self.assertIsNot(new_ctx, set_ctx, 'did not copy the context')
2204 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002205
Facundo Batista353750c2007-09-13 18:13:15 +00002206class ContextFlags(unittest.TestCase):
2207 def test_flags_irrelevant(self):
2208 # check that the result (numeric result + flags raised) of an
2209 # arithmetic operation doesn't depend on the current flags
2210
2211 context = Context(prec=9, Emin = -999999999, Emax = 999999999,
2212 rounding=ROUND_HALF_EVEN, traps=[], flags=[])
2213
2214 # operations that raise various flags, in the form (function, arglist)
2215 operations = [
2216 (context._apply, [Decimal("100E-1000000009")]),
2217 (context.sqrt, [Decimal(2)]),
2218 (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]),
2219 (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]),
2220 (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]),
2221 ]
2222
2223 # try various flags individually, then a whole lot at once
2224 flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal],
2225 [Inexact, Rounded, Underflow, Clamped, Subnormal]]
2226
2227 for fn, args in operations:
2228 # find answer and flags raised using a clean context
2229 context.clear_flags()
2230 ans = fn(*args)
2231 flags = [k for k, v in context.flags.items() if v]
2232
2233 for extra_flags in flagsets:
2234 # set flags, before calling operation
2235 context.clear_flags()
2236 for flag in extra_flags:
2237 context._raise_error(flag)
2238 new_ans = fn(*args)
2239
2240 # flags that we expect to be set after the operation
2241 expected_flags = list(flags)
2242 for flag in extra_flags:
2243 if flag not in expected_flags:
2244 expected_flags.append(flag)
Facundo Batista353750c2007-09-13 18:13:15 +00002245
2246 # flags we actually got
2247 new_flags = [k for k,v in context.flags.items() if v]
Facundo Batista353750c2007-09-13 18:13:15 +00002248
2249 self.assertEqual(ans, new_ans,
2250 "operation produces different answers depending on flags set: " +
2251 "expected %s, got %s." % (ans, new_ans))
Florent Xicluna8f43cec2010-03-21 10:51:40 +00002252 self.assertItemsEqual(new_flags, expected_flags,
Facundo Batista353750c2007-09-13 18:13:15 +00002253 "operation raises different flags depending on flags set: " +
2254 "expected %s, got %s" % (expected_flags, new_flags))
2255
2256def test_main(arith=False, verbose=None, todo_tests=None, debug=None):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002257 """ Execute the tests.
2258
Raymond Hettingered20ad82004-09-04 20:09:13 +00002259 Runs all arithmetic tests if arith is True or if the "decimal" resource
2260 is enabled in regrtest.py
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002261 """
Raymond Hettingered20ad82004-09-04 20:09:13 +00002262
Neal Norwitzce4a9c92006-04-09 08:36:46 +00002263 init()
Facundo Batista353750c2007-09-13 18:13:15 +00002264 global TEST_ALL, DEBUG
Raymond Hettingered20ad82004-09-04 20:09:13 +00002265 TEST_ALL = arith or is_resource_enabled('decimal')
Facundo Batista353750c2007-09-13 18:13:15 +00002266 DEBUG = debug
Raymond Hettingered20ad82004-09-04 20:09:13 +00002267
Facundo Batista353750c2007-09-13 18:13:15 +00002268 if todo_tests is None:
2269 test_classes = [
2270 DecimalExplicitConstructionTest,
2271 DecimalImplicitConstructionTest,
2272 DecimalArithmeticOperatorsTest,
Mark Dickinson1ddf1d82008-02-29 02:16:37 +00002273 DecimalFormatTest,
Facundo Batista353750c2007-09-13 18:13:15 +00002274 DecimalUseOfContextTest,
2275 DecimalUsabilityTest,
2276 DecimalPythonAPItests,
2277 ContextAPItests,
2278 DecimalTest,
2279 WithStatementTest,
2280 ContextFlags
2281 ]
2282 else:
2283 test_classes = [DecimalTest]
2284
2285 # Dynamically build custom test definition for each file in the test
2286 # directory and add the definitions to the DecimalTest class. This
2287 # procedure insures that new files do not get skipped.
2288 for filename in os.listdir(directory):
2289 if '.decTest' not in filename or filename.startswith("."):
2290 continue
2291 head, tail = filename.split('.')
2292 if todo_tests is not None and head not in todo_tests:
2293 continue
2294 tester = lambda self, f=filename: self.eval_file(directory + f)
2295 setattr(DecimalTest, 'test_' + head, tester)
2296 del filename, head, tail, tester
2297
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002298
Tim Peters46cc7022006-03-31 04:11:16 +00002299 try:
2300 run_unittest(*test_classes)
Facundo Batista353750c2007-09-13 18:13:15 +00002301 if todo_tests is None:
2302 import decimal as DecimalModule
2303 run_doctest(DecimalModule, verbose)
Tim Peters46cc7022006-03-31 04:11:16 +00002304 finally:
2305 setcontext(ORIGINAL_CONTEXT)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002306
2307if __name__ == '__main__':
Facundo Batista353750c2007-09-13 18:13:15 +00002308 import optparse
2309 p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]")
2310 p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test')
2311 p.add_option('--skip', '-s', action='store_true', help='skip over 90% of the arithmetic tests')
2312 (opt, args) = p.parse_args()
2313
2314 if opt.skip:
2315 test_main(arith=False, verbose=True)
2316 elif args:
2317 test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002318 else:
Facundo Batista353750c2007-09-13 18:13:15 +00002319 test_main(arith=True, verbose=True)