blob: a88da5bdb844558ac5c9d0fd77165363535767f0 [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):
1302 #just that it's hashable
1303 hash(Decimal(23))
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001304 hash(Decimal('Infinity'))
1305 hash(Decimal('-Infinity'))
1306 hash(Decimal('nan123'))
1307 hash(Decimal('-NaN'))
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001308
1309 test_values = [Decimal(sign*(2**m + n))
1310 for m in [0, 14, 15, 16, 17, 30, 31,
1311 32, 33, 62, 63, 64, 65, 66]
1312 for n in range(-10, 10)
1313 for sign in [-1, 1]]
1314 test_values.extend([
1315 Decimal("-0"), # zeros
1316 Decimal("0.00"),
1317 Decimal("-0.000"),
1318 Decimal("0E10"),
1319 Decimal("-0E12"),
1320 Decimal("10.0"), # negative exponent
1321 Decimal("-23.00000"),
1322 Decimal("1230E100"), # positive exponent
1323 Decimal("-4.5678E50"),
1324 # a value for which hash(n) != hash(n % (2**64-1))
1325 # in Python pre-2.6
1326 Decimal(2**64 + 2**32 - 1),
1327 # selection of values which fail with the old (before
1328 # version 2.6) long.__hash__
1329 Decimal("1.634E100"),
1330 Decimal("90.697E100"),
1331 Decimal("188.83E100"),
1332 Decimal("1652.9E100"),
1333 Decimal("56531E100"),
1334 ])
1335
1336 # check that hash(d) == hash(int(d)) for integral values
1337 for value in test_values:
1338 self.assertEqual(hash(value), hash(int(value)))
1339
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001340 #the same hash that to an int
1341 self.assertEqual(hash(Decimal(23)), hash(23))
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001342 self.assertRaises(TypeError, hash, Decimal('sNaN'))
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001343 self.assertTrue(hash(Decimal('Inf')))
1344 self.assertTrue(hash(Decimal('-Inf')))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001345
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001346 # check that the hashes of a Decimal float match when they
1347 # represent exactly the same values
1348 test_strings = ['inf', '-Inf', '0.0', '-.0e1',
1349 '34.0', '2.5', '112390.625', '-0.515625']
1350 for s in test_strings:
1351 f = float(s)
1352 d = Decimal(s)
1353 self.assertEqual(hash(f), hash(d))
1354
Christian Heimes2380ac72008-01-09 00:17:24 +00001355 # check that the value of the hash doesn't depend on the
1356 # current context (issue #1757)
1357 c = getcontext()
1358 old_precision = c.prec
1359 x = Decimal("123456789.1")
1360
1361 c.prec = 6
1362 h1 = hash(x)
1363 c.prec = 10
1364 h2 = hash(x)
1365 c.prec = 16
1366 h3 = hash(x)
1367
1368 self.assertEqual(h1, h2)
1369 self.assertEqual(h1, h3)
1370 c.prec = old_precision
1371
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001372 def test_min_and_max_methods(self):
1373
1374 d1 = Decimal('15.32')
1375 d2 = Decimal('28.5')
1376 l1 = 15
1377 l2 = 28
1378
1379 #between Decimals
Ezio Melotti6607d512010-04-03 14:59:49 +00001380 self.assertIs(min(d1,d2), d1)
1381 self.assertIs(min(d2,d1), d1)
1382 self.assertIs(max(d1,d2), d2)
1383 self.assertIs(max(d2,d1), d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001384
1385 #between Decimal and long
Ezio Melotti6607d512010-04-03 14:59:49 +00001386 self.assertIs(min(d1,l2), d1)
1387 self.assertIs(min(l2,d1), d1)
1388 self.assertIs(max(l1,d2), d2)
1389 self.assertIs(max(d2,l1), d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001390
1391 def test_as_nonzero(self):
1392 #as false
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001393 self.assertFalse(Decimal(0))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001394 #as true
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001395 self.assertTrue(Decimal('0.372'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001396
1397 def test_tostring_methods(self):
1398 #Test str and repr methods.
1399
1400 d = Decimal('15.32')
1401 self.assertEqual(str(d), '15.32') # str
Christian Heimes68f5fbe2008-02-14 08:27:37 +00001402 self.assertEqual(repr(d), "Decimal('15.32')") # repr
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001403
1404 def test_tonum_methods(self):
Mark Dickinson5c2db372009-12-05 20:28:34 +00001405 #Test float and int methods.
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001406
1407 d1 = Decimal('66')
1408 d2 = Decimal('15.32')
1409
1410 #int
1411 self.assertEqual(int(d1), 66)
1412 self.assertEqual(int(d2), 15)
1413
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001414 #float
1415 self.assertEqual(float(d1), 66)
1416 self.assertEqual(float(d2), 15.32)
1417
Mark Dickinsonb27406c2008-05-09 13:42:33 +00001418 #floor
1419 test_pairs = [
1420 ('123.00', 123),
1421 ('3.2', 3),
1422 ('3.54', 3),
1423 ('3.899', 3),
1424 ('-2.3', -3),
1425 ('-11.0', -11),
1426 ('0.0', 0),
1427 ('-0E3', 0),
1428 ]
1429 for d, i in test_pairs:
1430 self.assertEqual(math.floor(Decimal(d)), i)
1431 self.assertRaises(ValueError, math.floor, Decimal('-NaN'))
1432 self.assertRaises(ValueError, math.floor, Decimal('sNaN'))
1433 self.assertRaises(ValueError, math.floor, Decimal('NaN123'))
1434 self.assertRaises(OverflowError, math.floor, Decimal('Inf'))
1435 self.assertRaises(OverflowError, math.floor, Decimal('-Inf'))
1436
1437 #ceiling
1438 test_pairs = [
1439 ('123.00', 123),
1440 ('3.2', 4),
1441 ('3.54', 4),
1442 ('3.899', 4),
1443 ('-2.3', -2),
1444 ('-11.0', -11),
1445 ('0.0', 0),
1446 ('-0E3', 0),
1447 ]
1448 for d, i in test_pairs:
1449 self.assertEqual(math.ceil(Decimal(d)), i)
1450 self.assertRaises(ValueError, math.ceil, Decimal('-NaN'))
1451 self.assertRaises(ValueError, math.ceil, Decimal('sNaN'))
1452 self.assertRaises(ValueError, math.ceil, Decimal('NaN123'))
1453 self.assertRaises(OverflowError, math.ceil, Decimal('Inf'))
1454 self.assertRaises(OverflowError, math.ceil, Decimal('-Inf'))
1455
1456 #round, single argument
1457 test_pairs = [
1458 ('123.00', 123),
1459 ('3.2', 3),
1460 ('3.54', 4),
1461 ('3.899', 4),
1462 ('-2.3', -2),
1463 ('-11.0', -11),
1464 ('0.0', 0),
1465 ('-0E3', 0),
1466 ('-3.5', -4),
1467 ('-2.5', -2),
1468 ('-1.5', -2),
1469 ('-0.5', 0),
1470 ('0.5', 0),
1471 ('1.5', 2),
1472 ('2.5', 2),
1473 ('3.5', 4),
1474 ]
1475 for d, i in test_pairs:
1476 self.assertEqual(round(Decimal(d)), i)
1477 self.assertRaises(ValueError, round, Decimal('-NaN'))
1478 self.assertRaises(ValueError, round, Decimal('sNaN'))
1479 self.assertRaises(ValueError, round, Decimal('NaN123'))
1480 self.assertRaises(OverflowError, round, Decimal('Inf'))
1481 self.assertRaises(OverflowError, round, Decimal('-Inf'))
1482
1483 #round, two arguments; this is essentially equivalent
1484 #to quantize, which is already extensively tested
1485 test_triples = [
1486 ('123.456', -4, '0E+4'),
1487 ('123.456', -3, '0E+3'),
1488 ('123.456', -2, '1E+2'),
1489 ('123.456', -1, '1.2E+2'),
1490 ('123.456', 0, '123'),
1491 ('123.456', 1, '123.5'),
1492 ('123.456', 2, '123.46'),
1493 ('123.456', 3, '123.456'),
1494 ('123.456', 4, '123.4560'),
1495 ('123.455', 2, '123.46'),
1496 ('123.445', 2, '123.44'),
1497 ('Inf', 4, 'NaN'),
1498 ('-Inf', -23, 'NaN'),
1499 ('sNaN314', 3, 'NaN314'),
1500 ]
1501 for d, n, r in test_triples:
1502 self.assertEqual(str(round(Decimal(d), n)), r)
1503
1504
1505
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001506 def test_eval_round_trip(self):
1507
1508 #with zero
1509 d = Decimal( (0, (0,), 0) )
1510 self.assertEqual(d, eval(repr(d)))
1511
1512 #int
1513 d = Decimal( (1, (4, 5), 0) )
1514 self.assertEqual(d, eval(repr(d)))
1515
1516 #float
1517 d = Decimal( (0, (4, 5, 3, 4), -2) )
1518 self.assertEqual(d, eval(repr(d)))
1519
1520 #weird
1521 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1522 self.assertEqual(d, eval(repr(d)))
1523
1524 def test_as_tuple(self):
1525
1526 #with zero
1527 d = Decimal(0)
1528 self.assertEqual(d.as_tuple(), (0, (0,), 0) )
1529
1530 #int
1531 d = Decimal(-45)
1532 self.assertEqual(d.as_tuple(), (1, (4, 5), 0) )
1533
1534 #complicated string
1535 d = Decimal("-4.34913534E-17")
1536 self.assertEqual(d.as_tuple(), (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1537
1538 #inf
1539 d = Decimal("Infinity")
1540 self.assertEqual(d.as_tuple(), (0, (0,), 'F') )
1541
Guido van Rossum8ce8a782007-11-01 19:42:39 +00001542 #leading zeros in coefficient should be stripped
1543 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), -2) )
1544 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), -2) )
1545 d = Decimal( (1, (0, 0, 0), 37) )
1546 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1547 d = Decimal( (1, (), 37) )
1548 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1549
1550 #leading zeros in NaN diagnostic info should be stripped
1551 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), 'n') )
1552 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), 'n') )
1553 d = Decimal( (1, (0, 0, 0), 'N') )
1554 self.assertEqual(d.as_tuple(), (1, (), 'N') )
1555 d = Decimal( (1, (), 'n') )
1556 self.assertEqual(d.as_tuple(), (1, (), 'n') )
1557
1558 #coefficient in infinity should be ignored
1559 d = Decimal( (0, (4, 5, 3, 4), 'F') )
1560 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
1561 d = Decimal( (1, (0, 2, 7, 1), 'F') )
1562 self.assertEqual(d.as_tuple(), (1, (0,), 'F'))
1563
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001564 def test_immutability_operations(self):
1565 # Do operations and check that it didn't change change internal objects.
1566
1567 d1 = Decimal('-25e55')
1568 b1 = Decimal('-25e55')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001569 d2 = Decimal('33e+33')
1570 b2 = Decimal('33e+33')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001571
1572 def checkSameDec(operation, useOther=False):
1573 if useOther:
1574 eval("d1." + operation + "(d2)")
1575 self.assertEqual(d1._sign, b1._sign)
1576 self.assertEqual(d1._int, b1._int)
1577 self.assertEqual(d1._exp, b1._exp)
1578 self.assertEqual(d2._sign, b2._sign)
1579 self.assertEqual(d2._int, b2._int)
1580 self.assertEqual(d2._exp, b2._exp)
1581 else:
1582 eval("d1." + operation + "()")
1583 self.assertEqual(d1._sign, b1._sign)
1584 self.assertEqual(d1._int, b1._int)
1585 self.assertEqual(d1._exp, b1._exp)
1586 return
1587
1588 Decimal(d1)
1589 self.assertEqual(d1._sign, b1._sign)
1590 self.assertEqual(d1._int, b1._int)
1591 self.assertEqual(d1._exp, b1._exp)
1592
1593 checkSameDec("__abs__")
1594 checkSameDec("__add__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001595 checkSameDec("__divmod__", True)
Christian Heimes77c02eb2008-02-09 02:18:51 +00001596 checkSameDec("__eq__", True)
1597 checkSameDec("__ne__", True)
1598 checkSameDec("__le__", True)
1599 checkSameDec("__lt__", True)
1600 checkSameDec("__ge__", True)
1601 checkSameDec("__gt__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001602 checkSameDec("__float__")
1603 checkSameDec("__floordiv__", True)
1604 checkSameDec("__hash__")
1605 checkSameDec("__int__")
Christian Heimes969fe572008-01-25 11:23:10 +00001606 checkSameDec("__trunc__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001607 checkSameDec("__mod__", True)
1608 checkSameDec("__mul__", True)
1609 checkSameDec("__neg__")
Jack Diederich4dafcc42006-11-28 19:15:13 +00001610 checkSameDec("__bool__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001611 checkSameDec("__pos__")
1612 checkSameDec("__pow__", True)
1613 checkSameDec("__radd__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001614 checkSameDec("__rdivmod__", True)
1615 checkSameDec("__repr__")
1616 checkSameDec("__rfloordiv__", True)
1617 checkSameDec("__rmod__", True)
1618 checkSameDec("__rmul__", True)
1619 checkSameDec("__rpow__", True)
1620 checkSameDec("__rsub__", True)
1621 checkSameDec("__str__")
1622 checkSameDec("__sub__", True)
1623 checkSameDec("__truediv__", True)
1624 checkSameDec("adjusted")
1625 checkSameDec("as_tuple")
1626 checkSameDec("compare", True)
1627 checkSameDec("max", True)
1628 checkSameDec("min", True)
1629 checkSameDec("normalize")
1630 checkSameDec("quantize", True)
1631 checkSameDec("remainder_near", True)
1632 checkSameDec("same_quantum", True)
1633 checkSameDec("sqrt")
1634 checkSameDec("to_eng_string")
1635 checkSameDec("to_integral")
1636
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001637 def test_subclassing(self):
1638 # Different behaviours when subclassing Decimal
1639
1640 class MyDecimal(Decimal):
1641 pass
1642
1643 d1 = MyDecimal(1)
1644 d2 = MyDecimal(2)
1645 d = d1 + d2
Ezio Melotti6607d512010-04-03 14:59:49 +00001646 self.assertIs(type(d), Decimal)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001647
1648 d = d1.max(d2)
Ezio Melotti6607d512010-04-03 14:59:49 +00001649 self.assertIs(type(d), Decimal)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001650
Christian Heimes0348fb62008-03-26 12:55:56 +00001651 def test_implicit_context(self):
1652 # Check results when context given implicitly. (Issue 2478)
1653 c = getcontext()
1654 self.assertEqual(str(Decimal(0).sqrt()),
1655 str(c.sqrt(Decimal(0))))
1656
Mark Dickinsona2d1fe02009-10-29 12:23:02 +00001657 def test_conversions_from_int(self):
1658 # Check that methods taking a second Decimal argument will
1659 # always accept an integer in place of a Decimal.
1660 self.assertEqual(Decimal(4).compare(3),
1661 Decimal(4).compare(Decimal(3)))
1662 self.assertEqual(Decimal(4).compare_signal(3),
1663 Decimal(4).compare_signal(Decimal(3)))
1664 self.assertEqual(Decimal(4).compare_total(3),
1665 Decimal(4).compare_total(Decimal(3)))
1666 self.assertEqual(Decimal(4).compare_total_mag(3),
1667 Decimal(4).compare_total_mag(Decimal(3)))
1668 self.assertEqual(Decimal(10101).logical_and(1001),
1669 Decimal(10101).logical_and(Decimal(1001)))
1670 self.assertEqual(Decimal(10101).logical_or(1001),
1671 Decimal(10101).logical_or(Decimal(1001)))
1672 self.assertEqual(Decimal(10101).logical_xor(1001),
1673 Decimal(10101).logical_xor(Decimal(1001)))
1674 self.assertEqual(Decimal(567).max(123),
1675 Decimal(567).max(Decimal(123)))
1676 self.assertEqual(Decimal(567).max_mag(123),
1677 Decimal(567).max_mag(Decimal(123)))
1678 self.assertEqual(Decimal(567).min(123),
1679 Decimal(567).min(Decimal(123)))
1680 self.assertEqual(Decimal(567).min_mag(123),
1681 Decimal(567).min_mag(Decimal(123)))
1682 self.assertEqual(Decimal(567).next_toward(123),
1683 Decimal(567).next_toward(Decimal(123)))
1684 self.assertEqual(Decimal(1234).quantize(100),
1685 Decimal(1234).quantize(Decimal(100)))
1686 self.assertEqual(Decimal(768).remainder_near(1234),
1687 Decimal(768).remainder_near(Decimal(1234)))
1688 self.assertEqual(Decimal(123).rotate(1),
1689 Decimal(123).rotate(Decimal(1)))
1690 self.assertEqual(Decimal(1234).same_quantum(1000),
1691 Decimal(1234).same_quantum(Decimal(1000)))
1692 self.assertEqual(Decimal('9.123').scaleb(-100),
1693 Decimal('9.123').scaleb(Decimal(-100)))
1694 self.assertEqual(Decimal(456).shift(-1),
1695 Decimal(456).shift(Decimal(-1)))
1696
1697 self.assertEqual(Decimal(-12).fma(Decimal(45), 67),
1698 Decimal(-12).fma(Decimal(45), Decimal(67)))
1699 self.assertEqual(Decimal(-12).fma(45, 67),
1700 Decimal(-12).fma(Decimal(45), Decimal(67)))
1701 self.assertEqual(Decimal(-12).fma(45, Decimal(67)),
1702 Decimal(-12).fma(Decimal(45), Decimal(67)))
1703
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001704
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001705class DecimalPythonAPItests(unittest.TestCase):
1706
Raymond Hettinger82417ca2009-02-03 03:54:28 +00001707 def test_abc(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001708 self.assertTrue(issubclass(Decimal, numbers.Number))
Ezio Melotti6607d512010-04-03 14:59:49 +00001709 self.assertFalse(issubclass(Decimal, numbers.Real))
Ezio Melottie9615932010-01-24 19:26:24 +00001710 self.assertIsInstance(Decimal(0), numbers.Number)
1711 self.assertNotIsInstance(Decimal(0), numbers.Real)
Raymond Hettinger82417ca2009-02-03 03:54:28 +00001712
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001713 def test_pickle(self):
1714 d = Decimal('-3.141590000')
1715 p = pickle.dumps(d)
1716 e = pickle.loads(p)
1717 self.assertEqual(d, e)
1718
Raymond Hettinger5548be22004-07-05 18:49:38 +00001719 def test_int(self):
Raymond Hettinger605ed022004-11-24 07:28:48 +00001720 for x in range(-250, 250):
1721 s = '%0.2f' % (x / 100.0)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001722 # should work the same as for floats
1723 self.assertEqual(int(Decimal(s)), int(float(s)))
Raymond Hettinger605ed022004-11-24 07:28:48 +00001724 # should work the same as to_integral in the ROUND_DOWN mode
Raymond Hettinger5548be22004-07-05 18:49:38 +00001725 d = Decimal(s)
Raymond Hettinger605ed022004-11-24 07:28:48 +00001726 r = d.to_integral(ROUND_DOWN)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001727 self.assertEqual(Decimal(int(d)), r)
1728
Mark Dickinson825fce32009-09-07 18:08:12 +00001729 self.assertRaises(ValueError, int, Decimal('-nan'))
1730 self.assertRaises(ValueError, int, Decimal('snan'))
1731 self.assertRaises(OverflowError, int, Decimal('inf'))
1732 self.assertRaises(OverflowError, int, Decimal('-inf'))
1733
Christian Heimes969fe572008-01-25 11:23:10 +00001734 def test_trunc(self):
1735 for x in range(-250, 250):
1736 s = '%0.2f' % (x / 100.0)
1737 # should work the same as for floats
1738 self.assertEqual(int(Decimal(s)), int(float(s)))
1739 # should work the same as to_integral in the ROUND_DOWN mode
1740 d = Decimal(s)
1741 r = d.to_integral(ROUND_DOWN)
Christian Heimes400adb02008-02-01 08:12:03 +00001742 self.assertEqual(Decimal(math.trunc(d)), r)
Christian Heimes969fe572008-01-25 11:23:10 +00001743
Raymond Hettinger771ed762009-01-03 19:20:32 +00001744 def test_from_float(self):
1745
1746 class MyDecimal(Decimal):
1747 pass
1748
1749 r = MyDecimal.from_float(0.1)
1750 self.assertEqual(type(r), MyDecimal)
1751 self.assertEqual(str(r),
1752 '0.1000000000000000055511151231257827021181583404541015625')
1753 bigint = 12345678901234567890123456789
1754 self.assertEqual(MyDecimal.from_float(bigint), MyDecimal(bigint))
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001755 self.assertTrue(MyDecimal.from_float(float('nan')).is_qnan())
1756 self.assertTrue(MyDecimal.from_float(float('inf')).is_infinite())
1757 self.assertTrue(MyDecimal.from_float(float('-inf')).is_infinite())
Raymond Hettinger771ed762009-01-03 19:20:32 +00001758 self.assertEqual(str(MyDecimal.from_float(float('nan'))),
1759 str(Decimal('NaN')))
1760 self.assertEqual(str(MyDecimal.from_float(float('inf'))),
1761 str(Decimal('Infinity')))
1762 self.assertEqual(str(MyDecimal.from_float(float('-inf'))),
1763 str(Decimal('-Infinity')))
1764 self.assertRaises(TypeError, MyDecimal.from_float, 'abc')
1765 for i in range(200):
1766 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
1767 self.assertEqual(x, float(MyDecimal.from_float(x))) # roundtrip
1768
1769 def test_create_decimal_from_float(self):
1770 context = Context(prec=5, rounding=ROUND_DOWN)
1771 self.assertEqual(
1772 context.create_decimal_from_float(math.pi),
1773 Decimal('3.1415')
1774 )
1775 context = Context(prec=5, rounding=ROUND_UP)
1776 self.assertEqual(
1777 context.create_decimal_from_float(math.pi),
1778 Decimal('3.1416')
1779 )
1780 context = Context(prec=5, traps=[Inexact])
1781 self.assertRaises(
1782 Inexact,
1783 context.create_decimal_from_float,
1784 math.pi
1785 )
1786 self.assertEqual(repr(context.create_decimal_from_float(-0.0)),
1787 "Decimal('-0')")
1788 self.assertEqual(repr(context.create_decimal_from_float(1.0)),
1789 "Decimal('1')")
1790 self.assertEqual(repr(context.create_decimal_from_float(10)),
1791 "Decimal('10')")
1792
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00001793class ContextAPItests(unittest.TestCase):
1794
1795 def test_pickle(self):
1796 c = Context()
1797 e = pickle.loads(pickle.dumps(c))
1798 for k in vars(c):
1799 v1 = vars(c)[k]
1800 v2 = vars(e)[k]
1801 self.assertEqual(v1, v2)
1802
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001803 def test_equality_with_other_types(self):
Benjamin Peterson577473f2010-01-19 00:09:57 +00001804 self.assertIn(Decimal(10), ['a', 1.0, Decimal(10), (1,2), {}])
1805 self.assertNotIn(Decimal(10), ['a', 1.0, (1,2), {}])
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001806
Raymond Hettinger955d2b22004-08-08 20:17:45 +00001807 def test_copy(self):
1808 # All copies should be deep
1809 c = Context()
1810 d = c.copy()
1811 self.assertNotEqual(id(c), id(d))
1812 self.assertNotEqual(id(c.flags), id(d.flags))
1813 self.assertNotEqual(id(c.traps), id(d.traps))
1814
Mark Dickinsonb1d8e322010-05-22 18:35:36 +00001815 def test__clamp(self):
1816 # In Python 3.2, the private attribute `_clamp` was made
1817 # public (issue 8540), with the old `_clamp` becoming a
1818 # property wrapping `clamp`. For the duration of Python 3.2
1819 # only, the attribute should be gettable/settable via both
1820 # `clamp` and `_clamp`; in Python 3.3, `_clamp` should be
1821 # removed.
1822 c = Context(clamp = 0)
1823 self.assertEqual(c.clamp, 0)
1824
1825 with check_warnings(("", DeprecationWarning)):
1826 c._clamp = 1
1827 self.assertEqual(c.clamp, 1)
1828 with check_warnings(("", DeprecationWarning)):
1829 self.assertEqual(c._clamp, 1)
1830 c.clamp = 0
1831 self.assertEqual(c.clamp, 0)
1832 with check_warnings(("", DeprecationWarning)):
1833 self.assertEqual(c._clamp, 0)
1834
Mark Dickinson84230a12010-02-18 14:49:50 +00001835 def test_abs(self):
1836 c = Context()
1837 d = c.abs(Decimal(-1))
1838 self.assertEqual(c.abs(-1), d)
1839 self.assertRaises(TypeError, c.abs, '-1')
1840
1841 def test_add(self):
1842 c = Context()
1843 d = c.add(Decimal(1), Decimal(1))
1844 self.assertEqual(c.add(1, 1), d)
1845 self.assertEqual(c.add(Decimal(1), 1), d)
1846 self.assertEqual(c.add(1, Decimal(1)), d)
1847 self.assertRaises(TypeError, c.add, '1', 1)
1848 self.assertRaises(TypeError, c.add, 1, '1')
1849
1850 def test_compare(self):
1851 c = Context()
1852 d = c.compare(Decimal(1), Decimal(1))
1853 self.assertEqual(c.compare(1, 1), d)
1854 self.assertEqual(c.compare(Decimal(1), 1), d)
1855 self.assertEqual(c.compare(1, Decimal(1)), d)
1856 self.assertRaises(TypeError, c.compare, '1', 1)
1857 self.assertRaises(TypeError, c.compare, 1, '1')
1858
1859 def test_compare_signal(self):
1860 c = Context()
1861 d = c.compare_signal(Decimal(1), Decimal(1))
1862 self.assertEqual(c.compare_signal(1, 1), d)
1863 self.assertEqual(c.compare_signal(Decimal(1), 1), d)
1864 self.assertEqual(c.compare_signal(1, Decimal(1)), d)
1865 self.assertRaises(TypeError, c.compare_signal, '1', 1)
1866 self.assertRaises(TypeError, c.compare_signal, 1, '1')
1867
1868 def test_compare_total(self):
1869 c = Context()
1870 d = c.compare_total(Decimal(1), Decimal(1))
1871 self.assertEqual(c.compare_total(1, 1), d)
1872 self.assertEqual(c.compare_total(Decimal(1), 1), d)
1873 self.assertEqual(c.compare_total(1, Decimal(1)), d)
1874 self.assertRaises(TypeError, c.compare_total, '1', 1)
1875 self.assertRaises(TypeError, c.compare_total, 1, '1')
1876
1877 def test_compare_total_mag(self):
1878 c = Context()
1879 d = c.compare_total_mag(Decimal(1), Decimal(1))
1880 self.assertEqual(c.compare_total_mag(1, 1), d)
1881 self.assertEqual(c.compare_total_mag(Decimal(1), 1), d)
1882 self.assertEqual(c.compare_total_mag(1, Decimal(1)), d)
1883 self.assertRaises(TypeError, c.compare_total_mag, '1', 1)
1884 self.assertRaises(TypeError, c.compare_total_mag, 1, '1')
1885
1886 def test_copy_abs(self):
1887 c = Context()
1888 d = c.copy_abs(Decimal(-1))
1889 self.assertEqual(c.copy_abs(-1), d)
1890 self.assertRaises(TypeError, c.copy_abs, '-1')
1891
1892 def test_copy_decimal(self):
1893 c = Context()
1894 d = c.copy_decimal(Decimal(-1))
1895 self.assertEqual(c.copy_decimal(-1), d)
1896 self.assertRaises(TypeError, c.copy_decimal, '-1')
1897
1898 def test_copy_negate(self):
1899 c = Context()
1900 d = c.copy_negate(Decimal(-1))
1901 self.assertEqual(c.copy_negate(-1), d)
1902 self.assertRaises(TypeError, c.copy_negate, '-1')
1903
1904 def test_copy_sign(self):
1905 c = Context()
1906 d = c.copy_sign(Decimal(1), Decimal(-2))
1907 self.assertEqual(c.copy_sign(1, -2), d)
1908 self.assertEqual(c.copy_sign(Decimal(1), -2), d)
1909 self.assertEqual(c.copy_sign(1, Decimal(-2)), d)
1910 self.assertRaises(TypeError, c.copy_sign, '1', -2)
1911 self.assertRaises(TypeError, c.copy_sign, 1, '-2')
1912
1913 def test_divide(self):
1914 c = Context()
1915 d = c.divide(Decimal(1), Decimal(2))
1916 self.assertEqual(c.divide(1, 2), d)
1917 self.assertEqual(c.divide(Decimal(1), 2), d)
1918 self.assertEqual(c.divide(1, Decimal(2)), d)
1919 self.assertRaises(TypeError, c.divide, '1', 2)
1920 self.assertRaises(TypeError, c.divide, 1, '2')
1921
1922 def test_divide_int(self):
1923 c = Context()
1924 d = c.divide_int(Decimal(1), Decimal(2))
1925 self.assertEqual(c.divide_int(1, 2), d)
1926 self.assertEqual(c.divide_int(Decimal(1), 2), d)
1927 self.assertEqual(c.divide_int(1, Decimal(2)), d)
1928 self.assertRaises(TypeError, c.divide_int, '1', 2)
1929 self.assertRaises(TypeError, c.divide_int, 1, '2')
1930
1931 def test_divmod(self):
1932 c = Context()
1933 d = c.divmod(Decimal(1), Decimal(2))
1934 self.assertEqual(c.divmod(1, 2), d)
1935 self.assertEqual(c.divmod(Decimal(1), 2), d)
1936 self.assertEqual(c.divmod(1, Decimal(2)), d)
1937 self.assertRaises(TypeError, c.divmod, '1', 2)
1938 self.assertRaises(TypeError, c.divmod, 1, '2')
1939
1940 def test_exp(self):
1941 c = Context()
1942 d = c.exp(Decimal(10))
1943 self.assertEqual(c.exp(10), d)
1944 self.assertRaises(TypeError, c.exp, '10')
1945
1946 def test_fma(self):
1947 c = Context()
1948 d = c.fma(Decimal(2), Decimal(3), Decimal(4))
1949 self.assertEqual(c.fma(2, 3, 4), d)
1950 self.assertEqual(c.fma(Decimal(2), 3, 4), d)
1951 self.assertEqual(c.fma(2, Decimal(3), 4), d)
1952 self.assertEqual(c.fma(2, 3, Decimal(4)), d)
1953 self.assertEqual(c.fma(Decimal(2), Decimal(3), 4), d)
1954 self.assertRaises(TypeError, c.fma, '2', 3, 4)
1955 self.assertRaises(TypeError, c.fma, 2, '3', 4)
1956 self.assertRaises(TypeError, c.fma, 2, 3, '4')
1957
1958 def test_is_finite(self):
1959 c = Context()
1960 d = c.is_finite(Decimal(10))
1961 self.assertEqual(c.is_finite(10), d)
1962 self.assertRaises(TypeError, c.is_finite, '10')
1963
1964 def test_is_infinite(self):
1965 c = Context()
1966 d = c.is_infinite(Decimal(10))
1967 self.assertEqual(c.is_infinite(10), d)
1968 self.assertRaises(TypeError, c.is_infinite, '10')
1969
1970 def test_is_nan(self):
1971 c = Context()
1972 d = c.is_nan(Decimal(10))
1973 self.assertEqual(c.is_nan(10), d)
1974 self.assertRaises(TypeError, c.is_nan, '10')
1975
1976 def test_is_normal(self):
1977 c = Context()
1978 d = c.is_normal(Decimal(10))
1979 self.assertEqual(c.is_normal(10), d)
1980 self.assertRaises(TypeError, c.is_normal, '10')
1981
1982 def test_is_qnan(self):
1983 c = Context()
1984 d = c.is_qnan(Decimal(10))
1985 self.assertEqual(c.is_qnan(10), d)
1986 self.assertRaises(TypeError, c.is_qnan, '10')
1987
1988 def test_is_signed(self):
1989 c = Context()
1990 d = c.is_signed(Decimal(10))
1991 self.assertEqual(c.is_signed(10), d)
1992 self.assertRaises(TypeError, c.is_signed, '10')
1993
1994 def test_is_snan(self):
1995 c = Context()
1996 d = c.is_snan(Decimal(10))
1997 self.assertEqual(c.is_snan(10), d)
1998 self.assertRaises(TypeError, c.is_snan, '10')
1999
2000 def test_is_subnormal(self):
2001 c = Context()
2002 d = c.is_subnormal(Decimal(10))
2003 self.assertEqual(c.is_subnormal(10), d)
2004 self.assertRaises(TypeError, c.is_subnormal, '10')
2005
2006 def test_is_zero(self):
2007 c = Context()
2008 d = c.is_zero(Decimal(10))
2009 self.assertEqual(c.is_zero(10), d)
2010 self.assertRaises(TypeError, c.is_zero, '10')
2011
2012 def test_ln(self):
2013 c = Context()
2014 d = c.ln(Decimal(10))
2015 self.assertEqual(c.ln(10), d)
2016 self.assertRaises(TypeError, c.ln, '10')
2017
2018 def test_log10(self):
2019 c = Context()
2020 d = c.log10(Decimal(10))
2021 self.assertEqual(c.log10(10), d)
2022 self.assertRaises(TypeError, c.log10, '10')
2023
2024 def test_logb(self):
2025 c = Context()
2026 d = c.logb(Decimal(10))
2027 self.assertEqual(c.logb(10), d)
2028 self.assertRaises(TypeError, c.logb, '10')
2029
2030 def test_logical_and(self):
2031 c = Context()
2032 d = c.logical_and(Decimal(1), Decimal(1))
2033 self.assertEqual(c.logical_and(1, 1), d)
2034 self.assertEqual(c.logical_and(Decimal(1), 1), d)
2035 self.assertEqual(c.logical_and(1, Decimal(1)), d)
2036 self.assertRaises(TypeError, c.logical_and, '1', 1)
2037 self.assertRaises(TypeError, c.logical_and, 1, '1')
2038
2039 def test_logical_invert(self):
2040 c = Context()
2041 d = c.logical_invert(Decimal(1000))
2042 self.assertEqual(c.logical_invert(1000), d)
2043 self.assertRaises(TypeError, c.logical_invert, '1000')
2044
2045 def test_logical_or(self):
2046 c = Context()
2047 d = c.logical_or(Decimal(1), Decimal(1))
2048 self.assertEqual(c.logical_or(1, 1), d)
2049 self.assertEqual(c.logical_or(Decimal(1), 1), d)
2050 self.assertEqual(c.logical_or(1, Decimal(1)), d)
2051 self.assertRaises(TypeError, c.logical_or, '1', 1)
2052 self.assertRaises(TypeError, c.logical_or, 1, '1')
2053
2054 def test_logical_xor(self):
2055 c = Context()
2056 d = c.logical_xor(Decimal(1), Decimal(1))
2057 self.assertEqual(c.logical_xor(1, 1), d)
2058 self.assertEqual(c.logical_xor(Decimal(1), 1), d)
2059 self.assertEqual(c.logical_xor(1, Decimal(1)), d)
2060 self.assertRaises(TypeError, c.logical_xor, '1', 1)
2061 self.assertRaises(TypeError, c.logical_xor, 1, '1')
2062
2063 def test_max(self):
2064 c = Context()
2065 d = c.max(Decimal(1), Decimal(2))
2066 self.assertEqual(c.max(1, 2), d)
2067 self.assertEqual(c.max(Decimal(1), 2), d)
2068 self.assertEqual(c.max(1, Decimal(2)), d)
2069 self.assertRaises(TypeError, c.max, '1', 2)
2070 self.assertRaises(TypeError, c.max, 1, '2')
2071
2072 def test_max_mag(self):
2073 c = Context()
2074 d = c.max_mag(Decimal(1), Decimal(2))
2075 self.assertEqual(c.max_mag(1, 2), d)
2076 self.assertEqual(c.max_mag(Decimal(1), 2), d)
2077 self.assertEqual(c.max_mag(1, Decimal(2)), d)
2078 self.assertRaises(TypeError, c.max_mag, '1', 2)
2079 self.assertRaises(TypeError, c.max_mag, 1, '2')
2080
2081 def test_min(self):
2082 c = Context()
2083 d = c.min(Decimal(1), Decimal(2))
2084 self.assertEqual(c.min(1, 2), d)
2085 self.assertEqual(c.min(Decimal(1), 2), d)
2086 self.assertEqual(c.min(1, Decimal(2)), d)
2087 self.assertRaises(TypeError, c.min, '1', 2)
2088 self.assertRaises(TypeError, c.min, 1, '2')
2089
2090 def test_min_mag(self):
2091 c = Context()
2092 d = c.min_mag(Decimal(1), Decimal(2))
2093 self.assertEqual(c.min_mag(1, 2), d)
2094 self.assertEqual(c.min_mag(Decimal(1), 2), d)
2095 self.assertEqual(c.min_mag(1, Decimal(2)), d)
2096 self.assertRaises(TypeError, c.min_mag, '1', 2)
2097 self.assertRaises(TypeError, c.min_mag, 1, '2')
2098
2099 def test_minus(self):
2100 c = Context()
2101 d = c.minus(Decimal(10))
2102 self.assertEqual(c.minus(10), d)
2103 self.assertRaises(TypeError, c.minus, '10')
2104
2105 def test_multiply(self):
2106 c = Context()
2107 d = c.multiply(Decimal(1), Decimal(2))
2108 self.assertEqual(c.multiply(1, 2), d)
2109 self.assertEqual(c.multiply(Decimal(1), 2), d)
2110 self.assertEqual(c.multiply(1, Decimal(2)), d)
2111 self.assertRaises(TypeError, c.multiply, '1', 2)
2112 self.assertRaises(TypeError, c.multiply, 1, '2')
2113
2114 def test_next_minus(self):
2115 c = Context()
2116 d = c.next_minus(Decimal(10))
2117 self.assertEqual(c.next_minus(10), d)
2118 self.assertRaises(TypeError, c.next_minus, '10')
2119
2120 def test_next_plus(self):
2121 c = Context()
2122 d = c.next_plus(Decimal(10))
2123 self.assertEqual(c.next_plus(10), d)
2124 self.assertRaises(TypeError, c.next_plus, '10')
2125
2126 def test_next_toward(self):
2127 c = Context()
2128 d = c.next_toward(Decimal(1), Decimal(2))
2129 self.assertEqual(c.next_toward(1, 2), d)
2130 self.assertEqual(c.next_toward(Decimal(1), 2), d)
2131 self.assertEqual(c.next_toward(1, Decimal(2)), d)
2132 self.assertRaises(TypeError, c.next_toward, '1', 2)
2133 self.assertRaises(TypeError, c.next_toward, 1, '2')
2134
2135 def test_normalize(self):
2136 c = Context()
2137 d = c.normalize(Decimal(10))
2138 self.assertEqual(c.normalize(10), d)
2139 self.assertRaises(TypeError, c.normalize, '10')
2140
2141 def test_number_class(self):
2142 c = Context()
2143 self.assertEqual(c.number_class(123), c.number_class(Decimal(123)))
2144 self.assertEqual(c.number_class(0), c.number_class(Decimal(0)))
2145 self.assertEqual(c.number_class(-45), c.number_class(Decimal(-45)))
2146
2147 def test_power(self):
2148 c = Context()
2149 d = c.power(Decimal(1), Decimal(4), Decimal(2))
2150 self.assertEqual(c.power(1, 4, 2), d)
2151 self.assertEqual(c.power(Decimal(1), 4, 2), d)
2152 self.assertEqual(c.power(1, Decimal(4), 2), d)
2153 self.assertEqual(c.power(1, 4, Decimal(2)), d)
2154 self.assertEqual(c.power(Decimal(1), Decimal(4), 2), d)
2155 self.assertRaises(TypeError, c.power, '1', 4, 2)
2156 self.assertRaises(TypeError, c.power, 1, '4', 2)
2157 self.assertRaises(TypeError, c.power, 1, 4, '2')
2158
2159 def test_plus(self):
2160 c = Context()
2161 d = c.plus(Decimal(10))
2162 self.assertEqual(c.plus(10), d)
2163 self.assertRaises(TypeError, c.plus, '10')
2164
2165 def test_quantize(self):
2166 c = Context()
2167 d = c.quantize(Decimal(1), Decimal(2))
2168 self.assertEqual(c.quantize(1, 2), d)
2169 self.assertEqual(c.quantize(Decimal(1), 2), d)
2170 self.assertEqual(c.quantize(1, Decimal(2)), d)
2171 self.assertRaises(TypeError, c.quantize, '1', 2)
2172 self.assertRaises(TypeError, c.quantize, 1, '2')
2173
2174 def test_remainder(self):
2175 c = Context()
2176 d = c.remainder(Decimal(1), Decimal(2))
2177 self.assertEqual(c.remainder(1, 2), d)
2178 self.assertEqual(c.remainder(Decimal(1), 2), d)
2179 self.assertEqual(c.remainder(1, Decimal(2)), d)
2180 self.assertRaises(TypeError, c.remainder, '1', 2)
2181 self.assertRaises(TypeError, c.remainder, 1, '2')
2182
2183 def test_remainder_near(self):
2184 c = Context()
2185 d = c.remainder_near(Decimal(1), Decimal(2))
2186 self.assertEqual(c.remainder_near(1, 2), d)
2187 self.assertEqual(c.remainder_near(Decimal(1), 2), d)
2188 self.assertEqual(c.remainder_near(1, Decimal(2)), d)
2189 self.assertRaises(TypeError, c.remainder_near, '1', 2)
2190 self.assertRaises(TypeError, c.remainder_near, 1, '2')
2191
2192 def test_rotate(self):
2193 c = Context()
2194 d = c.rotate(Decimal(1), Decimal(2))
2195 self.assertEqual(c.rotate(1, 2), d)
2196 self.assertEqual(c.rotate(Decimal(1), 2), d)
2197 self.assertEqual(c.rotate(1, Decimal(2)), d)
2198 self.assertRaises(TypeError, c.rotate, '1', 2)
2199 self.assertRaises(TypeError, c.rotate, 1, '2')
2200
2201 def test_sqrt(self):
2202 c = Context()
2203 d = c.sqrt(Decimal(10))
2204 self.assertEqual(c.sqrt(10), d)
2205 self.assertRaises(TypeError, c.sqrt, '10')
2206
2207 def test_same_quantum(self):
2208 c = Context()
2209 d = c.same_quantum(Decimal(1), Decimal(2))
2210 self.assertEqual(c.same_quantum(1, 2), d)
2211 self.assertEqual(c.same_quantum(Decimal(1), 2), d)
2212 self.assertEqual(c.same_quantum(1, Decimal(2)), d)
2213 self.assertRaises(TypeError, c.same_quantum, '1', 2)
2214 self.assertRaises(TypeError, c.same_quantum, 1, '2')
2215
2216 def test_scaleb(self):
2217 c = Context()
2218 d = c.scaleb(Decimal(1), Decimal(2))
2219 self.assertEqual(c.scaleb(1, 2), d)
2220 self.assertEqual(c.scaleb(Decimal(1), 2), d)
2221 self.assertEqual(c.scaleb(1, Decimal(2)), d)
2222 self.assertRaises(TypeError, c.scaleb, '1', 2)
2223 self.assertRaises(TypeError, c.scaleb, 1, '2')
2224
2225 def test_shift(self):
2226 c = Context()
2227 d = c.shift(Decimal(1), Decimal(2))
2228 self.assertEqual(c.shift(1, 2), d)
2229 self.assertEqual(c.shift(Decimal(1), 2), d)
2230 self.assertEqual(c.shift(1, Decimal(2)), d)
2231 self.assertRaises(TypeError, c.shift, '1', 2)
2232 self.assertRaises(TypeError, c.shift, 1, '2')
2233
2234 def test_subtract(self):
2235 c = Context()
2236 d = c.subtract(Decimal(1), Decimal(2))
2237 self.assertEqual(c.subtract(1, 2), d)
2238 self.assertEqual(c.subtract(Decimal(1), 2), d)
2239 self.assertEqual(c.subtract(1, Decimal(2)), d)
2240 self.assertRaises(TypeError, c.subtract, '1', 2)
2241 self.assertRaises(TypeError, c.subtract, 1, '2')
2242
2243 def test_to_eng_string(self):
2244 c = Context()
2245 d = c.to_eng_string(Decimal(10))
2246 self.assertEqual(c.to_eng_string(10), d)
2247 self.assertRaises(TypeError, c.to_eng_string, '10')
2248
2249 def test_to_sci_string(self):
2250 c = Context()
2251 d = c.to_sci_string(Decimal(10))
2252 self.assertEqual(c.to_sci_string(10), d)
2253 self.assertRaises(TypeError, c.to_sci_string, '10')
2254
2255 def test_to_integral_exact(self):
2256 c = Context()
2257 d = c.to_integral_exact(Decimal(10))
2258 self.assertEqual(c.to_integral_exact(10), d)
2259 self.assertRaises(TypeError, c.to_integral_exact, '10')
2260
2261 def test_to_integral_value(self):
2262 c = Context()
2263 d = c.to_integral_value(Decimal(10))
2264 self.assertEqual(c.to_integral_value(10), d)
2265 self.assertRaises(TypeError, c.to_integral_value, '10')
2266
Thomas Wouters89f507f2006-12-13 04:49:30 +00002267class WithStatementTest(unittest.TestCase):
2268 # Can't do these as docstrings until Python 2.6
2269 # as doctest can't handle __future__ statements
2270
2271 def test_localcontext(self):
2272 # Use a copy of the current context in the block
2273 orig_ctx = getcontext()
2274 with localcontext() as enter_ctx:
2275 set_ctx = getcontext()
2276 final_ctx = getcontext()
Ezio Melotti6607d512010-04-03 14:59:49 +00002277 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
2278 self.assertIsNot(orig_ctx, set_ctx, 'did not copy the context')
2279 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
Thomas Wouters89f507f2006-12-13 04:49:30 +00002280
2281 def test_localcontextarg(self):
2282 # Use a copy of the supplied context in the block
2283 orig_ctx = getcontext()
2284 new_ctx = Context(prec=42)
2285 with localcontext(new_ctx) as enter_ctx:
2286 set_ctx = getcontext()
2287 final_ctx = getcontext()
Ezio Melotti6607d512010-04-03 14:59:49 +00002288 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
2289 self.assertEqual(set_ctx.prec, new_ctx.prec, 'did not set correct context')
2290 self.assertIsNot(new_ctx, set_ctx, 'did not copy the context')
2291 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
Thomas Wouters89f507f2006-12-13 04:49:30 +00002292
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002293class ContextFlags(unittest.TestCase):
2294 def test_flags_irrelevant(self):
2295 # check that the result (numeric result + flags raised) of an
2296 # arithmetic operation doesn't depend on the current flags
2297
2298 context = Context(prec=9, Emin = -999999999, Emax = 999999999,
2299 rounding=ROUND_HALF_EVEN, traps=[], flags=[])
2300
2301 # operations that raise various flags, in the form (function, arglist)
2302 operations = [
2303 (context._apply, [Decimal("100E-1000000009")]),
2304 (context.sqrt, [Decimal(2)]),
2305 (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]),
2306 (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]),
2307 (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]),
2308 ]
2309
2310 # try various flags individually, then a whole lot at once
2311 flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal],
2312 [Inexact, Rounded, Underflow, Clamped, Subnormal]]
2313
2314 for fn, args in operations:
2315 # find answer and flags raised using a clean context
2316 context.clear_flags()
2317 ans = fn(*args)
2318 flags = [k for k, v in context.flags.items() if v]
2319
2320 for extra_flags in flagsets:
2321 # set flags, before calling operation
2322 context.clear_flags()
2323 for flag in extra_flags:
2324 context._raise_error(flag)
2325 new_ans = fn(*args)
2326
2327 # flags that we expect to be set after the operation
2328 expected_flags = list(flags)
2329 for flag in extra_flags:
2330 if flag not in expected_flags:
2331 expected_flags.append(flag)
2332 expected_flags.sort(key=id)
2333
2334 # flags we actually got
2335 new_flags = [k for k,v in context.flags.items() if v]
2336 new_flags.sort(key=id)
2337
2338 self.assertEqual(ans, new_ans,
2339 "operation produces different answers depending on flags set: " +
2340 "expected %s, got %s." % (ans, new_ans))
2341 self.assertEqual(new_flags, expected_flags,
2342 "operation raises different flags depending on flags set: " +
2343 "expected %s, got %s" % (expected_flags, new_flags))
2344
2345def test_main(arith=False, verbose=None, todo_tests=None, debug=None):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002346 """ Execute the tests.
2347
Raymond Hettingered20ad82004-09-04 20:09:13 +00002348 Runs all arithmetic tests if arith is True or if the "decimal" resource
2349 is enabled in regrtest.py
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002350 """
Raymond Hettingered20ad82004-09-04 20:09:13 +00002351
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002352 init()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002353 global TEST_ALL, DEBUG
Raymond Hettingered20ad82004-09-04 20:09:13 +00002354 TEST_ALL = arith or is_resource_enabled('decimal')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002355 DEBUG = debug
Raymond Hettingered20ad82004-09-04 20:09:13 +00002356
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002357 if todo_tests is None:
2358 test_classes = [
2359 DecimalExplicitConstructionTest,
2360 DecimalImplicitConstructionTest,
2361 DecimalArithmeticOperatorsTest,
Christian Heimesf16baeb2008-02-29 14:57:44 +00002362 DecimalFormatTest,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002363 DecimalUseOfContextTest,
2364 DecimalUsabilityTest,
2365 DecimalPythonAPItests,
2366 ContextAPItests,
2367 DecimalTest,
2368 WithStatementTest,
2369 ContextFlags
2370 ]
2371 else:
2372 test_classes = [DecimalTest]
2373
2374 # Dynamically build custom test definition for each file in the test
2375 # directory and add the definitions to the DecimalTest class. This
2376 # procedure insures that new files do not get skipped.
2377 for filename in os.listdir(directory):
2378 if '.decTest' not in filename or filename.startswith("."):
2379 continue
2380 head, tail = filename.split('.')
2381 if todo_tests is not None and head not in todo_tests:
2382 continue
2383 tester = lambda self, f=filename: self.eval_file(directory + f)
2384 setattr(DecimalTest, 'test_' + head, tester)
2385 del filename, head, tail, tester
2386
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002387
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002388 try:
2389 run_unittest(*test_classes)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002390 if todo_tests is None:
2391 import decimal as DecimalModule
2392 run_doctest(DecimalModule, verbose)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002393 finally:
2394 setcontext(ORIGINAL_CONTEXT)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002395
2396if __name__ == '__main__':
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002397 import optparse
2398 p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]")
2399 p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test')
2400 p.add_option('--skip', '-s', action='store_true', help='skip over 90% of the arithmetic tests')
2401 (opt, args) = p.parse_args()
2402
2403 if opt.skip:
2404 test_main(arith=False, verbose=True)
2405 elif args:
2406 test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002407 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002408 test_main(arith=True, verbose=True)