blob: c2a6b0e0074c1935cd4fbda8bdec004477c63f82 [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))
Facundo Batista8c202442007-09-19 17:53:25 +00001277
1278 test_values = [Decimal(sign*(2**m + n))
1279 for m in [0, 14, 15, 16, 17, 30, 31,
1280 32, 33, 62, 63, 64, 65, 66]
1281 for n in range(-10, 10)
1282 for sign in [-1, 1]]
1283 test_values.extend([
1284 Decimal("-0"), # zeros
1285 Decimal("0.00"),
1286 Decimal("-0.000"),
1287 Decimal("0E10"),
1288 Decimal("-0E12"),
1289 Decimal("10.0"), # negative exponent
1290 Decimal("-23.00000"),
1291 Decimal("1230E100"), # positive exponent
1292 Decimal("-4.5678E50"),
1293 # a value for which hash(n) != hash(n % (2**64-1))
1294 # in Python pre-2.6
1295 Decimal(2**64 + 2**32 - 1),
1296 # selection of values which fail with the old (before
1297 # version 2.6) long.__hash__
1298 Decimal("1.634E100"),
1299 Decimal("90.697E100"),
1300 Decimal("188.83E100"),
1301 Decimal("1652.9E100"),
1302 Decimal("56531E100"),
1303 ])
1304
1305 # check that hash(d) == hash(int(d)) for integral values
1306 for value in test_values:
1307 self.assertEqual(hash(value), hash(int(value)))
1308
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001309 #the same hash that to an int
1310 self.assertEqual(hash(Decimal(23)), hash(23))
Raymond Hettingerbea3f6f2005-03-15 04:59:17 +00001311 self.assertRaises(TypeError, hash, Decimal('NaN'))
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001312 self.assertTrue(hash(Decimal('Inf')))
1313 self.assertTrue(hash(Decimal('-Inf')))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001314
Mark Dickinson99d80962010-04-02 08:53:22 +00001315 # check that the hashes of a Decimal float match when they
1316 # represent exactly the same values
1317 test_strings = ['inf', '-Inf', '0.0', '-.0e1',
1318 '34.0', '2.5', '112390.625', '-0.515625']
1319 for s in test_strings:
1320 f = float(s)
1321 d = Decimal(s)
1322 self.assertEqual(hash(f), hash(d))
1323
Facundo Batista52b25792008-01-08 12:25:20 +00001324 # check that the value of the hash doesn't depend on the
1325 # current context (issue #1757)
1326 c = getcontext()
1327 old_precision = c.prec
1328 x = Decimal("123456789.1")
1329
1330 c.prec = 6
1331 h1 = hash(x)
1332 c.prec = 10
1333 h2 = hash(x)
1334 c.prec = 16
1335 h3 = hash(x)
1336
1337 self.assertEqual(h1, h2)
1338 self.assertEqual(h1, h3)
1339 c.prec = old_precision
1340
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001341 def test_min_and_max_methods(self):
1342
1343 d1 = Decimal('15.32')
1344 d2 = Decimal('28.5')
1345 l1 = 15
1346 l2 = 28
1347
1348 #between Decimals
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001349 self.assertTrue(min(d1,d2) is d1)
1350 self.assertTrue(min(d2,d1) is d1)
1351 self.assertTrue(max(d1,d2) is d2)
1352 self.assertTrue(max(d2,d1) is d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001353
1354 #between Decimal and long
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001355 self.assertTrue(min(d1,l2) is d1)
1356 self.assertTrue(min(l2,d1) is d1)
1357 self.assertTrue(max(l1,d2) is d2)
1358 self.assertTrue(max(d2,l1) is d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001359
1360 def test_as_nonzero(self):
1361 #as false
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001362 self.assertFalse(Decimal(0))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001363 #as true
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001364 self.assertTrue(Decimal('0.372'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001365
1366 def test_tostring_methods(self):
1367 #Test str and repr methods.
1368
1369 d = Decimal('15.32')
1370 self.assertEqual(str(d), '15.32') # str
Raymond Hettingerabe32372008-02-14 02:41:22 +00001371 self.assertEqual(repr(d), "Decimal('15.32')") # repr
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001372
Mark Dickinson8e85ffa2008-03-25 18:47:59 +00001373 # result type of string methods should be str, not unicode
1374 unicode_inputs = [u'123.4', u'0.5E2', u'Infinity', u'sNaN',
1375 u'-0.0E100', u'-NaN001', u'-Inf']
1376
1377 for u in unicode_inputs:
1378 d = Decimal(u)
1379 self.assertEqual(type(str(d)), str)
1380 self.assertEqual(type(repr(d)), str)
1381 self.assertEqual(type(d.to_eng_string()), str)
1382
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001383 def test_tonum_methods(self):
1384 #Test float, int and long methods.
1385
1386 d1 = Decimal('66')
1387 d2 = Decimal('15.32')
1388
1389 #int
1390 self.assertEqual(int(d1), 66)
1391 self.assertEqual(int(d2), 15)
1392
1393 #long
1394 self.assertEqual(long(d1), 66)
1395 self.assertEqual(long(d2), 15)
1396
1397 #float
1398 self.assertEqual(float(d1), 66)
1399 self.assertEqual(float(d2), 15.32)
1400
1401 def test_eval_round_trip(self):
1402
1403 #with zero
1404 d = Decimal( (0, (0,), 0) )
1405 self.assertEqual(d, eval(repr(d)))
1406
1407 #int
1408 d = Decimal( (1, (4, 5), 0) )
1409 self.assertEqual(d, eval(repr(d)))
1410
1411 #float
1412 d = Decimal( (0, (4, 5, 3, 4), -2) )
1413 self.assertEqual(d, eval(repr(d)))
1414
1415 #weird
1416 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1417 self.assertEqual(d, eval(repr(d)))
1418
1419 def test_as_tuple(self):
1420
1421 #with zero
1422 d = Decimal(0)
1423 self.assertEqual(d.as_tuple(), (0, (0,), 0) )
1424
1425 #int
1426 d = Decimal(-45)
1427 self.assertEqual(d.as_tuple(), (1, (4, 5), 0) )
1428
1429 #complicated string
1430 d = Decimal("-4.34913534E-17")
1431 self.assertEqual(d.as_tuple(), (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1432
1433 #inf
1434 d = Decimal("Infinity")
1435 self.assertEqual(d.as_tuple(), (0, (0,), 'F') )
1436
Facundo Batista9b5e2312007-10-19 19:25:57 +00001437 #leading zeros in coefficient should be stripped
1438 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), -2) )
1439 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), -2) )
1440 d = Decimal( (1, (0, 0, 0), 37) )
1441 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1442 d = Decimal( (1, (), 37) )
1443 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1444
1445 #leading zeros in NaN diagnostic info should be stripped
1446 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), 'n') )
1447 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), 'n') )
1448 d = Decimal( (1, (0, 0, 0), 'N') )
1449 self.assertEqual(d.as_tuple(), (1, (), 'N') )
1450 d = Decimal( (1, (), 'n') )
1451 self.assertEqual(d.as_tuple(), (1, (), 'n') )
1452
1453 #coefficient in infinity should be ignored
1454 d = Decimal( (0, (4, 5, 3, 4), 'F') )
1455 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
1456 d = Decimal( (1, (0, 2, 7, 1), 'F') )
1457 self.assertEqual(d.as_tuple(), (1, (0,), 'F'))
1458
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001459 def test_immutability_operations(self):
1460 # Do operations and check that it didn't change change internal objects.
1461
1462 d1 = Decimal('-25e55')
1463 b1 = Decimal('-25e55')
Facundo Batista353750c2007-09-13 18:13:15 +00001464 d2 = Decimal('33e+33')
1465 b2 = Decimal('33e+33')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001466
1467 def checkSameDec(operation, useOther=False):
1468 if useOther:
1469 eval("d1." + operation + "(d2)")
1470 self.assertEqual(d1._sign, b1._sign)
1471 self.assertEqual(d1._int, b1._int)
1472 self.assertEqual(d1._exp, b1._exp)
1473 self.assertEqual(d2._sign, b2._sign)
1474 self.assertEqual(d2._int, b2._int)
1475 self.assertEqual(d2._exp, b2._exp)
1476 else:
1477 eval("d1." + operation + "()")
1478 self.assertEqual(d1._sign, b1._sign)
1479 self.assertEqual(d1._int, b1._int)
1480 self.assertEqual(d1._exp, b1._exp)
1481 return
1482
1483 Decimal(d1)
1484 self.assertEqual(d1._sign, b1._sign)
1485 self.assertEqual(d1._int, b1._int)
1486 self.assertEqual(d1._exp, b1._exp)
1487
1488 checkSameDec("__abs__")
1489 checkSameDec("__add__", True)
1490 checkSameDec("__div__", True)
1491 checkSameDec("__divmod__", True)
Mark Dickinson2fc92632008-02-06 22:10:50 +00001492 checkSameDec("__eq__", True)
1493 checkSameDec("__ne__", True)
1494 checkSameDec("__le__", True)
1495 checkSameDec("__lt__", True)
1496 checkSameDec("__ge__", True)
1497 checkSameDec("__gt__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001498 checkSameDec("__float__")
1499 checkSameDec("__floordiv__", True)
1500 checkSameDec("__hash__")
1501 checkSameDec("__int__")
Raymond Hettinger5a053642008-01-24 19:05:29 +00001502 checkSameDec("__trunc__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001503 checkSameDec("__long__")
1504 checkSameDec("__mod__", True)
1505 checkSameDec("__mul__", True)
1506 checkSameDec("__neg__")
1507 checkSameDec("__nonzero__")
1508 checkSameDec("__pos__")
1509 checkSameDec("__pow__", True)
1510 checkSameDec("__radd__", True)
1511 checkSameDec("__rdiv__", True)
1512 checkSameDec("__rdivmod__", True)
1513 checkSameDec("__repr__")
1514 checkSameDec("__rfloordiv__", True)
1515 checkSameDec("__rmod__", True)
1516 checkSameDec("__rmul__", True)
1517 checkSameDec("__rpow__", True)
1518 checkSameDec("__rsub__", True)
1519 checkSameDec("__str__")
1520 checkSameDec("__sub__", True)
1521 checkSameDec("__truediv__", True)
1522 checkSameDec("adjusted")
1523 checkSameDec("as_tuple")
1524 checkSameDec("compare", True)
1525 checkSameDec("max", True)
1526 checkSameDec("min", True)
1527 checkSameDec("normalize")
1528 checkSameDec("quantize", True)
1529 checkSameDec("remainder_near", True)
1530 checkSameDec("same_quantum", True)
1531 checkSameDec("sqrt")
1532 checkSameDec("to_eng_string")
1533 checkSameDec("to_integral")
1534
Facundo Batista6c398da2007-09-17 17:30:13 +00001535 def test_subclassing(self):
1536 # Different behaviours when subclassing Decimal
1537
1538 class MyDecimal(Decimal):
1539 pass
1540
1541 d1 = MyDecimal(1)
1542 d2 = MyDecimal(2)
1543 d = d1 + d2
1544 self.assertTrue(type(d) is Decimal)
1545
1546 d = d1.max(d2)
1547 self.assertTrue(type(d) is Decimal)
1548
Mark Dickinson3b24ccb2008-03-25 14:33:23 +00001549 def test_implicit_context(self):
1550 # Check results when context given implicitly. (Issue 2478)
1551 c = getcontext()
1552 self.assertEqual(str(Decimal(0).sqrt()),
1553 str(c.sqrt(Decimal(0))))
1554
Mark Dickinson0c673122009-10-29 12:04:00 +00001555 def test_conversions_from_int(self):
1556 # Check that methods taking a second Decimal argument will
1557 # always accept an integer in place of a Decimal.
1558 self.assertEqual(Decimal(4).compare(3),
1559 Decimal(4).compare(Decimal(3)))
1560 self.assertEqual(Decimal(4).compare_signal(3),
1561 Decimal(4).compare_signal(Decimal(3)))
1562 self.assertEqual(Decimal(4).compare_total(3),
1563 Decimal(4).compare_total(Decimal(3)))
1564 self.assertEqual(Decimal(4).compare_total_mag(3),
1565 Decimal(4).compare_total_mag(Decimal(3)))
1566 self.assertEqual(Decimal(10101).logical_and(1001),
1567 Decimal(10101).logical_and(Decimal(1001)))
1568 self.assertEqual(Decimal(10101).logical_or(1001),
1569 Decimal(10101).logical_or(Decimal(1001)))
1570 self.assertEqual(Decimal(10101).logical_xor(1001),
1571 Decimal(10101).logical_xor(Decimal(1001)))
1572 self.assertEqual(Decimal(567).max(123),
1573 Decimal(567).max(Decimal(123)))
1574 self.assertEqual(Decimal(567).max_mag(123),
1575 Decimal(567).max_mag(Decimal(123)))
1576 self.assertEqual(Decimal(567).min(123),
1577 Decimal(567).min(Decimal(123)))
1578 self.assertEqual(Decimal(567).min_mag(123),
1579 Decimal(567).min_mag(Decimal(123)))
1580 self.assertEqual(Decimal(567).next_toward(123),
1581 Decimal(567).next_toward(Decimal(123)))
1582 self.assertEqual(Decimal(1234).quantize(100),
1583 Decimal(1234).quantize(Decimal(100)))
1584 self.assertEqual(Decimal(768).remainder_near(1234),
1585 Decimal(768).remainder_near(Decimal(1234)))
1586 self.assertEqual(Decimal(123).rotate(1),
1587 Decimal(123).rotate(Decimal(1)))
1588 self.assertEqual(Decimal(1234).same_quantum(1000),
1589 Decimal(1234).same_quantum(Decimal(1000)))
1590 self.assertEqual(Decimal('9.123').scaleb(-100),
1591 Decimal('9.123').scaleb(Decimal(-100)))
1592 self.assertEqual(Decimal(456).shift(-1),
1593 Decimal(456).shift(Decimal(-1)))
1594
1595 self.assertEqual(Decimal(-12).fma(Decimal(45), 67),
1596 Decimal(-12).fma(Decimal(45), Decimal(67)))
1597 self.assertEqual(Decimal(-12).fma(45, 67),
1598 Decimal(-12).fma(Decimal(45), Decimal(67)))
1599 self.assertEqual(Decimal(-12).fma(45, Decimal(67)),
1600 Decimal(-12).fma(Decimal(45), Decimal(67)))
1601
Facundo Batista6c398da2007-09-17 17:30:13 +00001602
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001603class DecimalPythonAPItests(unittest.TestCase):
1604
Raymond Hettinger2c8585b2009-02-03 03:37:03 +00001605 def test_abc(self):
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001606 self.assertTrue(issubclass(Decimal, numbers.Number))
1607 self.assertTrue(not issubclass(Decimal, numbers.Real))
Ezio Melottib0f5adc2010-01-24 16:58:36 +00001608 self.assertIsInstance(Decimal(0), numbers.Number)
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001609 self.assertTrue(not isinstance(Decimal(0), numbers.Real))
Raymond Hettinger2c8585b2009-02-03 03:37:03 +00001610
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001611 def test_pickle(self):
1612 d = Decimal('-3.141590000')
1613 p = pickle.dumps(d)
1614 e = pickle.loads(p)
1615 self.assertEqual(d, e)
1616
Raymond Hettinger5548be22004-07-05 18:49:38 +00001617 def test_int(self):
Raymond Hettinger605ed022004-11-24 07:28:48 +00001618 for x in range(-250, 250):
1619 s = '%0.2f' % (x / 100.0)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001620 # should work the same as for floats
1621 self.assertEqual(int(Decimal(s)), int(float(s)))
Raymond Hettinger605ed022004-11-24 07:28:48 +00001622 # should work the same as to_integral in the ROUND_DOWN mode
Raymond Hettinger5548be22004-07-05 18:49:38 +00001623 d = Decimal(s)
Raymond Hettinger605ed022004-11-24 07:28:48 +00001624 r = d.to_integral(ROUND_DOWN)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001625 self.assertEqual(Decimal(int(d)), r)
1626
Mark Dickinson968f1692009-09-07 18:04:58 +00001627 self.assertRaises(ValueError, int, Decimal('-nan'))
1628 self.assertRaises(ValueError, int, Decimal('snan'))
1629 self.assertRaises(OverflowError, int, Decimal('inf'))
1630 self.assertRaises(OverflowError, int, Decimal('-inf'))
1631
1632 self.assertRaises(ValueError, long, Decimal('-nan'))
1633 self.assertRaises(ValueError, long, Decimal('snan'))
1634 self.assertRaises(OverflowError, long, Decimal('inf'))
1635 self.assertRaises(OverflowError, long, Decimal('-inf'))
1636
Raymond Hettinger5a053642008-01-24 19:05:29 +00001637 def test_trunc(self):
1638 for x in range(-250, 250):
1639 s = '%0.2f' % (x / 100.0)
1640 # should work the same as for floats
1641 self.assertEqual(int(Decimal(s)), int(float(s)))
1642 # should work the same as to_integral in the ROUND_DOWN mode
1643 d = Decimal(s)
1644 r = d.to_integral(ROUND_DOWN)
Jeffrey Yasskinca2b69f2008-02-01 06:22:46 +00001645 self.assertEqual(Decimal(math.trunc(d)), r)
Raymond Hettinger5a053642008-01-24 19:05:29 +00001646
Raymond Hettingerf4d85972009-01-03 19:02:23 +00001647 def test_from_float(self):
1648
1649 class MyDecimal(Decimal):
1650 pass
1651
1652 r = MyDecimal.from_float(0.1)
1653 self.assertEqual(type(r), MyDecimal)
1654 self.assertEqual(str(r),
1655 '0.1000000000000000055511151231257827021181583404541015625')
1656 bigint = 12345678901234567890123456789
1657 self.assertEqual(MyDecimal.from_float(bigint), MyDecimal(bigint))
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001658 self.assertTrue(MyDecimal.from_float(float('nan')).is_qnan())
1659 self.assertTrue(MyDecimal.from_float(float('inf')).is_infinite())
1660 self.assertTrue(MyDecimal.from_float(float('-inf')).is_infinite())
Raymond Hettingerf4d85972009-01-03 19:02:23 +00001661 self.assertEqual(str(MyDecimal.from_float(float('nan'))),
1662 str(Decimal('NaN')))
1663 self.assertEqual(str(MyDecimal.from_float(float('inf'))),
1664 str(Decimal('Infinity')))
1665 self.assertEqual(str(MyDecimal.from_float(float('-inf'))),
1666 str(Decimal('-Infinity')))
1667 self.assertRaises(TypeError, MyDecimal.from_float, 'abc')
1668 for i in range(200):
1669 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
1670 self.assertEqual(x, float(MyDecimal.from_float(x))) # roundtrip
1671
1672 def test_create_decimal_from_float(self):
1673 context = Context(prec=5, rounding=ROUND_DOWN)
1674 self.assertEqual(
1675 context.create_decimal_from_float(math.pi),
1676 Decimal('3.1415')
1677 )
1678 context = Context(prec=5, rounding=ROUND_UP)
1679 self.assertEqual(
1680 context.create_decimal_from_float(math.pi),
1681 Decimal('3.1416')
1682 )
1683 context = Context(prec=5, traps=[Inexact])
1684 self.assertRaises(
1685 Inexact,
1686 context.create_decimal_from_float,
1687 math.pi
1688 )
1689 self.assertEqual(repr(context.create_decimal_from_float(-0.0)),
1690 "Decimal('-0')")
1691 self.assertEqual(repr(context.create_decimal_from_float(1.0)),
1692 "Decimal('1')")
1693 self.assertEqual(repr(context.create_decimal_from_float(10)),
1694 "Decimal('10')")
1695
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00001696class ContextAPItests(unittest.TestCase):
1697
1698 def test_pickle(self):
1699 c = Context()
1700 e = pickle.loads(pickle.dumps(c))
1701 for k in vars(c):
1702 v1 = vars(c)[k]
1703 v2 = vars(e)[k]
1704 self.assertEqual(v1, v2)
1705
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001706 def test_equality_with_other_types(self):
Ezio Melottiaa980582010-01-23 23:04:36 +00001707 self.assertIn(Decimal(10), ['a', 1.0, Decimal(10), (1,2), {}])
1708 self.assertNotIn(Decimal(10), ['a', 1.0, (1,2), {}])
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001709
Raymond Hettinger955d2b22004-08-08 20:17:45 +00001710 def test_copy(self):
1711 # All copies should be deep
1712 c = Context()
1713 d = c.copy()
1714 self.assertNotEqual(id(c), id(d))
1715 self.assertNotEqual(id(c.flags), id(d.flags))
1716 self.assertNotEqual(id(c.traps), id(d.traps))
1717
Mark Dickinson6d8effb2010-02-18 14:27:02 +00001718 def test_abs(self):
1719 c = Context()
1720 d = c.abs(Decimal(-1))
1721 self.assertEqual(c.abs(-1), d)
1722 self.assertRaises(TypeError, c.abs, '-1')
1723
1724 def test_add(self):
1725 c = Context()
1726 d = c.add(Decimal(1), Decimal(1))
1727 self.assertEqual(c.add(1, 1), d)
1728 self.assertEqual(c.add(Decimal(1), 1), d)
1729 self.assertEqual(c.add(1, Decimal(1)), d)
1730 self.assertRaises(TypeError, c.add, '1', 1)
1731 self.assertRaises(TypeError, c.add, 1, '1')
1732
1733 def test_compare(self):
1734 c = Context()
1735 d = c.compare(Decimal(1), Decimal(1))
1736 self.assertEqual(c.compare(1, 1), d)
1737 self.assertEqual(c.compare(Decimal(1), 1), d)
1738 self.assertEqual(c.compare(1, Decimal(1)), d)
1739 self.assertRaises(TypeError, c.compare, '1', 1)
1740 self.assertRaises(TypeError, c.compare, 1, '1')
1741
1742 def test_compare_signal(self):
1743 c = Context()
1744 d = c.compare_signal(Decimal(1), Decimal(1))
1745 self.assertEqual(c.compare_signal(1, 1), d)
1746 self.assertEqual(c.compare_signal(Decimal(1), 1), d)
1747 self.assertEqual(c.compare_signal(1, Decimal(1)), d)
1748 self.assertRaises(TypeError, c.compare_signal, '1', 1)
1749 self.assertRaises(TypeError, c.compare_signal, 1, '1')
1750
1751 def test_compare_total(self):
1752 c = Context()
1753 d = c.compare_total(Decimal(1), Decimal(1))
1754 self.assertEqual(c.compare_total(1, 1), d)
1755 self.assertEqual(c.compare_total(Decimal(1), 1), d)
1756 self.assertEqual(c.compare_total(1, Decimal(1)), d)
1757 self.assertRaises(TypeError, c.compare_total, '1', 1)
1758 self.assertRaises(TypeError, c.compare_total, 1, '1')
1759
1760 def test_compare_total_mag(self):
1761 c = Context()
1762 d = c.compare_total_mag(Decimal(1), Decimal(1))
1763 self.assertEqual(c.compare_total_mag(1, 1), d)
1764 self.assertEqual(c.compare_total_mag(Decimal(1), 1), d)
1765 self.assertEqual(c.compare_total_mag(1, Decimal(1)), d)
1766 self.assertRaises(TypeError, c.compare_total_mag, '1', 1)
1767 self.assertRaises(TypeError, c.compare_total_mag, 1, '1')
1768
1769 def test_copy_abs(self):
1770 c = Context()
1771 d = c.copy_abs(Decimal(-1))
1772 self.assertEqual(c.copy_abs(-1), d)
1773 self.assertRaises(TypeError, c.copy_abs, '-1')
1774
1775 def test_copy_decimal(self):
1776 c = Context()
1777 d = c.copy_decimal(Decimal(-1))
1778 self.assertEqual(c.copy_decimal(-1), d)
1779 self.assertRaises(TypeError, c.copy_decimal, '-1')
1780
1781 def test_copy_negate(self):
1782 c = Context()
1783 d = c.copy_negate(Decimal(-1))
1784 self.assertEqual(c.copy_negate(-1), d)
1785 self.assertRaises(TypeError, c.copy_negate, '-1')
1786
1787 def test_copy_sign(self):
1788 c = Context()
1789 d = c.copy_sign(Decimal(1), Decimal(-2))
1790 self.assertEqual(c.copy_sign(1, -2), d)
1791 self.assertEqual(c.copy_sign(Decimal(1), -2), d)
1792 self.assertEqual(c.copy_sign(1, Decimal(-2)), d)
1793 self.assertRaises(TypeError, c.copy_sign, '1', -2)
1794 self.assertRaises(TypeError, c.copy_sign, 1, '-2')
1795
1796 def test_divide(self):
1797 c = Context()
1798 d = c.divide(Decimal(1), Decimal(2))
1799 self.assertEqual(c.divide(1, 2), d)
1800 self.assertEqual(c.divide(Decimal(1), 2), d)
1801 self.assertEqual(c.divide(1, Decimal(2)), d)
1802 self.assertRaises(TypeError, c.divide, '1', 2)
1803 self.assertRaises(TypeError, c.divide, 1, '2')
1804
1805 def test_divide_int(self):
1806 c = Context()
1807 d = c.divide_int(Decimal(1), Decimal(2))
1808 self.assertEqual(c.divide_int(1, 2), d)
1809 self.assertEqual(c.divide_int(Decimal(1), 2), d)
1810 self.assertEqual(c.divide_int(1, Decimal(2)), d)
1811 self.assertRaises(TypeError, c.divide_int, '1', 2)
1812 self.assertRaises(TypeError, c.divide_int, 1, '2')
1813
1814 def test_divmod(self):
1815 c = Context()
1816 d = c.divmod(Decimal(1), Decimal(2))
1817 self.assertEqual(c.divmod(1, 2), d)
1818 self.assertEqual(c.divmod(Decimal(1), 2), d)
1819 self.assertEqual(c.divmod(1, Decimal(2)), d)
1820 self.assertRaises(TypeError, c.divmod, '1', 2)
1821 self.assertRaises(TypeError, c.divmod, 1, '2')
1822
1823 def test_exp(self):
1824 c = Context()
1825 d = c.exp(Decimal(10))
1826 self.assertEqual(c.exp(10), d)
1827 self.assertRaises(TypeError, c.exp, '10')
1828
1829 def test_fma(self):
1830 c = Context()
1831 d = c.fma(Decimal(2), Decimal(3), Decimal(4))
1832 self.assertEqual(c.fma(2, 3, 4), d)
1833 self.assertEqual(c.fma(Decimal(2), 3, 4), d)
1834 self.assertEqual(c.fma(2, Decimal(3), 4), d)
1835 self.assertEqual(c.fma(2, 3, Decimal(4)), d)
1836 self.assertEqual(c.fma(Decimal(2), Decimal(3), 4), d)
1837 self.assertRaises(TypeError, c.fma, '2', 3, 4)
1838 self.assertRaises(TypeError, c.fma, 2, '3', 4)
1839 self.assertRaises(TypeError, c.fma, 2, 3, '4')
1840
1841 def test_is_finite(self):
1842 c = Context()
1843 d = c.is_finite(Decimal(10))
1844 self.assertEqual(c.is_finite(10), d)
1845 self.assertRaises(TypeError, c.is_finite, '10')
1846
1847 def test_is_infinite(self):
1848 c = Context()
1849 d = c.is_infinite(Decimal(10))
1850 self.assertEqual(c.is_infinite(10), d)
1851 self.assertRaises(TypeError, c.is_infinite, '10')
1852
1853 def test_is_nan(self):
1854 c = Context()
1855 d = c.is_nan(Decimal(10))
1856 self.assertEqual(c.is_nan(10), d)
1857 self.assertRaises(TypeError, c.is_nan, '10')
1858
1859 def test_is_normal(self):
1860 c = Context()
1861 d = c.is_normal(Decimal(10))
1862 self.assertEqual(c.is_normal(10), d)
1863 self.assertRaises(TypeError, c.is_normal, '10')
1864
1865 def test_is_qnan(self):
1866 c = Context()
1867 d = c.is_qnan(Decimal(10))
1868 self.assertEqual(c.is_qnan(10), d)
1869 self.assertRaises(TypeError, c.is_qnan, '10')
1870
1871 def test_is_signed(self):
1872 c = Context()
1873 d = c.is_signed(Decimal(10))
1874 self.assertEqual(c.is_signed(10), d)
1875 self.assertRaises(TypeError, c.is_signed, '10')
1876
1877 def test_is_snan(self):
1878 c = Context()
1879 d = c.is_snan(Decimal(10))
1880 self.assertEqual(c.is_snan(10), d)
1881 self.assertRaises(TypeError, c.is_snan, '10')
1882
1883 def test_is_subnormal(self):
1884 c = Context()
1885 d = c.is_subnormal(Decimal(10))
1886 self.assertEqual(c.is_subnormal(10), d)
1887 self.assertRaises(TypeError, c.is_subnormal, '10')
1888
1889 def test_is_zero(self):
1890 c = Context()
1891 d = c.is_zero(Decimal(10))
1892 self.assertEqual(c.is_zero(10), d)
1893 self.assertRaises(TypeError, c.is_zero, '10')
1894
1895 def test_ln(self):
1896 c = Context()
1897 d = c.ln(Decimal(10))
1898 self.assertEqual(c.ln(10), d)
1899 self.assertRaises(TypeError, c.ln, '10')
1900
1901 def test_log10(self):
1902 c = Context()
1903 d = c.log10(Decimal(10))
1904 self.assertEqual(c.log10(10), d)
1905 self.assertRaises(TypeError, c.log10, '10')
1906
1907 def test_logb(self):
1908 c = Context()
1909 d = c.logb(Decimal(10))
1910 self.assertEqual(c.logb(10), d)
1911 self.assertRaises(TypeError, c.logb, '10')
1912
1913 def test_logical_and(self):
1914 c = Context()
1915 d = c.logical_and(Decimal(1), Decimal(1))
1916 self.assertEqual(c.logical_and(1, 1), d)
1917 self.assertEqual(c.logical_and(Decimal(1), 1), d)
1918 self.assertEqual(c.logical_and(1, Decimal(1)), d)
1919 self.assertRaises(TypeError, c.logical_and, '1', 1)
1920 self.assertRaises(TypeError, c.logical_and, 1, '1')
1921
1922 def test_logical_invert(self):
1923 c = Context()
1924 d = c.logical_invert(Decimal(1000))
1925 self.assertEqual(c.logical_invert(1000), d)
1926 self.assertRaises(TypeError, c.logical_invert, '1000')
1927
1928 def test_logical_or(self):
1929 c = Context()
1930 d = c.logical_or(Decimal(1), Decimal(1))
1931 self.assertEqual(c.logical_or(1, 1), d)
1932 self.assertEqual(c.logical_or(Decimal(1), 1), d)
1933 self.assertEqual(c.logical_or(1, Decimal(1)), d)
1934 self.assertRaises(TypeError, c.logical_or, '1', 1)
1935 self.assertRaises(TypeError, c.logical_or, 1, '1')
1936
1937 def test_logical_xor(self):
1938 c = Context()
1939 d = c.logical_xor(Decimal(1), Decimal(1))
1940 self.assertEqual(c.logical_xor(1, 1), d)
1941 self.assertEqual(c.logical_xor(Decimal(1), 1), d)
1942 self.assertEqual(c.logical_xor(1, Decimal(1)), d)
1943 self.assertRaises(TypeError, c.logical_xor, '1', 1)
1944 self.assertRaises(TypeError, c.logical_xor, 1, '1')
1945
1946 def test_max(self):
1947 c = Context()
1948 d = c.max(Decimal(1), Decimal(2))
1949 self.assertEqual(c.max(1, 2), d)
1950 self.assertEqual(c.max(Decimal(1), 2), d)
1951 self.assertEqual(c.max(1, Decimal(2)), d)
1952 self.assertRaises(TypeError, c.max, '1', 2)
1953 self.assertRaises(TypeError, c.max, 1, '2')
1954
1955 def test_max_mag(self):
1956 c = Context()
1957 d = c.max_mag(Decimal(1), Decimal(2))
1958 self.assertEqual(c.max_mag(1, 2), d)
1959 self.assertEqual(c.max_mag(Decimal(1), 2), d)
1960 self.assertEqual(c.max_mag(1, Decimal(2)), d)
1961 self.assertRaises(TypeError, c.max_mag, '1', 2)
1962 self.assertRaises(TypeError, c.max_mag, 1, '2')
1963
1964 def test_min(self):
1965 c = Context()
1966 d = c.min(Decimal(1), Decimal(2))
1967 self.assertEqual(c.min(1, 2), d)
1968 self.assertEqual(c.min(Decimal(1), 2), d)
1969 self.assertEqual(c.min(1, Decimal(2)), d)
1970 self.assertRaises(TypeError, c.min, '1', 2)
1971 self.assertRaises(TypeError, c.min, 1, '2')
1972
1973 def test_min_mag(self):
1974 c = Context()
1975 d = c.min_mag(Decimal(1), Decimal(2))
1976 self.assertEqual(c.min_mag(1, 2), d)
1977 self.assertEqual(c.min_mag(Decimal(1), 2), d)
1978 self.assertEqual(c.min_mag(1, Decimal(2)), d)
1979 self.assertRaises(TypeError, c.min_mag, '1', 2)
1980 self.assertRaises(TypeError, c.min_mag, 1, '2')
1981
1982 def test_minus(self):
1983 c = Context()
1984 d = c.minus(Decimal(10))
1985 self.assertEqual(c.minus(10), d)
1986 self.assertRaises(TypeError, c.minus, '10')
1987
1988 def test_multiply(self):
1989 c = Context()
1990 d = c.multiply(Decimal(1), Decimal(2))
1991 self.assertEqual(c.multiply(1, 2), d)
1992 self.assertEqual(c.multiply(Decimal(1), 2), d)
1993 self.assertEqual(c.multiply(1, Decimal(2)), d)
1994 self.assertRaises(TypeError, c.multiply, '1', 2)
1995 self.assertRaises(TypeError, c.multiply, 1, '2')
1996
1997 def test_next_minus(self):
1998 c = Context()
1999 d = c.next_minus(Decimal(10))
2000 self.assertEqual(c.next_minus(10), d)
2001 self.assertRaises(TypeError, c.next_minus, '10')
2002
2003 def test_next_plus(self):
2004 c = Context()
2005 d = c.next_plus(Decimal(10))
2006 self.assertEqual(c.next_plus(10), d)
2007 self.assertRaises(TypeError, c.next_plus, '10')
2008
2009 def test_next_toward(self):
2010 c = Context()
2011 d = c.next_toward(Decimal(1), Decimal(2))
2012 self.assertEqual(c.next_toward(1, 2), d)
2013 self.assertEqual(c.next_toward(Decimal(1), 2), d)
2014 self.assertEqual(c.next_toward(1, Decimal(2)), d)
2015 self.assertRaises(TypeError, c.next_toward, '1', 2)
2016 self.assertRaises(TypeError, c.next_toward, 1, '2')
2017
2018 def test_normalize(self):
2019 c = Context()
2020 d = c.normalize(Decimal(10))
2021 self.assertEqual(c.normalize(10), d)
2022 self.assertRaises(TypeError, c.normalize, '10')
2023
2024 def test_number_class(self):
2025 c = Context()
2026 self.assertEqual(c.number_class(123), c.number_class(Decimal(123)))
2027 self.assertEqual(c.number_class(0), c.number_class(Decimal(0)))
2028 self.assertEqual(c.number_class(-45), c.number_class(Decimal(-45)))
2029
2030 def test_power(self):
2031 c = Context()
2032 d = c.power(Decimal(1), Decimal(4), Decimal(2))
2033 self.assertEqual(c.power(1, 4, 2), d)
2034 self.assertEqual(c.power(Decimal(1), 4, 2), d)
2035 self.assertEqual(c.power(1, Decimal(4), 2), d)
2036 self.assertEqual(c.power(1, 4, Decimal(2)), d)
2037 self.assertEqual(c.power(Decimal(1), Decimal(4), 2), d)
2038 self.assertRaises(TypeError, c.power, '1', 4, 2)
2039 self.assertRaises(TypeError, c.power, 1, '4', 2)
2040 self.assertRaises(TypeError, c.power, 1, 4, '2')
2041
2042 def test_plus(self):
2043 c = Context()
2044 d = c.plus(Decimal(10))
2045 self.assertEqual(c.plus(10), d)
2046 self.assertRaises(TypeError, c.plus, '10')
2047
2048 def test_quantize(self):
2049 c = Context()
2050 d = c.quantize(Decimal(1), Decimal(2))
2051 self.assertEqual(c.quantize(1, 2), d)
2052 self.assertEqual(c.quantize(Decimal(1), 2), d)
2053 self.assertEqual(c.quantize(1, Decimal(2)), d)
2054 self.assertRaises(TypeError, c.quantize, '1', 2)
2055 self.assertRaises(TypeError, c.quantize, 1, '2')
2056
2057 def test_remainder(self):
2058 c = Context()
2059 d = c.remainder(Decimal(1), Decimal(2))
2060 self.assertEqual(c.remainder(1, 2), d)
2061 self.assertEqual(c.remainder(Decimal(1), 2), d)
2062 self.assertEqual(c.remainder(1, Decimal(2)), d)
2063 self.assertRaises(TypeError, c.remainder, '1', 2)
2064 self.assertRaises(TypeError, c.remainder, 1, '2')
2065
2066 def test_remainder_near(self):
2067 c = Context()
2068 d = c.remainder_near(Decimal(1), Decimal(2))
2069 self.assertEqual(c.remainder_near(1, 2), d)
2070 self.assertEqual(c.remainder_near(Decimal(1), 2), d)
2071 self.assertEqual(c.remainder_near(1, Decimal(2)), d)
2072 self.assertRaises(TypeError, c.remainder_near, '1', 2)
2073 self.assertRaises(TypeError, c.remainder_near, 1, '2')
2074
2075 def test_rotate(self):
2076 c = Context()
2077 d = c.rotate(Decimal(1), Decimal(2))
2078 self.assertEqual(c.rotate(1, 2), d)
2079 self.assertEqual(c.rotate(Decimal(1), 2), d)
2080 self.assertEqual(c.rotate(1, Decimal(2)), d)
2081 self.assertRaises(TypeError, c.rotate, '1', 2)
2082 self.assertRaises(TypeError, c.rotate, 1, '2')
2083
2084 def test_sqrt(self):
2085 c = Context()
2086 d = c.sqrt(Decimal(10))
2087 self.assertEqual(c.sqrt(10), d)
2088 self.assertRaises(TypeError, c.sqrt, '10')
2089
2090 def test_same_quantum(self):
2091 c = Context()
2092 d = c.same_quantum(Decimal(1), Decimal(2))
2093 self.assertEqual(c.same_quantum(1, 2), d)
2094 self.assertEqual(c.same_quantum(Decimal(1), 2), d)
2095 self.assertEqual(c.same_quantum(1, Decimal(2)), d)
2096 self.assertRaises(TypeError, c.same_quantum, '1', 2)
2097 self.assertRaises(TypeError, c.same_quantum, 1, '2')
2098
2099 def test_scaleb(self):
2100 c = Context()
2101 d = c.scaleb(Decimal(1), Decimal(2))
2102 self.assertEqual(c.scaleb(1, 2), d)
2103 self.assertEqual(c.scaleb(Decimal(1), 2), d)
2104 self.assertEqual(c.scaleb(1, Decimal(2)), d)
2105 self.assertRaises(TypeError, c.scaleb, '1', 2)
2106 self.assertRaises(TypeError, c.scaleb, 1, '2')
2107
2108 def test_shift(self):
2109 c = Context()
2110 d = c.shift(Decimal(1), Decimal(2))
2111 self.assertEqual(c.shift(1, 2), d)
2112 self.assertEqual(c.shift(Decimal(1), 2), d)
2113 self.assertEqual(c.shift(1, Decimal(2)), d)
2114 self.assertRaises(TypeError, c.shift, '1', 2)
2115 self.assertRaises(TypeError, c.shift, 1, '2')
2116
2117 def test_subtract(self):
2118 c = Context()
2119 d = c.subtract(Decimal(1), Decimal(2))
2120 self.assertEqual(c.subtract(1, 2), d)
2121 self.assertEqual(c.subtract(Decimal(1), 2), d)
2122 self.assertEqual(c.subtract(1, Decimal(2)), d)
2123 self.assertRaises(TypeError, c.subtract, '1', 2)
2124 self.assertRaises(TypeError, c.subtract, 1, '2')
2125
2126 def test_to_eng_string(self):
2127 c = Context()
2128 d = c.to_eng_string(Decimal(10))
2129 self.assertEqual(c.to_eng_string(10), d)
2130 self.assertRaises(TypeError, c.to_eng_string, '10')
2131
2132 def test_to_sci_string(self):
2133 c = Context()
2134 d = c.to_sci_string(Decimal(10))
2135 self.assertEqual(c.to_sci_string(10), d)
2136 self.assertRaises(TypeError, c.to_sci_string, '10')
2137
2138 def test_to_integral_exact(self):
2139 c = Context()
2140 d = c.to_integral_exact(Decimal(10))
2141 self.assertEqual(c.to_integral_exact(10), d)
2142 self.assertRaises(TypeError, c.to_integral_exact, '10')
2143
2144 def test_to_integral_value(self):
2145 c = Context()
2146 d = c.to_integral_value(Decimal(10))
2147 self.assertEqual(c.to_integral_value(10), d)
2148 self.assertRaises(TypeError, c.to_integral_value, '10')
2149
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002150class WithStatementTest(unittest.TestCase):
2151 # Can't do these as docstrings until Python 2.6
2152 # as doctest can't handle __future__ statements
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002153
2154 def test_localcontext(self):
Nick Coghlanced12182006-09-02 03:54:17 +00002155 # Use a copy of the current context in the block
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002156 orig_ctx = getcontext()
2157 with localcontext() as enter_ctx:
2158 set_ctx = getcontext()
2159 final_ctx = getcontext()
Benjamin Peterson5c8da862009-06-30 22:57:08 +00002160 self.assertTrue(orig_ctx is final_ctx, 'did not restore context correctly')
2161 self.assertTrue(orig_ctx is not set_ctx, 'did not copy the context')
2162 self.assertTrue(set_ctx is enter_ctx, '__enter__ returned wrong context')
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002163
2164 def test_localcontextarg(self):
Nick Coghlanced12182006-09-02 03:54:17 +00002165 # Use a copy of the supplied context in the block
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002166 orig_ctx = getcontext()
2167 new_ctx = Context(prec=42)
2168 with localcontext(new_ctx) as enter_ctx:
2169 set_ctx = getcontext()
2170 final_ctx = getcontext()
Benjamin Peterson5c8da862009-06-30 22:57:08 +00002171 self.assertTrue(orig_ctx is final_ctx, 'did not restore context correctly')
2172 self.assertTrue(set_ctx.prec == new_ctx.prec, 'did not set correct context')
2173 self.assertTrue(new_ctx is not set_ctx, 'did not copy the context')
2174 self.assertTrue(set_ctx is enter_ctx, '__enter__ returned wrong context')
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002175
Facundo Batista353750c2007-09-13 18:13:15 +00002176class ContextFlags(unittest.TestCase):
2177 def test_flags_irrelevant(self):
2178 # check that the result (numeric result + flags raised) of an
2179 # arithmetic operation doesn't depend on the current flags
2180
2181 context = Context(prec=9, Emin = -999999999, Emax = 999999999,
2182 rounding=ROUND_HALF_EVEN, traps=[], flags=[])
2183
2184 # operations that raise various flags, in the form (function, arglist)
2185 operations = [
2186 (context._apply, [Decimal("100E-1000000009")]),
2187 (context.sqrt, [Decimal(2)]),
2188 (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]),
2189 (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]),
2190 (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]),
2191 ]
2192
2193 # try various flags individually, then a whole lot at once
2194 flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal],
2195 [Inexact, Rounded, Underflow, Clamped, Subnormal]]
2196
2197 for fn, args in operations:
2198 # find answer and flags raised using a clean context
2199 context.clear_flags()
2200 ans = fn(*args)
2201 flags = [k for k, v in context.flags.items() if v]
2202
2203 for extra_flags in flagsets:
2204 # set flags, before calling operation
2205 context.clear_flags()
2206 for flag in extra_flags:
2207 context._raise_error(flag)
2208 new_ans = fn(*args)
2209
2210 # flags that we expect to be set after the operation
2211 expected_flags = list(flags)
2212 for flag in extra_flags:
2213 if flag not in expected_flags:
2214 expected_flags.append(flag)
Facundo Batista353750c2007-09-13 18:13:15 +00002215
2216 # flags we actually got
2217 new_flags = [k for k,v in context.flags.items() if v]
Facundo Batista353750c2007-09-13 18:13:15 +00002218
2219 self.assertEqual(ans, new_ans,
2220 "operation produces different answers depending on flags set: " +
2221 "expected %s, got %s." % (ans, new_ans))
Florent Xicluna8f43cec2010-03-21 10:51:40 +00002222 self.assertItemsEqual(new_flags, expected_flags,
Facundo Batista353750c2007-09-13 18:13:15 +00002223 "operation raises different flags depending on flags set: " +
2224 "expected %s, got %s" % (expected_flags, new_flags))
2225
2226def test_main(arith=False, verbose=None, todo_tests=None, debug=None):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002227 """ Execute the tests.
2228
Raymond Hettingered20ad82004-09-04 20:09:13 +00002229 Runs all arithmetic tests if arith is True or if the "decimal" resource
2230 is enabled in regrtest.py
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002231 """
Raymond Hettingered20ad82004-09-04 20:09:13 +00002232
Neal Norwitzce4a9c92006-04-09 08:36:46 +00002233 init()
Facundo Batista353750c2007-09-13 18:13:15 +00002234 global TEST_ALL, DEBUG
Raymond Hettingered20ad82004-09-04 20:09:13 +00002235 TEST_ALL = arith or is_resource_enabled('decimal')
Facundo Batista353750c2007-09-13 18:13:15 +00002236 DEBUG = debug
Raymond Hettingered20ad82004-09-04 20:09:13 +00002237
Facundo Batista353750c2007-09-13 18:13:15 +00002238 if todo_tests is None:
2239 test_classes = [
2240 DecimalExplicitConstructionTest,
2241 DecimalImplicitConstructionTest,
2242 DecimalArithmeticOperatorsTest,
Mark Dickinson1ddf1d82008-02-29 02:16:37 +00002243 DecimalFormatTest,
Facundo Batista353750c2007-09-13 18:13:15 +00002244 DecimalUseOfContextTest,
2245 DecimalUsabilityTest,
2246 DecimalPythonAPItests,
2247 ContextAPItests,
2248 DecimalTest,
2249 WithStatementTest,
2250 ContextFlags
2251 ]
2252 else:
2253 test_classes = [DecimalTest]
2254
2255 # Dynamically build custom test definition for each file in the test
2256 # directory and add the definitions to the DecimalTest class. This
2257 # procedure insures that new files do not get skipped.
2258 for filename in os.listdir(directory):
2259 if '.decTest' not in filename or filename.startswith("."):
2260 continue
2261 head, tail = filename.split('.')
2262 if todo_tests is not None and head not in todo_tests:
2263 continue
2264 tester = lambda self, f=filename: self.eval_file(directory + f)
2265 setattr(DecimalTest, 'test_' + head, tester)
2266 del filename, head, tail, tester
2267
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002268
Tim Peters46cc7022006-03-31 04:11:16 +00002269 try:
2270 run_unittest(*test_classes)
Facundo Batista353750c2007-09-13 18:13:15 +00002271 if todo_tests is None:
2272 import decimal as DecimalModule
2273 run_doctest(DecimalModule, verbose)
Tim Peters46cc7022006-03-31 04:11:16 +00002274 finally:
2275 setcontext(ORIGINAL_CONTEXT)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002276
2277if __name__ == '__main__':
Facundo Batista353750c2007-09-13 18:13:15 +00002278 import optparse
2279 p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]")
2280 p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test')
2281 p.add_option('--skip', '-s', action='store_true', help='skip over 90% of the arithmetic tests')
2282 (opt, args) = p.parse_args()
2283
2284 if opt.skip:
2285 test_main(arith=False, verbose=True)
2286 elif args:
2287 test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002288 else:
Facundo Batista353750c2007-09-13 18:13:15 +00002289 test_main(arith=True, verbose=True)