blob: 3ff855fc1ccca35075ae79ed02c9e76cf5519ca9 [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
Mark Dickinsone4204bc2012-08-24 19:32:13 +01001521 def test_nan_to_float(self):
1522 # Test conversions of decimal NANs to float.
1523 # See http://bugs.python.org/issue15544
1524 Decimal = self.decimal.Decimal
1525 for s in ('nan', 'nan1234', '-nan', '-nan2468'):
1526 f = float(Decimal(s))
1527 self.assertTrue(math.isnan(f))
1528 sign = math.copysign(1.0, f)
1529 self.assertEqual(sign, -1.0 if s.startswith('-') else 1.0)
1530
1531 def test_snan_to_float(self):
1532 Decimal = self.decimal.Decimal
1533 for s in ('snan', '-snan', 'snan1357', '-snan1234'):
1534 d = Decimal(s)
1535 self.assertRaises(ValueError, float, d)
1536
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001537 def test_eval_round_trip(self):
1538
1539 #with zero
1540 d = Decimal( (0, (0,), 0) )
1541 self.assertEqual(d, eval(repr(d)))
1542
1543 #int
1544 d = Decimal( (1, (4, 5), 0) )
1545 self.assertEqual(d, eval(repr(d)))
1546
1547 #float
1548 d = Decimal( (0, (4, 5, 3, 4), -2) )
1549 self.assertEqual(d, eval(repr(d)))
1550
1551 #weird
1552 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1553 self.assertEqual(d, eval(repr(d)))
1554
1555 def test_as_tuple(self):
1556
1557 #with zero
1558 d = Decimal(0)
1559 self.assertEqual(d.as_tuple(), (0, (0,), 0) )
1560
1561 #int
1562 d = Decimal(-45)
1563 self.assertEqual(d.as_tuple(), (1, (4, 5), 0) )
1564
1565 #complicated string
1566 d = Decimal("-4.34913534E-17")
1567 self.assertEqual(d.as_tuple(), (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1568
1569 #inf
1570 d = Decimal("Infinity")
1571 self.assertEqual(d.as_tuple(), (0, (0,), 'F') )
1572
Guido van Rossum8ce8a782007-11-01 19:42:39 +00001573 #leading zeros in coefficient should be stripped
1574 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), -2) )
1575 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), -2) )
1576 d = Decimal( (1, (0, 0, 0), 37) )
1577 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1578 d = Decimal( (1, (), 37) )
1579 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1580
1581 #leading zeros in NaN diagnostic info should be stripped
1582 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), 'n') )
1583 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), 'n') )
1584 d = Decimal( (1, (0, 0, 0), 'N') )
1585 self.assertEqual(d.as_tuple(), (1, (), 'N') )
1586 d = Decimal( (1, (), 'n') )
1587 self.assertEqual(d.as_tuple(), (1, (), 'n') )
1588
1589 #coefficient in infinity should be ignored
1590 d = Decimal( (0, (4, 5, 3, 4), 'F') )
1591 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
1592 d = Decimal( (1, (0, 2, 7, 1), 'F') )
1593 self.assertEqual(d.as_tuple(), (1, (0,), 'F'))
1594
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001595 def test_immutability_operations(self):
1596 # Do operations and check that it didn't change change internal objects.
1597
1598 d1 = Decimal('-25e55')
1599 b1 = Decimal('-25e55')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001600 d2 = Decimal('33e+33')
1601 b2 = Decimal('33e+33')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001602
1603 def checkSameDec(operation, useOther=False):
1604 if useOther:
1605 eval("d1." + operation + "(d2)")
1606 self.assertEqual(d1._sign, b1._sign)
1607 self.assertEqual(d1._int, b1._int)
1608 self.assertEqual(d1._exp, b1._exp)
1609 self.assertEqual(d2._sign, b2._sign)
1610 self.assertEqual(d2._int, b2._int)
1611 self.assertEqual(d2._exp, b2._exp)
1612 else:
1613 eval("d1." + operation + "()")
1614 self.assertEqual(d1._sign, b1._sign)
1615 self.assertEqual(d1._int, b1._int)
1616 self.assertEqual(d1._exp, b1._exp)
1617 return
1618
1619 Decimal(d1)
1620 self.assertEqual(d1._sign, b1._sign)
1621 self.assertEqual(d1._int, b1._int)
1622 self.assertEqual(d1._exp, b1._exp)
1623
1624 checkSameDec("__abs__")
1625 checkSameDec("__add__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001626 checkSameDec("__divmod__", True)
Christian Heimes77c02eb2008-02-09 02:18:51 +00001627 checkSameDec("__eq__", True)
1628 checkSameDec("__ne__", True)
1629 checkSameDec("__le__", True)
1630 checkSameDec("__lt__", True)
1631 checkSameDec("__ge__", True)
1632 checkSameDec("__gt__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001633 checkSameDec("__float__")
1634 checkSameDec("__floordiv__", True)
1635 checkSameDec("__hash__")
1636 checkSameDec("__int__")
Christian Heimes969fe572008-01-25 11:23:10 +00001637 checkSameDec("__trunc__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001638 checkSameDec("__mod__", True)
1639 checkSameDec("__mul__", True)
1640 checkSameDec("__neg__")
Jack Diederich4dafcc42006-11-28 19:15:13 +00001641 checkSameDec("__bool__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001642 checkSameDec("__pos__")
1643 checkSameDec("__pow__", True)
1644 checkSameDec("__radd__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001645 checkSameDec("__rdivmod__", True)
1646 checkSameDec("__repr__")
1647 checkSameDec("__rfloordiv__", True)
1648 checkSameDec("__rmod__", True)
1649 checkSameDec("__rmul__", True)
1650 checkSameDec("__rpow__", True)
1651 checkSameDec("__rsub__", True)
1652 checkSameDec("__str__")
1653 checkSameDec("__sub__", True)
1654 checkSameDec("__truediv__", True)
1655 checkSameDec("adjusted")
1656 checkSameDec("as_tuple")
1657 checkSameDec("compare", True)
1658 checkSameDec("max", True)
1659 checkSameDec("min", True)
1660 checkSameDec("normalize")
1661 checkSameDec("quantize", True)
1662 checkSameDec("remainder_near", True)
1663 checkSameDec("same_quantum", True)
1664 checkSameDec("sqrt")
1665 checkSameDec("to_eng_string")
1666 checkSameDec("to_integral")
1667
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001668 def test_subclassing(self):
1669 # Different behaviours when subclassing Decimal
1670
1671 class MyDecimal(Decimal):
1672 pass
1673
1674 d1 = MyDecimal(1)
1675 d2 = MyDecimal(2)
1676 d = d1 + d2
Ezio Melotti6607d512010-04-03 14:59:49 +00001677 self.assertIs(type(d), Decimal)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001678
1679 d = d1.max(d2)
Ezio Melotti6607d512010-04-03 14:59:49 +00001680 self.assertIs(type(d), Decimal)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001681
Christian Heimes0348fb62008-03-26 12:55:56 +00001682 def test_implicit_context(self):
1683 # Check results when context given implicitly. (Issue 2478)
1684 c = getcontext()
1685 self.assertEqual(str(Decimal(0).sqrt()),
1686 str(c.sqrt(Decimal(0))))
1687
Mark Dickinsona2d1fe02009-10-29 12:23:02 +00001688 def test_conversions_from_int(self):
1689 # Check that methods taking a second Decimal argument will
1690 # always accept an integer in place of a Decimal.
1691 self.assertEqual(Decimal(4).compare(3),
1692 Decimal(4).compare(Decimal(3)))
1693 self.assertEqual(Decimal(4).compare_signal(3),
1694 Decimal(4).compare_signal(Decimal(3)))
1695 self.assertEqual(Decimal(4).compare_total(3),
1696 Decimal(4).compare_total(Decimal(3)))
1697 self.assertEqual(Decimal(4).compare_total_mag(3),
1698 Decimal(4).compare_total_mag(Decimal(3)))
1699 self.assertEqual(Decimal(10101).logical_and(1001),
1700 Decimal(10101).logical_and(Decimal(1001)))
1701 self.assertEqual(Decimal(10101).logical_or(1001),
1702 Decimal(10101).logical_or(Decimal(1001)))
1703 self.assertEqual(Decimal(10101).logical_xor(1001),
1704 Decimal(10101).logical_xor(Decimal(1001)))
1705 self.assertEqual(Decimal(567).max(123),
1706 Decimal(567).max(Decimal(123)))
1707 self.assertEqual(Decimal(567).max_mag(123),
1708 Decimal(567).max_mag(Decimal(123)))
1709 self.assertEqual(Decimal(567).min(123),
1710 Decimal(567).min(Decimal(123)))
1711 self.assertEqual(Decimal(567).min_mag(123),
1712 Decimal(567).min_mag(Decimal(123)))
1713 self.assertEqual(Decimal(567).next_toward(123),
1714 Decimal(567).next_toward(Decimal(123)))
1715 self.assertEqual(Decimal(1234).quantize(100),
1716 Decimal(1234).quantize(Decimal(100)))
1717 self.assertEqual(Decimal(768).remainder_near(1234),
1718 Decimal(768).remainder_near(Decimal(1234)))
1719 self.assertEqual(Decimal(123).rotate(1),
1720 Decimal(123).rotate(Decimal(1)))
1721 self.assertEqual(Decimal(1234).same_quantum(1000),
1722 Decimal(1234).same_quantum(Decimal(1000)))
1723 self.assertEqual(Decimal('9.123').scaleb(-100),
1724 Decimal('9.123').scaleb(Decimal(-100)))
1725 self.assertEqual(Decimal(456).shift(-1),
1726 Decimal(456).shift(Decimal(-1)))
1727
1728 self.assertEqual(Decimal(-12).fma(Decimal(45), 67),
1729 Decimal(-12).fma(Decimal(45), Decimal(67)))
1730 self.assertEqual(Decimal(-12).fma(45, 67),
1731 Decimal(-12).fma(Decimal(45), Decimal(67)))
1732 self.assertEqual(Decimal(-12).fma(45, Decimal(67)),
1733 Decimal(-12).fma(Decimal(45), Decimal(67)))
1734
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001735
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001736class DecimalPythonAPItests(unittest.TestCase):
1737
Raymond Hettinger82417ca2009-02-03 03:54:28 +00001738 def test_abc(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001739 self.assertTrue(issubclass(Decimal, numbers.Number))
Ezio Melotti6607d512010-04-03 14:59:49 +00001740 self.assertFalse(issubclass(Decimal, numbers.Real))
Ezio Melottie9615932010-01-24 19:26:24 +00001741 self.assertIsInstance(Decimal(0), numbers.Number)
1742 self.assertNotIsInstance(Decimal(0), numbers.Real)
Raymond Hettinger82417ca2009-02-03 03:54:28 +00001743
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001744 def test_pickle(self):
1745 d = Decimal('-3.141590000')
1746 p = pickle.dumps(d)
1747 e = pickle.loads(p)
1748 self.assertEqual(d, e)
1749
Raymond Hettinger5548be22004-07-05 18:49:38 +00001750 def test_int(self):
Raymond Hettinger605ed022004-11-24 07:28:48 +00001751 for x in range(-250, 250):
1752 s = '%0.2f' % (x / 100.0)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001753 # should work the same as for floats
1754 self.assertEqual(int(Decimal(s)), int(float(s)))
Raymond Hettinger605ed022004-11-24 07:28:48 +00001755 # should work the same as to_integral in the ROUND_DOWN mode
Raymond Hettinger5548be22004-07-05 18:49:38 +00001756 d = Decimal(s)
Raymond Hettinger605ed022004-11-24 07:28:48 +00001757 r = d.to_integral(ROUND_DOWN)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001758 self.assertEqual(Decimal(int(d)), r)
1759
Mark Dickinson825fce32009-09-07 18:08:12 +00001760 self.assertRaises(ValueError, int, Decimal('-nan'))
1761 self.assertRaises(ValueError, int, Decimal('snan'))
1762 self.assertRaises(OverflowError, int, Decimal('inf'))
1763 self.assertRaises(OverflowError, int, Decimal('-inf'))
1764
Christian Heimes969fe572008-01-25 11:23:10 +00001765 def test_trunc(self):
1766 for x in range(-250, 250):
1767 s = '%0.2f' % (x / 100.0)
1768 # should work the same as for floats
1769 self.assertEqual(int(Decimal(s)), int(float(s)))
1770 # should work the same as to_integral in the ROUND_DOWN mode
1771 d = Decimal(s)
1772 r = d.to_integral(ROUND_DOWN)
Christian Heimes400adb02008-02-01 08:12:03 +00001773 self.assertEqual(Decimal(math.trunc(d)), r)
Christian Heimes969fe572008-01-25 11:23:10 +00001774
Raymond Hettinger771ed762009-01-03 19:20:32 +00001775 def test_from_float(self):
1776
1777 class MyDecimal(Decimal):
1778 pass
1779
1780 r = MyDecimal.from_float(0.1)
1781 self.assertEqual(type(r), MyDecimal)
1782 self.assertEqual(str(r),
1783 '0.1000000000000000055511151231257827021181583404541015625')
1784 bigint = 12345678901234567890123456789
1785 self.assertEqual(MyDecimal.from_float(bigint), MyDecimal(bigint))
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001786 self.assertTrue(MyDecimal.from_float(float('nan')).is_qnan())
1787 self.assertTrue(MyDecimal.from_float(float('inf')).is_infinite())
1788 self.assertTrue(MyDecimal.from_float(float('-inf')).is_infinite())
Raymond Hettinger771ed762009-01-03 19:20:32 +00001789 self.assertEqual(str(MyDecimal.from_float(float('nan'))),
1790 str(Decimal('NaN')))
1791 self.assertEqual(str(MyDecimal.from_float(float('inf'))),
1792 str(Decimal('Infinity')))
1793 self.assertEqual(str(MyDecimal.from_float(float('-inf'))),
1794 str(Decimal('-Infinity')))
1795 self.assertRaises(TypeError, MyDecimal.from_float, 'abc')
1796 for i in range(200):
1797 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
1798 self.assertEqual(x, float(MyDecimal.from_float(x))) # roundtrip
1799
1800 def test_create_decimal_from_float(self):
1801 context = Context(prec=5, rounding=ROUND_DOWN)
1802 self.assertEqual(
1803 context.create_decimal_from_float(math.pi),
1804 Decimal('3.1415')
1805 )
1806 context = Context(prec=5, rounding=ROUND_UP)
1807 self.assertEqual(
1808 context.create_decimal_from_float(math.pi),
1809 Decimal('3.1416')
1810 )
1811 context = Context(prec=5, traps=[Inexact])
1812 self.assertRaises(
1813 Inexact,
1814 context.create_decimal_from_float,
1815 math.pi
1816 )
1817 self.assertEqual(repr(context.create_decimal_from_float(-0.0)),
1818 "Decimal('-0')")
1819 self.assertEqual(repr(context.create_decimal_from_float(1.0)),
1820 "Decimal('1')")
1821 self.assertEqual(repr(context.create_decimal_from_float(10)),
1822 "Decimal('10')")
1823
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00001824class ContextAPItests(unittest.TestCase):
1825
1826 def test_pickle(self):
1827 c = Context()
1828 e = pickle.loads(pickle.dumps(c))
1829 for k in vars(c):
1830 v1 = vars(c)[k]
1831 v2 = vars(e)[k]
1832 self.assertEqual(v1, v2)
1833
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001834 def test_equality_with_other_types(self):
Benjamin Peterson577473f2010-01-19 00:09:57 +00001835 self.assertIn(Decimal(10), ['a', 1.0, Decimal(10), (1,2), {}])
1836 self.assertNotIn(Decimal(10), ['a', 1.0, (1,2), {}])
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001837
Raymond Hettinger955d2b22004-08-08 20:17:45 +00001838 def test_copy(self):
1839 # All copies should be deep
1840 c = Context()
1841 d = c.copy()
1842 self.assertNotEqual(id(c), id(d))
1843 self.assertNotEqual(id(c.flags), id(d.flags))
1844 self.assertNotEqual(id(c.traps), id(d.traps))
1845
Mark Dickinsonb1d8e322010-05-22 18:35:36 +00001846 def test__clamp(self):
1847 # In Python 3.2, the private attribute `_clamp` was made
1848 # public (issue 8540), with the old `_clamp` becoming a
1849 # property wrapping `clamp`. For the duration of Python 3.2
1850 # only, the attribute should be gettable/settable via both
1851 # `clamp` and `_clamp`; in Python 3.3, `_clamp` should be
1852 # removed.
1853 c = Context(clamp = 0)
1854 self.assertEqual(c.clamp, 0)
1855
1856 with check_warnings(("", DeprecationWarning)):
1857 c._clamp = 1
1858 self.assertEqual(c.clamp, 1)
1859 with check_warnings(("", DeprecationWarning)):
1860 self.assertEqual(c._clamp, 1)
1861 c.clamp = 0
1862 self.assertEqual(c.clamp, 0)
1863 with check_warnings(("", DeprecationWarning)):
1864 self.assertEqual(c._clamp, 0)
1865
Mark Dickinson84230a12010-02-18 14:49:50 +00001866 def test_abs(self):
1867 c = Context()
1868 d = c.abs(Decimal(-1))
1869 self.assertEqual(c.abs(-1), d)
1870 self.assertRaises(TypeError, c.abs, '-1')
1871
1872 def test_add(self):
1873 c = Context()
1874 d = c.add(Decimal(1), Decimal(1))
1875 self.assertEqual(c.add(1, 1), d)
1876 self.assertEqual(c.add(Decimal(1), 1), d)
1877 self.assertEqual(c.add(1, Decimal(1)), d)
1878 self.assertRaises(TypeError, c.add, '1', 1)
1879 self.assertRaises(TypeError, c.add, 1, '1')
1880
1881 def test_compare(self):
1882 c = Context()
1883 d = c.compare(Decimal(1), Decimal(1))
1884 self.assertEqual(c.compare(1, 1), d)
1885 self.assertEqual(c.compare(Decimal(1), 1), d)
1886 self.assertEqual(c.compare(1, Decimal(1)), d)
1887 self.assertRaises(TypeError, c.compare, '1', 1)
1888 self.assertRaises(TypeError, c.compare, 1, '1')
1889
1890 def test_compare_signal(self):
1891 c = Context()
1892 d = c.compare_signal(Decimal(1), Decimal(1))
1893 self.assertEqual(c.compare_signal(1, 1), d)
1894 self.assertEqual(c.compare_signal(Decimal(1), 1), d)
1895 self.assertEqual(c.compare_signal(1, Decimal(1)), d)
1896 self.assertRaises(TypeError, c.compare_signal, '1', 1)
1897 self.assertRaises(TypeError, c.compare_signal, 1, '1')
1898
1899 def test_compare_total(self):
1900 c = Context()
1901 d = c.compare_total(Decimal(1), Decimal(1))
1902 self.assertEqual(c.compare_total(1, 1), d)
1903 self.assertEqual(c.compare_total(Decimal(1), 1), d)
1904 self.assertEqual(c.compare_total(1, Decimal(1)), d)
1905 self.assertRaises(TypeError, c.compare_total, '1', 1)
1906 self.assertRaises(TypeError, c.compare_total, 1, '1')
1907
1908 def test_compare_total_mag(self):
1909 c = Context()
1910 d = c.compare_total_mag(Decimal(1), Decimal(1))
1911 self.assertEqual(c.compare_total_mag(1, 1), d)
1912 self.assertEqual(c.compare_total_mag(Decimal(1), 1), d)
1913 self.assertEqual(c.compare_total_mag(1, Decimal(1)), d)
1914 self.assertRaises(TypeError, c.compare_total_mag, '1', 1)
1915 self.assertRaises(TypeError, c.compare_total_mag, 1, '1')
1916
1917 def test_copy_abs(self):
1918 c = Context()
1919 d = c.copy_abs(Decimal(-1))
1920 self.assertEqual(c.copy_abs(-1), d)
1921 self.assertRaises(TypeError, c.copy_abs, '-1')
1922
1923 def test_copy_decimal(self):
1924 c = Context()
1925 d = c.copy_decimal(Decimal(-1))
1926 self.assertEqual(c.copy_decimal(-1), d)
1927 self.assertRaises(TypeError, c.copy_decimal, '-1')
1928
1929 def test_copy_negate(self):
1930 c = Context()
1931 d = c.copy_negate(Decimal(-1))
1932 self.assertEqual(c.copy_negate(-1), d)
1933 self.assertRaises(TypeError, c.copy_negate, '-1')
1934
1935 def test_copy_sign(self):
1936 c = Context()
1937 d = c.copy_sign(Decimal(1), Decimal(-2))
1938 self.assertEqual(c.copy_sign(1, -2), d)
1939 self.assertEqual(c.copy_sign(Decimal(1), -2), d)
1940 self.assertEqual(c.copy_sign(1, Decimal(-2)), d)
1941 self.assertRaises(TypeError, c.copy_sign, '1', -2)
1942 self.assertRaises(TypeError, c.copy_sign, 1, '-2')
1943
1944 def test_divide(self):
1945 c = Context()
1946 d = c.divide(Decimal(1), Decimal(2))
1947 self.assertEqual(c.divide(1, 2), d)
1948 self.assertEqual(c.divide(Decimal(1), 2), d)
1949 self.assertEqual(c.divide(1, Decimal(2)), d)
1950 self.assertRaises(TypeError, c.divide, '1', 2)
1951 self.assertRaises(TypeError, c.divide, 1, '2')
1952
1953 def test_divide_int(self):
1954 c = Context()
1955 d = c.divide_int(Decimal(1), Decimal(2))
1956 self.assertEqual(c.divide_int(1, 2), d)
1957 self.assertEqual(c.divide_int(Decimal(1), 2), d)
1958 self.assertEqual(c.divide_int(1, Decimal(2)), d)
1959 self.assertRaises(TypeError, c.divide_int, '1', 2)
1960 self.assertRaises(TypeError, c.divide_int, 1, '2')
1961
1962 def test_divmod(self):
1963 c = Context()
1964 d = c.divmod(Decimal(1), Decimal(2))
1965 self.assertEqual(c.divmod(1, 2), d)
1966 self.assertEqual(c.divmod(Decimal(1), 2), d)
1967 self.assertEqual(c.divmod(1, Decimal(2)), d)
1968 self.assertRaises(TypeError, c.divmod, '1', 2)
1969 self.assertRaises(TypeError, c.divmod, 1, '2')
1970
1971 def test_exp(self):
1972 c = Context()
1973 d = c.exp(Decimal(10))
1974 self.assertEqual(c.exp(10), d)
1975 self.assertRaises(TypeError, c.exp, '10')
1976
1977 def test_fma(self):
1978 c = Context()
1979 d = c.fma(Decimal(2), Decimal(3), Decimal(4))
1980 self.assertEqual(c.fma(2, 3, 4), d)
1981 self.assertEqual(c.fma(Decimal(2), 3, 4), d)
1982 self.assertEqual(c.fma(2, Decimal(3), 4), d)
1983 self.assertEqual(c.fma(2, 3, Decimal(4)), d)
1984 self.assertEqual(c.fma(Decimal(2), Decimal(3), 4), d)
1985 self.assertRaises(TypeError, c.fma, '2', 3, 4)
1986 self.assertRaises(TypeError, c.fma, 2, '3', 4)
1987 self.assertRaises(TypeError, c.fma, 2, 3, '4')
1988
1989 def test_is_finite(self):
1990 c = Context()
1991 d = c.is_finite(Decimal(10))
1992 self.assertEqual(c.is_finite(10), d)
1993 self.assertRaises(TypeError, c.is_finite, '10')
1994
1995 def test_is_infinite(self):
1996 c = Context()
1997 d = c.is_infinite(Decimal(10))
1998 self.assertEqual(c.is_infinite(10), d)
1999 self.assertRaises(TypeError, c.is_infinite, '10')
2000
2001 def test_is_nan(self):
2002 c = Context()
2003 d = c.is_nan(Decimal(10))
2004 self.assertEqual(c.is_nan(10), d)
2005 self.assertRaises(TypeError, c.is_nan, '10')
2006
2007 def test_is_normal(self):
2008 c = Context()
2009 d = c.is_normal(Decimal(10))
2010 self.assertEqual(c.is_normal(10), d)
2011 self.assertRaises(TypeError, c.is_normal, '10')
2012
2013 def test_is_qnan(self):
2014 c = Context()
2015 d = c.is_qnan(Decimal(10))
2016 self.assertEqual(c.is_qnan(10), d)
2017 self.assertRaises(TypeError, c.is_qnan, '10')
2018
2019 def test_is_signed(self):
2020 c = Context()
2021 d = c.is_signed(Decimal(10))
2022 self.assertEqual(c.is_signed(10), d)
2023 self.assertRaises(TypeError, c.is_signed, '10')
2024
2025 def test_is_snan(self):
2026 c = Context()
2027 d = c.is_snan(Decimal(10))
2028 self.assertEqual(c.is_snan(10), d)
2029 self.assertRaises(TypeError, c.is_snan, '10')
2030
2031 def test_is_subnormal(self):
2032 c = Context()
2033 d = c.is_subnormal(Decimal(10))
2034 self.assertEqual(c.is_subnormal(10), d)
2035 self.assertRaises(TypeError, c.is_subnormal, '10')
2036
2037 def test_is_zero(self):
2038 c = Context()
2039 d = c.is_zero(Decimal(10))
2040 self.assertEqual(c.is_zero(10), d)
2041 self.assertRaises(TypeError, c.is_zero, '10')
2042
2043 def test_ln(self):
2044 c = Context()
2045 d = c.ln(Decimal(10))
2046 self.assertEqual(c.ln(10), d)
2047 self.assertRaises(TypeError, c.ln, '10')
2048
2049 def test_log10(self):
2050 c = Context()
2051 d = c.log10(Decimal(10))
2052 self.assertEqual(c.log10(10), d)
2053 self.assertRaises(TypeError, c.log10, '10')
2054
2055 def test_logb(self):
2056 c = Context()
2057 d = c.logb(Decimal(10))
2058 self.assertEqual(c.logb(10), d)
2059 self.assertRaises(TypeError, c.logb, '10')
2060
2061 def test_logical_and(self):
2062 c = Context()
2063 d = c.logical_and(Decimal(1), Decimal(1))
2064 self.assertEqual(c.logical_and(1, 1), d)
2065 self.assertEqual(c.logical_and(Decimal(1), 1), d)
2066 self.assertEqual(c.logical_and(1, Decimal(1)), d)
2067 self.assertRaises(TypeError, c.logical_and, '1', 1)
2068 self.assertRaises(TypeError, c.logical_and, 1, '1')
2069
2070 def test_logical_invert(self):
2071 c = Context()
2072 d = c.logical_invert(Decimal(1000))
2073 self.assertEqual(c.logical_invert(1000), d)
2074 self.assertRaises(TypeError, c.logical_invert, '1000')
2075
2076 def test_logical_or(self):
2077 c = Context()
2078 d = c.logical_or(Decimal(1), Decimal(1))
2079 self.assertEqual(c.logical_or(1, 1), d)
2080 self.assertEqual(c.logical_or(Decimal(1), 1), d)
2081 self.assertEqual(c.logical_or(1, Decimal(1)), d)
2082 self.assertRaises(TypeError, c.logical_or, '1', 1)
2083 self.assertRaises(TypeError, c.logical_or, 1, '1')
2084
2085 def test_logical_xor(self):
2086 c = Context()
2087 d = c.logical_xor(Decimal(1), Decimal(1))
2088 self.assertEqual(c.logical_xor(1, 1), d)
2089 self.assertEqual(c.logical_xor(Decimal(1), 1), d)
2090 self.assertEqual(c.logical_xor(1, Decimal(1)), d)
2091 self.assertRaises(TypeError, c.logical_xor, '1', 1)
2092 self.assertRaises(TypeError, c.logical_xor, 1, '1')
2093
2094 def test_max(self):
2095 c = Context()
2096 d = c.max(Decimal(1), Decimal(2))
2097 self.assertEqual(c.max(1, 2), d)
2098 self.assertEqual(c.max(Decimal(1), 2), d)
2099 self.assertEqual(c.max(1, Decimal(2)), d)
2100 self.assertRaises(TypeError, c.max, '1', 2)
2101 self.assertRaises(TypeError, c.max, 1, '2')
2102
2103 def test_max_mag(self):
2104 c = Context()
2105 d = c.max_mag(Decimal(1), Decimal(2))
2106 self.assertEqual(c.max_mag(1, 2), d)
2107 self.assertEqual(c.max_mag(Decimal(1), 2), d)
2108 self.assertEqual(c.max_mag(1, Decimal(2)), d)
2109 self.assertRaises(TypeError, c.max_mag, '1', 2)
2110 self.assertRaises(TypeError, c.max_mag, 1, '2')
2111
2112 def test_min(self):
2113 c = Context()
2114 d = c.min(Decimal(1), Decimal(2))
2115 self.assertEqual(c.min(1, 2), d)
2116 self.assertEqual(c.min(Decimal(1), 2), d)
2117 self.assertEqual(c.min(1, Decimal(2)), d)
2118 self.assertRaises(TypeError, c.min, '1', 2)
2119 self.assertRaises(TypeError, c.min, 1, '2')
2120
2121 def test_min_mag(self):
2122 c = Context()
2123 d = c.min_mag(Decimal(1), Decimal(2))
2124 self.assertEqual(c.min_mag(1, 2), d)
2125 self.assertEqual(c.min_mag(Decimal(1), 2), d)
2126 self.assertEqual(c.min_mag(1, Decimal(2)), d)
2127 self.assertRaises(TypeError, c.min_mag, '1', 2)
2128 self.assertRaises(TypeError, c.min_mag, 1, '2')
2129
2130 def test_minus(self):
2131 c = Context()
2132 d = c.minus(Decimal(10))
2133 self.assertEqual(c.minus(10), d)
2134 self.assertRaises(TypeError, c.minus, '10')
2135
2136 def test_multiply(self):
2137 c = Context()
2138 d = c.multiply(Decimal(1), Decimal(2))
2139 self.assertEqual(c.multiply(1, 2), d)
2140 self.assertEqual(c.multiply(Decimal(1), 2), d)
2141 self.assertEqual(c.multiply(1, Decimal(2)), d)
2142 self.assertRaises(TypeError, c.multiply, '1', 2)
2143 self.assertRaises(TypeError, c.multiply, 1, '2')
2144
2145 def test_next_minus(self):
2146 c = Context()
2147 d = c.next_minus(Decimal(10))
2148 self.assertEqual(c.next_minus(10), d)
2149 self.assertRaises(TypeError, c.next_minus, '10')
2150
2151 def test_next_plus(self):
2152 c = Context()
2153 d = c.next_plus(Decimal(10))
2154 self.assertEqual(c.next_plus(10), d)
2155 self.assertRaises(TypeError, c.next_plus, '10')
2156
2157 def test_next_toward(self):
2158 c = Context()
2159 d = c.next_toward(Decimal(1), Decimal(2))
2160 self.assertEqual(c.next_toward(1, 2), d)
2161 self.assertEqual(c.next_toward(Decimal(1), 2), d)
2162 self.assertEqual(c.next_toward(1, Decimal(2)), d)
2163 self.assertRaises(TypeError, c.next_toward, '1', 2)
2164 self.assertRaises(TypeError, c.next_toward, 1, '2')
2165
2166 def test_normalize(self):
2167 c = Context()
2168 d = c.normalize(Decimal(10))
2169 self.assertEqual(c.normalize(10), d)
2170 self.assertRaises(TypeError, c.normalize, '10')
2171
2172 def test_number_class(self):
2173 c = Context()
2174 self.assertEqual(c.number_class(123), c.number_class(Decimal(123)))
2175 self.assertEqual(c.number_class(0), c.number_class(Decimal(0)))
2176 self.assertEqual(c.number_class(-45), c.number_class(Decimal(-45)))
2177
2178 def test_power(self):
2179 c = Context()
2180 d = c.power(Decimal(1), Decimal(4), Decimal(2))
2181 self.assertEqual(c.power(1, 4, 2), d)
2182 self.assertEqual(c.power(Decimal(1), 4, 2), d)
2183 self.assertEqual(c.power(1, Decimal(4), 2), d)
2184 self.assertEqual(c.power(1, 4, Decimal(2)), d)
2185 self.assertEqual(c.power(Decimal(1), Decimal(4), 2), d)
2186 self.assertRaises(TypeError, c.power, '1', 4, 2)
2187 self.assertRaises(TypeError, c.power, 1, '4', 2)
2188 self.assertRaises(TypeError, c.power, 1, 4, '2')
2189
2190 def test_plus(self):
2191 c = Context()
2192 d = c.plus(Decimal(10))
2193 self.assertEqual(c.plus(10), d)
2194 self.assertRaises(TypeError, c.plus, '10')
2195
2196 def test_quantize(self):
2197 c = Context()
2198 d = c.quantize(Decimal(1), Decimal(2))
2199 self.assertEqual(c.quantize(1, 2), d)
2200 self.assertEqual(c.quantize(Decimal(1), 2), d)
2201 self.assertEqual(c.quantize(1, Decimal(2)), d)
2202 self.assertRaises(TypeError, c.quantize, '1', 2)
2203 self.assertRaises(TypeError, c.quantize, 1, '2')
2204
2205 def test_remainder(self):
2206 c = Context()
2207 d = c.remainder(Decimal(1), Decimal(2))
2208 self.assertEqual(c.remainder(1, 2), d)
2209 self.assertEqual(c.remainder(Decimal(1), 2), d)
2210 self.assertEqual(c.remainder(1, Decimal(2)), d)
2211 self.assertRaises(TypeError, c.remainder, '1', 2)
2212 self.assertRaises(TypeError, c.remainder, 1, '2')
2213
2214 def test_remainder_near(self):
2215 c = Context()
2216 d = c.remainder_near(Decimal(1), Decimal(2))
2217 self.assertEqual(c.remainder_near(1, 2), d)
2218 self.assertEqual(c.remainder_near(Decimal(1), 2), d)
2219 self.assertEqual(c.remainder_near(1, Decimal(2)), d)
2220 self.assertRaises(TypeError, c.remainder_near, '1', 2)
2221 self.assertRaises(TypeError, c.remainder_near, 1, '2')
2222
2223 def test_rotate(self):
2224 c = Context()
2225 d = c.rotate(Decimal(1), Decimal(2))
2226 self.assertEqual(c.rotate(1, 2), d)
2227 self.assertEqual(c.rotate(Decimal(1), 2), d)
2228 self.assertEqual(c.rotate(1, Decimal(2)), d)
2229 self.assertRaises(TypeError, c.rotate, '1', 2)
2230 self.assertRaises(TypeError, c.rotate, 1, '2')
2231
2232 def test_sqrt(self):
2233 c = Context()
2234 d = c.sqrt(Decimal(10))
2235 self.assertEqual(c.sqrt(10), d)
2236 self.assertRaises(TypeError, c.sqrt, '10')
2237
2238 def test_same_quantum(self):
2239 c = Context()
2240 d = c.same_quantum(Decimal(1), Decimal(2))
2241 self.assertEqual(c.same_quantum(1, 2), d)
2242 self.assertEqual(c.same_quantum(Decimal(1), 2), d)
2243 self.assertEqual(c.same_quantum(1, Decimal(2)), d)
2244 self.assertRaises(TypeError, c.same_quantum, '1', 2)
2245 self.assertRaises(TypeError, c.same_quantum, 1, '2')
2246
2247 def test_scaleb(self):
2248 c = Context()
2249 d = c.scaleb(Decimal(1), Decimal(2))
2250 self.assertEqual(c.scaleb(1, 2), d)
2251 self.assertEqual(c.scaleb(Decimal(1), 2), d)
2252 self.assertEqual(c.scaleb(1, Decimal(2)), d)
2253 self.assertRaises(TypeError, c.scaleb, '1', 2)
2254 self.assertRaises(TypeError, c.scaleb, 1, '2')
2255
2256 def test_shift(self):
2257 c = Context()
2258 d = c.shift(Decimal(1), Decimal(2))
2259 self.assertEqual(c.shift(1, 2), d)
2260 self.assertEqual(c.shift(Decimal(1), 2), d)
2261 self.assertEqual(c.shift(1, Decimal(2)), d)
2262 self.assertRaises(TypeError, c.shift, '1', 2)
2263 self.assertRaises(TypeError, c.shift, 1, '2')
2264
2265 def test_subtract(self):
2266 c = Context()
2267 d = c.subtract(Decimal(1), Decimal(2))
2268 self.assertEqual(c.subtract(1, 2), d)
2269 self.assertEqual(c.subtract(Decimal(1), 2), d)
2270 self.assertEqual(c.subtract(1, Decimal(2)), d)
2271 self.assertRaises(TypeError, c.subtract, '1', 2)
2272 self.assertRaises(TypeError, c.subtract, 1, '2')
2273
2274 def test_to_eng_string(self):
2275 c = Context()
2276 d = c.to_eng_string(Decimal(10))
2277 self.assertEqual(c.to_eng_string(10), d)
2278 self.assertRaises(TypeError, c.to_eng_string, '10')
2279
2280 def test_to_sci_string(self):
2281 c = Context()
2282 d = c.to_sci_string(Decimal(10))
2283 self.assertEqual(c.to_sci_string(10), d)
2284 self.assertRaises(TypeError, c.to_sci_string, '10')
2285
2286 def test_to_integral_exact(self):
2287 c = Context()
2288 d = c.to_integral_exact(Decimal(10))
2289 self.assertEqual(c.to_integral_exact(10), d)
2290 self.assertRaises(TypeError, c.to_integral_exact, '10')
2291
2292 def test_to_integral_value(self):
2293 c = Context()
2294 d = c.to_integral_value(Decimal(10))
2295 self.assertEqual(c.to_integral_value(10), d)
2296 self.assertRaises(TypeError, c.to_integral_value, '10')
2297
Thomas Wouters89f507f2006-12-13 04:49:30 +00002298class WithStatementTest(unittest.TestCase):
2299 # Can't do these as docstrings until Python 2.6
2300 # as doctest can't handle __future__ statements
2301
2302 def test_localcontext(self):
2303 # Use a copy of the current context in the block
2304 orig_ctx = getcontext()
2305 with localcontext() as enter_ctx:
2306 set_ctx = getcontext()
2307 final_ctx = getcontext()
Ezio Melotti6607d512010-04-03 14:59:49 +00002308 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
2309 self.assertIsNot(orig_ctx, set_ctx, 'did not copy the context')
2310 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
Thomas Wouters89f507f2006-12-13 04:49:30 +00002311
2312 def test_localcontextarg(self):
2313 # Use a copy of the supplied context in the block
2314 orig_ctx = getcontext()
2315 new_ctx = Context(prec=42)
2316 with localcontext(new_ctx) as enter_ctx:
2317 set_ctx = getcontext()
2318 final_ctx = getcontext()
Ezio Melotti6607d512010-04-03 14:59:49 +00002319 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
2320 self.assertEqual(set_ctx.prec, new_ctx.prec, 'did not set correct context')
2321 self.assertIsNot(new_ctx, set_ctx, 'did not copy the context')
2322 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
Thomas Wouters89f507f2006-12-13 04:49:30 +00002323
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002324class ContextFlags(unittest.TestCase):
2325 def test_flags_irrelevant(self):
2326 # check that the result (numeric result + flags raised) of an
2327 # arithmetic operation doesn't depend on the current flags
2328
2329 context = Context(prec=9, Emin = -999999999, Emax = 999999999,
2330 rounding=ROUND_HALF_EVEN, traps=[], flags=[])
2331
2332 # operations that raise various flags, in the form (function, arglist)
2333 operations = [
2334 (context._apply, [Decimal("100E-1000000009")]),
2335 (context.sqrt, [Decimal(2)]),
2336 (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]),
2337 (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]),
2338 (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]),
2339 ]
2340
2341 # try various flags individually, then a whole lot at once
2342 flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal],
2343 [Inexact, Rounded, Underflow, Clamped, Subnormal]]
2344
2345 for fn, args in operations:
2346 # find answer and flags raised using a clean context
2347 context.clear_flags()
2348 ans = fn(*args)
2349 flags = [k for k, v in context.flags.items() if v]
2350
2351 for extra_flags in flagsets:
2352 # set flags, before calling operation
2353 context.clear_flags()
2354 for flag in extra_flags:
2355 context._raise_error(flag)
2356 new_ans = fn(*args)
2357
2358 # flags that we expect to be set after the operation
2359 expected_flags = list(flags)
2360 for flag in extra_flags:
2361 if flag not in expected_flags:
2362 expected_flags.append(flag)
2363 expected_flags.sort(key=id)
2364
2365 # flags we actually got
2366 new_flags = [k for k,v in context.flags.items() if v]
2367 new_flags.sort(key=id)
2368
2369 self.assertEqual(ans, new_ans,
2370 "operation produces different answers depending on flags set: " +
2371 "expected %s, got %s." % (ans, new_ans))
2372 self.assertEqual(new_flags, expected_flags,
2373 "operation raises different flags depending on flags set: " +
2374 "expected %s, got %s" % (expected_flags, new_flags))
2375
2376def test_main(arith=False, verbose=None, todo_tests=None, debug=None):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002377 """ Execute the tests.
2378
Raymond Hettingered20ad82004-09-04 20:09:13 +00002379 Runs all arithmetic tests if arith is True or if the "decimal" resource
2380 is enabled in regrtest.py
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002381 """
Raymond Hettingered20ad82004-09-04 20:09:13 +00002382
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002383 init()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002384 global TEST_ALL, DEBUG
Raymond Hettingered20ad82004-09-04 20:09:13 +00002385 TEST_ALL = arith or is_resource_enabled('decimal')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002386 DEBUG = debug
Raymond Hettingered20ad82004-09-04 20:09:13 +00002387
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002388 if todo_tests is None:
2389 test_classes = [
2390 DecimalExplicitConstructionTest,
2391 DecimalImplicitConstructionTest,
2392 DecimalArithmeticOperatorsTest,
Christian Heimesf16baeb2008-02-29 14:57:44 +00002393 DecimalFormatTest,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002394 DecimalUseOfContextTest,
2395 DecimalUsabilityTest,
2396 DecimalPythonAPItests,
2397 ContextAPItests,
2398 DecimalTest,
2399 WithStatementTest,
2400 ContextFlags
2401 ]
2402 else:
2403 test_classes = [DecimalTest]
2404
2405 # Dynamically build custom test definition for each file in the test
2406 # directory and add the definitions to the DecimalTest class. This
2407 # procedure insures that new files do not get skipped.
2408 for filename in os.listdir(directory):
2409 if '.decTest' not in filename or filename.startswith("."):
2410 continue
2411 head, tail = filename.split('.')
2412 if todo_tests is not None and head not in todo_tests:
2413 continue
2414 tester = lambda self, f=filename: self.eval_file(directory + f)
2415 setattr(DecimalTest, 'test_' + head, tester)
2416 del filename, head, tail, tester
2417
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002418
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002419 try:
2420 run_unittest(*test_classes)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002421 if todo_tests is None:
2422 import decimal as DecimalModule
2423 run_doctest(DecimalModule, verbose)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002424 finally:
2425 setcontext(ORIGINAL_CONTEXT)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002426
2427if __name__ == '__main__':
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002428 import optparse
2429 p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]")
2430 p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test')
2431 p.add_option('--skip', '-s', action='store_true', help='skip over 90% of the arithmetic tests')
2432 (opt, args) = p.parse_args()
2433
2434 if opt.skip:
2435 test_main(arith=False, verbose=True)
2436 elif args:
2437 test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002438 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002439 test_main(arith=True, verbose=True)