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