blob: 3036170aeb83c77038d2f9ff43838ea47d3ca8c7 [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
Benjamin Petersone549ead2009-03-28 21:42:05 +000035from test.support import run_unittest, run_doctest, is_resource_enabled
Mark Dickinsonb1d8e322010-05-22 18:35:36 +000036from test.support import check_warnings
Raymond Hettinger0aeac102004-07-05 22:53:03 +000037import random
Raymond Hettinger7e71fa52004-12-18 19:07:19 +000038try:
39 import threading
40except ImportError:
41 threading = None
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000042
Raymond Hettingerfed52962004-07-14 15:41:57 +000043# Useful Test Constant
Guido van Rossumc1f779c2007-07-03 08:25:58 +000044Signals = tuple(getcontext().flags.keys())
Raymond Hettingerfed52962004-07-14 15:41:57 +000045
Mark Dickinsonc69160e2010-05-04 14:35:33 +000046# Signals ordered with respect to precedence: when an operation
47# produces multiple signals, signals occurring later in the list
48# should be handled before those occurring earlier in the list.
49OrderedSignals = (Clamped, Rounded, Inexact, Subnormal,
50 Underflow, Overflow, DivisionByZero, InvalidOperation)
51
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000052# Tests are built around these assumed context defaults.
53# test_main() restores the original context.
54def init():
55 global ORIGINAL_CONTEXT
56 ORIGINAL_CONTEXT = getcontext().copy()
Christian Heimes81ee3ef2008-05-04 22:42:01 +000057 DefaultTestContext = Context(
58 prec = 9,
59 rounding = ROUND_HALF_EVEN,
60 traps = dict.fromkeys(Signals, 0)
61 )
62 setcontext(DefaultTestContext)
Raymond Hettinger6ea48452004-07-03 12:26:21 +000063
Raymond Hettinger96798592010-04-02 16:58:27 +000064# decorator for skipping tests on non-IEEE 754 platforms
65requires_IEEE_754 = unittest.skipUnless(
66 float.__getformat__("double").startswith("IEEE"),
67 "test requires IEEE 754 doubles")
68
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000069TESTDATADIR = 'decimaltestdata'
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +000070if __name__ == '__main__':
71 file = sys.argv[0]
72else:
73 file = __file__
74testdir = os.path.dirname(file) or os.curdir
Raymond Hettinger267b8682005-03-27 10:47:39 +000075directory = testdir + os.sep + TESTDATADIR + os.sep
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000076
Raymond Hettinger267b8682005-03-27 10:47:39 +000077skip_expected = not os.path.isdir(directory)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000078
Mark Dickinson8a546532009-10-08 16:30:38 +000079# list of individual .decTest test ids that correspond to tests that
80# we're skipping for one reason or another.
Mark Dickinson247900c2010-07-08 17:23:40 +000081skipped_test_ids = set([
82 # Skip implementation-specific scaleb tests.
83 'scbx164',
84 'scbx165',
85
86 # For some operations (currently exp, ln, log10, power), the decNumber
87 # reference implementation imposes additional restrictions on the context
88 # and operands. These restrictions are not part of the specification;
89 # however, the effect of these restrictions does show up in some of the
90 # testcases. We skip testcases that violate these restrictions, since
91 # Decimal behaves differently from decNumber for these testcases so these
92 # testcases would otherwise fail.
93 'expx901',
94 'expx902',
95 'expx903',
96 'expx905',
97 'lnx901',
98 'lnx902',
99 'lnx903',
100 'lnx905',
101 'logx901',
102 'logx902',
103 'logx903',
104 'logx905',
105 'powx1183',
106 'powx1184',
107 'powx4001',
108 'powx4002',
109 'powx4003',
110 'powx4005',
111 'powx4008',
112 'powx4010',
113 'powx4012',
114 'powx4014',
115 ])
Mark Dickinson8a546532009-10-08 16:30:38 +0000116
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000117# Make sure it actually raises errors when not expected and caught in flags
118# Slower, since it runs some things several times.
119EXTENDEDERRORTEST = False
120
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000121#Map the test cases' error names to the actual errors
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000122ErrorNames = {'clamped' : Clamped,
Raymond Hettinger5aa478b2004-07-09 10:02:53 +0000123 'conversion_syntax' : InvalidOperation,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000124 'division_by_zero' : DivisionByZero,
Raymond Hettinger5aa478b2004-07-09 10:02:53 +0000125 'division_impossible' : InvalidOperation,
126 'division_undefined' : InvalidOperation,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000127 'inexact' : Inexact,
Raymond Hettinger5aa478b2004-07-09 10:02:53 +0000128 'invalid_context' : InvalidOperation,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000129 'invalid_operation' : InvalidOperation,
130 'overflow' : Overflow,
131 'rounded' : Rounded,
132 'subnormal' : Subnormal,
133 'underflow' : Underflow}
134
135
136def Nonfunction(*args):
137 """Doesn't do anything."""
138 return None
139
140RoundingDict = {'ceiling' : ROUND_CEILING, #Maps test-case names to roundings.
141 'down' : ROUND_DOWN,
142 'floor' : ROUND_FLOOR,
143 'half_down' : ROUND_HALF_DOWN,
144 'half_even' : ROUND_HALF_EVEN,
145 'half_up' : ROUND_HALF_UP,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000146 'up' : ROUND_UP,
147 '05up' : ROUND_05UP}
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000148
149# Name adapter to be able to change the Decimal and Context
150# interface without changing the test files from Cowlishaw
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000151nameAdapter = {'and':'logical_and',
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000152 'apply':'_apply',
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000153 'class':'number_class',
154 'comparesig':'compare_signal',
155 'comparetotal':'compare_total',
156 'comparetotmag':'compare_total_mag',
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000157 'copy':'copy_decimal',
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000158 'copyabs':'copy_abs',
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000159 'copynegate':'copy_negate',
160 'copysign':'copy_sign',
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000161 'divideint':'divide_int',
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000162 'invert':'logical_invert',
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000163 'iscanonical':'is_canonical',
164 'isfinite':'is_finite',
165 'isinfinite':'is_infinite',
166 'isnan':'is_nan',
167 'isnormal':'is_normal',
168 'isqnan':'is_qnan',
169 'issigned':'is_signed',
170 'issnan':'is_snan',
171 'issubnormal':'is_subnormal',
172 'iszero':'is_zero',
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000173 'maxmag':'max_mag',
174 'minmag':'min_mag',
175 'nextminus':'next_minus',
176 'nextplus':'next_plus',
177 'nexttoward':'next_toward',
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000178 'or':'logical_or',
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000179 'reduce':'normalize',
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000180 'remaindernear':'remainder_near',
181 'samequantum':'same_quantum',
182 'squareroot':'sqrt',
183 'toeng':'to_eng_string',
184 'tointegral':'to_integral_value',
185 'tointegralx':'to_integral_exact',
186 'tosci':'to_sci_string',
187 'xor':'logical_xor',
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000188 }
189
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000190# The following functions return True/False rather than a Decimal instance
191
192LOGICAL_FUNCTIONS = (
193 'is_canonical',
194 'is_finite',
195 'is_infinite',
196 'is_nan',
197 'is_normal',
198 'is_qnan',
199 'is_signed',
200 'is_snan',
201 'is_subnormal',
202 'is_zero',
203 'same_quantum',
204 )
205
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000206class DecimalTest(unittest.TestCase):
207 """Class which tests the Decimal class against the test cases.
208
209 Changed for unittest.
210 """
211 def setUp(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000212 self.context = Context()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000213 self.ignore_list = ['#']
214 # Basically, a # means return NaN InvalidOperation.
215 # Different from a sNaN in trim
216
217 self.ChangeDict = {'precision' : self.change_precision,
218 'rounding' : self.change_rounding_method,
219 'maxexponent' : self.change_max_exponent,
220 'minexponent' : self.change_min_exponent,
221 'clamp' : self.change_clamp}
222
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000223 def eval_file(self, file):
224 global skip_expected
225 if skip_expected:
Benjamin Petersone549ead2009-03-28 21:42:05 +0000226 raise unittest.SkipTest
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000227 return
Antoine Pitrou92f60ed2010-10-14 22:11:44 +0000228 with open(file) as f:
229 for line in f:
230 line = line.replace('\r\n', '').replace('\n', '')
231 #print line
232 try:
233 t = self.eval_line(line)
234 except DecimalException as exception:
235 #Exception raised where there shoudn't have been one.
236 self.fail('Exception "'+exception.__class__.__name__ + '" raised on line '+line)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000237
238 return
239
240 def eval_line(self, s):
241 if s.find(' -> ') >= 0 and s[:2] != '--' and not s.startswith(' --'):
242 s = (s.split('->')[0] + '->' +
243 s.split('->')[1].split('--')[0]).strip()
244 else:
245 s = s.split('--')[0].strip()
246
247 for ignore in self.ignore_list:
248 if s.find(ignore) >= 0:
249 #print s.split()[0], 'NotImplemented--', ignore
250 return
251 if not s:
252 return
253 elif ':' in s:
254 return self.eval_directive(s)
255 else:
256 return self.eval_equation(s)
257
258 def eval_directive(self, s):
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000259 funct, value = (x.strip().lower() for x in s.split(':'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000260 if funct == 'rounding':
261 value = RoundingDict[value]
262 else:
263 try:
264 value = int(value)
265 except ValueError:
266 pass
267
268 funct = self.ChangeDict.get(funct, Nonfunction)
269 funct(value)
270
271 def eval_equation(self, s):
272 #global DEFAULT_PRECISION
273 #print DEFAULT_PRECISION
Raymond Hettingered20ad82004-09-04 20:09:13 +0000274
275 if not TEST_ALL and random.random() < 0.90:
276 return
277
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000278 try:
279 Sides = s.split('->')
280 L = Sides[0].strip().split()
281 id = L[0]
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000282 if DEBUG:
283 print("Test ", id, end=" ")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000284 funct = L[1].lower()
285 valstemp = L[2:]
286 L = Sides[1].strip().split()
287 ans = L[0]
288 exceptions = L[1:]
289 except (TypeError, AttributeError, IndexError):
Raymond Hettingerd87ac8f2004-07-09 10:52:54 +0000290 raise InvalidOperation
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000291 def FixQuotes(val):
292 val = val.replace("''", 'SingleQuote').replace('""', 'DoubleQuote')
293 val = val.replace("'", '').replace('"', '')
294 val = val.replace('SingleQuote', "'").replace('DoubleQuote', '"')
295 return val
Mark Dickinson8a546532009-10-08 16:30:38 +0000296
297 if id in skipped_test_ids:
298 return
299
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000300 fname = nameAdapter.get(funct, funct)
301 if fname == 'rescale':
302 return
303 funct = getattr(self.context, fname)
304 vals = []
305 conglomerate = ''
306 quote = 0
307 theirexceptions = [ErrorNames[x.lower()] for x in exceptions]
308
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000309 for exception in Signals:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000310 self.context.traps[exception] = 1 #Catch these bugs...
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000311 for exception in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000312 self.context.traps[exception] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000313 for i, val in enumerate(valstemp):
314 if val.count("'") % 2 == 1:
315 quote = 1 - quote
316 if quote:
317 conglomerate = conglomerate + ' ' + val
318 continue
319 else:
320 val = conglomerate + val
321 conglomerate = ''
322 v = FixQuotes(val)
323 if fname in ('to_sci_string', 'to_eng_string'):
324 if EXTENDEDERRORTEST:
325 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000326 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000327 try:
328 funct(self.context.create_decimal(v))
329 except error:
330 pass
Guido van Rossumb940e112007-01-10 16:19:56 +0000331 except Signals as e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000332 self.fail("Raised %s in %s when %s disabled" % \
333 (e, s, error))
334 else:
335 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000336 self.context.traps[error] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000337 v = self.context.create_decimal(v)
338 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000339 v = Decimal(v, self.context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000340 vals.append(v)
341
342 ans = FixQuotes(ans)
343
344 if EXTENDEDERRORTEST and fname not in ('to_sci_string', 'to_eng_string'):
345 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000346 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000347 try:
348 funct(*vals)
349 except error:
350 pass
Guido van Rossumb940e112007-01-10 16:19:56 +0000351 except Signals as e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000352 self.fail("Raised %s in %s when %s disabled" % \
353 (e, s, error))
354 else:
355 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000356 self.context.traps[error] = 0
Mark Dickinsonc69160e2010-05-04 14:35:33 +0000357
358 # as above, but add traps cumulatively, to check precedence
359 ordered_errors = [e for e in OrderedSignals if e in theirexceptions]
360 for error in ordered_errors:
361 self.context.traps[error] = 1
362 try:
363 funct(*vals)
364 except error:
365 pass
366 except Signals as e:
367 self.fail("Raised %s in %s; expected %s" %
368 (type(e), s, error))
369 else:
370 self.fail("Did not raise %s in %s" % (error, s))
371 # reset traps
372 for error in ordered_errors:
373 self.context.traps[error] = 0
374
375
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000376 if DEBUG:
377 print("--", self.context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000378 try:
379 result = str(funct(*vals))
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000380 if fname in LOGICAL_FUNCTIONS:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000381 result = str(int(eval(result))) # 'True', 'False' -> '1', '0'
Guido van Rossumb940e112007-01-10 16:19:56 +0000382 except Signals as error:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000383 self.fail("Raised %s in %s" % (error, s))
384 except: #Catch any error long enough to state the test case.
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000385 print("ERROR:", s)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000386 raise
387
388 myexceptions = self.getexceptions()
Raymond Hettingerbf440692004-07-10 14:14:37 +0000389 self.context.clear_flags()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000390
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000391 myexceptions.sort(key=repr)
392 theirexceptions.sort(key=repr)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000393
394 self.assertEqual(result, ans,
395 'Incorrect answer for ' + s + ' -- got ' + result)
396 self.assertEqual(myexceptions, theirexceptions,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000397 'Incorrect flags set in ' + s + ' -- got ' + str(myexceptions))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000398 return
399
400 def getexceptions(self):
Raymond Hettingerf63ba432004-08-17 05:42:09 +0000401 return [e for e in Signals if self.context.flags[e]]
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000402
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000403 def change_precision(self, prec):
404 self.context.prec = prec
405 def change_rounding_method(self, rounding):
406 self.context.rounding = rounding
407 def change_min_exponent(self, exp):
408 self.context.Emin = exp
409 def change_max_exponent(self, exp):
410 self.context.Emax = exp
411 def change_clamp(self, clamp):
Mark Dickinsonb1d8e322010-05-22 18:35:36 +0000412 self.context.clamp = clamp
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000413
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000414
415
416# The following classes test the behaviour of Decimal according to PEP 327
417
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000418class DecimalExplicitConstructionTest(unittest.TestCase):
419 '''Unit tests for Explicit Construction cases of Decimal.'''
420
421 def test_explicit_empty(self):
422 self.assertEqual(Decimal(), Decimal("0"))
423
424 def test_explicit_from_None(self):
425 self.assertRaises(TypeError, Decimal, None)
426
427 def test_explicit_from_int(self):
428
429 #positive
430 d = Decimal(45)
431 self.assertEqual(str(d), '45')
432
433 #very large positive
434 d = Decimal(500000123)
435 self.assertEqual(str(d), '500000123')
436
437 #negative
438 d = Decimal(-45)
439 self.assertEqual(str(d), '-45')
440
441 #zero
442 d = Decimal(0)
443 self.assertEqual(str(d), '0')
444
445 def test_explicit_from_string(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000446
447 #empty
448 self.assertEqual(str(Decimal('')), 'NaN')
449
450 #int
451 self.assertEqual(str(Decimal('45')), '45')
452
453 #float
454 self.assertEqual(str(Decimal('45.34')), '45.34')
455
456 #engineer notation
457 self.assertEqual(str(Decimal('45e2')), '4.5E+3')
458
459 #just not a number
460 self.assertEqual(str(Decimal('ugly')), 'NaN')
461
Christian Heimesa62da1d2008-01-12 19:39:10 +0000462 #leading and trailing whitespace permitted
463 self.assertEqual(str(Decimal('1.3E4 \n')), '1.3E+4')
464 self.assertEqual(str(Decimal(' -7.89')), '-7.89')
465
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000466 def test_explicit_from_tuples(self):
467
468 #zero
469 d = Decimal( (0, (0,), 0) )
470 self.assertEqual(str(d), '0')
471
472 #int
473 d = Decimal( (1, (4, 5), 0) )
474 self.assertEqual(str(d), '-45')
475
476 #float
477 d = Decimal( (0, (4, 5, 3, 4), -2) )
478 self.assertEqual(str(d), '45.34')
479
480 #weird
481 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
482 self.assertEqual(str(d), '-4.34913534E-17')
483
484 #wrong number of items
485 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1)) )
486
487 #bad sign
488 self.assertRaises(ValueError, Decimal, (8, (4, 3, 4, 9, 1), 2) )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000489 self.assertRaises(ValueError, Decimal, (0., (4, 3, 4, 9, 1), 2) )
490 self.assertRaises(ValueError, Decimal, (Decimal(1), (4, 3, 4, 9, 1), 2))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000491
492 #bad exp
493 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 'wrong!') )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000494 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 0.) )
495 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), '1') )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000496
497 #bad coefficients
498 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, None, 1), 2) )
499 self.assertRaises(ValueError, Decimal, (1, (4, -3, 4, 9, 1), 2) )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000500 self.assertRaises(ValueError, Decimal, (1, (4, 10, 4, 9, 1), 2) )
Guido van Rossum0d3fb8a2007-11-26 23:23:18 +0000501 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 'a', 1), 2) )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000502
Antoine Pitrou503ab332010-03-30 18:56:19 +0000503 def test_explicit_from_bool(self):
504 self.assertIs(bool(Decimal(0)), False)
505 self.assertIs(bool(Decimal(1)), True)
506 self.assertEqual(Decimal(False), Decimal(0))
507 self.assertEqual(Decimal(True), Decimal(1))
508
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000509 def test_explicit_from_Decimal(self):
510
511 #positive
512 d = Decimal(45)
513 e = Decimal(d)
514 self.assertEqual(str(e), '45')
515 self.assertNotEqual(id(d), id(e))
516
517 #very large positive
518 d = Decimal(500000123)
519 e = Decimal(d)
520 self.assertEqual(str(e), '500000123')
521 self.assertNotEqual(id(d), id(e))
522
523 #negative
524 d = Decimal(-45)
525 e = Decimal(d)
526 self.assertEqual(str(e), '-45')
527 self.assertNotEqual(id(d), id(e))
528
529 #zero
530 d = Decimal(0)
531 e = Decimal(d)
532 self.assertEqual(str(e), '0')
533 self.assertNotEqual(id(d), id(e))
534
Raymond Hettinger96798592010-04-02 16:58:27 +0000535 @requires_IEEE_754
536 def test_explicit_from_float(self):
537 r = Decimal(0.1)
538 self.assertEqual(type(r), Decimal)
539 self.assertEqual(str(r),
540 '0.1000000000000000055511151231257827021181583404541015625')
541 self.assertTrue(Decimal(float('nan')).is_qnan())
542 self.assertTrue(Decimal(float('inf')).is_infinite())
543 self.assertTrue(Decimal(float('-inf')).is_infinite())
544 self.assertEqual(str(Decimal(float('nan'))),
545 str(Decimal('NaN')))
546 self.assertEqual(str(Decimal(float('inf'))),
547 str(Decimal('Infinity')))
548 self.assertEqual(str(Decimal(float('-inf'))),
549 str(Decimal('-Infinity')))
550 self.assertEqual(str(Decimal(float('-0.0'))),
551 str(Decimal('-0')))
552 for i in range(200):
553 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
554 self.assertEqual(x, float(Decimal(x))) # roundtrip
555
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000556 def test_explicit_context_create_decimal(self):
557
558 nc = copy.copy(getcontext())
559 nc.prec = 3
560
561 # empty
Raymond Hettingerfed52962004-07-14 15:41:57 +0000562 d = Decimal()
563 self.assertEqual(str(d), '0')
564 d = nc.create_decimal()
565 self.assertEqual(str(d), '0')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000566
567 # from None
568 self.assertRaises(TypeError, nc.create_decimal, None)
569
570 # from int
571 d = nc.create_decimal(456)
Ezio Melottie9615932010-01-24 19:26:24 +0000572 self.assertIsInstance(d, Decimal)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000573 self.assertEqual(nc.create_decimal(45678),
574 nc.create_decimal('457E+2'))
575
576 # from string
577 d = Decimal('456789')
578 self.assertEqual(str(d), '456789')
579 d = nc.create_decimal('456789')
580 self.assertEqual(str(d), '4.57E+5')
Christian Heimesa62da1d2008-01-12 19:39:10 +0000581 # leading and trailing whitespace should result in a NaN;
582 # spaces are already checked in Cowlishaw's test-suite, so
583 # here we just check that a trailing newline results in a NaN
584 self.assertEqual(str(nc.create_decimal('3.14\n')), 'NaN')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000585
586 # from tuples
587 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
588 self.assertEqual(str(d), '-4.34913534E-17')
589 d = nc.create_decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
590 self.assertEqual(str(d), '-4.35E-17')
591
592 # from Decimal
593 prevdec = Decimal(500000123)
594 d = Decimal(prevdec)
595 self.assertEqual(str(d), '500000123')
596 d = nc.create_decimal(prevdec)
597 self.assertEqual(str(d), '5.00E+8')
598
Mark Dickinson345adc42009-08-02 10:14:23 +0000599 def test_unicode_digits(self):
600 test_values = {
601 '\uff11': '1',
602 '\u0660.\u0660\u0663\u0667\u0662e-\u0663' : '0.0000372',
603 '-nan\u0c68\u0c6a\u0c66\u0c66' : '-NaN2400',
604 }
605 for input, expected in test_values.items():
606 self.assertEqual(str(Decimal(input)), expected)
607
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000608
609class DecimalImplicitConstructionTest(unittest.TestCase):
610 '''Unit tests for Implicit Construction cases of Decimal.'''
611
612 def test_implicit_from_None(self):
613 self.assertRaises(TypeError, eval, 'Decimal(5) + None', globals())
614
615 def test_implicit_from_int(self):
616 #normal
617 self.assertEqual(str(Decimal(5) + 45), '50')
618 #exceeding precision
619 self.assertEqual(Decimal(5) + 123456789000, Decimal(123456789000))
620
621 def test_implicit_from_string(self):
622 self.assertRaises(TypeError, eval, 'Decimal(5) + "3"', globals())
623
624 def test_implicit_from_float(self):
625 self.assertRaises(TypeError, eval, 'Decimal(5) + 2.2', globals())
626
627 def test_implicit_from_Decimal(self):
628 self.assertEqual(Decimal(5) + Decimal(45), Decimal(50))
629
Raymond Hettinger267b8682005-03-27 10:47:39 +0000630 def test_rop(self):
631 # Allow other classes to be trained to interact with Decimals
632 class E:
633 def __divmod__(self, other):
634 return 'divmod ' + str(other)
635 def __rdivmod__(self, other):
636 return str(other) + ' rdivmod'
637 def __lt__(self, other):
638 return 'lt ' + str(other)
639 def __gt__(self, other):
640 return 'gt ' + str(other)
641 def __le__(self, other):
642 return 'le ' + str(other)
643 def __ge__(self, other):
644 return 'ge ' + str(other)
645 def __eq__(self, other):
646 return 'eq ' + str(other)
647 def __ne__(self, other):
648 return 'ne ' + str(other)
649
650 self.assertEqual(divmod(E(), Decimal(10)), 'divmod 10')
651 self.assertEqual(divmod(Decimal(10), E()), '10 rdivmod')
652 self.assertEqual(eval('Decimal(10) < E()'), 'gt 10')
653 self.assertEqual(eval('Decimal(10) > E()'), 'lt 10')
654 self.assertEqual(eval('Decimal(10) <= E()'), 'ge 10')
655 self.assertEqual(eval('Decimal(10) >= E()'), 'le 10')
656 self.assertEqual(eval('Decimal(10) == E()'), 'eq 10')
657 self.assertEqual(eval('Decimal(10) != E()'), 'ne 10')
658
659 # insert operator methods and then exercise them
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000660 oplist = [
661 ('+', '__add__', '__radd__'),
662 ('-', '__sub__', '__rsub__'),
663 ('*', '__mul__', '__rmul__'),
Thomas Woutersdcc6d322006-04-21 11:30:52 +0000664 ('/', '__truediv__', '__rtruediv__'),
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000665 ('%', '__mod__', '__rmod__'),
666 ('//', '__floordiv__', '__rfloordiv__'),
667 ('**', '__pow__', '__rpow__')
668 ]
Raymond Hettinger267b8682005-03-27 10:47:39 +0000669
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000670 for sym, lop, rop in oplist:
Raymond Hettinger267b8682005-03-27 10:47:39 +0000671 setattr(E, lop, lambda self, other: 'str' + lop + str(other))
672 setattr(E, rop, lambda self, other: str(other) + rop + 'str')
673 self.assertEqual(eval('E()' + sym + 'Decimal(10)'),
674 'str' + lop + '10')
675 self.assertEqual(eval('Decimal(10)' + sym + 'E()'),
676 '10' + rop + 'str')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000677
Mark Dickinson79f52032009-03-17 23:12:51 +0000678
Christian Heimesf16baeb2008-02-29 14:57:44 +0000679class DecimalFormatTest(unittest.TestCase):
680 '''Unit tests for the format function.'''
681 def test_formatting(self):
682 # triples giving a format, a Decimal, and the expected result
683 test_values = [
684 ('e', '0E-15', '0e-15'),
685 ('e', '2.3E-15', '2.3e-15'),
686 ('e', '2.30E+2', '2.30e+2'), # preserve significant zeros
687 ('e', '2.30000E-15', '2.30000e-15'),
688 ('e', '1.23456789123456789e40', '1.23456789123456789e+40'),
689 ('e', '1.5', '1.5e+0'),
690 ('e', '0.15', '1.5e-1'),
691 ('e', '0.015', '1.5e-2'),
692 ('e', '0.0000000000015', '1.5e-12'),
693 ('e', '15.0', '1.50e+1'),
694 ('e', '-15', '-1.5e+1'),
695 ('e', '0', '0e+0'),
696 ('e', '0E1', '0e+1'),
697 ('e', '0.0', '0e-1'),
698 ('e', '0.00', '0e-2'),
699 ('.6e', '0E-15', '0.000000e-9'),
700 ('.6e', '0', '0.000000e+6'),
701 ('.6e', '9.999999', '9.999999e+0'),
702 ('.6e', '9.9999999', '1.000000e+1'),
703 ('.6e', '-1.23e5', '-1.230000e+5'),
704 ('.6e', '1.23456789e-3', '1.234568e-3'),
705 ('f', '0', '0'),
706 ('f', '0.0', '0.0'),
707 ('f', '0E-2', '0.00'),
708 ('f', '0.00E-8', '0.0000000000'),
709 ('f', '0E1', '0'), # loses exponent information
710 ('f', '3.2E1', '32'),
711 ('f', '3.2E2', '320'),
712 ('f', '3.20E2', '320'),
713 ('f', '3.200E2', '320.0'),
714 ('f', '3.2E-6', '0.0000032'),
715 ('.6f', '0E-15', '0.000000'), # all zeros treated equally
716 ('.6f', '0E1', '0.000000'),
717 ('.6f', '0', '0.000000'),
718 ('.0f', '0', '0'), # no decimal point
719 ('.0f', '0e-2', '0'),
720 ('.0f', '3.14159265', '3'),
721 ('.1f', '3.14159265', '3.1'),
722 ('.4f', '3.14159265', '3.1416'),
723 ('.6f', '3.14159265', '3.141593'),
724 ('.7f', '3.14159265', '3.1415926'), # round-half-even!
725 ('.8f', '3.14159265', '3.14159265'),
726 ('.9f', '3.14159265', '3.141592650'),
727
728 ('g', '0', '0'),
729 ('g', '0.0', '0.0'),
730 ('g', '0E1', '0e+1'),
731 ('G', '0E1', '0E+1'),
732 ('g', '0E-5', '0.00000'),
733 ('g', '0E-6', '0.000000'),
734 ('g', '0E-7', '0e-7'),
735 ('g', '-0E2', '-0e+2'),
736 ('.0g', '3.14159265', '3'), # 0 sig fig -> 1 sig fig
737 ('.1g', '3.14159265', '3'),
738 ('.2g', '3.14159265', '3.1'),
739 ('.5g', '3.14159265', '3.1416'),
740 ('.7g', '3.14159265', '3.141593'),
741 ('.8g', '3.14159265', '3.1415926'), # round-half-even!
742 ('.9g', '3.14159265', '3.14159265'),
743 ('.10g', '3.14159265', '3.14159265'), # don't pad
744
745 ('%', '0E1', '0%'),
746 ('%', '0E0', '0%'),
747 ('%', '0E-1', '0%'),
748 ('%', '0E-2', '0%'),
749 ('%', '0E-3', '0.0%'),
750 ('%', '0E-4', '0.00%'),
751
752 ('.3%', '0', '0.000%'), # all zeros treated equally
753 ('.3%', '0E10', '0.000%'),
754 ('.3%', '0E-10', '0.000%'),
755 ('.3%', '2.34', '234.000%'),
756 ('.3%', '1.234567', '123.457%'),
757 ('.0%', '1.23', '123%'),
758
759 ('e', 'NaN', 'NaN'),
760 ('f', '-NaN123', '-NaN123'),
761 ('+g', 'NaN456', '+NaN456'),
762 ('.3e', 'Inf', 'Infinity'),
763 ('.16f', '-Inf', '-Infinity'),
764 ('.0g', '-sNaN', '-sNaN'),
765
766 ('', '1.00', '1.00'),
Mark Dickinsonad416342009-03-17 18:10:15 +0000767
Mark Dickinson79f52032009-03-17 23:12:51 +0000768 # test alignment and padding
Mark Dickinson46ab5d02009-09-08 20:22:46 +0000769 ('6', '123', ' 123'),
Mark Dickinsonad416342009-03-17 18:10:15 +0000770 ('<6', '123', '123 '),
771 ('>6', '123', ' 123'),
772 ('^6', '123', ' 123 '),
773 ('=+6', '123', '+ 123'),
Mark Dickinson79f52032009-03-17 23:12:51 +0000774 ('#<10', 'NaN', 'NaN#######'),
775 ('#<10', '-4.3', '-4.3######'),
776 ('#<+10', '0.0130', '+0.0130###'),
777 ('#< 10', '0.0130', ' 0.0130###'),
778 ('@>10', '-Inf', '@-Infinity'),
779 ('#>5', '-Inf', '-Infinity'),
780 ('?^5', '123', '?123?'),
781 ('%^6', '123', '%123%%'),
782 (' ^6', '-45.6', '-45.6 '),
783 ('/=10', '-45.6', '-/////45.6'),
784 ('/=+10', '45.6', '+/////45.6'),
785 ('/= 10', '45.6', ' /////45.6'),
786
787 # thousands separator
788 (',', '1234567', '1,234,567'),
789 (',', '123456', '123,456'),
790 (',', '12345', '12,345'),
791 (',', '1234', '1,234'),
792 (',', '123', '123'),
793 (',', '12', '12'),
794 (',', '1', '1'),
795 (',', '0', '0'),
796 (',', '-1234567', '-1,234,567'),
797 (',', '-123456', '-123,456'),
798 ('7,', '123456', '123,456'),
Mark Dickinson46ab5d02009-09-08 20:22:46 +0000799 ('8,', '123456', ' 123,456'),
Mark Dickinson79f52032009-03-17 23:12:51 +0000800 ('08,', '123456', '0,123,456'), # special case: extra 0 needed
801 ('+08,', '123456', '+123,456'), # but not if there's a sign
802 (' 08,', '123456', ' 123,456'),
803 ('08,', '-123456', '-123,456'),
804 ('+09,', '123456', '+0,123,456'),
805 # ... with fractional part...
806 ('07,', '1234.56', '1,234.56'),
807 ('08,', '1234.56', '1,234.56'),
808 ('09,', '1234.56', '01,234.56'),
809 ('010,', '1234.56', '001,234.56'),
810 ('011,', '1234.56', '0,001,234.56'),
811 ('012,', '1234.56', '0,001,234.56'),
812 ('08,.1f', '1234.5', '01,234.5'),
813 # no thousands separators in fraction part
814 (',', '1.23456789', '1.23456789'),
815 (',%', '123.456789', '12,345.6789%'),
816 (',e', '123456', '1.23456e+5'),
817 (',E', '123456', '1.23456E+5'),
Mark Dickinson7718d2b2009-09-07 16:21:56 +0000818
819 # issue 6850
820 ('a=-7.0', '0.12345', 'aaaa0.1'),
Eric Smith984bb582010-11-25 16:08:06 +0000821
822 # Issue 7094: Alternate formatting (specified by #)
823 ('.0e', '1.0', '1e+0'),
824 ('#.0e', '1.0', '1.e+0'),
825 ('.0f', '1.0', '1'),
826 ('#.0f', '1.0', '1.'),
827 ('g', '1.1', '1.1'),
828 ('#g', '1.1', '1.1'),
829 ('.0g', '1', '1'),
830 ('#.0g', '1', '1.'),
831 ('.0%', '1.0', '100%'),
832 ('#.0%', '1.0', '100.%'),
Christian Heimesf16baeb2008-02-29 14:57:44 +0000833 ]
834 for fmt, d, result in test_values:
835 self.assertEqual(format(Decimal(d), fmt), result)
836
Mark Dickinson79f52032009-03-17 23:12:51 +0000837 def test_n_format(self):
838 try:
839 from locale import CHAR_MAX
840 except ImportError:
841 return
842
843 # Set up some localeconv-like dictionaries
844 en_US = {
845 'decimal_point' : '.',
846 'grouping' : [3, 3, 0],
847 'thousands_sep': ','
848 }
849
850 fr_FR = {
851 'decimal_point' : ',',
852 'grouping' : [CHAR_MAX],
853 'thousands_sep' : ''
854 }
855
856 ru_RU = {
857 'decimal_point' : ',',
858 'grouping' : [3, 3, 0],
859 'thousands_sep' : ' '
860 }
861
862 crazy = {
863 'decimal_point' : '&',
864 'grouping' : [1, 4, 2, CHAR_MAX],
865 'thousands_sep' : '-'
866 }
867
868
869 def get_fmt(x, locale, fmt='n'):
870 return Decimal.__format__(Decimal(x), fmt, _localeconv=locale)
871
872 self.assertEqual(get_fmt(Decimal('12.7'), en_US), '12.7')
873 self.assertEqual(get_fmt(Decimal('12.7'), fr_FR), '12,7')
874 self.assertEqual(get_fmt(Decimal('12.7'), ru_RU), '12,7')
875 self.assertEqual(get_fmt(Decimal('12.7'), crazy), '1-2&7')
876
877 self.assertEqual(get_fmt(123456789, en_US), '123,456,789')
878 self.assertEqual(get_fmt(123456789, fr_FR), '123456789')
879 self.assertEqual(get_fmt(123456789, ru_RU), '123 456 789')
880 self.assertEqual(get_fmt(1234567890123, crazy), '123456-78-9012-3')
881
882 self.assertEqual(get_fmt(123456789, en_US, '.6n'), '1.23457e+8')
883 self.assertEqual(get_fmt(123456789, fr_FR, '.6n'), '1,23457e+8')
884 self.assertEqual(get_fmt(123456789, ru_RU, '.6n'), '1,23457e+8')
885 self.assertEqual(get_fmt(123456789, crazy, '.6n'), '1&23457e+8')
886
Mark Dickinson7303b592009-03-18 08:25:36 +0000887 # zero padding
888 self.assertEqual(get_fmt(1234, fr_FR, '03n'), '1234')
889 self.assertEqual(get_fmt(1234, fr_FR, '04n'), '1234')
890 self.assertEqual(get_fmt(1234, fr_FR, '05n'), '01234')
891 self.assertEqual(get_fmt(1234, fr_FR, '06n'), '001234')
892
893 self.assertEqual(get_fmt(12345, en_US, '05n'), '12,345')
894 self.assertEqual(get_fmt(12345, en_US, '06n'), '12,345')
895 self.assertEqual(get_fmt(12345, en_US, '07n'), '012,345')
896 self.assertEqual(get_fmt(12345, en_US, '08n'), '0,012,345')
897 self.assertEqual(get_fmt(12345, en_US, '09n'), '0,012,345')
898 self.assertEqual(get_fmt(12345, en_US, '010n'), '00,012,345')
899
900 self.assertEqual(get_fmt(123456, crazy, '06n'), '1-2345-6')
901 self.assertEqual(get_fmt(123456, crazy, '07n'), '1-2345-6')
902 self.assertEqual(get_fmt(123456, crazy, '08n'), '1-2345-6')
903 self.assertEqual(get_fmt(123456, crazy, '09n'), '01-2345-6')
904 self.assertEqual(get_fmt(123456, crazy, '010n'), '0-01-2345-6')
905 self.assertEqual(get_fmt(123456, crazy, '011n'), '0-01-2345-6')
906 self.assertEqual(get_fmt(123456, crazy, '012n'), '00-01-2345-6')
907 self.assertEqual(get_fmt(123456, crazy, '013n'), '000-01-2345-6')
908
Mark Dickinson79f52032009-03-17 23:12:51 +0000909
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000910class DecimalArithmeticOperatorsTest(unittest.TestCase):
911 '''Unit tests for all arithmetic operators, binary and unary.'''
912
913 def test_addition(self):
914
915 d1 = Decimal('-11.1')
916 d2 = Decimal('22.2')
917
918 #two Decimals
919 self.assertEqual(d1+d2, Decimal('11.1'))
920 self.assertEqual(d2+d1, Decimal('11.1'))
921
922 #with other type, left
923 c = d1 + 5
924 self.assertEqual(c, Decimal('-6.1'))
925 self.assertEqual(type(c), type(d1))
926
927 #with other type, right
928 c = 5 + d1
929 self.assertEqual(c, Decimal('-6.1'))
930 self.assertEqual(type(c), type(d1))
931
932 #inline with decimal
933 d1 += d2
934 self.assertEqual(d1, Decimal('11.1'))
935
936 #inline with other type
937 d1 += 5
938 self.assertEqual(d1, Decimal('16.1'))
939
940 def test_subtraction(self):
941
942 d1 = Decimal('-11.1')
943 d2 = Decimal('22.2')
944
945 #two Decimals
946 self.assertEqual(d1-d2, Decimal('-33.3'))
947 self.assertEqual(d2-d1, Decimal('33.3'))
948
949 #with other type, left
950 c = d1 - 5
951 self.assertEqual(c, Decimal('-16.1'))
952 self.assertEqual(type(c), type(d1))
953
954 #with other type, right
955 c = 5 - d1
956 self.assertEqual(c, Decimal('16.1'))
957 self.assertEqual(type(c), type(d1))
958
959 #inline with decimal
960 d1 -= d2
961 self.assertEqual(d1, Decimal('-33.3'))
962
963 #inline with other type
964 d1 -= 5
965 self.assertEqual(d1, Decimal('-38.3'))
966
967 def test_multiplication(self):
968
969 d1 = Decimal('-5')
970 d2 = Decimal('3')
971
972 #two Decimals
973 self.assertEqual(d1*d2, Decimal('-15'))
974 self.assertEqual(d2*d1, Decimal('-15'))
975
976 #with other type, left
977 c = d1 * 5
978 self.assertEqual(c, Decimal('-25'))
979 self.assertEqual(type(c), type(d1))
980
981 #with other type, right
982 c = 5 * d1
983 self.assertEqual(c, Decimal('-25'))
984 self.assertEqual(type(c), type(d1))
985
986 #inline with decimal
987 d1 *= d2
988 self.assertEqual(d1, Decimal('-15'))
989
990 #inline with other type
991 d1 *= 5
992 self.assertEqual(d1, Decimal('-75'))
993
994 def test_division(self):
995
996 d1 = Decimal('-5')
997 d2 = Decimal('2')
998
999 #two Decimals
1000 self.assertEqual(d1/d2, Decimal('-2.5'))
1001 self.assertEqual(d2/d1, Decimal('-0.4'))
1002
1003 #with other type, left
1004 c = d1 / 4
1005 self.assertEqual(c, Decimal('-1.25'))
1006 self.assertEqual(type(c), type(d1))
1007
1008 #with other type, right
1009 c = 4 / d1
1010 self.assertEqual(c, Decimal('-0.8'))
1011 self.assertEqual(type(c), type(d1))
1012
1013 #inline with decimal
1014 d1 /= d2
1015 self.assertEqual(d1, Decimal('-2.5'))
1016
1017 #inline with other type
1018 d1 /= 4
1019 self.assertEqual(d1, Decimal('-0.625'))
1020
1021 def test_floor_division(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001022
1023 d1 = Decimal('5')
1024 d2 = Decimal('2')
1025
1026 #two Decimals
1027 self.assertEqual(d1//d2, Decimal('2'))
1028 self.assertEqual(d2//d1, Decimal('0'))
1029
1030 #with other type, left
1031 c = d1 // 4
1032 self.assertEqual(c, Decimal('1'))
1033 self.assertEqual(type(c), type(d1))
1034
1035 #with other type, right
1036 c = 7 // d1
1037 self.assertEqual(c, Decimal('1'))
1038 self.assertEqual(type(c), type(d1))
1039
1040 #inline with decimal
1041 d1 //= d2
1042 self.assertEqual(d1, Decimal('2'))
1043
1044 #inline with other type
1045 d1 //= 2
1046 self.assertEqual(d1, Decimal('1'))
1047
1048 def test_powering(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001049
1050 d1 = Decimal('5')
1051 d2 = Decimal('2')
1052
1053 #two Decimals
1054 self.assertEqual(d1**d2, Decimal('25'))
1055 self.assertEqual(d2**d1, Decimal('32'))
1056
1057 #with other type, left
1058 c = d1 ** 4
1059 self.assertEqual(c, Decimal('625'))
1060 self.assertEqual(type(c), type(d1))
1061
1062 #with other type, right
1063 c = 7 ** d1
1064 self.assertEqual(c, Decimal('16807'))
1065 self.assertEqual(type(c), type(d1))
1066
1067 #inline with decimal
1068 d1 **= d2
1069 self.assertEqual(d1, Decimal('25'))
1070
1071 #inline with other type
1072 d1 **= 4
1073 self.assertEqual(d1, Decimal('390625'))
1074
1075 def test_module(self):
1076
1077 d1 = Decimal('5')
1078 d2 = Decimal('2')
1079
1080 #two Decimals
1081 self.assertEqual(d1%d2, Decimal('1'))
1082 self.assertEqual(d2%d1, Decimal('2'))
1083
1084 #with other type, left
1085 c = d1 % 4
1086 self.assertEqual(c, Decimal('1'))
1087 self.assertEqual(type(c), type(d1))
1088
1089 #with other type, right
1090 c = 7 % d1
1091 self.assertEqual(c, Decimal('2'))
1092 self.assertEqual(type(c), type(d1))
1093
1094 #inline with decimal
1095 d1 %= d2
1096 self.assertEqual(d1, Decimal('1'))
1097
1098 #inline with other type
1099 d1 %= 4
1100 self.assertEqual(d1, Decimal('1'))
1101
1102 def test_floor_div_module(self):
1103
1104 d1 = Decimal('5')
1105 d2 = Decimal('2')
1106
1107 #two Decimals
1108 (p, q) = divmod(d1, d2)
1109 self.assertEqual(p, Decimal('2'))
1110 self.assertEqual(q, Decimal('1'))
1111 self.assertEqual(type(p), type(d1))
1112 self.assertEqual(type(q), type(d1))
1113
1114 #with other type, left
1115 (p, q) = divmod(d1, 4)
1116 self.assertEqual(p, Decimal('1'))
1117 self.assertEqual(q, Decimal('1'))
1118 self.assertEqual(type(p), type(d1))
1119 self.assertEqual(type(q), type(d1))
1120
1121 #with other type, right
1122 (p, q) = divmod(7, d1)
1123 self.assertEqual(p, Decimal('1'))
1124 self.assertEqual(q, Decimal('2'))
1125 self.assertEqual(type(p), type(d1))
1126 self.assertEqual(type(q), type(d1))
1127
1128 def test_unary_operators(self):
1129 self.assertEqual(+Decimal(45), Decimal(+45)) # +
1130 self.assertEqual(-Decimal(45), Decimal(-45)) # -
1131 self.assertEqual(abs(Decimal(45)), abs(Decimal(-45))) # abs
1132
Christian Heimes77c02eb2008-02-09 02:18:51 +00001133 def test_nan_comparisons(self):
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001134 # comparisons involving signaling nans signal InvalidOperation
1135
1136 # order comparisons (<, <=, >, >=) involving only quiet nans
1137 # also signal InvalidOperation
1138
1139 # equality comparisons (==, !=) involving only quiet nans
1140 # don't signal, but return False or True respectively.
1141
Christian Heimes77c02eb2008-02-09 02:18:51 +00001142 n = Decimal('NaN')
1143 s = Decimal('sNaN')
1144 i = Decimal('Inf')
1145 f = Decimal('2')
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001146
1147 qnan_pairs = (n, n), (n, i), (i, n), (n, f), (f, n)
1148 snan_pairs = (s, n), (n, s), (s, i), (i, s), (s, f), (f, s), (s, s)
1149 order_ops = operator.lt, operator.le, operator.gt, operator.ge
1150 equality_ops = operator.eq, operator.ne
1151
1152 # results when InvalidOperation is not trapped
1153 for x, y in qnan_pairs + snan_pairs:
1154 for op in order_ops + equality_ops:
1155 got = op(x, y)
1156 expected = True if op is operator.ne else False
1157 self.assertIs(expected, got,
1158 "expected {0!r} for operator.{1}({2!r}, {3!r}); "
1159 "got {4!r}".format(
1160 expected, op.__name__, x, y, got))
1161
1162 # repeat the above, but this time trap the InvalidOperation
1163 with localcontext() as ctx:
1164 ctx.traps[InvalidOperation] = 1
1165
1166 for x, y in qnan_pairs:
1167 for op in equality_ops:
1168 got = op(x, y)
1169 expected = True if op is operator.ne else False
1170 self.assertIs(expected, got,
1171 "expected {0!r} for "
1172 "operator.{1}({2!r}, {3!r}); "
1173 "got {4!r}".format(
1174 expected, op.__name__, x, y, got))
1175
1176 for x, y in snan_pairs:
1177 for op in equality_ops:
1178 self.assertRaises(InvalidOperation, operator.eq, x, y)
1179 self.assertRaises(InvalidOperation, operator.ne, x, y)
1180
1181 for x, y in qnan_pairs + snan_pairs:
1182 for op in order_ops:
1183 self.assertRaises(InvalidOperation, op, x, y)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001184
Mark Dickinson84230a12010-02-18 14:49:50 +00001185 def test_copy_sign(self):
1186 d = Decimal(1).copy_sign(Decimal(-2))
1187
1188 self.assertEqual(Decimal(1).copy_sign(-2), d)
1189 self.assertRaises(TypeError, Decimal(1).copy_sign, '-2')
1190
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001191# The following are two functions used to test threading in the next class
1192
1193def thfunc1(cls):
1194 d1 = Decimal(1)
1195 d3 = Decimal(3)
Christian Heimesfe337bf2008-03-23 21:54:12 +00001196 test1 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001197 cls.synchro.wait()
Christian Heimesfe337bf2008-03-23 21:54:12 +00001198 test2 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001199 cls.finish1.set()
Christian Heimesfe337bf2008-03-23 21:54:12 +00001200
Christian Heimes81ee3ef2008-05-04 22:42:01 +00001201 cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
1202 cls.assertEqual(test2, Decimal('0.3333333333333333333333333333'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001203 return
1204
1205def thfunc2(cls):
1206 d1 = Decimal(1)
1207 d3 = Decimal(3)
Christian Heimesfe337bf2008-03-23 21:54:12 +00001208 test1 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001209 thiscontext = getcontext()
1210 thiscontext.prec = 18
Christian Heimesfe337bf2008-03-23 21:54:12 +00001211 test2 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001212 cls.synchro.set()
1213 cls.finish2.set()
Christian Heimesfe337bf2008-03-23 21:54:12 +00001214
Christian Heimes81ee3ef2008-05-04 22:42:01 +00001215 cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
Christian Heimesfe337bf2008-03-23 21:54:12 +00001216 cls.assertEqual(test2, Decimal('0.333333333333333333'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001217 return
1218
1219
1220class DecimalUseOfContextTest(unittest.TestCase):
1221 '''Unit tests for Use of Context cases in Decimal.'''
1222
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001223 try:
1224 import threading
1225 except ImportError:
1226 threading = None
1227
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001228 # Take care executing this test from IDLE, there's an issue in threading
1229 # that hangs IDLE and I couldn't find it
1230
1231 def test_threading(self):
1232 #Test the "threading isolation" of a Context.
1233
1234 self.synchro = threading.Event()
1235 self.finish1 = threading.Event()
1236 self.finish2 = threading.Event()
1237
1238 th1 = threading.Thread(target=thfunc1, args=(self,))
1239 th2 = threading.Thread(target=thfunc2, args=(self,))
1240
1241 th1.start()
1242 th2.start()
1243
1244 self.finish1.wait()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001245 self.finish2.wait()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001246 return
1247
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001248 if threading is None:
1249 del test_threading
1250
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001251
1252class DecimalUsabilityTest(unittest.TestCase):
1253 '''Unit tests for Usability cases of Decimal.'''
1254
1255 def test_comparison_operators(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001256
1257 da = Decimal('23.42')
1258 db = Decimal('23.42')
1259 dc = Decimal('45')
1260
1261 #two Decimals
Ezio Melotti6607d512010-04-03 14:59:49 +00001262 self.assertGreater(dc, da)
1263 self.assertGreaterEqual(dc, da)
1264 self.assertLess(da, dc)
1265 self.assertLessEqual(da, dc)
Guido van Rossume61fd5b2007-07-11 12:20:59 +00001266 self.assertEqual(da, db)
Ezio Melotti6607d512010-04-03 14:59:49 +00001267 self.assertNotEqual(da, dc)
1268 self.assertLessEqual(da, db)
1269 self.assertGreaterEqual(da, db)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001270
1271 #a Decimal and an int
Ezio Melotti6607d512010-04-03 14:59:49 +00001272 self.assertGreater(dc, 23)
1273 self.assertLess(23, dc)
Guido van Rossume61fd5b2007-07-11 12:20:59 +00001274 self.assertEqual(dc, 45)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001275
1276 #a Decimal and uncomparable
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001277 self.assertNotEqual(da, 'ugly')
1278 self.assertNotEqual(da, 32.7)
1279 self.assertNotEqual(da, object())
1280 self.assertNotEqual(da, object)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001281
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001282 # sortable
Guido van Rossumc1f779c2007-07-03 08:25:58 +00001283 a = list(map(Decimal, range(100)))
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001284 b = a[:]
1285 random.shuffle(a)
1286 a.sort()
1287 self.assertEqual(a, b)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001288
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001289 def test_decimal_float_comparison(self):
1290 da = Decimal('0.25')
1291 db = Decimal('3.0')
Ezio Melotti6607d512010-04-03 14:59:49 +00001292 self.assertLess(da, 3.0)
1293 self.assertLessEqual(da, 3.0)
1294 self.assertGreater(db, 0.25)
1295 self.assertGreaterEqual(db, 0.25)
1296 self.assertNotEqual(da, 1.5)
1297 self.assertEqual(da, 0.25)
1298 self.assertGreater(3.0, da)
1299 self.assertGreaterEqual(3.0, da)
1300 self.assertLess(0.25, db)
1301 self.assertLessEqual(0.25, db)
1302 self.assertNotEqual(0.25, db)
1303 self.assertEqual(3.0, db)
1304 self.assertNotEqual(0.1, Decimal('0.1'))
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001305
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001306 def test_copy_and_deepcopy_methods(self):
1307 d = Decimal('43.24')
1308 c = copy.copy(d)
1309 self.assertEqual(id(c), id(d))
1310 dc = copy.deepcopy(d)
1311 self.assertEqual(id(dc), id(d))
1312
1313 def test_hash_method(self):
Stefan Krahdc817b22010-11-17 11:16:34 +00001314 def hashit(d):
1315 a = hash(d)
1316 b = d.__hash__()
1317 self.assertEqual(a, b)
1318 return a
1319
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001320 #just that it's hashable
Stefan Krahdc817b22010-11-17 11:16:34 +00001321 hashit(Decimal(23))
1322 hashit(Decimal('Infinity'))
1323 hashit(Decimal('-Infinity'))
1324 hashit(Decimal('nan123'))
1325 hashit(Decimal('-NaN'))
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001326
1327 test_values = [Decimal(sign*(2**m + n))
1328 for m in [0, 14, 15, 16, 17, 30, 31,
Stefan Krahdc817b22010-11-17 11:16:34 +00001329 32, 33, 61, 62, 63, 64, 65, 66]
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001330 for n in range(-10, 10)
1331 for sign in [-1, 1]]
1332 test_values.extend([
Stefan Krahdc817b22010-11-17 11:16:34 +00001333 Decimal("-1"), # ==> -2
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001334 Decimal("-0"), # zeros
1335 Decimal("0.00"),
1336 Decimal("-0.000"),
1337 Decimal("0E10"),
1338 Decimal("-0E12"),
1339 Decimal("10.0"), # negative exponent
1340 Decimal("-23.00000"),
1341 Decimal("1230E100"), # positive exponent
1342 Decimal("-4.5678E50"),
1343 # a value for which hash(n) != hash(n % (2**64-1))
1344 # in Python pre-2.6
1345 Decimal(2**64 + 2**32 - 1),
1346 # selection of values which fail with the old (before
1347 # version 2.6) long.__hash__
1348 Decimal("1.634E100"),
1349 Decimal("90.697E100"),
1350 Decimal("188.83E100"),
1351 Decimal("1652.9E100"),
1352 Decimal("56531E100"),
1353 ])
1354
1355 # check that hash(d) == hash(int(d)) for integral values
1356 for value in test_values:
Stefan Krahdc817b22010-11-17 11:16:34 +00001357 self.assertEqual(hashit(value), hashit(int(value)))
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001358
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001359 #the same hash that to an int
Stefan Krahdc817b22010-11-17 11:16:34 +00001360 self.assertEqual(hashit(Decimal(23)), hashit(23))
Raymond Hettingerd325c4b2010-11-21 04:08:28 +00001361 self.assertRaises(TypeError, hash, Decimal('sNaN'))
Stefan Krahdc817b22010-11-17 11:16:34 +00001362 self.assertTrue(hashit(Decimal('Inf')))
1363 self.assertTrue(hashit(Decimal('-Inf')))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001364
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001365 # check that the hashes of a Decimal float match when they
1366 # represent exactly the same values
1367 test_strings = ['inf', '-Inf', '0.0', '-.0e1',
1368 '34.0', '2.5', '112390.625', '-0.515625']
1369 for s in test_strings:
1370 f = float(s)
1371 d = Decimal(s)
Stefan Krahdc817b22010-11-17 11:16:34 +00001372 self.assertEqual(hashit(f), hashit(d))
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001373
Christian Heimes2380ac72008-01-09 00:17:24 +00001374 # check that the value of the hash doesn't depend on the
1375 # current context (issue #1757)
1376 c = getcontext()
1377 old_precision = c.prec
1378 x = Decimal("123456789.1")
1379
1380 c.prec = 6
Stefan Krahdc817b22010-11-17 11:16:34 +00001381 h1 = hashit(x)
Christian Heimes2380ac72008-01-09 00:17:24 +00001382 c.prec = 10
Stefan Krahdc817b22010-11-17 11:16:34 +00001383 h2 = hashit(x)
Christian Heimes2380ac72008-01-09 00:17:24 +00001384 c.prec = 16
Stefan Krahdc817b22010-11-17 11:16:34 +00001385 h3 = hashit(x)
Christian Heimes2380ac72008-01-09 00:17:24 +00001386
1387 self.assertEqual(h1, h2)
1388 self.assertEqual(h1, h3)
1389 c.prec = old_precision
1390
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001391 def test_min_and_max_methods(self):
1392
1393 d1 = Decimal('15.32')
1394 d2 = Decimal('28.5')
1395 l1 = 15
1396 l2 = 28
1397
1398 #between Decimals
Ezio Melotti6607d512010-04-03 14:59:49 +00001399 self.assertIs(min(d1,d2), d1)
1400 self.assertIs(min(d2,d1), d1)
1401 self.assertIs(max(d1,d2), d2)
1402 self.assertIs(max(d2,d1), d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001403
1404 #between Decimal and long
Ezio Melotti6607d512010-04-03 14:59:49 +00001405 self.assertIs(min(d1,l2), d1)
1406 self.assertIs(min(l2,d1), d1)
1407 self.assertIs(max(l1,d2), d2)
1408 self.assertIs(max(d2,l1), d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001409
1410 def test_as_nonzero(self):
1411 #as false
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001412 self.assertFalse(Decimal(0))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001413 #as true
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001414 self.assertTrue(Decimal('0.372'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001415
1416 def test_tostring_methods(self):
1417 #Test str and repr methods.
1418
1419 d = Decimal('15.32')
1420 self.assertEqual(str(d), '15.32') # str
Christian Heimes68f5fbe2008-02-14 08:27:37 +00001421 self.assertEqual(repr(d), "Decimal('15.32')") # repr
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001422
1423 def test_tonum_methods(self):
Mark Dickinson5c2db372009-12-05 20:28:34 +00001424 #Test float and int methods.
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001425
1426 d1 = Decimal('66')
1427 d2 = Decimal('15.32')
1428
1429 #int
1430 self.assertEqual(int(d1), 66)
1431 self.assertEqual(int(d2), 15)
1432
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001433 #float
1434 self.assertEqual(float(d1), 66)
1435 self.assertEqual(float(d2), 15.32)
1436
Mark Dickinsonb27406c2008-05-09 13:42:33 +00001437 #floor
1438 test_pairs = [
1439 ('123.00', 123),
1440 ('3.2', 3),
1441 ('3.54', 3),
1442 ('3.899', 3),
1443 ('-2.3', -3),
1444 ('-11.0', -11),
1445 ('0.0', 0),
1446 ('-0E3', 0),
1447 ]
1448 for d, i in test_pairs:
1449 self.assertEqual(math.floor(Decimal(d)), i)
1450 self.assertRaises(ValueError, math.floor, Decimal('-NaN'))
1451 self.assertRaises(ValueError, math.floor, Decimal('sNaN'))
1452 self.assertRaises(ValueError, math.floor, Decimal('NaN123'))
1453 self.assertRaises(OverflowError, math.floor, Decimal('Inf'))
1454 self.assertRaises(OverflowError, math.floor, Decimal('-Inf'))
1455
1456 #ceiling
1457 test_pairs = [
1458 ('123.00', 123),
1459 ('3.2', 4),
1460 ('3.54', 4),
1461 ('3.899', 4),
1462 ('-2.3', -2),
1463 ('-11.0', -11),
1464 ('0.0', 0),
1465 ('-0E3', 0),
1466 ]
1467 for d, i in test_pairs:
1468 self.assertEqual(math.ceil(Decimal(d)), i)
1469 self.assertRaises(ValueError, math.ceil, Decimal('-NaN'))
1470 self.assertRaises(ValueError, math.ceil, Decimal('sNaN'))
1471 self.assertRaises(ValueError, math.ceil, Decimal('NaN123'))
1472 self.assertRaises(OverflowError, math.ceil, Decimal('Inf'))
1473 self.assertRaises(OverflowError, math.ceil, Decimal('-Inf'))
1474
1475 #round, single argument
1476 test_pairs = [
1477 ('123.00', 123),
1478 ('3.2', 3),
1479 ('3.54', 4),
1480 ('3.899', 4),
1481 ('-2.3', -2),
1482 ('-11.0', -11),
1483 ('0.0', 0),
1484 ('-0E3', 0),
1485 ('-3.5', -4),
1486 ('-2.5', -2),
1487 ('-1.5', -2),
1488 ('-0.5', 0),
1489 ('0.5', 0),
1490 ('1.5', 2),
1491 ('2.5', 2),
1492 ('3.5', 4),
1493 ]
1494 for d, i in test_pairs:
1495 self.assertEqual(round(Decimal(d)), i)
1496 self.assertRaises(ValueError, round, Decimal('-NaN'))
1497 self.assertRaises(ValueError, round, Decimal('sNaN'))
1498 self.assertRaises(ValueError, round, Decimal('NaN123'))
1499 self.assertRaises(OverflowError, round, Decimal('Inf'))
1500 self.assertRaises(OverflowError, round, Decimal('-Inf'))
1501
1502 #round, two arguments; this is essentially equivalent
1503 #to quantize, which is already extensively tested
1504 test_triples = [
1505 ('123.456', -4, '0E+4'),
1506 ('123.456', -3, '0E+3'),
1507 ('123.456', -2, '1E+2'),
1508 ('123.456', -1, '1.2E+2'),
1509 ('123.456', 0, '123'),
1510 ('123.456', 1, '123.5'),
1511 ('123.456', 2, '123.46'),
1512 ('123.456', 3, '123.456'),
1513 ('123.456', 4, '123.4560'),
1514 ('123.455', 2, '123.46'),
1515 ('123.445', 2, '123.44'),
1516 ('Inf', 4, 'NaN'),
1517 ('-Inf', -23, 'NaN'),
1518 ('sNaN314', 3, 'NaN314'),
1519 ]
1520 for d, n, r in test_triples:
1521 self.assertEqual(str(round(Decimal(d), n)), r)
1522
1523
1524
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001525 def test_eval_round_trip(self):
1526
1527 #with zero
1528 d = Decimal( (0, (0,), 0) )
1529 self.assertEqual(d, eval(repr(d)))
1530
1531 #int
1532 d = Decimal( (1, (4, 5), 0) )
1533 self.assertEqual(d, eval(repr(d)))
1534
1535 #float
1536 d = Decimal( (0, (4, 5, 3, 4), -2) )
1537 self.assertEqual(d, eval(repr(d)))
1538
1539 #weird
1540 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1541 self.assertEqual(d, eval(repr(d)))
1542
1543 def test_as_tuple(self):
1544
1545 #with zero
1546 d = Decimal(0)
1547 self.assertEqual(d.as_tuple(), (0, (0,), 0) )
1548
1549 #int
1550 d = Decimal(-45)
1551 self.assertEqual(d.as_tuple(), (1, (4, 5), 0) )
1552
1553 #complicated string
1554 d = Decimal("-4.34913534E-17")
1555 self.assertEqual(d.as_tuple(), (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1556
1557 #inf
1558 d = Decimal("Infinity")
1559 self.assertEqual(d.as_tuple(), (0, (0,), 'F') )
1560
Guido van Rossum8ce8a782007-11-01 19:42:39 +00001561 #leading zeros in coefficient should be stripped
1562 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), -2) )
1563 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), -2) )
1564 d = Decimal( (1, (0, 0, 0), 37) )
1565 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1566 d = Decimal( (1, (), 37) )
1567 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1568
1569 #leading zeros in NaN diagnostic info should be stripped
1570 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), 'n') )
1571 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), 'n') )
1572 d = Decimal( (1, (0, 0, 0), 'N') )
1573 self.assertEqual(d.as_tuple(), (1, (), 'N') )
1574 d = Decimal( (1, (), 'n') )
1575 self.assertEqual(d.as_tuple(), (1, (), 'n') )
1576
1577 #coefficient in infinity should be ignored
1578 d = Decimal( (0, (4, 5, 3, 4), 'F') )
1579 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
1580 d = Decimal( (1, (0, 2, 7, 1), 'F') )
1581 self.assertEqual(d.as_tuple(), (1, (0,), 'F'))
1582
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001583 def test_immutability_operations(self):
1584 # Do operations and check that it didn't change change internal objects.
1585
1586 d1 = Decimal('-25e55')
1587 b1 = Decimal('-25e55')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001588 d2 = Decimal('33e+33')
1589 b2 = Decimal('33e+33')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001590
1591 def checkSameDec(operation, useOther=False):
1592 if useOther:
1593 eval("d1." + operation + "(d2)")
1594 self.assertEqual(d1._sign, b1._sign)
1595 self.assertEqual(d1._int, b1._int)
1596 self.assertEqual(d1._exp, b1._exp)
1597 self.assertEqual(d2._sign, b2._sign)
1598 self.assertEqual(d2._int, b2._int)
1599 self.assertEqual(d2._exp, b2._exp)
1600 else:
1601 eval("d1." + operation + "()")
1602 self.assertEqual(d1._sign, b1._sign)
1603 self.assertEqual(d1._int, b1._int)
1604 self.assertEqual(d1._exp, b1._exp)
1605 return
1606
1607 Decimal(d1)
1608 self.assertEqual(d1._sign, b1._sign)
1609 self.assertEqual(d1._int, b1._int)
1610 self.assertEqual(d1._exp, b1._exp)
1611
1612 checkSameDec("__abs__")
1613 checkSameDec("__add__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001614 checkSameDec("__divmod__", True)
Christian Heimes77c02eb2008-02-09 02:18:51 +00001615 checkSameDec("__eq__", True)
1616 checkSameDec("__ne__", True)
1617 checkSameDec("__le__", True)
1618 checkSameDec("__lt__", True)
1619 checkSameDec("__ge__", True)
1620 checkSameDec("__gt__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001621 checkSameDec("__float__")
1622 checkSameDec("__floordiv__", True)
1623 checkSameDec("__hash__")
1624 checkSameDec("__int__")
Christian Heimes969fe572008-01-25 11:23:10 +00001625 checkSameDec("__trunc__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001626 checkSameDec("__mod__", True)
1627 checkSameDec("__mul__", True)
1628 checkSameDec("__neg__")
Jack Diederich4dafcc42006-11-28 19:15:13 +00001629 checkSameDec("__bool__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001630 checkSameDec("__pos__")
1631 checkSameDec("__pow__", True)
1632 checkSameDec("__radd__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001633 checkSameDec("__rdivmod__", True)
1634 checkSameDec("__repr__")
1635 checkSameDec("__rfloordiv__", True)
1636 checkSameDec("__rmod__", True)
1637 checkSameDec("__rmul__", True)
1638 checkSameDec("__rpow__", True)
1639 checkSameDec("__rsub__", True)
1640 checkSameDec("__str__")
1641 checkSameDec("__sub__", True)
1642 checkSameDec("__truediv__", True)
1643 checkSameDec("adjusted")
1644 checkSameDec("as_tuple")
1645 checkSameDec("compare", True)
1646 checkSameDec("max", True)
1647 checkSameDec("min", True)
1648 checkSameDec("normalize")
1649 checkSameDec("quantize", True)
1650 checkSameDec("remainder_near", True)
1651 checkSameDec("same_quantum", True)
1652 checkSameDec("sqrt")
1653 checkSameDec("to_eng_string")
1654 checkSameDec("to_integral")
1655
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001656 def test_subclassing(self):
1657 # Different behaviours when subclassing Decimal
1658
1659 class MyDecimal(Decimal):
1660 pass
1661
1662 d1 = MyDecimal(1)
1663 d2 = MyDecimal(2)
1664 d = d1 + d2
Ezio Melotti6607d512010-04-03 14:59:49 +00001665 self.assertIs(type(d), Decimal)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001666
1667 d = d1.max(d2)
Ezio Melotti6607d512010-04-03 14:59:49 +00001668 self.assertIs(type(d), Decimal)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001669
Christian Heimes0348fb62008-03-26 12:55:56 +00001670 def test_implicit_context(self):
1671 # Check results when context given implicitly. (Issue 2478)
1672 c = getcontext()
1673 self.assertEqual(str(Decimal(0).sqrt()),
1674 str(c.sqrt(Decimal(0))))
1675
Mark Dickinsona2d1fe02009-10-29 12:23:02 +00001676 def test_conversions_from_int(self):
1677 # Check that methods taking a second Decimal argument will
1678 # always accept an integer in place of a Decimal.
1679 self.assertEqual(Decimal(4).compare(3),
1680 Decimal(4).compare(Decimal(3)))
1681 self.assertEqual(Decimal(4).compare_signal(3),
1682 Decimal(4).compare_signal(Decimal(3)))
1683 self.assertEqual(Decimal(4).compare_total(3),
1684 Decimal(4).compare_total(Decimal(3)))
1685 self.assertEqual(Decimal(4).compare_total_mag(3),
1686 Decimal(4).compare_total_mag(Decimal(3)))
1687 self.assertEqual(Decimal(10101).logical_and(1001),
1688 Decimal(10101).logical_and(Decimal(1001)))
1689 self.assertEqual(Decimal(10101).logical_or(1001),
1690 Decimal(10101).logical_or(Decimal(1001)))
1691 self.assertEqual(Decimal(10101).logical_xor(1001),
1692 Decimal(10101).logical_xor(Decimal(1001)))
1693 self.assertEqual(Decimal(567).max(123),
1694 Decimal(567).max(Decimal(123)))
1695 self.assertEqual(Decimal(567).max_mag(123),
1696 Decimal(567).max_mag(Decimal(123)))
1697 self.assertEqual(Decimal(567).min(123),
1698 Decimal(567).min(Decimal(123)))
1699 self.assertEqual(Decimal(567).min_mag(123),
1700 Decimal(567).min_mag(Decimal(123)))
1701 self.assertEqual(Decimal(567).next_toward(123),
1702 Decimal(567).next_toward(Decimal(123)))
1703 self.assertEqual(Decimal(1234).quantize(100),
1704 Decimal(1234).quantize(Decimal(100)))
1705 self.assertEqual(Decimal(768).remainder_near(1234),
1706 Decimal(768).remainder_near(Decimal(1234)))
1707 self.assertEqual(Decimal(123).rotate(1),
1708 Decimal(123).rotate(Decimal(1)))
1709 self.assertEqual(Decimal(1234).same_quantum(1000),
1710 Decimal(1234).same_quantum(Decimal(1000)))
1711 self.assertEqual(Decimal('9.123').scaleb(-100),
1712 Decimal('9.123').scaleb(Decimal(-100)))
1713 self.assertEqual(Decimal(456).shift(-1),
1714 Decimal(456).shift(Decimal(-1)))
1715
1716 self.assertEqual(Decimal(-12).fma(Decimal(45), 67),
1717 Decimal(-12).fma(Decimal(45), Decimal(67)))
1718 self.assertEqual(Decimal(-12).fma(45, 67),
1719 Decimal(-12).fma(Decimal(45), Decimal(67)))
1720 self.assertEqual(Decimal(-12).fma(45, Decimal(67)),
1721 Decimal(-12).fma(Decimal(45), Decimal(67)))
1722
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001723
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001724class DecimalPythonAPItests(unittest.TestCase):
1725
Raymond Hettinger82417ca2009-02-03 03:54:28 +00001726 def test_abc(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001727 self.assertTrue(issubclass(Decimal, numbers.Number))
Ezio Melotti6607d512010-04-03 14:59:49 +00001728 self.assertFalse(issubclass(Decimal, numbers.Real))
Ezio Melottie9615932010-01-24 19:26:24 +00001729 self.assertIsInstance(Decimal(0), numbers.Number)
1730 self.assertNotIsInstance(Decimal(0), numbers.Real)
Raymond Hettinger82417ca2009-02-03 03:54:28 +00001731
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001732 def test_pickle(self):
1733 d = Decimal('-3.141590000')
1734 p = pickle.dumps(d)
1735 e = pickle.loads(p)
1736 self.assertEqual(d, e)
1737
Raymond Hettinger5548be22004-07-05 18:49:38 +00001738 def test_int(self):
Raymond Hettinger605ed022004-11-24 07:28:48 +00001739 for x in range(-250, 250):
1740 s = '%0.2f' % (x / 100.0)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001741 # should work the same as for floats
1742 self.assertEqual(int(Decimal(s)), int(float(s)))
Raymond Hettinger605ed022004-11-24 07:28:48 +00001743 # should work the same as to_integral in the ROUND_DOWN mode
Raymond Hettinger5548be22004-07-05 18:49:38 +00001744 d = Decimal(s)
Raymond Hettinger605ed022004-11-24 07:28:48 +00001745 r = d.to_integral(ROUND_DOWN)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001746 self.assertEqual(Decimal(int(d)), r)
1747
Mark Dickinson825fce32009-09-07 18:08:12 +00001748 self.assertRaises(ValueError, int, Decimal('-nan'))
1749 self.assertRaises(ValueError, int, Decimal('snan'))
1750 self.assertRaises(OverflowError, int, Decimal('inf'))
1751 self.assertRaises(OverflowError, int, Decimal('-inf'))
1752
Christian Heimes969fe572008-01-25 11:23:10 +00001753 def test_trunc(self):
1754 for x in range(-250, 250):
1755 s = '%0.2f' % (x / 100.0)
1756 # should work the same as for floats
1757 self.assertEqual(int(Decimal(s)), int(float(s)))
1758 # should work the same as to_integral in the ROUND_DOWN mode
1759 d = Decimal(s)
1760 r = d.to_integral(ROUND_DOWN)
Christian Heimes400adb02008-02-01 08:12:03 +00001761 self.assertEqual(Decimal(math.trunc(d)), r)
Christian Heimes969fe572008-01-25 11:23:10 +00001762
Raymond Hettinger771ed762009-01-03 19:20:32 +00001763 def test_from_float(self):
1764
1765 class MyDecimal(Decimal):
1766 pass
1767
1768 r = MyDecimal.from_float(0.1)
1769 self.assertEqual(type(r), MyDecimal)
1770 self.assertEqual(str(r),
1771 '0.1000000000000000055511151231257827021181583404541015625')
1772 bigint = 12345678901234567890123456789
1773 self.assertEqual(MyDecimal.from_float(bigint), MyDecimal(bigint))
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001774 self.assertTrue(MyDecimal.from_float(float('nan')).is_qnan())
1775 self.assertTrue(MyDecimal.from_float(float('inf')).is_infinite())
1776 self.assertTrue(MyDecimal.from_float(float('-inf')).is_infinite())
Raymond Hettinger771ed762009-01-03 19:20:32 +00001777 self.assertEqual(str(MyDecimal.from_float(float('nan'))),
1778 str(Decimal('NaN')))
1779 self.assertEqual(str(MyDecimal.from_float(float('inf'))),
1780 str(Decimal('Infinity')))
1781 self.assertEqual(str(MyDecimal.from_float(float('-inf'))),
1782 str(Decimal('-Infinity')))
1783 self.assertRaises(TypeError, MyDecimal.from_float, 'abc')
1784 for i in range(200):
1785 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
1786 self.assertEqual(x, float(MyDecimal.from_float(x))) # roundtrip
1787
1788 def test_create_decimal_from_float(self):
1789 context = Context(prec=5, rounding=ROUND_DOWN)
1790 self.assertEqual(
1791 context.create_decimal_from_float(math.pi),
1792 Decimal('3.1415')
1793 )
1794 context = Context(prec=5, rounding=ROUND_UP)
1795 self.assertEqual(
1796 context.create_decimal_from_float(math.pi),
1797 Decimal('3.1416')
1798 )
1799 context = Context(prec=5, traps=[Inexact])
1800 self.assertRaises(
1801 Inexact,
1802 context.create_decimal_from_float,
1803 math.pi
1804 )
1805 self.assertEqual(repr(context.create_decimal_from_float(-0.0)),
1806 "Decimal('-0')")
1807 self.assertEqual(repr(context.create_decimal_from_float(1.0)),
1808 "Decimal('1')")
1809 self.assertEqual(repr(context.create_decimal_from_float(10)),
1810 "Decimal('10')")
1811
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00001812class ContextAPItests(unittest.TestCase):
1813
1814 def test_pickle(self):
1815 c = Context()
1816 e = pickle.loads(pickle.dumps(c))
1817 for k in vars(c):
1818 v1 = vars(c)[k]
1819 v2 = vars(e)[k]
1820 self.assertEqual(v1, v2)
1821
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001822 def test_equality_with_other_types(self):
Benjamin Peterson577473f2010-01-19 00:09:57 +00001823 self.assertIn(Decimal(10), ['a', 1.0, Decimal(10), (1,2), {}])
1824 self.assertNotIn(Decimal(10), ['a', 1.0, (1,2), {}])
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001825
Raymond Hettinger955d2b22004-08-08 20:17:45 +00001826 def test_copy(self):
1827 # All copies should be deep
1828 c = Context()
1829 d = c.copy()
1830 self.assertNotEqual(id(c), id(d))
1831 self.assertNotEqual(id(c.flags), id(d.flags))
1832 self.assertNotEqual(id(c.traps), id(d.traps))
1833
Mark Dickinsonb1d8e322010-05-22 18:35:36 +00001834 def test__clamp(self):
1835 # In Python 3.2, the private attribute `_clamp` was made
1836 # public (issue 8540), with the old `_clamp` becoming a
1837 # property wrapping `clamp`. For the duration of Python 3.2
1838 # only, the attribute should be gettable/settable via both
1839 # `clamp` and `_clamp`; in Python 3.3, `_clamp` should be
1840 # removed.
1841 c = Context(clamp = 0)
1842 self.assertEqual(c.clamp, 0)
1843
1844 with check_warnings(("", DeprecationWarning)):
1845 c._clamp = 1
1846 self.assertEqual(c.clamp, 1)
1847 with check_warnings(("", DeprecationWarning)):
1848 self.assertEqual(c._clamp, 1)
1849 c.clamp = 0
1850 self.assertEqual(c.clamp, 0)
1851 with check_warnings(("", DeprecationWarning)):
1852 self.assertEqual(c._clamp, 0)
1853
Mark Dickinson84230a12010-02-18 14:49:50 +00001854 def test_abs(self):
1855 c = Context()
1856 d = c.abs(Decimal(-1))
1857 self.assertEqual(c.abs(-1), d)
1858 self.assertRaises(TypeError, c.abs, '-1')
1859
1860 def test_add(self):
1861 c = Context()
1862 d = c.add(Decimal(1), Decimal(1))
1863 self.assertEqual(c.add(1, 1), d)
1864 self.assertEqual(c.add(Decimal(1), 1), d)
1865 self.assertEqual(c.add(1, Decimal(1)), d)
1866 self.assertRaises(TypeError, c.add, '1', 1)
1867 self.assertRaises(TypeError, c.add, 1, '1')
1868
1869 def test_compare(self):
1870 c = Context()
1871 d = c.compare(Decimal(1), Decimal(1))
1872 self.assertEqual(c.compare(1, 1), d)
1873 self.assertEqual(c.compare(Decimal(1), 1), d)
1874 self.assertEqual(c.compare(1, Decimal(1)), d)
1875 self.assertRaises(TypeError, c.compare, '1', 1)
1876 self.assertRaises(TypeError, c.compare, 1, '1')
1877
1878 def test_compare_signal(self):
1879 c = Context()
1880 d = c.compare_signal(Decimal(1), Decimal(1))
1881 self.assertEqual(c.compare_signal(1, 1), d)
1882 self.assertEqual(c.compare_signal(Decimal(1), 1), d)
1883 self.assertEqual(c.compare_signal(1, Decimal(1)), d)
1884 self.assertRaises(TypeError, c.compare_signal, '1', 1)
1885 self.assertRaises(TypeError, c.compare_signal, 1, '1')
1886
1887 def test_compare_total(self):
1888 c = Context()
1889 d = c.compare_total(Decimal(1), Decimal(1))
1890 self.assertEqual(c.compare_total(1, 1), d)
1891 self.assertEqual(c.compare_total(Decimal(1), 1), d)
1892 self.assertEqual(c.compare_total(1, Decimal(1)), d)
1893 self.assertRaises(TypeError, c.compare_total, '1', 1)
1894 self.assertRaises(TypeError, c.compare_total, 1, '1')
1895
1896 def test_compare_total_mag(self):
1897 c = Context()
1898 d = c.compare_total_mag(Decimal(1), Decimal(1))
1899 self.assertEqual(c.compare_total_mag(1, 1), d)
1900 self.assertEqual(c.compare_total_mag(Decimal(1), 1), d)
1901 self.assertEqual(c.compare_total_mag(1, Decimal(1)), d)
1902 self.assertRaises(TypeError, c.compare_total_mag, '1', 1)
1903 self.assertRaises(TypeError, c.compare_total_mag, 1, '1')
1904
1905 def test_copy_abs(self):
1906 c = Context()
1907 d = c.copy_abs(Decimal(-1))
1908 self.assertEqual(c.copy_abs(-1), d)
1909 self.assertRaises(TypeError, c.copy_abs, '-1')
1910
1911 def test_copy_decimal(self):
1912 c = Context()
1913 d = c.copy_decimal(Decimal(-1))
1914 self.assertEqual(c.copy_decimal(-1), d)
1915 self.assertRaises(TypeError, c.copy_decimal, '-1')
1916
1917 def test_copy_negate(self):
1918 c = Context()
1919 d = c.copy_negate(Decimal(-1))
1920 self.assertEqual(c.copy_negate(-1), d)
1921 self.assertRaises(TypeError, c.copy_negate, '-1')
1922
1923 def test_copy_sign(self):
1924 c = Context()
1925 d = c.copy_sign(Decimal(1), Decimal(-2))
1926 self.assertEqual(c.copy_sign(1, -2), d)
1927 self.assertEqual(c.copy_sign(Decimal(1), -2), d)
1928 self.assertEqual(c.copy_sign(1, Decimal(-2)), d)
1929 self.assertRaises(TypeError, c.copy_sign, '1', -2)
1930 self.assertRaises(TypeError, c.copy_sign, 1, '-2')
1931
1932 def test_divide(self):
1933 c = Context()
1934 d = c.divide(Decimal(1), Decimal(2))
1935 self.assertEqual(c.divide(1, 2), d)
1936 self.assertEqual(c.divide(Decimal(1), 2), d)
1937 self.assertEqual(c.divide(1, Decimal(2)), d)
1938 self.assertRaises(TypeError, c.divide, '1', 2)
1939 self.assertRaises(TypeError, c.divide, 1, '2')
1940
1941 def test_divide_int(self):
1942 c = Context()
1943 d = c.divide_int(Decimal(1), Decimal(2))
1944 self.assertEqual(c.divide_int(1, 2), d)
1945 self.assertEqual(c.divide_int(Decimal(1), 2), d)
1946 self.assertEqual(c.divide_int(1, Decimal(2)), d)
1947 self.assertRaises(TypeError, c.divide_int, '1', 2)
1948 self.assertRaises(TypeError, c.divide_int, 1, '2')
1949
1950 def test_divmod(self):
1951 c = Context()
1952 d = c.divmod(Decimal(1), Decimal(2))
1953 self.assertEqual(c.divmod(1, 2), d)
1954 self.assertEqual(c.divmod(Decimal(1), 2), d)
1955 self.assertEqual(c.divmod(1, Decimal(2)), d)
1956 self.assertRaises(TypeError, c.divmod, '1', 2)
1957 self.assertRaises(TypeError, c.divmod, 1, '2')
1958
1959 def test_exp(self):
1960 c = Context()
1961 d = c.exp(Decimal(10))
1962 self.assertEqual(c.exp(10), d)
1963 self.assertRaises(TypeError, c.exp, '10')
1964
1965 def test_fma(self):
1966 c = Context()
1967 d = c.fma(Decimal(2), Decimal(3), Decimal(4))
1968 self.assertEqual(c.fma(2, 3, 4), d)
1969 self.assertEqual(c.fma(Decimal(2), 3, 4), d)
1970 self.assertEqual(c.fma(2, Decimal(3), 4), d)
1971 self.assertEqual(c.fma(2, 3, Decimal(4)), d)
1972 self.assertEqual(c.fma(Decimal(2), Decimal(3), 4), d)
1973 self.assertRaises(TypeError, c.fma, '2', 3, 4)
1974 self.assertRaises(TypeError, c.fma, 2, '3', 4)
1975 self.assertRaises(TypeError, c.fma, 2, 3, '4')
1976
1977 def test_is_finite(self):
1978 c = Context()
1979 d = c.is_finite(Decimal(10))
1980 self.assertEqual(c.is_finite(10), d)
1981 self.assertRaises(TypeError, c.is_finite, '10')
1982
1983 def test_is_infinite(self):
1984 c = Context()
1985 d = c.is_infinite(Decimal(10))
1986 self.assertEqual(c.is_infinite(10), d)
1987 self.assertRaises(TypeError, c.is_infinite, '10')
1988
1989 def test_is_nan(self):
1990 c = Context()
1991 d = c.is_nan(Decimal(10))
1992 self.assertEqual(c.is_nan(10), d)
1993 self.assertRaises(TypeError, c.is_nan, '10')
1994
1995 def test_is_normal(self):
1996 c = Context()
1997 d = c.is_normal(Decimal(10))
1998 self.assertEqual(c.is_normal(10), d)
1999 self.assertRaises(TypeError, c.is_normal, '10')
2000
2001 def test_is_qnan(self):
2002 c = Context()
2003 d = c.is_qnan(Decimal(10))
2004 self.assertEqual(c.is_qnan(10), d)
2005 self.assertRaises(TypeError, c.is_qnan, '10')
2006
2007 def test_is_signed(self):
2008 c = Context()
2009 d = c.is_signed(Decimal(10))
2010 self.assertEqual(c.is_signed(10), d)
2011 self.assertRaises(TypeError, c.is_signed, '10')
2012
2013 def test_is_snan(self):
2014 c = Context()
2015 d = c.is_snan(Decimal(10))
2016 self.assertEqual(c.is_snan(10), d)
2017 self.assertRaises(TypeError, c.is_snan, '10')
2018
2019 def test_is_subnormal(self):
2020 c = Context()
2021 d = c.is_subnormal(Decimal(10))
2022 self.assertEqual(c.is_subnormal(10), d)
2023 self.assertRaises(TypeError, c.is_subnormal, '10')
2024
2025 def test_is_zero(self):
2026 c = Context()
2027 d = c.is_zero(Decimal(10))
2028 self.assertEqual(c.is_zero(10), d)
2029 self.assertRaises(TypeError, c.is_zero, '10')
2030
2031 def test_ln(self):
2032 c = Context()
2033 d = c.ln(Decimal(10))
2034 self.assertEqual(c.ln(10), d)
2035 self.assertRaises(TypeError, c.ln, '10')
2036
2037 def test_log10(self):
2038 c = Context()
2039 d = c.log10(Decimal(10))
2040 self.assertEqual(c.log10(10), d)
2041 self.assertRaises(TypeError, c.log10, '10')
2042
2043 def test_logb(self):
2044 c = Context()
2045 d = c.logb(Decimal(10))
2046 self.assertEqual(c.logb(10), d)
2047 self.assertRaises(TypeError, c.logb, '10')
2048
2049 def test_logical_and(self):
2050 c = Context()
2051 d = c.logical_and(Decimal(1), Decimal(1))
2052 self.assertEqual(c.logical_and(1, 1), d)
2053 self.assertEqual(c.logical_and(Decimal(1), 1), d)
2054 self.assertEqual(c.logical_and(1, Decimal(1)), d)
2055 self.assertRaises(TypeError, c.logical_and, '1', 1)
2056 self.assertRaises(TypeError, c.logical_and, 1, '1')
2057
2058 def test_logical_invert(self):
2059 c = Context()
2060 d = c.logical_invert(Decimal(1000))
2061 self.assertEqual(c.logical_invert(1000), d)
2062 self.assertRaises(TypeError, c.logical_invert, '1000')
2063
2064 def test_logical_or(self):
2065 c = Context()
2066 d = c.logical_or(Decimal(1), Decimal(1))
2067 self.assertEqual(c.logical_or(1, 1), d)
2068 self.assertEqual(c.logical_or(Decimal(1), 1), d)
2069 self.assertEqual(c.logical_or(1, Decimal(1)), d)
2070 self.assertRaises(TypeError, c.logical_or, '1', 1)
2071 self.assertRaises(TypeError, c.logical_or, 1, '1')
2072
2073 def test_logical_xor(self):
2074 c = Context()
2075 d = c.logical_xor(Decimal(1), Decimal(1))
2076 self.assertEqual(c.logical_xor(1, 1), d)
2077 self.assertEqual(c.logical_xor(Decimal(1), 1), d)
2078 self.assertEqual(c.logical_xor(1, Decimal(1)), d)
2079 self.assertRaises(TypeError, c.logical_xor, '1', 1)
2080 self.assertRaises(TypeError, c.logical_xor, 1, '1')
2081
2082 def test_max(self):
2083 c = Context()
2084 d = c.max(Decimal(1), Decimal(2))
2085 self.assertEqual(c.max(1, 2), d)
2086 self.assertEqual(c.max(Decimal(1), 2), d)
2087 self.assertEqual(c.max(1, Decimal(2)), d)
2088 self.assertRaises(TypeError, c.max, '1', 2)
2089 self.assertRaises(TypeError, c.max, 1, '2')
2090
2091 def test_max_mag(self):
2092 c = Context()
2093 d = c.max_mag(Decimal(1), Decimal(2))
2094 self.assertEqual(c.max_mag(1, 2), d)
2095 self.assertEqual(c.max_mag(Decimal(1), 2), d)
2096 self.assertEqual(c.max_mag(1, Decimal(2)), d)
2097 self.assertRaises(TypeError, c.max_mag, '1', 2)
2098 self.assertRaises(TypeError, c.max_mag, 1, '2')
2099
2100 def test_min(self):
2101 c = Context()
2102 d = c.min(Decimal(1), Decimal(2))
2103 self.assertEqual(c.min(1, 2), d)
2104 self.assertEqual(c.min(Decimal(1), 2), d)
2105 self.assertEqual(c.min(1, Decimal(2)), d)
2106 self.assertRaises(TypeError, c.min, '1', 2)
2107 self.assertRaises(TypeError, c.min, 1, '2')
2108
2109 def test_min_mag(self):
2110 c = Context()
2111 d = c.min_mag(Decimal(1), Decimal(2))
2112 self.assertEqual(c.min_mag(1, 2), d)
2113 self.assertEqual(c.min_mag(Decimal(1), 2), d)
2114 self.assertEqual(c.min_mag(1, Decimal(2)), d)
2115 self.assertRaises(TypeError, c.min_mag, '1', 2)
2116 self.assertRaises(TypeError, c.min_mag, 1, '2')
2117
2118 def test_minus(self):
2119 c = Context()
2120 d = c.minus(Decimal(10))
2121 self.assertEqual(c.minus(10), d)
2122 self.assertRaises(TypeError, c.minus, '10')
2123
2124 def test_multiply(self):
2125 c = Context()
2126 d = c.multiply(Decimal(1), Decimal(2))
2127 self.assertEqual(c.multiply(1, 2), d)
2128 self.assertEqual(c.multiply(Decimal(1), 2), d)
2129 self.assertEqual(c.multiply(1, Decimal(2)), d)
2130 self.assertRaises(TypeError, c.multiply, '1', 2)
2131 self.assertRaises(TypeError, c.multiply, 1, '2')
2132
2133 def test_next_minus(self):
2134 c = Context()
2135 d = c.next_minus(Decimal(10))
2136 self.assertEqual(c.next_minus(10), d)
2137 self.assertRaises(TypeError, c.next_minus, '10')
2138
2139 def test_next_plus(self):
2140 c = Context()
2141 d = c.next_plus(Decimal(10))
2142 self.assertEqual(c.next_plus(10), d)
2143 self.assertRaises(TypeError, c.next_plus, '10')
2144
2145 def test_next_toward(self):
2146 c = Context()
2147 d = c.next_toward(Decimal(1), Decimal(2))
2148 self.assertEqual(c.next_toward(1, 2), d)
2149 self.assertEqual(c.next_toward(Decimal(1), 2), d)
2150 self.assertEqual(c.next_toward(1, Decimal(2)), d)
2151 self.assertRaises(TypeError, c.next_toward, '1', 2)
2152 self.assertRaises(TypeError, c.next_toward, 1, '2')
2153
2154 def test_normalize(self):
2155 c = Context()
2156 d = c.normalize(Decimal(10))
2157 self.assertEqual(c.normalize(10), d)
2158 self.assertRaises(TypeError, c.normalize, '10')
2159
2160 def test_number_class(self):
2161 c = Context()
2162 self.assertEqual(c.number_class(123), c.number_class(Decimal(123)))
2163 self.assertEqual(c.number_class(0), c.number_class(Decimal(0)))
2164 self.assertEqual(c.number_class(-45), c.number_class(Decimal(-45)))
2165
2166 def test_power(self):
2167 c = Context()
2168 d = c.power(Decimal(1), Decimal(4), Decimal(2))
2169 self.assertEqual(c.power(1, 4, 2), d)
2170 self.assertEqual(c.power(Decimal(1), 4, 2), d)
2171 self.assertEqual(c.power(1, Decimal(4), 2), d)
2172 self.assertEqual(c.power(1, 4, Decimal(2)), d)
2173 self.assertEqual(c.power(Decimal(1), Decimal(4), 2), d)
2174 self.assertRaises(TypeError, c.power, '1', 4, 2)
2175 self.assertRaises(TypeError, c.power, 1, '4', 2)
2176 self.assertRaises(TypeError, c.power, 1, 4, '2')
2177
2178 def test_plus(self):
2179 c = Context()
2180 d = c.plus(Decimal(10))
2181 self.assertEqual(c.plus(10), d)
2182 self.assertRaises(TypeError, c.plus, '10')
2183
2184 def test_quantize(self):
2185 c = Context()
2186 d = c.quantize(Decimal(1), Decimal(2))
2187 self.assertEqual(c.quantize(1, 2), d)
2188 self.assertEqual(c.quantize(Decimal(1), 2), d)
2189 self.assertEqual(c.quantize(1, Decimal(2)), d)
2190 self.assertRaises(TypeError, c.quantize, '1', 2)
2191 self.assertRaises(TypeError, c.quantize, 1, '2')
2192
2193 def test_remainder(self):
2194 c = Context()
2195 d = c.remainder(Decimal(1), Decimal(2))
2196 self.assertEqual(c.remainder(1, 2), d)
2197 self.assertEqual(c.remainder(Decimal(1), 2), d)
2198 self.assertEqual(c.remainder(1, Decimal(2)), d)
2199 self.assertRaises(TypeError, c.remainder, '1', 2)
2200 self.assertRaises(TypeError, c.remainder, 1, '2')
2201
2202 def test_remainder_near(self):
2203 c = Context()
2204 d = c.remainder_near(Decimal(1), Decimal(2))
2205 self.assertEqual(c.remainder_near(1, 2), d)
2206 self.assertEqual(c.remainder_near(Decimal(1), 2), d)
2207 self.assertEqual(c.remainder_near(1, Decimal(2)), d)
2208 self.assertRaises(TypeError, c.remainder_near, '1', 2)
2209 self.assertRaises(TypeError, c.remainder_near, 1, '2')
2210
2211 def test_rotate(self):
2212 c = Context()
2213 d = c.rotate(Decimal(1), Decimal(2))
2214 self.assertEqual(c.rotate(1, 2), d)
2215 self.assertEqual(c.rotate(Decimal(1), 2), d)
2216 self.assertEqual(c.rotate(1, Decimal(2)), d)
2217 self.assertRaises(TypeError, c.rotate, '1', 2)
2218 self.assertRaises(TypeError, c.rotate, 1, '2')
2219
2220 def test_sqrt(self):
2221 c = Context()
2222 d = c.sqrt(Decimal(10))
2223 self.assertEqual(c.sqrt(10), d)
2224 self.assertRaises(TypeError, c.sqrt, '10')
2225
2226 def test_same_quantum(self):
2227 c = Context()
2228 d = c.same_quantum(Decimal(1), Decimal(2))
2229 self.assertEqual(c.same_quantum(1, 2), d)
2230 self.assertEqual(c.same_quantum(Decimal(1), 2), d)
2231 self.assertEqual(c.same_quantum(1, Decimal(2)), d)
2232 self.assertRaises(TypeError, c.same_quantum, '1', 2)
2233 self.assertRaises(TypeError, c.same_quantum, 1, '2')
2234
2235 def test_scaleb(self):
2236 c = Context()
2237 d = c.scaleb(Decimal(1), Decimal(2))
2238 self.assertEqual(c.scaleb(1, 2), d)
2239 self.assertEqual(c.scaleb(Decimal(1), 2), d)
2240 self.assertEqual(c.scaleb(1, Decimal(2)), d)
2241 self.assertRaises(TypeError, c.scaleb, '1', 2)
2242 self.assertRaises(TypeError, c.scaleb, 1, '2')
2243
2244 def test_shift(self):
2245 c = Context()
2246 d = c.shift(Decimal(1), Decimal(2))
2247 self.assertEqual(c.shift(1, 2), d)
2248 self.assertEqual(c.shift(Decimal(1), 2), d)
2249 self.assertEqual(c.shift(1, Decimal(2)), d)
2250 self.assertRaises(TypeError, c.shift, '1', 2)
2251 self.assertRaises(TypeError, c.shift, 1, '2')
2252
2253 def test_subtract(self):
2254 c = Context()
2255 d = c.subtract(Decimal(1), Decimal(2))
2256 self.assertEqual(c.subtract(1, 2), d)
2257 self.assertEqual(c.subtract(Decimal(1), 2), d)
2258 self.assertEqual(c.subtract(1, Decimal(2)), d)
2259 self.assertRaises(TypeError, c.subtract, '1', 2)
2260 self.assertRaises(TypeError, c.subtract, 1, '2')
2261
2262 def test_to_eng_string(self):
2263 c = Context()
2264 d = c.to_eng_string(Decimal(10))
2265 self.assertEqual(c.to_eng_string(10), d)
2266 self.assertRaises(TypeError, c.to_eng_string, '10')
2267
2268 def test_to_sci_string(self):
2269 c = Context()
2270 d = c.to_sci_string(Decimal(10))
2271 self.assertEqual(c.to_sci_string(10), d)
2272 self.assertRaises(TypeError, c.to_sci_string, '10')
2273
2274 def test_to_integral_exact(self):
2275 c = Context()
2276 d = c.to_integral_exact(Decimal(10))
2277 self.assertEqual(c.to_integral_exact(10), d)
2278 self.assertRaises(TypeError, c.to_integral_exact, '10')
2279
2280 def test_to_integral_value(self):
2281 c = Context()
2282 d = c.to_integral_value(Decimal(10))
2283 self.assertEqual(c.to_integral_value(10), d)
2284 self.assertRaises(TypeError, c.to_integral_value, '10')
2285
Thomas Wouters89f507f2006-12-13 04:49:30 +00002286class WithStatementTest(unittest.TestCase):
2287 # Can't do these as docstrings until Python 2.6
2288 # as doctest can't handle __future__ statements
2289
2290 def test_localcontext(self):
2291 # Use a copy of the current context in the block
2292 orig_ctx = getcontext()
2293 with localcontext() as enter_ctx:
2294 set_ctx = getcontext()
2295 final_ctx = getcontext()
Ezio Melotti6607d512010-04-03 14:59:49 +00002296 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
2297 self.assertIsNot(orig_ctx, set_ctx, 'did not copy the context')
2298 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
Thomas Wouters89f507f2006-12-13 04:49:30 +00002299
2300 def test_localcontextarg(self):
2301 # Use a copy of the supplied context in the block
2302 orig_ctx = getcontext()
2303 new_ctx = Context(prec=42)
2304 with localcontext(new_ctx) as enter_ctx:
2305 set_ctx = getcontext()
2306 final_ctx = getcontext()
Ezio Melotti6607d512010-04-03 14:59:49 +00002307 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
2308 self.assertEqual(set_ctx.prec, new_ctx.prec, 'did not set correct context')
2309 self.assertIsNot(new_ctx, set_ctx, 'did not copy the context')
2310 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
Thomas Wouters89f507f2006-12-13 04:49:30 +00002311
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002312class ContextFlags(unittest.TestCase):
2313 def test_flags_irrelevant(self):
2314 # check that the result (numeric result + flags raised) of an
2315 # arithmetic operation doesn't depend on the current flags
2316
2317 context = Context(prec=9, Emin = -999999999, Emax = 999999999,
2318 rounding=ROUND_HALF_EVEN, traps=[], flags=[])
2319
2320 # operations that raise various flags, in the form (function, arglist)
2321 operations = [
2322 (context._apply, [Decimal("100E-1000000009")]),
2323 (context.sqrt, [Decimal(2)]),
2324 (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]),
2325 (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]),
2326 (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]),
2327 ]
2328
2329 # try various flags individually, then a whole lot at once
2330 flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal],
2331 [Inexact, Rounded, Underflow, Clamped, Subnormal]]
2332
2333 for fn, args in operations:
2334 # find answer and flags raised using a clean context
2335 context.clear_flags()
2336 ans = fn(*args)
2337 flags = [k for k, v in context.flags.items() if v]
2338
2339 for extra_flags in flagsets:
2340 # set flags, before calling operation
2341 context.clear_flags()
2342 for flag in extra_flags:
2343 context._raise_error(flag)
2344 new_ans = fn(*args)
2345
2346 # flags that we expect to be set after the operation
2347 expected_flags = list(flags)
2348 for flag in extra_flags:
2349 if flag not in expected_flags:
2350 expected_flags.append(flag)
2351 expected_flags.sort(key=id)
2352
2353 # flags we actually got
2354 new_flags = [k for k,v in context.flags.items() if v]
2355 new_flags.sort(key=id)
2356
2357 self.assertEqual(ans, new_ans,
2358 "operation produces different answers depending on flags set: " +
2359 "expected %s, got %s." % (ans, new_ans))
2360 self.assertEqual(new_flags, expected_flags,
2361 "operation raises different flags depending on flags set: " +
2362 "expected %s, got %s" % (expected_flags, new_flags))
2363
2364def test_main(arith=False, verbose=None, todo_tests=None, debug=None):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002365 """ Execute the tests.
2366
Raymond Hettingered20ad82004-09-04 20:09:13 +00002367 Runs all arithmetic tests if arith is True or if the "decimal" resource
2368 is enabled in regrtest.py
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002369 """
Raymond Hettingered20ad82004-09-04 20:09:13 +00002370
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002371 init()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002372 global TEST_ALL, DEBUG
Raymond Hettingered20ad82004-09-04 20:09:13 +00002373 TEST_ALL = arith or is_resource_enabled('decimal')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002374 DEBUG = debug
Raymond Hettingered20ad82004-09-04 20:09:13 +00002375
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002376 if todo_tests is None:
2377 test_classes = [
2378 DecimalExplicitConstructionTest,
2379 DecimalImplicitConstructionTest,
2380 DecimalArithmeticOperatorsTest,
Christian Heimesf16baeb2008-02-29 14:57:44 +00002381 DecimalFormatTest,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002382 DecimalUseOfContextTest,
2383 DecimalUsabilityTest,
2384 DecimalPythonAPItests,
2385 ContextAPItests,
2386 DecimalTest,
2387 WithStatementTest,
2388 ContextFlags
2389 ]
2390 else:
2391 test_classes = [DecimalTest]
2392
2393 # Dynamically build custom test definition for each file in the test
2394 # directory and add the definitions to the DecimalTest class. This
2395 # procedure insures that new files do not get skipped.
2396 for filename in os.listdir(directory):
2397 if '.decTest' not in filename or filename.startswith("."):
2398 continue
2399 head, tail = filename.split('.')
2400 if todo_tests is not None and head not in todo_tests:
2401 continue
2402 tester = lambda self, f=filename: self.eval_file(directory + f)
2403 setattr(DecimalTest, 'test_' + head, tester)
2404 del filename, head, tail, tester
2405
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002406
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002407 try:
2408 run_unittest(*test_classes)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002409 if todo_tests is None:
2410 import decimal as DecimalModule
2411 run_doctest(DecimalModule, verbose)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002412 finally:
2413 setcontext(ORIGINAL_CONTEXT)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002414
2415if __name__ == '__main__':
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002416 import optparse
2417 p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]")
2418 p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test')
2419 p.add_option('--skip', '-s', action='store_true', help='skip over 90% of the arithmetic tests')
2420 (opt, args) = p.parse_args()
2421
2422 if opt.skip:
2423 test_main(arith=False, verbose=True)
2424 elif args:
2425 test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002426 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002427 test_main(arith=True, verbose=True)