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