blob: 19fb9dadc43634adabf6e470cf3b777f5739fce8 [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
43Signals = getcontext().flags.keys()
44
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 Hettinger7c85fa42004-07-01 11:01:35 +000057TESTDATADIR = 'decimaltestdata'
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +000058if __name__ == '__main__':
59 file = sys.argv[0]
60else:
61 file = __file__
62testdir = os.path.dirname(file) or os.curdir
Raymond Hettinger267b8682005-03-27 10:47:39 +000063directory = testdir + os.sep + TESTDATADIR + os.sep
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000064
Raymond Hettinger267b8682005-03-27 10:47:39 +000065skip_expected = not os.path.isdir(directory)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000066
Mark Dickinson539bff42009-10-08 16:28:39 +000067# list of individual .decTest test ids that correspond to tests that
68# we're skipping for one reason or another.
69skipped_test_ids = [
70 'scbx164', # skipping apparently implementation-specific scaleb
71 'scbx165', # tests, pending clarification of scaleb rules.
72]
73
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000074# Make sure it actually raises errors when not expected and caught in flags
75# Slower, since it runs some things several times.
76EXTENDEDERRORTEST = False
77
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000078#Map the test cases' error names to the actual errors
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000079ErrorNames = {'clamped' : Clamped,
Raymond Hettinger5aa478b2004-07-09 10:02:53 +000080 'conversion_syntax' : InvalidOperation,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000081 'division_by_zero' : DivisionByZero,
Raymond Hettinger5aa478b2004-07-09 10:02:53 +000082 'division_impossible' : InvalidOperation,
83 'division_undefined' : InvalidOperation,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000084 'inexact' : Inexact,
Raymond Hettinger5aa478b2004-07-09 10:02:53 +000085 'invalid_context' : InvalidOperation,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000086 'invalid_operation' : InvalidOperation,
87 'overflow' : Overflow,
88 'rounded' : Rounded,
89 'subnormal' : Subnormal,
90 'underflow' : Underflow}
91
92
93def Nonfunction(*args):
94 """Doesn't do anything."""
95 return None
96
97RoundingDict = {'ceiling' : ROUND_CEILING, #Maps test-case names to roundings.
98 'down' : ROUND_DOWN,
99 'floor' : ROUND_FLOOR,
100 'half_down' : ROUND_HALF_DOWN,
101 'half_even' : ROUND_HALF_EVEN,
102 'half_up' : ROUND_HALF_UP,
Facundo Batista353750c2007-09-13 18:13:15 +0000103 'up' : ROUND_UP,
104 '05up' : ROUND_05UP}
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000105
106# Name adapter to be able to change the Decimal and Context
107# interface without changing the test files from Cowlishaw
Facundo Batista1a191df2007-10-02 17:01:24 +0000108nameAdapter = {'and':'logical_and',
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000109 'apply':'_apply',
Facundo Batista353750c2007-09-13 18:13:15 +0000110 'class':'number_class',
111 'comparesig':'compare_signal',
112 'comparetotal':'compare_total',
113 'comparetotmag':'compare_total_mag',
Facundo Batista353750c2007-09-13 18:13:15 +0000114 'copy':'copy_decimal',
Facundo Batista1a191df2007-10-02 17:01:24 +0000115 'copyabs':'copy_abs',
Facundo Batista353750c2007-09-13 18:13:15 +0000116 'copynegate':'copy_negate',
117 'copysign':'copy_sign',
Facundo Batista1a191df2007-10-02 17:01:24 +0000118 'divideint':'divide_int',
Facundo Batista353750c2007-09-13 18:13:15 +0000119 'invert':'logical_invert',
Facundo Batista1a191df2007-10-02 17:01:24 +0000120 'iscanonical':'is_canonical',
121 'isfinite':'is_finite',
122 'isinfinite':'is_infinite',
123 'isnan':'is_nan',
124 'isnormal':'is_normal',
125 'isqnan':'is_qnan',
126 'issigned':'is_signed',
127 'issnan':'is_snan',
128 'issubnormal':'is_subnormal',
129 'iszero':'is_zero',
Facundo Batista353750c2007-09-13 18:13:15 +0000130 'maxmag':'max_mag',
131 'minmag':'min_mag',
132 'nextminus':'next_minus',
133 'nextplus':'next_plus',
134 'nexttoward':'next_toward',
Facundo Batista1a191df2007-10-02 17:01:24 +0000135 'or':'logical_or',
Facundo Batista353750c2007-09-13 18:13:15 +0000136 'reduce':'normalize',
Facundo Batista1a191df2007-10-02 17:01:24 +0000137 'remaindernear':'remainder_near',
138 'samequantum':'same_quantum',
139 'squareroot':'sqrt',
140 'toeng':'to_eng_string',
141 'tointegral':'to_integral_value',
142 'tointegralx':'to_integral_exact',
143 'tosci':'to_sci_string',
144 'xor':'logical_xor',
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000145 }
146
Facundo Batista1a191df2007-10-02 17:01:24 +0000147# The following functions return True/False rather than a Decimal instance
148
149LOGICAL_FUNCTIONS = (
150 'is_canonical',
151 'is_finite',
152 'is_infinite',
153 'is_nan',
154 'is_normal',
155 'is_qnan',
156 'is_signed',
157 'is_snan',
158 'is_subnormal',
159 'is_zero',
160 'same_quantum',
161 )
162
Facundo Batista353750c2007-09-13 18:13:15 +0000163# For some operations (currently exp, ln, log10, power), the decNumber
164# reference implementation imposes additional restrictions on the
165# context and operands. These restrictions are not part of the
166# specification; however, the effect of these restrictions does show
167# up in some of the testcases. We skip testcases that violate these
168# restrictions, since Decimal behaves differently from decNumber for
169# these testcases so these testcases would otherwise fail.
170
171decNumberRestricted = ('power', 'ln', 'log10', 'exp')
172DEC_MAX_MATH = 999999
173def outside_decNumber_bounds(v, context):
174 if (context.prec > DEC_MAX_MATH or
175 context.Emax > DEC_MAX_MATH or
176 -context.Emin > DEC_MAX_MATH):
177 return True
178 if not v._is_special and v and (
Facundo Batista353750c2007-09-13 18:13:15 +0000179 v.adjusted() > DEC_MAX_MATH or
180 v.adjusted() < 1-2*DEC_MAX_MATH):
181 return True
182 return False
183
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000184class DecimalTest(unittest.TestCase):
185 """Class which tests the Decimal class against the test cases.
186
187 Changed for unittest.
188 """
189 def setUp(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000190 self.context = Context()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000191 self.ignore_list = ['#']
192 # Basically, a # means return NaN InvalidOperation.
193 # Different from a sNaN in trim
194
195 self.ChangeDict = {'precision' : self.change_precision,
196 'rounding' : self.change_rounding_method,
197 'maxexponent' : self.change_max_exponent,
198 'minexponent' : self.change_min_exponent,
199 'clamp' : self.change_clamp}
200
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000201 def eval_file(self, file):
202 global skip_expected
203 if skip_expected:
Benjamin Petersonbec087f2009-03-26 21:10:30 +0000204 raise unittest.SkipTest
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000205 return
Florent Xicluna8f43cec2010-03-21 10:51:40 +0000206 for line in open(file):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000207 line = line.replace('\r\n', '').replace('\n', '')
Raymond Hettinger5aa478b2004-07-09 10:02:53 +0000208 #print line
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000209 try:
210 t = self.eval_line(line)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000211 except DecimalException, exception:
212 #Exception raised where there shoudn't have been one.
213 self.fail('Exception "'+exception.__class__.__name__ + '" raised on line '+line)
214
215 return
216
217 def eval_line(self, s):
218 if s.find(' -> ') >= 0 and s[:2] != '--' and not s.startswith(' --'):
219 s = (s.split('->')[0] + '->' +
220 s.split('->')[1].split('--')[0]).strip()
221 else:
222 s = s.split('--')[0].strip()
223
224 for ignore in self.ignore_list:
225 if s.find(ignore) >= 0:
226 #print s.split()[0], 'NotImplemented--', ignore
227 return
228 if not s:
229 return
230 elif ':' in s:
231 return self.eval_directive(s)
232 else:
233 return self.eval_equation(s)
234
235 def eval_directive(self, s):
236 funct, value = map(lambda x: x.strip().lower(), s.split(':'))
237 if funct == 'rounding':
238 value = RoundingDict[value]
239 else:
240 try:
241 value = int(value)
242 except ValueError:
243 pass
244
245 funct = self.ChangeDict.get(funct, Nonfunction)
246 funct(value)
247
248 def eval_equation(self, s):
249 #global DEFAULT_PRECISION
250 #print DEFAULT_PRECISION
Raymond Hettingered20ad82004-09-04 20:09:13 +0000251
252 if not TEST_ALL and random.random() < 0.90:
253 return
254
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000255 try:
256 Sides = s.split('->')
257 L = Sides[0].strip().split()
258 id = L[0]
Facundo Batista353750c2007-09-13 18:13:15 +0000259 if DEBUG:
260 print "Test ", id,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000261 funct = L[1].lower()
262 valstemp = L[2:]
263 L = Sides[1].strip().split()
264 ans = L[0]
265 exceptions = L[1:]
266 except (TypeError, AttributeError, IndexError):
Raymond Hettingerd87ac8f2004-07-09 10:52:54 +0000267 raise InvalidOperation
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000268 def FixQuotes(val):
269 val = val.replace("''", 'SingleQuote').replace('""', 'DoubleQuote')
270 val = val.replace("'", '').replace('"', '')
271 val = val.replace('SingleQuote', "'").replace('DoubleQuote', '"')
272 return val
Mark Dickinson539bff42009-10-08 16:28:39 +0000273
274 if id in skipped_test_ids:
275 return
276
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000277 fname = nameAdapter.get(funct, funct)
278 if fname == 'rescale':
279 return
280 funct = getattr(self.context, fname)
281 vals = []
282 conglomerate = ''
283 quote = 0
284 theirexceptions = [ErrorNames[x.lower()] for x in exceptions]
285
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000286 for exception in Signals:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000287 self.context.traps[exception] = 1 #Catch these bugs...
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000288 for exception in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000289 self.context.traps[exception] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000290 for i, val in enumerate(valstemp):
291 if val.count("'") % 2 == 1:
292 quote = 1 - quote
293 if quote:
294 conglomerate = conglomerate + ' ' + val
295 continue
296 else:
297 val = conglomerate + val
298 conglomerate = ''
299 v = FixQuotes(val)
300 if fname in ('to_sci_string', 'to_eng_string'):
301 if EXTENDEDERRORTEST:
302 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000303 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000304 try:
305 funct(self.context.create_decimal(v))
306 except error:
307 pass
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000308 except Signals, e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000309 self.fail("Raised %s in %s when %s disabled" % \
310 (e, s, error))
311 else:
312 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000313 self.context.traps[error] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000314 v = self.context.create_decimal(v)
315 else:
Facundo Batista353750c2007-09-13 18:13:15 +0000316 v = Decimal(v, self.context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000317 vals.append(v)
318
319 ans = FixQuotes(ans)
320
Facundo Batista353750c2007-09-13 18:13:15 +0000321 # skip tests that are related to bounds imposed in the decNumber
322 # reference implementation
323 if fname in decNumberRestricted:
324 if fname == 'power':
325 if not (vals[1]._isinteger() and
326 -1999999997 <= vals[1] <= 999999999):
327 if outside_decNumber_bounds(vals[0], self.context) or \
328 outside_decNumber_bounds(vals[1], self.context):
329 #print "Skipping test %s" % s
330 return
331 else:
332 if outside_decNumber_bounds(vals[0], self.context):
333 #print "Skipping test %s" % s
334 return
335
336
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000337 if EXTENDEDERRORTEST and fname not in ('to_sci_string', 'to_eng_string'):
338 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000339 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000340 try:
341 funct(*vals)
342 except error:
343 pass
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000344 except Signals, e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000345 self.fail("Raised %s in %s when %s disabled" % \
346 (e, s, error))
347 else:
348 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000349 self.context.traps[error] = 0
Facundo Batista353750c2007-09-13 18:13:15 +0000350 if DEBUG:
351 print "--", self.context
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000352 try:
353 result = str(funct(*vals))
Facundo Batista1a191df2007-10-02 17:01:24 +0000354 if fname in LOGICAL_FUNCTIONS:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000355 result = str(int(eval(result))) # 'True', 'False' -> '1', '0'
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000356 except Signals, error:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000357 self.fail("Raised %s in %s" % (error, s))
358 except: #Catch any error long enough to state the test case.
359 print "ERROR:", s
360 raise
361
362 myexceptions = self.getexceptions()
Raymond Hettingerbf440692004-07-10 14:14:37 +0000363 self.context.clear_flags()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000364
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000365 self.assertEqual(result, ans,
366 'Incorrect answer for ' + s + ' -- got ' + result)
Florent Xicluna8f43cec2010-03-21 10:51:40 +0000367 self.assertItemsEqual(myexceptions, theirexceptions,
Facundo Batista353750c2007-09-13 18:13:15 +0000368 'Incorrect flags set in ' + s + ' -- got ' + str(myexceptions))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000369 return
370
371 def getexceptions(self):
Raymond Hettingerf63ba432004-08-17 05:42:09 +0000372 return [e for e in Signals if self.context.flags[e]]
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000373
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000374 def change_precision(self, prec):
375 self.context.prec = prec
376 def change_rounding_method(self, rounding):
377 self.context.rounding = rounding
378 def change_min_exponent(self, exp):
379 self.context.Emin = exp
380 def change_max_exponent(self, exp):
381 self.context.Emax = exp
382 def change_clamp(self, clamp):
383 self.context._clamp = clamp
384
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000385
386
387# The following classes test the behaviour of Decimal according to PEP 327
388
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000389class DecimalExplicitConstructionTest(unittest.TestCase):
390 '''Unit tests for Explicit Construction cases of Decimal.'''
391
392 def test_explicit_empty(self):
393 self.assertEqual(Decimal(), Decimal("0"))
394
395 def test_explicit_from_None(self):
396 self.assertRaises(TypeError, Decimal, None)
397
398 def test_explicit_from_int(self):
399
400 #positive
401 d = Decimal(45)
402 self.assertEqual(str(d), '45')
403
404 #very large positive
405 d = Decimal(500000123)
406 self.assertEqual(str(d), '500000123')
407
408 #negative
409 d = Decimal(-45)
410 self.assertEqual(str(d), '-45')
411
412 #zero
413 d = Decimal(0)
414 self.assertEqual(str(d), '0')
415
416 def test_explicit_from_string(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000417
418 #empty
419 self.assertEqual(str(Decimal('')), 'NaN')
420
421 #int
422 self.assertEqual(str(Decimal('45')), '45')
423
424 #float
425 self.assertEqual(str(Decimal('45.34')), '45.34')
426
427 #engineer notation
428 self.assertEqual(str(Decimal('45e2')), '4.5E+3')
429
430 #just not a number
431 self.assertEqual(str(Decimal('ugly')), 'NaN')
432
Mark Dickinson59bc20b2008-01-12 01:56:00 +0000433 #leading and trailing whitespace permitted
434 self.assertEqual(str(Decimal('1.3E4 \n')), '1.3E+4')
435 self.assertEqual(str(Decimal(' -7.89')), '-7.89')
436
Mark Dickinson8e85ffa2008-03-25 18:47:59 +0000437 #unicode strings should be permitted
438 self.assertEqual(str(Decimal(u'0E-017')), '0E-17')
439 self.assertEqual(str(Decimal(u'45')), '45')
440 self.assertEqual(str(Decimal(u'-Inf')), '-Infinity')
441 self.assertEqual(str(Decimal(u'NaN123')), 'NaN123')
442
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000443 def test_explicit_from_tuples(self):
444
445 #zero
446 d = Decimal( (0, (0,), 0) )
447 self.assertEqual(str(d), '0')
448
449 #int
450 d = Decimal( (1, (4, 5), 0) )
451 self.assertEqual(str(d), '-45')
452
453 #float
454 d = Decimal( (0, (4, 5, 3, 4), -2) )
455 self.assertEqual(str(d), '45.34')
456
457 #weird
458 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
459 self.assertEqual(str(d), '-4.34913534E-17')
460
461 #wrong number of items
462 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1)) )
463
464 #bad sign
465 self.assertRaises(ValueError, Decimal, (8, (4, 3, 4, 9, 1), 2) )
Facundo Batista9b5e2312007-10-19 19:25:57 +0000466 self.assertRaises(ValueError, Decimal, (0., (4, 3, 4, 9, 1), 2) )
467 self.assertRaises(ValueError, Decimal, (Decimal(1), (4, 3, 4, 9, 1), 2))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000468
469 #bad exp
470 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 'wrong!') )
Facundo Batista9b5e2312007-10-19 19:25:57 +0000471 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 0.) )
472 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), '1') )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000473
474 #bad coefficients
475 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, None, 1), 2) )
476 self.assertRaises(ValueError, Decimal, (1, (4, -3, 4, 9, 1), 2) )
Facundo Batista9b5e2312007-10-19 19:25:57 +0000477 self.assertRaises(ValueError, Decimal, (1, (4, 10, 4, 9, 1), 2) )
Facundo Batista72bc54f2007-11-23 17:59:00 +0000478 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 'a', 1), 2) )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000479
Antoine Pitrou6032c252010-03-30 18:49:45 +0000480 def test_explicit_from_bool(self):
481 self.assertIs(bool(Decimal(0)), False)
482 self.assertIs(bool(Decimal(1)), True)
483 self.assertEqual(Decimal(False), Decimal(0))
484 self.assertEqual(Decimal(True), Decimal(1))
485
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000486 def test_explicit_from_Decimal(self):
487
488 #positive
489 d = Decimal(45)
490 e = Decimal(d)
491 self.assertEqual(str(e), '45')
492 self.assertNotEqual(id(d), id(e))
493
494 #very large positive
495 d = Decimal(500000123)
496 e = Decimal(d)
497 self.assertEqual(str(e), '500000123')
498 self.assertNotEqual(id(d), id(e))
499
500 #negative
501 d = Decimal(-45)
502 e = Decimal(d)
503 self.assertEqual(str(e), '-45')
504 self.assertNotEqual(id(d), id(e))
505
506 #zero
507 d = Decimal(0)
508 e = Decimal(d)
509 self.assertEqual(str(e), '0')
510 self.assertNotEqual(id(d), id(e))
511
512 def test_explicit_context_create_decimal(self):
513
514 nc = copy.copy(getcontext())
515 nc.prec = 3
516
517 # empty
Raymond Hettingerfed52962004-07-14 15:41:57 +0000518 d = Decimal()
519 self.assertEqual(str(d), '0')
520 d = nc.create_decimal()
521 self.assertEqual(str(d), '0')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000522
523 # from None
524 self.assertRaises(TypeError, nc.create_decimal, None)
525
526 # from int
527 d = nc.create_decimal(456)
Ezio Melottib0f5adc2010-01-24 16:58:36 +0000528 self.assertIsInstance(d, Decimal)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000529 self.assertEqual(nc.create_decimal(45678),
530 nc.create_decimal('457E+2'))
531
532 # from string
533 d = Decimal('456789')
534 self.assertEqual(str(d), '456789')
535 d = nc.create_decimal('456789')
536 self.assertEqual(str(d), '4.57E+5')
Mark Dickinson59bc20b2008-01-12 01:56:00 +0000537 # leading and trailing whitespace should result in a NaN;
538 # spaces are already checked in Cowlishaw's test-suite, so
539 # here we just check that a trailing newline results in a NaN
540 self.assertEqual(str(nc.create_decimal('3.14\n')), 'NaN')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000541
542 # from tuples
543 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
544 self.assertEqual(str(d), '-4.34913534E-17')
545 d = nc.create_decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
546 self.assertEqual(str(d), '-4.35E-17')
547
548 # from Decimal
549 prevdec = Decimal(500000123)
550 d = Decimal(prevdec)
551 self.assertEqual(str(d), '500000123')
552 d = nc.create_decimal(prevdec)
553 self.assertEqual(str(d), '5.00E+8')
554
Mark Dickinson4326ad82009-08-02 10:59:36 +0000555 def test_unicode_digits(self):
556 test_values = {
557 u'\uff11': '1',
558 u'\u0660.\u0660\u0663\u0667\u0662e-\u0663' : '0.0000372',
559 u'-nan\u0c68\u0c6a\u0c66\u0c66' : '-NaN2400',
560 }
561 for input, expected in test_values.items():
562 self.assertEqual(str(Decimal(input)), expected)
563
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000564
565class DecimalImplicitConstructionTest(unittest.TestCase):
566 '''Unit tests for Implicit Construction cases of Decimal.'''
567
568 def test_implicit_from_None(self):
569 self.assertRaises(TypeError, eval, 'Decimal(5) + None', globals())
570
571 def test_implicit_from_int(self):
572 #normal
573 self.assertEqual(str(Decimal(5) + 45), '50')
574 #exceeding precision
575 self.assertEqual(Decimal(5) + 123456789000, Decimal(123456789000))
576
577 def test_implicit_from_string(self):
578 self.assertRaises(TypeError, eval, 'Decimal(5) + "3"', globals())
579
580 def test_implicit_from_float(self):
581 self.assertRaises(TypeError, eval, 'Decimal(5) + 2.2', globals())
582
583 def test_implicit_from_Decimal(self):
584 self.assertEqual(Decimal(5) + Decimal(45), Decimal(50))
585
Raymond Hettinger267b8682005-03-27 10:47:39 +0000586 def test_rop(self):
587 # Allow other classes to be trained to interact with Decimals
588 class E:
589 def __divmod__(self, other):
590 return 'divmod ' + str(other)
591 def __rdivmod__(self, other):
592 return str(other) + ' rdivmod'
593 def __lt__(self, other):
594 return 'lt ' + str(other)
595 def __gt__(self, other):
596 return 'gt ' + str(other)
597 def __le__(self, other):
598 return 'le ' + str(other)
599 def __ge__(self, other):
600 return 'ge ' + str(other)
601 def __eq__(self, other):
602 return 'eq ' + str(other)
603 def __ne__(self, other):
604 return 'ne ' + str(other)
605
606 self.assertEqual(divmod(E(), Decimal(10)), 'divmod 10')
607 self.assertEqual(divmod(Decimal(10), E()), '10 rdivmod')
608 self.assertEqual(eval('Decimal(10) < E()'), 'gt 10')
609 self.assertEqual(eval('Decimal(10) > E()'), 'lt 10')
610 self.assertEqual(eval('Decimal(10) <= E()'), 'ge 10')
611 self.assertEqual(eval('Decimal(10) >= E()'), 'le 10')
612 self.assertEqual(eval('Decimal(10) == E()'), 'eq 10')
613 self.assertEqual(eval('Decimal(10) != E()'), 'ne 10')
614
615 # insert operator methods and then exercise them
Georg Brandl96c3f7f2006-03-28 08:06:35 +0000616 oplist = [
617 ('+', '__add__', '__radd__'),
618 ('-', '__sub__', '__rsub__'),
619 ('*', '__mul__', '__rmul__'),
620 ('%', '__mod__', '__rmod__'),
621 ('//', '__floordiv__', '__rfloordiv__'),
622 ('**', '__pow__', '__rpow__')
623 ]
Florent Xicluna8f43cec2010-03-21 10:51:40 +0000624 with check_py3k_warnings():
625 if 1 / 2 == 0:
626 # testing with classic division, so add __div__
627 oplist.append(('/', '__div__', '__rdiv__'))
628 else:
629 # testing with -Qnew, so add __truediv__
630 oplist.append(('/', '__truediv__', '__rtruediv__'))
Anthony Baxter4ef3a232006-03-30 12:59:11 +0000631
Georg Brandl96c3f7f2006-03-28 08:06:35 +0000632 for sym, lop, rop in oplist:
Raymond Hettinger267b8682005-03-27 10:47:39 +0000633 setattr(E, lop, lambda self, other: 'str' + lop + str(other))
634 setattr(E, rop, lambda self, other: str(other) + rop + 'str')
635 self.assertEqual(eval('E()' + sym + 'Decimal(10)'),
636 'str' + lop + '10')
637 self.assertEqual(eval('Decimal(10)' + sym + 'E()'),
638 '10' + rop + 'str')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000639
Mark Dickinson277859d2009-03-17 23:03:46 +0000640
Mark Dickinson1ddf1d82008-02-29 02:16:37 +0000641class DecimalFormatTest(unittest.TestCase):
642 '''Unit tests for the format function.'''
643 def test_formatting(self):
644 # triples giving a format, a Decimal, and the expected result
645 test_values = [
646 ('e', '0E-15', '0e-15'),
647 ('e', '2.3E-15', '2.3e-15'),
648 ('e', '2.30E+2', '2.30e+2'), # preserve significant zeros
649 ('e', '2.30000E-15', '2.30000e-15'),
650 ('e', '1.23456789123456789e40', '1.23456789123456789e+40'),
651 ('e', '1.5', '1.5e+0'),
652 ('e', '0.15', '1.5e-1'),
653 ('e', '0.015', '1.5e-2'),
654 ('e', '0.0000000000015', '1.5e-12'),
655 ('e', '15.0', '1.50e+1'),
656 ('e', '-15', '-1.5e+1'),
657 ('e', '0', '0e+0'),
658 ('e', '0E1', '0e+1'),
659 ('e', '0.0', '0e-1'),
660 ('e', '0.00', '0e-2'),
661 ('.6e', '0E-15', '0.000000e-9'),
662 ('.6e', '0', '0.000000e+6'),
663 ('.6e', '9.999999', '9.999999e+0'),
664 ('.6e', '9.9999999', '1.000000e+1'),
665 ('.6e', '-1.23e5', '-1.230000e+5'),
666 ('.6e', '1.23456789e-3', '1.234568e-3'),
667 ('f', '0', '0'),
668 ('f', '0.0', '0.0'),
669 ('f', '0E-2', '0.00'),
670 ('f', '0.00E-8', '0.0000000000'),
671 ('f', '0E1', '0'), # loses exponent information
672 ('f', '3.2E1', '32'),
673 ('f', '3.2E2', '320'),
674 ('f', '3.20E2', '320'),
675 ('f', '3.200E2', '320.0'),
676 ('f', '3.2E-6', '0.0000032'),
677 ('.6f', '0E-15', '0.000000'), # all zeros treated equally
678 ('.6f', '0E1', '0.000000'),
679 ('.6f', '0', '0.000000'),
680 ('.0f', '0', '0'), # no decimal point
681 ('.0f', '0e-2', '0'),
682 ('.0f', '3.14159265', '3'),
683 ('.1f', '3.14159265', '3.1'),
684 ('.4f', '3.14159265', '3.1416'),
685 ('.6f', '3.14159265', '3.141593'),
686 ('.7f', '3.14159265', '3.1415926'), # round-half-even!
687 ('.8f', '3.14159265', '3.14159265'),
688 ('.9f', '3.14159265', '3.141592650'),
689
690 ('g', '0', '0'),
691 ('g', '0.0', '0.0'),
692 ('g', '0E1', '0e+1'),
693 ('G', '0E1', '0E+1'),
694 ('g', '0E-5', '0.00000'),
695 ('g', '0E-6', '0.000000'),
696 ('g', '0E-7', '0e-7'),
697 ('g', '-0E2', '-0e+2'),
698 ('.0g', '3.14159265', '3'), # 0 sig fig -> 1 sig fig
699 ('.1g', '3.14159265', '3'),
700 ('.2g', '3.14159265', '3.1'),
701 ('.5g', '3.14159265', '3.1416'),
702 ('.7g', '3.14159265', '3.141593'),
703 ('.8g', '3.14159265', '3.1415926'), # round-half-even!
704 ('.9g', '3.14159265', '3.14159265'),
705 ('.10g', '3.14159265', '3.14159265'), # don't pad
706
707 ('%', '0E1', '0%'),
708 ('%', '0E0', '0%'),
709 ('%', '0E-1', '0%'),
710 ('%', '0E-2', '0%'),
711 ('%', '0E-3', '0.0%'),
712 ('%', '0E-4', '0.00%'),
713
714 ('.3%', '0', '0.000%'), # all zeros treated equally
715 ('.3%', '0E10', '0.000%'),
716 ('.3%', '0E-10', '0.000%'),
717 ('.3%', '2.34', '234.000%'),
718 ('.3%', '1.234567', '123.457%'),
719 ('.0%', '1.23', '123%'),
720
721 ('e', 'NaN', 'NaN'),
722 ('f', '-NaN123', '-NaN123'),
723 ('+g', 'NaN456', '+NaN456'),
724 ('.3e', 'Inf', 'Infinity'),
725 ('.16f', '-Inf', '-Infinity'),
726 ('.0g', '-sNaN', '-sNaN'),
727
728 ('', '1.00', '1.00'),
Mark Dickinsonb065e522009-03-17 18:01:03 +0000729
Mark Dickinson277859d2009-03-17 23:03:46 +0000730 # test alignment and padding
Mark Dickinson5cfa8042009-09-08 20:20:19 +0000731 ('6', '123', ' 123'),
Mark Dickinsonb065e522009-03-17 18:01:03 +0000732 ('<6', '123', '123 '),
733 ('>6', '123', ' 123'),
734 ('^6', '123', ' 123 '),
735 ('=+6', '123', '+ 123'),
Mark Dickinson277859d2009-03-17 23:03:46 +0000736 ('#<10', 'NaN', 'NaN#######'),
737 ('#<10', '-4.3', '-4.3######'),
738 ('#<+10', '0.0130', '+0.0130###'),
739 ('#< 10', '0.0130', ' 0.0130###'),
740 ('@>10', '-Inf', '@-Infinity'),
741 ('#>5', '-Inf', '-Infinity'),
742 ('?^5', '123', '?123?'),
743 ('%^6', '123', '%123%%'),
744 (' ^6', '-45.6', '-45.6 '),
745 ('/=10', '-45.6', '-/////45.6'),
746 ('/=+10', '45.6', '+/////45.6'),
747 ('/= 10', '45.6', ' /////45.6'),
748
749 # thousands separator
750 (',', '1234567', '1,234,567'),
751 (',', '123456', '123,456'),
752 (',', '12345', '12,345'),
753 (',', '1234', '1,234'),
754 (',', '123', '123'),
755 (',', '12', '12'),
756 (',', '1', '1'),
757 (',', '0', '0'),
758 (',', '-1234567', '-1,234,567'),
759 (',', '-123456', '-123,456'),
760 ('7,', '123456', '123,456'),
Mark Dickinson5cfa8042009-09-08 20:20:19 +0000761 ('8,', '123456', ' 123,456'),
Mark Dickinson277859d2009-03-17 23:03:46 +0000762 ('08,', '123456', '0,123,456'), # special case: extra 0 needed
763 ('+08,', '123456', '+123,456'), # but not if there's a sign
764 (' 08,', '123456', ' 123,456'),
765 ('08,', '-123456', '-123,456'),
766 ('+09,', '123456', '+0,123,456'),
767 # ... with fractional part...
768 ('07,', '1234.56', '1,234.56'),
769 ('08,', '1234.56', '1,234.56'),
770 ('09,', '1234.56', '01,234.56'),
771 ('010,', '1234.56', '001,234.56'),
772 ('011,', '1234.56', '0,001,234.56'),
773 ('012,', '1234.56', '0,001,234.56'),
774 ('08,.1f', '1234.5', '01,234.5'),
775 # no thousands separators in fraction part
776 (',', '1.23456789', '1.23456789'),
777 (',%', '123.456789', '12,345.6789%'),
778 (',e', '123456', '1.23456e+5'),
779 (',E', '123456', '1.23456E+5'),
Mark Dickinson491ea552009-09-07 16:17:41 +0000780
781 # issue 6850
782 ('a=-7.0', '0.12345', 'aaaa0.1'),
Mark Dickinson1ddf1d82008-02-29 02:16:37 +0000783 ]
784 for fmt, d, result in test_values:
785 self.assertEqual(format(Decimal(d), fmt), result)
786
Mark Dickinson277859d2009-03-17 23:03:46 +0000787 def test_n_format(self):
788 try:
789 from locale import CHAR_MAX
790 except ImportError:
791 return
792
793 # Set up some localeconv-like dictionaries
794 en_US = {
795 'decimal_point' : '.',
796 'grouping' : [3, 3, 0],
797 'thousands_sep': ','
798 }
799
800 fr_FR = {
801 'decimal_point' : ',',
802 'grouping' : [CHAR_MAX],
803 'thousands_sep' : ''
804 }
805
806 ru_RU = {
807 'decimal_point' : ',',
808 'grouping' : [3, 3, 0],
809 'thousands_sep' : ' '
810 }
811
812 crazy = {
813 'decimal_point' : '&',
814 'grouping' : [1, 4, 2, CHAR_MAX],
815 'thousands_sep' : '-'
816 }
817
818
819 def get_fmt(x, locale, fmt='n'):
820 return Decimal.__format__(Decimal(x), fmt, _localeconv=locale)
821
822 self.assertEqual(get_fmt(Decimal('12.7'), en_US), '12.7')
823 self.assertEqual(get_fmt(Decimal('12.7'), fr_FR), '12,7')
824 self.assertEqual(get_fmt(Decimal('12.7'), ru_RU), '12,7')
825 self.assertEqual(get_fmt(Decimal('12.7'), crazy), '1-2&7')
826
827 self.assertEqual(get_fmt(123456789, en_US), '123,456,789')
828 self.assertEqual(get_fmt(123456789, fr_FR), '123456789')
829 self.assertEqual(get_fmt(123456789, ru_RU), '123 456 789')
830 self.assertEqual(get_fmt(1234567890123, crazy), '123456-78-9012-3')
831
832 self.assertEqual(get_fmt(123456789, en_US, '.6n'), '1.23457e+8')
833 self.assertEqual(get_fmt(123456789, fr_FR, '.6n'), '1,23457e+8')
834 self.assertEqual(get_fmt(123456789, ru_RU, '.6n'), '1,23457e+8')
835 self.assertEqual(get_fmt(123456789, crazy, '.6n'), '1&23457e+8')
836
Mark Dickinsonb14514a2009-03-18 08:22:51 +0000837 # zero padding
838 self.assertEqual(get_fmt(1234, fr_FR, '03n'), '1234')
839 self.assertEqual(get_fmt(1234, fr_FR, '04n'), '1234')
840 self.assertEqual(get_fmt(1234, fr_FR, '05n'), '01234')
841 self.assertEqual(get_fmt(1234, fr_FR, '06n'), '001234')
842
843 self.assertEqual(get_fmt(12345, en_US, '05n'), '12,345')
844 self.assertEqual(get_fmt(12345, en_US, '06n'), '12,345')
845 self.assertEqual(get_fmt(12345, en_US, '07n'), '012,345')
846 self.assertEqual(get_fmt(12345, en_US, '08n'), '0,012,345')
847 self.assertEqual(get_fmt(12345, en_US, '09n'), '0,012,345')
848 self.assertEqual(get_fmt(12345, en_US, '010n'), '00,012,345')
849
850 self.assertEqual(get_fmt(123456, crazy, '06n'), '1-2345-6')
851 self.assertEqual(get_fmt(123456, crazy, '07n'), '1-2345-6')
852 self.assertEqual(get_fmt(123456, crazy, '08n'), '1-2345-6')
853 self.assertEqual(get_fmt(123456, crazy, '09n'), '01-2345-6')
854 self.assertEqual(get_fmt(123456, crazy, '010n'), '0-01-2345-6')
855 self.assertEqual(get_fmt(123456, crazy, '011n'), '0-01-2345-6')
856 self.assertEqual(get_fmt(123456, crazy, '012n'), '00-01-2345-6')
857 self.assertEqual(get_fmt(123456, crazy, '013n'), '000-01-2345-6')
858
Mark Dickinson277859d2009-03-17 23:03:46 +0000859
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000860class DecimalArithmeticOperatorsTest(unittest.TestCase):
861 '''Unit tests for all arithmetic operators, binary and unary.'''
862
863 def test_addition(self):
864
865 d1 = Decimal('-11.1')
866 d2 = Decimal('22.2')
867
868 #two Decimals
869 self.assertEqual(d1+d2, Decimal('11.1'))
870 self.assertEqual(d2+d1, Decimal('11.1'))
871
872 #with other type, left
873 c = d1 + 5
874 self.assertEqual(c, Decimal('-6.1'))
875 self.assertEqual(type(c), type(d1))
876
877 #with other type, right
878 c = 5 + d1
879 self.assertEqual(c, Decimal('-6.1'))
880 self.assertEqual(type(c), type(d1))
881
882 #inline with decimal
883 d1 += d2
884 self.assertEqual(d1, Decimal('11.1'))
885
886 #inline with other type
887 d1 += 5
888 self.assertEqual(d1, Decimal('16.1'))
889
890 def test_subtraction(self):
891
892 d1 = Decimal('-11.1')
893 d2 = Decimal('22.2')
894
895 #two Decimals
896 self.assertEqual(d1-d2, Decimal('-33.3'))
897 self.assertEqual(d2-d1, Decimal('33.3'))
898
899 #with other type, left
900 c = d1 - 5
901 self.assertEqual(c, Decimal('-16.1'))
902 self.assertEqual(type(c), type(d1))
903
904 #with other type, right
905 c = 5 - d1
906 self.assertEqual(c, Decimal('16.1'))
907 self.assertEqual(type(c), type(d1))
908
909 #inline with decimal
910 d1 -= d2
911 self.assertEqual(d1, Decimal('-33.3'))
912
913 #inline with other type
914 d1 -= 5
915 self.assertEqual(d1, Decimal('-38.3'))
916
917 def test_multiplication(self):
918
919 d1 = Decimal('-5')
920 d2 = Decimal('3')
921
922 #two Decimals
923 self.assertEqual(d1*d2, Decimal('-15'))
924 self.assertEqual(d2*d1, Decimal('-15'))
925
926 #with other type, left
927 c = d1 * 5
928 self.assertEqual(c, Decimal('-25'))
929 self.assertEqual(type(c), type(d1))
930
931 #with other type, right
932 c = 5 * d1
933 self.assertEqual(c, Decimal('-25'))
934 self.assertEqual(type(c), type(d1))
935
936 #inline with decimal
937 d1 *= d2
938 self.assertEqual(d1, Decimal('-15'))
939
940 #inline with other type
941 d1 *= 5
942 self.assertEqual(d1, Decimal('-75'))
943
944 def test_division(self):
945
946 d1 = Decimal('-5')
947 d2 = Decimal('2')
948
949 #two Decimals
950 self.assertEqual(d1/d2, Decimal('-2.5'))
951 self.assertEqual(d2/d1, Decimal('-0.4'))
952
953 #with other type, left
954 c = d1 / 4
955 self.assertEqual(c, Decimal('-1.25'))
956 self.assertEqual(type(c), type(d1))
957
958 #with other type, right
959 c = 4 / d1
960 self.assertEqual(c, Decimal('-0.8'))
961 self.assertEqual(type(c), type(d1))
962
963 #inline with decimal
964 d1 /= d2
965 self.assertEqual(d1, Decimal('-2.5'))
966
967 #inline with other type
968 d1 /= 4
969 self.assertEqual(d1, Decimal('-0.625'))
970
971 def test_floor_division(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000972
973 d1 = Decimal('5')
974 d2 = Decimal('2')
975
976 #two Decimals
977 self.assertEqual(d1//d2, Decimal('2'))
978 self.assertEqual(d2//d1, Decimal('0'))
979
980 #with other type, left
981 c = d1 // 4
982 self.assertEqual(c, Decimal('1'))
983 self.assertEqual(type(c), type(d1))
984
985 #with other type, right
986 c = 7 // d1
987 self.assertEqual(c, Decimal('1'))
988 self.assertEqual(type(c), type(d1))
989
990 #inline with decimal
991 d1 //= d2
992 self.assertEqual(d1, Decimal('2'))
993
994 #inline with other type
995 d1 //= 2
996 self.assertEqual(d1, Decimal('1'))
997
998 def test_powering(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000999
1000 d1 = Decimal('5')
1001 d2 = Decimal('2')
1002
1003 #two Decimals
1004 self.assertEqual(d1**d2, Decimal('25'))
1005 self.assertEqual(d2**d1, Decimal('32'))
1006
1007 #with other type, left
1008 c = d1 ** 4
1009 self.assertEqual(c, Decimal('625'))
1010 self.assertEqual(type(c), type(d1))
1011
1012 #with other type, right
1013 c = 7 ** d1
1014 self.assertEqual(c, Decimal('16807'))
1015 self.assertEqual(type(c), type(d1))
1016
1017 #inline with decimal
1018 d1 **= d2
1019 self.assertEqual(d1, Decimal('25'))
1020
1021 #inline with other type
1022 d1 **= 4
1023 self.assertEqual(d1, Decimal('390625'))
1024
1025 def test_module(self):
1026
1027 d1 = Decimal('5')
1028 d2 = Decimal('2')
1029
1030 #two Decimals
1031 self.assertEqual(d1%d2, Decimal('1'))
1032 self.assertEqual(d2%d1, Decimal('2'))
1033
1034 #with other type, left
1035 c = d1 % 4
1036 self.assertEqual(c, Decimal('1'))
1037 self.assertEqual(type(c), type(d1))
1038
1039 #with other type, right
1040 c = 7 % d1
1041 self.assertEqual(c, Decimal('2'))
1042 self.assertEqual(type(c), type(d1))
1043
1044 #inline with decimal
1045 d1 %= d2
1046 self.assertEqual(d1, Decimal('1'))
1047
1048 #inline with other type
1049 d1 %= 4
1050 self.assertEqual(d1, Decimal('1'))
1051
1052 def test_floor_div_module(self):
1053
1054 d1 = Decimal('5')
1055 d2 = Decimal('2')
1056
1057 #two Decimals
1058 (p, q) = divmod(d1, d2)
1059 self.assertEqual(p, Decimal('2'))
1060 self.assertEqual(q, Decimal('1'))
1061 self.assertEqual(type(p), type(d1))
1062 self.assertEqual(type(q), type(d1))
1063
1064 #with other type, left
1065 (p, q) = divmod(d1, 4)
1066 self.assertEqual(p, Decimal('1'))
1067 self.assertEqual(q, Decimal('1'))
1068 self.assertEqual(type(p), type(d1))
1069 self.assertEqual(type(q), type(d1))
1070
1071 #with other type, right
1072 (p, q) = divmod(7, d1)
1073 self.assertEqual(p, Decimal('1'))
1074 self.assertEqual(q, Decimal('2'))
1075 self.assertEqual(type(p), type(d1))
1076 self.assertEqual(type(q), type(d1))
1077
1078 def test_unary_operators(self):
1079 self.assertEqual(+Decimal(45), Decimal(+45)) # +
1080 self.assertEqual(-Decimal(45), Decimal(-45)) # -
1081 self.assertEqual(abs(Decimal(45)), abs(Decimal(-45))) # abs
1082
Mark Dickinson2fc92632008-02-06 22:10:50 +00001083 def test_nan_comparisons(self):
Mark Dickinsone096e822010-04-02 10:17:07 +00001084 # comparisons involving signaling nans signal InvalidOperation
1085
1086 # order comparisons (<, <=, >, >=) involving only quiet nans
1087 # also signal InvalidOperation
1088
1089 # equality comparisons (==, !=) involving only quiet nans
1090 # don't signal, but return False or True respectively.
1091
Mark Dickinson2fc92632008-02-06 22:10:50 +00001092 n = Decimal('NaN')
1093 s = Decimal('sNaN')
1094 i = Decimal('Inf')
1095 f = Decimal('2')
Mark Dickinsone096e822010-04-02 10:17:07 +00001096
1097 qnan_pairs = (n, n), (n, i), (i, n), (n, f), (f, n)
1098 snan_pairs = (s, n), (n, s), (s, i), (i, s), (s, f), (f, s), (s, s)
1099 order_ops = operator.lt, operator.le, operator.gt, operator.ge
1100 equality_ops = operator.eq, operator.ne
1101
1102 # results when InvalidOperation is not trapped
1103 for x, y in qnan_pairs + snan_pairs:
1104 for op in order_ops + equality_ops:
1105 got = op(x, y)
1106 expected = True if op is operator.ne else False
1107 self.assertIs(expected, got,
1108 "expected {0!r} for operator.{1}({2!r}, {3!r}); "
1109 "got {4!r}".format(
1110 expected, op.__name__, x, y, got))
1111
1112 # repeat the above, but this time trap the InvalidOperation
1113 with localcontext() as ctx:
1114 ctx.traps[InvalidOperation] = 1
1115
1116 for x, y in qnan_pairs:
1117 for op in equality_ops:
1118 got = op(x, y)
1119 expected = True if op is operator.ne else False
1120 self.assertIs(expected, got,
1121 "expected {0!r} for "
1122 "operator.{1}({2!r}, {3!r}); "
1123 "got {4!r}".format(
1124 expected, op.__name__, x, y, got))
1125
1126 for x, y in snan_pairs:
1127 for op in equality_ops:
1128 self.assertRaises(InvalidOperation, operator.eq, x, y)
1129 self.assertRaises(InvalidOperation, operator.ne, x, y)
1130
1131 for x, y in qnan_pairs + snan_pairs:
1132 for op in order_ops:
1133 self.assertRaises(InvalidOperation, op, x, y)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001134
Mark Dickinson6d8effb2010-02-18 14:27:02 +00001135 def test_copy_sign(self):
1136 d = Decimal(1).copy_sign(Decimal(-2))
1137
1138 self.assertEqual(Decimal(1).copy_sign(-2), d)
1139 self.assertRaises(TypeError, Decimal(1).copy_sign, '-2')
1140
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001141# The following are two functions used to test threading in the next class
1142
1143def thfunc1(cls):
1144 d1 = Decimal(1)
1145 d3 = Decimal(3)
Facundo Batista64156672008-03-22 02:45:37 +00001146 test1 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001147 cls.synchro.wait()
Facundo Batista64156672008-03-22 02:45:37 +00001148 test2 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001149 cls.finish1.set()
Facundo Batista64156672008-03-22 02:45:37 +00001150
Facundo Batistaee340e52008-05-02 17:39:00 +00001151 cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
1152 cls.assertEqual(test2, Decimal('0.3333333333333333333333333333'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001153 return
1154
1155def thfunc2(cls):
1156 d1 = Decimal(1)
1157 d3 = Decimal(3)
Facundo Batista64156672008-03-22 02:45:37 +00001158 test1 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001159 thiscontext = getcontext()
1160 thiscontext.prec = 18
Facundo Batista64156672008-03-22 02:45:37 +00001161 test2 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001162 cls.synchro.set()
1163 cls.finish2.set()
Facundo Batista64156672008-03-22 02:45:37 +00001164
Facundo Batistaee340e52008-05-02 17:39:00 +00001165 cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
Facundo Batista64156672008-03-22 02:45:37 +00001166 cls.assertEqual(test2, Decimal('0.333333333333333333'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001167 return
1168
1169
1170class DecimalUseOfContextTest(unittest.TestCase):
1171 '''Unit tests for Use of Context cases in Decimal.'''
1172
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001173 try:
1174 import threading
1175 except ImportError:
1176 threading = None
1177
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001178 # Take care executing this test from IDLE, there's an issue in threading
1179 # that hangs IDLE and I couldn't find it
1180
1181 def test_threading(self):
1182 #Test the "threading isolation" of a Context.
1183
1184 self.synchro = threading.Event()
1185 self.finish1 = threading.Event()
1186 self.finish2 = threading.Event()
1187
1188 th1 = threading.Thread(target=thfunc1, args=(self,))
1189 th2 = threading.Thread(target=thfunc2, args=(self,))
1190
1191 th1.start()
1192 th2.start()
1193
1194 self.finish1.wait()
Thomas Woutersb3e6e8c2007-09-19 17:27:29 +00001195 self.finish2.wait()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001196 return
1197
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001198 if threading is None:
1199 del test_threading
1200
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001201
1202class DecimalUsabilityTest(unittest.TestCase):
1203 '''Unit tests for Usability cases of Decimal.'''
1204
1205 def test_comparison_operators(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001206
1207 da = Decimal('23.42')
1208 db = Decimal('23.42')
1209 dc = Decimal('45')
1210
1211 #two Decimals
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001212 self.assertTrue(dc > da)
1213 self.assertTrue(dc >= da)
1214 self.assertTrue(da < dc)
1215 self.assertTrue(da <= dc)
1216 self.assertTrue(da == db)
1217 self.assertTrue(da != dc)
1218 self.assertTrue(da <= db)
1219 self.assertTrue(da >= db)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001220 self.assertEqual(cmp(dc,da), 1)
1221 self.assertEqual(cmp(da,dc), -1)
1222 self.assertEqual(cmp(da,db), 0)
1223
1224 #a Decimal and an int
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001225 self.assertTrue(dc > 23)
1226 self.assertTrue(23 < dc)
1227 self.assertTrue(dc == 45)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001228 self.assertEqual(cmp(dc,23), 1)
1229 self.assertEqual(cmp(23,dc), -1)
1230 self.assertEqual(cmp(dc,45), 0)
1231
1232 #a Decimal and uncomparable
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001233 self.assertNotEqual(da, 'ugly')
1234 self.assertNotEqual(da, 32.7)
1235 self.assertNotEqual(da, object())
1236 self.assertNotEqual(da, object)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001237
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001238 # sortable
1239 a = map(Decimal, xrange(100))
1240 b = a[:]
1241 random.shuffle(a)
1242 a.sort()
1243 self.assertEqual(a, b)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001244
Facundo Batista353750c2007-09-13 18:13:15 +00001245 # with None
Florent Xicluna8f43cec2010-03-21 10:51:40 +00001246 with check_py3k_warnings():
1247 self.assertFalse(Decimal(1) < None)
1248 self.assertTrue(Decimal(1) > None)
Facundo Batista353750c2007-09-13 18:13:15 +00001249
Mark Dickinson99d80962010-04-02 08:53:22 +00001250 def test_decimal_float_comparison(self):
1251 da = Decimal('0.25')
1252 db = Decimal('3.0')
1253 self.assert_(da < 3.0)
1254 self.assert_(da <= 3.0)
1255 self.assert_(db > 0.25)
1256 self.assert_(db >= 0.25)
1257 self.assert_(da != 1.5)
1258 self.assert_(da == 0.25)
1259 self.assert_(3.0 > da)
1260 self.assert_(3.0 >= da)
1261 self.assert_(0.25 < db)
1262 self.assert_(0.25 <= db)
1263 self.assert_(0.25 != db)
1264 self.assert_(3.0 == db)
1265 self.assert_(0.1 != Decimal('0.1'))
1266
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001267 def test_copy_and_deepcopy_methods(self):
1268 d = Decimal('43.24')
1269 c = copy.copy(d)
1270 self.assertEqual(id(c), id(d))
1271 dc = copy.deepcopy(d)
1272 self.assertEqual(id(dc), id(d))
1273
1274 def test_hash_method(self):
1275 #just that it's hashable
1276 hash(Decimal(23))
Mark Dickinsonf3eeca12010-04-02 10:35:12 +00001277 hash(Decimal('Infinity'))
1278 hash(Decimal('-Infinity'))
1279 hash(Decimal('nan123'))
1280 hash(Decimal('-NaN'))
Facundo Batista8c202442007-09-19 17:53:25 +00001281
1282 test_values = [Decimal(sign*(2**m + n))
1283 for m in [0, 14, 15, 16, 17, 30, 31,
1284 32, 33, 62, 63, 64, 65, 66]
1285 for n in range(-10, 10)
1286 for sign in [-1, 1]]
1287 test_values.extend([
1288 Decimal("-0"), # zeros
1289 Decimal("0.00"),
1290 Decimal("-0.000"),
1291 Decimal("0E10"),
1292 Decimal("-0E12"),
1293 Decimal("10.0"), # negative exponent
1294 Decimal("-23.00000"),
1295 Decimal("1230E100"), # positive exponent
1296 Decimal("-4.5678E50"),
1297 # a value for which hash(n) != hash(n % (2**64-1))
1298 # in Python pre-2.6
1299 Decimal(2**64 + 2**32 - 1),
1300 # selection of values which fail with the old (before
1301 # version 2.6) long.__hash__
1302 Decimal("1.634E100"),
1303 Decimal("90.697E100"),
1304 Decimal("188.83E100"),
1305 Decimal("1652.9E100"),
1306 Decimal("56531E100"),
1307 ])
1308
1309 # check that hash(d) == hash(int(d)) for integral values
1310 for value in test_values:
1311 self.assertEqual(hash(value), hash(int(value)))
1312
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001313 #the same hash that to an int
1314 self.assertEqual(hash(Decimal(23)), hash(23))
Mark Dickinsonf3eeca12010-04-02 10:35:12 +00001315 self.assertRaises(TypeError, hash, Decimal('sNaN'))
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001316 self.assertTrue(hash(Decimal('Inf')))
1317 self.assertTrue(hash(Decimal('-Inf')))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001318
Mark Dickinson99d80962010-04-02 08:53:22 +00001319 # check that the hashes of a Decimal float match when they
1320 # represent exactly the same values
1321 test_strings = ['inf', '-Inf', '0.0', '-.0e1',
1322 '34.0', '2.5', '112390.625', '-0.515625']
1323 for s in test_strings:
1324 f = float(s)
1325 d = Decimal(s)
1326 self.assertEqual(hash(f), hash(d))
1327
Facundo Batista52b25792008-01-08 12:25:20 +00001328 # check that the value of the hash doesn't depend on the
1329 # current context (issue #1757)
1330 c = getcontext()
1331 old_precision = c.prec
1332 x = Decimal("123456789.1")
1333
1334 c.prec = 6
1335 h1 = hash(x)
1336 c.prec = 10
1337 h2 = hash(x)
1338 c.prec = 16
1339 h3 = hash(x)
1340
1341 self.assertEqual(h1, h2)
1342 self.assertEqual(h1, h3)
1343 c.prec = old_precision
1344
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001345 def test_min_and_max_methods(self):
1346
1347 d1 = Decimal('15.32')
1348 d2 = Decimal('28.5')
1349 l1 = 15
1350 l2 = 28
1351
1352 #between Decimals
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001353 self.assertTrue(min(d1,d2) is d1)
1354 self.assertTrue(min(d2,d1) is d1)
1355 self.assertTrue(max(d1,d2) is d2)
1356 self.assertTrue(max(d2,d1) is d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001357
1358 #between Decimal and long
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001359 self.assertTrue(min(d1,l2) is d1)
1360 self.assertTrue(min(l2,d1) is d1)
1361 self.assertTrue(max(l1,d2) is d2)
1362 self.assertTrue(max(d2,l1) is d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001363
1364 def test_as_nonzero(self):
1365 #as false
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001366 self.assertFalse(Decimal(0))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001367 #as true
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001368 self.assertTrue(Decimal('0.372'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001369
1370 def test_tostring_methods(self):
1371 #Test str and repr methods.
1372
1373 d = Decimal('15.32')
1374 self.assertEqual(str(d), '15.32') # str
Raymond Hettingerabe32372008-02-14 02:41:22 +00001375 self.assertEqual(repr(d), "Decimal('15.32')") # repr
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001376
Mark Dickinson8e85ffa2008-03-25 18:47:59 +00001377 # result type of string methods should be str, not unicode
1378 unicode_inputs = [u'123.4', u'0.5E2', u'Infinity', u'sNaN',
1379 u'-0.0E100', u'-NaN001', u'-Inf']
1380
1381 for u in unicode_inputs:
1382 d = Decimal(u)
1383 self.assertEqual(type(str(d)), str)
1384 self.assertEqual(type(repr(d)), str)
1385 self.assertEqual(type(d.to_eng_string()), str)
1386
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001387 def test_tonum_methods(self):
1388 #Test float, int and long methods.
1389
1390 d1 = Decimal('66')
1391 d2 = Decimal('15.32')
1392
1393 #int
1394 self.assertEqual(int(d1), 66)
1395 self.assertEqual(int(d2), 15)
1396
1397 #long
1398 self.assertEqual(long(d1), 66)
1399 self.assertEqual(long(d2), 15)
1400
1401 #float
1402 self.assertEqual(float(d1), 66)
1403 self.assertEqual(float(d2), 15.32)
1404
1405 def test_eval_round_trip(self):
1406
1407 #with zero
1408 d = Decimal( (0, (0,), 0) )
1409 self.assertEqual(d, eval(repr(d)))
1410
1411 #int
1412 d = Decimal( (1, (4, 5), 0) )
1413 self.assertEqual(d, eval(repr(d)))
1414
1415 #float
1416 d = Decimal( (0, (4, 5, 3, 4), -2) )
1417 self.assertEqual(d, eval(repr(d)))
1418
1419 #weird
1420 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1421 self.assertEqual(d, eval(repr(d)))
1422
1423 def test_as_tuple(self):
1424
1425 #with zero
1426 d = Decimal(0)
1427 self.assertEqual(d.as_tuple(), (0, (0,), 0) )
1428
1429 #int
1430 d = Decimal(-45)
1431 self.assertEqual(d.as_tuple(), (1, (4, 5), 0) )
1432
1433 #complicated string
1434 d = Decimal("-4.34913534E-17")
1435 self.assertEqual(d.as_tuple(), (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1436
1437 #inf
1438 d = Decimal("Infinity")
1439 self.assertEqual(d.as_tuple(), (0, (0,), 'F') )
1440
Facundo Batista9b5e2312007-10-19 19:25:57 +00001441 #leading zeros in coefficient should be stripped
1442 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), -2) )
1443 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), -2) )
1444 d = Decimal( (1, (0, 0, 0), 37) )
1445 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1446 d = Decimal( (1, (), 37) )
1447 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1448
1449 #leading zeros in NaN diagnostic info should be stripped
1450 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), 'n') )
1451 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), 'n') )
1452 d = Decimal( (1, (0, 0, 0), 'N') )
1453 self.assertEqual(d.as_tuple(), (1, (), 'N') )
1454 d = Decimal( (1, (), 'n') )
1455 self.assertEqual(d.as_tuple(), (1, (), 'n') )
1456
1457 #coefficient in infinity should be ignored
1458 d = Decimal( (0, (4, 5, 3, 4), 'F') )
1459 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
1460 d = Decimal( (1, (0, 2, 7, 1), 'F') )
1461 self.assertEqual(d.as_tuple(), (1, (0,), 'F'))
1462
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001463 def test_immutability_operations(self):
1464 # Do operations and check that it didn't change change internal objects.
1465
1466 d1 = Decimal('-25e55')
1467 b1 = Decimal('-25e55')
Facundo Batista353750c2007-09-13 18:13:15 +00001468 d2 = Decimal('33e+33')
1469 b2 = Decimal('33e+33')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001470
1471 def checkSameDec(operation, useOther=False):
1472 if useOther:
1473 eval("d1." + operation + "(d2)")
1474 self.assertEqual(d1._sign, b1._sign)
1475 self.assertEqual(d1._int, b1._int)
1476 self.assertEqual(d1._exp, b1._exp)
1477 self.assertEqual(d2._sign, b2._sign)
1478 self.assertEqual(d2._int, b2._int)
1479 self.assertEqual(d2._exp, b2._exp)
1480 else:
1481 eval("d1." + operation + "()")
1482 self.assertEqual(d1._sign, b1._sign)
1483 self.assertEqual(d1._int, b1._int)
1484 self.assertEqual(d1._exp, b1._exp)
1485 return
1486
1487 Decimal(d1)
1488 self.assertEqual(d1._sign, b1._sign)
1489 self.assertEqual(d1._int, b1._int)
1490 self.assertEqual(d1._exp, b1._exp)
1491
1492 checkSameDec("__abs__")
1493 checkSameDec("__add__", True)
1494 checkSameDec("__div__", True)
1495 checkSameDec("__divmod__", True)
Mark Dickinson2fc92632008-02-06 22:10:50 +00001496 checkSameDec("__eq__", True)
1497 checkSameDec("__ne__", True)
1498 checkSameDec("__le__", True)
1499 checkSameDec("__lt__", True)
1500 checkSameDec("__ge__", True)
1501 checkSameDec("__gt__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001502 checkSameDec("__float__")
1503 checkSameDec("__floordiv__", True)
1504 checkSameDec("__hash__")
1505 checkSameDec("__int__")
Raymond Hettinger5a053642008-01-24 19:05:29 +00001506 checkSameDec("__trunc__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001507 checkSameDec("__long__")
1508 checkSameDec("__mod__", True)
1509 checkSameDec("__mul__", True)
1510 checkSameDec("__neg__")
1511 checkSameDec("__nonzero__")
1512 checkSameDec("__pos__")
1513 checkSameDec("__pow__", True)
1514 checkSameDec("__radd__", True)
1515 checkSameDec("__rdiv__", True)
1516 checkSameDec("__rdivmod__", True)
1517 checkSameDec("__repr__")
1518 checkSameDec("__rfloordiv__", True)
1519 checkSameDec("__rmod__", True)
1520 checkSameDec("__rmul__", True)
1521 checkSameDec("__rpow__", True)
1522 checkSameDec("__rsub__", True)
1523 checkSameDec("__str__")
1524 checkSameDec("__sub__", True)
1525 checkSameDec("__truediv__", True)
1526 checkSameDec("adjusted")
1527 checkSameDec("as_tuple")
1528 checkSameDec("compare", True)
1529 checkSameDec("max", True)
1530 checkSameDec("min", True)
1531 checkSameDec("normalize")
1532 checkSameDec("quantize", True)
1533 checkSameDec("remainder_near", True)
1534 checkSameDec("same_quantum", True)
1535 checkSameDec("sqrt")
1536 checkSameDec("to_eng_string")
1537 checkSameDec("to_integral")
1538
Facundo Batista6c398da2007-09-17 17:30:13 +00001539 def test_subclassing(self):
1540 # Different behaviours when subclassing Decimal
1541
1542 class MyDecimal(Decimal):
1543 pass
1544
1545 d1 = MyDecimal(1)
1546 d2 = MyDecimal(2)
1547 d = d1 + d2
1548 self.assertTrue(type(d) is Decimal)
1549
1550 d = d1.max(d2)
1551 self.assertTrue(type(d) is Decimal)
1552
Mark Dickinson3b24ccb2008-03-25 14:33:23 +00001553 def test_implicit_context(self):
1554 # Check results when context given implicitly. (Issue 2478)
1555 c = getcontext()
1556 self.assertEqual(str(Decimal(0).sqrt()),
1557 str(c.sqrt(Decimal(0))))
1558
Mark Dickinson0c673122009-10-29 12:04:00 +00001559 def test_conversions_from_int(self):
1560 # Check that methods taking a second Decimal argument will
1561 # always accept an integer in place of a Decimal.
1562 self.assertEqual(Decimal(4).compare(3),
1563 Decimal(4).compare(Decimal(3)))
1564 self.assertEqual(Decimal(4).compare_signal(3),
1565 Decimal(4).compare_signal(Decimal(3)))
1566 self.assertEqual(Decimal(4).compare_total(3),
1567 Decimal(4).compare_total(Decimal(3)))
1568 self.assertEqual(Decimal(4).compare_total_mag(3),
1569 Decimal(4).compare_total_mag(Decimal(3)))
1570 self.assertEqual(Decimal(10101).logical_and(1001),
1571 Decimal(10101).logical_and(Decimal(1001)))
1572 self.assertEqual(Decimal(10101).logical_or(1001),
1573 Decimal(10101).logical_or(Decimal(1001)))
1574 self.assertEqual(Decimal(10101).logical_xor(1001),
1575 Decimal(10101).logical_xor(Decimal(1001)))
1576 self.assertEqual(Decimal(567).max(123),
1577 Decimal(567).max(Decimal(123)))
1578 self.assertEqual(Decimal(567).max_mag(123),
1579 Decimal(567).max_mag(Decimal(123)))
1580 self.assertEqual(Decimal(567).min(123),
1581 Decimal(567).min(Decimal(123)))
1582 self.assertEqual(Decimal(567).min_mag(123),
1583 Decimal(567).min_mag(Decimal(123)))
1584 self.assertEqual(Decimal(567).next_toward(123),
1585 Decimal(567).next_toward(Decimal(123)))
1586 self.assertEqual(Decimal(1234).quantize(100),
1587 Decimal(1234).quantize(Decimal(100)))
1588 self.assertEqual(Decimal(768).remainder_near(1234),
1589 Decimal(768).remainder_near(Decimal(1234)))
1590 self.assertEqual(Decimal(123).rotate(1),
1591 Decimal(123).rotate(Decimal(1)))
1592 self.assertEqual(Decimal(1234).same_quantum(1000),
1593 Decimal(1234).same_quantum(Decimal(1000)))
1594 self.assertEqual(Decimal('9.123').scaleb(-100),
1595 Decimal('9.123').scaleb(Decimal(-100)))
1596 self.assertEqual(Decimal(456).shift(-1),
1597 Decimal(456).shift(Decimal(-1)))
1598
1599 self.assertEqual(Decimal(-12).fma(Decimal(45), 67),
1600 Decimal(-12).fma(Decimal(45), Decimal(67)))
1601 self.assertEqual(Decimal(-12).fma(45, 67),
1602 Decimal(-12).fma(Decimal(45), Decimal(67)))
1603 self.assertEqual(Decimal(-12).fma(45, Decimal(67)),
1604 Decimal(-12).fma(Decimal(45), Decimal(67)))
1605
Facundo Batista6c398da2007-09-17 17:30:13 +00001606
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001607class DecimalPythonAPItests(unittest.TestCase):
1608
Raymond Hettinger2c8585b2009-02-03 03:37:03 +00001609 def test_abc(self):
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001610 self.assertTrue(issubclass(Decimal, numbers.Number))
1611 self.assertTrue(not issubclass(Decimal, numbers.Real))
Ezio Melottib0f5adc2010-01-24 16:58:36 +00001612 self.assertIsInstance(Decimal(0), numbers.Number)
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001613 self.assertTrue(not isinstance(Decimal(0), numbers.Real))
Raymond Hettinger2c8585b2009-02-03 03:37:03 +00001614
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001615 def test_pickle(self):
1616 d = Decimal('-3.141590000')
1617 p = pickle.dumps(d)
1618 e = pickle.loads(p)
1619 self.assertEqual(d, e)
1620
Raymond Hettinger5548be22004-07-05 18:49:38 +00001621 def test_int(self):
Raymond Hettinger605ed022004-11-24 07:28:48 +00001622 for x in range(-250, 250):
1623 s = '%0.2f' % (x / 100.0)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001624 # should work the same as for floats
1625 self.assertEqual(int(Decimal(s)), int(float(s)))
Raymond Hettinger605ed022004-11-24 07:28:48 +00001626 # should work the same as to_integral in the ROUND_DOWN mode
Raymond Hettinger5548be22004-07-05 18:49:38 +00001627 d = Decimal(s)
Raymond Hettinger605ed022004-11-24 07:28:48 +00001628 r = d.to_integral(ROUND_DOWN)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001629 self.assertEqual(Decimal(int(d)), r)
1630
Mark Dickinson968f1692009-09-07 18:04:58 +00001631 self.assertRaises(ValueError, int, Decimal('-nan'))
1632 self.assertRaises(ValueError, int, Decimal('snan'))
1633 self.assertRaises(OverflowError, int, Decimal('inf'))
1634 self.assertRaises(OverflowError, int, Decimal('-inf'))
1635
1636 self.assertRaises(ValueError, long, Decimal('-nan'))
1637 self.assertRaises(ValueError, long, Decimal('snan'))
1638 self.assertRaises(OverflowError, long, Decimal('inf'))
1639 self.assertRaises(OverflowError, long, Decimal('-inf'))
1640
Raymond Hettinger5a053642008-01-24 19:05:29 +00001641 def test_trunc(self):
1642 for x in range(-250, 250):
1643 s = '%0.2f' % (x / 100.0)
1644 # should work the same as for floats
1645 self.assertEqual(int(Decimal(s)), int(float(s)))
1646 # should work the same as to_integral in the ROUND_DOWN mode
1647 d = Decimal(s)
1648 r = d.to_integral(ROUND_DOWN)
Jeffrey Yasskinca2b69f2008-02-01 06:22:46 +00001649 self.assertEqual(Decimal(math.trunc(d)), r)
Raymond Hettinger5a053642008-01-24 19:05:29 +00001650
Raymond Hettingerf4d85972009-01-03 19:02:23 +00001651 def test_from_float(self):
1652
1653 class MyDecimal(Decimal):
1654 pass
1655
1656 r = MyDecimal.from_float(0.1)
1657 self.assertEqual(type(r), MyDecimal)
1658 self.assertEqual(str(r),
1659 '0.1000000000000000055511151231257827021181583404541015625')
1660 bigint = 12345678901234567890123456789
1661 self.assertEqual(MyDecimal.from_float(bigint), MyDecimal(bigint))
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001662 self.assertTrue(MyDecimal.from_float(float('nan')).is_qnan())
1663 self.assertTrue(MyDecimal.from_float(float('inf')).is_infinite())
1664 self.assertTrue(MyDecimal.from_float(float('-inf')).is_infinite())
Raymond Hettingerf4d85972009-01-03 19:02:23 +00001665 self.assertEqual(str(MyDecimal.from_float(float('nan'))),
1666 str(Decimal('NaN')))
1667 self.assertEqual(str(MyDecimal.from_float(float('inf'))),
1668 str(Decimal('Infinity')))
1669 self.assertEqual(str(MyDecimal.from_float(float('-inf'))),
1670 str(Decimal('-Infinity')))
1671 self.assertRaises(TypeError, MyDecimal.from_float, 'abc')
1672 for i in range(200):
1673 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
1674 self.assertEqual(x, float(MyDecimal.from_float(x))) # roundtrip
1675
1676 def test_create_decimal_from_float(self):
1677 context = Context(prec=5, rounding=ROUND_DOWN)
1678 self.assertEqual(
1679 context.create_decimal_from_float(math.pi),
1680 Decimal('3.1415')
1681 )
1682 context = Context(prec=5, rounding=ROUND_UP)
1683 self.assertEqual(
1684 context.create_decimal_from_float(math.pi),
1685 Decimal('3.1416')
1686 )
1687 context = Context(prec=5, traps=[Inexact])
1688 self.assertRaises(
1689 Inexact,
1690 context.create_decimal_from_float,
1691 math.pi
1692 )
1693 self.assertEqual(repr(context.create_decimal_from_float(-0.0)),
1694 "Decimal('-0')")
1695 self.assertEqual(repr(context.create_decimal_from_float(1.0)),
1696 "Decimal('1')")
1697 self.assertEqual(repr(context.create_decimal_from_float(10)),
1698 "Decimal('10')")
1699
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00001700class ContextAPItests(unittest.TestCase):
1701
1702 def test_pickle(self):
1703 c = Context()
1704 e = pickle.loads(pickle.dumps(c))
1705 for k in vars(c):
1706 v1 = vars(c)[k]
1707 v2 = vars(e)[k]
1708 self.assertEqual(v1, v2)
1709
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001710 def test_equality_with_other_types(self):
Ezio Melottiaa980582010-01-23 23:04:36 +00001711 self.assertIn(Decimal(10), ['a', 1.0, Decimal(10), (1,2), {}])
1712 self.assertNotIn(Decimal(10), ['a', 1.0, (1,2), {}])
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001713
Raymond Hettinger955d2b22004-08-08 20:17:45 +00001714 def test_copy(self):
1715 # All copies should be deep
1716 c = Context()
1717 d = c.copy()
1718 self.assertNotEqual(id(c), id(d))
1719 self.assertNotEqual(id(c.flags), id(d.flags))
1720 self.assertNotEqual(id(c.traps), id(d.traps))
1721
Mark Dickinson6d8effb2010-02-18 14:27:02 +00001722 def test_abs(self):
1723 c = Context()
1724 d = c.abs(Decimal(-1))
1725 self.assertEqual(c.abs(-1), d)
1726 self.assertRaises(TypeError, c.abs, '-1')
1727
1728 def test_add(self):
1729 c = Context()
1730 d = c.add(Decimal(1), Decimal(1))
1731 self.assertEqual(c.add(1, 1), d)
1732 self.assertEqual(c.add(Decimal(1), 1), d)
1733 self.assertEqual(c.add(1, Decimal(1)), d)
1734 self.assertRaises(TypeError, c.add, '1', 1)
1735 self.assertRaises(TypeError, c.add, 1, '1')
1736
1737 def test_compare(self):
1738 c = Context()
1739 d = c.compare(Decimal(1), Decimal(1))
1740 self.assertEqual(c.compare(1, 1), d)
1741 self.assertEqual(c.compare(Decimal(1), 1), d)
1742 self.assertEqual(c.compare(1, Decimal(1)), d)
1743 self.assertRaises(TypeError, c.compare, '1', 1)
1744 self.assertRaises(TypeError, c.compare, 1, '1')
1745
1746 def test_compare_signal(self):
1747 c = Context()
1748 d = c.compare_signal(Decimal(1), Decimal(1))
1749 self.assertEqual(c.compare_signal(1, 1), d)
1750 self.assertEqual(c.compare_signal(Decimal(1), 1), d)
1751 self.assertEqual(c.compare_signal(1, Decimal(1)), d)
1752 self.assertRaises(TypeError, c.compare_signal, '1', 1)
1753 self.assertRaises(TypeError, c.compare_signal, 1, '1')
1754
1755 def test_compare_total(self):
1756 c = Context()
1757 d = c.compare_total(Decimal(1), Decimal(1))
1758 self.assertEqual(c.compare_total(1, 1), d)
1759 self.assertEqual(c.compare_total(Decimal(1), 1), d)
1760 self.assertEqual(c.compare_total(1, Decimal(1)), d)
1761 self.assertRaises(TypeError, c.compare_total, '1', 1)
1762 self.assertRaises(TypeError, c.compare_total, 1, '1')
1763
1764 def test_compare_total_mag(self):
1765 c = Context()
1766 d = c.compare_total_mag(Decimal(1), Decimal(1))
1767 self.assertEqual(c.compare_total_mag(1, 1), d)
1768 self.assertEqual(c.compare_total_mag(Decimal(1), 1), d)
1769 self.assertEqual(c.compare_total_mag(1, Decimal(1)), d)
1770 self.assertRaises(TypeError, c.compare_total_mag, '1', 1)
1771 self.assertRaises(TypeError, c.compare_total_mag, 1, '1')
1772
1773 def test_copy_abs(self):
1774 c = Context()
1775 d = c.copy_abs(Decimal(-1))
1776 self.assertEqual(c.copy_abs(-1), d)
1777 self.assertRaises(TypeError, c.copy_abs, '-1')
1778
1779 def test_copy_decimal(self):
1780 c = Context()
1781 d = c.copy_decimal(Decimal(-1))
1782 self.assertEqual(c.copy_decimal(-1), d)
1783 self.assertRaises(TypeError, c.copy_decimal, '-1')
1784
1785 def test_copy_negate(self):
1786 c = Context()
1787 d = c.copy_negate(Decimal(-1))
1788 self.assertEqual(c.copy_negate(-1), d)
1789 self.assertRaises(TypeError, c.copy_negate, '-1')
1790
1791 def test_copy_sign(self):
1792 c = Context()
1793 d = c.copy_sign(Decimal(1), Decimal(-2))
1794 self.assertEqual(c.copy_sign(1, -2), d)
1795 self.assertEqual(c.copy_sign(Decimal(1), -2), d)
1796 self.assertEqual(c.copy_sign(1, Decimal(-2)), d)
1797 self.assertRaises(TypeError, c.copy_sign, '1', -2)
1798 self.assertRaises(TypeError, c.copy_sign, 1, '-2')
1799
1800 def test_divide(self):
1801 c = Context()
1802 d = c.divide(Decimal(1), Decimal(2))
1803 self.assertEqual(c.divide(1, 2), d)
1804 self.assertEqual(c.divide(Decimal(1), 2), d)
1805 self.assertEqual(c.divide(1, Decimal(2)), d)
1806 self.assertRaises(TypeError, c.divide, '1', 2)
1807 self.assertRaises(TypeError, c.divide, 1, '2')
1808
1809 def test_divide_int(self):
1810 c = Context()
1811 d = c.divide_int(Decimal(1), Decimal(2))
1812 self.assertEqual(c.divide_int(1, 2), d)
1813 self.assertEqual(c.divide_int(Decimal(1), 2), d)
1814 self.assertEqual(c.divide_int(1, Decimal(2)), d)
1815 self.assertRaises(TypeError, c.divide_int, '1', 2)
1816 self.assertRaises(TypeError, c.divide_int, 1, '2')
1817
1818 def test_divmod(self):
1819 c = Context()
1820 d = c.divmod(Decimal(1), Decimal(2))
1821 self.assertEqual(c.divmod(1, 2), d)
1822 self.assertEqual(c.divmod(Decimal(1), 2), d)
1823 self.assertEqual(c.divmod(1, Decimal(2)), d)
1824 self.assertRaises(TypeError, c.divmod, '1', 2)
1825 self.assertRaises(TypeError, c.divmod, 1, '2')
1826
1827 def test_exp(self):
1828 c = Context()
1829 d = c.exp(Decimal(10))
1830 self.assertEqual(c.exp(10), d)
1831 self.assertRaises(TypeError, c.exp, '10')
1832
1833 def test_fma(self):
1834 c = Context()
1835 d = c.fma(Decimal(2), Decimal(3), Decimal(4))
1836 self.assertEqual(c.fma(2, 3, 4), d)
1837 self.assertEqual(c.fma(Decimal(2), 3, 4), d)
1838 self.assertEqual(c.fma(2, Decimal(3), 4), d)
1839 self.assertEqual(c.fma(2, 3, Decimal(4)), d)
1840 self.assertEqual(c.fma(Decimal(2), Decimal(3), 4), d)
1841 self.assertRaises(TypeError, c.fma, '2', 3, 4)
1842 self.assertRaises(TypeError, c.fma, 2, '3', 4)
1843 self.assertRaises(TypeError, c.fma, 2, 3, '4')
1844
1845 def test_is_finite(self):
1846 c = Context()
1847 d = c.is_finite(Decimal(10))
1848 self.assertEqual(c.is_finite(10), d)
1849 self.assertRaises(TypeError, c.is_finite, '10')
1850
1851 def test_is_infinite(self):
1852 c = Context()
1853 d = c.is_infinite(Decimal(10))
1854 self.assertEqual(c.is_infinite(10), d)
1855 self.assertRaises(TypeError, c.is_infinite, '10')
1856
1857 def test_is_nan(self):
1858 c = Context()
1859 d = c.is_nan(Decimal(10))
1860 self.assertEqual(c.is_nan(10), d)
1861 self.assertRaises(TypeError, c.is_nan, '10')
1862
1863 def test_is_normal(self):
1864 c = Context()
1865 d = c.is_normal(Decimal(10))
1866 self.assertEqual(c.is_normal(10), d)
1867 self.assertRaises(TypeError, c.is_normal, '10')
1868
1869 def test_is_qnan(self):
1870 c = Context()
1871 d = c.is_qnan(Decimal(10))
1872 self.assertEqual(c.is_qnan(10), d)
1873 self.assertRaises(TypeError, c.is_qnan, '10')
1874
1875 def test_is_signed(self):
1876 c = Context()
1877 d = c.is_signed(Decimal(10))
1878 self.assertEqual(c.is_signed(10), d)
1879 self.assertRaises(TypeError, c.is_signed, '10')
1880
1881 def test_is_snan(self):
1882 c = Context()
1883 d = c.is_snan(Decimal(10))
1884 self.assertEqual(c.is_snan(10), d)
1885 self.assertRaises(TypeError, c.is_snan, '10')
1886
1887 def test_is_subnormal(self):
1888 c = Context()
1889 d = c.is_subnormal(Decimal(10))
1890 self.assertEqual(c.is_subnormal(10), d)
1891 self.assertRaises(TypeError, c.is_subnormal, '10')
1892
1893 def test_is_zero(self):
1894 c = Context()
1895 d = c.is_zero(Decimal(10))
1896 self.assertEqual(c.is_zero(10), d)
1897 self.assertRaises(TypeError, c.is_zero, '10')
1898
1899 def test_ln(self):
1900 c = Context()
1901 d = c.ln(Decimal(10))
1902 self.assertEqual(c.ln(10), d)
1903 self.assertRaises(TypeError, c.ln, '10')
1904
1905 def test_log10(self):
1906 c = Context()
1907 d = c.log10(Decimal(10))
1908 self.assertEqual(c.log10(10), d)
1909 self.assertRaises(TypeError, c.log10, '10')
1910
1911 def test_logb(self):
1912 c = Context()
1913 d = c.logb(Decimal(10))
1914 self.assertEqual(c.logb(10), d)
1915 self.assertRaises(TypeError, c.logb, '10')
1916
1917 def test_logical_and(self):
1918 c = Context()
1919 d = c.logical_and(Decimal(1), Decimal(1))
1920 self.assertEqual(c.logical_and(1, 1), d)
1921 self.assertEqual(c.logical_and(Decimal(1), 1), d)
1922 self.assertEqual(c.logical_and(1, Decimal(1)), d)
1923 self.assertRaises(TypeError, c.logical_and, '1', 1)
1924 self.assertRaises(TypeError, c.logical_and, 1, '1')
1925
1926 def test_logical_invert(self):
1927 c = Context()
1928 d = c.logical_invert(Decimal(1000))
1929 self.assertEqual(c.logical_invert(1000), d)
1930 self.assertRaises(TypeError, c.logical_invert, '1000')
1931
1932 def test_logical_or(self):
1933 c = Context()
1934 d = c.logical_or(Decimal(1), Decimal(1))
1935 self.assertEqual(c.logical_or(1, 1), d)
1936 self.assertEqual(c.logical_or(Decimal(1), 1), d)
1937 self.assertEqual(c.logical_or(1, Decimal(1)), d)
1938 self.assertRaises(TypeError, c.logical_or, '1', 1)
1939 self.assertRaises(TypeError, c.logical_or, 1, '1')
1940
1941 def test_logical_xor(self):
1942 c = Context()
1943 d = c.logical_xor(Decimal(1), Decimal(1))
1944 self.assertEqual(c.logical_xor(1, 1), d)
1945 self.assertEqual(c.logical_xor(Decimal(1), 1), d)
1946 self.assertEqual(c.logical_xor(1, Decimal(1)), d)
1947 self.assertRaises(TypeError, c.logical_xor, '1', 1)
1948 self.assertRaises(TypeError, c.logical_xor, 1, '1')
1949
1950 def test_max(self):
1951 c = Context()
1952 d = c.max(Decimal(1), Decimal(2))
1953 self.assertEqual(c.max(1, 2), d)
1954 self.assertEqual(c.max(Decimal(1), 2), d)
1955 self.assertEqual(c.max(1, Decimal(2)), d)
1956 self.assertRaises(TypeError, c.max, '1', 2)
1957 self.assertRaises(TypeError, c.max, 1, '2')
1958
1959 def test_max_mag(self):
1960 c = Context()
1961 d = c.max_mag(Decimal(1), Decimal(2))
1962 self.assertEqual(c.max_mag(1, 2), d)
1963 self.assertEqual(c.max_mag(Decimal(1), 2), d)
1964 self.assertEqual(c.max_mag(1, Decimal(2)), d)
1965 self.assertRaises(TypeError, c.max_mag, '1', 2)
1966 self.assertRaises(TypeError, c.max_mag, 1, '2')
1967
1968 def test_min(self):
1969 c = Context()
1970 d = c.min(Decimal(1), Decimal(2))
1971 self.assertEqual(c.min(1, 2), d)
1972 self.assertEqual(c.min(Decimal(1), 2), d)
1973 self.assertEqual(c.min(1, Decimal(2)), d)
1974 self.assertRaises(TypeError, c.min, '1', 2)
1975 self.assertRaises(TypeError, c.min, 1, '2')
1976
1977 def test_min_mag(self):
1978 c = Context()
1979 d = c.min_mag(Decimal(1), Decimal(2))
1980 self.assertEqual(c.min_mag(1, 2), d)
1981 self.assertEqual(c.min_mag(Decimal(1), 2), d)
1982 self.assertEqual(c.min_mag(1, Decimal(2)), d)
1983 self.assertRaises(TypeError, c.min_mag, '1', 2)
1984 self.assertRaises(TypeError, c.min_mag, 1, '2')
1985
1986 def test_minus(self):
1987 c = Context()
1988 d = c.minus(Decimal(10))
1989 self.assertEqual(c.minus(10), d)
1990 self.assertRaises(TypeError, c.minus, '10')
1991
1992 def test_multiply(self):
1993 c = Context()
1994 d = c.multiply(Decimal(1), Decimal(2))
1995 self.assertEqual(c.multiply(1, 2), d)
1996 self.assertEqual(c.multiply(Decimal(1), 2), d)
1997 self.assertEqual(c.multiply(1, Decimal(2)), d)
1998 self.assertRaises(TypeError, c.multiply, '1', 2)
1999 self.assertRaises(TypeError, c.multiply, 1, '2')
2000
2001 def test_next_minus(self):
2002 c = Context()
2003 d = c.next_minus(Decimal(10))
2004 self.assertEqual(c.next_minus(10), d)
2005 self.assertRaises(TypeError, c.next_minus, '10')
2006
2007 def test_next_plus(self):
2008 c = Context()
2009 d = c.next_plus(Decimal(10))
2010 self.assertEqual(c.next_plus(10), d)
2011 self.assertRaises(TypeError, c.next_plus, '10')
2012
2013 def test_next_toward(self):
2014 c = Context()
2015 d = c.next_toward(Decimal(1), Decimal(2))
2016 self.assertEqual(c.next_toward(1, 2), d)
2017 self.assertEqual(c.next_toward(Decimal(1), 2), d)
2018 self.assertEqual(c.next_toward(1, Decimal(2)), d)
2019 self.assertRaises(TypeError, c.next_toward, '1', 2)
2020 self.assertRaises(TypeError, c.next_toward, 1, '2')
2021
2022 def test_normalize(self):
2023 c = Context()
2024 d = c.normalize(Decimal(10))
2025 self.assertEqual(c.normalize(10), d)
2026 self.assertRaises(TypeError, c.normalize, '10')
2027
2028 def test_number_class(self):
2029 c = Context()
2030 self.assertEqual(c.number_class(123), c.number_class(Decimal(123)))
2031 self.assertEqual(c.number_class(0), c.number_class(Decimal(0)))
2032 self.assertEqual(c.number_class(-45), c.number_class(Decimal(-45)))
2033
2034 def test_power(self):
2035 c = Context()
2036 d = c.power(Decimal(1), Decimal(4), Decimal(2))
2037 self.assertEqual(c.power(1, 4, 2), d)
2038 self.assertEqual(c.power(Decimal(1), 4, 2), d)
2039 self.assertEqual(c.power(1, Decimal(4), 2), d)
2040 self.assertEqual(c.power(1, 4, Decimal(2)), d)
2041 self.assertEqual(c.power(Decimal(1), Decimal(4), 2), d)
2042 self.assertRaises(TypeError, c.power, '1', 4, 2)
2043 self.assertRaises(TypeError, c.power, 1, '4', 2)
2044 self.assertRaises(TypeError, c.power, 1, 4, '2')
2045
2046 def test_plus(self):
2047 c = Context()
2048 d = c.plus(Decimal(10))
2049 self.assertEqual(c.plus(10), d)
2050 self.assertRaises(TypeError, c.plus, '10')
2051
2052 def test_quantize(self):
2053 c = Context()
2054 d = c.quantize(Decimal(1), Decimal(2))
2055 self.assertEqual(c.quantize(1, 2), d)
2056 self.assertEqual(c.quantize(Decimal(1), 2), d)
2057 self.assertEqual(c.quantize(1, Decimal(2)), d)
2058 self.assertRaises(TypeError, c.quantize, '1', 2)
2059 self.assertRaises(TypeError, c.quantize, 1, '2')
2060
2061 def test_remainder(self):
2062 c = Context()
2063 d = c.remainder(Decimal(1), Decimal(2))
2064 self.assertEqual(c.remainder(1, 2), d)
2065 self.assertEqual(c.remainder(Decimal(1), 2), d)
2066 self.assertEqual(c.remainder(1, Decimal(2)), d)
2067 self.assertRaises(TypeError, c.remainder, '1', 2)
2068 self.assertRaises(TypeError, c.remainder, 1, '2')
2069
2070 def test_remainder_near(self):
2071 c = Context()
2072 d = c.remainder_near(Decimal(1), Decimal(2))
2073 self.assertEqual(c.remainder_near(1, 2), d)
2074 self.assertEqual(c.remainder_near(Decimal(1), 2), d)
2075 self.assertEqual(c.remainder_near(1, Decimal(2)), d)
2076 self.assertRaises(TypeError, c.remainder_near, '1', 2)
2077 self.assertRaises(TypeError, c.remainder_near, 1, '2')
2078
2079 def test_rotate(self):
2080 c = Context()
2081 d = c.rotate(Decimal(1), Decimal(2))
2082 self.assertEqual(c.rotate(1, 2), d)
2083 self.assertEqual(c.rotate(Decimal(1), 2), d)
2084 self.assertEqual(c.rotate(1, Decimal(2)), d)
2085 self.assertRaises(TypeError, c.rotate, '1', 2)
2086 self.assertRaises(TypeError, c.rotate, 1, '2')
2087
2088 def test_sqrt(self):
2089 c = Context()
2090 d = c.sqrt(Decimal(10))
2091 self.assertEqual(c.sqrt(10), d)
2092 self.assertRaises(TypeError, c.sqrt, '10')
2093
2094 def test_same_quantum(self):
2095 c = Context()
2096 d = c.same_quantum(Decimal(1), Decimal(2))
2097 self.assertEqual(c.same_quantum(1, 2), d)
2098 self.assertEqual(c.same_quantum(Decimal(1), 2), d)
2099 self.assertEqual(c.same_quantum(1, Decimal(2)), d)
2100 self.assertRaises(TypeError, c.same_quantum, '1', 2)
2101 self.assertRaises(TypeError, c.same_quantum, 1, '2')
2102
2103 def test_scaleb(self):
2104 c = Context()
2105 d = c.scaleb(Decimal(1), Decimal(2))
2106 self.assertEqual(c.scaleb(1, 2), d)
2107 self.assertEqual(c.scaleb(Decimal(1), 2), d)
2108 self.assertEqual(c.scaleb(1, Decimal(2)), d)
2109 self.assertRaises(TypeError, c.scaleb, '1', 2)
2110 self.assertRaises(TypeError, c.scaleb, 1, '2')
2111
2112 def test_shift(self):
2113 c = Context()
2114 d = c.shift(Decimal(1), Decimal(2))
2115 self.assertEqual(c.shift(1, 2), d)
2116 self.assertEqual(c.shift(Decimal(1), 2), d)
2117 self.assertEqual(c.shift(1, Decimal(2)), d)
2118 self.assertRaises(TypeError, c.shift, '1', 2)
2119 self.assertRaises(TypeError, c.shift, 1, '2')
2120
2121 def test_subtract(self):
2122 c = Context()
2123 d = c.subtract(Decimal(1), Decimal(2))
2124 self.assertEqual(c.subtract(1, 2), d)
2125 self.assertEqual(c.subtract(Decimal(1), 2), d)
2126 self.assertEqual(c.subtract(1, Decimal(2)), d)
2127 self.assertRaises(TypeError, c.subtract, '1', 2)
2128 self.assertRaises(TypeError, c.subtract, 1, '2')
2129
2130 def test_to_eng_string(self):
2131 c = Context()
2132 d = c.to_eng_string(Decimal(10))
2133 self.assertEqual(c.to_eng_string(10), d)
2134 self.assertRaises(TypeError, c.to_eng_string, '10')
2135
2136 def test_to_sci_string(self):
2137 c = Context()
2138 d = c.to_sci_string(Decimal(10))
2139 self.assertEqual(c.to_sci_string(10), d)
2140 self.assertRaises(TypeError, c.to_sci_string, '10')
2141
2142 def test_to_integral_exact(self):
2143 c = Context()
2144 d = c.to_integral_exact(Decimal(10))
2145 self.assertEqual(c.to_integral_exact(10), d)
2146 self.assertRaises(TypeError, c.to_integral_exact, '10')
2147
2148 def test_to_integral_value(self):
2149 c = Context()
2150 d = c.to_integral_value(Decimal(10))
2151 self.assertEqual(c.to_integral_value(10), d)
2152 self.assertRaises(TypeError, c.to_integral_value, '10')
2153
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002154class WithStatementTest(unittest.TestCase):
2155 # Can't do these as docstrings until Python 2.6
2156 # as doctest can't handle __future__ statements
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002157
2158 def test_localcontext(self):
Nick Coghlanced12182006-09-02 03:54:17 +00002159 # Use a copy of the current context in the block
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002160 orig_ctx = getcontext()
2161 with localcontext() as enter_ctx:
2162 set_ctx = getcontext()
2163 final_ctx = getcontext()
Benjamin Peterson5c8da862009-06-30 22:57:08 +00002164 self.assertTrue(orig_ctx is final_ctx, 'did not restore context correctly')
2165 self.assertTrue(orig_ctx is not set_ctx, 'did not copy the context')
2166 self.assertTrue(set_ctx is enter_ctx, '__enter__ returned wrong context')
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002167
2168 def test_localcontextarg(self):
Nick Coghlanced12182006-09-02 03:54:17 +00002169 # Use a copy of the supplied context in the block
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002170 orig_ctx = getcontext()
2171 new_ctx = Context(prec=42)
2172 with localcontext(new_ctx) as enter_ctx:
2173 set_ctx = getcontext()
2174 final_ctx = getcontext()
Benjamin Peterson5c8da862009-06-30 22:57:08 +00002175 self.assertTrue(orig_ctx is final_ctx, 'did not restore context correctly')
2176 self.assertTrue(set_ctx.prec == new_ctx.prec, 'did not set correct context')
2177 self.assertTrue(new_ctx is not set_ctx, 'did not copy the context')
2178 self.assertTrue(set_ctx is enter_ctx, '__enter__ returned wrong context')
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002179
Facundo Batista353750c2007-09-13 18:13:15 +00002180class ContextFlags(unittest.TestCase):
2181 def test_flags_irrelevant(self):
2182 # check that the result (numeric result + flags raised) of an
2183 # arithmetic operation doesn't depend on the current flags
2184
2185 context = Context(prec=9, Emin = -999999999, Emax = 999999999,
2186 rounding=ROUND_HALF_EVEN, traps=[], flags=[])
2187
2188 # operations that raise various flags, in the form (function, arglist)
2189 operations = [
2190 (context._apply, [Decimal("100E-1000000009")]),
2191 (context.sqrt, [Decimal(2)]),
2192 (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]),
2193 (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]),
2194 (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]),
2195 ]
2196
2197 # try various flags individually, then a whole lot at once
2198 flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal],
2199 [Inexact, Rounded, Underflow, Clamped, Subnormal]]
2200
2201 for fn, args in operations:
2202 # find answer and flags raised using a clean context
2203 context.clear_flags()
2204 ans = fn(*args)
2205 flags = [k for k, v in context.flags.items() if v]
2206
2207 for extra_flags in flagsets:
2208 # set flags, before calling operation
2209 context.clear_flags()
2210 for flag in extra_flags:
2211 context._raise_error(flag)
2212 new_ans = fn(*args)
2213
2214 # flags that we expect to be set after the operation
2215 expected_flags = list(flags)
2216 for flag in extra_flags:
2217 if flag not in expected_flags:
2218 expected_flags.append(flag)
Facundo Batista353750c2007-09-13 18:13:15 +00002219
2220 # flags we actually got
2221 new_flags = [k for k,v in context.flags.items() if v]
Facundo Batista353750c2007-09-13 18:13:15 +00002222
2223 self.assertEqual(ans, new_ans,
2224 "operation produces different answers depending on flags set: " +
2225 "expected %s, got %s." % (ans, new_ans))
Florent Xicluna8f43cec2010-03-21 10:51:40 +00002226 self.assertItemsEqual(new_flags, expected_flags,
Facundo Batista353750c2007-09-13 18:13:15 +00002227 "operation raises different flags depending on flags set: " +
2228 "expected %s, got %s" % (expected_flags, new_flags))
2229
2230def test_main(arith=False, verbose=None, todo_tests=None, debug=None):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002231 """ Execute the tests.
2232
Raymond Hettingered20ad82004-09-04 20:09:13 +00002233 Runs all arithmetic tests if arith is True or if the "decimal" resource
2234 is enabled in regrtest.py
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002235 """
Raymond Hettingered20ad82004-09-04 20:09:13 +00002236
Neal Norwitzce4a9c92006-04-09 08:36:46 +00002237 init()
Facundo Batista353750c2007-09-13 18:13:15 +00002238 global TEST_ALL, DEBUG
Raymond Hettingered20ad82004-09-04 20:09:13 +00002239 TEST_ALL = arith or is_resource_enabled('decimal')
Facundo Batista353750c2007-09-13 18:13:15 +00002240 DEBUG = debug
Raymond Hettingered20ad82004-09-04 20:09:13 +00002241
Facundo Batista353750c2007-09-13 18:13:15 +00002242 if todo_tests is None:
2243 test_classes = [
2244 DecimalExplicitConstructionTest,
2245 DecimalImplicitConstructionTest,
2246 DecimalArithmeticOperatorsTest,
Mark Dickinson1ddf1d82008-02-29 02:16:37 +00002247 DecimalFormatTest,
Facundo Batista353750c2007-09-13 18:13:15 +00002248 DecimalUseOfContextTest,
2249 DecimalUsabilityTest,
2250 DecimalPythonAPItests,
2251 ContextAPItests,
2252 DecimalTest,
2253 WithStatementTest,
2254 ContextFlags
2255 ]
2256 else:
2257 test_classes = [DecimalTest]
2258
2259 # Dynamically build custom test definition for each file in the test
2260 # directory and add the definitions to the DecimalTest class. This
2261 # procedure insures that new files do not get skipped.
2262 for filename in os.listdir(directory):
2263 if '.decTest' not in filename or filename.startswith("."):
2264 continue
2265 head, tail = filename.split('.')
2266 if todo_tests is not None and head not in todo_tests:
2267 continue
2268 tester = lambda self, f=filename: self.eval_file(directory + f)
2269 setattr(DecimalTest, 'test_' + head, tester)
2270 del filename, head, tail, tester
2271
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002272
Tim Peters46cc7022006-03-31 04:11:16 +00002273 try:
2274 run_unittest(*test_classes)
Facundo Batista353750c2007-09-13 18:13:15 +00002275 if todo_tests is None:
2276 import decimal as DecimalModule
2277 run_doctest(DecimalModule, verbose)
Tim Peters46cc7022006-03-31 04:11:16 +00002278 finally:
2279 setcontext(ORIGINAL_CONTEXT)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002280
2281if __name__ == '__main__':
Facundo Batista353750c2007-09-13 18:13:15 +00002282 import optparse
2283 p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]")
2284 p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test')
2285 p.add_option('--skip', '-s', action='store_true', help='skip over 90% of the arithmetic tests')
2286 (opt, args) = p.parse_args()
2287
2288 if opt.skip:
2289 test_main(arith=False, verbose=True)
2290 elif args:
2291 test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002292 else:
Facundo Batista353750c2007-09-13 18:13:15 +00002293 test_main(arith=True, verbose=True)