blob: 4a354657967022faa8c12719b941b593700261c8 [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
Neal Norwitz70967602006-03-17 08:29:44 +0000228 for line in open(file):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000229 line = line.replace('\r\n', '').replace('\n', '')
Raymond Hettinger5aa478b2004-07-09 10:02:53 +0000230 #print line
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000231 try:
232 t = self.eval_line(line)
Guido van Rossumb940e112007-01-10 16:19:56 +0000233 except DecimalException as exception:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000234 #Exception raised where there shoudn't have been one.
235 self.fail('Exception "'+exception.__class__.__name__ + '" raised on line '+line)
236
237 return
238
239 def eval_line(self, s):
240 if s.find(' -> ') >= 0 and s[:2] != '--' and not s.startswith(' --'):
241 s = (s.split('->')[0] + '->' +
242 s.split('->')[1].split('--')[0]).strip()
243 else:
244 s = s.split('--')[0].strip()
245
246 for ignore in self.ignore_list:
247 if s.find(ignore) >= 0:
248 #print s.split()[0], 'NotImplemented--', ignore
249 return
250 if not s:
251 return
252 elif ':' in s:
253 return self.eval_directive(s)
254 else:
255 return self.eval_equation(s)
256
257 def eval_directive(self, s):
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000258 funct, value = (x.strip().lower() for x in s.split(':'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000259 if funct == 'rounding':
260 value = RoundingDict[value]
261 else:
262 try:
263 value = int(value)
264 except ValueError:
265 pass
266
267 funct = self.ChangeDict.get(funct, Nonfunction)
268 funct(value)
269
270 def eval_equation(self, s):
271 #global DEFAULT_PRECISION
272 #print DEFAULT_PRECISION
Raymond Hettingered20ad82004-09-04 20:09:13 +0000273
274 if not TEST_ALL and random.random() < 0.90:
275 return
276
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000277 try:
278 Sides = s.split('->')
279 L = Sides[0].strip().split()
280 id = L[0]
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000281 if DEBUG:
282 print("Test ", id, end=" ")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000283 funct = L[1].lower()
284 valstemp = L[2:]
285 L = Sides[1].strip().split()
286 ans = L[0]
287 exceptions = L[1:]
288 except (TypeError, AttributeError, IndexError):
Raymond Hettingerd87ac8f2004-07-09 10:52:54 +0000289 raise InvalidOperation
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000290 def FixQuotes(val):
291 val = val.replace("''", 'SingleQuote').replace('""', 'DoubleQuote')
292 val = val.replace("'", '').replace('"', '')
293 val = val.replace('SingleQuote', "'").replace('DoubleQuote', '"')
294 return val
Mark Dickinson8a546532009-10-08 16:30:38 +0000295
296 if id in skipped_test_ids:
297 return
298
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000299 fname = nameAdapter.get(funct, funct)
300 if fname == 'rescale':
301 return
302 funct = getattr(self.context, fname)
303 vals = []
304 conglomerate = ''
305 quote = 0
306 theirexceptions = [ErrorNames[x.lower()] for x in exceptions]
307
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000308 for exception in Signals:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000309 self.context.traps[exception] = 1 #Catch these bugs...
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000310 for exception in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000311 self.context.traps[exception] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000312 for i, val in enumerate(valstemp):
313 if val.count("'") % 2 == 1:
314 quote = 1 - quote
315 if quote:
316 conglomerate = conglomerate + ' ' + val
317 continue
318 else:
319 val = conglomerate + val
320 conglomerate = ''
321 v = FixQuotes(val)
322 if fname in ('to_sci_string', 'to_eng_string'):
323 if EXTENDEDERRORTEST:
324 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000325 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000326 try:
327 funct(self.context.create_decimal(v))
328 except error:
329 pass
Guido van Rossumb940e112007-01-10 16:19:56 +0000330 except Signals as e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000331 self.fail("Raised %s in %s when %s disabled" % \
332 (e, s, error))
333 else:
334 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000335 self.context.traps[error] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000336 v = self.context.create_decimal(v)
337 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000338 v = Decimal(v, self.context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000339 vals.append(v)
340
341 ans = FixQuotes(ans)
342
343 if EXTENDEDERRORTEST and fname not in ('to_sci_string', 'to_eng_string'):
344 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000345 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000346 try:
347 funct(*vals)
348 except error:
349 pass
Guido van Rossumb940e112007-01-10 16:19:56 +0000350 except Signals as e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000351 self.fail("Raised %s in %s when %s disabled" % \
352 (e, s, error))
353 else:
354 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000355 self.context.traps[error] = 0
Mark Dickinsonc69160e2010-05-04 14:35:33 +0000356
357 # as above, but add traps cumulatively, to check precedence
358 ordered_errors = [e for e in OrderedSignals if e in theirexceptions]
359 for error in ordered_errors:
360 self.context.traps[error] = 1
361 try:
362 funct(*vals)
363 except error:
364 pass
365 except Signals as e:
366 self.fail("Raised %s in %s; expected %s" %
367 (type(e), s, error))
368 else:
369 self.fail("Did not raise %s in %s" % (error, s))
370 # reset traps
371 for error in ordered_errors:
372 self.context.traps[error] = 0
373
374
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000375 if DEBUG:
376 print("--", self.context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000377 try:
378 result = str(funct(*vals))
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000379 if fname in LOGICAL_FUNCTIONS:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000380 result = str(int(eval(result))) # 'True', 'False' -> '1', '0'
Guido van Rossumb940e112007-01-10 16:19:56 +0000381 except Signals as error:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000382 self.fail("Raised %s in %s" % (error, s))
383 except: #Catch any error long enough to state the test case.
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000384 print("ERROR:", s)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000385 raise
386
387 myexceptions = self.getexceptions()
Raymond Hettingerbf440692004-07-10 14:14:37 +0000388 self.context.clear_flags()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000389
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000390 myexceptions.sort(key=repr)
391 theirexceptions.sort(key=repr)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000392
393 self.assertEqual(result, ans,
394 'Incorrect answer for ' + s + ' -- got ' + result)
395 self.assertEqual(myexceptions, theirexceptions,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000396 'Incorrect flags set in ' + s + ' -- got ' + str(myexceptions))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000397 return
398
399 def getexceptions(self):
Raymond Hettingerf63ba432004-08-17 05:42:09 +0000400 return [e for e in Signals if self.context.flags[e]]
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000401
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000402 def change_precision(self, prec):
403 self.context.prec = prec
404 def change_rounding_method(self, rounding):
405 self.context.rounding = rounding
406 def change_min_exponent(self, exp):
407 self.context.Emin = exp
408 def change_max_exponent(self, exp):
409 self.context.Emax = exp
410 def change_clamp(self, clamp):
Mark Dickinsonb1d8e322010-05-22 18:35:36 +0000411 self.context.clamp = clamp
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000412
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000413
414
415# The following classes test the behaviour of Decimal according to PEP 327
416
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000417class DecimalExplicitConstructionTest(unittest.TestCase):
418 '''Unit tests for Explicit Construction cases of Decimal.'''
419
420 def test_explicit_empty(self):
421 self.assertEqual(Decimal(), Decimal("0"))
422
423 def test_explicit_from_None(self):
424 self.assertRaises(TypeError, Decimal, None)
425
426 def test_explicit_from_int(self):
427
428 #positive
429 d = Decimal(45)
430 self.assertEqual(str(d), '45')
431
432 #very large positive
433 d = Decimal(500000123)
434 self.assertEqual(str(d), '500000123')
435
436 #negative
437 d = Decimal(-45)
438 self.assertEqual(str(d), '-45')
439
440 #zero
441 d = Decimal(0)
442 self.assertEqual(str(d), '0')
443
444 def test_explicit_from_string(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000445
446 #empty
447 self.assertEqual(str(Decimal('')), 'NaN')
448
449 #int
450 self.assertEqual(str(Decimal('45')), '45')
451
452 #float
453 self.assertEqual(str(Decimal('45.34')), '45.34')
454
455 #engineer notation
456 self.assertEqual(str(Decimal('45e2')), '4.5E+3')
457
458 #just not a number
459 self.assertEqual(str(Decimal('ugly')), 'NaN')
460
Christian Heimesa62da1d2008-01-12 19:39:10 +0000461 #leading and trailing whitespace permitted
462 self.assertEqual(str(Decimal('1.3E4 \n')), '1.3E+4')
463 self.assertEqual(str(Decimal(' -7.89')), '-7.89')
464
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000465 def test_explicit_from_tuples(self):
466
467 #zero
468 d = Decimal( (0, (0,), 0) )
469 self.assertEqual(str(d), '0')
470
471 #int
472 d = Decimal( (1, (4, 5), 0) )
473 self.assertEqual(str(d), '-45')
474
475 #float
476 d = Decimal( (0, (4, 5, 3, 4), -2) )
477 self.assertEqual(str(d), '45.34')
478
479 #weird
480 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
481 self.assertEqual(str(d), '-4.34913534E-17')
482
483 #wrong number of items
484 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1)) )
485
486 #bad sign
487 self.assertRaises(ValueError, Decimal, (8, (4, 3, 4, 9, 1), 2) )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000488 self.assertRaises(ValueError, Decimal, (0., (4, 3, 4, 9, 1), 2) )
489 self.assertRaises(ValueError, Decimal, (Decimal(1), (4, 3, 4, 9, 1), 2))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000490
491 #bad exp
492 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 'wrong!') )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000493 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 0.) )
494 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), '1') )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000495
496 #bad coefficients
497 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, None, 1), 2) )
498 self.assertRaises(ValueError, Decimal, (1, (4, -3, 4, 9, 1), 2) )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000499 self.assertRaises(ValueError, Decimal, (1, (4, 10, 4, 9, 1), 2) )
Guido van Rossum0d3fb8a2007-11-26 23:23:18 +0000500 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 'a', 1), 2) )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000501
Antoine Pitrou503ab332010-03-30 18:56:19 +0000502 def test_explicit_from_bool(self):
503 self.assertIs(bool(Decimal(0)), False)
504 self.assertIs(bool(Decimal(1)), True)
505 self.assertEqual(Decimal(False), Decimal(0))
506 self.assertEqual(Decimal(True), Decimal(1))
507
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000508 def test_explicit_from_Decimal(self):
509
510 #positive
511 d = Decimal(45)
512 e = Decimal(d)
513 self.assertEqual(str(e), '45')
514 self.assertNotEqual(id(d), id(e))
515
516 #very large positive
517 d = Decimal(500000123)
518 e = Decimal(d)
519 self.assertEqual(str(e), '500000123')
520 self.assertNotEqual(id(d), id(e))
521
522 #negative
523 d = Decimal(-45)
524 e = Decimal(d)
525 self.assertEqual(str(e), '-45')
526 self.assertNotEqual(id(d), id(e))
527
528 #zero
529 d = Decimal(0)
530 e = Decimal(d)
531 self.assertEqual(str(e), '0')
532 self.assertNotEqual(id(d), id(e))
533
Raymond Hettinger96798592010-04-02 16:58:27 +0000534 @requires_IEEE_754
535 def test_explicit_from_float(self):
536 r = Decimal(0.1)
537 self.assertEqual(type(r), Decimal)
538 self.assertEqual(str(r),
539 '0.1000000000000000055511151231257827021181583404541015625')
540 self.assertTrue(Decimal(float('nan')).is_qnan())
541 self.assertTrue(Decimal(float('inf')).is_infinite())
542 self.assertTrue(Decimal(float('-inf')).is_infinite())
543 self.assertEqual(str(Decimal(float('nan'))),
544 str(Decimal('NaN')))
545 self.assertEqual(str(Decimal(float('inf'))),
546 str(Decimal('Infinity')))
547 self.assertEqual(str(Decimal(float('-inf'))),
548 str(Decimal('-Infinity')))
549 self.assertEqual(str(Decimal(float('-0.0'))),
550 str(Decimal('-0')))
551 for i in range(200):
552 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
553 self.assertEqual(x, float(Decimal(x))) # roundtrip
554
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000555 def test_explicit_context_create_decimal(self):
556
557 nc = copy.copy(getcontext())
558 nc.prec = 3
559
560 # empty
Raymond Hettingerfed52962004-07-14 15:41:57 +0000561 d = Decimal()
562 self.assertEqual(str(d), '0')
563 d = nc.create_decimal()
564 self.assertEqual(str(d), '0')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000565
566 # from None
567 self.assertRaises(TypeError, nc.create_decimal, None)
568
569 # from int
570 d = nc.create_decimal(456)
Ezio Melottie9615932010-01-24 19:26:24 +0000571 self.assertIsInstance(d, Decimal)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000572 self.assertEqual(nc.create_decimal(45678),
573 nc.create_decimal('457E+2'))
574
575 # from string
576 d = Decimal('456789')
577 self.assertEqual(str(d), '456789')
578 d = nc.create_decimal('456789')
579 self.assertEqual(str(d), '4.57E+5')
Christian Heimesa62da1d2008-01-12 19:39:10 +0000580 # leading and trailing whitespace should result in a NaN;
581 # spaces are already checked in Cowlishaw's test-suite, so
582 # here we just check that a trailing newline results in a NaN
583 self.assertEqual(str(nc.create_decimal('3.14\n')), 'NaN')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000584
585 # from tuples
586 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
587 self.assertEqual(str(d), '-4.34913534E-17')
588 d = nc.create_decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
589 self.assertEqual(str(d), '-4.35E-17')
590
591 # from Decimal
592 prevdec = Decimal(500000123)
593 d = Decimal(prevdec)
594 self.assertEqual(str(d), '500000123')
595 d = nc.create_decimal(prevdec)
596 self.assertEqual(str(d), '5.00E+8')
597
Mark Dickinson345adc42009-08-02 10:14:23 +0000598 def test_unicode_digits(self):
599 test_values = {
600 '\uff11': '1',
601 '\u0660.\u0660\u0663\u0667\u0662e-\u0663' : '0.0000372',
602 '-nan\u0c68\u0c6a\u0c66\u0c66' : '-NaN2400',
603 }
604 for input, expected in test_values.items():
605 self.assertEqual(str(Decimal(input)), expected)
606
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000607
608class DecimalImplicitConstructionTest(unittest.TestCase):
609 '''Unit tests for Implicit Construction cases of Decimal.'''
610
611 def test_implicit_from_None(self):
612 self.assertRaises(TypeError, eval, 'Decimal(5) + None', globals())
613
614 def test_implicit_from_int(self):
615 #normal
616 self.assertEqual(str(Decimal(5) + 45), '50')
617 #exceeding precision
618 self.assertEqual(Decimal(5) + 123456789000, Decimal(123456789000))
619
620 def test_implicit_from_string(self):
621 self.assertRaises(TypeError, eval, 'Decimal(5) + "3"', globals())
622
623 def test_implicit_from_float(self):
624 self.assertRaises(TypeError, eval, 'Decimal(5) + 2.2', globals())
625
626 def test_implicit_from_Decimal(self):
627 self.assertEqual(Decimal(5) + Decimal(45), Decimal(50))
628
Raymond Hettinger267b8682005-03-27 10:47:39 +0000629 def test_rop(self):
630 # Allow other classes to be trained to interact with Decimals
631 class E:
632 def __divmod__(self, other):
633 return 'divmod ' + str(other)
634 def __rdivmod__(self, other):
635 return str(other) + ' rdivmod'
636 def __lt__(self, other):
637 return 'lt ' + str(other)
638 def __gt__(self, other):
639 return 'gt ' + str(other)
640 def __le__(self, other):
641 return 'le ' + str(other)
642 def __ge__(self, other):
643 return 'ge ' + str(other)
644 def __eq__(self, other):
645 return 'eq ' + str(other)
646 def __ne__(self, other):
647 return 'ne ' + str(other)
648
649 self.assertEqual(divmod(E(), Decimal(10)), 'divmod 10')
650 self.assertEqual(divmod(Decimal(10), E()), '10 rdivmod')
651 self.assertEqual(eval('Decimal(10) < E()'), 'gt 10')
652 self.assertEqual(eval('Decimal(10) > E()'), 'lt 10')
653 self.assertEqual(eval('Decimal(10) <= E()'), 'ge 10')
654 self.assertEqual(eval('Decimal(10) >= E()'), 'le 10')
655 self.assertEqual(eval('Decimal(10) == E()'), 'eq 10')
656 self.assertEqual(eval('Decimal(10) != E()'), 'ne 10')
657
658 # insert operator methods and then exercise them
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000659 oplist = [
660 ('+', '__add__', '__radd__'),
661 ('-', '__sub__', '__rsub__'),
662 ('*', '__mul__', '__rmul__'),
Thomas Woutersdcc6d322006-04-21 11:30:52 +0000663 ('/', '__truediv__', '__rtruediv__'),
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000664 ('%', '__mod__', '__rmod__'),
665 ('//', '__floordiv__', '__rfloordiv__'),
666 ('**', '__pow__', '__rpow__')
667 ]
Raymond Hettinger267b8682005-03-27 10:47:39 +0000668
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000669 for sym, lop, rop in oplist:
Raymond Hettinger267b8682005-03-27 10:47:39 +0000670 setattr(E, lop, lambda self, other: 'str' + lop + str(other))
671 setattr(E, rop, lambda self, other: str(other) + rop + 'str')
672 self.assertEqual(eval('E()' + sym + 'Decimal(10)'),
673 'str' + lop + '10')
674 self.assertEqual(eval('Decimal(10)' + sym + 'E()'),
675 '10' + rop + 'str')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000676
Mark Dickinson79f52032009-03-17 23:12:51 +0000677
Christian Heimesf16baeb2008-02-29 14:57:44 +0000678class DecimalFormatTest(unittest.TestCase):
679 '''Unit tests for the format function.'''
680 def test_formatting(self):
681 # triples giving a format, a Decimal, and the expected result
682 test_values = [
683 ('e', '0E-15', '0e-15'),
684 ('e', '2.3E-15', '2.3e-15'),
685 ('e', '2.30E+2', '2.30e+2'), # preserve significant zeros
686 ('e', '2.30000E-15', '2.30000e-15'),
687 ('e', '1.23456789123456789e40', '1.23456789123456789e+40'),
688 ('e', '1.5', '1.5e+0'),
689 ('e', '0.15', '1.5e-1'),
690 ('e', '0.015', '1.5e-2'),
691 ('e', '0.0000000000015', '1.5e-12'),
692 ('e', '15.0', '1.50e+1'),
693 ('e', '-15', '-1.5e+1'),
694 ('e', '0', '0e+0'),
695 ('e', '0E1', '0e+1'),
696 ('e', '0.0', '0e-1'),
697 ('e', '0.00', '0e-2'),
698 ('.6e', '0E-15', '0.000000e-9'),
699 ('.6e', '0', '0.000000e+6'),
700 ('.6e', '9.999999', '9.999999e+0'),
701 ('.6e', '9.9999999', '1.000000e+1'),
702 ('.6e', '-1.23e5', '-1.230000e+5'),
703 ('.6e', '1.23456789e-3', '1.234568e-3'),
704 ('f', '0', '0'),
705 ('f', '0.0', '0.0'),
706 ('f', '0E-2', '0.00'),
707 ('f', '0.00E-8', '0.0000000000'),
708 ('f', '0E1', '0'), # loses exponent information
709 ('f', '3.2E1', '32'),
710 ('f', '3.2E2', '320'),
711 ('f', '3.20E2', '320'),
712 ('f', '3.200E2', '320.0'),
713 ('f', '3.2E-6', '0.0000032'),
714 ('.6f', '0E-15', '0.000000'), # all zeros treated equally
715 ('.6f', '0E1', '0.000000'),
716 ('.6f', '0', '0.000000'),
717 ('.0f', '0', '0'), # no decimal point
718 ('.0f', '0e-2', '0'),
719 ('.0f', '3.14159265', '3'),
720 ('.1f', '3.14159265', '3.1'),
721 ('.4f', '3.14159265', '3.1416'),
722 ('.6f', '3.14159265', '3.141593'),
723 ('.7f', '3.14159265', '3.1415926'), # round-half-even!
724 ('.8f', '3.14159265', '3.14159265'),
725 ('.9f', '3.14159265', '3.141592650'),
726
727 ('g', '0', '0'),
728 ('g', '0.0', '0.0'),
729 ('g', '0E1', '0e+1'),
730 ('G', '0E1', '0E+1'),
731 ('g', '0E-5', '0.00000'),
732 ('g', '0E-6', '0.000000'),
733 ('g', '0E-7', '0e-7'),
734 ('g', '-0E2', '-0e+2'),
735 ('.0g', '3.14159265', '3'), # 0 sig fig -> 1 sig fig
736 ('.1g', '3.14159265', '3'),
737 ('.2g', '3.14159265', '3.1'),
738 ('.5g', '3.14159265', '3.1416'),
739 ('.7g', '3.14159265', '3.141593'),
740 ('.8g', '3.14159265', '3.1415926'), # round-half-even!
741 ('.9g', '3.14159265', '3.14159265'),
742 ('.10g', '3.14159265', '3.14159265'), # don't pad
743
744 ('%', '0E1', '0%'),
745 ('%', '0E0', '0%'),
746 ('%', '0E-1', '0%'),
747 ('%', '0E-2', '0%'),
748 ('%', '0E-3', '0.0%'),
749 ('%', '0E-4', '0.00%'),
750
751 ('.3%', '0', '0.000%'), # all zeros treated equally
752 ('.3%', '0E10', '0.000%'),
753 ('.3%', '0E-10', '0.000%'),
754 ('.3%', '2.34', '234.000%'),
755 ('.3%', '1.234567', '123.457%'),
756 ('.0%', '1.23', '123%'),
757
758 ('e', 'NaN', 'NaN'),
759 ('f', '-NaN123', '-NaN123'),
760 ('+g', 'NaN456', '+NaN456'),
761 ('.3e', 'Inf', 'Infinity'),
762 ('.16f', '-Inf', '-Infinity'),
763 ('.0g', '-sNaN', '-sNaN'),
764
765 ('', '1.00', '1.00'),
Mark Dickinsonad416342009-03-17 18:10:15 +0000766
Mark Dickinson79f52032009-03-17 23:12:51 +0000767 # test alignment and padding
Mark Dickinson46ab5d02009-09-08 20:22:46 +0000768 ('6', '123', ' 123'),
Mark Dickinsonad416342009-03-17 18:10:15 +0000769 ('<6', '123', '123 '),
770 ('>6', '123', ' 123'),
771 ('^6', '123', ' 123 '),
772 ('=+6', '123', '+ 123'),
Mark Dickinson79f52032009-03-17 23:12:51 +0000773 ('#<10', 'NaN', 'NaN#######'),
774 ('#<10', '-4.3', '-4.3######'),
775 ('#<+10', '0.0130', '+0.0130###'),
776 ('#< 10', '0.0130', ' 0.0130###'),
777 ('@>10', '-Inf', '@-Infinity'),
778 ('#>5', '-Inf', '-Infinity'),
779 ('?^5', '123', '?123?'),
780 ('%^6', '123', '%123%%'),
781 (' ^6', '-45.6', '-45.6 '),
782 ('/=10', '-45.6', '-/////45.6'),
783 ('/=+10', '45.6', '+/////45.6'),
784 ('/= 10', '45.6', ' /////45.6'),
785
786 # thousands separator
787 (',', '1234567', '1,234,567'),
788 (',', '123456', '123,456'),
789 (',', '12345', '12,345'),
790 (',', '1234', '1,234'),
791 (',', '123', '123'),
792 (',', '12', '12'),
793 (',', '1', '1'),
794 (',', '0', '0'),
795 (',', '-1234567', '-1,234,567'),
796 (',', '-123456', '-123,456'),
797 ('7,', '123456', '123,456'),
Mark Dickinson46ab5d02009-09-08 20:22:46 +0000798 ('8,', '123456', ' 123,456'),
Mark Dickinson79f52032009-03-17 23:12:51 +0000799 ('08,', '123456', '0,123,456'), # special case: extra 0 needed
800 ('+08,', '123456', '+123,456'), # but not if there's a sign
801 (' 08,', '123456', ' 123,456'),
802 ('08,', '-123456', '-123,456'),
803 ('+09,', '123456', '+0,123,456'),
804 # ... with fractional part...
805 ('07,', '1234.56', '1,234.56'),
806 ('08,', '1234.56', '1,234.56'),
807 ('09,', '1234.56', '01,234.56'),
808 ('010,', '1234.56', '001,234.56'),
809 ('011,', '1234.56', '0,001,234.56'),
810 ('012,', '1234.56', '0,001,234.56'),
811 ('08,.1f', '1234.5', '01,234.5'),
812 # no thousands separators in fraction part
813 (',', '1.23456789', '1.23456789'),
814 (',%', '123.456789', '12,345.6789%'),
815 (',e', '123456', '1.23456e+5'),
816 (',E', '123456', '1.23456E+5'),
Mark Dickinson7718d2b2009-09-07 16:21:56 +0000817
818 # issue 6850
819 ('a=-7.0', '0.12345', 'aaaa0.1'),
Christian Heimesf16baeb2008-02-29 14:57:44 +0000820 ]
821 for fmt, d, result in test_values:
822 self.assertEqual(format(Decimal(d), fmt), result)
823
Mark Dickinson79f52032009-03-17 23:12:51 +0000824 def test_n_format(self):
825 try:
826 from locale import CHAR_MAX
827 except ImportError:
828 return
829
830 # Set up some localeconv-like dictionaries
831 en_US = {
832 'decimal_point' : '.',
833 'grouping' : [3, 3, 0],
834 'thousands_sep': ','
835 }
836
837 fr_FR = {
838 'decimal_point' : ',',
839 'grouping' : [CHAR_MAX],
840 'thousands_sep' : ''
841 }
842
843 ru_RU = {
844 'decimal_point' : ',',
845 'grouping' : [3, 3, 0],
846 'thousands_sep' : ' '
847 }
848
849 crazy = {
850 'decimal_point' : '&',
851 'grouping' : [1, 4, 2, CHAR_MAX],
852 'thousands_sep' : '-'
853 }
854
855
856 def get_fmt(x, locale, fmt='n'):
857 return Decimal.__format__(Decimal(x), fmt, _localeconv=locale)
858
859 self.assertEqual(get_fmt(Decimal('12.7'), en_US), '12.7')
860 self.assertEqual(get_fmt(Decimal('12.7'), fr_FR), '12,7')
861 self.assertEqual(get_fmt(Decimal('12.7'), ru_RU), '12,7')
862 self.assertEqual(get_fmt(Decimal('12.7'), crazy), '1-2&7')
863
864 self.assertEqual(get_fmt(123456789, en_US), '123,456,789')
865 self.assertEqual(get_fmt(123456789, fr_FR), '123456789')
866 self.assertEqual(get_fmt(123456789, ru_RU), '123 456 789')
867 self.assertEqual(get_fmt(1234567890123, crazy), '123456-78-9012-3')
868
869 self.assertEqual(get_fmt(123456789, en_US, '.6n'), '1.23457e+8')
870 self.assertEqual(get_fmt(123456789, fr_FR, '.6n'), '1,23457e+8')
871 self.assertEqual(get_fmt(123456789, ru_RU, '.6n'), '1,23457e+8')
872 self.assertEqual(get_fmt(123456789, crazy, '.6n'), '1&23457e+8')
873
Mark Dickinson7303b592009-03-18 08:25:36 +0000874 # zero padding
875 self.assertEqual(get_fmt(1234, fr_FR, '03n'), '1234')
876 self.assertEqual(get_fmt(1234, fr_FR, '04n'), '1234')
877 self.assertEqual(get_fmt(1234, fr_FR, '05n'), '01234')
878 self.assertEqual(get_fmt(1234, fr_FR, '06n'), '001234')
879
880 self.assertEqual(get_fmt(12345, en_US, '05n'), '12,345')
881 self.assertEqual(get_fmt(12345, en_US, '06n'), '12,345')
882 self.assertEqual(get_fmt(12345, en_US, '07n'), '012,345')
883 self.assertEqual(get_fmt(12345, en_US, '08n'), '0,012,345')
884 self.assertEqual(get_fmt(12345, en_US, '09n'), '0,012,345')
885 self.assertEqual(get_fmt(12345, en_US, '010n'), '00,012,345')
886
887 self.assertEqual(get_fmt(123456, crazy, '06n'), '1-2345-6')
888 self.assertEqual(get_fmt(123456, crazy, '07n'), '1-2345-6')
889 self.assertEqual(get_fmt(123456, crazy, '08n'), '1-2345-6')
890 self.assertEqual(get_fmt(123456, crazy, '09n'), '01-2345-6')
891 self.assertEqual(get_fmt(123456, crazy, '010n'), '0-01-2345-6')
892 self.assertEqual(get_fmt(123456, crazy, '011n'), '0-01-2345-6')
893 self.assertEqual(get_fmt(123456, crazy, '012n'), '00-01-2345-6')
894 self.assertEqual(get_fmt(123456, crazy, '013n'), '000-01-2345-6')
895
Mark Dickinson79f52032009-03-17 23:12:51 +0000896
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000897class DecimalArithmeticOperatorsTest(unittest.TestCase):
898 '''Unit tests for all arithmetic operators, binary and unary.'''
899
900 def test_addition(self):
901
902 d1 = Decimal('-11.1')
903 d2 = Decimal('22.2')
904
905 #two Decimals
906 self.assertEqual(d1+d2, Decimal('11.1'))
907 self.assertEqual(d2+d1, Decimal('11.1'))
908
909 #with other type, left
910 c = d1 + 5
911 self.assertEqual(c, Decimal('-6.1'))
912 self.assertEqual(type(c), type(d1))
913
914 #with other type, right
915 c = 5 + d1
916 self.assertEqual(c, Decimal('-6.1'))
917 self.assertEqual(type(c), type(d1))
918
919 #inline with decimal
920 d1 += d2
921 self.assertEqual(d1, Decimal('11.1'))
922
923 #inline with other type
924 d1 += 5
925 self.assertEqual(d1, Decimal('16.1'))
926
927 def test_subtraction(self):
928
929 d1 = Decimal('-11.1')
930 d2 = Decimal('22.2')
931
932 #two Decimals
933 self.assertEqual(d1-d2, Decimal('-33.3'))
934 self.assertEqual(d2-d1, Decimal('33.3'))
935
936 #with other type, left
937 c = d1 - 5
938 self.assertEqual(c, Decimal('-16.1'))
939 self.assertEqual(type(c), type(d1))
940
941 #with other type, right
942 c = 5 - d1
943 self.assertEqual(c, Decimal('16.1'))
944 self.assertEqual(type(c), type(d1))
945
946 #inline with decimal
947 d1 -= d2
948 self.assertEqual(d1, Decimal('-33.3'))
949
950 #inline with other type
951 d1 -= 5
952 self.assertEqual(d1, Decimal('-38.3'))
953
954 def test_multiplication(self):
955
956 d1 = Decimal('-5')
957 d2 = Decimal('3')
958
959 #two Decimals
960 self.assertEqual(d1*d2, Decimal('-15'))
961 self.assertEqual(d2*d1, Decimal('-15'))
962
963 #with other type, left
964 c = d1 * 5
965 self.assertEqual(c, Decimal('-25'))
966 self.assertEqual(type(c), type(d1))
967
968 #with other type, right
969 c = 5 * d1
970 self.assertEqual(c, Decimal('-25'))
971 self.assertEqual(type(c), type(d1))
972
973 #inline with decimal
974 d1 *= d2
975 self.assertEqual(d1, Decimal('-15'))
976
977 #inline with other type
978 d1 *= 5
979 self.assertEqual(d1, Decimal('-75'))
980
981 def test_division(self):
982
983 d1 = Decimal('-5')
984 d2 = Decimal('2')
985
986 #two Decimals
987 self.assertEqual(d1/d2, Decimal('-2.5'))
988 self.assertEqual(d2/d1, Decimal('-0.4'))
989
990 #with other type, left
991 c = d1 / 4
992 self.assertEqual(c, Decimal('-1.25'))
993 self.assertEqual(type(c), type(d1))
994
995 #with other type, right
996 c = 4 / d1
997 self.assertEqual(c, Decimal('-0.8'))
998 self.assertEqual(type(c), type(d1))
999
1000 #inline with decimal
1001 d1 /= d2
1002 self.assertEqual(d1, Decimal('-2.5'))
1003
1004 #inline with other type
1005 d1 /= 4
1006 self.assertEqual(d1, Decimal('-0.625'))
1007
1008 def test_floor_division(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001009
1010 d1 = Decimal('5')
1011 d2 = Decimal('2')
1012
1013 #two Decimals
1014 self.assertEqual(d1//d2, Decimal('2'))
1015 self.assertEqual(d2//d1, Decimal('0'))
1016
1017 #with other type, left
1018 c = d1 // 4
1019 self.assertEqual(c, Decimal('1'))
1020 self.assertEqual(type(c), type(d1))
1021
1022 #with other type, right
1023 c = 7 // d1
1024 self.assertEqual(c, Decimal('1'))
1025 self.assertEqual(type(c), type(d1))
1026
1027 #inline with decimal
1028 d1 //= d2
1029 self.assertEqual(d1, Decimal('2'))
1030
1031 #inline with other type
1032 d1 //= 2
1033 self.assertEqual(d1, Decimal('1'))
1034
1035 def test_powering(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001036
1037 d1 = Decimal('5')
1038 d2 = Decimal('2')
1039
1040 #two Decimals
1041 self.assertEqual(d1**d2, Decimal('25'))
1042 self.assertEqual(d2**d1, Decimal('32'))
1043
1044 #with other type, left
1045 c = d1 ** 4
1046 self.assertEqual(c, Decimal('625'))
1047 self.assertEqual(type(c), type(d1))
1048
1049 #with other type, right
1050 c = 7 ** d1
1051 self.assertEqual(c, Decimal('16807'))
1052 self.assertEqual(type(c), type(d1))
1053
1054 #inline with decimal
1055 d1 **= d2
1056 self.assertEqual(d1, Decimal('25'))
1057
1058 #inline with other type
1059 d1 **= 4
1060 self.assertEqual(d1, Decimal('390625'))
1061
1062 def test_module(self):
1063
1064 d1 = Decimal('5')
1065 d2 = Decimal('2')
1066
1067 #two Decimals
1068 self.assertEqual(d1%d2, Decimal('1'))
1069 self.assertEqual(d2%d1, Decimal('2'))
1070
1071 #with other type, left
1072 c = d1 % 4
1073 self.assertEqual(c, Decimal('1'))
1074 self.assertEqual(type(c), type(d1))
1075
1076 #with other type, right
1077 c = 7 % d1
1078 self.assertEqual(c, Decimal('2'))
1079 self.assertEqual(type(c), type(d1))
1080
1081 #inline with decimal
1082 d1 %= d2
1083 self.assertEqual(d1, Decimal('1'))
1084
1085 #inline with other type
1086 d1 %= 4
1087 self.assertEqual(d1, Decimal('1'))
1088
1089 def test_floor_div_module(self):
1090
1091 d1 = Decimal('5')
1092 d2 = Decimal('2')
1093
1094 #two Decimals
1095 (p, q) = divmod(d1, d2)
1096 self.assertEqual(p, Decimal('2'))
1097 self.assertEqual(q, Decimal('1'))
1098 self.assertEqual(type(p), type(d1))
1099 self.assertEqual(type(q), type(d1))
1100
1101 #with other type, left
1102 (p, q) = divmod(d1, 4)
1103 self.assertEqual(p, Decimal('1'))
1104 self.assertEqual(q, Decimal('1'))
1105 self.assertEqual(type(p), type(d1))
1106 self.assertEqual(type(q), type(d1))
1107
1108 #with other type, right
1109 (p, q) = divmod(7, d1)
1110 self.assertEqual(p, Decimal('1'))
1111 self.assertEqual(q, Decimal('2'))
1112 self.assertEqual(type(p), type(d1))
1113 self.assertEqual(type(q), type(d1))
1114
1115 def test_unary_operators(self):
1116 self.assertEqual(+Decimal(45), Decimal(+45)) # +
1117 self.assertEqual(-Decimal(45), Decimal(-45)) # -
1118 self.assertEqual(abs(Decimal(45)), abs(Decimal(-45))) # abs
1119
Christian Heimes77c02eb2008-02-09 02:18:51 +00001120 def test_nan_comparisons(self):
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001121 # comparisons involving signaling nans signal InvalidOperation
1122
1123 # order comparisons (<, <=, >, >=) involving only quiet nans
1124 # also signal InvalidOperation
1125
1126 # equality comparisons (==, !=) involving only quiet nans
1127 # don't signal, but return False or True respectively.
1128
Christian Heimes77c02eb2008-02-09 02:18:51 +00001129 n = Decimal('NaN')
1130 s = Decimal('sNaN')
1131 i = Decimal('Inf')
1132 f = Decimal('2')
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001133
1134 qnan_pairs = (n, n), (n, i), (i, n), (n, f), (f, n)
1135 snan_pairs = (s, n), (n, s), (s, i), (i, s), (s, f), (f, s), (s, s)
1136 order_ops = operator.lt, operator.le, operator.gt, operator.ge
1137 equality_ops = operator.eq, operator.ne
1138
1139 # results when InvalidOperation is not trapped
1140 for x, y in qnan_pairs + snan_pairs:
1141 for op in order_ops + equality_ops:
1142 got = op(x, y)
1143 expected = True if op is operator.ne else False
1144 self.assertIs(expected, got,
1145 "expected {0!r} for operator.{1}({2!r}, {3!r}); "
1146 "got {4!r}".format(
1147 expected, op.__name__, x, y, got))
1148
1149 # repeat the above, but this time trap the InvalidOperation
1150 with localcontext() as ctx:
1151 ctx.traps[InvalidOperation] = 1
1152
1153 for x, y in qnan_pairs:
1154 for op in equality_ops:
1155 got = op(x, y)
1156 expected = True if op is operator.ne else False
1157 self.assertIs(expected, got,
1158 "expected {0!r} for "
1159 "operator.{1}({2!r}, {3!r}); "
1160 "got {4!r}".format(
1161 expected, op.__name__, x, y, got))
1162
1163 for x, y in snan_pairs:
1164 for op in equality_ops:
1165 self.assertRaises(InvalidOperation, operator.eq, x, y)
1166 self.assertRaises(InvalidOperation, operator.ne, x, y)
1167
1168 for x, y in qnan_pairs + snan_pairs:
1169 for op in order_ops:
1170 self.assertRaises(InvalidOperation, op, x, y)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001171
Mark Dickinson84230a12010-02-18 14:49:50 +00001172 def test_copy_sign(self):
1173 d = Decimal(1).copy_sign(Decimal(-2))
1174
1175 self.assertEqual(Decimal(1).copy_sign(-2), d)
1176 self.assertRaises(TypeError, Decimal(1).copy_sign, '-2')
1177
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001178# The following are two functions used to test threading in the next class
1179
1180def thfunc1(cls):
1181 d1 = Decimal(1)
1182 d3 = Decimal(3)
Christian Heimesfe337bf2008-03-23 21:54:12 +00001183 test1 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001184 cls.synchro.wait()
Christian Heimesfe337bf2008-03-23 21:54:12 +00001185 test2 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001186 cls.finish1.set()
Christian Heimesfe337bf2008-03-23 21:54:12 +00001187
Christian Heimes81ee3ef2008-05-04 22:42:01 +00001188 cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
1189 cls.assertEqual(test2, Decimal('0.3333333333333333333333333333'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001190 return
1191
1192def thfunc2(cls):
1193 d1 = Decimal(1)
1194 d3 = Decimal(3)
Christian Heimesfe337bf2008-03-23 21:54:12 +00001195 test1 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001196 thiscontext = getcontext()
1197 thiscontext.prec = 18
Christian Heimesfe337bf2008-03-23 21:54:12 +00001198 test2 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001199 cls.synchro.set()
1200 cls.finish2.set()
Christian Heimesfe337bf2008-03-23 21:54:12 +00001201
Christian Heimes81ee3ef2008-05-04 22:42:01 +00001202 cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
Christian Heimesfe337bf2008-03-23 21:54:12 +00001203 cls.assertEqual(test2, Decimal('0.333333333333333333'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001204 return
1205
1206
1207class DecimalUseOfContextTest(unittest.TestCase):
1208 '''Unit tests for Use of Context cases in Decimal.'''
1209
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001210 try:
1211 import threading
1212 except ImportError:
1213 threading = None
1214
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001215 # Take care executing this test from IDLE, there's an issue in threading
1216 # that hangs IDLE and I couldn't find it
1217
1218 def test_threading(self):
1219 #Test the "threading isolation" of a Context.
1220
1221 self.synchro = threading.Event()
1222 self.finish1 = threading.Event()
1223 self.finish2 = threading.Event()
1224
1225 th1 = threading.Thread(target=thfunc1, args=(self,))
1226 th2 = threading.Thread(target=thfunc2, args=(self,))
1227
1228 th1.start()
1229 th2.start()
1230
1231 self.finish1.wait()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001232 self.finish2.wait()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001233 return
1234
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001235 if threading is None:
1236 del test_threading
1237
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001238
1239class DecimalUsabilityTest(unittest.TestCase):
1240 '''Unit tests for Usability cases of Decimal.'''
1241
1242 def test_comparison_operators(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001243
1244 da = Decimal('23.42')
1245 db = Decimal('23.42')
1246 dc = Decimal('45')
1247
1248 #two Decimals
Ezio Melotti6607d512010-04-03 14:59:49 +00001249 self.assertGreater(dc, da)
1250 self.assertGreaterEqual(dc, da)
1251 self.assertLess(da, dc)
1252 self.assertLessEqual(da, dc)
Guido van Rossume61fd5b2007-07-11 12:20:59 +00001253 self.assertEqual(da, db)
Ezio Melotti6607d512010-04-03 14:59:49 +00001254 self.assertNotEqual(da, dc)
1255 self.assertLessEqual(da, db)
1256 self.assertGreaterEqual(da, db)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001257
1258 #a Decimal and an int
Ezio Melotti6607d512010-04-03 14:59:49 +00001259 self.assertGreater(dc, 23)
1260 self.assertLess(23, dc)
Guido van Rossume61fd5b2007-07-11 12:20:59 +00001261 self.assertEqual(dc, 45)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001262
1263 #a Decimal and uncomparable
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001264 self.assertNotEqual(da, 'ugly')
1265 self.assertNotEqual(da, 32.7)
1266 self.assertNotEqual(da, object())
1267 self.assertNotEqual(da, object)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001268
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001269 # sortable
Guido van Rossumc1f779c2007-07-03 08:25:58 +00001270 a = list(map(Decimal, range(100)))
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001271 b = a[:]
1272 random.shuffle(a)
1273 a.sort()
1274 self.assertEqual(a, b)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001275
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001276 def test_decimal_float_comparison(self):
1277 da = Decimal('0.25')
1278 db = Decimal('3.0')
Ezio Melotti6607d512010-04-03 14:59:49 +00001279 self.assertLess(da, 3.0)
1280 self.assertLessEqual(da, 3.0)
1281 self.assertGreater(db, 0.25)
1282 self.assertGreaterEqual(db, 0.25)
1283 self.assertNotEqual(da, 1.5)
1284 self.assertEqual(da, 0.25)
1285 self.assertGreater(3.0, da)
1286 self.assertGreaterEqual(3.0, da)
1287 self.assertLess(0.25, db)
1288 self.assertLessEqual(0.25, db)
1289 self.assertNotEqual(0.25, db)
1290 self.assertEqual(3.0, db)
1291 self.assertNotEqual(0.1, Decimal('0.1'))
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001292
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001293 def test_copy_and_deepcopy_methods(self):
1294 d = Decimal('43.24')
1295 c = copy.copy(d)
1296 self.assertEqual(id(c), id(d))
1297 dc = copy.deepcopy(d)
1298 self.assertEqual(id(dc), id(d))
1299
1300 def test_hash_method(self):
1301 #just that it's hashable
1302 hash(Decimal(23))
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001303 hash(Decimal('Infinity'))
1304 hash(Decimal('-Infinity'))
1305 hash(Decimal('nan123'))
1306 hash(Decimal('-NaN'))
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001307
1308 test_values = [Decimal(sign*(2**m + n))
1309 for m in [0, 14, 15, 16, 17, 30, 31,
1310 32, 33, 62, 63, 64, 65, 66]
1311 for n in range(-10, 10)
1312 for sign in [-1, 1]]
1313 test_values.extend([
1314 Decimal("-0"), # zeros
1315 Decimal("0.00"),
1316 Decimal("-0.000"),
1317 Decimal("0E10"),
1318 Decimal("-0E12"),
1319 Decimal("10.0"), # negative exponent
1320 Decimal("-23.00000"),
1321 Decimal("1230E100"), # positive exponent
1322 Decimal("-4.5678E50"),
1323 # a value for which hash(n) != hash(n % (2**64-1))
1324 # in Python pre-2.6
1325 Decimal(2**64 + 2**32 - 1),
1326 # selection of values which fail with the old (before
1327 # version 2.6) long.__hash__
1328 Decimal("1.634E100"),
1329 Decimal("90.697E100"),
1330 Decimal("188.83E100"),
1331 Decimal("1652.9E100"),
1332 Decimal("56531E100"),
1333 ])
1334
1335 # check that hash(d) == hash(int(d)) for integral values
1336 for value in test_values:
1337 self.assertEqual(hash(value), hash(int(value)))
1338
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001339 #the same hash that to an int
1340 self.assertEqual(hash(Decimal(23)), hash(23))
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001341 self.assertRaises(TypeError, hash, Decimal('sNaN'))
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001342 self.assertTrue(hash(Decimal('Inf')))
1343 self.assertTrue(hash(Decimal('-Inf')))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001344
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001345 # check that the hashes of a Decimal float match when they
1346 # represent exactly the same values
1347 test_strings = ['inf', '-Inf', '0.0', '-.0e1',
1348 '34.0', '2.5', '112390.625', '-0.515625']
1349 for s in test_strings:
1350 f = float(s)
1351 d = Decimal(s)
1352 self.assertEqual(hash(f), hash(d))
1353
Christian Heimes2380ac72008-01-09 00:17:24 +00001354 # check that the value of the hash doesn't depend on the
1355 # current context (issue #1757)
1356 c = getcontext()
1357 old_precision = c.prec
1358 x = Decimal("123456789.1")
1359
1360 c.prec = 6
1361 h1 = hash(x)
1362 c.prec = 10
1363 h2 = hash(x)
1364 c.prec = 16
1365 h3 = hash(x)
1366
1367 self.assertEqual(h1, h2)
1368 self.assertEqual(h1, h3)
1369 c.prec = old_precision
1370
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001371 def test_min_and_max_methods(self):
1372
1373 d1 = Decimal('15.32')
1374 d2 = Decimal('28.5')
1375 l1 = 15
1376 l2 = 28
1377
1378 #between Decimals
Ezio Melotti6607d512010-04-03 14:59:49 +00001379 self.assertIs(min(d1,d2), d1)
1380 self.assertIs(min(d2,d1), d1)
1381 self.assertIs(max(d1,d2), d2)
1382 self.assertIs(max(d2,d1), d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001383
1384 #between Decimal and long
Ezio Melotti6607d512010-04-03 14:59:49 +00001385 self.assertIs(min(d1,l2), d1)
1386 self.assertIs(min(l2,d1), d1)
1387 self.assertIs(max(l1,d2), d2)
1388 self.assertIs(max(d2,l1), d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001389
1390 def test_as_nonzero(self):
1391 #as false
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001392 self.assertFalse(Decimal(0))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001393 #as true
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001394 self.assertTrue(Decimal('0.372'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001395
1396 def test_tostring_methods(self):
1397 #Test str and repr methods.
1398
1399 d = Decimal('15.32')
1400 self.assertEqual(str(d), '15.32') # str
Christian Heimes68f5fbe2008-02-14 08:27:37 +00001401 self.assertEqual(repr(d), "Decimal('15.32')") # repr
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001402
1403 def test_tonum_methods(self):
Mark Dickinson5c2db372009-12-05 20:28:34 +00001404 #Test float and int methods.
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001405
1406 d1 = Decimal('66')
1407 d2 = Decimal('15.32')
1408
1409 #int
1410 self.assertEqual(int(d1), 66)
1411 self.assertEqual(int(d2), 15)
1412
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001413 #float
1414 self.assertEqual(float(d1), 66)
1415 self.assertEqual(float(d2), 15.32)
1416
Mark Dickinsonb27406c2008-05-09 13:42:33 +00001417 #floor
1418 test_pairs = [
1419 ('123.00', 123),
1420 ('3.2', 3),
1421 ('3.54', 3),
1422 ('3.899', 3),
1423 ('-2.3', -3),
1424 ('-11.0', -11),
1425 ('0.0', 0),
1426 ('-0E3', 0),
1427 ]
1428 for d, i in test_pairs:
1429 self.assertEqual(math.floor(Decimal(d)), i)
1430 self.assertRaises(ValueError, math.floor, Decimal('-NaN'))
1431 self.assertRaises(ValueError, math.floor, Decimal('sNaN'))
1432 self.assertRaises(ValueError, math.floor, Decimal('NaN123'))
1433 self.assertRaises(OverflowError, math.floor, Decimal('Inf'))
1434 self.assertRaises(OverflowError, math.floor, Decimal('-Inf'))
1435
1436 #ceiling
1437 test_pairs = [
1438 ('123.00', 123),
1439 ('3.2', 4),
1440 ('3.54', 4),
1441 ('3.899', 4),
1442 ('-2.3', -2),
1443 ('-11.0', -11),
1444 ('0.0', 0),
1445 ('-0E3', 0),
1446 ]
1447 for d, i in test_pairs:
1448 self.assertEqual(math.ceil(Decimal(d)), i)
1449 self.assertRaises(ValueError, math.ceil, Decimal('-NaN'))
1450 self.assertRaises(ValueError, math.ceil, Decimal('sNaN'))
1451 self.assertRaises(ValueError, math.ceil, Decimal('NaN123'))
1452 self.assertRaises(OverflowError, math.ceil, Decimal('Inf'))
1453 self.assertRaises(OverflowError, math.ceil, Decimal('-Inf'))
1454
1455 #round, single argument
1456 test_pairs = [
1457 ('123.00', 123),
1458 ('3.2', 3),
1459 ('3.54', 4),
1460 ('3.899', 4),
1461 ('-2.3', -2),
1462 ('-11.0', -11),
1463 ('0.0', 0),
1464 ('-0E3', 0),
1465 ('-3.5', -4),
1466 ('-2.5', -2),
1467 ('-1.5', -2),
1468 ('-0.5', 0),
1469 ('0.5', 0),
1470 ('1.5', 2),
1471 ('2.5', 2),
1472 ('3.5', 4),
1473 ]
1474 for d, i in test_pairs:
1475 self.assertEqual(round(Decimal(d)), i)
1476 self.assertRaises(ValueError, round, Decimal('-NaN'))
1477 self.assertRaises(ValueError, round, Decimal('sNaN'))
1478 self.assertRaises(ValueError, round, Decimal('NaN123'))
1479 self.assertRaises(OverflowError, round, Decimal('Inf'))
1480 self.assertRaises(OverflowError, round, Decimal('-Inf'))
1481
1482 #round, two arguments; this is essentially equivalent
1483 #to quantize, which is already extensively tested
1484 test_triples = [
1485 ('123.456', -4, '0E+4'),
1486 ('123.456', -3, '0E+3'),
1487 ('123.456', -2, '1E+2'),
1488 ('123.456', -1, '1.2E+2'),
1489 ('123.456', 0, '123'),
1490 ('123.456', 1, '123.5'),
1491 ('123.456', 2, '123.46'),
1492 ('123.456', 3, '123.456'),
1493 ('123.456', 4, '123.4560'),
1494 ('123.455', 2, '123.46'),
1495 ('123.445', 2, '123.44'),
1496 ('Inf', 4, 'NaN'),
1497 ('-Inf', -23, 'NaN'),
1498 ('sNaN314', 3, 'NaN314'),
1499 ]
1500 for d, n, r in test_triples:
1501 self.assertEqual(str(round(Decimal(d), n)), r)
1502
1503
1504
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001505 def test_eval_round_trip(self):
1506
1507 #with zero
1508 d = Decimal( (0, (0,), 0) )
1509 self.assertEqual(d, eval(repr(d)))
1510
1511 #int
1512 d = Decimal( (1, (4, 5), 0) )
1513 self.assertEqual(d, eval(repr(d)))
1514
1515 #float
1516 d = Decimal( (0, (4, 5, 3, 4), -2) )
1517 self.assertEqual(d, eval(repr(d)))
1518
1519 #weird
1520 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1521 self.assertEqual(d, eval(repr(d)))
1522
1523 def test_as_tuple(self):
1524
1525 #with zero
1526 d = Decimal(0)
1527 self.assertEqual(d.as_tuple(), (0, (0,), 0) )
1528
1529 #int
1530 d = Decimal(-45)
1531 self.assertEqual(d.as_tuple(), (1, (4, 5), 0) )
1532
1533 #complicated string
1534 d = Decimal("-4.34913534E-17")
1535 self.assertEqual(d.as_tuple(), (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1536
1537 #inf
1538 d = Decimal("Infinity")
1539 self.assertEqual(d.as_tuple(), (0, (0,), 'F') )
1540
Guido van Rossum8ce8a782007-11-01 19:42:39 +00001541 #leading zeros in coefficient should be stripped
1542 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), -2) )
1543 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), -2) )
1544 d = Decimal( (1, (0, 0, 0), 37) )
1545 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1546 d = Decimal( (1, (), 37) )
1547 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1548
1549 #leading zeros in NaN diagnostic info should be stripped
1550 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), 'n') )
1551 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), 'n') )
1552 d = Decimal( (1, (0, 0, 0), 'N') )
1553 self.assertEqual(d.as_tuple(), (1, (), 'N') )
1554 d = Decimal( (1, (), 'n') )
1555 self.assertEqual(d.as_tuple(), (1, (), 'n') )
1556
1557 #coefficient in infinity should be ignored
1558 d = Decimal( (0, (4, 5, 3, 4), 'F') )
1559 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
1560 d = Decimal( (1, (0, 2, 7, 1), 'F') )
1561 self.assertEqual(d.as_tuple(), (1, (0,), 'F'))
1562
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001563 def test_immutability_operations(self):
1564 # Do operations and check that it didn't change change internal objects.
1565
1566 d1 = Decimal('-25e55')
1567 b1 = Decimal('-25e55')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001568 d2 = Decimal('33e+33')
1569 b2 = Decimal('33e+33')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001570
1571 def checkSameDec(operation, useOther=False):
1572 if useOther:
1573 eval("d1." + operation + "(d2)")
1574 self.assertEqual(d1._sign, b1._sign)
1575 self.assertEqual(d1._int, b1._int)
1576 self.assertEqual(d1._exp, b1._exp)
1577 self.assertEqual(d2._sign, b2._sign)
1578 self.assertEqual(d2._int, b2._int)
1579 self.assertEqual(d2._exp, b2._exp)
1580 else:
1581 eval("d1." + operation + "()")
1582 self.assertEqual(d1._sign, b1._sign)
1583 self.assertEqual(d1._int, b1._int)
1584 self.assertEqual(d1._exp, b1._exp)
1585 return
1586
1587 Decimal(d1)
1588 self.assertEqual(d1._sign, b1._sign)
1589 self.assertEqual(d1._int, b1._int)
1590 self.assertEqual(d1._exp, b1._exp)
1591
1592 checkSameDec("__abs__")
1593 checkSameDec("__add__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001594 checkSameDec("__divmod__", True)
Christian Heimes77c02eb2008-02-09 02:18:51 +00001595 checkSameDec("__eq__", True)
1596 checkSameDec("__ne__", True)
1597 checkSameDec("__le__", True)
1598 checkSameDec("__lt__", True)
1599 checkSameDec("__ge__", True)
1600 checkSameDec("__gt__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001601 checkSameDec("__float__")
1602 checkSameDec("__floordiv__", True)
1603 checkSameDec("__hash__")
1604 checkSameDec("__int__")
Christian Heimes969fe572008-01-25 11:23:10 +00001605 checkSameDec("__trunc__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001606 checkSameDec("__mod__", True)
1607 checkSameDec("__mul__", True)
1608 checkSameDec("__neg__")
Jack Diederich4dafcc42006-11-28 19:15:13 +00001609 checkSameDec("__bool__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001610 checkSameDec("__pos__")
1611 checkSameDec("__pow__", True)
1612 checkSameDec("__radd__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001613 checkSameDec("__rdivmod__", True)
1614 checkSameDec("__repr__")
1615 checkSameDec("__rfloordiv__", True)
1616 checkSameDec("__rmod__", True)
1617 checkSameDec("__rmul__", True)
1618 checkSameDec("__rpow__", True)
1619 checkSameDec("__rsub__", True)
1620 checkSameDec("__str__")
1621 checkSameDec("__sub__", True)
1622 checkSameDec("__truediv__", True)
1623 checkSameDec("adjusted")
1624 checkSameDec("as_tuple")
1625 checkSameDec("compare", True)
1626 checkSameDec("max", True)
1627 checkSameDec("min", True)
1628 checkSameDec("normalize")
1629 checkSameDec("quantize", True)
1630 checkSameDec("remainder_near", True)
1631 checkSameDec("same_quantum", True)
1632 checkSameDec("sqrt")
1633 checkSameDec("to_eng_string")
1634 checkSameDec("to_integral")
1635
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001636 def test_subclassing(self):
1637 # Different behaviours when subclassing Decimal
1638
1639 class MyDecimal(Decimal):
1640 pass
1641
1642 d1 = MyDecimal(1)
1643 d2 = MyDecimal(2)
1644 d = d1 + d2
Ezio Melotti6607d512010-04-03 14:59:49 +00001645 self.assertIs(type(d), Decimal)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001646
1647 d = d1.max(d2)
Ezio Melotti6607d512010-04-03 14:59:49 +00001648 self.assertIs(type(d), Decimal)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001649
Christian Heimes0348fb62008-03-26 12:55:56 +00001650 def test_implicit_context(self):
1651 # Check results when context given implicitly. (Issue 2478)
1652 c = getcontext()
1653 self.assertEqual(str(Decimal(0).sqrt()),
1654 str(c.sqrt(Decimal(0))))
1655
Mark Dickinsona2d1fe02009-10-29 12:23:02 +00001656 def test_conversions_from_int(self):
1657 # Check that methods taking a second Decimal argument will
1658 # always accept an integer in place of a Decimal.
1659 self.assertEqual(Decimal(4).compare(3),
1660 Decimal(4).compare(Decimal(3)))
1661 self.assertEqual(Decimal(4).compare_signal(3),
1662 Decimal(4).compare_signal(Decimal(3)))
1663 self.assertEqual(Decimal(4).compare_total(3),
1664 Decimal(4).compare_total(Decimal(3)))
1665 self.assertEqual(Decimal(4).compare_total_mag(3),
1666 Decimal(4).compare_total_mag(Decimal(3)))
1667 self.assertEqual(Decimal(10101).logical_and(1001),
1668 Decimal(10101).logical_and(Decimal(1001)))
1669 self.assertEqual(Decimal(10101).logical_or(1001),
1670 Decimal(10101).logical_or(Decimal(1001)))
1671 self.assertEqual(Decimal(10101).logical_xor(1001),
1672 Decimal(10101).logical_xor(Decimal(1001)))
1673 self.assertEqual(Decimal(567).max(123),
1674 Decimal(567).max(Decimal(123)))
1675 self.assertEqual(Decimal(567).max_mag(123),
1676 Decimal(567).max_mag(Decimal(123)))
1677 self.assertEqual(Decimal(567).min(123),
1678 Decimal(567).min(Decimal(123)))
1679 self.assertEqual(Decimal(567).min_mag(123),
1680 Decimal(567).min_mag(Decimal(123)))
1681 self.assertEqual(Decimal(567).next_toward(123),
1682 Decimal(567).next_toward(Decimal(123)))
1683 self.assertEqual(Decimal(1234).quantize(100),
1684 Decimal(1234).quantize(Decimal(100)))
1685 self.assertEqual(Decimal(768).remainder_near(1234),
1686 Decimal(768).remainder_near(Decimal(1234)))
1687 self.assertEqual(Decimal(123).rotate(1),
1688 Decimal(123).rotate(Decimal(1)))
1689 self.assertEqual(Decimal(1234).same_quantum(1000),
1690 Decimal(1234).same_quantum(Decimal(1000)))
1691 self.assertEqual(Decimal('9.123').scaleb(-100),
1692 Decimal('9.123').scaleb(Decimal(-100)))
1693 self.assertEqual(Decimal(456).shift(-1),
1694 Decimal(456).shift(Decimal(-1)))
1695
1696 self.assertEqual(Decimal(-12).fma(Decimal(45), 67),
1697 Decimal(-12).fma(Decimal(45), Decimal(67)))
1698 self.assertEqual(Decimal(-12).fma(45, 67),
1699 Decimal(-12).fma(Decimal(45), Decimal(67)))
1700 self.assertEqual(Decimal(-12).fma(45, Decimal(67)),
1701 Decimal(-12).fma(Decimal(45), Decimal(67)))
1702
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001703
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001704class DecimalPythonAPItests(unittest.TestCase):
1705
Raymond Hettinger82417ca2009-02-03 03:54:28 +00001706 def test_abc(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001707 self.assertTrue(issubclass(Decimal, numbers.Number))
Ezio Melotti6607d512010-04-03 14:59:49 +00001708 self.assertFalse(issubclass(Decimal, numbers.Real))
Ezio Melottie9615932010-01-24 19:26:24 +00001709 self.assertIsInstance(Decimal(0), numbers.Number)
1710 self.assertNotIsInstance(Decimal(0), numbers.Real)
Raymond Hettinger82417ca2009-02-03 03:54:28 +00001711
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001712 def test_pickle(self):
1713 d = Decimal('-3.141590000')
1714 p = pickle.dumps(d)
1715 e = pickle.loads(p)
1716 self.assertEqual(d, e)
1717
Raymond Hettinger5548be22004-07-05 18:49:38 +00001718 def test_int(self):
Raymond Hettinger605ed022004-11-24 07:28:48 +00001719 for x in range(-250, 250):
1720 s = '%0.2f' % (x / 100.0)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001721 # should work the same as for floats
1722 self.assertEqual(int(Decimal(s)), int(float(s)))
Raymond Hettinger605ed022004-11-24 07:28:48 +00001723 # should work the same as to_integral in the ROUND_DOWN mode
Raymond Hettinger5548be22004-07-05 18:49:38 +00001724 d = Decimal(s)
Raymond Hettinger605ed022004-11-24 07:28:48 +00001725 r = d.to_integral(ROUND_DOWN)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001726 self.assertEqual(Decimal(int(d)), r)
1727
Mark Dickinson825fce32009-09-07 18:08:12 +00001728 self.assertRaises(ValueError, int, Decimal('-nan'))
1729 self.assertRaises(ValueError, int, Decimal('snan'))
1730 self.assertRaises(OverflowError, int, Decimal('inf'))
1731 self.assertRaises(OverflowError, int, Decimal('-inf'))
1732
Christian Heimes969fe572008-01-25 11:23:10 +00001733 def test_trunc(self):
1734 for x in range(-250, 250):
1735 s = '%0.2f' % (x / 100.0)
1736 # should work the same as for floats
1737 self.assertEqual(int(Decimal(s)), int(float(s)))
1738 # should work the same as to_integral in the ROUND_DOWN mode
1739 d = Decimal(s)
1740 r = d.to_integral(ROUND_DOWN)
Christian Heimes400adb02008-02-01 08:12:03 +00001741 self.assertEqual(Decimal(math.trunc(d)), r)
Christian Heimes969fe572008-01-25 11:23:10 +00001742
Raymond Hettinger771ed762009-01-03 19:20:32 +00001743 def test_from_float(self):
1744
1745 class MyDecimal(Decimal):
1746 pass
1747
1748 r = MyDecimal.from_float(0.1)
1749 self.assertEqual(type(r), MyDecimal)
1750 self.assertEqual(str(r),
1751 '0.1000000000000000055511151231257827021181583404541015625')
1752 bigint = 12345678901234567890123456789
1753 self.assertEqual(MyDecimal.from_float(bigint), MyDecimal(bigint))
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001754 self.assertTrue(MyDecimal.from_float(float('nan')).is_qnan())
1755 self.assertTrue(MyDecimal.from_float(float('inf')).is_infinite())
1756 self.assertTrue(MyDecimal.from_float(float('-inf')).is_infinite())
Raymond Hettinger771ed762009-01-03 19:20:32 +00001757 self.assertEqual(str(MyDecimal.from_float(float('nan'))),
1758 str(Decimal('NaN')))
1759 self.assertEqual(str(MyDecimal.from_float(float('inf'))),
1760 str(Decimal('Infinity')))
1761 self.assertEqual(str(MyDecimal.from_float(float('-inf'))),
1762 str(Decimal('-Infinity')))
1763 self.assertRaises(TypeError, MyDecimal.from_float, 'abc')
1764 for i in range(200):
1765 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
1766 self.assertEqual(x, float(MyDecimal.from_float(x))) # roundtrip
1767
1768 def test_create_decimal_from_float(self):
1769 context = Context(prec=5, rounding=ROUND_DOWN)
1770 self.assertEqual(
1771 context.create_decimal_from_float(math.pi),
1772 Decimal('3.1415')
1773 )
1774 context = Context(prec=5, rounding=ROUND_UP)
1775 self.assertEqual(
1776 context.create_decimal_from_float(math.pi),
1777 Decimal('3.1416')
1778 )
1779 context = Context(prec=5, traps=[Inexact])
1780 self.assertRaises(
1781 Inexact,
1782 context.create_decimal_from_float,
1783 math.pi
1784 )
1785 self.assertEqual(repr(context.create_decimal_from_float(-0.0)),
1786 "Decimal('-0')")
1787 self.assertEqual(repr(context.create_decimal_from_float(1.0)),
1788 "Decimal('1')")
1789 self.assertEqual(repr(context.create_decimal_from_float(10)),
1790 "Decimal('10')")
1791
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00001792class ContextAPItests(unittest.TestCase):
1793
1794 def test_pickle(self):
1795 c = Context()
1796 e = pickle.loads(pickle.dumps(c))
1797 for k in vars(c):
1798 v1 = vars(c)[k]
1799 v2 = vars(e)[k]
1800 self.assertEqual(v1, v2)
1801
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001802 def test_equality_with_other_types(self):
Benjamin Peterson577473f2010-01-19 00:09:57 +00001803 self.assertIn(Decimal(10), ['a', 1.0, Decimal(10), (1,2), {}])
1804 self.assertNotIn(Decimal(10), ['a', 1.0, (1,2), {}])
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001805
Raymond Hettinger955d2b22004-08-08 20:17:45 +00001806 def test_copy(self):
1807 # All copies should be deep
1808 c = Context()
1809 d = c.copy()
1810 self.assertNotEqual(id(c), id(d))
1811 self.assertNotEqual(id(c.flags), id(d.flags))
1812 self.assertNotEqual(id(c.traps), id(d.traps))
1813
Mark Dickinsonb1d8e322010-05-22 18:35:36 +00001814 def test__clamp(self):
1815 # In Python 3.2, the private attribute `_clamp` was made
1816 # public (issue 8540), with the old `_clamp` becoming a
1817 # property wrapping `clamp`. For the duration of Python 3.2
1818 # only, the attribute should be gettable/settable via both
1819 # `clamp` and `_clamp`; in Python 3.3, `_clamp` should be
1820 # removed.
1821 c = Context(clamp = 0)
1822 self.assertEqual(c.clamp, 0)
1823
1824 with check_warnings(("", DeprecationWarning)):
1825 c._clamp = 1
1826 self.assertEqual(c.clamp, 1)
1827 with check_warnings(("", DeprecationWarning)):
1828 self.assertEqual(c._clamp, 1)
1829 c.clamp = 0
1830 self.assertEqual(c.clamp, 0)
1831 with check_warnings(("", DeprecationWarning)):
1832 self.assertEqual(c._clamp, 0)
1833
Mark Dickinson84230a12010-02-18 14:49:50 +00001834 def test_abs(self):
1835 c = Context()
1836 d = c.abs(Decimal(-1))
1837 self.assertEqual(c.abs(-1), d)
1838 self.assertRaises(TypeError, c.abs, '-1')
1839
1840 def test_add(self):
1841 c = Context()
1842 d = c.add(Decimal(1), Decimal(1))
1843 self.assertEqual(c.add(1, 1), d)
1844 self.assertEqual(c.add(Decimal(1), 1), d)
1845 self.assertEqual(c.add(1, Decimal(1)), d)
1846 self.assertRaises(TypeError, c.add, '1', 1)
1847 self.assertRaises(TypeError, c.add, 1, '1')
1848
1849 def test_compare(self):
1850 c = Context()
1851 d = c.compare(Decimal(1), Decimal(1))
1852 self.assertEqual(c.compare(1, 1), d)
1853 self.assertEqual(c.compare(Decimal(1), 1), d)
1854 self.assertEqual(c.compare(1, Decimal(1)), d)
1855 self.assertRaises(TypeError, c.compare, '1', 1)
1856 self.assertRaises(TypeError, c.compare, 1, '1')
1857
1858 def test_compare_signal(self):
1859 c = Context()
1860 d = c.compare_signal(Decimal(1), Decimal(1))
1861 self.assertEqual(c.compare_signal(1, 1), d)
1862 self.assertEqual(c.compare_signal(Decimal(1), 1), d)
1863 self.assertEqual(c.compare_signal(1, Decimal(1)), d)
1864 self.assertRaises(TypeError, c.compare_signal, '1', 1)
1865 self.assertRaises(TypeError, c.compare_signal, 1, '1')
1866
1867 def test_compare_total(self):
1868 c = Context()
1869 d = c.compare_total(Decimal(1), Decimal(1))
1870 self.assertEqual(c.compare_total(1, 1), d)
1871 self.assertEqual(c.compare_total(Decimal(1), 1), d)
1872 self.assertEqual(c.compare_total(1, Decimal(1)), d)
1873 self.assertRaises(TypeError, c.compare_total, '1', 1)
1874 self.assertRaises(TypeError, c.compare_total, 1, '1')
1875
1876 def test_compare_total_mag(self):
1877 c = Context()
1878 d = c.compare_total_mag(Decimal(1), Decimal(1))
1879 self.assertEqual(c.compare_total_mag(1, 1), d)
1880 self.assertEqual(c.compare_total_mag(Decimal(1), 1), d)
1881 self.assertEqual(c.compare_total_mag(1, Decimal(1)), d)
1882 self.assertRaises(TypeError, c.compare_total_mag, '1', 1)
1883 self.assertRaises(TypeError, c.compare_total_mag, 1, '1')
1884
1885 def test_copy_abs(self):
1886 c = Context()
1887 d = c.copy_abs(Decimal(-1))
1888 self.assertEqual(c.copy_abs(-1), d)
1889 self.assertRaises(TypeError, c.copy_abs, '-1')
1890
1891 def test_copy_decimal(self):
1892 c = Context()
1893 d = c.copy_decimal(Decimal(-1))
1894 self.assertEqual(c.copy_decimal(-1), d)
1895 self.assertRaises(TypeError, c.copy_decimal, '-1')
1896
1897 def test_copy_negate(self):
1898 c = Context()
1899 d = c.copy_negate(Decimal(-1))
1900 self.assertEqual(c.copy_negate(-1), d)
1901 self.assertRaises(TypeError, c.copy_negate, '-1')
1902
1903 def test_copy_sign(self):
1904 c = Context()
1905 d = c.copy_sign(Decimal(1), Decimal(-2))
1906 self.assertEqual(c.copy_sign(1, -2), d)
1907 self.assertEqual(c.copy_sign(Decimal(1), -2), d)
1908 self.assertEqual(c.copy_sign(1, Decimal(-2)), d)
1909 self.assertRaises(TypeError, c.copy_sign, '1', -2)
1910 self.assertRaises(TypeError, c.copy_sign, 1, '-2')
1911
1912 def test_divide(self):
1913 c = Context()
1914 d = c.divide(Decimal(1), Decimal(2))
1915 self.assertEqual(c.divide(1, 2), d)
1916 self.assertEqual(c.divide(Decimal(1), 2), d)
1917 self.assertEqual(c.divide(1, Decimal(2)), d)
1918 self.assertRaises(TypeError, c.divide, '1', 2)
1919 self.assertRaises(TypeError, c.divide, 1, '2')
1920
1921 def test_divide_int(self):
1922 c = Context()
1923 d = c.divide_int(Decimal(1), Decimal(2))
1924 self.assertEqual(c.divide_int(1, 2), d)
1925 self.assertEqual(c.divide_int(Decimal(1), 2), d)
1926 self.assertEqual(c.divide_int(1, Decimal(2)), d)
1927 self.assertRaises(TypeError, c.divide_int, '1', 2)
1928 self.assertRaises(TypeError, c.divide_int, 1, '2')
1929
1930 def test_divmod(self):
1931 c = Context()
1932 d = c.divmod(Decimal(1), Decimal(2))
1933 self.assertEqual(c.divmod(1, 2), d)
1934 self.assertEqual(c.divmod(Decimal(1), 2), d)
1935 self.assertEqual(c.divmod(1, Decimal(2)), d)
1936 self.assertRaises(TypeError, c.divmod, '1', 2)
1937 self.assertRaises(TypeError, c.divmod, 1, '2')
1938
1939 def test_exp(self):
1940 c = Context()
1941 d = c.exp(Decimal(10))
1942 self.assertEqual(c.exp(10), d)
1943 self.assertRaises(TypeError, c.exp, '10')
1944
1945 def test_fma(self):
1946 c = Context()
1947 d = c.fma(Decimal(2), Decimal(3), Decimal(4))
1948 self.assertEqual(c.fma(2, 3, 4), d)
1949 self.assertEqual(c.fma(Decimal(2), 3, 4), d)
1950 self.assertEqual(c.fma(2, Decimal(3), 4), d)
1951 self.assertEqual(c.fma(2, 3, Decimal(4)), d)
1952 self.assertEqual(c.fma(Decimal(2), Decimal(3), 4), d)
1953 self.assertRaises(TypeError, c.fma, '2', 3, 4)
1954 self.assertRaises(TypeError, c.fma, 2, '3', 4)
1955 self.assertRaises(TypeError, c.fma, 2, 3, '4')
1956
1957 def test_is_finite(self):
1958 c = Context()
1959 d = c.is_finite(Decimal(10))
1960 self.assertEqual(c.is_finite(10), d)
1961 self.assertRaises(TypeError, c.is_finite, '10')
1962
1963 def test_is_infinite(self):
1964 c = Context()
1965 d = c.is_infinite(Decimal(10))
1966 self.assertEqual(c.is_infinite(10), d)
1967 self.assertRaises(TypeError, c.is_infinite, '10')
1968
1969 def test_is_nan(self):
1970 c = Context()
1971 d = c.is_nan(Decimal(10))
1972 self.assertEqual(c.is_nan(10), d)
1973 self.assertRaises(TypeError, c.is_nan, '10')
1974
1975 def test_is_normal(self):
1976 c = Context()
1977 d = c.is_normal(Decimal(10))
1978 self.assertEqual(c.is_normal(10), d)
1979 self.assertRaises(TypeError, c.is_normal, '10')
1980
1981 def test_is_qnan(self):
1982 c = Context()
1983 d = c.is_qnan(Decimal(10))
1984 self.assertEqual(c.is_qnan(10), d)
1985 self.assertRaises(TypeError, c.is_qnan, '10')
1986
1987 def test_is_signed(self):
1988 c = Context()
1989 d = c.is_signed(Decimal(10))
1990 self.assertEqual(c.is_signed(10), d)
1991 self.assertRaises(TypeError, c.is_signed, '10')
1992
1993 def test_is_snan(self):
1994 c = Context()
1995 d = c.is_snan(Decimal(10))
1996 self.assertEqual(c.is_snan(10), d)
1997 self.assertRaises(TypeError, c.is_snan, '10')
1998
1999 def test_is_subnormal(self):
2000 c = Context()
2001 d = c.is_subnormal(Decimal(10))
2002 self.assertEqual(c.is_subnormal(10), d)
2003 self.assertRaises(TypeError, c.is_subnormal, '10')
2004
2005 def test_is_zero(self):
2006 c = Context()
2007 d = c.is_zero(Decimal(10))
2008 self.assertEqual(c.is_zero(10), d)
2009 self.assertRaises(TypeError, c.is_zero, '10')
2010
2011 def test_ln(self):
2012 c = Context()
2013 d = c.ln(Decimal(10))
2014 self.assertEqual(c.ln(10), d)
2015 self.assertRaises(TypeError, c.ln, '10')
2016
2017 def test_log10(self):
2018 c = Context()
2019 d = c.log10(Decimal(10))
2020 self.assertEqual(c.log10(10), d)
2021 self.assertRaises(TypeError, c.log10, '10')
2022
2023 def test_logb(self):
2024 c = Context()
2025 d = c.logb(Decimal(10))
2026 self.assertEqual(c.logb(10), d)
2027 self.assertRaises(TypeError, c.logb, '10')
2028
2029 def test_logical_and(self):
2030 c = Context()
2031 d = c.logical_and(Decimal(1), Decimal(1))
2032 self.assertEqual(c.logical_and(1, 1), d)
2033 self.assertEqual(c.logical_and(Decimal(1), 1), d)
2034 self.assertEqual(c.logical_and(1, Decimal(1)), d)
2035 self.assertRaises(TypeError, c.logical_and, '1', 1)
2036 self.assertRaises(TypeError, c.logical_and, 1, '1')
2037
2038 def test_logical_invert(self):
2039 c = Context()
2040 d = c.logical_invert(Decimal(1000))
2041 self.assertEqual(c.logical_invert(1000), d)
2042 self.assertRaises(TypeError, c.logical_invert, '1000')
2043
2044 def test_logical_or(self):
2045 c = Context()
2046 d = c.logical_or(Decimal(1), Decimal(1))
2047 self.assertEqual(c.logical_or(1, 1), d)
2048 self.assertEqual(c.logical_or(Decimal(1), 1), d)
2049 self.assertEqual(c.logical_or(1, Decimal(1)), d)
2050 self.assertRaises(TypeError, c.logical_or, '1', 1)
2051 self.assertRaises(TypeError, c.logical_or, 1, '1')
2052
2053 def test_logical_xor(self):
2054 c = Context()
2055 d = c.logical_xor(Decimal(1), Decimal(1))
2056 self.assertEqual(c.logical_xor(1, 1), d)
2057 self.assertEqual(c.logical_xor(Decimal(1), 1), d)
2058 self.assertEqual(c.logical_xor(1, Decimal(1)), d)
2059 self.assertRaises(TypeError, c.logical_xor, '1', 1)
2060 self.assertRaises(TypeError, c.logical_xor, 1, '1')
2061
2062 def test_max(self):
2063 c = Context()
2064 d = c.max(Decimal(1), Decimal(2))
2065 self.assertEqual(c.max(1, 2), d)
2066 self.assertEqual(c.max(Decimal(1), 2), d)
2067 self.assertEqual(c.max(1, Decimal(2)), d)
2068 self.assertRaises(TypeError, c.max, '1', 2)
2069 self.assertRaises(TypeError, c.max, 1, '2')
2070
2071 def test_max_mag(self):
2072 c = Context()
2073 d = c.max_mag(Decimal(1), Decimal(2))
2074 self.assertEqual(c.max_mag(1, 2), d)
2075 self.assertEqual(c.max_mag(Decimal(1), 2), d)
2076 self.assertEqual(c.max_mag(1, Decimal(2)), d)
2077 self.assertRaises(TypeError, c.max_mag, '1', 2)
2078 self.assertRaises(TypeError, c.max_mag, 1, '2')
2079
2080 def test_min(self):
2081 c = Context()
2082 d = c.min(Decimal(1), Decimal(2))
2083 self.assertEqual(c.min(1, 2), d)
2084 self.assertEqual(c.min(Decimal(1), 2), d)
2085 self.assertEqual(c.min(1, Decimal(2)), d)
2086 self.assertRaises(TypeError, c.min, '1', 2)
2087 self.assertRaises(TypeError, c.min, 1, '2')
2088
2089 def test_min_mag(self):
2090 c = Context()
2091 d = c.min_mag(Decimal(1), Decimal(2))
2092 self.assertEqual(c.min_mag(1, 2), d)
2093 self.assertEqual(c.min_mag(Decimal(1), 2), d)
2094 self.assertEqual(c.min_mag(1, Decimal(2)), d)
2095 self.assertRaises(TypeError, c.min_mag, '1', 2)
2096 self.assertRaises(TypeError, c.min_mag, 1, '2')
2097
2098 def test_minus(self):
2099 c = Context()
2100 d = c.minus(Decimal(10))
2101 self.assertEqual(c.minus(10), d)
2102 self.assertRaises(TypeError, c.minus, '10')
2103
2104 def test_multiply(self):
2105 c = Context()
2106 d = c.multiply(Decimal(1), Decimal(2))
2107 self.assertEqual(c.multiply(1, 2), d)
2108 self.assertEqual(c.multiply(Decimal(1), 2), d)
2109 self.assertEqual(c.multiply(1, Decimal(2)), d)
2110 self.assertRaises(TypeError, c.multiply, '1', 2)
2111 self.assertRaises(TypeError, c.multiply, 1, '2')
2112
2113 def test_next_minus(self):
2114 c = Context()
2115 d = c.next_minus(Decimal(10))
2116 self.assertEqual(c.next_minus(10), d)
2117 self.assertRaises(TypeError, c.next_minus, '10')
2118
2119 def test_next_plus(self):
2120 c = Context()
2121 d = c.next_plus(Decimal(10))
2122 self.assertEqual(c.next_plus(10), d)
2123 self.assertRaises(TypeError, c.next_plus, '10')
2124
2125 def test_next_toward(self):
2126 c = Context()
2127 d = c.next_toward(Decimal(1), Decimal(2))
2128 self.assertEqual(c.next_toward(1, 2), d)
2129 self.assertEqual(c.next_toward(Decimal(1), 2), d)
2130 self.assertEqual(c.next_toward(1, Decimal(2)), d)
2131 self.assertRaises(TypeError, c.next_toward, '1', 2)
2132 self.assertRaises(TypeError, c.next_toward, 1, '2')
2133
2134 def test_normalize(self):
2135 c = Context()
2136 d = c.normalize(Decimal(10))
2137 self.assertEqual(c.normalize(10), d)
2138 self.assertRaises(TypeError, c.normalize, '10')
2139
2140 def test_number_class(self):
2141 c = Context()
2142 self.assertEqual(c.number_class(123), c.number_class(Decimal(123)))
2143 self.assertEqual(c.number_class(0), c.number_class(Decimal(0)))
2144 self.assertEqual(c.number_class(-45), c.number_class(Decimal(-45)))
2145
2146 def test_power(self):
2147 c = Context()
2148 d = c.power(Decimal(1), Decimal(4), Decimal(2))
2149 self.assertEqual(c.power(1, 4, 2), d)
2150 self.assertEqual(c.power(Decimal(1), 4, 2), d)
2151 self.assertEqual(c.power(1, Decimal(4), 2), d)
2152 self.assertEqual(c.power(1, 4, Decimal(2)), d)
2153 self.assertEqual(c.power(Decimal(1), Decimal(4), 2), d)
2154 self.assertRaises(TypeError, c.power, '1', 4, 2)
2155 self.assertRaises(TypeError, c.power, 1, '4', 2)
2156 self.assertRaises(TypeError, c.power, 1, 4, '2')
2157
2158 def test_plus(self):
2159 c = Context()
2160 d = c.plus(Decimal(10))
2161 self.assertEqual(c.plus(10), d)
2162 self.assertRaises(TypeError, c.plus, '10')
2163
2164 def test_quantize(self):
2165 c = Context()
2166 d = c.quantize(Decimal(1), Decimal(2))
2167 self.assertEqual(c.quantize(1, 2), d)
2168 self.assertEqual(c.quantize(Decimal(1), 2), d)
2169 self.assertEqual(c.quantize(1, Decimal(2)), d)
2170 self.assertRaises(TypeError, c.quantize, '1', 2)
2171 self.assertRaises(TypeError, c.quantize, 1, '2')
2172
2173 def test_remainder(self):
2174 c = Context()
2175 d = c.remainder(Decimal(1), Decimal(2))
2176 self.assertEqual(c.remainder(1, 2), d)
2177 self.assertEqual(c.remainder(Decimal(1), 2), d)
2178 self.assertEqual(c.remainder(1, Decimal(2)), d)
2179 self.assertRaises(TypeError, c.remainder, '1', 2)
2180 self.assertRaises(TypeError, c.remainder, 1, '2')
2181
2182 def test_remainder_near(self):
2183 c = Context()
2184 d = c.remainder_near(Decimal(1), Decimal(2))
2185 self.assertEqual(c.remainder_near(1, 2), d)
2186 self.assertEqual(c.remainder_near(Decimal(1), 2), d)
2187 self.assertEqual(c.remainder_near(1, Decimal(2)), d)
2188 self.assertRaises(TypeError, c.remainder_near, '1', 2)
2189 self.assertRaises(TypeError, c.remainder_near, 1, '2')
2190
2191 def test_rotate(self):
2192 c = Context()
2193 d = c.rotate(Decimal(1), Decimal(2))
2194 self.assertEqual(c.rotate(1, 2), d)
2195 self.assertEqual(c.rotate(Decimal(1), 2), d)
2196 self.assertEqual(c.rotate(1, Decimal(2)), d)
2197 self.assertRaises(TypeError, c.rotate, '1', 2)
2198 self.assertRaises(TypeError, c.rotate, 1, '2')
2199
2200 def test_sqrt(self):
2201 c = Context()
2202 d = c.sqrt(Decimal(10))
2203 self.assertEqual(c.sqrt(10), d)
2204 self.assertRaises(TypeError, c.sqrt, '10')
2205
2206 def test_same_quantum(self):
2207 c = Context()
2208 d = c.same_quantum(Decimal(1), Decimal(2))
2209 self.assertEqual(c.same_quantum(1, 2), d)
2210 self.assertEqual(c.same_quantum(Decimal(1), 2), d)
2211 self.assertEqual(c.same_quantum(1, Decimal(2)), d)
2212 self.assertRaises(TypeError, c.same_quantum, '1', 2)
2213 self.assertRaises(TypeError, c.same_quantum, 1, '2')
2214
2215 def test_scaleb(self):
2216 c = Context()
2217 d = c.scaleb(Decimal(1), Decimal(2))
2218 self.assertEqual(c.scaleb(1, 2), d)
2219 self.assertEqual(c.scaleb(Decimal(1), 2), d)
2220 self.assertEqual(c.scaleb(1, Decimal(2)), d)
2221 self.assertRaises(TypeError, c.scaleb, '1', 2)
2222 self.assertRaises(TypeError, c.scaleb, 1, '2')
2223
2224 def test_shift(self):
2225 c = Context()
2226 d = c.shift(Decimal(1), Decimal(2))
2227 self.assertEqual(c.shift(1, 2), d)
2228 self.assertEqual(c.shift(Decimal(1), 2), d)
2229 self.assertEqual(c.shift(1, Decimal(2)), d)
2230 self.assertRaises(TypeError, c.shift, '1', 2)
2231 self.assertRaises(TypeError, c.shift, 1, '2')
2232
2233 def test_subtract(self):
2234 c = Context()
2235 d = c.subtract(Decimal(1), Decimal(2))
2236 self.assertEqual(c.subtract(1, 2), d)
2237 self.assertEqual(c.subtract(Decimal(1), 2), d)
2238 self.assertEqual(c.subtract(1, Decimal(2)), d)
2239 self.assertRaises(TypeError, c.subtract, '1', 2)
2240 self.assertRaises(TypeError, c.subtract, 1, '2')
2241
2242 def test_to_eng_string(self):
2243 c = Context()
2244 d = c.to_eng_string(Decimal(10))
2245 self.assertEqual(c.to_eng_string(10), d)
2246 self.assertRaises(TypeError, c.to_eng_string, '10')
2247
2248 def test_to_sci_string(self):
2249 c = Context()
2250 d = c.to_sci_string(Decimal(10))
2251 self.assertEqual(c.to_sci_string(10), d)
2252 self.assertRaises(TypeError, c.to_sci_string, '10')
2253
2254 def test_to_integral_exact(self):
2255 c = Context()
2256 d = c.to_integral_exact(Decimal(10))
2257 self.assertEqual(c.to_integral_exact(10), d)
2258 self.assertRaises(TypeError, c.to_integral_exact, '10')
2259
2260 def test_to_integral_value(self):
2261 c = Context()
2262 d = c.to_integral_value(Decimal(10))
2263 self.assertEqual(c.to_integral_value(10), d)
2264 self.assertRaises(TypeError, c.to_integral_value, '10')
2265
Thomas Wouters89f507f2006-12-13 04:49:30 +00002266class WithStatementTest(unittest.TestCase):
2267 # Can't do these as docstrings until Python 2.6
2268 # as doctest can't handle __future__ statements
2269
2270 def test_localcontext(self):
2271 # Use a copy of the current context in the block
2272 orig_ctx = getcontext()
2273 with localcontext() as enter_ctx:
2274 set_ctx = getcontext()
2275 final_ctx = getcontext()
Ezio Melotti6607d512010-04-03 14:59:49 +00002276 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
2277 self.assertIsNot(orig_ctx, set_ctx, 'did not copy the context')
2278 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
Thomas Wouters89f507f2006-12-13 04:49:30 +00002279
2280 def test_localcontextarg(self):
2281 # Use a copy of the supplied context in the block
2282 orig_ctx = getcontext()
2283 new_ctx = Context(prec=42)
2284 with localcontext(new_ctx) as enter_ctx:
2285 set_ctx = getcontext()
2286 final_ctx = getcontext()
Ezio Melotti6607d512010-04-03 14:59:49 +00002287 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
2288 self.assertEqual(set_ctx.prec, new_ctx.prec, 'did not set correct context')
2289 self.assertIsNot(new_ctx, set_ctx, 'did not copy the context')
2290 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
Thomas Wouters89f507f2006-12-13 04:49:30 +00002291
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002292class ContextFlags(unittest.TestCase):
2293 def test_flags_irrelevant(self):
2294 # check that the result (numeric result + flags raised) of an
2295 # arithmetic operation doesn't depend on the current flags
2296
2297 context = Context(prec=9, Emin = -999999999, Emax = 999999999,
2298 rounding=ROUND_HALF_EVEN, traps=[], flags=[])
2299
2300 # operations that raise various flags, in the form (function, arglist)
2301 operations = [
2302 (context._apply, [Decimal("100E-1000000009")]),
2303 (context.sqrt, [Decimal(2)]),
2304 (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]),
2305 (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]),
2306 (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]),
2307 ]
2308
2309 # try various flags individually, then a whole lot at once
2310 flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal],
2311 [Inexact, Rounded, Underflow, Clamped, Subnormal]]
2312
2313 for fn, args in operations:
2314 # find answer and flags raised using a clean context
2315 context.clear_flags()
2316 ans = fn(*args)
2317 flags = [k for k, v in context.flags.items() if v]
2318
2319 for extra_flags in flagsets:
2320 # set flags, before calling operation
2321 context.clear_flags()
2322 for flag in extra_flags:
2323 context._raise_error(flag)
2324 new_ans = fn(*args)
2325
2326 # flags that we expect to be set after the operation
2327 expected_flags = list(flags)
2328 for flag in extra_flags:
2329 if flag not in expected_flags:
2330 expected_flags.append(flag)
2331 expected_flags.sort(key=id)
2332
2333 # flags we actually got
2334 new_flags = [k for k,v in context.flags.items() if v]
2335 new_flags.sort(key=id)
2336
2337 self.assertEqual(ans, new_ans,
2338 "operation produces different answers depending on flags set: " +
2339 "expected %s, got %s." % (ans, new_ans))
2340 self.assertEqual(new_flags, expected_flags,
2341 "operation raises different flags depending on flags set: " +
2342 "expected %s, got %s" % (expected_flags, new_flags))
2343
2344def test_main(arith=False, verbose=None, todo_tests=None, debug=None):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002345 """ Execute the tests.
2346
Raymond Hettingered20ad82004-09-04 20:09:13 +00002347 Runs all arithmetic tests if arith is True or if the "decimal" resource
2348 is enabled in regrtest.py
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002349 """
Raymond Hettingered20ad82004-09-04 20:09:13 +00002350
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002351 init()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002352 global TEST_ALL, DEBUG
Raymond Hettingered20ad82004-09-04 20:09:13 +00002353 TEST_ALL = arith or is_resource_enabled('decimal')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002354 DEBUG = debug
Raymond Hettingered20ad82004-09-04 20:09:13 +00002355
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002356 if todo_tests is None:
2357 test_classes = [
2358 DecimalExplicitConstructionTest,
2359 DecimalImplicitConstructionTest,
2360 DecimalArithmeticOperatorsTest,
Christian Heimesf16baeb2008-02-29 14:57:44 +00002361 DecimalFormatTest,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002362 DecimalUseOfContextTest,
2363 DecimalUsabilityTest,
2364 DecimalPythonAPItests,
2365 ContextAPItests,
2366 DecimalTest,
2367 WithStatementTest,
2368 ContextFlags
2369 ]
2370 else:
2371 test_classes = [DecimalTest]
2372
2373 # Dynamically build custom test definition for each file in the test
2374 # directory and add the definitions to the DecimalTest class. This
2375 # procedure insures that new files do not get skipped.
2376 for filename in os.listdir(directory):
2377 if '.decTest' not in filename or filename.startswith("."):
2378 continue
2379 head, tail = filename.split('.')
2380 if todo_tests is not None and head not in todo_tests:
2381 continue
2382 tester = lambda self, f=filename: self.eval_file(directory + f)
2383 setattr(DecimalTest, 'test_' + head, tester)
2384 del filename, head, tail, tester
2385
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002386
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002387 try:
2388 run_unittest(*test_classes)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002389 if todo_tests is None:
2390 import decimal as DecimalModule
2391 run_doctest(DecimalModule, verbose)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002392 finally:
2393 setcontext(ORIGINAL_CONTEXT)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002394
2395if __name__ == '__main__':
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002396 import optparse
2397 p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]")
2398 p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test')
2399 p.add_option('--skip', '-s', action='store_true', help='skip over 90% of the arithmetic tests')
2400 (opt, args) = p.parse_args()
2401
2402 if opt.skip:
2403 test_main(arith=False, verbose=True)
2404 elif args:
2405 test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002406 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002407 test_main(arith=True, verbose=True)