blob: 35d74056c9501763c7d0099d2945fed767bc8b5e [file] [log] [blame]
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001# Copyright (c) 2004 Python Software Foundation.
2# All rights reserved.
3
4# Written by Eric Price <eprice at tjhsst.edu>
5# and Facundo Batista <facundo at taniquetil.com.ar>
6# and Raymond Hettinger <python at rcn.com>
7# and Aahz (aahz at pobox.com)
8# and Tim Peters
9
10"""
11These are the test cases for the Decimal module.
12
13There are two groups of tests, Arithmetic and Behaviour. The former test
14the Decimal arithmetic using the tests provided by Mike Cowlishaw. The latter
15test the pythonic behaviour according to PEP 327.
16
17Cowlishaw's tests can be downloaded from:
18
19 www2.hursley.ibm.com/decimal/dectest.zip
20
21This test module can be called from command line with one parameter (Arithmetic
22or Behaviour) to test each part, or without parameter to test both parts. If
23you're working through IDLE, you can import this test module and call test_main()
24with the corresponding argument.
25"""
26
Jeffrey Yasskinca2b69f2008-02-01 06:22:46 +000027import math
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000028import os, sys
29import pickle, copy
Jeffrey Yasskinca2b69f2008-02-01 06:22:46 +000030import unittest
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000031from decimal import *
Raymond Hettinger2c8585b2009-02-03 03:37:03 +000032import numbers
Florent Xicluna8f43cec2010-03-21 10:51:40 +000033from test.test_support import (run_unittest, run_doctest,
34 is_resource_enabled, check_py3k_warnings)
Raymond Hettinger0aeac102004-07-05 22:53:03 +000035import random
Raymond Hettinger7e71fa52004-12-18 19:07:19 +000036try:
37 import threading
38except ImportError:
39 threading = None
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000040
Raymond Hettingerfed52962004-07-14 15:41:57 +000041# Useful Test Constant
42Signals = getcontext().flags.keys()
43
Tim Peters46cc7022006-03-31 04:11:16 +000044# Tests are built around these assumed context defaults.
45# test_main() restores the original context.
Neal Norwitzce4a9c92006-04-09 08:36:46 +000046def init():
47 global ORIGINAL_CONTEXT
48 ORIGINAL_CONTEXT = getcontext().copy()
Facundo Batistaee340e52008-05-02 17:39:00 +000049 DefaultTestContext = Context(
50 prec = 9,
51 rounding = ROUND_HALF_EVEN,
52 traps = dict.fromkeys(Signals, 0)
53 )
54 setcontext(DefaultTestContext)
Raymond Hettinger6ea48452004-07-03 12:26:21 +000055
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000056TESTDATADIR = 'decimaltestdata'
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +000057if __name__ == '__main__':
58 file = sys.argv[0]
59else:
60 file = __file__
61testdir = os.path.dirname(file) or os.curdir
Raymond Hettinger267b8682005-03-27 10:47:39 +000062directory = testdir + os.sep + TESTDATADIR + os.sep
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000063
Raymond Hettinger267b8682005-03-27 10:47:39 +000064skip_expected = not os.path.isdir(directory)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000065
Mark Dickinson539bff42009-10-08 16:28:39 +000066# list of individual .decTest test ids that correspond to tests that
67# we're skipping for one reason or another.
68skipped_test_ids = [
69 'scbx164', # skipping apparently implementation-specific scaleb
70 'scbx165', # tests, pending clarification of scaleb rules.
71]
72
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000073# Make sure it actually raises errors when not expected and caught in flags
74# Slower, since it runs some things several times.
75EXTENDEDERRORTEST = False
76
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000077#Map the test cases' error names to the actual errors
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000078ErrorNames = {'clamped' : Clamped,
Raymond Hettinger5aa478b2004-07-09 10:02:53 +000079 'conversion_syntax' : InvalidOperation,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000080 'division_by_zero' : DivisionByZero,
Raymond Hettinger5aa478b2004-07-09 10:02:53 +000081 'division_impossible' : InvalidOperation,
82 'division_undefined' : InvalidOperation,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000083 'inexact' : Inexact,
Raymond Hettinger5aa478b2004-07-09 10:02:53 +000084 'invalid_context' : InvalidOperation,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000085 'invalid_operation' : InvalidOperation,
86 'overflow' : Overflow,
87 'rounded' : Rounded,
88 'subnormal' : Subnormal,
89 'underflow' : Underflow}
90
91
92def Nonfunction(*args):
93 """Doesn't do anything."""
94 return None
95
96RoundingDict = {'ceiling' : ROUND_CEILING, #Maps test-case names to roundings.
97 'down' : ROUND_DOWN,
98 'floor' : ROUND_FLOOR,
99 'half_down' : ROUND_HALF_DOWN,
100 'half_even' : ROUND_HALF_EVEN,
101 'half_up' : ROUND_HALF_UP,
Facundo Batista353750c2007-09-13 18:13:15 +0000102 'up' : ROUND_UP,
103 '05up' : ROUND_05UP}
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000104
105# Name adapter to be able to change the Decimal and Context
106# interface without changing the test files from Cowlishaw
Facundo Batista1a191df2007-10-02 17:01:24 +0000107nameAdapter = {'and':'logical_and',
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000108 'apply':'_apply',
Facundo Batista353750c2007-09-13 18:13:15 +0000109 'class':'number_class',
110 'comparesig':'compare_signal',
111 'comparetotal':'compare_total',
112 'comparetotmag':'compare_total_mag',
Facundo Batista353750c2007-09-13 18:13:15 +0000113 'copy':'copy_decimal',
Facundo Batista1a191df2007-10-02 17:01:24 +0000114 'copyabs':'copy_abs',
Facundo Batista353750c2007-09-13 18:13:15 +0000115 'copynegate':'copy_negate',
116 'copysign':'copy_sign',
Facundo Batista1a191df2007-10-02 17:01:24 +0000117 'divideint':'divide_int',
Facundo Batista353750c2007-09-13 18:13:15 +0000118 'invert':'logical_invert',
Facundo Batista1a191df2007-10-02 17:01:24 +0000119 'iscanonical':'is_canonical',
120 'isfinite':'is_finite',
121 'isinfinite':'is_infinite',
122 'isnan':'is_nan',
123 'isnormal':'is_normal',
124 'isqnan':'is_qnan',
125 'issigned':'is_signed',
126 'issnan':'is_snan',
127 'issubnormal':'is_subnormal',
128 'iszero':'is_zero',
Facundo Batista353750c2007-09-13 18:13:15 +0000129 'maxmag':'max_mag',
130 'minmag':'min_mag',
131 'nextminus':'next_minus',
132 'nextplus':'next_plus',
133 'nexttoward':'next_toward',
Facundo Batista1a191df2007-10-02 17:01:24 +0000134 'or':'logical_or',
Facundo Batista353750c2007-09-13 18:13:15 +0000135 'reduce':'normalize',
Facundo Batista1a191df2007-10-02 17:01:24 +0000136 'remaindernear':'remainder_near',
137 'samequantum':'same_quantum',
138 'squareroot':'sqrt',
139 'toeng':'to_eng_string',
140 'tointegral':'to_integral_value',
141 'tointegralx':'to_integral_exact',
142 'tosci':'to_sci_string',
143 'xor':'logical_xor',
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000144 }
145
Facundo Batista1a191df2007-10-02 17:01:24 +0000146# The following functions return True/False rather than a Decimal instance
147
148LOGICAL_FUNCTIONS = (
149 'is_canonical',
150 'is_finite',
151 'is_infinite',
152 'is_nan',
153 'is_normal',
154 'is_qnan',
155 'is_signed',
156 'is_snan',
157 'is_subnormal',
158 'is_zero',
159 'same_quantum',
160 )
161
Facundo Batista353750c2007-09-13 18:13:15 +0000162# For some operations (currently exp, ln, log10, power), the decNumber
163# reference implementation imposes additional restrictions on the
164# context and operands. These restrictions are not part of the
165# specification; however, the effect of these restrictions does show
166# up in some of the testcases. We skip testcases that violate these
167# restrictions, since Decimal behaves differently from decNumber for
168# these testcases so these testcases would otherwise fail.
169
170decNumberRestricted = ('power', 'ln', 'log10', 'exp')
171DEC_MAX_MATH = 999999
172def outside_decNumber_bounds(v, context):
173 if (context.prec > DEC_MAX_MATH or
174 context.Emax > DEC_MAX_MATH or
175 -context.Emin > DEC_MAX_MATH):
176 return True
177 if not v._is_special and v and (
Facundo Batista353750c2007-09-13 18:13:15 +0000178 v.adjusted() > DEC_MAX_MATH or
179 v.adjusted() < 1-2*DEC_MAX_MATH):
180 return True
181 return False
182
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000183class DecimalTest(unittest.TestCase):
184 """Class which tests the Decimal class against the test cases.
185
186 Changed for unittest.
187 """
188 def setUp(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000189 self.context = Context()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000190 self.ignore_list = ['#']
191 # Basically, a # means return NaN InvalidOperation.
192 # Different from a sNaN in trim
193
194 self.ChangeDict = {'precision' : self.change_precision,
195 'rounding' : self.change_rounding_method,
196 'maxexponent' : self.change_max_exponent,
197 'minexponent' : self.change_min_exponent,
198 'clamp' : self.change_clamp}
199
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000200 def eval_file(self, file):
201 global skip_expected
202 if skip_expected:
Benjamin Petersonbec087f2009-03-26 21:10:30 +0000203 raise unittest.SkipTest
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000204 return
Florent Xicluna8f43cec2010-03-21 10:51:40 +0000205 for line in open(file):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000206 line = line.replace('\r\n', '').replace('\n', '')
Raymond Hettinger5aa478b2004-07-09 10:02:53 +0000207 #print line
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000208 try:
209 t = self.eval_line(line)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000210 except DecimalException, exception:
211 #Exception raised where there shoudn't have been one.
212 self.fail('Exception "'+exception.__class__.__name__ + '" raised on line '+line)
213
214 return
215
216 def eval_line(self, s):
217 if s.find(' -> ') >= 0 and s[:2] != '--' and not s.startswith(' --'):
218 s = (s.split('->')[0] + '->' +
219 s.split('->')[1].split('--')[0]).strip()
220 else:
221 s = s.split('--')[0].strip()
222
223 for ignore in self.ignore_list:
224 if s.find(ignore) >= 0:
225 #print s.split()[0], 'NotImplemented--', ignore
226 return
227 if not s:
228 return
229 elif ':' in s:
230 return self.eval_directive(s)
231 else:
232 return self.eval_equation(s)
233
234 def eval_directive(self, s):
235 funct, value = map(lambda x: x.strip().lower(), s.split(':'))
236 if funct == 'rounding':
237 value = RoundingDict[value]
238 else:
239 try:
240 value = int(value)
241 except ValueError:
242 pass
243
244 funct = self.ChangeDict.get(funct, Nonfunction)
245 funct(value)
246
247 def eval_equation(self, s):
248 #global DEFAULT_PRECISION
249 #print DEFAULT_PRECISION
Raymond Hettingered20ad82004-09-04 20:09:13 +0000250
251 if not TEST_ALL and random.random() < 0.90:
252 return
253
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000254 try:
255 Sides = s.split('->')
256 L = Sides[0].strip().split()
257 id = L[0]
Facundo Batista353750c2007-09-13 18:13:15 +0000258 if DEBUG:
259 print "Test ", id,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000260 funct = L[1].lower()
261 valstemp = L[2:]
262 L = Sides[1].strip().split()
263 ans = L[0]
264 exceptions = L[1:]
265 except (TypeError, AttributeError, IndexError):
Raymond Hettingerd87ac8f2004-07-09 10:52:54 +0000266 raise InvalidOperation
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000267 def FixQuotes(val):
268 val = val.replace("''", 'SingleQuote').replace('""', 'DoubleQuote')
269 val = val.replace("'", '').replace('"', '')
270 val = val.replace('SingleQuote', "'").replace('DoubleQuote', '"')
271 return val
Mark Dickinson539bff42009-10-08 16:28:39 +0000272
273 if id in skipped_test_ids:
274 return
275
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000276 fname = nameAdapter.get(funct, funct)
277 if fname == 'rescale':
278 return
279 funct = getattr(self.context, fname)
280 vals = []
281 conglomerate = ''
282 quote = 0
283 theirexceptions = [ErrorNames[x.lower()] for x in exceptions]
284
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000285 for exception in Signals:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000286 self.context.traps[exception] = 1 #Catch these bugs...
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000287 for exception in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000288 self.context.traps[exception] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000289 for i, val in enumerate(valstemp):
290 if val.count("'") % 2 == 1:
291 quote = 1 - quote
292 if quote:
293 conglomerate = conglomerate + ' ' + val
294 continue
295 else:
296 val = conglomerate + val
297 conglomerate = ''
298 v = FixQuotes(val)
299 if fname in ('to_sci_string', 'to_eng_string'):
300 if EXTENDEDERRORTEST:
301 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000302 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000303 try:
304 funct(self.context.create_decimal(v))
305 except error:
306 pass
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000307 except Signals, e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000308 self.fail("Raised %s in %s when %s disabled" % \
309 (e, s, error))
310 else:
311 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000312 self.context.traps[error] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000313 v = self.context.create_decimal(v)
314 else:
Facundo Batista353750c2007-09-13 18:13:15 +0000315 v = Decimal(v, self.context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000316 vals.append(v)
317
318 ans = FixQuotes(ans)
319
Facundo Batista353750c2007-09-13 18:13:15 +0000320 # skip tests that are related to bounds imposed in the decNumber
321 # reference implementation
322 if fname in decNumberRestricted:
323 if fname == 'power':
324 if not (vals[1]._isinteger() and
325 -1999999997 <= vals[1] <= 999999999):
326 if outside_decNumber_bounds(vals[0], self.context) or \
327 outside_decNumber_bounds(vals[1], self.context):
328 #print "Skipping test %s" % s
329 return
330 else:
331 if outside_decNumber_bounds(vals[0], self.context):
332 #print "Skipping test %s" % s
333 return
334
335
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000336 if EXTENDEDERRORTEST and fname not in ('to_sci_string', 'to_eng_string'):
337 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000338 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000339 try:
340 funct(*vals)
341 except error:
342 pass
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000343 except Signals, e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000344 self.fail("Raised %s in %s when %s disabled" % \
345 (e, s, error))
346 else:
347 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000348 self.context.traps[error] = 0
Facundo Batista353750c2007-09-13 18:13:15 +0000349 if DEBUG:
350 print "--", self.context
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000351 try:
352 result = str(funct(*vals))
Facundo Batista1a191df2007-10-02 17:01:24 +0000353 if fname in LOGICAL_FUNCTIONS:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000354 result = str(int(eval(result))) # 'True', 'False' -> '1', '0'
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000355 except Signals, error:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000356 self.fail("Raised %s in %s" % (error, s))
357 except: #Catch any error long enough to state the test case.
358 print "ERROR:", s
359 raise
360
361 myexceptions = self.getexceptions()
Raymond Hettingerbf440692004-07-10 14:14:37 +0000362 self.context.clear_flags()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000363
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000364 self.assertEqual(result, ans,
365 'Incorrect answer for ' + s + ' -- got ' + result)
Florent Xicluna8f43cec2010-03-21 10:51:40 +0000366 self.assertItemsEqual(myexceptions, theirexceptions,
Facundo Batista353750c2007-09-13 18:13:15 +0000367 'Incorrect flags set in ' + s + ' -- got ' + str(myexceptions))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000368 return
369
370 def getexceptions(self):
Raymond Hettingerf63ba432004-08-17 05:42:09 +0000371 return [e for e in Signals if self.context.flags[e]]
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000372
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000373 def change_precision(self, prec):
374 self.context.prec = prec
375 def change_rounding_method(self, rounding):
376 self.context.rounding = rounding
377 def change_min_exponent(self, exp):
378 self.context.Emin = exp
379 def change_max_exponent(self, exp):
380 self.context.Emax = exp
381 def change_clamp(self, clamp):
382 self.context._clamp = clamp
383
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000384
385
386# The following classes test the behaviour of Decimal according to PEP 327
387
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000388class DecimalExplicitConstructionTest(unittest.TestCase):
389 '''Unit tests for Explicit Construction cases of Decimal.'''
390
391 def test_explicit_empty(self):
392 self.assertEqual(Decimal(), Decimal("0"))
393
394 def test_explicit_from_None(self):
395 self.assertRaises(TypeError, Decimal, None)
396
397 def test_explicit_from_int(self):
398
399 #positive
400 d = Decimal(45)
401 self.assertEqual(str(d), '45')
402
403 #very large positive
404 d = Decimal(500000123)
405 self.assertEqual(str(d), '500000123')
406
407 #negative
408 d = Decimal(-45)
409 self.assertEqual(str(d), '-45')
410
411 #zero
412 d = Decimal(0)
413 self.assertEqual(str(d), '0')
414
415 def test_explicit_from_string(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000416
417 #empty
418 self.assertEqual(str(Decimal('')), 'NaN')
419
420 #int
421 self.assertEqual(str(Decimal('45')), '45')
422
423 #float
424 self.assertEqual(str(Decimal('45.34')), '45.34')
425
426 #engineer notation
427 self.assertEqual(str(Decimal('45e2')), '4.5E+3')
428
429 #just not a number
430 self.assertEqual(str(Decimal('ugly')), 'NaN')
431
Mark Dickinson59bc20b2008-01-12 01:56:00 +0000432 #leading and trailing whitespace permitted
433 self.assertEqual(str(Decimal('1.3E4 \n')), '1.3E+4')
434 self.assertEqual(str(Decimal(' -7.89')), '-7.89')
435
Mark Dickinson8e85ffa2008-03-25 18:47:59 +0000436 #unicode strings should be permitted
437 self.assertEqual(str(Decimal(u'0E-017')), '0E-17')
438 self.assertEqual(str(Decimal(u'45')), '45')
439 self.assertEqual(str(Decimal(u'-Inf')), '-Infinity')
440 self.assertEqual(str(Decimal(u'NaN123')), 'NaN123')
441
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000442 def test_explicit_from_tuples(self):
443
444 #zero
445 d = Decimal( (0, (0,), 0) )
446 self.assertEqual(str(d), '0')
447
448 #int
449 d = Decimal( (1, (4, 5), 0) )
450 self.assertEqual(str(d), '-45')
451
452 #float
453 d = Decimal( (0, (4, 5, 3, 4), -2) )
454 self.assertEqual(str(d), '45.34')
455
456 #weird
457 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
458 self.assertEqual(str(d), '-4.34913534E-17')
459
460 #wrong number of items
461 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1)) )
462
463 #bad sign
464 self.assertRaises(ValueError, Decimal, (8, (4, 3, 4, 9, 1), 2) )
Facundo Batista9b5e2312007-10-19 19:25:57 +0000465 self.assertRaises(ValueError, Decimal, (0., (4, 3, 4, 9, 1), 2) )
466 self.assertRaises(ValueError, Decimal, (Decimal(1), (4, 3, 4, 9, 1), 2))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000467
468 #bad exp
469 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 'wrong!') )
Facundo Batista9b5e2312007-10-19 19:25:57 +0000470 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 0.) )
471 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), '1') )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000472
473 #bad coefficients
474 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, None, 1), 2) )
475 self.assertRaises(ValueError, Decimal, (1, (4, -3, 4, 9, 1), 2) )
Facundo Batista9b5e2312007-10-19 19:25:57 +0000476 self.assertRaises(ValueError, Decimal, (1, (4, 10, 4, 9, 1), 2) )
Facundo Batista72bc54f2007-11-23 17:59:00 +0000477 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 'a', 1), 2) )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000478
Antoine Pitrou6032c252010-03-30 18:49:45 +0000479 def test_explicit_from_bool(self):
480 self.assertIs(bool(Decimal(0)), False)
481 self.assertIs(bool(Decimal(1)), True)
482 self.assertEqual(Decimal(False), Decimal(0))
483 self.assertEqual(Decimal(True), Decimal(1))
484
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000485 def test_explicit_from_Decimal(self):
486
487 #positive
488 d = Decimal(45)
489 e = Decimal(d)
490 self.assertEqual(str(e), '45')
491 self.assertNotEqual(id(d), id(e))
492
493 #very large positive
494 d = Decimal(500000123)
495 e = Decimal(d)
496 self.assertEqual(str(e), '500000123')
497 self.assertNotEqual(id(d), id(e))
498
499 #negative
500 d = Decimal(-45)
501 e = Decimal(d)
502 self.assertEqual(str(e), '-45')
503 self.assertNotEqual(id(d), id(e))
504
505 #zero
506 d = Decimal(0)
507 e = Decimal(d)
508 self.assertEqual(str(e), '0')
509 self.assertNotEqual(id(d), id(e))
510
511 def test_explicit_context_create_decimal(self):
512
513 nc = copy.copy(getcontext())
514 nc.prec = 3
515
516 # empty
Raymond Hettingerfed52962004-07-14 15:41:57 +0000517 d = Decimal()
518 self.assertEqual(str(d), '0')
519 d = nc.create_decimal()
520 self.assertEqual(str(d), '0')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000521
522 # from None
523 self.assertRaises(TypeError, nc.create_decimal, None)
524
525 # from int
526 d = nc.create_decimal(456)
Ezio Melottib0f5adc2010-01-24 16:58:36 +0000527 self.assertIsInstance(d, Decimal)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000528 self.assertEqual(nc.create_decimal(45678),
529 nc.create_decimal('457E+2'))
530
531 # from string
532 d = Decimal('456789')
533 self.assertEqual(str(d), '456789')
534 d = nc.create_decimal('456789')
535 self.assertEqual(str(d), '4.57E+5')
Mark Dickinson59bc20b2008-01-12 01:56:00 +0000536 # leading and trailing whitespace should result in a NaN;
537 # spaces are already checked in Cowlishaw's test-suite, so
538 # here we just check that a trailing newline results in a NaN
539 self.assertEqual(str(nc.create_decimal('3.14\n')), 'NaN')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000540
541 # from tuples
542 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
543 self.assertEqual(str(d), '-4.34913534E-17')
544 d = nc.create_decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
545 self.assertEqual(str(d), '-4.35E-17')
546
547 # from Decimal
548 prevdec = Decimal(500000123)
549 d = Decimal(prevdec)
550 self.assertEqual(str(d), '500000123')
551 d = nc.create_decimal(prevdec)
552 self.assertEqual(str(d), '5.00E+8')
553
Mark Dickinson4326ad82009-08-02 10:59:36 +0000554 def test_unicode_digits(self):
555 test_values = {
556 u'\uff11': '1',
557 u'\u0660.\u0660\u0663\u0667\u0662e-\u0663' : '0.0000372',
558 u'-nan\u0c68\u0c6a\u0c66\u0c66' : '-NaN2400',
559 }
560 for input, expected in test_values.items():
561 self.assertEqual(str(Decimal(input)), expected)
562
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000563
564class DecimalImplicitConstructionTest(unittest.TestCase):
565 '''Unit tests for Implicit Construction cases of Decimal.'''
566
567 def test_implicit_from_None(self):
568 self.assertRaises(TypeError, eval, 'Decimal(5) + None', globals())
569
570 def test_implicit_from_int(self):
571 #normal
572 self.assertEqual(str(Decimal(5) + 45), '50')
573 #exceeding precision
574 self.assertEqual(Decimal(5) + 123456789000, Decimal(123456789000))
575
576 def test_implicit_from_string(self):
577 self.assertRaises(TypeError, eval, 'Decimal(5) + "3"', globals())
578
579 def test_implicit_from_float(self):
580 self.assertRaises(TypeError, eval, 'Decimal(5) + 2.2', globals())
581
582 def test_implicit_from_Decimal(self):
583 self.assertEqual(Decimal(5) + Decimal(45), Decimal(50))
584
Raymond Hettinger267b8682005-03-27 10:47:39 +0000585 def test_rop(self):
586 # Allow other classes to be trained to interact with Decimals
587 class E:
588 def __divmod__(self, other):
589 return 'divmod ' + str(other)
590 def __rdivmod__(self, other):
591 return str(other) + ' rdivmod'
592 def __lt__(self, other):
593 return 'lt ' + str(other)
594 def __gt__(self, other):
595 return 'gt ' + str(other)
596 def __le__(self, other):
597 return 'le ' + str(other)
598 def __ge__(self, other):
599 return 'ge ' + str(other)
600 def __eq__(self, other):
601 return 'eq ' + str(other)
602 def __ne__(self, other):
603 return 'ne ' + str(other)
604
605 self.assertEqual(divmod(E(), Decimal(10)), 'divmod 10')
606 self.assertEqual(divmod(Decimal(10), E()), '10 rdivmod')
607 self.assertEqual(eval('Decimal(10) < E()'), 'gt 10')
608 self.assertEqual(eval('Decimal(10) > E()'), 'lt 10')
609 self.assertEqual(eval('Decimal(10) <= E()'), 'ge 10')
610 self.assertEqual(eval('Decimal(10) >= E()'), 'le 10')
611 self.assertEqual(eval('Decimal(10) == E()'), 'eq 10')
612 self.assertEqual(eval('Decimal(10) != E()'), 'ne 10')
613
614 # insert operator methods and then exercise them
Georg Brandl96c3f7f2006-03-28 08:06:35 +0000615 oplist = [
616 ('+', '__add__', '__radd__'),
617 ('-', '__sub__', '__rsub__'),
618 ('*', '__mul__', '__rmul__'),
619 ('%', '__mod__', '__rmod__'),
620 ('//', '__floordiv__', '__rfloordiv__'),
621 ('**', '__pow__', '__rpow__')
622 ]
Florent Xicluna8f43cec2010-03-21 10:51:40 +0000623 with check_py3k_warnings():
624 if 1 / 2 == 0:
625 # testing with classic division, so add __div__
626 oplist.append(('/', '__div__', '__rdiv__'))
627 else:
628 # testing with -Qnew, so add __truediv__
629 oplist.append(('/', '__truediv__', '__rtruediv__'))
Anthony Baxter4ef3a232006-03-30 12:59:11 +0000630
Georg Brandl96c3f7f2006-03-28 08:06:35 +0000631 for sym, lop, rop in oplist:
Raymond Hettinger267b8682005-03-27 10:47:39 +0000632 setattr(E, lop, lambda self, other: 'str' + lop + str(other))
633 setattr(E, rop, lambda self, other: str(other) + rop + 'str')
634 self.assertEqual(eval('E()' + sym + 'Decimal(10)'),
635 'str' + lop + '10')
636 self.assertEqual(eval('Decimal(10)' + sym + 'E()'),
637 '10' + rop + 'str')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000638
Mark Dickinson277859d2009-03-17 23:03:46 +0000639
Mark Dickinson1ddf1d82008-02-29 02:16:37 +0000640class DecimalFormatTest(unittest.TestCase):
641 '''Unit tests for the format function.'''
642 def test_formatting(self):
643 # triples giving a format, a Decimal, and the expected result
644 test_values = [
645 ('e', '0E-15', '0e-15'),
646 ('e', '2.3E-15', '2.3e-15'),
647 ('e', '2.30E+2', '2.30e+2'), # preserve significant zeros
648 ('e', '2.30000E-15', '2.30000e-15'),
649 ('e', '1.23456789123456789e40', '1.23456789123456789e+40'),
650 ('e', '1.5', '1.5e+0'),
651 ('e', '0.15', '1.5e-1'),
652 ('e', '0.015', '1.5e-2'),
653 ('e', '0.0000000000015', '1.5e-12'),
654 ('e', '15.0', '1.50e+1'),
655 ('e', '-15', '-1.5e+1'),
656 ('e', '0', '0e+0'),
657 ('e', '0E1', '0e+1'),
658 ('e', '0.0', '0e-1'),
659 ('e', '0.00', '0e-2'),
660 ('.6e', '0E-15', '0.000000e-9'),
661 ('.6e', '0', '0.000000e+6'),
662 ('.6e', '9.999999', '9.999999e+0'),
663 ('.6e', '9.9999999', '1.000000e+1'),
664 ('.6e', '-1.23e5', '-1.230000e+5'),
665 ('.6e', '1.23456789e-3', '1.234568e-3'),
666 ('f', '0', '0'),
667 ('f', '0.0', '0.0'),
668 ('f', '0E-2', '0.00'),
669 ('f', '0.00E-8', '0.0000000000'),
670 ('f', '0E1', '0'), # loses exponent information
671 ('f', '3.2E1', '32'),
672 ('f', '3.2E2', '320'),
673 ('f', '3.20E2', '320'),
674 ('f', '3.200E2', '320.0'),
675 ('f', '3.2E-6', '0.0000032'),
676 ('.6f', '0E-15', '0.000000'), # all zeros treated equally
677 ('.6f', '0E1', '0.000000'),
678 ('.6f', '0', '0.000000'),
679 ('.0f', '0', '0'), # no decimal point
680 ('.0f', '0e-2', '0'),
681 ('.0f', '3.14159265', '3'),
682 ('.1f', '3.14159265', '3.1'),
683 ('.4f', '3.14159265', '3.1416'),
684 ('.6f', '3.14159265', '3.141593'),
685 ('.7f', '3.14159265', '3.1415926'), # round-half-even!
686 ('.8f', '3.14159265', '3.14159265'),
687 ('.9f', '3.14159265', '3.141592650'),
688
689 ('g', '0', '0'),
690 ('g', '0.0', '0.0'),
691 ('g', '0E1', '0e+1'),
692 ('G', '0E1', '0E+1'),
693 ('g', '0E-5', '0.00000'),
694 ('g', '0E-6', '0.000000'),
695 ('g', '0E-7', '0e-7'),
696 ('g', '-0E2', '-0e+2'),
697 ('.0g', '3.14159265', '3'), # 0 sig fig -> 1 sig fig
698 ('.1g', '3.14159265', '3'),
699 ('.2g', '3.14159265', '3.1'),
700 ('.5g', '3.14159265', '3.1416'),
701 ('.7g', '3.14159265', '3.141593'),
702 ('.8g', '3.14159265', '3.1415926'), # round-half-even!
703 ('.9g', '3.14159265', '3.14159265'),
704 ('.10g', '3.14159265', '3.14159265'), # don't pad
705
706 ('%', '0E1', '0%'),
707 ('%', '0E0', '0%'),
708 ('%', '0E-1', '0%'),
709 ('%', '0E-2', '0%'),
710 ('%', '0E-3', '0.0%'),
711 ('%', '0E-4', '0.00%'),
712
713 ('.3%', '0', '0.000%'), # all zeros treated equally
714 ('.3%', '0E10', '0.000%'),
715 ('.3%', '0E-10', '0.000%'),
716 ('.3%', '2.34', '234.000%'),
717 ('.3%', '1.234567', '123.457%'),
718 ('.0%', '1.23', '123%'),
719
720 ('e', 'NaN', 'NaN'),
721 ('f', '-NaN123', '-NaN123'),
722 ('+g', 'NaN456', '+NaN456'),
723 ('.3e', 'Inf', 'Infinity'),
724 ('.16f', '-Inf', '-Infinity'),
725 ('.0g', '-sNaN', '-sNaN'),
726
727 ('', '1.00', '1.00'),
Mark Dickinsonb065e522009-03-17 18:01:03 +0000728
Mark Dickinson277859d2009-03-17 23:03:46 +0000729 # test alignment and padding
Mark Dickinson5cfa8042009-09-08 20:20:19 +0000730 ('6', '123', ' 123'),
Mark Dickinsonb065e522009-03-17 18:01:03 +0000731 ('<6', '123', '123 '),
732 ('>6', '123', ' 123'),
733 ('^6', '123', ' 123 '),
734 ('=+6', '123', '+ 123'),
Mark Dickinson277859d2009-03-17 23:03:46 +0000735 ('#<10', 'NaN', 'NaN#######'),
736 ('#<10', '-4.3', '-4.3######'),
737 ('#<+10', '0.0130', '+0.0130###'),
738 ('#< 10', '0.0130', ' 0.0130###'),
739 ('@>10', '-Inf', '@-Infinity'),
740 ('#>5', '-Inf', '-Infinity'),
741 ('?^5', '123', '?123?'),
742 ('%^6', '123', '%123%%'),
743 (' ^6', '-45.6', '-45.6 '),
744 ('/=10', '-45.6', '-/////45.6'),
745 ('/=+10', '45.6', '+/////45.6'),
746 ('/= 10', '45.6', ' /////45.6'),
747
748 # thousands separator
749 (',', '1234567', '1,234,567'),
750 (',', '123456', '123,456'),
751 (',', '12345', '12,345'),
752 (',', '1234', '1,234'),
753 (',', '123', '123'),
754 (',', '12', '12'),
755 (',', '1', '1'),
756 (',', '0', '0'),
757 (',', '-1234567', '-1,234,567'),
758 (',', '-123456', '-123,456'),
759 ('7,', '123456', '123,456'),
Mark Dickinson5cfa8042009-09-08 20:20:19 +0000760 ('8,', '123456', ' 123,456'),
Mark Dickinson277859d2009-03-17 23:03:46 +0000761 ('08,', '123456', '0,123,456'), # special case: extra 0 needed
762 ('+08,', '123456', '+123,456'), # but not if there's a sign
763 (' 08,', '123456', ' 123,456'),
764 ('08,', '-123456', '-123,456'),
765 ('+09,', '123456', '+0,123,456'),
766 # ... with fractional part...
767 ('07,', '1234.56', '1,234.56'),
768 ('08,', '1234.56', '1,234.56'),
769 ('09,', '1234.56', '01,234.56'),
770 ('010,', '1234.56', '001,234.56'),
771 ('011,', '1234.56', '0,001,234.56'),
772 ('012,', '1234.56', '0,001,234.56'),
773 ('08,.1f', '1234.5', '01,234.5'),
774 # no thousands separators in fraction part
775 (',', '1.23456789', '1.23456789'),
776 (',%', '123.456789', '12,345.6789%'),
777 (',e', '123456', '1.23456e+5'),
778 (',E', '123456', '1.23456E+5'),
Mark Dickinson491ea552009-09-07 16:17:41 +0000779
780 # issue 6850
781 ('a=-7.0', '0.12345', 'aaaa0.1'),
Mark Dickinson1ddf1d82008-02-29 02:16:37 +0000782 ]
783 for fmt, d, result in test_values:
784 self.assertEqual(format(Decimal(d), fmt), result)
785
Mark Dickinson277859d2009-03-17 23:03:46 +0000786 def test_n_format(self):
787 try:
788 from locale import CHAR_MAX
789 except ImportError:
790 return
791
792 # Set up some localeconv-like dictionaries
793 en_US = {
794 'decimal_point' : '.',
795 'grouping' : [3, 3, 0],
796 'thousands_sep': ','
797 }
798
799 fr_FR = {
800 'decimal_point' : ',',
801 'grouping' : [CHAR_MAX],
802 'thousands_sep' : ''
803 }
804
805 ru_RU = {
806 'decimal_point' : ',',
807 'grouping' : [3, 3, 0],
808 'thousands_sep' : ' '
809 }
810
811 crazy = {
812 'decimal_point' : '&',
813 'grouping' : [1, 4, 2, CHAR_MAX],
814 'thousands_sep' : '-'
815 }
816
817
818 def get_fmt(x, locale, fmt='n'):
819 return Decimal.__format__(Decimal(x), fmt, _localeconv=locale)
820
821 self.assertEqual(get_fmt(Decimal('12.7'), en_US), '12.7')
822 self.assertEqual(get_fmt(Decimal('12.7'), fr_FR), '12,7')
823 self.assertEqual(get_fmt(Decimal('12.7'), ru_RU), '12,7')
824 self.assertEqual(get_fmt(Decimal('12.7'), crazy), '1-2&7')
825
826 self.assertEqual(get_fmt(123456789, en_US), '123,456,789')
827 self.assertEqual(get_fmt(123456789, fr_FR), '123456789')
828 self.assertEqual(get_fmt(123456789, ru_RU), '123 456 789')
829 self.assertEqual(get_fmt(1234567890123, crazy), '123456-78-9012-3')
830
831 self.assertEqual(get_fmt(123456789, en_US, '.6n'), '1.23457e+8')
832 self.assertEqual(get_fmt(123456789, fr_FR, '.6n'), '1,23457e+8')
833 self.assertEqual(get_fmt(123456789, ru_RU, '.6n'), '1,23457e+8')
834 self.assertEqual(get_fmt(123456789, crazy, '.6n'), '1&23457e+8')
835
Mark Dickinsonb14514a2009-03-18 08:22:51 +0000836 # zero padding
837 self.assertEqual(get_fmt(1234, fr_FR, '03n'), '1234')
838 self.assertEqual(get_fmt(1234, fr_FR, '04n'), '1234')
839 self.assertEqual(get_fmt(1234, fr_FR, '05n'), '01234')
840 self.assertEqual(get_fmt(1234, fr_FR, '06n'), '001234')
841
842 self.assertEqual(get_fmt(12345, en_US, '05n'), '12,345')
843 self.assertEqual(get_fmt(12345, en_US, '06n'), '12,345')
844 self.assertEqual(get_fmt(12345, en_US, '07n'), '012,345')
845 self.assertEqual(get_fmt(12345, en_US, '08n'), '0,012,345')
846 self.assertEqual(get_fmt(12345, en_US, '09n'), '0,012,345')
847 self.assertEqual(get_fmt(12345, en_US, '010n'), '00,012,345')
848
849 self.assertEqual(get_fmt(123456, crazy, '06n'), '1-2345-6')
850 self.assertEqual(get_fmt(123456, crazy, '07n'), '1-2345-6')
851 self.assertEqual(get_fmt(123456, crazy, '08n'), '1-2345-6')
852 self.assertEqual(get_fmt(123456, crazy, '09n'), '01-2345-6')
853 self.assertEqual(get_fmt(123456, crazy, '010n'), '0-01-2345-6')
854 self.assertEqual(get_fmt(123456, crazy, '011n'), '0-01-2345-6')
855 self.assertEqual(get_fmt(123456, crazy, '012n'), '00-01-2345-6')
856 self.assertEqual(get_fmt(123456, crazy, '013n'), '000-01-2345-6')
857
Mark Dickinson277859d2009-03-17 23:03:46 +0000858
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000859class DecimalArithmeticOperatorsTest(unittest.TestCase):
860 '''Unit tests for all arithmetic operators, binary and unary.'''
861
862 def test_addition(self):
863
864 d1 = Decimal('-11.1')
865 d2 = Decimal('22.2')
866
867 #two Decimals
868 self.assertEqual(d1+d2, Decimal('11.1'))
869 self.assertEqual(d2+d1, Decimal('11.1'))
870
871 #with other type, left
872 c = d1 + 5
873 self.assertEqual(c, Decimal('-6.1'))
874 self.assertEqual(type(c), type(d1))
875
876 #with other type, right
877 c = 5 + d1
878 self.assertEqual(c, Decimal('-6.1'))
879 self.assertEqual(type(c), type(d1))
880
881 #inline with decimal
882 d1 += d2
883 self.assertEqual(d1, Decimal('11.1'))
884
885 #inline with other type
886 d1 += 5
887 self.assertEqual(d1, Decimal('16.1'))
888
889 def test_subtraction(self):
890
891 d1 = Decimal('-11.1')
892 d2 = Decimal('22.2')
893
894 #two Decimals
895 self.assertEqual(d1-d2, Decimal('-33.3'))
896 self.assertEqual(d2-d1, Decimal('33.3'))
897
898 #with other type, left
899 c = d1 - 5
900 self.assertEqual(c, Decimal('-16.1'))
901 self.assertEqual(type(c), type(d1))
902
903 #with other type, right
904 c = 5 - d1
905 self.assertEqual(c, Decimal('16.1'))
906 self.assertEqual(type(c), type(d1))
907
908 #inline with decimal
909 d1 -= d2
910 self.assertEqual(d1, Decimal('-33.3'))
911
912 #inline with other type
913 d1 -= 5
914 self.assertEqual(d1, Decimal('-38.3'))
915
916 def test_multiplication(self):
917
918 d1 = Decimal('-5')
919 d2 = Decimal('3')
920
921 #two Decimals
922 self.assertEqual(d1*d2, Decimal('-15'))
923 self.assertEqual(d2*d1, Decimal('-15'))
924
925 #with other type, left
926 c = d1 * 5
927 self.assertEqual(c, Decimal('-25'))
928 self.assertEqual(type(c), type(d1))
929
930 #with other type, right
931 c = 5 * d1
932 self.assertEqual(c, Decimal('-25'))
933 self.assertEqual(type(c), type(d1))
934
935 #inline with decimal
936 d1 *= d2
937 self.assertEqual(d1, Decimal('-15'))
938
939 #inline with other type
940 d1 *= 5
941 self.assertEqual(d1, Decimal('-75'))
942
943 def test_division(self):
944
945 d1 = Decimal('-5')
946 d2 = Decimal('2')
947
948 #two Decimals
949 self.assertEqual(d1/d2, Decimal('-2.5'))
950 self.assertEqual(d2/d1, Decimal('-0.4'))
951
952 #with other type, left
953 c = d1 / 4
954 self.assertEqual(c, Decimal('-1.25'))
955 self.assertEqual(type(c), type(d1))
956
957 #with other type, right
958 c = 4 / d1
959 self.assertEqual(c, Decimal('-0.8'))
960 self.assertEqual(type(c), type(d1))
961
962 #inline with decimal
963 d1 /= d2
964 self.assertEqual(d1, Decimal('-2.5'))
965
966 #inline with other type
967 d1 /= 4
968 self.assertEqual(d1, Decimal('-0.625'))
969
970 def test_floor_division(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000971
972 d1 = Decimal('5')
973 d2 = Decimal('2')
974
975 #two Decimals
976 self.assertEqual(d1//d2, Decimal('2'))
977 self.assertEqual(d2//d1, Decimal('0'))
978
979 #with other type, left
980 c = d1 // 4
981 self.assertEqual(c, Decimal('1'))
982 self.assertEqual(type(c), type(d1))
983
984 #with other type, right
985 c = 7 // d1
986 self.assertEqual(c, Decimal('1'))
987 self.assertEqual(type(c), type(d1))
988
989 #inline with decimal
990 d1 //= d2
991 self.assertEqual(d1, Decimal('2'))
992
993 #inline with other type
994 d1 //= 2
995 self.assertEqual(d1, Decimal('1'))
996
997 def test_powering(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000998
999 d1 = Decimal('5')
1000 d2 = Decimal('2')
1001
1002 #two Decimals
1003 self.assertEqual(d1**d2, Decimal('25'))
1004 self.assertEqual(d2**d1, Decimal('32'))
1005
1006 #with other type, left
1007 c = d1 ** 4
1008 self.assertEqual(c, Decimal('625'))
1009 self.assertEqual(type(c), type(d1))
1010
1011 #with other type, right
1012 c = 7 ** d1
1013 self.assertEqual(c, Decimal('16807'))
1014 self.assertEqual(type(c), type(d1))
1015
1016 #inline with decimal
1017 d1 **= d2
1018 self.assertEqual(d1, Decimal('25'))
1019
1020 #inline with other type
1021 d1 **= 4
1022 self.assertEqual(d1, Decimal('390625'))
1023
1024 def test_module(self):
1025
1026 d1 = Decimal('5')
1027 d2 = Decimal('2')
1028
1029 #two Decimals
1030 self.assertEqual(d1%d2, Decimal('1'))
1031 self.assertEqual(d2%d1, Decimal('2'))
1032
1033 #with other type, left
1034 c = d1 % 4
1035 self.assertEqual(c, Decimal('1'))
1036 self.assertEqual(type(c), type(d1))
1037
1038 #with other type, right
1039 c = 7 % d1
1040 self.assertEqual(c, Decimal('2'))
1041 self.assertEqual(type(c), type(d1))
1042
1043 #inline with decimal
1044 d1 %= d2
1045 self.assertEqual(d1, Decimal('1'))
1046
1047 #inline with other type
1048 d1 %= 4
1049 self.assertEqual(d1, Decimal('1'))
1050
1051 def test_floor_div_module(self):
1052
1053 d1 = Decimal('5')
1054 d2 = Decimal('2')
1055
1056 #two Decimals
1057 (p, q) = divmod(d1, d2)
1058 self.assertEqual(p, Decimal('2'))
1059 self.assertEqual(q, Decimal('1'))
1060 self.assertEqual(type(p), type(d1))
1061 self.assertEqual(type(q), type(d1))
1062
1063 #with other type, left
1064 (p, q) = divmod(d1, 4)
1065 self.assertEqual(p, Decimal('1'))
1066 self.assertEqual(q, Decimal('1'))
1067 self.assertEqual(type(p), type(d1))
1068 self.assertEqual(type(q), type(d1))
1069
1070 #with other type, right
1071 (p, q) = divmod(7, d1)
1072 self.assertEqual(p, Decimal('1'))
1073 self.assertEqual(q, Decimal('2'))
1074 self.assertEqual(type(p), type(d1))
1075 self.assertEqual(type(q), type(d1))
1076
1077 def test_unary_operators(self):
1078 self.assertEqual(+Decimal(45), Decimal(+45)) # +
1079 self.assertEqual(-Decimal(45), Decimal(-45)) # -
1080 self.assertEqual(abs(Decimal(45)), abs(Decimal(-45))) # abs
1081
Mark Dickinson2fc92632008-02-06 22:10:50 +00001082 def test_nan_comparisons(self):
1083 n = Decimal('NaN')
1084 s = Decimal('sNaN')
1085 i = Decimal('Inf')
1086 f = Decimal('2')
1087 for x, y in [(n, n), (n, i), (i, n), (n, f), (f, n),
1088 (s, n), (n, s), (s, i), (i, s), (s, f), (f, s), (s, s)]:
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001089 self.assertTrue(x != y)
1090 self.assertTrue(not (x == y))
1091 self.assertTrue(not (x < y))
1092 self.assertTrue(not (x <= y))
1093 self.assertTrue(not (x > y))
1094 self.assertTrue(not (x >= y))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001095
Mark Dickinson6d8effb2010-02-18 14:27:02 +00001096 def test_copy_sign(self):
1097 d = Decimal(1).copy_sign(Decimal(-2))
1098
1099 self.assertEqual(Decimal(1).copy_sign(-2), d)
1100 self.assertRaises(TypeError, Decimal(1).copy_sign, '-2')
1101
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001102# The following are two functions used to test threading in the next class
1103
1104def thfunc1(cls):
1105 d1 = Decimal(1)
1106 d3 = Decimal(3)
Facundo Batista64156672008-03-22 02:45:37 +00001107 test1 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001108 cls.synchro.wait()
Facundo Batista64156672008-03-22 02:45:37 +00001109 test2 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001110 cls.finish1.set()
Facundo Batista64156672008-03-22 02:45:37 +00001111
Facundo Batistaee340e52008-05-02 17:39:00 +00001112 cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
1113 cls.assertEqual(test2, Decimal('0.3333333333333333333333333333'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001114 return
1115
1116def thfunc2(cls):
1117 d1 = Decimal(1)
1118 d3 = Decimal(3)
Facundo Batista64156672008-03-22 02:45:37 +00001119 test1 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001120 thiscontext = getcontext()
1121 thiscontext.prec = 18
Facundo Batista64156672008-03-22 02:45:37 +00001122 test2 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001123 cls.synchro.set()
1124 cls.finish2.set()
Facundo Batista64156672008-03-22 02:45:37 +00001125
Facundo Batistaee340e52008-05-02 17:39:00 +00001126 cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
Facundo Batista64156672008-03-22 02:45:37 +00001127 cls.assertEqual(test2, Decimal('0.333333333333333333'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001128 return
1129
1130
1131class DecimalUseOfContextTest(unittest.TestCase):
1132 '''Unit tests for Use of Context cases in Decimal.'''
1133
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001134 try:
1135 import threading
1136 except ImportError:
1137 threading = None
1138
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001139 # Take care executing this test from IDLE, there's an issue in threading
1140 # that hangs IDLE and I couldn't find it
1141
1142 def test_threading(self):
1143 #Test the "threading isolation" of a Context.
1144
1145 self.synchro = threading.Event()
1146 self.finish1 = threading.Event()
1147 self.finish2 = threading.Event()
1148
1149 th1 = threading.Thread(target=thfunc1, args=(self,))
1150 th2 = threading.Thread(target=thfunc2, args=(self,))
1151
1152 th1.start()
1153 th2.start()
1154
1155 self.finish1.wait()
Thomas Woutersb3e6e8c2007-09-19 17:27:29 +00001156 self.finish2.wait()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001157 return
1158
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001159 if threading is None:
1160 del test_threading
1161
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001162
1163class DecimalUsabilityTest(unittest.TestCase):
1164 '''Unit tests for Usability cases of Decimal.'''
1165
1166 def test_comparison_operators(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001167
1168 da = Decimal('23.42')
1169 db = Decimal('23.42')
1170 dc = Decimal('45')
1171
1172 #two Decimals
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001173 self.assertTrue(dc > da)
1174 self.assertTrue(dc >= da)
1175 self.assertTrue(da < dc)
1176 self.assertTrue(da <= dc)
1177 self.assertTrue(da == db)
1178 self.assertTrue(da != dc)
1179 self.assertTrue(da <= db)
1180 self.assertTrue(da >= db)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001181 self.assertEqual(cmp(dc,da), 1)
1182 self.assertEqual(cmp(da,dc), -1)
1183 self.assertEqual(cmp(da,db), 0)
1184
1185 #a Decimal and an int
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001186 self.assertTrue(dc > 23)
1187 self.assertTrue(23 < dc)
1188 self.assertTrue(dc == 45)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001189 self.assertEqual(cmp(dc,23), 1)
1190 self.assertEqual(cmp(23,dc), -1)
1191 self.assertEqual(cmp(dc,45), 0)
1192
1193 #a Decimal and uncomparable
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001194 self.assertNotEqual(da, 'ugly')
1195 self.assertNotEqual(da, 32.7)
1196 self.assertNotEqual(da, object())
1197 self.assertNotEqual(da, object)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001198
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001199 # sortable
1200 a = map(Decimal, xrange(100))
1201 b = a[:]
1202 random.shuffle(a)
1203 a.sort()
1204 self.assertEqual(a, b)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001205
Facundo Batista353750c2007-09-13 18:13:15 +00001206 # with None
Florent Xicluna8f43cec2010-03-21 10:51:40 +00001207 with check_py3k_warnings():
1208 self.assertFalse(Decimal(1) < None)
1209 self.assertTrue(Decimal(1) > None)
Facundo Batista353750c2007-09-13 18:13:15 +00001210
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001211 def test_copy_and_deepcopy_methods(self):
1212 d = Decimal('43.24')
1213 c = copy.copy(d)
1214 self.assertEqual(id(c), id(d))
1215 dc = copy.deepcopy(d)
1216 self.assertEqual(id(dc), id(d))
1217
1218 def test_hash_method(self):
1219 #just that it's hashable
1220 hash(Decimal(23))
Facundo Batista8c202442007-09-19 17:53:25 +00001221
1222 test_values = [Decimal(sign*(2**m + n))
1223 for m in [0, 14, 15, 16, 17, 30, 31,
1224 32, 33, 62, 63, 64, 65, 66]
1225 for n in range(-10, 10)
1226 for sign in [-1, 1]]
1227 test_values.extend([
1228 Decimal("-0"), # zeros
1229 Decimal("0.00"),
1230 Decimal("-0.000"),
1231 Decimal("0E10"),
1232 Decimal("-0E12"),
1233 Decimal("10.0"), # negative exponent
1234 Decimal("-23.00000"),
1235 Decimal("1230E100"), # positive exponent
1236 Decimal("-4.5678E50"),
1237 # a value for which hash(n) != hash(n % (2**64-1))
1238 # in Python pre-2.6
1239 Decimal(2**64 + 2**32 - 1),
1240 # selection of values which fail with the old (before
1241 # version 2.6) long.__hash__
1242 Decimal("1.634E100"),
1243 Decimal("90.697E100"),
1244 Decimal("188.83E100"),
1245 Decimal("1652.9E100"),
1246 Decimal("56531E100"),
1247 ])
1248
1249 # check that hash(d) == hash(int(d)) for integral values
1250 for value in test_values:
1251 self.assertEqual(hash(value), hash(int(value)))
1252
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001253 #the same hash that to an int
1254 self.assertEqual(hash(Decimal(23)), hash(23))
Raymond Hettingerbea3f6f2005-03-15 04:59:17 +00001255 self.assertRaises(TypeError, hash, Decimal('NaN'))
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001256 self.assertTrue(hash(Decimal('Inf')))
1257 self.assertTrue(hash(Decimal('-Inf')))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001258
Facundo Batista52b25792008-01-08 12:25:20 +00001259 # check that the value of the hash doesn't depend on the
1260 # current context (issue #1757)
1261 c = getcontext()
1262 old_precision = c.prec
1263 x = Decimal("123456789.1")
1264
1265 c.prec = 6
1266 h1 = hash(x)
1267 c.prec = 10
1268 h2 = hash(x)
1269 c.prec = 16
1270 h3 = hash(x)
1271
1272 self.assertEqual(h1, h2)
1273 self.assertEqual(h1, h3)
1274 c.prec = old_precision
1275
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001276 def test_min_and_max_methods(self):
1277
1278 d1 = Decimal('15.32')
1279 d2 = Decimal('28.5')
1280 l1 = 15
1281 l2 = 28
1282
1283 #between Decimals
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001284 self.assertTrue(min(d1,d2) is d1)
1285 self.assertTrue(min(d2,d1) is d1)
1286 self.assertTrue(max(d1,d2) is d2)
1287 self.assertTrue(max(d2,d1) is d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001288
1289 #between Decimal and long
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001290 self.assertTrue(min(d1,l2) is d1)
1291 self.assertTrue(min(l2,d1) is d1)
1292 self.assertTrue(max(l1,d2) is d2)
1293 self.assertTrue(max(d2,l1) is d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001294
1295 def test_as_nonzero(self):
1296 #as false
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001297 self.assertFalse(Decimal(0))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001298 #as true
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001299 self.assertTrue(Decimal('0.372'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001300
1301 def test_tostring_methods(self):
1302 #Test str and repr methods.
1303
1304 d = Decimal('15.32')
1305 self.assertEqual(str(d), '15.32') # str
Raymond Hettingerabe32372008-02-14 02:41:22 +00001306 self.assertEqual(repr(d), "Decimal('15.32')") # repr
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001307
Mark Dickinson8e85ffa2008-03-25 18:47:59 +00001308 # result type of string methods should be str, not unicode
1309 unicode_inputs = [u'123.4', u'0.5E2', u'Infinity', u'sNaN',
1310 u'-0.0E100', u'-NaN001', u'-Inf']
1311
1312 for u in unicode_inputs:
1313 d = Decimal(u)
1314 self.assertEqual(type(str(d)), str)
1315 self.assertEqual(type(repr(d)), str)
1316 self.assertEqual(type(d.to_eng_string()), str)
1317
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001318 def test_tonum_methods(self):
1319 #Test float, int and long methods.
1320
1321 d1 = Decimal('66')
1322 d2 = Decimal('15.32')
1323
1324 #int
1325 self.assertEqual(int(d1), 66)
1326 self.assertEqual(int(d2), 15)
1327
1328 #long
1329 self.assertEqual(long(d1), 66)
1330 self.assertEqual(long(d2), 15)
1331
1332 #float
1333 self.assertEqual(float(d1), 66)
1334 self.assertEqual(float(d2), 15.32)
1335
1336 def test_eval_round_trip(self):
1337
1338 #with zero
1339 d = Decimal( (0, (0,), 0) )
1340 self.assertEqual(d, eval(repr(d)))
1341
1342 #int
1343 d = Decimal( (1, (4, 5), 0) )
1344 self.assertEqual(d, eval(repr(d)))
1345
1346 #float
1347 d = Decimal( (0, (4, 5, 3, 4), -2) )
1348 self.assertEqual(d, eval(repr(d)))
1349
1350 #weird
1351 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1352 self.assertEqual(d, eval(repr(d)))
1353
1354 def test_as_tuple(self):
1355
1356 #with zero
1357 d = Decimal(0)
1358 self.assertEqual(d.as_tuple(), (0, (0,), 0) )
1359
1360 #int
1361 d = Decimal(-45)
1362 self.assertEqual(d.as_tuple(), (1, (4, 5), 0) )
1363
1364 #complicated string
1365 d = Decimal("-4.34913534E-17")
1366 self.assertEqual(d.as_tuple(), (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1367
1368 #inf
1369 d = Decimal("Infinity")
1370 self.assertEqual(d.as_tuple(), (0, (0,), 'F') )
1371
Facundo Batista9b5e2312007-10-19 19:25:57 +00001372 #leading zeros in coefficient should be stripped
1373 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), -2) )
1374 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), -2) )
1375 d = Decimal( (1, (0, 0, 0), 37) )
1376 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1377 d = Decimal( (1, (), 37) )
1378 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1379
1380 #leading zeros in NaN diagnostic info should be stripped
1381 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), 'n') )
1382 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), 'n') )
1383 d = Decimal( (1, (0, 0, 0), 'N') )
1384 self.assertEqual(d.as_tuple(), (1, (), 'N') )
1385 d = Decimal( (1, (), 'n') )
1386 self.assertEqual(d.as_tuple(), (1, (), 'n') )
1387
1388 #coefficient in infinity should be ignored
1389 d = Decimal( (0, (4, 5, 3, 4), 'F') )
1390 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
1391 d = Decimal( (1, (0, 2, 7, 1), 'F') )
1392 self.assertEqual(d.as_tuple(), (1, (0,), 'F'))
1393
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001394 def test_immutability_operations(self):
1395 # Do operations and check that it didn't change change internal objects.
1396
1397 d1 = Decimal('-25e55')
1398 b1 = Decimal('-25e55')
Facundo Batista353750c2007-09-13 18:13:15 +00001399 d2 = Decimal('33e+33')
1400 b2 = Decimal('33e+33')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001401
1402 def checkSameDec(operation, useOther=False):
1403 if useOther:
1404 eval("d1." + operation + "(d2)")
1405 self.assertEqual(d1._sign, b1._sign)
1406 self.assertEqual(d1._int, b1._int)
1407 self.assertEqual(d1._exp, b1._exp)
1408 self.assertEqual(d2._sign, b2._sign)
1409 self.assertEqual(d2._int, b2._int)
1410 self.assertEqual(d2._exp, b2._exp)
1411 else:
1412 eval("d1." + operation + "()")
1413 self.assertEqual(d1._sign, b1._sign)
1414 self.assertEqual(d1._int, b1._int)
1415 self.assertEqual(d1._exp, b1._exp)
1416 return
1417
1418 Decimal(d1)
1419 self.assertEqual(d1._sign, b1._sign)
1420 self.assertEqual(d1._int, b1._int)
1421 self.assertEqual(d1._exp, b1._exp)
1422
1423 checkSameDec("__abs__")
1424 checkSameDec("__add__", True)
1425 checkSameDec("__div__", True)
1426 checkSameDec("__divmod__", True)
Mark Dickinson2fc92632008-02-06 22:10:50 +00001427 checkSameDec("__eq__", True)
1428 checkSameDec("__ne__", True)
1429 checkSameDec("__le__", True)
1430 checkSameDec("__lt__", True)
1431 checkSameDec("__ge__", True)
1432 checkSameDec("__gt__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001433 checkSameDec("__float__")
1434 checkSameDec("__floordiv__", True)
1435 checkSameDec("__hash__")
1436 checkSameDec("__int__")
Raymond Hettinger5a053642008-01-24 19:05:29 +00001437 checkSameDec("__trunc__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001438 checkSameDec("__long__")
1439 checkSameDec("__mod__", True)
1440 checkSameDec("__mul__", True)
1441 checkSameDec("__neg__")
1442 checkSameDec("__nonzero__")
1443 checkSameDec("__pos__")
1444 checkSameDec("__pow__", True)
1445 checkSameDec("__radd__", True)
1446 checkSameDec("__rdiv__", True)
1447 checkSameDec("__rdivmod__", True)
1448 checkSameDec("__repr__")
1449 checkSameDec("__rfloordiv__", True)
1450 checkSameDec("__rmod__", True)
1451 checkSameDec("__rmul__", True)
1452 checkSameDec("__rpow__", True)
1453 checkSameDec("__rsub__", True)
1454 checkSameDec("__str__")
1455 checkSameDec("__sub__", True)
1456 checkSameDec("__truediv__", True)
1457 checkSameDec("adjusted")
1458 checkSameDec("as_tuple")
1459 checkSameDec("compare", True)
1460 checkSameDec("max", True)
1461 checkSameDec("min", True)
1462 checkSameDec("normalize")
1463 checkSameDec("quantize", True)
1464 checkSameDec("remainder_near", True)
1465 checkSameDec("same_quantum", True)
1466 checkSameDec("sqrt")
1467 checkSameDec("to_eng_string")
1468 checkSameDec("to_integral")
1469
Facundo Batista6c398da2007-09-17 17:30:13 +00001470 def test_subclassing(self):
1471 # Different behaviours when subclassing Decimal
1472
1473 class MyDecimal(Decimal):
1474 pass
1475
1476 d1 = MyDecimal(1)
1477 d2 = MyDecimal(2)
1478 d = d1 + d2
1479 self.assertTrue(type(d) is Decimal)
1480
1481 d = d1.max(d2)
1482 self.assertTrue(type(d) is Decimal)
1483
Mark Dickinson3b24ccb2008-03-25 14:33:23 +00001484 def test_implicit_context(self):
1485 # Check results when context given implicitly. (Issue 2478)
1486 c = getcontext()
1487 self.assertEqual(str(Decimal(0).sqrt()),
1488 str(c.sqrt(Decimal(0))))
1489
Mark Dickinson0c673122009-10-29 12:04:00 +00001490 def test_conversions_from_int(self):
1491 # Check that methods taking a second Decimal argument will
1492 # always accept an integer in place of a Decimal.
1493 self.assertEqual(Decimal(4).compare(3),
1494 Decimal(4).compare(Decimal(3)))
1495 self.assertEqual(Decimal(4).compare_signal(3),
1496 Decimal(4).compare_signal(Decimal(3)))
1497 self.assertEqual(Decimal(4).compare_total(3),
1498 Decimal(4).compare_total(Decimal(3)))
1499 self.assertEqual(Decimal(4).compare_total_mag(3),
1500 Decimal(4).compare_total_mag(Decimal(3)))
1501 self.assertEqual(Decimal(10101).logical_and(1001),
1502 Decimal(10101).logical_and(Decimal(1001)))
1503 self.assertEqual(Decimal(10101).logical_or(1001),
1504 Decimal(10101).logical_or(Decimal(1001)))
1505 self.assertEqual(Decimal(10101).logical_xor(1001),
1506 Decimal(10101).logical_xor(Decimal(1001)))
1507 self.assertEqual(Decimal(567).max(123),
1508 Decimal(567).max(Decimal(123)))
1509 self.assertEqual(Decimal(567).max_mag(123),
1510 Decimal(567).max_mag(Decimal(123)))
1511 self.assertEqual(Decimal(567).min(123),
1512 Decimal(567).min(Decimal(123)))
1513 self.assertEqual(Decimal(567).min_mag(123),
1514 Decimal(567).min_mag(Decimal(123)))
1515 self.assertEqual(Decimal(567).next_toward(123),
1516 Decimal(567).next_toward(Decimal(123)))
1517 self.assertEqual(Decimal(1234).quantize(100),
1518 Decimal(1234).quantize(Decimal(100)))
1519 self.assertEqual(Decimal(768).remainder_near(1234),
1520 Decimal(768).remainder_near(Decimal(1234)))
1521 self.assertEqual(Decimal(123).rotate(1),
1522 Decimal(123).rotate(Decimal(1)))
1523 self.assertEqual(Decimal(1234).same_quantum(1000),
1524 Decimal(1234).same_quantum(Decimal(1000)))
1525 self.assertEqual(Decimal('9.123').scaleb(-100),
1526 Decimal('9.123').scaleb(Decimal(-100)))
1527 self.assertEqual(Decimal(456).shift(-1),
1528 Decimal(456).shift(Decimal(-1)))
1529
1530 self.assertEqual(Decimal(-12).fma(Decimal(45), 67),
1531 Decimal(-12).fma(Decimal(45), Decimal(67)))
1532 self.assertEqual(Decimal(-12).fma(45, 67),
1533 Decimal(-12).fma(Decimal(45), Decimal(67)))
1534 self.assertEqual(Decimal(-12).fma(45, Decimal(67)),
1535 Decimal(-12).fma(Decimal(45), Decimal(67)))
1536
Facundo Batista6c398da2007-09-17 17:30:13 +00001537
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001538class DecimalPythonAPItests(unittest.TestCase):
1539
Raymond Hettinger2c8585b2009-02-03 03:37:03 +00001540 def test_abc(self):
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001541 self.assertTrue(issubclass(Decimal, numbers.Number))
1542 self.assertTrue(not issubclass(Decimal, numbers.Real))
Ezio Melottib0f5adc2010-01-24 16:58:36 +00001543 self.assertIsInstance(Decimal(0), numbers.Number)
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001544 self.assertTrue(not isinstance(Decimal(0), numbers.Real))
Raymond Hettinger2c8585b2009-02-03 03:37:03 +00001545
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001546 def test_pickle(self):
1547 d = Decimal('-3.141590000')
1548 p = pickle.dumps(d)
1549 e = pickle.loads(p)
1550 self.assertEqual(d, e)
1551
Raymond Hettinger5548be22004-07-05 18:49:38 +00001552 def test_int(self):
Raymond Hettinger605ed022004-11-24 07:28:48 +00001553 for x in range(-250, 250):
1554 s = '%0.2f' % (x / 100.0)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001555 # should work the same as for floats
1556 self.assertEqual(int(Decimal(s)), int(float(s)))
Raymond Hettinger605ed022004-11-24 07:28:48 +00001557 # should work the same as to_integral in the ROUND_DOWN mode
Raymond Hettinger5548be22004-07-05 18:49:38 +00001558 d = Decimal(s)
Raymond Hettinger605ed022004-11-24 07:28:48 +00001559 r = d.to_integral(ROUND_DOWN)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001560 self.assertEqual(Decimal(int(d)), r)
1561
Mark Dickinson968f1692009-09-07 18:04:58 +00001562 self.assertRaises(ValueError, int, Decimal('-nan'))
1563 self.assertRaises(ValueError, int, Decimal('snan'))
1564 self.assertRaises(OverflowError, int, Decimal('inf'))
1565 self.assertRaises(OverflowError, int, Decimal('-inf'))
1566
1567 self.assertRaises(ValueError, long, Decimal('-nan'))
1568 self.assertRaises(ValueError, long, Decimal('snan'))
1569 self.assertRaises(OverflowError, long, Decimal('inf'))
1570 self.assertRaises(OverflowError, long, Decimal('-inf'))
1571
Raymond Hettinger5a053642008-01-24 19:05:29 +00001572 def test_trunc(self):
1573 for x in range(-250, 250):
1574 s = '%0.2f' % (x / 100.0)
1575 # should work the same as for floats
1576 self.assertEqual(int(Decimal(s)), int(float(s)))
1577 # should work the same as to_integral in the ROUND_DOWN mode
1578 d = Decimal(s)
1579 r = d.to_integral(ROUND_DOWN)
Jeffrey Yasskinca2b69f2008-02-01 06:22:46 +00001580 self.assertEqual(Decimal(math.trunc(d)), r)
Raymond Hettinger5a053642008-01-24 19:05:29 +00001581
Raymond Hettingerf4d85972009-01-03 19:02:23 +00001582 def test_from_float(self):
1583
1584 class MyDecimal(Decimal):
1585 pass
1586
1587 r = MyDecimal.from_float(0.1)
1588 self.assertEqual(type(r), MyDecimal)
1589 self.assertEqual(str(r),
1590 '0.1000000000000000055511151231257827021181583404541015625')
1591 bigint = 12345678901234567890123456789
1592 self.assertEqual(MyDecimal.from_float(bigint), MyDecimal(bigint))
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001593 self.assertTrue(MyDecimal.from_float(float('nan')).is_qnan())
1594 self.assertTrue(MyDecimal.from_float(float('inf')).is_infinite())
1595 self.assertTrue(MyDecimal.from_float(float('-inf')).is_infinite())
Raymond Hettingerf4d85972009-01-03 19:02:23 +00001596 self.assertEqual(str(MyDecimal.from_float(float('nan'))),
1597 str(Decimal('NaN')))
1598 self.assertEqual(str(MyDecimal.from_float(float('inf'))),
1599 str(Decimal('Infinity')))
1600 self.assertEqual(str(MyDecimal.from_float(float('-inf'))),
1601 str(Decimal('-Infinity')))
1602 self.assertRaises(TypeError, MyDecimal.from_float, 'abc')
1603 for i in range(200):
1604 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
1605 self.assertEqual(x, float(MyDecimal.from_float(x))) # roundtrip
1606
1607 def test_create_decimal_from_float(self):
1608 context = Context(prec=5, rounding=ROUND_DOWN)
1609 self.assertEqual(
1610 context.create_decimal_from_float(math.pi),
1611 Decimal('3.1415')
1612 )
1613 context = Context(prec=5, rounding=ROUND_UP)
1614 self.assertEqual(
1615 context.create_decimal_from_float(math.pi),
1616 Decimal('3.1416')
1617 )
1618 context = Context(prec=5, traps=[Inexact])
1619 self.assertRaises(
1620 Inexact,
1621 context.create_decimal_from_float,
1622 math.pi
1623 )
1624 self.assertEqual(repr(context.create_decimal_from_float(-0.0)),
1625 "Decimal('-0')")
1626 self.assertEqual(repr(context.create_decimal_from_float(1.0)),
1627 "Decimal('1')")
1628 self.assertEqual(repr(context.create_decimal_from_float(10)),
1629 "Decimal('10')")
1630
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00001631class ContextAPItests(unittest.TestCase):
1632
1633 def test_pickle(self):
1634 c = Context()
1635 e = pickle.loads(pickle.dumps(c))
1636 for k in vars(c):
1637 v1 = vars(c)[k]
1638 v2 = vars(e)[k]
1639 self.assertEqual(v1, v2)
1640
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001641 def test_equality_with_other_types(self):
Ezio Melottiaa980582010-01-23 23:04:36 +00001642 self.assertIn(Decimal(10), ['a', 1.0, Decimal(10), (1,2), {}])
1643 self.assertNotIn(Decimal(10), ['a', 1.0, (1,2), {}])
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001644
Raymond Hettinger955d2b22004-08-08 20:17:45 +00001645 def test_copy(self):
1646 # All copies should be deep
1647 c = Context()
1648 d = c.copy()
1649 self.assertNotEqual(id(c), id(d))
1650 self.assertNotEqual(id(c.flags), id(d.flags))
1651 self.assertNotEqual(id(c.traps), id(d.traps))
1652
Mark Dickinson6d8effb2010-02-18 14:27:02 +00001653 def test_abs(self):
1654 c = Context()
1655 d = c.abs(Decimal(-1))
1656 self.assertEqual(c.abs(-1), d)
1657 self.assertRaises(TypeError, c.abs, '-1')
1658
1659 def test_add(self):
1660 c = Context()
1661 d = c.add(Decimal(1), Decimal(1))
1662 self.assertEqual(c.add(1, 1), d)
1663 self.assertEqual(c.add(Decimal(1), 1), d)
1664 self.assertEqual(c.add(1, Decimal(1)), d)
1665 self.assertRaises(TypeError, c.add, '1', 1)
1666 self.assertRaises(TypeError, c.add, 1, '1')
1667
1668 def test_compare(self):
1669 c = Context()
1670 d = c.compare(Decimal(1), Decimal(1))
1671 self.assertEqual(c.compare(1, 1), d)
1672 self.assertEqual(c.compare(Decimal(1), 1), d)
1673 self.assertEqual(c.compare(1, Decimal(1)), d)
1674 self.assertRaises(TypeError, c.compare, '1', 1)
1675 self.assertRaises(TypeError, c.compare, 1, '1')
1676
1677 def test_compare_signal(self):
1678 c = Context()
1679 d = c.compare_signal(Decimal(1), Decimal(1))
1680 self.assertEqual(c.compare_signal(1, 1), d)
1681 self.assertEqual(c.compare_signal(Decimal(1), 1), d)
1682 self.assertEqual(c.compare_signal(1, Decimal(1)), d)
1683 self.assertRaises(TypeError, c.compare_signal, '1', 1)
1684 self.assertRaises(TypeError, c.compare_signal, 1, '1')
1685
1686 def test_compare_total(self):
1687 c = Context()
1688 d = c.compare_total(Decimal(1), Decimal(1))
1689 self.assertEqual(c.compare_total(1, 1), d)
1690 self.assertEqual(c.compare_total(Decimal(1), 1), d)
1691 self.assertEqual(c.compare_total(1, Decimal(1)), d)
1692 self.assertRaises(TypeError, c.compare_total, '1', 1)
1693 self.assertRaises(TypeError, c.compare_total, 1, '1')
1694
1695 def test_compare_total_mag(self):
1696 c = Context()
1697 d = c.compare_total_mag(Decimal(1), Decimal(1))
1698 self.assertEqual(c.compare_total_mag(1, 1), d)
1699 self.assertEqual(c.compare_total_mag(Decimal(1), 1), d)
1700 self.assertEqual(c.compare_total_mag(1, Decimal(1)), d)
1701 self.assertRaises(TypeError, c.compare_total_mag, '1', 1)
1702 self.assertRaises(TypeError, c.compare_total_mag, 1, '1')
1703
1704 def test_copy_abs(self):
1705 c = Context()
1706 d = c.copy_abs(Decimal(-1))
1707 self.assertEqual(c.copy_abs(-1), d)
1708 self.assertRaises(TypeError, c.copy_abs, '-1')
1709
1710 def test_copy_decimal(self):
1711 c = Context()
1712 d = c.copy_decimal(Decimal(-1))
1713 self.assertEqual(c.copy_decimal(-1), d)
1714 self.assertRaises(TypeError, c.copy_decimal, '-1')
1715
1716 def test_copy_negate(self):
1717 c = Context()
1718 d = c.copy_negate(Decimal(-1))
1719 self.assertEqual(c.copy_negate(-1), d)
1720 self.assertRaises(TypeError, c.copy_negate, '-1')
1721
1722 def test_copy_sign(self):
1723 c = Context()
1724 d = c.copy_sign(Decimal(1), Decimal(-2))
1725 self.assertEqual(c.copy_sign(1, -2), d)
1726 self.assertEqual(c.copy_sign(Decimal(1), -2), d)
1727 self.assertEqual(c.copy_sign(1, Decimal(-2)), d)
1728 self.assertRaises(TypeError, c.copy_sign, '1', -2)
1729 self.assertRaises(TypeError, c.copy_sign, 1, '-2')
1730
1731 def test_divide(self):
1732 c = Context()
1733 d = c.divide(Decimal(1), Decimal(2))
1734 self.assertEqual(c.divide(1, 2), d)
1735 self.assertEqual(c.divide(Decimal(1), 2), d)
1736 self.assertEqual(c.divide(1, Decimal(2)), d)
1737 self.assertRaises(TypeError, c.divide, '1', 2)
1738 self.assertRaises(TypeError, c.divide, 1, '2')
1739
1740 def test_divide_int(self):
1741 c = Context()
1742 d = c.divide_int(Decimal(1), Decimal(2))
1743 self.assertEqual(c.divide_int(1, 2), d)
1744 self.assertEqual(c.divide_int(Decimal(1), 2), d)
1745 self.assertEqual(c.divide_int(1, Decimal(2)), d)
1746 self.assertRaises(TypeError, c.divide_int, '1', 2)
1747 self.assertRaises(TypeError, c.divide_int, 1, '2')
1748
1749 def test_divmod(self):
1750 c = Context()
1751 d = c.divmod(Decimal(1), Decimal(2))
1752 self.assertEqual(c.divmod(1, 2), d)
1753 self.assertEqual(c.divmod(Decimal(1), 2), d)
1754 self.assertEqual(c.divmod(1, Decimal(2)), d)
1755 self.assertRaises(TypeError, c.divmod, '1', 2)
1756 self.assertRaises(TypeError, c.divmod, 1, '2')
1757
1758 def test_exp(self):
1759 c = Context()
1760 d = c.exp(Decimal(10))
1761 self.assertEqual(c.exp(10), d)
1762 self.assertRaises(TypeError, c.exp, '10')
1763
1764 def test_fma(self):
1765 c = Context()
1766 d = c.fma(Decimal(2), Decimal(3), Decimal(4))
1767 self.assertEqual(c.fma(2, 3, 4), d)
1768 self.assertEqual(c.fma(Decimal(2), 3, 4), d)
1769 self.assertEqual(c.fma(2, Decimal(3), 4), d)
1770 self.assertEqual(c.fma(2, 3, Decimal(4)), d)
1771 self.assertEqual(c.fma(Decimal(2), Decimal(3), 4), d)
1772 self.assertRaises(TypeError, c.fma, '2', 3, 4)
1773 self.assertRaises(TypeError, c.fma, 2, '3', 4)
1774 self.assertRaises(TypeError, c.fma, 2, 3, '4')
1775
1776 def test_is_finite(self):
1777 c = Context()
1778 d = c.is_finite(Decimal(10))
1779 self.assertEqual(c.is_finite(10), d)
1780 self.assertRaises(TypeError, c.is_finite, '10')
1781
1782 def test_is_infinite(self):
1783 c = Context()
1784 d = c.is_infinite(Decimal(10))
1785 self.assertEqual(c.is_infinite(10), d)
1786 self.assertRaises(TypeError, c.is_infinite, '10')
1787
1788 def test_is_nan(self):
1789 c = Context()
1790 d = c.is_nan(Decimal(10))
1791 self.assertEqual(c.is_nan(10), d)
1792 self.assertRaises(TypeError, c.is_nan, '10')
1793
1794 def test_is_normal(self):
1795 c = Context()
1796 d = c.is_normal(Decimal(10))
1797 self.assertEqual(c.is_normal(10), d)
1798 self.assertRaises(TypeError, c.is_normal, '10')
1799
1800 def test_is_qnan(self):
1801 c = Context()
1802 d = c.is_qnan(Decimal(10))
1803 self.assertEqual(c.is_qnan(10), d)
1804 self.assertRaises(TypeError, c.is_qnan, '10')
1805
1806 def test_is_signed(self):
1807 c = Context()
1808 d = c.is_signed(Decimal(10))
1809 self.assertEqual(c.is_signed(10), d)
1810 self.assertRaises(TypeError, c.is_signed, '10')
1811
1812 def test_is_snan(self):
1813 c = Context()
1814 d = c.is_snan(Decimal(10))
1815 self.assertEqual(c.is_snan(10), d)
1816 self.assertRaises(TypeError, c.is_snan, '10')
1817
1818 def test_is_subnormal(self):
1819 c = Context()
1820 d = c.is_subnormal(Decimal(10))
1821 self.assertEqual(c.is_subnormal(10), d)
1822 self.assertRaises(TypeError, c.is_subnormal, '10')
1823
1824 def test_is_zero(self):
1825 c = Context()
1826 d = c.is_zero(Decimal(10))
1827 self.assertEqual(c.is_zero(10), d)
1828 self.assertRaises(TypeError, c.is_zero, '10')
1829
1830 def test_ln(self):
1831 c = Context()
1832 d = c.ln(Decimal(10))
1833 self.assertEqual(c.ln(10), d)
1834 self.assertRaises(TypeError, c.ln, '10')
1835
1836 def test_log10(self):
1837 c = Context()
1838 d = c.log10(Decimal(10))
1839 self.assertEqual(c.log10(10), d)
1840 self.assertRaises(TypeError, c.log10, '10')
1841
1842 def test_logb(self):
1843 c = Context()
1844 d = c.logb(Decimal(10))
1845 self.assertEqual(c.logb(10), d)
1846 self.assertRaises(TypeError, c.logb, '10')
1847
1848 def test_logical_and(self):
1849 c = Context()
1850 d = c.logical_and(Decimal(1), Decimal(1))
1851 self.assertEqual(c.logical_and(1, 1), d)
1852 self.assertEqual(c.logical_and(Decimal(1), 1), d)
1853 self.assertEqual(c.logical_and(1, Decimal(1)), d)
1854 self.assertRaises(TypeError, c.logical_and, '1', 1)
1855 self.assertRaises(TypeError, c.logical_and, 1, '1')
1856
1857 def test_logical_invert(self):
1858 c = Context()
1859 d = c.logical_invert(Decimal(1000))
1860 self.assertEqual(c.logical_invert(1000), d)
1861 self.assertRaises(TypeError, c.logical_invert, '1000')
1862
1863 def test_logical_or(self):
1864 c = Context()
1865 d = c.logical_or(Decimal(1), Decimal(1))
1866 self.assertEqual(c.logical_or(1, 1), d)
1867 self.assertEqual(c.logical_or(Decimal(1), 1), d)
1868 self.assertEqual(c.logical_or(1, Decimal(1)), d)
1869 self.assertRaises(TypeError, c.logical_or, '1', 1)
1870 self.assertRaises(TypeError, c.logical_or, 1, '1')
1871
1872 def test_logical_xor(self):
1873 c = Context()
1874 d = c.logical_xor(Decimal(1), Decimal(1))
1875 self.assertEqual(c.logical_xor(1, 1), d)
1876 self.assertEqual(c.logical_xor(Decimal(1), 1), d)
1877 self.assertEqual(c.logical_xor(1, Decimal(1)), d)
1878 self.assertRaises(TypeError, c.logical_xor, '1', 1)
1879 self.assertRaises(TypeError, c.logical_xor, 1, '1')
1880
1881 def test_max(self):
1882 c = Context()
1883 d = c.max(Decimal(1), Decimal(2))
1884 self.assertEqual(c.max(1, 2), d)
1885 self.assertEqual(c.max(Decimal(1), 2), d)
1886 self.assertEqual(c.max(1, Decimal(2)), d)
1887 self.assertRaises(TypeError, c.max, '1', 2)
1888 self.assertRaises(TypeError, c.max, 1, '2')
1889
1890 def test_max_mag(self):
1891 c = Context()
1892 d = c.max_mag(Decimal(1), Decimal(2))
1893 self.assertEqual(c.max_mag(1, 2), d)
1894 self.assertEqual(c.max_mag(Decimal(1), 2), d)
1895 self.assertEqual(c.max_mag(1, Decimal(2)), d)
1896 self.assertRaises(TypeError, c.max_mag, '1', 2)
1897 self.assertRaises(TypeError, c.max_mag, 1, '2')
1898
1899 def test_min(self):
1900 c = Context()
1901 d = c.min(Decimal(1), Decimal(2))
1902 self.assertEqual(c.min(1, 2), d)
1903 self.assertEqual(c.min(Decimal(1), 2), d)
1904 self.assertEqual(c.min(1, Decimal(2)), d)
1905 self.assertRaises(TypeError, c.min, '1', 2)
1906 self.assertRaises(TypeError, c.min, 1, '2')
1907
1908 def test_min_mag(self):
1909 c = Context()
1910 d = c.min_mag(Decimal(1), Decimal(2))
1911 self.assertEqual(c.min_mag(1, 2), d)
1912 self.assertEqual(c.min_mag(Decimal(1), 2), d)
1913 self.assertEqual(c.min_mag(1, Decimal(2)), d)
1914 self.assertRaises(TypeError, c.min_mag, '1', 2)
1915 self.assertRaises(TypeError, c.min_mag, 1, '2')
1916
1917 def test_minus(self):
1918 c = Context()
1919 d = c.minus(Decimal(10))
1920 self.assertEqual(c.minus(10), d)
1921 self.assertRaises(TypeError, c.minus, '10')
1922
1923 def test_multiply(self):
1924 c = Context()
1925 d = c.multiply(Decimal(1), Decimal(2))
1926 self.assertEqual(c.multiply(1, 2), d)
1927 self.assertEqual(c.multiply(Decimal(1), 2), d)
1928 self.assertEqual(c.multiply(1, Decimal(2)), d)
1929 self.assertRaises(TypeError, c.multiply, '1', 2)
1930 self.assertRaises(TypeError, c.multiply, 1, '2')
1931
1932 def test_next_minus(self):
1933 c = Context()
1934 d = c.next_minus(Decimal(10))
1935 self.assertEqual(c.next_minus(10), d)
1936 self.assertRaises(TypeError, c.next_minus, '10')
1937
1938 def test_next_plus(self):
1939 c = Context()
1940 d = c.next_plus(Decimal(10))
1941 self.assertEqual(c.next_plus(10), d)
1942 self.assertRaises(TypeError, c.next_plus, '10')
1943
1944 def test_next_toward(self):
1945 c = Context()
1946 d = c.next_toward(Decimal(1), Decimal(2))
1947 self.assertEqual(c.next_toward(1, 2), d)
1948 self.assertEqual(c.next_toward(Decimal(1), 2), d)
1949 self.assertEqual(c.next_toward(1, Decimal(2)), d)
1950 self.assertRaises(TypeError, c.next_toward, '1', 2)
1951 self.assertRaises(TypeError, c.next_toward, 1, '2')
1952
1953 def test_normalize(self):
1954 c = Context()
1955 d = c.normalize(Decimal(10))
1956 self.assertEqual(c.normalize(10), d)
1957 self.assertRaises(TypeError, c.normalize, '10')
1958
1959 def test_number_class(self):
1960 c = Context()
1961 self.assertEqual(c.number_class(123), c.number_class(Decimal(123)))
1962 self.assertEqual(c.number_class(0), c.number_class(Decimal(0)))
1963 self.assertEqual(c.number_class(-45), c.number_class(Decimal(-45)))
1964
1965 def test_power(self):
1966 c = Context()
1967 d = c.power(Decimal(1), Decimal(4), Decimal(2))
1968 self.assertEqual(c.power(1, 4, 2), d)
1969 self.assertEqual(c.power(Decimal(1), 4, 2), d)
1970 self.assertEqual(c.power(1, Decimal(4), 2), d)
1971 self.assertEqual(c.power(1, 4, Decimal(2)), d)
1972 self.assertEqual(c.power(Decimal(1), Decimal(4), 2), d)
1973 self.assertRaises(TypeError, c.power, '1', 4, 2)
1974 self.assertRaises(TypeError, c.power, 1, '4', 2)
1975 self.assertRaises(TypeError, c.power, 1, 4, '2')
1976
1977 def test_plus(self):
1978 c = Context()
1979 d = c.plus(Decimal(10))
1980 self.assertEqual(c.plus(10), d)
1981 self.assertRaises(TypeError, c.plus, '10')
1982
1983 def test_quantize(self):
1984 c = Context()
1985 d = c.quantize(Decimal(1), Decimal(2))
1986 self.assertEqual(c.quantize(1, 2), d)
1987 self.assertEqual(c.quantize(Decimal(1), 2), d)
1988 self.assertEqual(c.quantize(1, Decimal(2)), d)
1989 self.assertRaises(TypeError, c.quantize, '1', 2)
1990 self.assertRaises(TypeError, c.quantize, 1, '2')
1991
1992 def test_remainder(self):
1993 c = Context()
1994 d = c.remainder(Decimal(1), Decimal(2))
1995 self.assertEqual(c.remainder(1, 2), d)
1996 self.assertEqual(c.remainder(Decimal(1), 2), d)
1997 self.assertEqual(c.remainder(1, Decimal(2)), d)
1998 self.assertRaises(TypeError, c.remainder, '1', 2)
1999 self.assertRaises(TypeError, c.remainder, 1, '2')
2000
2001 def test_remainder_near(self):
2002 c = Context()
2003 d = c.remainder_near(Decimal(1), Decimal(2))
2004 self.assertEqual(c.remainder_near(1, 2), d)
2005 self.assertEqual(c.remainder_near(Decimal(1), 2), d)
2006 self.assertEqual(c.remainder_near(1, Decimal(2)), d)
2007 self.assertRaises(TypeError, c.remainder_near, '1', 2)
2008 self.assertRaises(TypeError, c.remainder_near, 1, '2')
2009
2010 def test_rotate(self):
2011 c = Context()
2012 d = c.rotate(Decimal(1), Decimal(2))
2013 self.assertEqual(c.rotate(1, 2), d)
2014 self.assertEqual(c.rotate(Decimal(1), 2), d)
2015 self.assertEqual(c.rotate(1, Decimal(2)), d)
2016 self.assertRaises(TypeError, c.rotate, '1', 2)
2017 self.assertRaises(TypeError, c.rotate, 1, '2')
2018
2019 def test_sqrt(self):
2020 c = Context()
2021 d = c.sqrt(Decimal(10))
2022 self.assertEqual(c.sqrt(10), d)
2023 self.assertRaises(TypeError, c.sqrt, '10')
2024
2025 def test_same_quantum(self):
2026 c = Context()
2027 d = c.same_quantum(Decimal(1), Decimal(2))
2028 self.assertEqual(c.same_quantum(1, 2), d)
2029 self.assertEqual(c.same_quantum(Decimal(1), 2), d)
2030 self.assertEqual(c.same_quantum(1, Decimal(2)), d)
2031 self.assertRaises(TypeError, c.same_quantum, '1', 2)
2032 self.assertRaises(TypeError, c.same_quantum, 1, '2')
2033
2034 def test_scaleb(self):
2035 c = Context()
2036 d = c.scaleb(Decimal(1), Decimal(2))
2037 self.assertEqual(c.scaleb(1, 2), d)
2038 self.assertEqual(c.scaleb(Decimal(1), 2), d)
2039 self.assertEqual(c.scaleb(1, Decimal(2)), d)
2040 self.assertRaises(TypeError, c.scaleb, '1', 2)
2041 self.assertRaises(TypeError, c.scaleb, 1, '2')
2042
2043 def test_shift(self):
2044 c = Context()
2045 d = c.shift(Decimal(1), Decimal(2))
2046 self.assertEqual(c.shift(1, 2), d)
2047 self.assertEqual(c.shift(Decimal(1), 2), d)
2048 self.assertEqual(c.shift(1, Decimal(2)), d)
2049 self.assertRaises(TypeError, c.shift, '1', 2)
2050 self.assertRaises(TypeError, c.shift, 1, '2')
2051
2052 def test_subtract(self):
2053 c = Context()
2054 d = c.subtract(Decimal(1), Decimal(2))
2055 self.assertEqual(c.subtract(1, 2), d)
2056 self.assertEqual(c.subtract(Decimal(1), 2), d)
2057 self.assertEqual(c.subtract(1, Decimal(2)), d)
2058 self.assertRaises(TypeError, c.subtract, '1', 2)
2059 self.assertRaises(TypeError, c.subtract, 1, '2')
2060
2061 def test_to_eng_string(self):
2062 c = Context()
2063 d = c.to_eng_string(Decimal(10))
2064 self.assertEqual(c.to_eng_string(10), d)
2065 self.assertRaises(TypeError, c.to_eng_string, '10')
2066
2067 def test_to_sci_string(self):
2068 c = Context()
2069 d = c.to_sci_string(Decimal(10))
2070 self.assertEqual(c.to_sci_string(10), d)
2071 self.assertRaises(TypeError, c.to_sci_string, '10')
2072
2073 def test_to_integral_exact(self):
2074 c = Context()
2075 d = c.to_integral_exact(Decimal(10))
2076 self.assertEqual(c.to_integral_exact(10), d)
2077 self.assertRaises(TypeError, c.to_integral_exact, '10')
2078
2079 def test_to_integral_value(self):
2080 c = Context()
2081 d = c.to_integral_value(Decimal(10))
2082 self.assertEqual(c.to_integral_value(10), d)
2083 self.assertRaises(TypeError, c.to_integral_value, '10')
2084
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002085class WithStatementTest(unittest.TestCase):
2086 # Can't do these as docstrings until Python 2.6
2087 # as doctest can't handle __future__ statements
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002088
2089 def test_localcontext(self):
Nick Coghlanced12182006-09-02 03:54:17 +00002090 # Use a copy of the current context in the block
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002091 orig_ctx = getcontext()
2092 with localcontext() as enter_ctx:
2093 set_ctx = getcontext()
2094 final_ctx = getcontext()
Benjamin Peterson5c8da862009-06-30 22:57:08 +00002095 self.assertTrue(orig_ctx is final_ctx, 'did not restore context correctly')
2096 self.assertTrue(orig_ctx is not set_ctx, 'did not copy the context')
2097 self.assertTrue(set_ctx is enter_ctx, '__enter__ returned wrong context')
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002098
2099 def test_localcontextarg(self):
Nick Coghlanced12182006-09-02 03:54:17 +00002100 # Use a copy of the supplied context in the block
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002101 orig_ctx = getcontext()
2102 new_ctx = Context(prec=42)
2103 with localcontext(new_ctx) as enter_ctx:
2104 set_ctx = getcontext()
2105 final_ctx = getcontext()
Benjamin Peterson5c8da862009-06-30 22:57:08 +00002106 self.assertTrue(orig_ctx is final_ctx, 'did not restore context correctly')
2107 self.assertTrue(set_ctx.prec == new_ctx.prec, 'did not set correct context')
2108 self.assertTrue(new_ctx is not set_ctx, 'did not copy the context')
2109 self.assertTrue(set_ctx is enter_ctx, '__enter__ returned wrong context')
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002110
Facundo Batista353750c2007-09-13 18:13:15 +00002111class ContextFlags(unittest.TestCase):
2112 def test_flags_irrelevant(self):
2113 # check that the result (numeric result + flags raised) of an
2114 # arithmetic operation doesn't depend on the current flags
2115
2116 context = Context(prec=9, Emin = -999999999, Emax = 999999999,
2117 rounding=ROUND_HALF_EVEN, traps=[], flags=[])
2118
2119 # operations that raise various flags, in the form (function, arglist)
2120 operations = [
2121 (context._apply, [Decimal("100E-1000000009")]),
2122 (context.sqrt, [Decimal(2)]),
2123 (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]),
2124 (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]),
2125 (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]),
2126 ]
2127
2128 # try various flags individually, then a whole lot at once
2129 flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal],
2130 [Inexact, Rounded, Underflow, Clamped, Subnormal]]
2131
2132 for fn, args in operations:
2133 # find answer and flags raised using a clean context
2134 context.clear_flags()
2135 ans = fn(*args)
2136 flags = [k for k, v in context.flags.items() if v]
2137
2138 for extra_flags in flagsets:
2139 # set flags, before calling operation
2140 context.clear_flags()
2141 for flag in extra_flags:
2142 context._raise_error(flag)
2143 new_ans = fn(*args)
2144
2145 # flags that we expect to be set after the operation
2146 expected_flags = list(flags)
2147 for flag in extra_flags:
2148 if flag not in expected_flags:
2149 expected_flags.append(flag)
Facundo Batista353750c2007-09-13 18:13:15 +00002150
2151 # flags we actually got
2152 new_flags = [k for k,v in context.flags.items() if v]
Facundo Batista353750c2007-09-13 18:13:15 +00002153
2154 self.assertEqual(ans, new_ans,
2155 "operation produces different answers depending on flags set: " +
2156 "expected %s, got %s." % (ans, new_ans))
Florent Xicluna8f43cec2010-03-21 10:51:40 +00002157 self.assertItemsEqual(new_flags, expected_flags,
Facundo Batista353750c2007-09-13 18:13:15 +00002158 "operation raises different flags depending on flags set: " +
2159 "expected %s, got %s" % (expected_flags, new_flags))
2160
2161def test_main(arith=False, verbose=None, todo_tests=None, debug=None):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002162 """ Execute the tests.
2163
Raymond Hettingered20ad82004-09-04 20:09:13 +00002164 Runs all arithmetic tests if arith is True or if the "decimal" resource
2165 is enabled in regrtest.py
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002166 """
Raymond Hettingered20ad82004-09-04 20:09:13 +00002167
Neal Norwitzce4a9c92006-04-09 08:36:46 +00002168 init()
Facundo Batista353750c2007-09-13 18:13:15 +00002169 global TEST_ALL, DEBUG
Raymond Hettingered20ad82004-09-04 20:09:13 +00002170 TEST_ALL = arith or is_resource_enabled('decimal')
Facundo Batista353750c2007-09-13 18:13:15 +00002171 DEBUG = debug
Raymond Hettingered20ad82004-09-04 20:09:13 +00002172
Facundo Batista353750c2007-09-13 18:13:15 +00002173 if todo_tests is None:
2174 test_classes = [
2175 DecimalExplicitConstructionTest,
2176 DecimalImplicitConstructionTest,
2177 DecimalArithmeticOperatorsTest,
Mark Dickinson1ddf1d82008-02-29 02:16:37 +00002178 DecimalFormatTest,
Facundo Batista353750c2007-09-13 18:13:15 +00002179 DecimalUseOfContextTest,
2180 DecimalUsabilityTest,
2181 DecimalPythonAPItests,
2182 ContextAPItests,
2183 DecimalTest,
2184 WithStatementTest,
2185 ContextFlags
2186 ]
2187 else:
2188 test_classes = [DecimalTest]
2189
2190 # Dynamically build custom test definition for each file in the test
2191 # directory and add the definitions to the DecimalTest class. This
2192 # procedure insures that new files do not get skipped.
2193 for filename in os.listdir(directory):
2194 if '.decTest' not in filename or filename.startswith("."):
2195 continue
2196 head, tail = filename.split('.')
2197 if todo_tests is not None and head not in todo_tests:
2198 continue
2199 tester = lambda self, f=filename: self.eval_file(directory + f)
2200 setattr(DecimalTest, 'test_' + head, tester)
2201 del filename, head, tail, tester
2202
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002203
Tim Peters46cc7022006-03-31 04:11:16 +00002204 try:
2205 run_unittest(*test_classes)
Facundo Batista353750c2007-09-13 18:13:15 +00002206 if todo_tests is None:
2207 import decimal as DecimalModule
2208 run_doctest(DecimalModule, verbose)
Tim Peters46cc7022006-03-31 04:11:16 +00002209 finally:
2210 setcontext(ORIGINAL_CONTEXT)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002211
2212if __name__ == '__main__':
Facundo Batista353750c2007-09-13 18:13:15 +00002213 import optparse
2214 p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]")
2215 p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test')
2216 p.add_option('--skip', '-s', action='store_true', help='skip over 90% of the arithmetic tests')
2217 (opt, args) = p.parse_args()
2218
2219 if opt.skip:
2220 test_main(arith=False, verbose=True)
2221 elif args:
2222 test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002223 else:
Facundo Batista353750c2007-09-13 18:13:15 +00002224 test_main(arith=True, verbose=True)