blob: 4071eff8db9c619ecaae9c93c51b9aa5be2b74dc [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
Mark Dickinson99d80962010-04-02 08:53:22 +00001211 def test_decimal_float_comparison(self):
1212 da = Decimal('0.25')
1213 db = Decimal('3.0')
1214 self.assert_(da < 3.0)
1215 self.assert_(da <= 3.0)
1216 self.assert_(db > 0.25)
1217 self.assert_(db >= 0.25)
1218 self.assert_(da != 1.5)
1219 self.assert_(da == 0.25)
1220 self.assert_(3.0 > da)
1221 self.assert_(3.0 >= da)
1222 self.assert_(0.25 < db)
1223 self.assert_(0.25 <= db)
1224 self.assert_(0.25 != db)
1225 self.assert_(3.0 == db)
1226 self.assert_(0.1 != Decimal('0.1'))
1227
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001228 def test_copy_and_deepcopy_methods(self):
1229 d = Decimal('43.24')
1230 c = copy.copy(d)
1231 self.assertEqual(id(c), id(d))
1232 dc = copy.deepcopy(d)
1233 self.assertEqual(id(dc), id(d))
1234
1235 def test_hash_method(self):
1236 #just that it's hashable
1237 hash(Decimal(23))
Facundo Batista8c202442007-09-19 17:53:25 +00001238
1239 test_values = [Decimal(sign*(2**m + n))
1240 for m in [0, 14, 15, 16, 17, 30, 31,
1241 32, 33, 62, 63, 64, 65, 66]
1242 for n in range(-10, 10)
1243 for sign in [-1, 1]]
1244 test_values.extend([
1245 Decimal("-0"), # zeros
1246 Decimal("0.00"),
1247 Decimal("-0.000"),
1248 Decimal("0E10"),
1249 Decimal("-0E12"),
1250 Decimal("10.0"), # negative exponent
1251 Decimal("-23.00000"),
1252 Decimal("1230E100"), # positive exponent
1253 Decimal("-4.5678E50"),
1254 # a value for which hash(n) != hash(n % (2**64-1))
1255 # in Python pre-2.6
1256 Decimal(2**64 + 2**32 - 1),
1257 # selection of values which fail with the old (before
1258 # version 2.6) long.__hash__
1259 Decimal("1.634E100"),
1260 Decimal("90.697E100"),
1261 Decimal("188.83E100"),
1262 Decimal("1652.9E100"),
1263 Decimal("56531E100"),
1264 ])
1265
1266 # check that hash(d) == hash(int(d)) for integral values
1267 for value in test_values:
1268 self.assertEqual(hash(value), hash(int(value)))
1269
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001270 #the same hash that to an int
1271 self.assertEqual(hash(Decimal(23)), hash(23))
Raymond Hettingerbea3f6f2005-03-15 04:59:17 +00001272 self.assertRaises(TypeError, hash, Decimal('NaN'))
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001273 self.assertTrue(hash(Decimal('Inf')))
1274 self.assertTrue(hash(Decimal('-Inf')))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001275
Mark Dickinson99d80962010-04-02 08:53:22 +00001276 # check that the hashes of a Decimal float match when they
1277 # represent exactly the same values
1278 test_strings = ['inf', '-Inf', '0.0', '-.0e1',
1279 '34.0', '2.5', '112390.625', '-0.515625']
1280 for s in test_strings:
1281 f = float(s)
1282 d = Decimal(s)
1283 self.assertEqual(hash(f), hash(d))
1284
Facundo Batista52b25792008-01-08 12:25:20 +00001285 # check that the value of the hash doesn't depend on the
1286 # current context (issue #1757)
1287 c = getcontext()
1288 old_precision = c.prec
1289 x = Decimal("123456789.1")
1290
1291 c.prec = 6
1292 h1 = hash(x)
1293 c.prec = 10
1294 h2 = hash(x)
1295 c.prec = 16
1296 h3 = hash(x)
1297
1298 self.assertEqual(h1, h2)
1299 self.assertEqual(h1, h3)
1300 c.prec = old_precision
1301
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001302 def test_min_and_max_methods(self):
1303
1304 d1 = Decimal('15.32')
1305 d2 = Decimal('28.5')
1306 l1 = 15
1307 l2 = 28
1308
1309 #between Decimals
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001310 self.assertTrue(min(d1,d2) is d1)
1311 self.assertTrue(min(d2,d1) is d1)
1312 self.assertTrue(max(d1,d2) is d2)
1313 self.assertTrue(max(d2,d1) is d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001314
1315 #between Decimal and long
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001316 self.assertTrue(min(d1,l2) is d1)
1317 self.assertTrue(min(l2,d1) is d1)
1318 self.assertTrue(max(l1,d2) is d2)
1319 self.assertTrue(max(d2,l1) is d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001320
1321 def test_as_nonzero(self):
1322 #as false
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001323 self.assertFalse(Decimal(0))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001324 #as true
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001325 self.assertTrue(Decimal('0.372'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001326
1327 def test_tostring_methods(self):
1328 #Test str and repr methods.
1329
1330 d = Decimal('15.32')
1331 self.assertEqual(str(d), '15.32') # str
Raymond Hettingerabe32372008-02-14 02:41:22 +00001332 self.assertEqual(repr(d), "Decimal('15.32')") # repr
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001333
Mark Dickinson8e85ffa2008-03-25 18:47:59 +00001334 # result type of string methods should be str, not unicode
1335 unicode_inputs = [u'123.4', u'0.5E2', u'Infinity', u'sNaN',
1336 u'-0.0E100', u'-NaN001', u'-Inf']
1337
1338 for u in unicode_inputs:
1339 d = Decimal(u)
1340 self.assertEqual(type(str(d)), str)
1341 self.assertEqual(type(repr(d)), str)
1342 self.assertEqual(type(d.to_eng_string()), str)
1343
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001344 def test_tonum_methods(self):
1345 #Test float, int and long methods.
1346
1347 d1 = Decimal('66')
1348 d2 = Decimal('15.32')
1349
1350 #int
1351 self.assertEqual(int(d1), 66)
1352 self.assertEqual(int(d2), 15)
1353
1354 #long
1355 self.assertEqual(long(d1), 66)
1356 self.assertEqual(long(d2), 15)
1357
1358 #float
1359 self.assertEqual(float(d1), 66)
1360 self.assertEqual(float(d2), 15.32)
1361
1362 def test_eval_round_trip(self):
1363
1364 #with zero
1365 d = Decimal( (0, (0,), 0) )
1366 self.assertEqual(d, eval(repr(d)))
1367
1368 #int
1369 d = Decimal( (1, (4, 5), 0) )
1370 self.assertEqual(d, eval(repr(d)))
1371
1372 #float
1373 d = Decimal( (0, (4, 5, 3, 4), -2) )
1374 self.assertEqual(d, eval(repr(d)))
1375
1376 #weird
1377 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1378 self.assertEqual(d, eval(repr(d)))
1379
1380 def test_as_tuple(self):
1381
1382 #with zero
1383 d = Decimal(0)
1384 self.assertEqual(d.as_tuple(), (0, (0,), 0) )
1385
1386 #int
1387 d = Decimal(-45)
1388 self.assertEqual(d.as_tuple(), (1, (4, 5), 0) )
1389
1390 #complicated string
1391 d = Decimal("-4.34913534E-17")
1392 self.assertEqual(d.as_tuple(), (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1393
1394 #inf
1395 d = Decimal("Infinity")
1396 self.assertEqual(d.as_tuple(), (0, (0,), 'F') )
1397
Facundo Batista9b5e2312007-10-19 19:25:57 +00001398 #leading zeros in coefficient should be stripped
1399 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), -2) )
1400 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), -2) )
1401 d = Decimal( (1, (0, 0, 0), 37) )
1402 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1403 d = Decimal( (1, (), 37) )
1404 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1405
1406 #leading zeros in NaN diagnostic info should be stripped
1407 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), 'n') )
1408 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), 'n') )
1409 d = Decimal( (1, (0, 0, 0), 'N') )
1410 self.assertEqual(d.as_tuple(), (1, (), 'N') )
1411 d = Decimal( (1, (), 'n') )
1412 self.assertEqual(d.as_tuple(), (1, (), 'n') )
1413
1414 #coefficient in infinity should be ignored
1415 d = Decimal( (0, (4, 5, 3, 4), 'F') )
1416 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
1417 d = Decimal( (1, (0, 2, 7, 1), 'F') )
1418 self.assertEqual(d.as_tuple(), (1, (0,), 'F'))
1419
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001420 def test_immutability_operations(self):
1421 # Do operations and check that it didn't change change internal objects.
1422
1423 d1 = Decimal('-25e55')
1424 b1 = Decimal('-25e55')
Facundo Batista353750c2007-09-13 18:13:15 +00001425 d2 = Decimal('33e+33')
1426 b2 = Decimal('33e+33')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001427
1428 def checkSameDec(operation, useOther=False):
1429 if useOther:
1430 eval("d1." + operation + "(d2)")
1431 self.assertEqual(d1._sign, b1._sign)
1432 self.assertEqual(d1._int, b1._int)
1433 self.assertEqual(d1._exp, b1._exp)
1434 self.assertEqual(d2._sign, b2._sign)
1435 self.assertEqual(d2._int, b2._int)
1436 self.assertEqual(d2._exp, b2._exp)
1437 else:
1438 eval("d1." + operation + "()")
1439 self.assertEqual(d1._sign, b1._sign)
1440 self.assertEqual(d1._int, b1._int)
1441 self.assertEqual(d1._exp, b1._exp)
1442 return
1443
1444 Decimal(d1)
1445 self.assertEqual(d1._sign, b1._sign)
1446 self.assertEqual(d1._int, b1._int)
1447 self.assertEqual(d1._exp, b1._exp)
1448
1449 checkSameDec("__abs__")
1450 checkSameDec("__add__", True)
1451 checkSameDec("__div__", True)
1452 checkSameDec("__divmod__", True)
Mark Dickinson2fc92632008-02-06 22:10:50 +00001453 checkSameDec("__eq__", True)
1454 checkSameDec("__ne__", True)
1455 checkSameDec("__le__", True)
1456 checkSameDec("__lt__", True)
1457 checkSameDec("__ge__", True)
1458 checkSameDec("__gt__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001459 checkSameDec("__float__")
1460 checkSameDec("__floordiv__", True)
1461 checkSameDec("__hash__")
1462 checkSameDec("__int__")
Raymond Hettinger5a053642008-01-24 19:05:29 +00001463 checkSameDec("__trunc__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001464 checkSameDec("__long__")
1465 checkSameDec("__mod__", True)
1466 checkSameDec("__mul__", True)
1467 checkSameDec("__neg__")
1468 checkSameDec("__nonzero__")
1469 checkSameDec("__pos__")
1470 checkSameDec("__pow__", True)
1471 checkSameDec("__radd__", True)
1472 checkSameDec("__rdiv__", True)
1473 checkSameDec("__rdivmod__", True)
1474 checkSameDec("__repr__")
1475 checkSameDec("__rfloordiv__", True)
1476 checkSameDec("__rmod__", True)
1477 checkSameDec("__rmul__", True)
1478 checkSameDec("__rpow__", True)
1479 checkSameDec("__rsub__", True)
1480 checkSameDec("__str__")
1481 checkSameDec("__sub__", True)
1482 checkSameDec("__truediv__", True)
1483 checkSameDec("adjusted")
1484 checkSameDec("as_tuple")
1485 checkSameDec("compare", True)
1486 checkSameDec("max", True)
1487 checkSameDec("min", True)
1488 checkSameDec("normalize")
1489 checkSameDec("quantize", True)
1490 checkSameDec("remainder_near", True)
1491 checkSameDec("same_quantum", True)
1492 checkSameDec("sqrt")
1493 checkSameDec("to_eng_string")
1494 checkSameDec("to_integral")
1495
Facundo Batista6c398da2007-09-17 17:30:13 +00001496 def test_subclassing(self):
1497 # Different behaviours when subclassing Decimal
1498
1499 class MyDecimal(Decimal):
1500 pass
1501
1502 d1 = MyDecimal(1)
1503 d2 = MyDecimal(2)
1504 d = d1 + d2
1505 self.assertTrue(type(d) is Decimal)
1506
1507 d = d1.max(d2)
1508 self.assertTrue(type(d) is Decimal)
1509
Mark Dickinson3b24ccb2008-03-25 14:33:23 +00001510 def test_implicit_context(self):
1511 # Check results when context given implicitly. (Issue 2478)
1512 c = getcontext()
1513 self.assertEqual(str(Decimal(0).sqrt()),
1514 str(c.sqrt(Decimal(0))))
1515
Mark Dickinson0c673122009-10-29 12:04:00 +00001516 def test_conversions_from_int(self):
1517 # Check that methods taking a second Decimal argument will
1518 # always accept an integer in place of a Decimal.
1519 self.assertEqual(Decimal(4).compare(3),
1520 Decimal(4).compare(Decimal(3)))
1521 self.assertEqual(Decimal(4).compare_signal(3),
1522 Decimal(4).compare_signal(Decimal(3)))
1523 self.assertEqual(Decimal(4).compare_total(3),
1524 Decimal(4).compare_total(Decimal(3)))
1525 self.assertEqual(Decimal(4).compare_total_mag(3),
1526 Decimal(4).compare_total_mag(Decimal(3)))
1527 self.assertEqual(Decimal(10101).logical_and(1001),
1528 Decimal(10101).logical_and(Decimal(1001)))
1529 self.assertEqual(Decimal(10101).logical_or(1001),
1530 Decimal(10101).logical_or(Decimal(1001)))
1531 self.assertEqual(Decimal(10101).logical_xor(1001),
1532 Decimal(10101).logical_xor(Decimal(1001)))
1533 self.assertEqual(Decimal(567).max(123),
1534 Decimal(567).max(Decimal(123)))
1535 self.assertEqual(Decimal(567).max_mag(123),
1536 Decimal(567).max_mag(Decimal(123)))
1537 self.assertEqual(Decimal(567).min(123),
1538 Decimal(567).min(Decimal(123)))
1539 self.assertEqual(Decimal(567).min_mag(123),
1540 Decimal(567).min_mag(Decimal(123)))
1541 self.assertEqual(Decimal(567).next_toward(123),
1542 Decimal(567).next_toward(Decimal(123)))
1543 self.assertEqual(Decimal(1234).quantize(100),
1544 Decimal(1234).quantize(Decimal(100)))
1545 self.assertEqual(Decimal(768).remainder_near(1234),
1546 Decimal(768).remainder_near(Decimal(1234)))
1547 self.assertEqual(Decimal(123).rotate(1),
1548 Decimal(123).rotate(Decimal(1)))
1549 self.assertEqual(Decimal(1234).same_quantum(1000),
1550 Decimal(1234).same_quantum(Decimal(1000)))
1551 self.assertEqual(Decimal('9.123').scaleb(-100),
1552 Decimal('9.123').scaleb(Decimal(-100)))
1553 self.assertEqual(Decimal(456).shift(-1),
1554 Decimal(456).shift(Decimal(-1)))
1555
1556 self.assertEqual(Decimal(-12).fma(Decimal(45), 67),
1557 Decimal(-12).fma(Decimal(45), Decimal(67)))
1558 self.assertEqual(Decimal(-12).fma(45, 67),
1559 Decimal(-12).fma(Decimal(45), Decimal(67)))
1560 self.assertEqual(Decimal(-12).fma(45, Decimal(67)),
1561 Decimal(-12).fma(Decimal(45), Decimal(67)))
1562
Facundo Batista6c398da2007-09-17 17:30:13 +00001563
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001564class DecimalPythonAPItests(unittest.TestCase):
1565
Raymond Hettinger2c8585b2009-02-03 03:37:03 +00001566 def test_abc(self):
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001567 self.assertTrue(issubclass(Decimal, numbers.Number))
1568 self.assertTrue(not issubclass(Decimal, numbers.Real))
Ezio Melottib0f5adc2010-01-24 16:58:36 +00001569 self.assertIsInstance(Decimal(0), numbers.Number)
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001570 self.assertTrue(not isinstance(Decimal(0), numbers.Real))
Raymond Hettinger2c8585b2009-02-03 03:37:03 +00001571
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001572 def test_pickle(self):
1573 d = Decimal('-3.141590000')
1574 p = pickle.dumps(d)
1575 e = pickle.loads(p)
1576 self.assertEqual(d, e)
1577
Raymond Hettinger5548be22004-07-05 18:49:38 +00001578 def test_int(self):
Raymond Hettinger605ed022004-11-24 07:28:48 +00001579 for x in range(-250, 250):
1580 s = '%0.2f' % (x / 100.0)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001581 # should work the same as for floats
1582 self.assertEqual(int(Decimal(s)), int(float(s)))
Raymond Hettinger605ed022004-11-24 07:28:48 +00001583 # should work the same as to_integral in the ROUND_DOWN mode
Raymond Hettinger5548be22004-07-05 18:49:38 +00001584 d = Decimal(s)
Raymond Hettinger605ed022004-11-24 07:28:48 +00001585 r = d.to_integral(ROUND_DOWN)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001586 self.assertEqual(Decimal(int(d)), r)
1587
Mark Dickinson968f1692009-09-07 18:04:58 +00001588 self.assertRaises(ValueError, int, Decimal('-nan'))
1589 self.assertRaises(ValueError, int, Decimal('snan'))
1590 self.assertRaises(OverflowError, int, Decimal('inf'))
1591 self.assertRaises(OverflowError, int, Decimal('-inf'))
1592
1593 self.assertRaises(ValueError, long, Decimal('-nan'))
1594 self.assertRaises(ValueError, long, Decimal('snan'))
1595 self.assertRaises(OverflowError, long, Decimal('inf'))
1596 self.assertRaises(OverflowError, long, Decimal('-inf'))
1597
Raymond Hettinger5a053642008-01-24 19:05:29 +00001598 def test_trunc(self):
1599 for x in range(-250, 250):
1600 s = '%0.2f' % (x / 100.0)
1601 # should work the same as for floats
1602 self.assertEqual(int(Decimal(s)), int(float(s)))
1603 # should work the same as to_integral in the ROUND_DOWN mode
1604 d = Decimal(s)
1605 r = d.to_integral(ROUND_DOWN)
Jeffrey Yasskinca2b69f2008-02-01 06:22:46 +00001606 self.assertEqual(Decimal(math.trunc(d)), r)
Raymond Hettinger5a053642008-01-24 19:05:29 +00001607
Raymond Hettingerf4d85972009-01-03 19:02:23 +00001608 def test_from_float(self):
1609
1610 class MyDecimal(Decimal):
1611 pass
1612
1613 r = MyDecimal.from_float(0.1)
1614 self.assertEqual(type(r), MyDecimal)
1615 self.assertEqual(str(r),
1616 '0.1000000000000000055511151231257827021181583404541015625')
1617 bigint = 12345678901234567890123456789
1618 self.assertEqual(MyDecimal.from_float(bigint), MyDecimal(bigint))
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001619 self.assertTrue(MyDecimal.from_float(float('nan')).is_qnan())
1620 self.assertTrue(MyDecimal.from_float(float('inf')).is_infinite())
1621 self.assertTrue(MyDecimal.from_float(float('-inf')).is_infinite())
Raymond Hettingerf4d85972009-01-03 19:02:23 +00001622 self.assertEqual(str(MyDecimal.from_float(float('nan'))),
1623 str(Decimal('NaN')))
1624 self.assertEqual(str(MyDecimal.from_float(float('inf'))),
1625 str(Decimal('Infinity')))
1626 self.assertEqual(str(MyDecimal.from_float(float('-inf'))),
1627 str(Decimal('-Infinity')))
1628 self.assertRaises(TypeError, MyDecimal.from_float, 'abc')
1629 for i in range(200):
1630 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
1631 self.assertEqual(x, float(MyDecimal.from_float(x))) # roundtrip
1632
1633 def test_create_decimal_from_float(self):
1634 context = Context(prec=5, rounding=ROUND_DOWN)
1635 self.assertEqual(
1636 context.create_decimal_from_float(math.pi),
1637 Decimal('3.1415')
1638 )
1639 context = Context(prec=5, rounding=ROUND_UP)
1640 self.assertEqual(
1641 context.create_decimal_from_float(math.pi),
1642 Decimal('3.1416')
1643 )
1644 context = Context(prec=5, traps=[Inexact])
1645 self.assertRaises(
1646 Inexact,
1647 context.create_decimal_from_float,
1648 math.pi
1649 )
1650 self.assertEqual(repr(context.create_decimal_from_float(-0.0)),
1651 "Decimal('-0')")
1652 self.assertEqual(repr(context.create_decimal_from_float(1.0)),
1653 "Decimal('1')")
1654 self.assertEqual(repr(context.create_decimal_from_float(10)),
1655 "Decimal('10')")
1656
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00001657class ContextAPItests(unittest.TestCase):
1658
1659 def test_pickle(self):
1660 c = Context()
1661 e = pickle.loads(pickle.dumps(c))
1662 for k in vars(c):
1663 v1 = vars(c)[k]
1664 v2 = vars(e)[k]
1665 self.assertEqual(v1, v2)
1666
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001667 def test_equality_with_other_types(self):
Ezio Melottiaa980582010-01-23 23:04:36 +00001668 self.assertIn(Decimal(10), ['a', 1.0, Decimal(10), (1,2), {}])
1669 self.assertNotIn(Decimal(10), ['a', 1.0, (1,2), {}])
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001670
Raymond Hettinger955d2b22004-08-08 20:17:45 +00001671 def test_copy(self):
1672 # All copies should be deep
1673 c = Context()
1674 d = c.copy()
1675 self.assertNotEqual(id(c), id(d))
1676 self.assertNotEqual(id(c.flags), id(d.flags))
1677 self.assertNotEqual(id(c.traps), id(d.traps))
1678
Mark Dickinson6d8effb2010-02-18 14:27:02 +00001679 def test_abs(self):
1680 c = Context()
1681 d = c.abs(Decimal(-1))
1682 self.assertEqual(c.abs(-1), d)
1683 self.assertRaises(TypeError, c.abs, '-1')
1684
1685 def test_add(self):
1686 c = Context()
1687 d = c.add(Decimal(1), Decimal(1))
1688 self.assertEqual(c.add(1, 1), d)
1689 self.assertEqual(c.add(Decimal(1), 1), d)
1690 self.assertEqual(c.add(1, Decimal(1)), d)
1691 self.assertRaises(TypeError, c.add, '1', 1)
1692 self.assertRaises(TypeError, c.add, 1, '1')
1693
1694 def test_compare(self):
1695 c = Context()
1696 d = c.compare(Decimal(1), Decimal(1))
1697 self.assertEqual(c.compare(1, 1), d)
1698 self.assertEqual(c.compare(Decimal(1), 1), d)
1699 self.assertEqual(c.compare(1, Decimal(1)), d)
1700 self.assertRaises(TypeError, c.compare, '1', 1)
1701 self.assertRaises(TypeError, c.compare, 1, '1')
1702
1703 def test_compare_signal(self):
1704 c = Context()
1705 d = c.compare_signal(Decimal(1), Decimal(1))
1706 self.assertEqual(c.compare_signal(1, 1), d)
1707 self.assertEqual(c.compare_signal(Decimal(1), 1), d)
1708 self.assertEqual(c.compare_signal(1, Decimal(1)), d)
1709 self.assertRaises(TypeError, c.compare_signal, '1', 1)
1710 self.assertRaises(TypeError, c.compare_signal, 1, '1')
1711
1712 def test_compare_total(self):
1713 c = Context()
1714 d = c.compare_total(Decimal(1), Decimal(1))
1715 self.assertEqual(c.compare_total(1, 1), d)
1716 self.assertEqual(c.compare_total(Decimal(1), 1), d)
1717 self.assertEqual(c.compare_total(1, Decimal(1)), d)
1718 self.assertRaises(TypeError, c.compare_total, '1', 1)
1719 self.assertRaises(TypeError, c.compare_total, 1, '1')
1720
1721 def test_compare_total_mag(self):
1722 c = Context()
1723 d = c.compare_total_mag(Decimal(1), Decimal(1))
1724 self.assertEqual(c.compare_total_mag(1, 1), d)
1725 self.assertEqual(c.compare_total_mag(Decimal(1), 1), d)
1726 self.assertEqual(c.compare_total_mag(1, Decimal(1)), d)
1727 self.assertRaises(TypeError, c.compare_total_mag, '1', 1)
1728 self.assertRaises(TypeError, c.compare_total_mag, 1, '1')
1729
1730 def test_copy_abs(self):
1731 c = Context()
1732 d = c.copy_abs(Decimal(-1))
1733 self.assertEqual(c.copy_abs(-1), d)
1734 self.assertRaises(TypeError, c.copy_abs, '-1')
1735
1736 def test_copy_decimal(self):
1737 c = Context()
1738 d = c.copy_decimal(Decimal(-1))
1739 self.assertEqual(c.copy_decimal(-1), d)
1740 self.assertRaises(TypeError, c.copy_decimal, '-1')
1741
1742 def test_copy_negate(self):
1743 c = Context()
1744 d = c.copy_negate(Decimal(-1))
1745 self.assertEqual(c.copy_negate(-1), d)
1746 self.assertRaises(TypeError, c.copy_negate, '-1')
1747
1748 def test_copy_sign(self):
1749 c = Context()
1750 d = c.copy_sign(Decimal(1), Decimal(-2))
1751 self.assertEqual(c.copy_sign(1, -2), d)
1752 self.assertEqual(c.copy_sign(Decimal(1), -2), d)
1753 self.assertEqual(c.copy_sign(1, Decimal(-2)), d)
1754 self.assertRaises(TypeError, c.copy_sign, '1', -2)
1755 self.assertRaises(TypeError, c.copy_sign, 1, '-2')
1756
1757 def test_divide(self):
1758 c = Context()
1759 d = c.divide(Decimal(1), Decimal(2))
1760 self.assertEqual(c.divide(1, 2), d)
1761 self.assertEqual(c.divide(Decimal(1), 2), d)
1762 self.assertEqual(c.divide(1, Decimal(2)), d)
1763 self.assertRaises(TypeError, c.divide, '1', 2)
1764 self.assertRaises(TypeError, c.divide, 1, '2')
1765
1766 def test_divide_int(self):
1767 c = Context()
1768 d = c.divide_int(Decimal(1), Decimal(2))
1769 self.assertEqual(c.divide_int(1, 2), d)
1770 self.assertEqual(c.divide_int(Decimal(1), 2), d)
1771 self.assertEqual(c.divide_int(1, Decimal(2)), d)
1772 self.assertRaises(TypeError, c.divide_int, '1', 2)
1773 self.assertRaises(TypeError, c.divide_int, 1, '2')
1774
1775 def test_divmod(self):
1776 c = Context()
1777 d = c.divmod(Decimal(1), Decimal(2))
1778 self.assertEqual(c.divmod(1, 2), d)
1779 self.assertEqual(c.divmod(Decimal(1), 2), d)
1780 self.assertEqual(c.divmod(1, Decimal(2)), d)
1781 self.assertRaises(TypeError, c.divmod, '1', 2)
1782 self.assertRaises(TypeError, c.divmod, 1, '2')
1783
1784 def test_exp(self):
1785 c = Context()
1786 d = c.exp(Decimal(10))
1787 self.assertEqual(c.exp(10), d)
1788 self.assertRaises(TypeError, c.exp, '10')
1789
1790 def test_fma(self):
1791 c = Context()
1792 d = c.fma(Decimal(2), Decimal(3), Decimal(4))
1793 self.assertEqual(c.fma(2, 3, 4), d)
1794 self.assertEqual(c.fma(Decimal(2), 3, 4), d)
1795 self.assertEqual(c.fma(2, Decimal(3), 4), d)
1796 self.assertEqual(c.fma(2, 3, Decimal(4)), d)
1797 self.assertEqual(c.fma(Decimal(2), Decimal(3), 4), d)
1798 self.assertRaises(TypeError, c.fma, '2', 3, 4)
1799 self.assertRaises(TypeError, c.fma, 2, '3', 4)
1800 self.assertRaises(TypeError, c.fma, 2, 3, '4')
1801
1802 def test_is_finite(self):
1803 c = Context()
1804 d = c.is_finite(Decimal(10))
1805 self.assertEqual(c.is_finite(10), d)
1806 self.assertRaises(TypeError, c.is_finite, '10')
1807
1808 def test_is_infinite(self):
1809 c = Context()
1810 d = c.is_infinite(Decimal(10))
1811 self.assertEqual(c.is_infinite(10), d)
1812 self.assertRaises(TypeError, c.is_infinite, '10')
1813
1814 def test_is_nan(self):
1815 c = Context()
1816 d = c.is_nan(Decimal(10))
1817 self.assertEqual(c.is_nan(10), d)
1818 self.assertRaises(TypeError, c.is_nan, '10')
1819
1820 def test_is_normal(self):
1821 c = Context()
1822 d = c.is_normal(Decimal(10))
1823 self.assertEqual(c.is_normal(10), d)
1824 self.assertRaises(TypeError, c.is_normal, '10')
1825
1826 def test_is_qnan(self):
1827 c = Context()
1828 d = c.is_qnan(Decimal(10))
1829 self.assertEqual(c.is_qnan(10), d)
1830 self.assertRaises(TypeError, c.is_qnan, '10')
1831
1832 def test_is_signed(self):
1833 c = Context()
1834 d = c.is_signed(Decimal(10))
1835 self.assertEqual(c.is_signed(10), d)
1836 self.assertRaises(TypeError, c.is_signed, '10')
1837
1838 def test_is_snan(self):
1839 c = Context()
1840 d = c.is_snan(Decimal(10))
1841 self.assertEqual(c.is_snan(10), d)
1842 self.assertRaises(TypeError, c.is_snan, '10')
1843
1844 def test_is_subnormal(self):
1845 c = Context()
1846 d = c.is_subnormal(Decimal(10))
1847 self.assertEqual(c.is_subnormal(10), d)
1848 self.assertRaises(TypeError, c.is_subnormal, '10')
1849
1850 def test_is_zero(self):
1851 c = Context()
1852 d = c.is_zero(Decimal(10))
1853 self.assertEqual(c.is_zero(10), d)
1854 self.assertRaises(TypeError, c.is_zero, '10')
1855
1856 def test_ln(self):
1857 c = Context()
1858 d = c.ln(Decimal(10))
1859 self.assertEqual(c.ln(10), d)
1860 self.assertRaises(TypeError, c.ln, '10')
1861
1862 def test_log10(self):
1863 c = Context()
1864 d = c.log10(Decimal(10))
1865 self.assertEqual(c.log10(10), d)
1866 self.assertRaises(TypeError, c.log10, '10')
1867
1868 def test_logb(self):
1869 c = Context()
1870 d = c.logb(Decimal(10))
1871 self.assertEqual(c.logb(10), d)
1872 self.assertRaises(TypeError, c.logb, '10')
1873
1874 def test_logical_and(self):
1875 c = Context()
1876 d = c.logical_and(Decimal(1), Decimal(1))
1877 self.assertEqual(c.logical_and(1, 1), d)
1878 self.assertEqual(c.logical_and(Decimal(1), 1), d)
1879 self.assertEqual(c.logical_and(1, Decimal(1)), d)
1880 self.assertRaises(TypeError, c.logical_and, '1', 1)
1881 self.assertRaises(TypeError, c.logical_and, 1, '1')
1882
1883 def test_logical_invert(self):
1884 c = Context()
1885 d = c.logical_invert(Decimal(1000))
1886 self.assertEqual(c.logical_invert(1000), d)
1887 self.assertRaises(TypeError, c.logical_invert, '1000')
1888
1889 def test_logical_or(self):
1890 c = Context()
1891 d = c.logical_or(Decimal(1), Decimal(1))
1892 self.assertEqual(c.logical_or(1, 1), d)
1893 self.assertEqual(c.logical_or(Decimal(1), 1), d)
1894 self.assertEqual(c.logical_or(1, Decimal(1)), d)
1895 self.assertRaises(TypeError, c.logical_or, '1', 1)
1896 self.assertRaises(TypeError, c.logical_or, 1, '1')
1897
1898 def test_logical_xor(self):
1899 c = Context()
1900 d = c.logical_xor(Decimal(1), Decimal(1))
1901 self.assertEqual(c.logical_xor(1, 1), d)
1902 self.assertEqual(c.logical_xor(Decimal(1), 1), d)
1903 self.assertEqual(c.logical_xor(1, Decimal(1)), d)
1904 self.assertRaises(TypeError, c.logical_xor, '1', 1)
1905 self.assertRaises(TypeError, c.logical_xor, 1, '1')
1906
1907 def test_max(self):
1908 c = Context()
1909 d = c.max(Decimal(1), Decimal(2))
1910 self.assertEqual(c.max(1, 2), d)
1911 self.assertEqual(c.max(Decimal(1), 2), d)
1912 self.assertEqual(c.max(1, Decimal(2)), d)
1913 self.assertRaises(TypeError, c.max, '1', 2)
1914 self.assertRaises(TypeError, c.max, 1, '2')
1915
1916 def test_max_mag(self):
1917 c = Context()
1918 d = c.max_mag(Decimal(1), Decimal(2))
1919 self.assertEqual(c.max_mag(1, 2), d)
1920 self.assertEqual(c.max_mag(Decimal(1), 2), d)
1921 self.assertEqual(c.max_mag(1, Decimal(2)), d)
1922 self.assertRaises(TypeError, c.max_mag, '1', 2)
1923 self.assertRaises(TypeError, c.max_mag, 1, '2')
1924
1925 def test_min(self):
1926 c = Context()
1927 d = c.min(Decimal(1), Decimal(2))
1928 self.assertEqual(c.min(1, 2), d)
1929 self.assertEqual(c.min(Decimal(1), 2), d)
1930 self.assertEqual(c.min(1, Decimal(2)), d)
1931 self.assertRaises(TypeError, c.min, '1', 2)
1932 self.assertRaises(TypeError, c.min, 1, '2')
1933
1934 def test_min_mag(self):
1935 c = Context()
1936 d = c.min_mag(Decimal(1), Decimal(2))
1937 self.assertEqual(c.min_mag(1, 2), d)
1938 self.assertEqual(c.min_mag(Decimal(1), 2), d)
1939 self.assertEqual(c.min_mag(1, Decimal(2)), d)
1940 self.assertRaises(TypeError, c.min_mag, '1', 2)
1941 self.assertRaises(TypeError, c.min_mag, 1, '2')
1942
1943 def test_minus(self):
1944 c = Context()
1945 d = c.minus(Decimal(10))
1946 self.assertEqual(c.minus(10), d)
1947 self.assertRaises(TypeError, c.minus, '10')
1948
1949 def test_multiply(self):
1950 c = Context()
1951 d = c.multiply(Decimal(1), Decimal(2))
1952 self.assertEqual(c.multiply(1, 2), d)
1953 self.assertEqual(c.multiply(Decimal(1), 2), d)
1954 self.assertEqual(c.multiply(1, Decimal(2)), d)
1955 self.assertRaises(TypeError, c.multiply, '1', 2)
1956 self.assertRaises(TypeError, c.multiply, 1, '2')
1957
1958 def test_next_minus(self):
1959 c = Context()
1960 d = c.next_minus(Decimal(10))
1961 self.assertEqual(c.next_minus(10), d)
1962 self.assertRaises(TypeError, c.next_minus, '10')
1963
1964 def test_next_plus(self):
1965 c = Context()
1966 d = c.next_plus(Decimal(10))
1967 self.assertEqual(c.next_plus(10), d)
1968 self.assertRaises(TypeError, c.next_plus, '10')
1969
1970 def test_next_toward(self):
1971 c = Context()
1972 d = c.next_toward(Decimal(1), Decimal(2))
1973 self.assertEqual(c.next_toward(1, 2), d)
1974 self.assertEqual(c.next_toward(Decimal(1), 2), d)
1975 self.assertEqual(c.next_toward(1, Decimal(2)), d)
1976 self.assertRaises(TypeError, c.next_toward, '1', 2)
1977 self.assertRaises(TypeError, c.next_toward, 1, '2')
1978
1979 def test_normalize(self):
1980 c = Context()
1981 d = c.normalize(Decimal(10))
1982 self.assertEqual(c.normalize(10), d)
1983 self.assertRaises(TypeError, c.normalize, '10')
1984
1985 def test_number_class(self):
1986 c = Context()
1987 self.assertEqual(c.number_class(123), c.number_class(Decimal(123)))
1988 self.assertEqual(c.number_class(0), c.number_class(Decimal(0)))
1989 self.assertEqual(c.number_class(-45), c.number_class(Decimal(-45)))
1990
1991 def test_power(self):
1992 c = Context()
1993 d = c.power(Decimal(1), Decimal(4), Decimal(2))
1994 self.assertEqual(c.power(1, 4, 2), d)
1995 self.assertEqual(c.power(Decimal(1), 4, 2), d)
1996 self.assertEqual(c.power(1, Decimal(4), 2), d)
1997 self.assertEqual(c.power(1, 4, Decimal(2)), d)
1998 self.assertEqual(c.power(Decimal(1), Decimal(4), 2), d)
1999 self.assertRaises(TypeError, c.power, '1', 4, 2)
2000 self.assertRaises(TypeError, c.power, 1, '4', 2)
2001 self.assertRaises(TypeError, c.power, 1, 4, '2')
2002
2003 def test_plus(self):
2004 c = Context()
2005 d = c.plus(Decimal(10))
2006 self.assertEqual(c.plus(10), d)
2007 self.assertRaises(TypeError, c.plus, '10')
2008
2009 def test_quantize(self):
2010 c = Context()
2011 d = c.quantize(Decimal(1), Decimal(2))
2012 self.assertEqual(c.quantize(1, 2), d)
2013 self.assertEqual(c.quantize(Decimal(1), 2), d)
2014 self.assertEqual(c.quantize(1, Decimal(2)), d)
2015 self.assertRaises(TypeError, c.quantize, '1', 2)
2016 self.assertRaises(TypeError, c.quantize, 1, '2')
2017
2018 def test_remainder(self):
2019 c = Context()
2020 d = c.remainder(Decimal(1), Decimal(2))
2021 self.assertEqual(c.remainder(1, 2), d)
2022 self.assertEqual(c.remainder(Decimal(1), 2), d)
2023 self.assertEqual(c.remainder(1, Decimal(2)), d)
2024 self.assertRaises(TypeError, c.remainder, '1', 2)
2025 self.assertRaises(TypeError, c.remainder, 1, '2')
2026
2027 def test_remainder_near(self):
2028 c = Context()
2029 d = c.remainder_near(Decimal(1), Decimal(2))
2030 self.assertEqual(c.remainder_near(1, 2), d)
2031 self.assertEqual(c.remainder_near(Decimal(1), 2), d)
2032 self.assertEqual(c.remainder_near(1, Decimal(2)), d)
2033 self.assertRaises(TypeError, c.remainder_near, '1', 2)
2034 self.assertRaises(TypeError, c.remainder_near, 1, '2')
2035
2036 def test_rotate(self):
2037 c = Context()
2038 d = c.rotate(Decimal(1), Decimal(2))
2039 self.assertEqual(c.rotate(1, 2), d)
2040 self.assertEqual(c.rotate(Decimal(1), 2), d)
2041 self.assertEqual(c.rotate(1, Decimal(2)), d)
2042 self.assertRaises(TypeError, c.rotate, '1', 2)
2043 self.assertRaises(TypeError, c.rotate, 1, '2')
2044
2045 def test_sqrt(self):
2046 c = Context()
2047 d = c.sqrt(Decimal(10))
2048 self.assertEqual(c.sqrt(10), d)
2049 self.assertRaises(TypeError, c.sqrt, '10')
2050
2051 def test_same_quantum(self):
2052 c = Context()
2053 d = c.same_quantum(Decimal(1), Decimal(2))
2054 self.assertEqual(c.same_quantum(1, 2), d)
2055 self.assertEqual(c.same_quantum(Decimal(1), 2), d)
2056 self.assertEqual(c.same_quantum(1, Decimal(2)), d)
2057 self.assertRaises(TypeError, c.same_quantum, '1', 2)
2058 self.assertRaises(TypeError, c.same_quantum, 1, '2')
2059
2060 def test_scaleb(self):
2061 c = Context()
2062 d = c.scaleb(Decimal(1), Decimal(2))
2063 self.assertEqual(c.scaleb(1, 2), d)
2064 self.assertEqual(c.scaleb(Decimal(1), 2), d)
2065 self.assertEqual(c.scaleb(1, Decimal(2)), d)
2066 self.assertRaises(TypeError, c.scaleb, '1', 2)
2067 self.assertRaises(TypeError, c.scaleb, 1, '2')
2068
2069 def test_shift(self):
2070 c = Context()
2071 d = c.shift(Decimal(1), Decimal(2))
2072 self.assertEqual(c.shift(1, 2), d)
2073 self.assertEqual(c.shift(Decimal(1), 2), d)
2074 self.assertEqual(c.shift(1, Decimal(2)), d)
2075 self.assertRaises(TypeError, c.shift, '1', 2)
2076 self.assertRaises(TypeError, c.shift, 1, '2')
2077
2078 def test_subtract(self):
2079 c = Context()
2080 d = c.subtract(Decimal(1), Decimal(2))
2081 self.assertEqual(c.subtract(1, 2), d)
2082 self.assertEqual(c.subtract(Decimal(1), 2), d)
2083 self.assertEqual(c.subtract(1, Decimal(2)), d)
2084 self.assertRaises(TypeError, c.subtract, '1', 2)
2085 self.assertRaises(TypeError, c.subtract, 1, '2')
2086
2087 def test_to_eng_string(self):
2088 c = Context()
2089 d = c.to_eng_string(Decimal(10))
2090 self.assertEqual(c.to_eng_string(10), d)
2091 self.assertRaises(TypeError, c.to_eng_string, '10')
2092
2093 def test_to_sci_string(self):
2094 c = Context()
2095 d = c.to_sci_string(Decimal(10))
2096 self.assertEqual(c.to_sci_string(10), d)
2097 self.assertRaises(TypeError, c.to_sci_string, '10')
2098
2099 def test_to_integral_exact(self):
2100 c = Context()
2101 d = c.to_integral_exact(Decimal(10))
2102 self.assertEqual(c.to_integral_exact(10), d)
2103 self.assertRaises(TypeError, c.to_integral_exact, '10')
2104
2105 def test_to_integral_value(self):
2106 c = Context()
2107 d = c.to_integral_value(Decimal(10))
2108 self.assertEqual(c.to_integral_value(10), d)
2109 self.assertRaises(TypeError, c.to_integral_value, '10')
2110
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002111class WithStatementTest(unittest.TestCase):
2112 # Can't do these as docstrings until Python 2.6
2113 # as doctest can't handle __future__ statements
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002114
2115 def test_localcontext(self):
Nick Coghlanced12182006-09-02 03:54:17 +00002116 # Use a copy of the current context in the block
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002117 orig_ctx = getcontext()
2118 with localcontext() as enter_ctx:
2119 set_ctx = getcontext()
2120 final_ctx = getcontext()
Benjamin Peterson5c8da862009-06-30 22:57:08 +00002121 self.assertTrue(orig_ctx is final_ctx, 'did not restore context correctly')
2122 self.assertTrue(orig_ctx is not set_ctx, 'did not copy the context')
2123 self.assertTrue(set_ctx is enter_ctx, '__enter__ returned wrong context')
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002124
2125 def test_localcontextarg(self):
Nick Coghlanced12182006-09-02 03:54:17 +00002126 # Use a copy of the supplied context in the block
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002127 orig_ctx = getcontext()
2128 new_ctx = Context(prec=42)
2129 with localcontext(new_ctx) as enter_ctx:
2130 set_ctx = getcontext()
2131 final_ctx = getcontext()
Benjamin Peterson5c8da862009-06-30 22:57:08 +00002132 self.assertTrue(orig_ctx is final_ctx, 'did not restore context correctly')
2133 self.assertTrue(set_ctx.prec == new_ctx.prec, 'did not set correct context')
2134 self.assertTrue(new_ctx is not set_ctx, 'did not copy the context')
2135 self.assertTrue(set_ctx is enter_ctx, '__enter__ returned wrong context')
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002136
Facundo Batista353750c2007-09-13 18:13:15 +00002137class ContextFlags(unittest.TestCase):
2138 def test_flags_irrelevant(self):
2139 # check that the result (numeric result + flags raised) of an
2140 # arithmetic operation doesn't depend on the current flags
2141
2142 context = Context(prec=9, Emin = -999999999, Emax = 999999999,
2143 rounding=ROUND_HALF_EVEN, traps=[], flags=[])
2144
2145 # operations that raise various flags, in the form (function, arglist)
2146 operations = [
2147 (context._apply, [Decimal("100E-1000000009")]),
2148 (context.sqrt, [Decimal(2)]),
2149 (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]),
2150 (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]),
2151 (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]),
2152 ]
2153
2154 # try various flags individually, then a whole lot at once
2155 flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal],
2156 [Inexact, Rounded, Underflow, Clamped, Subnormal]]
2157
2158 for fn, args in operations:
2159 # find answer and flags raised using a clean context
2160 context.clear_flags()
2161 ans = fn(*args)
2162 flags = [k for k, v in context.flags.items() if v]
2163
2164 for extra_flags in flagsets:
2165 # set flags, before calling operation
2166 context.clear_flags()
2167 for flag in extra_flags:
2168 context._raise_error(flag)
2169 new_ans = fn(*args)
2170
2171 # flags that we expect to be set after the operation
2172 expected_flags = list(flags)
2173 for flag in extra_flags:
2174 if flag not in expected_flags:
2175 expected_flags.append(flag)
Facundo Batista353750c2007-09-13 18:13:15 +00002176
2177 # flags we actually got
2178 new_flags = [k for k,v in context.flags.items() if v]
Facundo Batista353750c2007-09-13 18:13:15 +00002179
2180 self.assertEqual(ans, new_ans,
2181 "operation produces different answers depending on flags set: " +
2182 "expected %s, got %s." % (ans, new_ans))
Florent Xicluna8f43cec2010-03-21 10:51:40 +00002183 self.assertItemsEqual(new_flags, expected_flags,
Facundo Batista353750c2007-09-13 18:13:15 +00002184 "operation raises different flags depending on flags set: " +
2185 "expected %s, got %s" % (expected_flags, new_flags))
2186
2187def test_main(arith=False, verbose=None, todo_tests=None, debug=None):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002188 """ Execute the tests.
2189
Raymond Hettingered20ad82004-09-04 20:09:13 +00002190 Runs all arithmetic tests if arith is True or if the "decimal" resource
2191 is enabled in regrtest.py
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002192 """
Raymond Hettingered20ad82004-09-04 20:09:13 +00002193
Neal Norwitzce4a9c92006-04-09 08:36:46 +00002194 init()
Facundo Batista353750c2007-09-13 18:13:15 +00002195 global TEST_ALL, DEBUG
Raymond Hettingered20ad82004-09-04 20:09:13 +00002196 TEST_ALL = arith or is_resource_enabled('decimal')
Facundo Batista353750c2007-09-13 18:13:15 +00002197 DEBUG = debug
Raymond Hettingered20ad82004-09-04 20:09:13 +00002198
Facundo Batista353750c2007-09-13 18:13:15 +00002199 if todo_tests is None:
2200 test_classes = [
2201 DecimalExplicitConstructionTest,
2202 DecimalImplicitConstructionTest,
2203 DecimalArithmeticOperatorsTest,
Mark Dickinson1ddf1d82008-02-29 02:16:37 +00002204 DecimalFormatTest,
Facundo Batista353750c2007-09-13 18:13:15 +00002205 DecimalUseOfContextTest,
2206 DecimalUsabilityTest,
2207 DecimalPythonAPItests,
2208 ContextAPItests,
2209 DecimalTest,
2210 WithStatementTest,
2211 ContextFlags
2212 ]
2213 else:
2214 test_classes = [DecimalTest]
2215
2216 # Dynamically build custom test definition for each file in the test
2217 # directory and add the definitions to the DecimalTest class. This
2218 # procedure insures that new files do not get skipped.
2219 for filename in os.listdir(directory):
2220 if '.decTest' not in filename or filename.startswith("."):
2221 continue
2222 head, tail = filename.split('.')
2223 if todo_tests is not None and head not in todo_tests:
2224 continue
2225 tester = lambda self, f=filename: self.eval_file(directory + f)
2226 setattr(DecimalTest, 'test_' + head, tester)
2227 del filename, head, tail, tester
2228
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002229
Tim Peters46cc7022006-03-31 04:11:16 +00002230 try:
2231 run_unittest(*test_classes)
Facundo Batista353750c2007-09-13 18:13:15 +00002232 if todo_tests is None:
2233 import decimal as DecimalModule
2234 run_doctest(DecimalModule, verbose)
Tim Peters46cc7022006-03-31 04:11:16 +00002235 finally:
2236 setcontext(ORIGINAL_CONTEXT)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002237
2238if __name__ == '__main__':
Facundo Batista353750c2007-09-13 18:13:15 +00002239 import optparse
2240 p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]")
2241 p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test')
2242 p.add_option('--skip', '-s', action='store_true', help='skip over 90% of the arithmetic tests')
2243 (opt, args) = p.parse_args()
2244
2245 if opt.skip:
2246 test_main(arith=False, verbose=True)
2247 elif args:
2248 test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002249 else:
Facundo Batista353750c2007-09-13 18:13:15 +00002250 test_main(arith=True, verbose=True)