blob: 96bbafe7395e22e1344a3d15a918afc92509e3da [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
Christian Heimes400adb02008-02-01 08:12:03 +000027import math
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000028import os, sys
Mark Dickinsonac256ab2010-04-03 11:08:14 +000029import operator
Mark Dickinsonb1d8e322010-05-22 18:35:36 +000030import warnings
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000031import pickle, copy
Christian Heimes400adb02008-02-01 08:12:03 +000032import unittest
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000033from decimal import *
Raymond Hettinger82417ca2009-02-03 03:54:28 +000034import numbers
Eric Smith3ab08ca2010-12-04 15:17:38 +000035from test.support import (run_unittest, run_doctest, is_resource_enabled,
36 requires_IEEE_754)
Mark Dickinsonb1d8e322010-05-22 18:35:36 +000037from test.support import check_warnings
Raymond Hettinger0aeac102004-07-05 22:53:03 +000038import random
Raymond Hettinger7e71fa52004-12-18 19:07:19 +000039try:
40 import threading
41except ImportError:
42 threading = None
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000043
Raymond Hettingerfed52962004-07-14 15:41:57 +000044# Useful Test Constant
Guido van Rossumc1f779c2007-07-03 08:25:58 +000045Signals = tuple(getcontext().flags.keys())
Raymond Hettingerfed52962004-07-14 15:41:57 +000046
Mark Dickinsonc69160e2010-05-04 14:35:33 +000047# Signals ordered with respect to precedence: when an operation
48# produces multiple signals, signals occurring later in the list
49# should be handled before those occurring earlier in the list.
50OrderedSignals = (Clamped, Rounded, Inexact, Subnormal,
51 Underflow, Overflow, DivisionByZero, InvalidOperation)
52
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000053# Tests are built around these assumed context defaults.
54# test_main() restores the original context.
55def init():
56 global ORIGINAL_CONTEXT
57 ORIGINAL_CONTEXT = getcontext().copy()
Christian Heimes81ee3ef2008-05-04 22:42:01 +000058 DefaultTestContext = Context(
59 prec = 9,
60 rounding = ROUND_HALF_EVEN,
61 traps = dict.fromkeys(Signals, 0)
62 )
63 setcontext(DefaultTestContext)
Raymond Hettinger6ea48452004-07-03 12:26:21 +000064
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000065TESTDATADIR = 'decimaltestdata'
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +000066if __name__ == '__main__':
67 file = sys.argv[0]
68else:
69 file = __file__
70testdir = os.path.dirname(file) or os.curdir
Raymond Hettinger267b8682005-03-27 10:47:39 +000071directory = testdir + os.sep + TESTDATADIR + os.sep
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000072
Raymond Hettinger267b8682005-03-27 10:47:39 +000073skip_expected = not os.path.isdir(directory)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000074
Mark Dickinson8a546532009-10-08 16:30:38 +000075# list of individual .decTest test ids that correspond to tests that
76# we're skipping for one reason or another.
Mark Dickinson247900c2010-07-08 17:23:40 +000077skipped_test_ids = set([
78 # Skip implementation-specific scaleb tests.
79 'scbx164',
80 'scbx165',
81
82 # For some operations (currently exp, ln, log10, power), the decNumber
83 # reference implementation imposes additional restrictions on the context
84 # and operands. These restrictions are not part of the specification;
85 # however, the effect of these restrictions does show up in some of the
86 # testcases. We skip testcases that violate these restrictions, since
87 # Decimal behaves differently from decNumber for these testcases so these
88 # testcases would otherwise fail.
89 'expx901',
90 'expx902',
91 'expx903',
92 'expx905',
93 'lnx901',
94 'lnx902',
95 'lnx903',
96 'lnx905',
97 'logx901',
98 'logx902',
99 'logx903',
100 'logx905',
101 'powx1183',
102 'powx1184',
103 'powx4001',
104 'powx4002',
105 'powx4003',
106 'powx4005',
107 'powx4008',
108 'powx4010',
109 'powx4012',
110 'powx4014',
111 ])
Mark Dickinson8a546532009-10-08 16:30:38 +0000112
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000113# Make sure it actually raises errors when not expected and caught in flags
114# Slower, since it runs some things several times.
115EXTENDEDERRORTEST = False
116
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000117#Map the test cases' error names to the actual errors
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000118ErrorNames = {'clamped' : Clamped,
Raymond Hettinger5aa478b2004-07-09 10:02:53 +0000119 'conversion_syntax' : InvalidOperation,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000120 'division_by_zero' : DivisionByZero,
Raymond Hettinger5aa478b2004-07-09 10:02:53 +0000121 'division_impossible' : InvalidOperation,
122 'division_undefined' : InvalidOperation,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000123 'inexact' : Inexact,
Raymond Hettinger5aa478b2004-07-09 10:02:53 +0000124 'invalid_context' : InvalidOperation,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000125 'invalid_operation' : InvalidOperation,
126 'overflow' : Overflow,
127 'rounded' : Rounded,
128 'subnormal' : Subnormal,
129 'underflow' : Underflow}
130
131
132def Nonfunction(*args):
133 """Doesn't do anything."""
134 return None
135
136RoundingDict = {'ceiling' : ROUND_CEILING, #Maps test-case names to roundings.
137 'down' : ROUND_DOWN,
138 'floor' : ROUND_FLOOR,
139 'half_down' : ROUND_HALF_DOWN,
140 'half_even' : ROUND_HALF_EVEN,
141 'half_up' : ROUND_HALF_UP,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000142 'up' : ROUND_UP,
143 '05up' : ROUND_05UP}
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000144
145# Name adapter to be able to change the Decimal and Context
146# interface without changing the test files from Cowlishaw
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000147nameAdapter = {'and':'logical_and',
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000148 'apply':'_apply',
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000149 'class':'number_class',
150 'comparesig':'compare_signal',
151 'comparetotal':'compare_total',
152 'comparetotmag':'compare_total_mag',
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000153 'copy':'copy_decimal',
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000154 'copyabs':'copy_abs',
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000155 'copynegate':'copy_negate',
156 'copysign':'copy_sign',
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000157 'divideint':'divide_int',
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000158 'invert':'logical_invert',
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000159 'iscanonical':'is_canonical',
160 'isfinite':'is_finite',
161 'isinfinite':'is_infinite',
162 'isnan':'is_nan',
163 'isnormal':'is_normal',
164 'isqnan':'is_qnan',
165 'issigned':'is_signed',
166 'issnan':'is_snan',
167 'issubnormal':'is_subnormal',
168 'iszero':'is_zero',
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000169 'maxmag':'max_mag',
170 'minmag':'min_mag',
171 'nextminus':'next_minus',
172 'nextplus':'next_plus',
173 'nexttoward':'next_toward',
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000174 'or':'logical_or',
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000175 'reduce':'normalize',
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000176 'remaindernear':'remainder_near',
177 'samequantum':'same_quantum',
178 'squareroot':'sqrt',
179 'toeng':'to_eng_string',
180 'tointegral':'to_integral_value',
181 'tointegralx':'to_integral_exact',
182 'tosci':'to_sci_string',
183 'xor':'logical_xor',
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000184 }
185
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000186# The following functions return True/False rather than a Decimal instance
187
188LOGICAL_FUNCTIONS = (
189 'is_canonical',
190 'is_finite',
191 'is_infinite',
192 'is_nan',
193 'is_normal',
194 'is_qnan',
195 'is_signed',
196 'is_snan',
197 'is_subnormal',
198 'is_zero',
199 'same_quantum',
200 )
201
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000202class DecimalTest(unittest.TestCase):
203 """Class which tests the Decimal class against the test cases.
204
205 Changed for unittest.
206 """
207 def setUp(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000208 self.context = Context()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000209 self.ignore_list = ['#']
210 # Basically, a # means return NaN InvalidOperation.
211 # Different from a sNaN in trim
212
213 self.ChangeDict = {'precision' : self.change_precision,
214 'rounding' : self.change_rounding_method,
215 'maxexponent' : self.change_max_exponent,
216 'minexponent' : self.change_min_exponent,
217 'clamp' : self.change_clamp}
218
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000219 def eval_file(self, file):
220 global skip_expected
221 if skip_expected:
Benjamin Petersone549ead2009-03-28 21:42:05 +0000222 raise unittest.SkipTest
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000223 return
Antoine Pitrou92f60ed2010-10-14 22:11:44 +0000224 with open(file) as f:
225 for line in f:
226 line = line.replace('\r\n', '').replace('\n', '')
227 #print line
228 try:
229 t = self.eval_line(line)
230 except DecimalException as exception:
Ezio Melotti13925002011-03-16 11:05:33 +0200231 #Exception raised where there shouldn't have been one.
Antoine Pitrou92f60ed2010-10-14 22:11:44 +0000232 self.fail('Exception "'+exception.__class__.__name__ + '" raised on line '+line)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000233
234 return
235
236 def eval_line(self, s):
237 if s.find(' -> ') >= 0 and s[:2] != '--' and not s.startswith(' --'):
238 s = (s.split('->')[0] + '->' +
239 s.split('->')[1].split('--')[0]).strip()
240 else:
241 s = s.split('--')[0].strip()
242
243 for ignore in self.ignore_list:
244 if s.find(ignore) >= 0:
245 #print s.split()[0], 'NotImplemented--', ignore
246 return
247 if not s:
248 return
249 elif ':' in s:
250 return self.eval_directive(s)
251 else:
252 return self.eval_equation(s)
253
254 def eval_directive(self, s):
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000255 funct, value = (x.strip().lower() for x in s.split(':'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000256 if funct == 'rounding':
257 value = RoundingDict[value]
258 else:
259 try:
260 value = int(value)
261 except ValueError:
262 pass
263
264 funct = self.ChangeDict.get(funct, Nonfunction)
265 funct(value)
266
267 def eval_equation(self, s):
268 #global DEFAULT_PRECISION
269 #print DEFAULT_PRECISION
Raymond Hettingered20ad82004-09-04 20:09:13 +0000270
271 if not TEST_ALL and random.random() < 0.90:
272 return
273
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000274 try:
275 Sides = s.split('->')
276 L = Sides[0].strip().split()
277 id = L[0]
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000278 if DEBUG:
279 print("Test ", id, end=" ")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000280 funct = L[1].lower()
281 valstemp = L[2:]
282 L = Sides[1].strip().split()
283 ans = L[0]
284 exceptions = L[1:]
285 except (TypeError, AttributeError, IndexError):
Raymond Hettingerd87ac8f2004-07-09 10:52:54 +0000286 raise InvalidOperation
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000287 def FixQuotes(val):
288 val = val.replace("''", 'SingleQuote').replace('""', 'DoubleQuote')
289 val = val.replace("'", '').replace('"', '')
290 val = val.replace('SingleQuote', "'").replace('DoubleQuote', '"')
291 return val
Mark Dickinson8a546532009-10-08 16:30:38 +0000292
293 if id in skipped_test_ids:
294 return
295
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000296 fname = nameAdapter.get(funct, funct)
297 if fname == 'rescale':
298 return
299 funct = getattr(self.context, fname)
300 vals = []
301 conglomerate = ''
302 quote = 0
303 theirexceptions = [ErrorNames[x.lower()] for x in exceptions]
304
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000305 for exception in Signals:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000306 self.context.traps[exception] = 1 #Catch these bugs...
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000307 for exception in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000308 self.context.traps[exception] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000309 for i, val in enumerate(valstemp):
310 if val.count("'") % 2 == 1:
311 quote = 1 - quote
312 if quote:
313 conglomerate = conglomerate + ' ' + val
314 continue
315 else:
316 val = conglomerate + val
317 conglomerate = ''
318 v = FixQuotes(val)
319 if fname in ('to_sci_string', 'to_eng_string'):
320 if EXTENDEDERRORTEST:
321 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000322 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000323 try:
324 funct(self.context.create_decimal(v))
325 except error:
326 pass
Guido van Rossumb940e112007-01-10 16:19:56 +0000327 except Signals as e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000328 self.fail("Raised %s in %s when %s disabled" % \
329 (e, s, error))
330 else:
331 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000332 self.context.traps[error] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000333 v = self.context.create_decimal(v)
334 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000335 v = Decimal(v, self.context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000336 vals.append(v)
337
338 ans = FixQuotes(ans)
339
340 if EXTENDEDERRORTEST and fname not in ('to_sci_string', 'to_eng_string'):
341 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000342 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000343 try:
344 funct(*vals)
345 except error:
346 pass
Guido van Rossumb940e112007-01-10 16:19:56 +0000347 except Signals as e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000348 self.fail("Raised %s in %s when %s disabled" % \
349 (e, s, error))
350 else:
351 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000352 self.context.traps[error] = 0
Mark Dickinsonc69160e2010-05-04 14:35:33 +0000353
354 # as above, but add traps cumulatively, to check precedence
355 ordered_errors = [e for e in OrderedSignals if e in theirexceptions]
356 for error in ordered_errors:
357 self.context.traps[error] = 1
358 try:
359 funct(*vals)
360 except error:
361 pass
362 except Signals as e:
363 self.fail("Raised %s in %s; expected %s" %
364 (type(e), s, error))
365 else:
366 self.fail("Did not raise %s in %s" % (error, s))
367 # reset traps
368 for error in ordered_errors:
369 self.context.traps[error] = 0
370
371
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000372 if DEBUG:
373 print("--", self.context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000374 try:
375 result = str(funct(*vals))
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000376 if fname in LOGICAL_FUNCTIONS:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000377 result = str(int(eval(result))) # 'True', 'False' -> '1', '0'
Guido van Rossumb940e112007-01-10 16:19:56 +0000378 except Signals as error:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000379 self.fail("Raised %s in %s" % (error, s))
380 except: #Catch any error long enough to state the test case.
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000381 print("ERROR:", s)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000382 raise
383
384 myexceptions = self.getexceptions()
Raymond Hettingerbf440692004-07-10 14:14:37 +0000385 self.context.clear_flags()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000386
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000387 myexceptions.sort(key=repr)
388 theirexceptions.sort(key=repr)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000389
390 self.assertEqual(result, ans,
391 'Incorrect answer for ' + s + ' -- got ' + result)
392 self.assertEqual(myexceptions, theirexceptions,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000393 'Incorrect flags set in ' + s + ' -- got ' + str(myexceptions))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000394 return
395
396 def getexceptions(self):
Raymond Hettingerf63ba432004-08-17 05:42:09 +0000397 return [e for e in Signals if self.context.flags[e]]
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000398
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000399 def change_precision(self, prec):
400 self.context.prec = prec
401 def change_rounding_method(self, rounding):
402 self.context.rounding = rounding
403 def change_min_exponent(self, exp):
404 self.context.Emin = exp
405 def change_max_exponent(self, exp):
406 self.context.Emax = exp
407 def change_clamp(self, clamp):
Mark Dickinsonb1d8e322010-05-22 18:35:36 +0000408 self.context.clamp = clamp
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000409
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000410
411
412# The following classes test the behaviour of Decimal according to PEP 327
413
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000414class DecimalExplicitConstructionTest(unittest.TestCase):
415 '''Unit tests for Explicit Construction cases of Decimal.'''
416
417 def test_explicit_empty(self):
418 self.assertEqual(Decimal(), Decimal("0"))
419
420 def test_explicit_from_None(self):
421 self.assertRaises(TypeError, Decimal, None)
422
423 def test_explicit_from_int(self):
424
425 #positive
426 d = Decimal(45)
427 self.assertEqual(str(d), '45')
428
429 #very large positive
430 d = Decimal(500000123)
431 self.assertEqual(str(d), '500000123')
432
433 #negative
434 d = Decimal(-45)
435 self.assertEqual(str(d), '-45')
436
437 #zero
438 d = Decimal(0)
439 self.assertEqual(str(d), '0')
440
441 def test_explicit_from_string(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000442
443 #empty
444 self.assertEqual(str(Decimal('')), 'NaN')
445
446 #int
447 self.assertEqual(str(Decimal('45')), '45')
448
449 #float
450 self.assertEqual(str(Decimal('45.34')), '45.34')
451
452 #engineer notation
453 self.assertEqual(str(Decimal('45e2')), '4.5E+3')
454
455 #just not a number
456 self.assertEqual(str(Decimal('ugly')), 'NaN')
457
Christian Heimesa62da1d2008-01-12 19:39:10 +0000458 #leading and trailing whitespace permitted
459 self.assertEqual(str(Decimal('1.3E4 \n')), '1.3E+4')
460 self.assertEqual(str(Decimal(' -7.89')), '-7.89')
461
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000462 def test_explicit_from_tuples(self):
463
464 #zero
465 d = Decimal( (0, (0,), 0) )
466 self.assertEqual(str(d), '0')
467
468 #int
469 d = Decimal( (1, (4, 5), 0) )
470 self.assertEqual(str(d), '-45')
471
472 #float
473 d = Decimal( (0, (4, 5, 3, 4), -2) )
474 self.assertEqual(str(d), '45.34')
475
476 #weird
477 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
478 self.assertEqual(str(d), '-4.34913534E-17')
479
480 #wrong number of items
481 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1)) )
482
483 #bad sign
484 self.assertRaises(ValueError, Decimal, (8, (4, 3, 4, 9, 1), 2) )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000485 self.assertRaises(ValueError, Decimal, (0., (4, 3, 4, 9, 1), 2) )
486 self.assertRaises(ValueError, Decimal, (Decimal(1), (4, 3, 4, 9, 1), 2))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000487
488 #bad exp
489 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 'wrong!') )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000490 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 0.) )
491 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), '1') )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000492
493 #bad coefficients
494 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, None, 1), 2) )
495 self.assertRaises(ValueError, Decimal, (1, (4, -3, 4, 9, 1), 2) )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000496 self.assertRaises(ValueError, Decimal, (1, (4, 10, 4, 9, 1), 2) )
Guido van Rossum0d3fb8a2007-11-26 23:23:18 +0000497 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 'a', 1), 2) )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000498
Antoine Pitrou503ab332010-03-30 18:56:19 +0000499 def test_explicit_from_bool(self):
500 self.assertIs(bool(Decimal(0)), False)
501 self.assertIs(bool(Decimal(1)), True)
502 self.assertEqual(Decimal(False), Decimal(0))
503 self.assertEqual(Decimal(True), Decimal(1))
504
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000505 def test_explicit_from_Decimal(self):
506
507 #positive
508 d = Decimal(45)
509 e = Decimal(d)
510 self.assertEqual(str(e), '45')
511 self.assertNotEqual(id(d), id(e))
512
513 #very large positive
514 d = Decimal(500000123)
515 e = Decimal(d)
516 self.assertEqual(str(e), '500000123')
517 self.assertNotEqual(id(d), id(e))
518
519 #negative
520 d = Decimal(-45)
521 e = Decimal(d)
522 self.assertEqual(str(e), '-45')
523 self.assertNotEqual(id(d), id(e))
524
525 #zero
526 d = Decimal(0)
527 e = Decimal(d)
528 self.assertEqual(str(e), '0')
529 self.assertNotEqual(id(d), id(e))
530
Raymond Hettinger96798592010-04-02 16:58:27 +0000531 @requires_IEEE_754
532 def test_explicit_from_float(self):
533 r = Decimal(0.1)
534 self.assertEqual(type(r), Decimal)
535 self.assertEqual(str(r),
536 '0.1000000000000000055511151231257827021181583404541015625')
537 self.assertTrue(Decimal(float('nan')).is_qnan())
538 self.assertTrue(Decimal(float('inf')).is_infinite())
539 self.assertTrue(Decimal(float('-inf')).is_infinite())
540 self.assertEqual(str(Decimal(float('nan'))),
541 str(Decimal('NaN')))
542 self.assertEqual(str(Decimal(float('inf'))),
543 str(Decimal('Infinity')))
544 self.assertEqual(str(Decimal(float('-inf'))),
545 str(Decimal('-Infinity')))
546 self.assertEqual(str(Decimal(float('-0.0'))),
547 str(Decimal('-0')))
548 for i in range(200):
549 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
550 self.assertEqual(x, float(Decimal(x))) # roundtrip
551
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000552 def test_explicit_context_create_decimal(self):
553
554 nc = copy.copy(getcontext())
555 nc.prec = 3
556
557 # empty
Raymond Hettingerfed52962004-07-14 15:41:57 +0000558 d = Decimal()
559 self.assertEqual(str(d), '0')
560 d = nc.create_decimal()
561 self.assertEqual(str(d), '0')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000562
563 # from None
564 self.assertRaises(TypeError, nc.create_decimal, None)
565
566 # from int
567 d = nc.create_decimal(456)
Ezio Melottie9615932010-01-24 19:26:24 +0000568 self.assertIsInstance(d, Decimal)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000569 self.assertEqual(nc.create_decimal(45678),
570 nc.create_decimal('457E+2'))
571
572 # from string
573 d = Decimal('456789')
574 self.assertEqual(str(d), '456789')
575 d = nc.create_decimal('456789')
576 self.assertEqual(str(d), '4.57E+5')
Christian Heimesa62da1d2008-01-12 19:39:10 +0000577 # leading and trailing whitespace should result in a NaN;
578 # spaces are already checked in Cowlishaw's test-suite, so
579 # here we just check that a trailing newline results in a NaN
580 self.assertEqual(str(nc.create_decimal('3.14\n')), 'NaN')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000581
582 # from tuples
583 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
584 self.assertEqual(str(d), '-4.34913534E-17')
585 d = nc.create_decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
586 self.assertEqual(str(d), '-4.35E-17')
587
588 # from Decimal
589 prevdec = Decimal(500000123)
590 d = Decimal(prevdec)
591 self.assertEqual(str(d), '500000123')
592 d = nc.create_decimal(prevdec)
593 self.assertEqual(str(d), '5.00E+8')
594
Mark Dickinson345adc42009-08-02 10:14:23 +0000595 def test_unicode_digits(self):
596 test_values = {
597 '\uff11': '1',
598 '\u0660.\u0660\u0663\u0667\u0662e-\u0663' : '0.0000372',
599 '-nan\u0c68\u0c6a\u0c66\u0c66' : '-NaN2400',
600 }
601 for input, expected in test_values.items():
602 self.assertEqual(str(Decimal(input)), expected)
603
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000604
605class DecimalImplicitConstructionTest(unittest.TestCase):
606 '''Unit tests for Implicit Construction cases of Decimal.'''
607
608 def test_implicit_from_None(self):
609 self.assertRaises(TypeError, eval, 'Decimal(5) + None', globals())
610
611 def test_implicit_from_int(self):
612 #normal
613 self.assertEqual(str(Decimal(5) + 45), '50')
614 #exceeding precision
615 self.assertEqual(Decimal(5) + 123456789000, Decimal(123456789000))
616
617 def test_implicit_from_string(self):
618 self.assertRaises(TypeError, eval, 'Decimal(5) + "3"', globals())
619
620 def test_implicit_from_float(self):
621 self.assertRaises(TypeError, eval, 'Decimal(5) + 2.2', globals())
622
623 def test_implicit_from_Decimal(self):
624 self.assertEqual(Decimal(5) + Decimal(45), Decimal(50))
625
Raymond Hettinger267b8682005-03-27 10:47:39 +0000626 def test_rop(self):
627 # Allow other classes to be trained to interact with Decimals
628 class E:
629 def __divmod__(self, other):
630 return 'divmod ' + str(other)
631 def __rdivmod__(self, other):
632 return str(other) + ' rdivmod'
633 def __lt__(self, other):
634 return 'lt ' + str(other)
635 def __gt__(self, other):
636 return 'gt ' + str(other)
637 def __le__(self, other):
638 return 'le ' + str(other)
639 def __ge__(self, other):
640 return 'ge ' + str(other)
641 def __eq__(self, other):
642 return 'eq ' + str(other)
643 def __ne__(self, other):
644 return 'ne ' + str(other)
645
646 self.assertEqual(divmod(E(), Decimal(10)), 'divmod 10')
647 self.assertEqual(divmod(Decimal(10), E()), '10 rdivmod')
648 self.assertEqual(eval('Decimal(10) < E()'), 'gt 10')
649 self.assertEqual(eval('Decimal(10) > E()'), 'lt 10')
650 self.assertEqual(eval('Decimal(10) <= E()'), 'ge 10')
651 self.assertEqual(eval('Decimal(10) >= E()'), 'le 10')
652 self.assertEqual(eval('Decimal(10) == E()'), 'eq 10')
653 self.assertEqual(eval('Decimal(10) != E()'), 'ne 10')
654
655 # insert operator methods and then exercise them
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000656 oplist = [
657 ('+', '__add__', '__radd__'),
658 ('-', '__sub__', '__rsub__'),
659 ('*', '__mul__', '__rmul__'),
Thomas Woutersdcc6d322006-04-21 11:30:52 +0000660 ('/', '__truediv__', '__rtruediv__'),
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000661 ('%', '__mod__', '__rmod__'),
662 ('//', '__floordiv__', '__rfloordiv__'),
663 ('**', '__pow__', '__rpow__')
664 ]
Raymond Hettinger267b8682005-03-27 10:47:39 +0000665
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000666 for sym, lop, rop in oplist:
Raymond Hettinger267b8682005-03-27 10:47:39 +0000667 setattr(E, lop, lambda self, other: 'str' + lop + str(other))
668 setattr(E, rop, lambda self, other: str(other) + rop + 'str')
669 self.assertEqual(eval('E()' + sym + 'Decimal(10)'),
670 'str' + lop + '10')
671 self.assertEqual(eval('Decimal(10)' + sym + 'E()'),
672 '10' + rop + 'str')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000673
Mark Dickinson79f52032009-03-17 23:12:51 +0000674
Christian Heimesf16baeb2008-02-29 14:57:44 +0000675class DecimalFormatTest(unittest.TestCase):
676 '''Unit tests for the format function.'''
677 def test_formatting(self):
678 # triples giving a format, a Decimal, and the expected result
679 test_values = [
680 ('e', '0E-15', '0e-15'),
681 ('e', '2.3E-15', '2.3e-15'),
682 ('e', '2.30E+2', '2.30e+2'), # preserve significant zeros
683 ('e', '2.30000E-15', '2.30000e-15'),
684 ('e', '1.23456789123456789e40', '1.23456789123456789e+40'),
685 ('e', '1.5', '1.5e+0'),
686 ('e', '0.15', '1.5e-1'),
687 ('e', '0.015', '1.5e-2'),
688 ('e', '0.0000000000015', '1.5e-12'),
689 ('e', '15.0', '1.50e+1'),
690 ('e', '-15', '-1.5e+1'),
691 ('e', '0', '0e+0'),
692 ('e', '0E1', '0e+1'),
693 ('e', '0.0', '0e-1'),
694 ('e', '0.00', '0e-2'),
695 ('.6e', '0E-15', '0.000000e-9'),
696 ('.6e', '0', '0.000000e+6'),
697 ('.6e', '9.999999', '9.999999e+0'),
698 ('.6e', '9.9999999', '1.000000e+1'),
699 ('.6e', '-1.23e5', '-1.230000e+5'),
700 ('.6e', '1.23456789e-3', '1.234568e-3'),
701 ('f', '0', '0'),
702 ('f', '0.0', '0.0'),
703 ('f', '0E-2', '0.00'),
704 ('f', '0.00E-8', '0.0000000000'),
705 ('f', '0E1', '0'), # loses exponent information
706 ('f', '3.2E1', '32'),
707 ('f', '3.2E2', '320'),
708 ('f', '3.20E2', '320'),
709 ('f', '3.200E2', '320.0'),
710 ('f', '3.2E-6', '0.0000032'),
711 ('.6f', '0E-15', '0.000000'), # all zeros treated equally
712 ('.6f', '0E1', '0.000000'),
713 ('.6f', '0', '0.000000'),
714 ('.0f', '0', '0'), # no decimal point
715 ('.0f', '0e-2', '0'),
716 ('.0f', '3.14159265', '3'),
717 ('.1f', '3.14159265', '3.1'),
718 ('.4f', '3.14159265', '3.1416'),
719 ('.6f', '3.14159265', '3.141593'),
720 ('.7f', '3.14159265', '3.1415926'), # round-half-even!
721 ('.8f', '3.14159265', '3.14159265'),
722 ('.9f', '3.14159265', '3.141592650'),
723
724 ('g', '0', '0'),
725 ('g', '0.0', '0.0'),
726 ('g', '0E1', '0e+1'),
727 ('G', '0E1', '0E+1'),
728 ('g', '0E-5', '0.00000'),
729 ('g', '0E-6', '0.000000'),
730 ('g', '0E-7', '0e-7'),
731 ('g', '-0E2', '-0e+2'),
732 ('.0g', '3.14159265', '3'), # 0 sig fig -> 1 sig fig
733 ('.1g', '3.14159265', '3'),
734 ('.2g', '3.14159265', '3.1'),
735 ('.5g', '3.14159265', '3.1416'),
736 ('.7g', '3.14159265', '3.141593'),
737 ('.8g', '3.14159265', '3.1415926'), # round-half-even!
738 ('.9g', '3.14159265', '3.14159265'),
739 ('.10g', '3.14159265', '3.14159265'), # don't pad
740
741 ('%', '0E1', '0%'),
742 ('%', '0E0', '0%'),
743 ('%', '0E-1', '0%'),
744 ('%', '0E-2', '0%'),
745 ('%', '0E-3', '0.0%'),
746 ('%', '0E-4', '0.00%'),
747
748 ('.3%', '0', '0.000%'), # all zeros treated equally
749 ('.3%', '0E10', '0.000%'),
750 ('.3%', '0E-10', '0.000%'),
751 ('.3%', '2.34', '234.000%'),
752 ('.3%', '1.234567', '123.457%'),
753 ('.0%', '1.23', '123%'),
754
755 ('e', 'NaN', 'NaN'),
756 ('f', '-NaN123', '-NaN123'),
757 ('+g', 'NaN456', '+NaN456'),
758 ('.3e', 'Inf', 'Infinity'),
759 ('.16f', '-Inf', '-Infinity'),
760 ('.0g', '-sNaN', '-sNaN'),
761
762 ('', '1.00', '1.00'),
Mark Dickinsonad416342009-03-17 18:10:15 +0000763
Mark Dickinson79f52032009-03-17 23:12:51 +0000764 # test alignment and padding
Mark Dickinson46ab5d02009-09-08 20:22:46 +0000765 ('6', '123', ' 123'),
Mark Dickinsonad416342009-03-17 18:10:15 +0000766 ('<6', '123', '123 '),
767 ('>6', '123', ' 123'),
768 ('^6', '123', ' 123 '),
769 ('=+6', '123', '+ 123'),
Mark Dickinson79f52032009-03-17 23:12:51 +0000770 ('#<10', 'NaN', 'NaN#######'),
771 ('#<10', '-4.3', '-4.3######'),
772 ('#<+10', '0.0130', '+0.0130###'),
773 ('#< 10', '0.0130', ' 0.0130###'),
774 ('@>10', '-Inf', '@-Infinity'),
775 ('#>5', '-Inf', '-Infinity'),
776 ('?^5', '123', '?123?'),
777 ('%^6', '123', '%123%%'),
778 (' ^6', '-45.6', '-45.6 '),
779 ('/=10', '-45.6', '-/////45.6'),
780 ('/=+10', '45.6', '+/////45.6'),
781 ('/= 10', '45.6', ' /////45.6'),
782
783 # thousands separator
784 (',', '1234567', '1,234,567'),
785 (',', '123456', '123,456'),
786 (',', '12345', '12,345'),
787 (',', '1234', '1,234'),
788 (',', '123', '123'),
789 (',', '12', '12'),
790 (',', '1', '1'),
791 (',', '0', '0'),
792 (',', '-1234567', '-1,234,567'),
793 (',', '-123456', '-123,456'),
794 ('7,', '123456', '123,456'),
Mark Dickinson46ab5d02009-09-08 20:22:46 +0000795 ('8,', '123456', ' 123,456'),
Mark Dickinson79f52032009-03-17 23:12:51 +0000796 ('08,', '123456', '0,123,456'), # special case: extra 0 needed
797 ('+08,', '123456', '+123,456'), # but not if there's a sign
798 (' 08,', '123456', ' 123,456'),
799 ('08,', '-123456', '-123,456'),
800 ('+09,', '123456', '+0,123,456'),
801 # ... with fractional part...
802 ('07,', '1234.56', '1,234.56'),
803 ('08,', '1234.56', '1,234.56'),
804 ('09,', '1234.56', '01,234.56'),
805 ('010,', '1234.56', '001,234.56'),
806 ('011,', '1234.56', '0,001,234.56'),
807 ('012,', '1234.56', '0,001,234.56'),
808 ('08,.1f', '1234.5', '01,234.5'),
809 # no thousands separators in fraction part
810 (',', '1.23456789', '1.23456789'),
811 (',%', '123.456789', '12,345.6789%'),
812 (',e', '123456', '1.23456e+5'),
813 (',E', '123456', '1.23456E+5'),
Mark Dickinson7718d2b2009-09-07 16:21:56 +0000814
815 # issue 6850
816 ('a=-7.0', '0.12345', 'aaaa0.1'),
Eric Smith984bb582010-11-25 16:08:06 +0000817
818 # Issue 7094: Alternate formatting (specified by #)
819 ('.0e', '1.0', '1e+0'),
820 ('#.0e', '1.0', '1.e+0'),
821 ('.0f', '1.0', '1'),
822 ('#.0f', '1.0', '1.'),
823 ('g', '1.1', '1.1'),
824 ('#g', '1.1', '1.1'),
825 ('.0g', '1', '1'),
826 ('#.0g', '1', '1.'),
827 ('.0%', '1.0', '100%'),
828 ('#.0%', '1.0', '100.%'),
Christian Heimesf16baeb2008-02-29 14:57:44 +0000829 ]
830 for fmt, d, result in test_values:
831 self.assertEqual(format(Decimal(d), fmt), result)
832
Mark Dickinson79f52032009-03-17 23:12:51 +0000833 def test_n_format(self):
834 try:
835 from locale import CHAR_MAX
836 except ImportError:
837 return
838
839 # Set up some localeconv-like dictionaries
840 en_US = {
841 'decimal_point' : '.',
842 'grouping' : [3, 3, 0],
843 'thousands_sep': ','
844 }
845
846 fr_FR = {
847 'decimal_point' : ',',
848 'grouping' : [CHAR_MAX],
849 'thousands_sep' : ''
850 }
851
852 ru_RU = {
853 'decimal_point' : ',',
854 'grouping' : [3, 3, 0],
855 'thousands_sep' : ' '
856 }
857
858 crazy = {
859 'decimal_point' : '&',
860 'grouping' : [1, 4, 2, CHAR_MAX],
861 'thousands_sep' : '-'
862 }
863
864
865 def get_fmt(x, locale, fmt='n'):
866 return Decimal.__format__(Decimal(x), fmt, _localeconv=locale)
867
868 self.assertEqual(get_fmt(Decimal('12.7'), en_US), '12.7')
869 self.assertEqual(get_fmt(Decimal('12.7'), fr_FR), '12,7')
870 self.assertEqual(get_fmt(Decimal('12.7'), ru_RU), '12,7')
871 self.assertEqual(get_fmt(Decimal('12.7'), crazy), '1-2&7')
872
873 self.assertEqual(get_fmt(123456789, en_US), '123,456,789')
874 self.assertEqual(get_fmt(123456789, fr_FR), '123456789')
875 self.assertEqual(get_fmt(123456789, ru_RU), '123 456 789')
876 self.assertEqual(get_fmt(1234567890123, crazy), '123456-78-9012-3')
877
878 self.assertEqual(get_fmt(123456789, en_US, '.6n'), '1.23457e+8')
879 self.assertEqual(get_fmt(123456789, fr_FR, '.6n'), '1,23457e+8')
880 self.assertEqual(get_fmt(123456789, ru_RU, '.6n'), '1,23457e+8')
881 self.assertEqual(get_fmt(123456789, crazy, '.6n'), '1&23457e+8')
882
Mark Dickinson7303b592009-03-18 08:25:36 +0000883 # zero padding
884 self.assertEqual(get_fmt(1234, fr_FR, '03n'), '1234')
885 self.assertEqual(get_fmt(1234, fr_FR, '04n'), '1234')
886 self.assertEqual(get_fmt(1234, fr_FR, '05n'), '01234')
887 self.assertEqual(get_fmt(1234, fr_FR, '06n'), '001234')
888
889 self.assertEqual(get_fmt(12345, en_US, '05n'), '12,345')
890 self.assertEqual(get_fmt(12345, en_US, '06n'), '12,345')
891 self.assertEqual(get_fmt(12345, en_US, '07n'), '012,345')
892 self.assertEqual(get_fmt(12345, en_US, '08n'), '0,012,345')
893 self.assertEqual(get_fmt(12345, en_US, '09n'), '0,012,345')
894 self.assertEqual(get_fmt(12345, en_US, '010n'), '00,012,345')
895
896 self.assertEqual(get_fmt(123456, crazy, '06n'), '1-2345-6')
897 self.assertEqual(get_fmt(123456, crazy, '07n'), '1-2345-6')
898 self.assertEqual(get_fmt(123456, crazy, '08n'), '1-2345-6')
899 self.assertEqual(get_fmt(123456, crazy, '09n'), '01-2345-6')
900 self.assertEqual(get_fmt(123456, crazy, '010n'), '0-01-2345-6')
901 self.assertEqual(get_fmt(123456, crazy, '011n'), '0-01-2345-6')
902 self.assertEqual(get_fmt(123456, crazy, '012n'), '00-01-2345-6')
903 self.assertEqual(get_fmt(123456, crazy, '013n'), '000-01-2345-6')
904
Mark Dickinson79f52032009-03-17 23:12:51 +0000905
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000906class DecimalArithmeticOperatorsTest(unittest.TestCase):
907 '''Unit tests for all arithmetic operators, binary and unary.'''
908
909 def test_addition(self):
910
911 d1 = Decimal('-11.1')
912 d2 = Decimal('22.2')
913
914 #two Decimals
915 self.assertEqual(d1+d2, Decimal('11.1'))
916 self.assertEqual(d2+d1, Decimal('11.1'))
917
918 #with other type, left
919 c = d1 + 5
920 self.assertEqual(c, Decimal('-6.1'))
921 self.assertEqual(type(c), type(d1))
922
923 #with other type, right
924 c = 5 + d1
925 self.assertEqual(c, Decimal('-6.1'))
926 self.assertEqual(type(c), type(d1))
927
928 #inline with decimal
929 d1 += d2
930 self.assertEqual(d1, Decimal('11.1'))
931
932 #inline with other type
933 d1 += 5
934 self.assertEqual(d1, Decimal('16.1'))
935
936 def test_subtraction(self):
937
938 d1 = Decimal('-11.1')
939 d2 = Decimal('22.2')
940
941 #two Decimals
942 self.assertEqual(d1-d2, Decimal('-33.3'))
943 self.assertEqual(d2-d1, Decimal('33.3'))
944
945 #with other type, left
946 c = d1 - 5
947 self.assertEqual(c, Decimal('-16.1'))
948 self.assertEqual(type(c), type(d1))
949
950 #with other type, right
951 c = 5 - d1
952 self.assertEqual(c, Decimal('16.1'))
953 self.assertEqual(type(c), type(d1))
954
955 #inline with decimal
956 d1 -= d2
957 self.assertEqual(d1, Decimal('-33.3'))
958
959 #inline with other type
960 d1 -= 5
961 self.assertEqual(d1, Decimal('-38.3'))
962
963 def test_multiplication(self):
964
965 d1 = Decimal('-5')
966 d2 = Decimal('3')
967
968 #two Decimals
969 self.assertEqual(d1*d2, Decimal('-15'))
970 self.assertEqual(d2*d1, Decimal('-15'))
971
972 #with other type, left
973 c = d1 * 5
974 self.assertEqual(c, Decimal('-25'))
975 self.assertEqual(type(c), type(d1))
976
977 #with other type, right
978 c = 5 * d1
979 self.assertEqual(c, Decimal('-25'))
980 self.assertEqual(type(c), type(d1))
981
982 #inline with decimal
983 d1 *= d2
984 self.assertEqual(d1, Decimal('-15'))
985
986 #inline with other type
987 d1 *= 5
988 self.assertEqual(d1, Decimal('-75'))
989
990 def test_division(self):
991
992 d1 = Decimal('-5')
993 d2 = Decimal('2')
994
995 #two Decimals
996 self.assertEqual(d1/d2, Decimal('-2.5'))
997 self.assertEqual(d2/d1, Decimal('-0.4'))
998
999 #with other type, left
1000 c = d1 / 4
1001 self.assertEqual(c, Decimal('-1.25'))
1002 self.assertEqual(type(c), type(d1))
1003
1004 #with other type, right
1005 c = 4 / d1
1006 self.assertEqual(c, Decimal('-0.8'))
1007 self.assertEqual(type(c), type(d1))
1008
1009 #inline with decimal
1010 d1 /= d2
1011 self.assertEqual(d1, Decimal('-2.5'))
1012
1013 #inline with other type
1014 d1 /= 4
1015 self.assertEqual(d1, Decimal('-0.625'))
1016
1017 def test_floor_division(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001018
1019 d1 = Decimal('5')
1020 d2 = Decimal('2')
1021
1022 #two Decimals
1023 self.assertEqual(d1//d2, Decimal('2'))
1024 self.assertEqual(d2//d1, Decimal('0'))
1025
1026 #with other type, left
1027 c = d1 // 4
1028 self.assertEqual(c, Decimal('1'))
1029 self.assertEqual(type(c), type(d1))
1030
1031 #with other type, right
1032 c = 7 // d1
1033 self.assertEqual(c, Decimal('1'))
1034 self.assertEqual(type(c), type(d1))
1035
1036 #inline with decimal
1037 d1 //= d2
1038 self.assertEqual(d1, Decimal('2'))
1039
1040 #inline with other type
1041 d1 //= 2
1042 self.assertEqual(d1, Decimal('1'))
1043
1044 def test_powering(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001045
1046 d1 = Decimal('5')
1047 d2 = Decimal('2')
1048
1049 #two Decimals
1050 self.assertEqual(d1**d2, Decimal('25'))
1051 self.assertEqual(d2**d1, Decimal('32'))
1052
1053 #with other type, left
1054 c = d1 ** 4
1055 self.assertEqual(c, Decimal('625'))
1056 self.assertEqual(type(c), type(d1))
1057
1058 #with other type, right
1059 c = 7 ** d1
1060 self.assertEqual(c, Decimal('16807'))
1061 self.assertEqual(type(c), type(d1))
1062
1063 #inline with decimal
1064 d1 **= d2
1065 self.assertEqual(d1, Decimal('25'))
1066
1067 #inline with other type
1068 d1 **= 4
1069 self.assertEqual(d1, Decimal('390625'))
1070
1071 def test_module(self):
1072
1073 d1 = Decimal('5')
1074 d2 = Decimal('2')
1075
1076 #two Decimals
1077 self.assertEqual(d1%d2, Decimal('1'))
1078 self.assertEqual(d2%d1, Decimal('2'))
1079
1080 #with other type, left
1081 c = d1 % 4
1082 self.assertEqual(c, Decimal('1'))
1083 self.assertEqual(type(c), type(d1))
1084
1085 #with other type, right
1086 c = 7 % d1
1087 self.assertEqual(c, Decimal('2'))
1088 self.assertEqual(type(c), type(d1))
1089
1090 #inline with decimal
1091 d1 %= d2
1092 self.assertEqual(d1, Decimal('1'))
1093
1094 #inline with other type
1095 d1 %= 4
1096 self.assertEqual(d1, Decimal('1'))
1097
1098 def test_floor_div_module(self):
1099
1100 d1 = Decimal('5')
1101 d2 = Decimal('2')
1102
1103 #two Decimals
1104 (p, q) = divmod(d1, d2)
1105 self.assertEqual(p, Decimal('2'))
1106 self.assertEqual(q, Decimal('1'))
1107 self.assertEqual(type(p), type(d1))
1108 self.assertEqual(type(q), type(d1))
1109
1110 #with other type, left
1111 (p, q) = divmod(d1, 4)
1112 self.assertEqual(p, Decimal('1'))
1113 self.assertEqual(q, Decimal('1'))
1114 self.assertEqual(type(p), type(d1))
1115 self.assertEqual(type(q), type(d1))
1116
1117 #with other type, right
1118 (p, q) = divmod(7, d1)
1119 self.assertEqual(p, Decimal('1'))
1120 self.assertEqual(q, Decimal('2'))
1121 self.assertEqual(type(p), type(d1))
1122 self.assertEqual(type(q), type(d1))
1123
1124 def test_unary_operators(self):
1125 self.assertEqual(+Decimal(45), Decimal(+45)) # +
1126 self.assertEqual(-Decimal(45), Decimal(-45)) # -
1127 self.assertEqual(abs(Decimal(45)), abs(Decimal(-45))) # abs
1128
Christian Heimes77c02eb2008-02-09 02:18:51 +00001129 def test_nan_comparisons(self):
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001130 # comparisons involving signaling nans signal InvalidOperation
1131
1132 # order comparisons (<, <=, >, >=) involving only quiet nans
1133 # also signal InvalidOperation
1134
1135 # equality comparisons (==, !=) involving only quiet nans
1136 # don't signal, but return False or True respectively.
1137
Christian Heimes77c02eb2008-02-09 02:18:51 +00001138 n = Decimal('NaN')
1139 s = Decimal('sNaN')
1140 i = Decimal('Inf')
1141 f = Decimal('2')
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001142
1143 qnan_pairs = (n, n), (n, i), (i, n), (n, f), (f, n)
1144 snan_pairs = (s, n), (n, s), (s, i), (i, s), (s, f), (f, s), (s, s)
1145 order_ops = operator.lt, operator.le, operator.gt, operator.ge
1146 equality_ops = operator.eq, operator.ne
1147
1148 # results when InvalidOperation is not trapped
1149 for x, y in qnan_pairs + snan_pairs:
1150 for op in order_ops + equality_ops:
1151 got = op(x, y)
1152 expected = True if op is operator.ne else False
1153 self.assertIs(expected, got,
1154 "expected {0!r} for operator.{1}({2!r}, {3!r}); "
1155 "got {4!r}".format(
1156 expected, op.__name__, x, y, got))
1157
1158 # repeat the above, but this time trap the InvalidOperation
1159 with localcontext() as ctx:
1160 ctx.traps[InvalidOperation] = 1
1161
1162 for x, y in qnan_pairs:
1163 for op in equality_ops:
1164 got = op(x, y)
1165 expected = True if op is operator.ne else False
1166 self.assertIs(expected, got,
1167 "expected {0!r} for "
1168 "operator.{1}({2!r}, {3!r}); "
1169 "got {4!r}".format(
1170 expected, op.__name__, x, y, got))
1171
1172 for x, y in snan_pairs:
1173 for op in equality_ops:
1174 self.assertRaises(InvalidOperation, operator.eq, x, y)
1175 self.assertRaises(InvalidOperation, operator.ne, x, y)
1176
1177 for x, y in qnan_pairs + snan_pairs:
1178 for op in order_ops:
1179 self.assertRaises(InvalidOperation, op, x, y)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001180
Mark Dickinson84230a12010-02-18 14:49:50 +00001181 def test_copy_sign(self):
1182 d = Decimal(1).copy_sign(Decimal(-2))
1183
1184 self.assertEqual(Decimal(1).copy_sign(-2), d)
1185 self.assertRaises(TypeError, Decimal(1).copy_sign, '-2')
1186
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001187# The following are two functions used to test threading in the next class
1188
1189def thfunc1(cls):
1190 d1 = Decimal(1)
1191 d3 = Decimal(3)
Christian Heimesfe337bf2008-03-23 21:54:12 +00001192 test1 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001193 cls.synchro.wait()
Christian Heimesfe337bf2008-03-23 21:54:12 +00001194 test2 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001195 cls.finish1.set()
Christian Heimesfe337bf2008-03-23 21:54:12 +00001196
Christian Heimes81ee3ef2008-05-04 22:42:01 +00001197 cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
1198 cls.assertEqual(test2, Decimal('0.3333333333333333333333333333'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001199 return
1200
1201def thfunc2(cls):
1202 d1 = Decimal(1)
1203 d3 = Decimal(3)
Christian Heimesfe337bf2008-03-23 21:54:12 +00001204 test1 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001205 thiscontext = getcontext()
1206 thiscontext.prec = 18
Christian Heimesfe337bf2008-03-23 21:54:12 +00001207 test2 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001208 cls.synchro.set()
1209 cls.finish2.set()
Christian Heimesfe337bf2008-03-23 21:54:12 +00001210
Christian Heimes81ee3ef2008-05-04 22:42:01 +00001211 cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
Christian Heimesfe337bf2008-03-23 21:54:12 +00001212 cls.assertEqual(test2, Decimal('0.333333333333333333'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001213 return
1214
1215
1216class DecimalUseOfContextTest(unittest.TestCase):
1217 '''Unit tests for Use of Context cases in Decimal.'''
1218
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001219 try:
1220 import threading
1221 except ImportError:
1222 threading = None
1223
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001224 # Take care executing this test from IDLE, there's an issue in threading
1225 # that hangs IDLE and I couldn't find it
1226
1227 def test_threading(self):
1228 #Test the "threading isolation" of a Context.
1229
1230 self.synchro = threading.Event()
1231 self.finish1 = threading.Event()
1232 self.finish2 = threading.Event()
1233
1234 th1 = threading.Thread(target=thfunc1, args=(self,))
1235 th2 = threading.Thread(target=thfunc2, args=(self,))
1236
1237 th1.start()
1238 th2.start()
1239
1240 self.finish1.wait()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001241 self.finish2.wait()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001242 return
1243
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001244 if threading is None:
1245 del test_threading
1246
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001247
1248class DecimalUsabilityTest(unittest.TestCase):
1249 '''Unit tests for Usability cases of Decimal.'''
1250
1251 def test_comparison_operators(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001252
1253 da = Decimal('23.42')
1254 db = Decimal('23.42')
1255 dc = Decimal('45')
1256
1257 #two Decimals
Ezio Melotti6607d512010-04-03 14:59:49 +00001258 self.assertGreater(dc, da)
1259 self.assertGreaterEqual(dc, da)
1260 self.assertLess(da, dc)
1261 self.assertLessEqual(da, dc)
Guido van Rossume61fd5b2007-07-11 12:20:59 +00001262 self.assertEqual(da, db)
Ezio Melotti6607d512010-04-03 14:59:49 +00001263 self.assertNotEqual(da, dc)
1264 self.assertLessEqual(da, db)
1265 self.assertGreaterEqual(da, db)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001266
1267 #a Decimal and an int
Ezio Melotti6607d512010-04-03 14:59:49 +00001268 self.assertGreater(dc, 23)
1269 self.assertLess(23, dc)
Guido van Rossume61fd5b2007-07-11 12:20:59 +00001270 self.assertEqual(dc, 45)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001271
1272 #a Decimal and uncomparable
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001273 self.assertNotEqual(da, 'ugly')
1274 self.assertNotEqual(da, 32.7)
1275 self.assertNotEqual(da, object())
1276 self.assertNotEqual(da, object)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001277
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001278 # sortable
Guido van Rossumc1f779c2007-07-03 08:25:58 +00001279 a = list(map(Decimal, range(100)))
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001280 b = a[:]
1281 random.shuffle(a)
1282 a.sort()
1283 self.assertEqual(a, b)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001284
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001285 def test_decimal_float_comparison(self):
1286 da = Decimal('0.25')
1287 db = Decimal('3.0')
Ezio Melotti6607d512010-04-03 14:59:49 +00001288 self.assertLess(da, 3.0)
1289 self.assertLessEqual(da, 3.0)
1290 self.assertGreater(db, 0.25)
1291 self.assertGreaterEqual(db, 0.25)
1292 self.assertNotEqual(da, 1.5)
1293 self.assertEqual(da, 0.25)
1294 self.assertGreater(3.0, da)
1295 self.assertGreaterEqual(3.0, da)
1296 self.assertLess(0.25, db)
1297 self.assertLessEqual(0.25, db)
1298 self.assertNotEqual(0.25, db)
1299 self.assertEqual(3.0, db)
1300 self.assertNotEqual(0.1, Decimal('0.1'))
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001301
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001302 def test_copy_and_deepcopy_methods(self):
1303 d = Decimal('43.24')
1304 c = copy.copy(d)
1305 self.assertEqual(id(c), id(d))
1306 dc = copy.deepcopy(d)
1307 self.assertEqual(id(dc), id(d))
1308
1309 def test_hash_method(self):
Stefan Krahdc817b22010-11-17 11:16:34 +00001310 def hashit(d):
1311 a = hash(d)
1312 b = d.__hash__()
1313 self.assertEqual(a, b)
1314 return a
1315
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001316 #just that it's hashable
Stefan Krahdc817b22010-11-17 11:16:34 +00001317 hashit(Decimal(23))
1318 hashit(Decimal('Infinity'))
1319 hashit(Decimal('-Infinity'))
1320 hashit(Decimal('nan123'))
1321 hashit(Decimal('-NaN'))
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001322
1323 test_values = [Decimal(sign*(2**m + n))
1324 for m in [0, 14, 15, 16, 17, 30, 31,
Stefan Krahdc817b22010-11-17 11:16:34 +00001325 32, 33, 61, 62, 63, 64, 65, 66]
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001326 for n in range(-10, 10)
1327 for sign in [-1, 1]]
1328 test_values.extend([
Stefan Krahdc817b22010-11-17 11:16:34 +00001329 Decimal("-1"), # ==> -2
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001330 Decimal("-0"), # zeros
1331 Decimal("0.00"),
1332 Decimal("-0.000"),
1333 Decimal("0E10"),
1334 Decimal("-0E12"),
1335 Decimal("10.0"), # negative exponent
1336 Decimal("-23.00000"),
1337 Decimal("1230E100"), # positive exponent
1338 Decimal("-4.5678E50"),
1339 # a value for which hash(n) != hash(n % (2**64-1))
1340 # in Python pre-2.6
1341 Decimal(2**64 + 2**32 - 1),
1342 # selection of values which fail with the old (before
1343 # version 2.6) long.__hash__
1344 Decimal("1.634E100"),
1345 Decimal("90.697E100"),
1346 Decimal("188.83E100"),
1347 Decimal("1652.9E100"),
1348 Decimal("56531E100"),
1349 ])
1350
1351 # check that hash(d) == hash(int(d)) for integral values
1352 for value in test_values:
Stefan Krahdc817b22010-11-17 11:16:34 +00001353 self.assertEqual(hashit(value), hashit(int(value)))
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001354
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001355 #the same hash that to an int
Stefan Krahdc817b22010-11-17 11:16:34 +00001356 self.assertEqual(hashit(Decimal(23)), hashit(23))
Raymond Hettingerd325c4b2010-11-21 04:08:28 +00001357 self.assertRaises(TypeError, hash, Decimal('sNaN'))
Stefan Krahdc817b22010-11-17 11:16:34 +00001358 self.assertTrue(hashit(Decimal('Inf')))
1359 self.assertTrue(hashit(Decimal('-Inf')))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001360
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001361 # check that the hashes of a Decimal float match when they
1362 # represent exactly the same values
1363 test_strings = ['inf', '-Inf', '0.0', '-.0e1',
1364 '34.0', '2.5', '112390.625', '-0.515625']
1365 for s in test_strings:
1366 f = float(s)
1367 d = Decimal(s)
Stefan Krahdc817b22010-11-17 11:16:34 +00001368 self.assertEqual(hashit(f), hashit(d))
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001369
Christian Heimes2380ac72008-01-09 00:17:24 +00001370 # check that the value of the hash doesn't depend on the
1371 # current context (issue #1757)
1372 c = getcontext()
1373 old_precision = c.prec
1374 x = Decimal("123456789.1")
1375
1376 c.prec = 6
Stefan Krahdc817b22010-11-17 11:16:34 +00001377 h1 = hashit(x)
Christian Heimes2380ac72008-01-09 00:17:24 +00001378 c.prec = 10
Stefan Krahdc817b22010-11-17 11:16:34 +00001379 h2 = hashit(x)
Christian Heimes2380ac72008-01-09 00:17:24 +00001380 c.prec = 16
Stefan Krahdc817b22010-11-17 11:16:34 +00001381 h3 = hashit(x)
Christian Heimes2380ac72008-01-09 00:17:24 +00001382
1383 self.assertEqual(h1, h2)
1384 self.assertEqual(h1, h3)
1385 c.prec = old_precision
1386
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001387 def test_min_and_max_methods(self):
1388
1389 d1 = Decimal('15.32')
1390 d2 = Decimal('28.5')
1391 l1 = 15
1392 l2 = 28
1393
1394 #between Decimals
Ezio Melotti6607d512010-04-03 14:59:49 +00001395 self.assertIs(min(d1,d2), d1)
1396 self.assertIs(min(d2,d1), d1)
1397 self.assertIs(max(d1,d2), d2)
1398 self.assertIs(max(d2,d1), d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001399
1400 #between Decimal and long
Ezio Melotti6607d512010-04-03 14:59:49 +00001401 self.assertIs(min(d1,l2), d1)
1402 self.assertIs(min(l2,d1), d1)
1403 self.assertIs(max(l1,d2), d2)
1404 self.assertIs(max(d2,l1), d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001405
1406 def test_as_nonzero(self):
1407 #as false
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001408 self.assertFalse(Decimal(0))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001409 #as true
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001410 self.assertTrue(Decimal('0.372'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001411
1412 def test_tostring_methods(self):
1413 #Test str and repr methods.
1414
1415 d = Decimal('15.32')
1416 self.assertEqual(str(d), '15.32') # str
Christian Heimes68f5fbe2008-02-14 08:27:37 +00001417 self.assertEqual(repr(d), "Decimal('15.32')") # repr
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001418
1419 def test_tonum_methods(self):
Mark Dickinson5c2db372009-12-05 20:28:34 +00001420 #Test float and int methods.
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001421
1422 d1 = Decimal('66')
1423 d2 = Decimal('15.32')
1424
1425 #int
1426 self.assertEqual(int(d1), 66)
1427 self.assertEqual(int(d2), 15)
1428
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001429 #float
1430 self.assertEqual(float(d1), 66)
1431 self.assertEqual(float(d2), 15.32)
1432
Mark Dickinsonb27406c2008-05-09 13:42:33 +00001433 #floor
1434 test_pairs = [
1435 ('123.00', 123),
1436 ('3.2', 3),
1437 ('3.54', 3),
1438 ('3.899', 3),
1439 ('-2.3', -3),
1440 ('-11.0', -11),
1441 ('0.0', 0),
1442 ('-0E3', 0),
1443 ]
1444 for d, i in test_pairs:
1445 self.assertEqual(math.floor(Decimal(d)), i)
1446 self.assertRaises(ValueError, math.floor, Decimal('-NaN'))
1447 self.assertRaises(ValueError, math.floor, Decimal('sNaN'))
1448 self.assertRaises(ValueError, math.floor, Decimal('NaN123'))
1449 self.assertRaises(OverflowError, math.floor, Decimal('Inf'))
1450 self.assertRaises(OverflowError, math.floor, Decimal('-Inf'))
1451
1452 #ceiling
1453 test_pairs = [
1454 ('123.00', 123),
1455 ('3.2', 4),
1456 ('3.54', 4),
1457 ('3.899', 4),
1458 ('-2.3', -2),
1459 ('-11.0', -11),
1460 ('0.0', 0),
1461 ('-0E3', 0),
1462 ]
1463 for d, i in test_pairs:
1464 self.assertEqual(math.ceil(Decimal(d)), i)
1465 self.assertRaises(ValueError, math.ceil, Decimal('-NaN'))
1466 self.assertRaises(ValueError, math.ceil, Decimal('sNaN'))
1467 self.assertRaises(ValueError, math.ceil, Decimal('NaN123'))
1468 self.assertRaises(OverflowError, math.ceil, Decimal('Inf'))
1469 self.assertRaises(OverflowError, math.ceil, Decimal('-Inf'))
1470
1471 #round, single argument
1472 test_pairs = [
1473 ('123.00', 123),
1474 ('3.2', 3),
1475 ('3.54', 4),
1476 ('3.899', 4),
1477 ('-2.3', -2),
1478 ('-11.0', -11),
1479 ('0.0', 0),
1480 ('-0E3', 0),
1481 ('-3.5', -4),
1482 ('-2.5', -2),
1483 ('-1.5', -2),
1484 ('-0.5', 0),
1485 ('0.5', 0),
1486 ('1.5', 2),
1487 ('2.5', 2),
1488 ('3.5', 4),
1489 ]
1490 for d, i in test_pairs:
1491 self.assertEqual(round(Decimal(d)), i)
1492 self.assertRaises(ValueError, round, Decimal('-NaN'))
1493 self.assertRaises(ValueError, round, Decimal('sNaN'))
1494 self.assertRaises(ValueError, round, Decimal('NaN123'))
1495 self.assertRaises(OverflowError, round, Decimal('Inf'))
1496 self.assertRaises(OverflowError, round, Decimal('-Inf'))
1497
1498 #round, two arguments; this is essentially equivalent
1499 #to quantize, which is already extensively tested
1500 test_triples = [
1501 ('123.456', -4, '0E+4'),
1502 ('123.456', -3, '0E+3'),
1503 ('123.456', -2, '1E+2'),
1504 ('123.456', -1, '1.2E+2'),
1505 ('123.456', 0, '123'),
1506 ('123.456', 1, '123.5'),
1507 ('123.456', 2, '123.46'),
1508 ('123.456', 3, '123.456'),
1509 ('123.456', 4, '123.4560'),
1510 ('123.455', 2, '123.46'),
1511 ('123.445', 2, '123.44'),
1512 ('Inf', 4, 'NaN'),
1513 ('-Inf', -23, 'NaN'),
1514 ('sNaN314', 3, 'NaN314'),
1515 ]
1516 for d, n, r in test_triples:
1517 self.assertEqual(str(round(Decimal(d), n)), r)
1518
1519
1520
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001521 def test_eval_round_trip(self):
1522
1523 #with zero
1524 d = Decimal( (0, (0,), 0) )
1525 self.assertEqual(d, eval(repr(d)))
1526
1527 #int
1528 d = Decimal( (1, (4, 5), 0) )
1529 self.assertEqual(d, eval(repr(d)))
1530
1531 #float
1532 d = Decimal( (0, (4, 5, 3, 4), -2) )
1533 self.assertEqual(d, eval(repr(d)))
1534
1535 #weird
1536 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1537 self.assertEqual(d, eval(repr(d)))
1538
1539 def test_as_tuple(self):
1540
1541 #with zero
1542 d = Decimal(0)
1543 self.assertEqual(d.as_tuple(), (0, (0,), 0) )
1544
1545 #int
1546 d = Decimal(-45)
1547 self.assertEqual(d.as_tuple(), (1, (4, 5), 0) )
1548
1549 #complicated string
1550 d = Decimal("-4.34913534E-17")
1551 self.assertEqual(d.as_tuple(), (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1552
1553 #inf
1554 d = Decimal("Infinity")
1555 self.assertEqual(d.as_tuple(), (0, (0,), 'F') )
1556
Guido van Rossum8ce8a782007-11-01 19:42:39 +00001557 #leading zeros in coefficient should be stripped
1558 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), -2) )
1559 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), -2) )
1560 d = Decimal( (1, (0, 0, 0), 37) )
1561 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1562 d = Decimal( (1, (), 37) )
1563 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1564
1565 #leading zeros in NaN diagnostic info should be stripped
1566 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), 'n') )
1567 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), 'n') )
1568 d = Decimal( (1, (0, 0, 0), 'N') )
1569 self.assertEqual(d.as_tuple(), (1, (), 'N') )
1570 d = Decimal( (1, (), 'n') )
1571 self.assertEqual(d.as_tuple(), (1, (), 'n') )
1572
1573 #coefficient in infinity should be ignored
1574 d = Decimal( (0, (4, 5, 3, 4), 'F') )
1575 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
1576 d = Decimal( (1, (0, 2, 7, 1), 'F') )
1577 self.assertEqual(d.as_tuple(), (1, (0,), 'F'))
1578
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001579 def test_immutability_operations(self):
1580 # Do operations and check that it didn't change change internal objects.
1581
1582 d1 = Decimal('-25e55')
1583 b1 = Decimal('-25e55')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001584 d2 = Decimal('33e+33')
1585 b2 = Decimal('33e+33')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001586
1587 def checkSameDec(operation, useOther=False):
1588 if useOther:
1589 eval("d1." + operation + "(d2)")
1590 self.assertEqual(d1._sign, b1._sign)
1591 self.assertEqual(d1._int, b1._int)
1592 self.assertEqual(d1._exp, b1._exp)
1593 self.assertEqual(d2._sign, b2._sign)
1594 self.assertEqual(d2._int, b2._int)
1595 self.assertEqual(d2._exp, b2._exp)
1596 else:
1597 eval("d1." + operation + "()")
1598 self.assertEqual(d1._sign, b1._sign)
1599 self.assertEqual(d1._int, b1._int)
1600 self.assertEqual(d1._exp, b1._exp)
1601 return
1602
1603 Decimal(d1)
1604 self.assertEqual(d1._sign, b1._sign)
1605 self.assertEqual(d1._int, b1._int)
1606 self.assertEqual(d1._exp, b1._exp)
1607
1608 checkSameDec("__abs__")
1609 checkSameDec("__add__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001610 checkSameDec("__divmod__", True)
Christian Heimes77c02eb2008-02-09 02:18:51 +00001611 checkSameDec("__eq__", True)
1612 checkSameDec("__ne__", True)
1613 checkSameDec("__le__", True)
1614 checkSameDec("__lt__", True)
1615 checkSameDec("__ge__", True)
1616 checkSameDec("__gt__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001617 checkSameDec("__float__")
1618 checkSameDec("__floordiv__", True)
1619 checkSameDec("__hash__")
1620 checkSameDec("__int__")
Christian Heimes969fe572008-01-25 11:23:10 +00001621 checkSameDec("__trunc__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001622 checkSameDec("__mod__", True)
1623 checkSameDec("__mul__", True)
1624 checkSameDec("__neg__")
Jack Diederich4dafcc42006-11-28 19:15:13 +00001625 checkSameDec("__bool__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001626 checkSameDec("__pos__")
1627 checkSameDec("__pow__", True)
1628 checkSameDec("__radd__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001629 checkSameDec("__rdivmod__", True)
1630 checkSameDec("__repr__")
1631 checkSameDec("__rfloordiv__", True)
1632 checkSameDec("__rmod__", True)
1633 checkSameDec("__rmul__", True)
1634 checkSameDec("__rpow__", True)
1635 checkSameDec("__rsub__", True)
1636 checkSameDec("__str__")
1637 checkSameDec("__sub__", True)
1638 checkSameDec("__truediv__", True)
1639 checkSameDec("adjusted")
1640 checkSameDec("as_tuple")
1641 checkSameDec("compare", True)
1642 checkSameDec("max", True)
1643 checkSameDec("min", True)
1644 checkSameDec("normalize")
1645 checkSameDec("quantize", True)
1646 checkSameDec("remainder_near", True)
1647 checkSameDec("same_quantum", True)
1648 checkSameDec("sqrt")
1649 checkSameDec("to_eng_string")
1650 checkSameDec("to_integral")
1651
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001652 def test_subclassing(self):
1653 # Different behaviours when subclassing Decimal
1654
1655 class MyDecimal(Decimal):
1656 pass
1657
1658 d1 = MyDecimal(1)
1659 d2 = MyDecimal(2)
1660 d = d1 + d2
Ezio Melotti6607d512010-04-03 14:59:49 +00001661 self.assertIs(type(d), Decimal)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001662
1663 d = d1.max(d2)
Ezio Melotti6607d512010-04-03 14:59:49 +00001664 self.assertIs(type(d), Decimal)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001665
Christian Heimes0348fb62008-03-26 12:55:56 +00001666 def test_implicit_context(self):
1667 # Check results when context given implicitly. (Issue 2478)
1668 c = getcontext()
1669 self.assertEqual(str(Decimal(0).sqrt()),
1670 str(c.sqrt(Decimal(0))))
1671
Mark Dickinsona2d1fe02009-10-29 12:23:02 +00001672 def test_conversions_from_int(self):
1673 # Check that methods taking a second Decimal argument will
1674 # always accept an integer in place of a Decimal.
1675 self.assertEqual(Decimal(4).compare(3),
1676 Decimal(4).compare(Decimal(3)))
1677 self.assertEqual(Decimal(4).compare_signal(3),
1678 Decimal(4).compare_signal(Decimal(3)))
1679 self.assertEqual(Decimal(4).compare_total(3),
1680 Decimal(4).compare_total(Decimal(3)))
1681 self.assertEqual(Decimal(4).compare_total_mag(3),
1682 Decimal(4).compare_total_mag(Decimal(3)))
1683 self.assertEqual(Decimal(10101).logical_and(1001),
1684 Decimal(10101).logical_and(Decimal(1001)))
1685 self.assertEqual(Decimal(10101).logical_or(1001),
1686 Decimal(10101).logical_or(Decimal(1001)))
1687 self.assertEqual(Decimal(10101).logical_xor(1001),
1688 Decimal(10101).logical_xor(Decimal(1001)))
1689 self.assertEqual(Decimal(567).max(123),
1690 Decimal(567).max(Decimal(123)))
1691 self.assertEqual(Decimal(567).max_mag(123),
1692 Decimal(567).max_mag(Decimal(123)))
1693 self.assertEqual(Decimal(567).min(123),
1694 Decimal(567).min(Decimal(123)))
1695 self.assertEqual(Decimal(567).min_mag(123),
1696 Decimal(567).min_mag(Decimal(123)))
1697 self.assertEqual(Decimal(567).next_toward(123),
1698 Decimal(567).next_toward(Decimal(123)))
1699 self.assertEqual(Decimal(1234).quantize(100),
1700 Decimal(1234).quantize(Decimal(100)))
1701 self.assertEqual(Decimal(768).remainder_near(1234),
1702 Decimal(768).remainder_near(Decimal(1234)))
1703 self.assertEqual(Decimal(123).rotate(1),
1704 Decimal(123).rotate(Decimal(1)))
1705 self.assertEqual(Decimal(1234).same_quantum(1000),
1706 Decimal(1234).same_quantum(Decimal(1000)))
1707 self.assertEqual(Decimal('9.123').scaleb(-100),
1708 Decimal('9.123').scaleb(Decimal(-100)))
1709 self.assertEqual(Decimal(456).shift(-1),
1710 Decimal(456).shift(Decimal(-1)))
1711
1712 self.assertEqual(Decimal(-12).fma(Decimal(45), 67),
1713 Decimal(-12).fma(Decimal(45), Decimal(67)))
1714 self.assertEqual(Decimal(-12).fma(45, 67),
1715 Decimal(-12).fma(Decimal(45), Decimal(67)))
1716 self.assertEqual(Decimal(-12).fma(45, Decimal(67)),
1717 Decimal(-12).fma(Decimal(45), Decimal(67)))
1718
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001719
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001720class DecimalPythonAPItests(unittest.TestCase):
1721
Raymond Hettinger82417ca2009-02-03 03:54:28 +00001722 def test_abc(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001723 self.assertTrue(issubclass(Decimal, numbers.Number))
Ezio Melotti6607d512010-04-03 14:59:49 +00001724 self.assertFalse(issubclass(Decimal, numbers.Real))
Ezio Melottie9615932010-01-24 19:26:24 +00001725 self.assertIsInstance(Decimal(0), numbers.Number)
1726 self.assertNotIsInstance(Decimal(0), numbers.Real)
Raymond Hettinger82417ca2009-02-03 03:54:28 +00001727
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001728 def test_pickle(self):
1729 d = Decimal('-3.141590000')
1730 p = pickle.dumps(d)
1731 e = pickle.loads(p)
1732 self.assertEqual(d, e)
1733
Raymond Hettinger5548be22004-07-05 18:49:38 +00001734 def test_int(self):
Raymond Hettinger605ed022004-11-24 07:28:48 +00001735 for x in range(-250, 250):
1736 s = '%0.2f' % (x / 100.0)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001737 # should work the same as for floats
1738 self.assertEqual(int(Decimal(s)), int(float(s)))
Raymond Hettinger605ed022004-11-24 07:28:48 +00001739 # should work the same as to_integral in the ROUND_DOWN mode
Raymond Hettinger5548be22004-07-05 18:49:38 +00001740 d = Decimal(s)
Raymond Hettinger605ed022004-11-24 07:28:48 +00001741 r = d.to_integral(ROUND_DOWN)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001742 self.assertEqual(Decimal(int(d)), r)
1743
Mark Dickinson825fce32009-09-07 18:08:12 +00001744 self.assertRaises(ValueError, int, Decimal('-nan'))
1745 self.assertRaises(ValueError, int, Decimal('snan'))
1746 self.assertRaises(OverflowError, int, Decimal('inf'))
1747 self.assertRaises(OverflowError, int, Decimal('-inf'))
1748
Christian Heimes969fe572008-01-25 11:23:10 +00001749 def test_trunc(self):
1750 for x in range(-250, 250):
1751 s = '%0.2f' % (x / 100.0)
1752 # should work the same as for floats
1753 self.assertEqual(int(Decimal(s)), int(float(s)))
1754 # should work the same as to_integral in the ROUND_DOWN mode
1755 d = Decimal(s)
1756 r = d.to_integral(ROUND_DOWN)
Christian Heimes400adb02008-02-01 08:12:03 +00001757 self.assertEqual(Decimal(math.trunc(d)), r)
Christian Heimes969fe572008-01-25 11:23:10 +00001758
Raymond Hettinger771ed762009-01-03 19:20:32 +00001759 def test_from_float(self):
1760
1761 class MyDecimal(Decimal):
1762 pass
1763
1764 r = MyDecimal.from_float(0.1)
1765 self.assertEqual(type(r), MyDecimal)
1766 self.assertEqual(str(r),
1767 '0.1000000000000000055511151231257827021181583404541015625')
1768 bigint = 12345678901234567890123456789
1769 self.assertEqual(MyDecimal.from_float(bigint), MyDecimal(bigint))
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001770 self.assertTrue(MyDecimal.from_float(float('nan')).is_qnan())
1771 self.assertTrue(MyDecimal.from_float(float('inf')).is_infinite())
1772 self.assertTrue(MyDecimal.from_float(float('-inf')).is_infinite())
Raymond Hettinger771ed762009-01-03 19:20:32 +00001773 self.assertEqual(str(MyDecimal.from_float(float('nan'))),
1774 str(Decimal('NaN')))
1775 self.assertEqual(str(MyDecimal.from_float(float('inf'))),
1776 str(Decimal('Infinity')))
1777 self.assertEqual(str(MyDecimal.from_float(float('-inf'))),
1778 str(Decimal('-Infinity')))
1779 self.assertRaises(TypeError, MyDecimal.from_float, 'abc')
1780 for i in range(200):
1781 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
1782 self.assertEqual(x, float(MyDecimal.from_float(x))) # roundtrip
1783
1784 def test_create_decimal_from_float(self):
1785 context = Context(prec=5, rounding=ROUND_DOWN)
1786 self.assertEqual(
1787 context.create_decimal_from_float(math.pi),
1788 Decimal('3.1415')
1789 )
1790 context = Context(prec=5, rounding=ROUND_UP)
1791 self.assertEqual(
1792 context.create_decimal_from_float(math.pi),
1793 Decimal('3.1416')
1794 )
1795 context = Context(prec=5, traps=[Inexact])
1796 self.assertRaises(
1797 Inexact,
1798 context.create_decimal_from_float,
1799 math.pi
1800 )
1801 self.assertEqual(repr(context.create_decimal_from_float(-0.0)),
1802 "Decimal('-0')")
1803 self.assertEqual(repr(context.create_decimal_from_float(1.0)),
1804 "Decimal('1')")
1805 self.assertEqual(repr(context.create_decimal_from_float(10)),
1806 "Decimal('10')")
1807
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00001808class ContextAPItests(unittest.TestCase):
1809
1810 def test_pickle(self):
1811 c = Context()
1812 e = pickle.loads(pickle.dumps(c))
1813 for k in vars(c):
1814 v1 = vars(c)[k]
1815 v2 = vars(e)[k]
1816 self.assertEqual(v1, v2)
1817
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001818 def test_equality_with_other_types(self):
Benjamin Peterson577473f2010-01-19 00:09:57 +00001819 self.assertIn(Decimal(10), ['a', 1.0, Decimal(10), (1,2), {}])
1820 self.assertNotIn(Decimal(10), ['a', 1.0, (1,2), {}])
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001821
Raymond Hettinger955d2b22004-08-08 20:17:45 +00001822 def test_copy(self):
1823 # All copies should be deep
1824 c = Context()
1825 d = c.copy()
1826 self.assertNotEqual(id(c), id(d))
1827 self.assertNotEqual(id(c.flags), id(d.flags))
1828 self.assertNotEqual(id(c.traps), id(d.traps))
1829
Mark Dickinsonb1d8e322010-05-22 18:35:36 +00001830 def test__clamp(self):
1831 # In Python 3.2, the private attribute `_clamp` was made
1832 # public (issue 8540), with the old `_clamp` becoming a
1833 # property wrapping `clamp`. For the duration of Python 3.2
1834 # only, the attribute should be gettable/settable via both
1835 # `clamp` and `_clamp`; in Python 3.3, `_clamp` should be
1836 # removed.
1837 c = Context(clamp = 0)
1838 self.assertEqual(c.clamp, 0)
1839
1840 with check_warnings(("", DeprecationWarning)):
1841 c._clamp = 1
1842 self.assertEqual(c.clamp, 1)
1843 with check_warnings(("", DeprecationWarning)):
1844 self.assertEqual(c._clamp, 1)
1845 c.clamp = 0
1846 self.assertEqual(c.clamp, 0)
1847 with check_warnings(("", DeprecationWarning)):
1848 self.assertEqual(c._clamp, 0)
1849
Mark Dickinson84230a12010-02-18 14:49:50 +00001850 def test_abs(self):
1851 c = Context()
1852 d = c.abs(Decimal(-1))
1853 self.assertEqual(c.abs(-1), d)
1854 self.assertRaises(TypeError, c.abs, '-1')
1855
1856 def test_add(self):
1857 c = Context()
1858 d = c.add(Decimal(1), Decimal(1))
1859 self.assertEqual(c.add(1, 1), d)
1860 self.assertEqual(c.add(Decimal(1), 1), d)
1861 self.assertEqual(c.add(1, Decimal(1)), d)
1862 self.assertRaises(TypeError, c.add, '1', 1)
1863 self.assertRaises(TypeError, c.add, 1, '1')
1864
1865 def test_compare(self):
1866 c = Context()
1867 d = c.compare(Decimal(1), Decimal(1))
1868 self.assertEqual(c.compare(1, 1), d)
1869 self.assertEqual(c.compare(Decimal(1), 1), d)
1870 self.assertEqual(c.compare(1, Decimal(1)), d)
1871 self.assertRaises(TypeError, c.compare, '1', 1)
1872 self.assertRaises(TypeError, c.compare, 1, '1')
1873
1874 def test_compare_signal(self):
1875 c = Context()
1876 d = c.compare_signal(Decimal(1), Decimal(1))
1877 self.assertEqual(c.compare_signal(1, 1), d)
1878 self.assertEqual(c.compare_signal(Decimal(1), 1), d)
1879 self.assertEqual(c.compare_signal(1, Decimal(1)), d)
1880 self.assertRaises(TypeError, c.compare_signal, '1', 1)
1881 self.assertRaises(TypeError, c.compare_signal, 1, '1')
1882
1883 def test_compare_total(self):
1884 c = Context()
1885 d = c.compare_total(Decimal(1), Decimal(1))
1886 self.assertEqual(c.compare_total(1, 1), d)
1887 self.assertEqual(c.compare_total(Decimal(1), 1), d)
1888 self.assertEqual(c.compare_total(1, Decimal(1)), d)
1889 self.assertRaises(TypeError, c.compare_total, '1', 1)
1890 self.assertRaises(TypeError, c.compare_total, 1, '1')
1891
1892 def test_compare_total_mag(self):
1893 c = Context()
1894 d = c.compare_total_mag(Decimal(1), Decimal(1))
1895 self.assertEqual(c.compare_total_mag(1, 1), d)
1896 self.assertEqual(c.compare_total_mag(Decimal(1), 1), d)
1897 self.assertEqual(c.compare_total_mag(1, Decimal(1)), d)
1898 self.assertRaises(TypeError, c.compare_total_mag, '1', 1)
1899 self.assertRaises(TypeError, c.compare_total_mag, 1, '1')
1900
1901 def test_copy_abs(self):
1902 c = Context()
1903 d = c.copy_abs(Decimal(-1))
1904 self.assertEqual(c.copy_abs(-1), d)
1905 self.assertRaises(TypeError, c.copy_abs, '-1')
1906
1907 def test_copy_decimal(self):
1908 c = Context()
1909 d = c.copy_decimal(Decimal(-1))
1910 self.assertEqual(c.copy_decimal(-1), d)
1911 self.assertRaises(TypeError, c.copy_decimal, '-1')
1912
1913 def test_copy_negate(self):
1914 c = Context()
1915 d = c.copy_negate(Decimal(-1))
1916 self.assertEqual(c.copy_negate(-1), d)
1917 self.assertRaises(TypeError, c.copy_negate, '-1')
1918
1919 def test_copy_sign(self):
1920 c = Context()
1921 d = c.copy_sign(Decimal(1), Decimal(-2))
1922 self.assertEqual(c.copy_sign(1, -2), d)
1923 self.assertEqual(c.copy_sign(Decimal(1), -2), d)
1924 self.assertEqual(c.copy_sign(1, Decimal(-2)), d)
1925 self.assertRaises(TypeError, c.copy_sign, '1', -2)
1926 self.assertRaises(TypeError, c.copy_sign, 1, '-2')
1927
1928 def test_divide(self):
1929 c = Context()
1930 d = c.divide(Decimal(1), Decimal(2))
1931 self.assertEqual(c.divide(1, 2), d)
1932 self.assertEqual(c.divide(Decimal(1), 2), d)
1933 self.assertEqual(c.divide(1, Decimal(2)), d)
1934 self.assertRaises(TypeError, c.divide, '1', 2)
1935 self.assertRaises(TypeError, c.divide, 1, '2')
1936
1937 def test_divide_int(self):
1938 c = Context()
1939 d = c.divide_int(Decimal(1), Decimal(2))
1940 self.assertEqual(c.divide_int(1, 2), d)
1941 self.assertEqual(c.divide_int(Decimal(1), 2), d)
1942 self.assertEqual(c.divide_int(1, Decimal(2)), d)
1943 self.assertRaises(TypeError, c.divide_int, '1', 2)
1944 self.assertRaises(TypeError, c.divide_int, 1, '2')
1945
1946 def test_divmod(self):
1947 c = Context()
1948 d = c.divmod(Decimal(1), Decimal(2))
1949 self.assertEqual(c.divmod(1, 2), d)
1950 self.assertEqual(c.divmod(Decimal(1), 2), d)
1951 self.assertEqual(c.divmod(1, Decimal(2)), d)
1952 self.assertRaises(TypeError, c.divmod, '1', 2)
1953 self.assertRaises(TypeError, c.divmod, 1, '2')
1954
1955 def test_exp(self):
1956 c = Context()
1957 d = c.exp(Decimal(10))
1958 self.assertEqual(c.exp(10), d)
1959 self.assertRaises(TypeError, c.exp, '10')
1960
1961 def test_fma(self):
1962 c = Context()
1963 d = c.fma(Decimal(2), Decimal(3), Decimal(4))
1964 self.assertEqual(c.fma(2, 3, 4), d)
1965 self.assertEqual(c.fma(Decimal(2), 3, 4), d)
1966 self.assertEqual(c.fma(2, Decimal(3), 4), d)
1967 self.assertEqual(c.fma(2, 3, Decimal(4)), d)
1968 self.assertEqual(c.fma(Decimal(2), Decimal(3), 4), d)
1969 self.assertRaises(TypeError, c.fma, '2', 3, 4)
1970 self.assertRaises(TypeError, c.fma, 2, '3', 4)
1971 self.assertRaises(TypeError, c.fma, 2, 3, '4')
1972
Mark Dickinsonb455e582011-05-22 12:53:18 +01001973 # Issue 12079 for Context.fma ...
1974 self.assertRaises(TypeError, c.fma,
1975 Decimal('Infinity'), Decimal(0), "not a decimal")
1976 self.assertRaises(TypeError, c.fma,
1977 Decimal(1), Decimal('snan'), 1.222)
1978 # ... and for Decimal.fma.
1979 self.assertRaises(TypeError, Decimal('Infinity').fma,
1980 Decimal(0), "not a decimal")
1981 self.assertRaises(TypeError, Decimal(1).fma,
1982 Decimal('snan'), 1.222)
1983
Mark Dickinson84230a12010-02-18 14:49:50 +00001984 def test_is_finite(self):
1985 c = Context()
1986 d = c.is_finite(Decimal(10))
1987 self.assertEqual(c.is_finite(10), d)
1988 self.assertRaises(TypeError, c.is_finite, '10')
1989
1990 def test_is_infinite(self):
1991 c = Context()
1992 d = c.is_infinite(Decimal(10))
1993 self.assertEqual(c.is_infinite(10), d)
1994 self.assertRaises(TypeError, c.is_infinite, '10')
1995
1996 def test_is_nan(self):
1997 c = Context()
1998 d = c.is_nan(Decimal(10))
1999 self.assertEqual(c.is_nan(10), d)
2000 self.assertRaises(TypeError, c.is_nan, '10')
2001
2002 def test_is_normal(self):
2003 c = Context()
2004 d = c.is_normal(Decimal(10))
2005 self.assertEqual(c.is_normal(10), d)
2006 self.assertRaises(TypeError, c.is_normal, '10')
2007
2008 def test_is_qnan(self):
2009 c = Context()
2010 d = c.is_qnan(Decimal(10))
2011 self.assertEqual(c.is_qnan(10), d)
2012 self.assertRaises(TypeError, c.is_qnan, '10')
2013
2014 def test_is_signed(self):
2015 c = Context()
2016 d = c.is_signed(Decimal(10))
2017 self.assertEqual(c.is_signed(10), d)
2018 self.assertRaises(TypeError, c.is_signed, '10')
2019
2020 def test_is_snan(self):
2021 c = Context()
2022 d = c.is_snan(Decimal(10))
2023 self.assertEqual(c.is_snan(10), d)
2024 self.assertRaises(TypeError, c.is_snan, '10')
2025
2026 def test_is_subnormal(self):
2027 c = Context()
2028 d = c.is_subnormal(Decimal(10))
2029 self.assertEqual(c.is_subnormal(10), d)
2030 self.assertRaises(TypeError, c.is_subnormal, '10')
2031
2032 def test_is_zero(self):
2033 c = Context()
2034 d = c.is_zero(Decimal(10))
2035 self.assertEqual(c.is_zero(10), d)
2036 self.assertRaises(TypeError, c.is_zero, '10')
2037
2038 def test_ln(self):
2039 c = Context()
2040 d = c.ln(Decimal(10))
2041 self.assertEqual(c.ln(10), d)
2042 self.assertRaises(TypeError, c.ln, '10')
2043
2044 def test_log10(self):
2045 c = Context()
2046 d = c.log10(Decimal(10))
2047 self.assertEqual(c.log10(10), d)
2048 self.assertRaises(TypeError, c.log10, '10')
2049
2050 def test_logb(self):
2051 c = Context()
2052 d = c.logb(Decimal(10))
2053 self.assertEqual(c.logb(10), d)
2054 self.assertRaises(TypeError, c.logb, '10')
2055
2056 def test_logical_and(self):
2057 c = Context()
2058 d = c.logical_and(Decimal(1), Decimal(1))
2059 self.assertEqual(c.logical_and(1, 1), d)
2060 self.assertEqual(c.logical_and(Decimal(1), 1), d)
2061 self.assertEqual(c.logical_and(1, Decimal(1)), d)
2062 self.assertRaises(TypeError, c.logical_and, '1', 1)
2063 self.assertRaises(TypeError, c.logical_and, 1, '1')
2064
2065 def test_logical_invert(self):
2066 c = Context()
2067 d = c.logical_invert(Decimal(1000))
2068 self.assertEqual(c.logical_invert(1000), d)
2069 self.assertRaises(TypeError, c.logical_invert, '1000')
2070
2071 def test_logical_or(self):
2072 c = Context()
2073 d = c.logical_or(Decimal(1), Decimal(1))
2074 self.assertEqual(c.logical_or(1, 1), d)
2075 self.assertEqual(c.logical_or(Decimal(1), 1), d)
2076 self.assertEqual(c.logical_or(1, Decimal(1)), d)
2077 self.assertRaises(TypeError, c.logical_or, '1', 1)
2078 self.assertRaises(TypeError, c.logical_or, 1, '1')
2079
2080 def test_logical_xor(self):
2081 c = Context()
2082 d = c.logical_xor(Decimal(1), Decimal(1))
2083 self.assertEqual(c.logical_xor(1, 1), d)
2084 self.assertEqual(c.logical_xor(Decimal(1), 1), d)
2085 self.assertEqual(c.logical_xor(1, Decimal(1)), d)
2086 self.assertRaises(TypeError, c.logical_xor, '1', 1)
2087 self.assertRaises(TypeError, c.logical_xor, 1, '1')
2088
2089 def test_max(self):
2090 c = Context()
2091 d = c.max(Decimal(1), Decimal(2))
2092 self.assertEqual(c.max(1, 2), d)
2093 self.assertEqual(c.max(Decimal(1), 2), d)
2094 self.assertEqual(c.max(1, Decimal(2)), d)
2095 self.assertRaises(TypeError, c.max, '1', 2)
2096 self.assertRaises(TypeError, c.max, 1, '2')
2097
2098 def test_max_mag(self):
2099 c = Context()
2100 d = c.max_mag(Decimal(1), Decimal(2))
2101 self.assertEqual(c.max_mag(1, 2), d)
2102 self.assertEqual(c.max_mag(Decimal(1), 2), d)
2103 self.assertEqual(c.max_mag(1, Decimal(2)), d)
2104 self.assertRaises(TypeError, c.max_mag, '1', 2)
2105 self.assertRaises(TypeError, c.max_mag, 1, '2')
2106
2107 def test_min(self):
2108 c = Context()
2109 d = c.min(Decimal(1), Decimal(2))
2110 self.assertEqual(c.min(1, 2), d)
2111 self.assertEqual(c.min(Decimal(1), 2), d)
2112 self.assertEqual(c.min(1, Decimal(2)), d)
2113 self.assertRaises(TypeError, c.min, '1', 2)
2114 self.assertRaises(TypeError, c.min, 1, '2')
2115
2116 def test_min_mag(self):
2117 c = Context()
2118 d = c.min_mag(Decimal(1), Decimal(2))
2119 self.assertEqual(c.min_mag(1, 2), d)
2120 self.assertEqual(c.min_mag(Decimal(1), 2), d)
2121 self.assertEqual(c.min_mag(1, Decimal(2)), d)
2122 self.assertRaises(TypeError, c.min_mag, '1', 2)
2123 self.assertRaises(TypeError, c.min_mag, 1, '2')
2124
2125 def test_minus(self):
2126 c = Context()
2127 d = c.minus(Decimal(10))
2128 self.assertEqual(c.minus(10), d)
2129 self.assertRaises(TypeError, c.minus, '10')
2130
2131 def test_multiply(self):
2132 c = Context()
2133 d = c.multiply(Decimal(1), Decimal(2))
2134 self.assertEqual(c.multiply(1, 2), d)
2135 self.assertEqual(c.multiply(Decimal(1), 2), d)
2136 self.assertEqual(c.multiply(1, Decimal(2)), d)
2137 self.assertRaises(TypeError, c.multiply, '1', 2)
2138 self.assertRaises(TypeError, c.multiply, 1, '2')
2139
2140 def test_next_minus(self):
2141 c = Context()
2142 d = c.next_minus(Decimal(10))
2143 self.assertEqual(c.next_minus(10), d)
2144 self.assertRaises(TypeError, c.next_minus, '10')
2145
2146 def test_next_plus(self):
2147 c = Context()
2148 d = c.next_plus(Decimal(10))
2149 self.assertEqual(c.next_plus(10), d)
2150 self.assertRaises(TypeError, c.next_plus, '10')
2151
2152 def test_next_toward(self):
2153 c = Context()
2154 d = c.next_toward(Decimal(1), Decimal(2))
2155 self.assertEqual(c.next_toward(1, 2), d)
2156 self.assertEqual(c.next_toward(Decimal(1), 2), d)
2157 self.assertEqual(c.next_toward(1, Decimal(2)), d)
2158 self.assertRaises(TypeError, c.next_toward, '1', 2)
2159 self.assertRaises(TypeError, c.next_toward, 1, '2')
2160
2161 def test_normalize(self):
2162 c = Context()
2163 d = c.normalize(Decimal(10))
2164 self.assertEqual(c.normalize(10), d)
2165 self.assertRaises(TypeError, c.normalize, '10')
2166
2167 def test_number_class(self):
2168 c = Context()
2169 self.assertEqual(c.number_class(123), c.number_class(Decimal(123)))
2170 self.assertEqual(c.number_class(0), c.number_class(Decimal(0)))
2171 self.assertEqual(c.number_class(-45), c.number_class(Decimal(-45)))
2172
2173 def test_power(self):
2174 c = Context()
2175 d = c.power(Decimal(1), Decimal(4), Decimal(2))
2176 self.assertEqual(c.power(1, 4, 2), d)
2177 self.assertEqual(c.power(Decimal(1), 4, 2), d)
2178 self.assertEqual(c.power(1, Decimal(4), 2), d)
2179 self.assertEqual(c.power(1, 4, Decimal(2)), d)
2180 self.assertEqual(c.power(Decimal(1), Decimal(4), 2), d)
2181 self.assertRaises(TypeError, c.power, '1', 4, 2)
2182 self.assertRaises(TypeError, c.power, 1, '4', 2)
2183 self.assertRaises(TypeError, c.power, 1, 4, '2')
2184
2185 def test_plus(self):
2186 c = Context()
2187 d = c.plus(Decimal(10))
2188 self.assertEqual(c.plus(10), d)
2189 self.assertRaises(TypeError, c.plus, '10')
2190
2191 def test_quantize(self):
2192 c = Context()
2193 d = c.quantize(Decimal(1), Decimal(2))
2194 self.assertEqual(c.quantize(1, 2), d)
2195 self.assertEqual(c.quantize(Decimal(1), 2), d)
2196 self.assertEqual(c.quantize(1, Decimal(2)), d)
2197 self.assertRaises(TypeError, c.quantize, '1', 2)
2198 self.assertRaises(TypeError, c.quantize, 1, '2')
2199
2200 def test_remainder(self):
2201 c = Context()
2202 d = c.remainder(Decimal(1), Decimal(2))
2203 self.assertEqual(c.remainder(1, 2), d)
2204 self.assertEqual(c.remainder(Decimal(1), 2), d)
2205 self.assertEqual(c.remainder(1, Decimal(2)), d)
2206 self.assertRaises(TypeError, c.remainder, '1', 2)
2207 self.assertRaises(TypeError, c.remainder, 1, '2')
2208
2209 def test_remainder_near(self):
2210 c = Context()
2211 d = c.remainder_near(Decimal(1), Decimal(2))
2212 self.assertEqual(c.remainder_near(1, 2), d)
2213 self.assertEqual(c.remainder_near(Decimal(1), 2), d)
2214 self.assertEqual(c.remainder_near(1, Decimal(2)), d)
2215 self.assertRaises(TypeError, c.remainder_near, '1', 2)
2216 self.assertRaises(TypeError, c.remainder_near, 1, '2')
2217
2218 def test_rotate(self):
2219 c = Context()
2220 d = c.rotate(Decimal(1), Decimal(2))
2221 self.assertEqual(c.rotate(1, 2), d)
2222 self.assertEqual(c.rotate(Decimal(1), 2), d)
2223 self.assertEqual(c.rotate(1, Decimal(2)), d)
2224 self.assertRaises(TypeError, c.rotate, '1', 2)
2225 self.assertRaises(TypeError, c.rotate, 1, '2')
2226
2227 def test_sqrt(self):
2228 c = Context()
2229 d = c.sqrt(Decimal(10))
2230 self.assertEqual(c.sqrt(10), d)
2231 self.assertRaises(TypeError, c.sqrt, '10')
2232
2233 def test_same_quantum(self):
2234 c = Context()
2235 d = c.same_quantum(Decimal(1), Decimal(2))
2236 self.assertEqual(c.same_quantum(1, 2), d)
2237 self.assertEqual(c.same_quantum(Decimal(1), 2), d)
2238 self.assertEqual(c.same_quantum(1, Decimal(2)), d)
2239 self.assertRaises(TypeError, c.same_quantum, '1', 2)
2240 self.assertRaises(TypeError, c.same_quantum, 1, '2')
2241
2242 def test_scaleb(self):
2243 c = Context()
2244 d = c.scaleb(Decimal(1), Decimal(2))
2245 self.assertEqual(c.scaleb(1, 2), d)
2246 self.assertEqual(c.scaleb(Decimal(1), 2), d)
2247 self.assertEqual(c.scaleb(1, Decimal(2)), d)
2248 self.assertRaises(TypeError, c.scaleb, '1', 2)
2249 self.assertRaises(TypeError, c.scaleb, 1, '2')
2250
2251 def test_shift(self):
2252 c = Context()
2253 d = c.shift(Decimal(1), Decimal(2))
2254 self.assertEqual(c.shift(1, 2), d)
2255 self.assertEqual(c.shift(Decimal(1), 2), d)
2256 self.assertEqual(c.shift(1, Decimal(2)), d)
2257 self.assertRaises(TypeError, c.shift, '1', 2)
2258 self.assertRaises(TypeError, c.shift, 1, '2')
2259
2260 def test_subtract(self):
2261 c = Context()
2262 d = c.subtract(Decimal(1), Decimal(2))
2263 self.assertEqual(c.subtract(1, 2), d)
2264 self.assertEqual(c.subtract(Decimal(1), 2), d)
2265 self.assertEqual(c.subtract(1, Decimal(2)), d)
2266 self.assertRaises(TypeError, c.subtract, '1', 2)
2267 self.assertRaises(TypeError, c.subtract, 1, '2')
2268
2269 def test_to_eng_string(self):
2270 c = Context()
2271 d = c.to_eng_string(Decimal(10))
2272 self.assertEqual(c.to_eng_string(10), d)
2273 self.assertRaises(TypeError, c.to_eng_string, '10')
2274
2275 def test_to_sci_string(self):
2276 c = Context()
2277 d = c.to_sci_string(Decimal(10))
2278 self.assertEqual(c.to_sci_string(10), d)
2279 self.assertRaises(TypeError, c.to_sci_string, '10')
2280
2281 def test_to_integral_exact(self):
2282 c = Context()
2283 d = c.to_integral_exact(Decimal(10))
2284 self.assertEqual(c.to_integral_exact(10), d)
2285 self.assertRaises(TypeError, c.to_integral_exact, '10')
2286
2287 def test_to_integral_value(self):
2288 c = Context()
2289 d = c.to_integral_value(Decimal(10))
2290 self.assertEqual(c.to_integral_value(10), d)
2291 self.assertRaises(TypeError, c.to_integral_value, '10')
2292
Thomas Wouters89f507f2006-12-13 04:49:30 +00002293class WithStatementTest(unittest.TestCase):
2294 # Can't do these as docstrings until Python 2.6
2295 # as doctest can't handle __future__ statements
2296
2297 def test_localcontext(self):
2298 # Use a copy of the current context in the block
2299 orig_ctx = getcontext()
2300 with localcontext() as enter_ctx:
2301 set_ctx = getcontext()
2302 final_ctx = getcontext()
Ezio Melotti6607d512010-04-03 14:59:49 +00002303 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
2304 self.assertIsNot(orig_ctx, set_ctx, 'did not copy the context')
2305 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
Thomas Wouters89f507f2006-12-13 04:49:30 +00002306
2307 def test_localcontextarg(self):
2308 # Use a copy of the supplied context in the block
2309 orig_ctx = getcontext()
2310 new_ctx = Context(prec=42)
2311 with localcontext(new_ctx) as enter_ctx:
2312 set_ctx = getcontext()
2313 final_ctx = getcontext()
Ezio Melotti6607d512010-04-03 14:59:49 +00002314 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
2315 self.assertEqual(set_ctx.prec, new_ctx.prec, 'did not set correct context')
2316 self.assertIsNot(new_ctx, set_ctx, 'did not copy the context')
2317 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
Thomas Wouters89f507f2006-12-13 04:49:30 +00002318
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002319class ContextFlags(unittest.TestCase):
2320 def test_flags_irrelevant(self):
2321 # check that the result (numeric result + flags raised) of an
2322 # arithmetic operation doesn't depend on the current flags
2323
2324 context = Context(prec=9, Emin = -999999999, Emax = 999999999,
2325 rounding=ROUND_HALF_EVEN, traps=[], flags=[])
2326
2327 # operations that raise various flags, in the form (function, arglist)
2328 operations = [
2329 (context._apply, [Decimal("100E-1000000009")]),
2330 (context.sqrt, [Decimal(2)]),
2331 (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]),
2332 (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]),
2333 (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]),
2334 ]
2335
2336 # try various flags individually, then a whole lot at once
2337 flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal],
2338 [Inexact, Rounded, Underflow, Clamped, Subnormal]]
2339
2340 for fn, args in operations:
2341 # find answer and flags raised using a clean context
2342 context.clear_flags()
2343 ans = fn(*args)
2344 flags = [k for k, v in context.flags.items() if v]
2345
2346 for extra_flags in flagsets:
2347 # set flags, before calling operation
2348 context.clear_flags()
2349 for flag in extra_flags:
2350 context._raise_error(flag)
2351 new_ans = fn(*args)
2352
2353 # flags that we expect to be set after the operation
2354 expected_flags = list(flags)
2355 for flag in extra_flags:
2356 if flag not in expected_flags:
2357 expected_flags.append(flag)
2358 expected_flags.sort(key=id)
2359
2360 # flags we actually got
2361 new_flags = [k for k,v in context.flags.items() if v]
2362 new_flags.sort(key=id)
2363
2364 self.assertEqual(ans, new_ans,
2365 "operation produces different answers depending on flags set: " +
2366 "expected %s, got %s." % (ans, new_ans))
2367 self.assertEqual(new_flags, expected_flags,
2368 "operation raises different flags depending on flags set: " +
2369 "expected %s, got %s" % (expected_flags, new_flags))
2370
2371def test_main(arith=False, verbose=None, todo_tests=None, debug=None):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002372 """ Execute the tests.
2373
Raymond Hettingered20ad82004-09-04 20:09:13 +00002374 Runs all arithmetic tests if arith is True or if the "decimal" resource
2375 is enabled in regrtest.py
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002376 """
Raymond Hettingered20ad82004-09-04 20:09:13 +00002377
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002378 init()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002379 global TEST_ALL, DEBUG
Raymond Hettingered20ad82004-09-04 20:09:13 +00002380 TEST_ALL = arith or is_resource_enabled('decimal')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002381 DEBUG = debug
Raymond Hettingered20ad82004-09-04 20:09:13 +00002382
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002383 if todo_tests is None:
2384 test_classes = [
2385 DecimalExplicitConstructionTest,
2386 DecimalImplicitConstructionTest,
2387 DecimalArithmeticOperatorsTest,
Christian Heimesf16baeb2008-02-29 14:57:44 +00002388 DecimalFormatTest,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002389 DecimalUseOfContextTest,
2390 DecimalUsabilityTest,
2391 DecimalPythonAPItests,
2392 ContextAPItests,
2393 DecimalTest,
2394 WithStatementTest,
2395 ContextFlags
2396 ]
2397 else:
2398 test_classes = [DecimalTest]
2399
2400 # Dynamically build custom test definition for each file in the test
2401 # directory and add the definitions to the DecimalTest class. This
2402 # procedure insures that new files do not get skipped.
2403 for filename in os.listdir(directory):
2404 if '.decTest' not in filename or filename.startswith("."):
2405 continue
2406 head, tail = filename.split('.')
2407 if todo_tests is not None and head not in todo_tests:
2408 continue
2409 tester = lambda self, f=filename: self.eval_file(directory + f)
2410 setattr(DecimalTest, 'test_' + head, tester)
2411 del filename, head, tail, tester
2412
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002413
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002414 try:
2415 run_unittest(*test_classes)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002416 if todo_tests is None:
2417 import decimal as DecimalModule
2418 run_doctest(DecimalModule, verbose)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002419 finally:
2420 setcontext(ORIGINAL_CONTEXT)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002421
2422if __name__ == '__main__':
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002423 import optparse
2424 p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]")
2425 p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test')
2426 p.add_option('--skip', '-s', action='store_true', help='skip over 90% of the arithmetic tests')
2427 (opt, args) = p.parse_args()
2428
2429 if opt.skip:
2430 test_main(arith=False, verbose=True)
2431 elif args:
2432 test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002433 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002434 test_main(arith=True, verbose=True)