blob: 611ef55007336db1445fce948b255a5d18ea5bd5 [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'),
Christian Heimesf16baeb2008-02-29 14:57:44 +0000821 ]
822 for fmt, d, result in test_values:
823 self.assertEqual(format(Decimal(d), fmt), result)
824
Mark Dickinson79f52032009-03-17 23:12:51 +0000825 def test_n_format(self):
826 try:
827 from locale import CHAR_MAX
828 except ImportError:
829 return
830
831 # Set up some localeconv-like dictionaries
832 en_US = {
833 'decimal_point' : '.',
834 'grouping' : [3, 3, 0],
835 'thousands_sep': ','
836 }
837
838 fr_FR = {
839 'decimal_point' : ',',
840 'grouping' : [CHAR_MAX],
841 'thousands_sep' : ''
842 }
843
844 ru_RU = {
845 'decimal_point' : ',',
846 'grouping' : [3, 3, 0],
847 'thousands_sep' : ' '
848 }
849
850 crazy = {
851 'decimal_point' : '&',
852 'grouping' : [1, 4, 2, CHAR_MAX],
853 'thousands_sep' : '-'
854 }
855
856
857 def get_fmt(x, locale, fmt='n'):
858 return Decimal.__format__(Decimal(x), fmt, _localeconv=locale)
859
860 self.assertEqual(get_fmt(Decimal('12.7'), en_US), '12.7')
861 self.assertEqual(get_fmt(Decimal('12.7'), fr_FR), '12,7')
862 self.assertEqual(get_fmt(Decimal('12.7'), ru_RU), '12,7')
863 self.assertEqual(get_fmt(Decimal('12.7'), crazy), '1-2&7')
864
865 self.assertEqual(get_fmt(123456789, en_US), '123,456,789')
866 self.assertEqual(get_fmt(123456789, fr_FR), '123456789')
867 self.assertEqual(get_fmt(123456789, ru_RU), '123 456 789')
868 self.assertEqual(get_fmt(1234567890123, crazy), '123456-78-9012-3')
869
870 self.assertEqual(get_fmt(123456789, en_US, '.6n'), '1.23457e+8')
871 self.assertEqual(get_fmt(123456789, fr_FR, '.6n'), '1,23457e+8')
872 self.assertEqual(get_fmt(123456789, ru_RU, '.6n'), '1,23457e+8')
873 self.assertEqual(get_fmt(123456789, crazy, '.6n'), '1&23457e+8')
874
Mark Dickinson7303b592009-03-18 08:25:36 +0000875 # zero padding
876 self.assertEqual(get_fmt(1234, fr_FR, '03n'), '1234')
877 self.assertEqual(get_fmt(1234, fr_FR, '04n'), '1234')
878 self.assertEqual(get_fmt(1234, fr_FR, '05n'), '01234')
879 self.assertEqual(get_fmt(1234, fr_FR, '06n'), '001234')
880
881 self.assertEqual(get_fmt(12345, en_US, '05n'), '12,345')
882 self.assertEqual(get_fmt(12345, en_US, '06n'), '12,345')
883 self.assertEqual(get_fmt(12345, en_US, '07n'), '012,345')
884 self.assertEqual(get_fmt(12345, en_US, '08n'), '0,012,345')
885 self.assertEqual(get_fmt(12345, en_US, '09n'), '0,012,345')
886 self.assertEqual(get_fmt(12345, en_US, '010n'), '00,012,345')
887
888 self.assertEqual(get_fmt(123456, crazy, '06n'), '1-2345-6')
889 self.assertEqual(get_fmt(123456, crazy, '07n'), '1-2345-6')
890 self.assertEqual(get_fmt(123456, crazy, '08n'), '1-2345-6')
891 self.assertEqual(get_fmt(123456, crazy, '09n'), '01-2345-6')
892 self.assertEqual(get_fmt(123456, crazy, '010n'), '0-01-2345-6')
893 self.assertEqual(get_fmt(123456, crazy, '011n'), '0-01-2345-6')
894 self.assertEqual(get_fmt(123456, crazy, '012n'), '00-01-2345-6')
895 self.assertEqual(get_fmt(123456, crazy, '013n'), '000-01-2345-6')
896
Mark Dickinson79f52032009-03-17 23:12:51 +0000897
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000898class DecimalArithmeticOperatorsTest(unittest.TestCase):
899 '''Unit tests for all arithmetic operators, binary and unary.'''
900
901 def test_addition(self):
902
903 d1 = Decimal('-11.1')
904 d2 = Decimal('22.2')
905
906 #two Decimals
907 self.assertEqual(d1+d2, Decimal('11.1'))
908 self.assertEqual(d2+d1, Decimal('11.1'))
909
910 #with other type, left
911 c = d1 + 5
912 self.assertEqual(c, Decimal('-6.1'))
913 self.assertEqual(type(c), type(d1))
914
915 #with other type, right
916 c = 5 + d1
917 self.assertEqual(c, Decimal('-6.1'))
918 self.assertEqual(type(c), type(d1))
919
920 #inline with decimal
921 d1 += d2
922 self.assertEqual(d1, Decimal('11.1'))
923
924 #inline with other type
925 d1 += 5
926 self.assertEqual(d1, Decimal('16.1'))
927
928 def test_subtraction(self):
929
930 d1 = Decimal('-11.1')
931 d2 = Decimal('22.2')
932
933 #two Decimals
934 self.assertEqual(d1-d2, Decimal('-33.3'))
935 self.assertEqual(d2-d1, Decimal('33.3'))
936
937 #with other type, left
938 c = d1 - 5
939 self.assertEqual(c, Decimal('-16.1'))
940 self.assertEqual(type(c), type(d1))
941
942 #with other type, right
943 c = 5 - d1
944 self.assertEqual(c, Decimal('16.1'))
945 self.assertEqual(type(c), type(d1))
946
947 #inline with decimal
948 d1 -= d2
949 self.assertEqual(d1, Decimal('-33.3'))
950
951 #inline with other type
952 d1 -= 5
953 self.assertEqual(d1, Decimal('-38.3'))
954
955 def test_multiplication(self):
956
957 d1 = Decimal('-5')
958 d2 = Decimal('3')
959
960 #two Decimals
961 self.assertEqual(d1*d2, Decimal('-15'))
962 self.assertEqual(d2*d1, Decimal('-15'))
963
964 #with other type, left
965 c = d1 * 5
966 self.assertEqual(c, Decimal('-25'))
967 self.assertEqual(type(c), type(d1))
968
969 #with other type, right
970 c = 5 * d1
971 self.assertEqual(c, Decimal('-25'))
972 self.assertEqual(type(c), type(d1))
973
974 #inline with decimal
975 d1 *= d2
976 self.assertEqual(d1, Decimal('-15'))
977
978 #inline with other type
979 d1 *= 5
980 self.assertEqual(d1, Decimal('-75'))
981
982 def test_division(self):
983
984 d1 = Decimal('-5')
985 d2 = Decimal('2')
986
987 #two Decimals
988 self.assertEqual(d1/d2, Decimal('-2.5'))
989 self.assertEqual(d2/d1, Decimal('-0.4'))
990
991 #with other type, left
992 c = d1 / 4
993 self.assertEqual(c, Decimal('-1.25'))
994 self.assertEqual(type(c), type(d1))
995
996 #with other type, right
997 c = 4 / d1
998 self.assertEqual(c, Decimal('-0.8'))
999 self.assertEqual(type(c), type(d1))
1000
1001 #inline with decimal
1002 d1 /= d2
1003 self.assertEqual(d1, Decimal('-2.5'))
1004
1005 #inline with other type
1006 d1 /= 4
1007 self.assertEqual(d1, Decimal('-0.625'))
1008
1009 def test_floor_division(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001010
1011 d1 = Decimal('5')
1012 d2 = Decimal('2')
1013
1014 #two Decimals
1015 self.assertEqual(d1//d2, Decimal('2'))
1016 self.assertEqual(d2//d1, Decimal('0'))
1017
1018 #with other type, left
1019 c = d1 // 4
1020 self.assertEqual(c, Decimal('1'))
1021 self.assertEqual(type(c), type(d1))
1022
1023 #with other type, right
1024 c = 7 // d1
1025 self.assertEqual(c, Decimal('1'))
1026 self.assertEqual(type(c), type(d1))
1027
1028 #inline with decimal
1029 d1 //= d2
1030 self.assertEqual(d1, Decimal('2'))
1031
1032 #inline with other type
1033 d1 //= 2
1034 self.assertEqual(d1, Decimal('1'))
1035
1036 def test_powering(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001037
1038 d1 = Decimal('5')
1039 d2 = Decimal('2')
1040
1041 #two Decimals
1042 self.assertEqual(d1**d2, Decimal('25'))
1043 self.assertEqual(d2**d1, Decimal('32'))
1044
1045 #with other type, left
1046 c = d1 ** 4
1047 self.assertEqual(c, Decimal('625'))
1048 self.assertEqual(type(c), type(d1))
1049
1050 #with other type, right
1051 c = 7 ** d1
1052 self.assertEqual(c, Decimal('16807'))
1053 self.assertEqual(type(c), type(d1))
1054
1055 #inline with decimal
1056 d1 **= d2
1057 self.assertEqual(d1, Decimal('25'))
1058
1059 #inline with other type
1060 d1 **= 4
1061 self.assertEqual(d1, Decimal('390625'))
1062
1063 def test_module(self):
1064
1065 d1 = Decimal('5')
1066 d2 = Decimal('2')
1067
1068 #two Decimals
1069 self.assertEqual(d1%d2, Decimal('1'))
1070 self.assertEqual(d2%d1, Decimal('2'))
1071
1072 #with other type, left
1073 c = d1 % 4
1074 self.assertEqual(c, Decimal('1'))
1075 self.assertEqual(type(c), type(d1))
1076
1077 #with other type, right
1078 c = 7 % d1
1079 self.assertEqual(c, Decimal('2'))
1080 self.assertEqual(type(c), type(d1))
1081
1082 #inline with decimal
1083 d1 %= d2
1084 self.assertEqual(d1, Decimal('1'))
1085
1086 #inline with other type
1087 d1 %= 4
1088 self.assertEqual(d1, Decimal('1'))
1089
1090 def test_floor_div_module(self):
1091
1092 d1 = Decimal('5')
1093 d2 = Decimal('2')
1094
1095 #two Decimals
1096 (p, q) = divmod(d1, d2)
1097 self.assertEqual(p, Decimal('2'))
1098 self.assertEqual(q, Decimal('1'))
1099 self.assertEqual(type(p), type(d1))
1100 self.assertEqual(type(q), type(d1))
1101
1102 #with other type, left
1103 (p, q) = divmod(d1, 4)
1104 self.assertEqual(p, Decimal('1'))
1105 self.assertEqual(q, Decimal('1'))
1106 self.assertEqual(type(p), type(d1))
1107 self.assertEqual(type(q), type(d1))
1108
1109 #with other type, right
1110 (p, q) = divmod(7, d1)
1111 self.assertEqual(p, Decimal('1'))
1112 self.assertEqual(q, Decimal('2'))
1113 self.assertEqual(type(p), type(d1))
1114 self.assertEqual(type(q), type(d1))
1115
1116 def test_unary_operators(self):
1117 self.assertEqual(+Decimal(45), Decimal(+45)) # +
1118 self.assertEqual(-Decimal(45), Decimal(-45)) # -
1119 self.assertEqual(abs(Decimal(45)), abs(Decimal(-45))) # abs
1120
Christian Heimes77c02eb2008-02-09 02:18:51 +00001121 def test_nan_comparisons(self):
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001122 # comparisons involving signaling nans signal InvalidOperation
1123
1124 # order comparisons (<, <=, >, >=) involving only quiet nans
1125 # also signal InvalidOperation
1126
1127 # equality comparisons (==, !=) involving only quiet nans
1128 # don't signal, but return False or True respectively.
1129
Christian Heimes77c02eb2008-02-09 02:18:51 +00001130 n = Decimal('NaN')
1131 s = Decimal('sNaN')
1132 i = Decimal('Inf')
1133 f = Decimal('2')
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001134
1135 qnan_pairs = (n, n), (n, i), (i, n), (n, f), (f, n)
1136 snan_pairs = (s, n), (n, s), (s, i), (i, s), (s, f), (f, s), (s, s)
1137 order_ops = operator.lt, operator.le, operator.gt, operator.ge
1138 equality_ops = operator.eq, operator.ne
1139
1140 # results when InvalidOperation is not trapped
1141 for x, y in qnan_pairs + snan_pairs:
1142 for op in order_ops + equality_ops:
1143 got = op(x, y)
1144 expected = True if op is operator.ne else False
1145 self.assertIs(expected, got,
1146 "expected {0!r} for operator.{1}({2!r}, {3!r}); "
1147 "got {4!r}".format(
1148 expected, op.__name__, x, y, got))
1149
1150 # repeat the above, but this time trap the InvalidOperation
1151 with localcontext() as ctx:
1152 ctx.traps[InvalidOperation] = 1
1153
1154 for x, y in qnan_pairs:
1155 for op in equality_ops:
1156 got = op(x, y)
1157 expected = True if op is operator.ne else False
1158 self.assertIs(expected, got,
1159 "expected {0!r} for "
1160 "operator.{1}({2!r}, {3!r}); "
1161 "got {4!r}".format(
1162 expected, op.__name__, x, y, got))
1163
1164 for x, y in snan_pairs:
1165 for op in equality_ops:
1166 self.assertRaises(InvalidOperation, operator.eq, x, y)
1167 self.assertRaises(InvalidOperation, operator.ne, x, y)
1168
1169 for x, y in qnan_pairs + snan_pairs:
1170 for op in order_ops:
1171 self.assertRaises(InvalidOperation, op, x, y)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001172
Mark Dickinson84230a12010-02-18 14:49:50 +00001173 def test_copy_sign(self):
1174 d = Decimal(1).copy_sign(Decimal(-2))
1175
1176 self.assertEqual(Decimal(1).copy_sign(-2), d)
1177 self.assertRaises(TypeError, Decimal(1).copy_sign, '-2')
1178
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001179# The following are two functions used to test threading in the next class
1180
1181def thfunc1(cls):
1182 d1 = Decimal(1)
1183 d3 = Decimal(3)
Christian Heimesfe337bf2008-03-23 21:54:12 +00001184 test1 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001185 cls.synchro.wait()
Christian Heimesfe337bf2008-03-23 21:54:12 +00001186 test2 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001187 cls.finish1.set()
Christian Heimesfe337bf2008-03-23 21:54:12 +00001188
Christian Heimes81ee3ef2008-05-04 22:42:01 +00001189 cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
1190 cls.assertEqual(test2, Decimal('0.3333333333333333333333333333'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001191 return
1192
1193def thfunc2(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 thiscontext = getcontext()
1198 thiscontext.prec = 18
Christian Heimesfe337bf2008-03-23 21:54:12 +00001199 test2 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001200 cls.synchro.set()
1201 cls.finish2.set()
Christian Heimesfe337bf2008-03-23 21:54:12 +00001202
Christian Heimes81ee3ef2008-05-04 22:42:01 +00001203 cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
Christian Heimesfe337bf2008-03-23 21:54:12 +00001204 cls.assertEqual(test2, Decimal('0.333333333333333333'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001205 return
1206
1207
1208class DecimalUseOfContextTest(unittest.TestCase):
1209 '''Unit tests for Use of Context cases in Decimal.'''
1210
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001211 try:
1212 import threading
1213 except ImportError:
1214 threading = None
1215
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001216 # Take care executing this test from IDLE, there's an issue in threading
1217 # that hangs IDLE and I couldn't find it
1218
1219 def test_threading(self):
1220 #Test the "threading isolation" of a Context.
1221
1222 self.synchro = threading.Event()
1223 self.finish1 = threading.Event()
1224 self.finish2 = threading.Event()
1225
1226 th1 = threading.Thread(target=thfunc1, args=(self,))
1227 th2 = threading.Thread(target=thfunc2, args=(self,))
1228
1229 th1.start()
1230 th2.start()
1231
1232 self.finish1.wait()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001233 self.finish2.wait()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001234 return
1235
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001236 if threading is None:
1237 del test_threading
1238
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001239
1240class DecimalUsabilityTest(unittest.TestCase):
1241 '''Unit tests for Usability cases of Decimal.'''
1242
1243 def test_comparison_operators(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001244
1245 da = Decimal('23.42')
1246 db = Decimal('23.42')
1247 dc = Decimal('45')
1248
1249 #two Decimals
Ezio Melotti6607d512010-04-03 14:59:49 +00001250 self.assertGreater(dc, da)
1251 self.assertGreaterEqual(dc, da)
1252 self.assertLess(da, dc)
1253 self.assertLessEqual(da, dc)
Guido van Rossume61fd5b2007-07-11 12:20:59 +00001254 self.assertEqual(da, db)
Ezio Melotti6607d512010-04-03 14:59:49 +00001255 self.assertNotEqual(da, dc)
1256 self.assertLessEqual(da, db)
1257 self.assertGreaterEqual(da, db)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001258
1259 #a Decimal and an int
Ezio Melotti6607d512010-04-03 14:59:49 +00001260 self.assertGreater(dc, 23)
1261 self.assertLess(23, dc)
Guido van Rossume61fd5b2007-07-11 12:20:59 +00001262 self.assertEqual(dc, 45)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001263
1264 #a Decimal and uncomparable
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001265 self.assertNotEqual(da, 'ugly')
1266 self.assertNotEqual(da, 32.7)
1267 self.assertNotEqual(da, object())
1268 self.assertNotEqual(da, object)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001269
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001270 # sortable
Guido van Rossumc1f779c2007-07-03 08:25:58 +00001271 a = list(map(Decimal, range(100)))
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001272 b = a[:]
1273 random.shuffle(a)
1274 a.sort()
1275 self.assertEqual(a, b)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001276
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001277 def test_decimal_float_comparison(self):
1278 da = Decimal('0.25')
1279 db = Decimal('3.0')
Ezio Melotti6607d512010-04-03 14:59:49 +00001280 self.assertLess(da, 3.0)
1281 self.assertLessEqual(da, 3.0)
1282 self.assertGreater(db, 0.25)
1283 self.assertGreaterEqual(db, 0.25)
1284 self.assertNotEqual(da, 1.5)
1285 self.assertEqual(da, 0.25)
1286 self.assertGreater(3.0, da)
1287 self.assertGreaterEqual(3.0, da)
1288 self.assertLess(0.25, db)
1289 self.assertLessEqual(0.25, db)
1290 self.assertNotEqual(0.25, db)
1291 self.assertEqual(3.0, db)
1292 self.assertNotEqual(0.1, Decimal('0.1'))
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001293
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001294 def test_copy_and_deepcopy_methods(self):
1295 d = Decimal('43.24')
1296 c = copy.copy(d)
1297 self.assertEqual(id(c), id(d))
1298 dc = copy.deepcopy(d)
1299 self.assertEqual(id(dc), id(d))
1300
1301 def test_hash_method(self):
Stefan Krahdc817b22010-11-17 11:16:34 +00001302 def hashit(d):
1303 a = hash(d)
1304 b = d.__hash__()
1305 self.assertEqual(a, b)
1306 return a
1307
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001308 #just that it's hashable
Stefan Krahdc817b22010-11-17 11:16:34 +00001309 hashit(Decimal(23))
1310 hashit(Decimal('Infinity'))
1311 hashit(Decimal('-Infinity'))
1312 hashit(Decimal('nan123'))
1313 hashit(Decimal('-NaN'))
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001314
1315 test_values = [Decimal(sign*(2**m + n))
1316 for m in [0, 14, 15, 16, 17, 30, 31,
Stefan Krahdc817b22010-11-17 11:16:34 +00001317 32, 33, 61, 62, 63, 64, 65, 66]
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001318 for n in range(-10, 10)
1319 for sign in [-1, 1]]
1320 test_values.extend([
Stefan Krahdc817b22010-11-17 11:16:34 +00001321 Decimal("-1"), # ==> -2
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001322 Decimal("-0"), # zeros
1323 Decimal("0.00"),
1324 Decimal("-0.000"),
1325 Decimal("0E10"),
1326 Decimal("-0E12"),
1327 Decimal("10.0"), # negative exponent
1328 Decimal("-23.00000"),
1329 Decimal("1230E100"), # positive exponent
1330 Decimal("-4.5678E50"),
1331 # a value for which hash(n) != hash(n % (2**64-1))
1332 # in Python pre-2.6
1333 Decimal(2**64 + 2**32 - 1),
1334 # selection of values which fail with the old (before
1335 # version 2.6) long.__hash__
1336 Decimal("1.634E100"),
1337 Decimal("90.697E100"),
1338 Decimal("188.83E100"),
1339 Decimal("1652.9E100"),
1340 Decimal("56531E100"),
1341 ])
1342
1343 # check that hash(d) == hash(int(d)) for integral values
1344 for value in test_values:
Stefan Krahdc817b22010-11-17 11:16:34 +00001345 self.assertEqual(hashit(value), hashit(int(value)))
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001346
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001347 #the same hash that to an int
Stefan Krahdc817b22010-11-17 11:16:34 +00001348 self.assertEqual(hashit(Decimal(23)), hashit(23))
Raymond Hettingerd325c4b2010-11-21 04:08:28 +00001349 self.assertRaises(TypeError, hash, Decimal('sNaN'))
Stefan Krahdc817b22010-11-17 11:16:34 +00001350 self.assertTrue(hashit(Decimal('Inf')))
1351 self.assertTrue(hashit(Decimal('-Inf')))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001352
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001353 # check that the hashes of a Decimal float match when they
1354 # represent exactly the same values
1355 test_strings = ['inf', '-Inf', '0.0', '-.0e1',
1356 '34.0', '2.5', '112390.625', '-0.515625']
1357 for s in test_strings:
1358 f = float(s)
1359 d = Decimal(s)
Stefan Krahdc817b22010-11-17 11:16:34 +00001360 self.assertEqual(hashit(f), hashit(d))
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001361
Christian Heimes2380ac72008-01-09 00:17:24 +00001362 # check that the value of the hash doesn't depend on the
1363 # current context (issue #1757)
1364 c = getcontext()
1365 old_precision = c.prec
1366 x = Decimal("123456789.1")
1367
1368 c.prec = 6
Stefan Krahdc817b22010-11-17 11:16:34 +00001369 h1 = hashit(x)
Christian Heimes2380ac72008-01-09 00:17:24 +00001370 c.prec = 10
Stefan Krahdc817b22010-11-17 11:16:34 +00001371 h2 = hashit(x)
Christian Heimes2380ac72008-01-09 00:17:24 +00001372 c.prec = 16
Stefan Krahdc817b22010-11-17 11:16:34 +00001373 h3 = hashit(x)
Christian Heimes2380ac72008-01-09 00:17:24 +00001374
1375 self.assertEqual(h1, h2)
1376 self.assertEqual(h1, h3)
1377 c.prec = old_precision
1378
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001379 def test_min_and_max_methods(self):
1380
1381 d1 = Decimal('15.32')
1382 d2 = Decimal('28.5')
1383 l1 = 15
1384 l2 = 28
1385
1386 #between Decimals
Ezio Melotti6607d512010-04-03 14:59:49 +00001387 self.assertIs(min(d1,d2), d1)
1388 self.assertIs(min(d2,d1), d1)
1389 self.assertIs(max(d1,d2), d2)
1390 self.assertIs(max(d2,d1), d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001391
1392 #between Decimal and long
Ezio Melotti6607d512010-04-03 14:59:49 +00001393 self.assertIs(min(d1,l2), d1)
1394 self.assertIs(min(l2,d1), d1)
1395 self.assertIs(max(l1,d2), d2)
1396 self.assertIs(max(d2,l1), d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001397
1398 def test_as_nonzero(self):
1399 #as false
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001400 self.assertFalse(Decimal(0))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001401 #as true
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001402 self.assertTrue(Decimal('0.372'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001403
1404 def test_tostring_methods(self):
1405 #Test str and repr methods.
1406
1407 d = Decimal('15.32')
1408 self.assertEqual(str(d), '15.32') # str
Christian Heimes68f5fbe2008-02-14 08:27:37 +00001409 self.assertEqual(repr(d), "Decimal('15.32')") # repr
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001410
1411 def test_tonum_methods(self):
Mark Dickinson5c2db372009-12-05 20:28:34 +00001412 #Test float and int methods.
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001413
1414 d1 = Decimal('66')
1415 d2 = Decimal('15.32')
1416
1417 #int
1418 self.assertEqual(int(d1), 66)
1419 self.assertEqual(int(d2), 15)
1420
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001421 #float
1422 self.assertEqual(float(d1), 66)
1423 self.assertEqual(float(d2), 15.32)
1424
Mark Dickinsonb27406c2008-05-09 13:42:33 +00001425 #floor
1426 test_pairs = [
1427 ('123.00', 123),
1428 ('3.2', 3),
1429 ('3.54', 3),
1430 ('3.899', 3),
1431 ('-2.3', -3),
1432 ('-11.0', -11),
1433 ('0.0', 0),
1434 ('-0E3', 0),
1435 ]
1436 for d, i in test_pairs:
1437 self.assertEqual(math.floor(Decimal(d)), i)
1438 self.assertRaises(ValueError, math.floor, Decimal('-NaN'))
1439 self.assertRaises(ValueError, math.floor, Decimal('sNaN'))
1440 self.assertRaises(ValueError, math.floor, Decimal('NaN123'))
1441 self.assertRaises(OverflowError, math.floor, Decimal('Inf'))
1442 self.assertRaises(OverflowError, math.floor, Decimal('-Inf'))
1443
1444 #ceiling
1445 test_pairs = [
1446 ('123.00', 123),
1447 ('3.2', 4),
1448 ('3.54', 4),
1449 ('3.899', 4),
1450 ('-2.3', -2),
1451 ('-11.0', -11),
1452 ('0.0', 0),
1453 ('-0E3', 0),
1454 ]
1455 for d, i in test_pairs:
1456 self.assertEqual(math.ceil(Decimal(d)), i)
1457 self.assertRaises(ValueError, math.ceil, Decimal('-NaN'))
1458 self.assertRaises(ValueError, math.ceil, Decimal('sNaN'))
1459 self.assertRaises(ValueError, math.ceil, Decimal('NaN123'))
1460 self.assertRaises(OverflowError, math.ceil, Decimal('Inf'))
1461 self.assertRaises(OverflowError, math.ceil, Decimal('-Inf'))
1462
1463 #round, single argument
1464 test_pairs = [
1465 ('123.00', 123),
1466 ('3.2', 3),
1467 ('3.54', 4),
1468 ('3.899', 4),
1469 ('-2.3', -2),
1470 ('-11.0', -11),
1471 ('0.0', 0),
1472 ('-0E3', 0),
1473 ('-3.5', -4),
1474 ('-2.5', -2),
1475 ('-1.5', -2),
1476 ('-0.5', 0),
1477 ('0.5', 0),
1478 ('1.5', 2),
1479 ('2.5', 2),
1480 ('3.5', 4),
1481 ]
1482 for d, i in test_pairs:
1483 self.assertEqual(round(Decimal(d)), i)
1484 self.assertRaises(ValueError, round, Decimal('-NaN'))
1485 self.assertRaises(ValueError, round, Decimal('sNaN'))
1486 self.assertRaises(ValueError, round, Decimal('NaN123'))
1487 self.assertRaises(OverflowError, round, Decimal('Inf'))
1488 self.assertRaises(OverflowError, round, Decimal('-Inf'))
1489
1490 #round, two arguments; this is essentially equivalent
1491 #to quantize, which is already extensively tested
1492 test_triples = [
1493 ('123.456', -4, '0E+4'),
1494 ('123.456', -3, '0E+3'),
1495 ('123.456', -2, '1E+2'),
1496 ('123.456', -1, '1.2E+2'),
1497 ('123.456', 0, '123'),
1498 ('123.456', 1, '123.5'),
1499 ('123.456', 2, '123.46'),
1500 ('123.456', 3, '123.456'),
1501 ('123.456', 4, '123.4560'),
1502 ('123.455', 2, '123.46'),
1503 ('123.445', 2, '123.44'),
1504 ('Inf', 4, 'NaN'),
1505 ('-Inf', -23, 'NaN'),
1506 ('sNaN314', 3, 'NaN314'),
1507 ]
1508 for d, n, r in test_triples:
1509 self.assertEqual(str(round(Decimal(d), n)), r)
1510
1511
1512
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001513 def test_eval_round_trip(self):
1514
1515 #with zero
1516 d = Decimal( (0, (0,), 0) )
1517 self.assertEqual(d, eval(repr(d)))
1518
1519 #int
1520 d = Decimal( (1, (4, 5), 0) )
1521 self.assertEqual(d, eval(repr(d)))
1522
1523 #float
1524 d = Decimal( (0, (4, 5, 3, 4), -2) )
1525 self.assertEqual(d, eval(repr(d)))
1526
1527 #weird
1528 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1529 self.assertEqual(d, eval(repr(d)))
1530
1531 def test_as_tuple(self):
1532
1533 #with zero
1534 d = Decimal(0)
1535 self.assertEqual(d.as_tuple(), (0, (0,), 0) )
1536
1537 #int
1538 d = Decimal(-45)
1539 self.assertEqual(d.as_tuple(), (1, (4, 5), 0) )
1540
1541 #complicated string
1542 d = Decimal("-4.34913534E-17")
1543 self.assertEqual(d.as_tuple(), (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1544
1545 #inf
1546 d = Decimal("Infinity")
1547 self.assertEqual(d.as_tuple(), (0, (0,), 'F') )
1548
Guido van Rossum8ce8a782007-11-01 19:42:39 +00001549 #leading zeros in coefficient should be stripped
1550 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), -2) )
1551 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), -2) )
1552 d = Decimal( (1, (0, 0, 0), 37) )
1553 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1554 d = Decimal( (1, (), 37) )
1555 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1556
1557 #leading zeros in NaN diagnostic info should be stripped
1558 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), 'n') )
1559 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), 'n') )
1560 d = Decimal( (1, (0, 0, 0), 'N') )
1561 self.assertEqual(d.as_tuple(), (1, (), 'N') )
1562 d = Decimal( (1, (), 'n') )
1563 self.assertEqual(d.as_tuple(), (1, (), 'n') )
1564
1565 #coefficient in infinity should be ignored
1566 d = Decimal( (0, (4, 5, 3, 4), 'F') )
1567 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
1568 d = Decimal( (1, (0, 2, 7, 1), 'F') )
1569 self.assertEqual(d.as_tuple(), (1, (0,), 'F'))
1570
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001571 def test_immutability_operations(self):
1572 # Do operations and check that it didn't change change internal objects.
1573
1574 d1 = Decimal('-25e55')
1575 b1 = Decimal('-25e55')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001576 d2 = Decimal('33e+33')
1577 b2 = Decimal('33e+33')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001578
1579 def checkSameDec(operation, useOther=False):
1580 if useOther:
1581 eval("d1." + operation + "(d2)")
1582 self.assertEqual(d1._sign, b1._sign)
1583 self.assertEqual(d1._int, b1._int)
1584 self.assertEqual(d1._exp, b1._exp)
1585 self.assertEqual(d2._sign, b2._sign)
1586 self.assertEqual(d2._int, b2._int)
1587 self.assertEqual(d2._exp, b2._exp)
1588 else:
1589 eval("d1." + operation + "()")
1590 self.assertEqual(d1._sign, b1._sign)
1591 self.assertEqual(d1._int, b1._int)
1592 self.assertEqual(d1._exp, b1._exp)
1593 return
1594
1595 Decimal(d1)
1596 self.assertEqual(d1._sign, b1._sign)
1597 self.assertEqual(d1._int, b1._int)
1598 self.assertEqual(d1._exp, b1._exp)
1599
1600 checkSameDec("__abs__")
1601 checkSameDec("__add__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001602 checkSameDec("__divmod__", True)
Christian Heimes77c02eb2008-02-09 02:18:51 +00001603 checkSameDec("__eq__", True)
1604 checkSameDec("__ne__", True)
1605 checkSameDec("__le__", True)
1606 checkSameDec("__lt__", True)
1607 checkSameDec("__ge__", True)
1608 checkSameDec("__gt__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001609 checkSameDec("__float__")
1610 checkSameDec("__floordiv__", True)
1611 checkSameDec("__hash__")
1612 checkSameDec("__int__")
Christian Heimes969fe572008-01-25 11:23:10 +00001613 checkSameDec("__trunc__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001614 checkSameDec("__mod__", True)
1615 checkSameDec("__mul__", True)
1616 checkSameDec("__neg__")
Jack Diederich4dafcc42006-11-28 19:15:13 +00001617 checkSameDec("__bool__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001618 checkSameDec("__pos__")
1619 checkSameDec("__pow__", True)
1620 checkSameDec("__radd__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001621 checkSameDec("__rdivmod__", True)
1622 checkSameDec("__repr__")
1623 checkSameDec("__rfloordiv__", True)
1624 checkSameDec("__rmod__", True)
1625 checkSameDec("__rmul__", True)
1626 checkSameDec("__rpow__", True)
1627 checkSameDec("__rsub__", True)
1628 checkSameDec("__str__")
1629 checkSameDec("__sub__", True)
1630 checkSameDec("__truediv__", True)
1631 checkSameDec("adjusted")
1632 checkSameDec("as_tuple")
1633 checkSameDec("compare", True)
1634 checkSameDec("max", True)
1635 checkSameDec("min", True)
1636 checkSameDec("normalize")
1637 checkSameDec("quantize", True)
1638 checkSameDec("remainder_near", True)
1639 checkSameDec("same_quantum", True)
1640 checkSameDec("sqrt")
1641 checkSameDec("to_eng_string")
1642 checkSameDec("to_integral")
1643
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001644 def test_subclassing(self):
1645 # Different behaviours when subclassing Decimal
1646
1647 class MyDecimal(Decimal):
1648 pass
1649
1650 d1 = MyDecimal(1)
1651 d2 = MyDecimal(2)
1652 d = d1 + d2
Ezio Melotti6607d512010-04-03 14:59:49 +00001653 self.assertIs(type(d), Decimal)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001654
1655 d = d1.max(d2)
Ezio Melotti6607d512010-04-03 14:59:49 +00001656 self.assertIs(type(d), Decimal)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001657
Christian Heimes0348fb62008-03-26 12:55:56 +00001658 def test_implicit_context(self):
1659 # Check results when context given implicitly. (Issue 2478)
1660 c = getcontext()
1661 self.assertEqual(str(Decimal(0).sqrt()),
1662 str(c.sqrt(Decimal(0))))
1663
Mark Dickinsona2d1fe02009-10-29 12:23:02 +00001664 def test_conversions_from_int(self):
1665 # Check that methods taking a second Decimal argument will
1666 # always accept an integer in place of a Decimal.
1667 self.assertEqual(Decimal(4).compare(3),
1668 Decimal(4).compare(Decimal(3)))
1669 self.assertEqual(Decimal(4).compare_signal(3),
1670 Decimal(4).compare_signal(Decimal(3)))
1671 self.assertEqual(Decimal(4).compare_total(3),
1672 Decimal(4).compare_total(Decimal(3)))
1673 self.assertEqual(Decimal(4).compare_total_mag(3),
1674 Decimal(4).compare_total_mag(Decimal(3)))
1675 self.assertEqual(Decimal(10101).logical_and(1001),
1676 Decimal(10101).logical_and(Decimal(1001)))
1677 self.assertEqual(Decimal(10101).logical_or(1001),
1678 Decimal(10101).logical_or(Decimal(1001)))
1679 self.assertEqual(Decimal(10101).logical_xor(1001),
1680 Decimal(10101).logical_xor(Decimal(1001)))
1681 self.assertEqual(Decimal(567).max(123),
1682 Decimal(567).max(Decimal(123)))
1683 self.assertEqual(Decimal(567).max_mag(123),
1684 Decimal(567).max_mag(Decimal(123)))
1685 self.assertEqual(Decimal(567).min(123),
1686 Decimal(567).min(Decimal(123)))
1687 self.assertEqual(Decimal(567).min_mag(123),
1688 Decimal(567).min_mag(Decimal(123)))
1689 self.assertEqual(Decimal(567).next_toward(123),
1690 Decimal(567).next_toward(Decimal(123)))
1691 self.assertEqual(Decimal(1234).quantize(100),
1692 Decimal(1234).quantize(Decimal(100)))
1693 self.assertEqual(Decimal(768).remainder_near(1234),
1694 Decimal(768).remainder_near(Decimal(1234)))
1695 self.assertEqual(Decimal(123).rotate(1),
1696 Decimal(123).rotate(Decimal(1)))
1697 self.assertEqual(Decimal(1234).same_quantum(1000),
1698 Decimal(1234).same_quantum(Decimal(1000)))
1699 self.assertEqual(Decimal('9.123').scaleb(-100),
1700 Decimal('9.123').scaleb(Decimal(-100)))
1701 self.assertEqual(Decimal(456).shift(-1),
1702 Decimal(456).shift(Decimal(-1)))
1703
1704 self.assertEqual(Decimal(-12).fma(Decimal(45), 67),
1705 Decimal(-12).fma(Decimal(45), Decimal(67)))
1706 self.assertEqual(Decimal(-12).fma(45, 67),
1707 Decimal(-12).fma(Decimal(45), Decimal(67)))
1708 self.assertEqual(Decimal(-12).fma(45, Decimal(67)),
1709 Decimal(-12).fma(Decimal(45), Decimal(67)))
1710
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001711
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001712class DecimalPythonAPItests(unittest.TestCase):
1713
Raymond Hettinger82417ca2009-02-03 03:54:28 +00001714 def test_abc(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001715 self.assertTrue(issubclass(Decimal, numbers.Number))
Ezio Melotti6607d512010-04-03 14:59:49 +00001716 self.assertFalse(issubclass(Decimal, numbers.Real))
Ezio Melottie9615932010-01-24 19:26:24 +00001717 self.assertIsInstance(Decimal(0), numbers.Number)
1718 self.assertNotIsInstance(Decimal(0), numbers.Real)
Raymond Hettinger82417ca2009-02-03 03:54:28 +00001719
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001720 def test_pickle(self):
1721 d = Decimal('-3.141590000')
1722 p = pickle.dumps(d)
1723 e = pickle.loads(p)
1724 self.assertEqual(d, e)
1725
Raymond Hettinger5548be22004-07-05 18:49:38 +00001726 def test_int(self):
Raymond Hettinger605ed022004-11-24 07:28:48 +00001727 for x in range(-250, 250):
1728 s = '%0.2f' % (x / 100.0)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001729 # should work the same as for floats
1730 self.assertEqual(int(Decimal(s)), int(float(s)))
Raymond Hettinger605ed022004-11-24 07:28:48 +00001731 # should work the same as to_integral in the ROUND_DOWN mode
Raymond Hettinger5548be22004-07-05 18:49:38 +00001732 d = Decimal(s)
Raymond Hettinger605ed022004-11-24 07:28:48 +00001733 r = d.to_integral(ROUND_DOWN)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001734 self.assertEqual(Decimal(int(d)), r)
1735
Mark Dickinson825fce32009-09-07 18:08:12 +00001736 self.assertRaises(ValueError, int, Decimal('-nan'))
1737 self.assertRaises(ValueError, int, Decimal('snan'))
1738 self.assertRaises(OverflowError, int, Decimal('inf'))
1739 self.assertRaises(OverflowError, int, Decimal('-inf'))
1740
Christian Heimes969fe572008-01-25 11:23:10 +00001741 def test_trunc(self):
1742 for x in range(-250, 250):
1743 s = '%0.2f' % (x / 100.0)
1744 # should work the same as for floats
1745 self.assertEqual(int(Decimal(s)), int(float(s)))
1746 # should work the same as to_integral in the ROUND_DOWN mode
1747 d = Decimal(s)
1748 r = d.to_integral(ROUND_DOWN)
Christian Heimes400adb02008-02-01 08:12:03 +00001749 self.assertEqual(Decimal(math.trunc(d)), r)
Christian Heimes969fe572008-01-25 11:23:10 +00001750
Raymond Hettinger771ed762009-01-03 19:20:32 +00001751 def test_from_float(self):
1752
1753 class MyDecimal(Decimal):
1754 pass
1755
1756 r = MyDecimal.from_float(0.1)
1757 self.assertEqual(type(r), MyDecimal)
1758 self.assertEqual(str(r),
1759 '0.1000000000000000055511151231257827021181583404541015625')
1760 bigint = 12345678901234567890123456789
1761 self.assertEqual(MyDecimal.from_float(bigint), MyDecimal(bigint))
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001762 self.assertTrue(MyDecimal.from_float(float('nan')).is_qnan())
1763 self.assertTrue(MyDecimal.from_float(float('inf')).is_infinite())
1764 self.assertTrue(MyDecimal.from_float(float('-inf')).is_infinite())
Raymond Hettinger771ed762009-01-03 19:20:32 +00001765 self.assertEqual(str(MyDecimal.from_float(float('nan'))),
1766 str(Decimal('NaN')))
1767 self.assertEqual(str(MyDecimal.from_float(float('inf'))),
1768 str(Decimal('Infinity')))
1769 self.assertEqual(str(MyDecimal.from_float(float('-inf'))),
1770 str(Decimal('-Infinity')))
1771 self.assertRaises(TypeError, MyDecimal.from_float, 'abc')
1772 for i in range(200):
1773 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
1774 self.assertEqual(x, float(MyDecimal.from_float(x))) # roundtrip
1775
1776 def test_create_decimal_from_float(self):
1777 context = Context(prec=5, rounding=ROUND_DOWN)
1778 self.assertEqual(
1779 context.create_decimal_from_float(math.pi),
1780 Decimal('3.1415')
1781 )
1782 context = Context(prec=5, rounding=ROUND_UP)
1783 self.assertEqual(
1784 context.create_decimal_from_float(math.pi),
1785 Decimal('3.1416')
1786 )
1787 context = Context(prec=5, traps=[Inexact])
1788 self.assertRaises(
1789 Inexact,
1790 context.create_decimal_from_float,
1791 math.pi
1792 )
1793 self.assertEqual(repr(context.create_decimal_from_float(-0.0)),
1794 "Decimal('-0')")
1795 self.assertEqual(repr(context.create_decimal_from_float(1.0)),
1796 "Decimal('1')")
1797 self.assertEqual(repr(context.create_decimal_from_float(10)),
1798 "Decimal('10')")
1799
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00001800class ContextAPItests(unittest.TestCase):
1801
1802 def test_pickle(self):
1803 c = Context()
1804 e = pickle.loads(pickle.dumps(c))
1805 for k in vars(c):
1806 v1 = vars(c)[k]
1807 v2 = vars(e)[k]
1808 self.assertEqual(v1, v2)
1809
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001810 def test_equality_with_other_types(self):
Benjamin Peterson577473f2010-01-19 00:09:57 +00001811 self.assertIn(Decimal(10), ['a', 1.0, Decimal(10), (1,2), {}])
1812 self.assertNotIn(Decimal(10), ['a', 1.0, (1,2), {}])
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001813
Raymond Hettinger955d2b22004-08-08 20:17:45 +00001814 def test_copy(self):
1815 # All copies should be deep
1816 c = Context()
1817 d = c.copy()
1818 self.assertNotEqual(id(c), id(d))
1819 self.assertNotEqual(id(c.flags), id(d.flags))
1820 self.assertNotEqual(id(c.traps), id(d.traps))
1821
Mark Dickinsonb1d8e322010-05-22 18:35:36 +00001822 def test__clamp(self):
1823 # In Python 3.2, the private attribute `_clamp` was made
1824 # public (issue 8540), with the old `_clamp` becoming a
1825 # property wrapping `clamp`. For the duration of Python 3.2
1826 # only, the attribute should be gettable/settable via both
1827 # `clamp` and `_clamp`; in Python 3.3, `_clamp` should be
1828 # removed.
1829 c = Context(clamp = 0)
1830 self.assertEqual(c.clamp, 0)
1831
1832 with check_warnings(("", DeprecationWarning)):
1833 c._clamp = 1
1834 self.assertEqual(c.clamp, 1)
1835 with check_warnings(("", DeprecationWarning)):
1836 self.assertEqual(c._clamp, 1)
1837 c.clamp = 0
1838 self.assertEqual(c.clamp, 0)
1839 with check_warnings(("", DeprecationWarning)):
1840 self.assertEqual(c._clamp, 0)
1841
Mark Dickinson84230a12010-02-18 14:49:50 +00001842 def test_abs(self):
1843 c = Context()
1844 d = c.abs(Decimal(-1))
1845 self.assertEqual(c.abs(-1), d)
1846 self.assertRaises(TypeError, c.abs, '-1')
1847
1848 def test_add(self):
1849 c = Context()
1850 d = c.add(Decimal(1), Decimal(1))
1851 self.assertEqual(c.add(1, 1), d)
1852 self.assertEqual(c.add(Decimal(1), 1), d)
1853 self.assertEqual(c.add(1, Decimal(1)), d)
1854 self.assertRaises(TypeError, c.add, '1', 1)
1855 self.assertRaises(TypeError, c.add, 1, '1')
1856
1857 def test_compare(self):
1858 c = Context()
1859 d = c.compare(Decimal(1), Decimal(1))
1860 self.assertEqual(c.compare(1, 1), d)
1861 self.assertEqual(c.compare(Decimal(1), 1), d)
1862 self.assertEqual(c.compare(1, Decimal(1)), d)
1863 self.assertRaises(TypeError, c.compare, '1', 1)
1864 self.assertRaises(TypeError, c.compare, 1, '1')
1865
1866 def test_compare_signal(self):
1867 c = Context()
1868 d = c.compare_signal(Decimal(1), Decimal(1))
1869 self.assertEqual(c.compare_signal(1, 1), d)
1870 self.assertEqual(c.compare_signal(Decimal(1), 1), d)
1871 self.assertEqual(c.compare_signal(1, Decimal(1)), d)
1872 self.assertRaises(TypeError, c.compare_signal, '1', 1)
1873 self.assertRaises(TypeError, c.compare_signal, 1, '1')
1874
1875 def test_compare_total(self):
1876 c = Context()
1877 d = c.compare_total(Decimal(1), Decimal(1))
1878 self.assertEqual(c.compare_total(1, 1), d)
1879 self.assertEqual(c.compare_total(Decimal(1), 1), d)
1880 self.assertEqual(c.compare_total(1, Decimal(1)), d)
1881 self.assertRaises(TypeError, c.compare_total, '1', 1)
1882 self.assertRaises(TypeError, c.compare_total, 1, '1')
1883
1884 def test_compare_total_mag(self):
1885 c = Context()
1886 d = c.compare_total_mag(Decimal(1), Decimal(1))
1887 self.assertEqual(c.compare_total_mag(1, 1), d)
1888 self.assertEqual(c.compare_total_mag(Decimal(1), 1), d)
1889 self.assertEqual(c.compare_total_mag(1, Decimal(1)), d)
1890 self.assertRaises(TypeError, c.compare_total_mag, '1', 1)
1891 self.assertRaises(TypeError, c.compare_total_mag, 1, '1')
1892
1893 def test_copy_abs(self):
1894 c = Context()
1895 d = c.copy_abs(Decimal(-1))
1896 self.assertEqual(c.copy_abs(-1), d)
1897 self.assertRaises(TypeError, c.copy_abs, '-1')
1898
1899 def test_copy_decimal(self):
1900 c = Context()
1901 d = c.copy_decimal(Decimal(-1))
1902 self.assertEqual(c.copy_decimal(-1), d)
1903 self.assertRaises(TypeError, c.copy_decimal, '-1')
1904
1905 def test_copy_negate(self):
1906 c = Context()
1907 d = c.copy_negate(Decimal(-1))
1908 self.assertEqual(c.copy_negate(-1), d)
1909 self.assertRaises(TypeError, c.copy_negate, '-1')
1910
1911 def test_copy_sign(self):
1912 c = Context()
1913 d = c.copy_sign(Decimal(1), Decimal(-2))
1914 self.assertEqual(c.copy_sign(1, -2), d)
1915 self.assertEqual(c.copy_sign(Decimal(1), -2), d)
1916 self.assertEqual(c.copy_sign(1, Decimal(-2)), d)
1917 self.assertRaises(TypeError, c.copy_sign, '1', -2)
1918 self.assertRaises(TypeError, c.copy_sign, 1, '-2')
1919
1920 def test_divide(self):
1921 c = Context()
1922 d = c.divide(Decimal(1), Decimal(2))
1923 self.assertEqual(c.divide(1, 2), d)
1924 self.assertEqual(c.divide(Decimal(1), 2), d)
1925 self.assertEqual(c.divide(1, Decimal(2)), d)
1926 self.assertRaises(TypeError, c.divide, '1', 2)
1927 self.assertRaises(TypeError, c.divide, 1, '2')
1928
1929 def test_divide_int(self):
1930 c = Context()
1931 d = c.divide_int(Decimal(1), Decimal(2))
1932 self.assertEqual(c.divide_int(1, 2), d)
1933 self.assertEqual(c.divide_int(Decimal(1), 2), d)
1934 self.assertEqual(c.divide_int(1, Decimal(2)), d)
1935 self.assertRaises(TypeError, c.divide_int, '1', 2)
1936 self.assertRaises(TypeError, c.divide_int, 1, '2')
1937
1938 def test_divmod(self):
1939 c = Context()
1940 d = c.divmod(Decimal(1), Decimal(2))
1941 self.assertEqual(c.divmod(1, 2), d)
1942 self.assertEqual(c.divmod(Decimal(1), 2), d)
1943 self.assertEqual(c.divmod(1, Decimal(2)), d)
1944 self.assertRaises(TypeError, c.divmod, '1', 2)
1945 self.assertRaises(TypeError, c.divmod, 1, '2')
1946
1947 def test_exp(self):
1948 c = Context()
1949 d = c.exp(Decimal(10))
1950 self.assertEqual(c.exp(10), d)
1951 self.assertRaises(TypeError, c.exp, '10')
1952
1953 def test_fma(self):
1954 c = Context()
1955 d = c.fma(Decimal(2), Decimal(3), Decimal(4))
1956 self.assertEqual(c.fma(2, 3, 4), d)
1957 self.assertEqual(c.fma(Decimal(2), 3, 4), d)
1958 self.assertEqual(c.fma(2, Decimal(3), 4), d)
1959 self.assertEqual(c.fma(2, 3, Decimal(4)), d)
1960 self.assertEqual(c.fma(Decimal(2), Decimal(3), 4), d)
1961 self.assertRaises(TypeError, c.fma, '2', 3, 4)
1962 self.assertRaises(TypeError, c.fma, 2, '3', 4)
1963 self.assertRaises(TypeError, c.fma, 2, 3, '4')
1964
1965 def test_is_finite(self):
1966 c = Context()
1967 d = c.is_finite(Decimal(10))
1968 self.assertEqual(c.is_finite(10), d)
1969 self.assertRaises(TypeError, c.is_finite, '10')
1970
1971 def test_is_infinite(self):
1972 c = Context()
1973 d = c.is_infinite(Decimal(10))
1974 self.assertEqual(c.is_infinite(10), d)
1975 self.assertRaises(TypeError, c.is_infinite, '10')
1976
1977 def test_is_nan(self):
1978 c = Context()
1979 d = c.is_nan(Decimal(10))
1980 self.assertEqual(c.is_nan(10), d)
1981 self.assertRaises(TypeError, c.is_nan, '10')
1982
1983 def test_is_normal(self):
1984 c = Context()
1985 d = c.is_normal(Decimal(10))
1986 self.assertEqual(c.is_normal(10), d)
1987 self.assertRaises(TypeError, c.is_normal, '10')
1988
1989 def test_is_qnan(self):
1990 c = Context()
1991 d = c.is_qnan(Decimal(10))
1992 self.assertEqual(c.is_qnan(10), d)
1993 self.assertRaises(TypeError, c.is_qnan, '10')
1994
1995 def test_is_signed(self):
1996 c = Context()
1997 d = c.is_signed(Decimal(10))
1998 self.assertEqual(c.is_signed(10), d)
1999 self.assertRaises(TypeError, c.is_signed, '10')
2000
2001 def test_is_snan(self):
2002 c = Context()
2003 d = c.is_snan(Decimal(10))
2004 self.assertEqual(c.is_snan(10), d)
2005 self.assertRaises(TypeError, c.is_snan, '10')
2006
2007 def test_is_subnormal(self):
2008 c = Context()
2009 d = c.is_subnormal(Decimal(10))
2010 self.assertEqual(c.is_subnormal(10), d)
2011 self.assertRaises(TypeError, c.is_subnormal, '10')
2012
2013 def test_is_zero(self):
2014 c = Context()
2015 d = c.is_zero(Decimal(10))
2016 self.assertEqual(c.is_zero(10), d)
2017 self.assertRaises(TypeError, c.is_zero, '10')
2018
2019 def test_ln(self):
2020 c = Context()
2021 d = c.ln(Decimal(10))
2022 self.assertEqual(c.ln(10), d)
2023 self.assertRaises(TypeError, c.ln, '10')
2024
2025 def test_log10(self):
2026 c = Context()
2027 d = c.log10(Decimal(10))
2028 self.assertEqual(c.log10(10), d)
2029 self.assertRaises(TypeError, c.log10, '10')
2030
2031 def test_logb(self):
2032 c = Context()
2033 d = c.logb(Decimal(10))
2034 self.assertEqual(c.logb(10), d)
2035 self.assertRaises(TypeError, c.logb, '10')
2036
2037 def test_logical_and(self):
2038 c = Context()
2039 d = c.logical_and(Decimal(1), Decimal(1))
2040 self.assertEqual(c.logical_and(1, 1), d)
2041 self.assertEqual(c.logical_and(Decimal(1), 1), d)
2042 self.assertEqual(c.logical_and(1, Decimal(1)), d)
2043 self.assertRaises(TypeError, c.logical_and, '1', 1)
2044 self.assertRaises(TypeError, c.logical_and, 1, '1')
2045
2046 def test_logical_invert(self):
2047 c = Context()
2048 d = c.logical_invert(Decimal(1000))
2049 self.assertEqual(c.logical_invert(1000), d)
2050 self.assertRaises(TypeError, c.logical_invert, '1000')
2051
2052 def test_logical_or(self):
2053 c = Context()
2054 d = c.logical_or(Decimal(1), Decimal(1))
2055 self.assertEqual(c.logical_or(1, 1), d)
2056 self.assertEqual(c.logical_or(Decimal(1), 1), d)
2057 self.assertEqual(c.logical_or(1, Decimal(1)), d)
2058 self.assertRaises(TypeError, c.logical_or, '1', 1)
2059 self.assertRaises(TypeError, c.logical_or, 1, '1')
2060
2061 def test_logical_xor(self):
2062 c = Context()
2063 d = c.logical_xor(Decimal(1), Decimal(1))
2064 self.assertEqual(c.logical_xor(1, 1), d)
2065 self.assertEqual(c.logical_xor(Decimal(1), 1), d)
2066 self.assertEqual(c.logical_xor(1, Decimal(1)), d)
2067 self.assertRaises(TypeError, c.logical_xor, '1', 1)
2068 self.assertRaises(TypeError, c.logical_xor, 1, '1')
2069
2070 def test_max(self):
2071 c = Context()
2072 d = c.max(Decimal(1), Decimal(2))
2073 self.assertEqual(c.max(1, 2), d)
2074 self.assertEqual(c.max(Decimal(1), 2), d)
2075 self.assertEqual(c.max(1, Decimal(2)), d)
2076 self.assertRaises(TypeError, c.max, '1', 2)
2077 self.assertRaises(TypeError, c.max, 1, '2')
2078
2079 def test_max_mag(self):
2080 c = Context()
2081 d = c.max_mag(Decimal(1), Decimal(2))
2082 self.assertEqual(c.max_mag(1, 2), d)
2083 self.assertEqual(c.max_mag(Decimal(1), 2), d)
2084 self.assertEqual(c.max_mag(1, Decimal(2)), d)
2085 self.assertRaises(TypeError, c.max_mag, '1', 2)
2086 self.assertRaises(TypeError, c.max_mag, 1, '2')
2087
2088 def test_min(self):
2089 c = Context()
2090 d = c.min(Decimal(1), Decimal(2))
2091 self.assertEqual(c.min(1, 2), d)
2092 self.assertEqual(c.min(Decimal(1), 2), d)
2093 self.assertEqual(c.min(1, Decimal(2)), d)
2094 self.assertRaises(TypeError, c.min, '1', 2)
2095 self.assertRaises(TypeError, c.min, 1, '2')
2096
2097 def test_min_mag(self):
2098 c = Context()
2099 d = c.min_mag(Decimal(1), Decimal(2))
2100 self.assertEqual(c.min_mag(1, 2), d)
2101 self.assertEqual(c.min_mag(Decimal(1), 2), d)
2102 self.assertEqual(c.min_mag(1, Decimal(2)), d)
2103 self.assertRaises(TypeError, c.min_mag, '1', 2)
2104 self.assertRaises(TypeError, c.min_mag, 1, '2')
2105
2106 def test_minus(self):
2107 c = Context()
2108 d = c.minus(Decimal(10))
2109 self.assertEqual(c.minus(10), d)
2110 self.assertRaises(TypeError, c.minus, '10')
2111
2112 def test_multiply(self):
2113 c = Context()
2114 d = c.multiply(Decimal(1), Decimal(2))
2115 self.assertEqual(c.multiply(1, 2), d)
2116 self.assertEqual(c.multiply(Decimal(1), 2), d)
2117 self.assertEqual(c.multiply(1, Decimal(2)), d)
2118 self.assertRaises(TypeError, c.multiply, '1', 2)
2119 self.assertRaises(TypeError, c.multiply, 1, '2')
2120
2121 def test_next_minus(self):
2122 c = Context()
2123 d = c.next_minus(Decimal(10))
2124 self.assertEqual(c.next_minus(10), d)
2125 self.assertRaises(TypeError, c.next_minus, '10')
2126
2127 def test_next_plus(self):
2128 c = Context()
2129 d = c.next_plus(Decimal(10))
2130 self.assertEqual(c.next_plus(10), d)
2131 self.assertRaises(TypeError, c.next_plus, '10')
2132
2133 def test_next_toward(self):
2134 c = Context()
2135 d = c.next_toward(Decimal(1), Decimal(2))
2136 self.assertEqual(c.next_toward(1, 2), d)
2137 self.assertEqual(c.next_toward(Decimal(1), 2), d)
2138 self.assertEqual(c.next_toward(1, Decimal(2)), d)
2139 self.assertRaises(TypeError, c.next_toward, '1', 2)
2140 self.assertRaises(TypeError, c.next_toward, 1, '2')
2141
2142 def test_normalize(self):
2143 c = Context()
2144 d = c.normalize(Decimal(10))
2145 self.assertEqual(c.normalize(10), d)
2146 self.assertRaises(TypeError, c.normalize, '10')
2147
2148 def test_number_class(self):
2149 c = Context()
2150 self.assertEqual(c.number_class(123), c.number_class(Decimal(123)))
2151 self.assertEqual(c.number_class(0), c.number_class(Decimal(0)))
2152 self.assertEqual(c.number_class(-45), c.number_class(Decimal(-45)))
2153
2154 def test_power(self):
2155 c = Context()
2156 d = c.power(Decimal(1), Decimal(4), Decimal(2))
2157 self.assertEqual(c.power(1, 4, 2), d)
2158 self.assertEqual(c.power(Decimal(1), 4, 2), d)
2159 self.assertEqual(c.power(1, Decimal(4), 2), d)
2160 self.assertEqual(c.power(1, 4, Decimal(2)), d)
2161 self.assertEqual(c.power(Decimal(1), Decimal(4), 2), d)
2162 self.assertRaises(TypeError, c.power, '1', 4, 2)
2163 self.assertRaises(TypeError, c.power, 1, '4', 2)
2164 self.assertRaises(TypeError, c.power, 1, 4, '2')
2165
2166 def test_plus(self):
2167 c = Context()
2168 d = c.plus(Decimal(10))
2169 self.assertEqual(c.plus(10), d)
2170 self.assertRaises(TypeError, c.plus, '10')
2171
2172 def test_quantize(self):
2173 c = Context()
2174 d = c.quantize(Decimal(1), Decimal(2))
2175 self.assertEqual(c.quantize(1, 2), d)
2176 self.assertEqual(c.quantize(Decimal(1), 2), d)
2177 self.assertEqual(c.quantize(1, Decimal(2)), d)
2178 self.assertRaises(TypeError, c.quantize, '1', 2)
2179 self.assertRaises(TypeError, c.quantize, 1, '2')
2180
2181 def test_remainder(self):
2182 c = Context()
2183 d = c.remainder(Decimal(1), Decimal(2))
2184 self.assertEqual(c.remainder(1, 2), d)
2185 self.assertEqual(c.remainder(Decimal(1), 2), d)
2186 self.assertEqual(c.remainder(1, Decimal(2)), d)
2187 self.assertRaises(TypeError, c.remainder, '1', 2)
2188 self.assertRaises(TypeError, c.remainder, 1, '2')
2189
2190 def test_remainder_near(self):
2191 c = Context()
2192 d = c.remainder_near(Decimal(1), Decimal(2))
2193 self.assertEqual(c.remainder_near(1, 2), d)
2194 self.assertEqual(c.remainder_near(Decimal(1), 2), d)
2195 self.assertEqual(c.remainder_near(1, Decimal(2)), d)
2196 self.assertRaises(TypeError, c.remainder_near, '1', 2)
2197 self.assertRaises(TypeError, c.remainder_near, 1, '2')
2198
2199 def test_rotate(self):
2200 c = Context()
2201 d = c.rotate(Decimal(1), Decimal(2))
2202 self.assertEqual(c.rotate(1, 2), d)
2203 self.assertEqual(c.rotate(Decimal(1), 2), d)
2204 self.assertEqual(c.rotate(1, Decimal(2)), d)
2205 self.assertRaises(TypeError, c.rotate, '1', 2)
2206 self.assertRaises(TypeError, c.rotate, 1, '2')
2207
2208 def test_sqrt(self):
2209 c = Context()
2210 d = c.sqrt(Decimal(10))
2211 self.assertEqual(c.sqrt(10), d)
2212 self.assertRaises(TypeError, c.sqrt, '10')
2213
2214 def test_same_quantum(self):
2215 c = Context()
2216 d = c.same_quantum(Decimal(1), Decimal(2))
2217 self.assertEqual(c.same_quantum(1, 2), d)
2218 self.assertEqual(c.same_quantum(Decimal(1), 2), d)
2219 self.assertEqual(c.same_quantum(1, Decimal(2)), d)
2220 self.assertRaises(TypeError, c.same_quantum, '1', 2)
2221 self.assertRaises(TypeError, c.same_quantum, 1, '2')
2222
2223 def test_scaleb(self):
2224 c = Context()
2225 d = c.scaleb(Decimal(1), Decimal(2))
2226 self.assertEqual(c.scaleb(1, 2), d)
2227 self.assertEqual(c.scaleb(Decimal(1), 2), d)
2228 self.assertEqual(c.scaleb(1, Decimal(2)), d)
2229 self.assertRaises(TypeError, c.scaleb, '1', 2)
2230 self.assertRaises(TypeError, c.scaleb, 1, '2')
2231
2232 def test_shift(self):
2233 c = Context()
2234 d = c.shift(Decimal(1), Decimal(2))
2235 self.assertEqual(c.shift(1, 2), d)
2236 self.assertEqual(c.shift(Decimal(1), 2), d)
2237 self.assertEqual(c.shift(1, Decimal(2)), d)
2238 self.assertRaises(TypeError, c.shift, '1', 2)
2239 self.assertRaises(TypeError, c.shift, 1, '2')
2240
2241 def test_subtract(self):
2242 c = Context()
2243 d = c.subtract(Decimal(1), Decimal(2))
2244 self.assertEqual(c.subtract(1, 2), d)
2245 self.assertEqual(c.subtract(Decimal(1), 2), d)
2246 self.assertEqual(c.subtract(1, Decimal(2)), d)
2247 self.assertRaises(TypeError, c.subtract, '1', 2)
2248 self.assertRaises(TypeError, c.subtract, 1, '2')
2249
2250 def test_to_eng_string(self):
2251 c = Context()
2252 d = c.to_eng_string(Decimal(10))
2253 self.assertEqual(c.to_eng_string(10), d)
2254 self.assertRaises(TypeError, c.to_eng_string, '10')
2255
2256 def test_to_sci_string(self):
2257 c = Context()
2258 d = c.to_sci_string(Decimal(10))
2259 self.assertEqual(c.to_sci_string(10), d)
2260 self.assertRaises(TypeError, c.to_sci_string, '10')
2261
2262 def test_to_integral_exact(self):
2263 c = Context()
2264 d = c.to_integral_exact(Decimal(10))
2265 self.assertEqual(c.to_integral_exact(10), d)
2266 self.assertRaises(TypeError, c.to_integral_exact, '10')
2267
2268 def test_to_integral_value(self):
2269 c = Context()
2270 d = c.to_integral_value(Decimal(10))
2271 self.assertEqual(c.to_integral_value(10), d)
2272 self.assertRaises(TypeError, c.to_integral_value, '10')
2273
Thomas Wouters89f507f2006-12-13 04:49:30 +00002274class WithStatementTest(unittest.TestCase):
2275 # Can't do these as docstrings until Python 2.6
2276 # as doctest can't handle __future__ statements
2277
2278 def test_localcontext(self):
2279 # Use a copy of the current context in the block
2280 orig_ctx = getcontext()
2281 with localcontext() as enter_ctx:
2282 set_ctx = getcontext()
2283 final_ctx = getcontext()
Ezio Melotti6607d512010-04-03 14:59:49 +00002284 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
2285 self.assertIsNot(orig_ctx, set_ctx, 'did not copy the context')
2286 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
Thomas Wouters89f507f2006-12-13 04:49:30 +00002287
2288 def test_localcontextarg(self):
2289 # Use a copy of the supplied context in the block
2290 orig_ctx = getcontext()
2291 new_ctx = Context(prec=42)
2292 with localcontext(new_ctx) as enter_ctx:
2293 set_ctx = getcontext()
2294 final_ctx = getcontext()
Ezio Melotti6607d512010-04-03 14:59:49 +00002295 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
2296 self.assertEqual(set_ctx.prec, new_ctx.prec, 'did not set correct context')
2297 self.assertIsNot(new_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
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002300class ContextFlags(unittest.TestCase):
2301 def test_flags_irrelevant(self):
2302 # check that the result (numeric result + flags raised) of an
2303 # arithmetic operation doesn't depend on the current flags
2304
2305 context = Context(prec=9, Emin = -999999999, Emax = 999999999,
2306 rounding=ROUND_HALF_EVEN, traps=[], flags=[])
2307
2308 # operations that raise various flags, in the form (function, arglist)
2309 operations = [
2310 (context._apply, [Decimal("100E-1000000009")]),
2311 (context.sqrt, [Decimal(2)]),
2312 (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]),
2313 (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]),
2314 (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]),
2315 ]
2316
2317 # try various flags individually, then a whole lot at once
2318 flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal],
2319 [Inexact, Rounded, Underflow, Clamped, Subnormal]]
2320
2321 for fn, args in operations:
2322 # find answer and flags raised using a clean context
2323 context.clear_flags()
2324 ans = fn(*args)
2325 flags = [k for k, v in context.flags.items() if v]
2326
2327 for extra_flags in flagsets:
2328 # set flags, before calling operation
2329 context.clear_flags()
2330 for flag in extra_flags:
2331 context._raise_error(flag)
2332 new_ans = fn(*args)
2333
2334 # flags that we expect to be set after the operation
2335 expected_flags = list(flags)
2336 for flag in extra_flags:
2337 if flag not in expected_flags:
2338 expected_flags.append(flag)
2339 expected_flags.sort(key=id)
2340
2341 # flags we actually got
2342 new_flags = [k for k,v in context.flags.items() if v]
2343 new_flags.sort(key=id)
2344
2345 self.assertEqual(ans, new_ans,
2346 "operation produces different answers depending on flags set: " +
2347 "expected %s, got %s." % (ans, new_ans))
2348 self.assertEqual(new_flags, expected_flags,
2349 "operation raises different flags depending on flags set: " +
2350 "expected %s, got %s" % (expected_flags, new_flags))
2351
2352def test_main(arith=False, verbose=None, todo_tests=None, debug=None):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002353 """ Execute the tests.
2354
Raymond Hettingered20ad82004-09-04 20:09:13 +00002355 Runs all arithmetic tests if arith is True or if the "decimal" resource
2356 is enabled in regrtest.py
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002357 """
Raymond Hettingered20ad82004-09-04 20:09:13 +00002358
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002359 init()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002360 global TEST_ALL, DEBUG
Raymond Hettingered20ad82004-09-04 20:09:13 +00002361 TEST_ALL = arith or is_resource_enabled('decimal')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002362 DEBUG = debug
Raymond Hettingered20ad82004-09-04 20:09:13 +00002363
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002364 if todo_tests is None:
2365 test_classes = [
2366 DecimalExplicitConstructionTest,
2367 DecimalImplicitConstructionTest,
2368 DecimalArithmeticOperatorsTest,
Christian Heimesf16baeb2008-02-29 14:57:44 +00002369 DecimalFormatTest,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002370 DecimalUseOfContextTest,
2371 DecimalUsabilityTest,
2372 DecimalPythonAPItests,
2373 ContextAPItests,
2374 DecimalTest,
2375 WithStatementTest,
2376 ContextFlags
2377 ]
2378 else:
2379 test_classes = [DecimalTest]
2380
2381 # Dynamically build custom test definition for each file in the test
2382 # directory and add the definitions to the DecimalTest class. This
2383 # procedure insures that new files do not get skipped.
2384 for filename in os.listdir(directory):
2385 if '.decTest' not in filename or filename.startswith("."):
2386 continue
2387 head, tail = filename.split('.')
2388 if todo_tests is not None and head not in todo_tests:
2389 continue
2390 tester = lambda self, f=filename: self.eval_file(directory + f)
2391 setattr(DecimalTest, 'test_' + head, tester)
2392 del filename, head, tail, tester
2393
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002394
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002395 try:
2396 run_unittest(*test_classes)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002397 if todo_tests is None:
2398 import decimal as DecimalModule
2399 run_doctest(DecimalModule, verbose)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002400 finally:
2401 setcontext(ORIGINAL_CONTEXT)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002402
2403if __name__ == '__main__':
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002404 import optparse
2405 p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]")
2406 p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test')
2407 p.add_option('--skip', '-s', action='store_true', help='skip over 90% of the arithmetic tests')
2408 (opt, args) = p.parse_args()
2409
2410 if opt.skip:
2411 test_main(arith=False, verbose=True)
2412 elif args:
2413 test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002414 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002415 test_main(arith=True, verbose=True)