blob: 50b660b3413ef31098019cdf5128ec9f57210ad7 [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.
81skipped_test_ids = [
82 'scbx164', # skipping apparently implementation-specific scaleb
83 'scbx165', # tests, pending clarification of scaleb rules.
84]
85
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000086# Make sure it actually raises errors when not expected and caught in flags
87# Slower, since it runs some things several times.
88EXTENDEDERRORTEST = False
89
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000090#Map the test cases' error names to the actual errors
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000091ErrorNames = {'clamped' : Clamped,
Raymond Hettinger5aa478b2004-07-09 10:02:53 +000092 'conversion_syntax' : InvalidOperation,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000093 'division_by_zero' : DivisionByZero,
Raymond Hettinger5aa478b2004-07-09 10:02:53 +000094 'division_impossible' : InvalidOperation,
95 'division_undefined' : InvalidOperation,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000096 'inexact' : Inexact,
Raymond Hettinger5aa478b2004-07-09 10:02:53 +000097 'invalid_context' : InvalidOperation,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000098 'invalid_operation' : InvalidOperation,
99 'overflow' : Overflow,
100 'rounded' : Rounded,
101 'subnormal' : Subnormal,
102 'underflow' : Underflow}
103
104
105def Nonfunction(*args):
106 """Doesn't do anything."""
107 return None
108
109RoundingDict = {'ceiling' : ROUND_CEILING, #Maps test-case names to roundings.
110 'down' : ROUND_DOWN,
111 'floor' : ROUND_FLOOR,
112 'half_down' : ROUND_HALF_DOWN,
113 'half_even' : ROUND_HALF_EVEN,
114 'half_up' : ROUND_HALF_UP,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000115 'up' : ROUND_UP,
116 '05up' : ROUND_05UP}
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000117
118# Name adapter to be able to change the Decimal and Context
119# interface without changing the test files from Cowlishaw
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000120nameAdapter = {'and':'logical_and',
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000121 'apply':'_apply',
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000122 'class':'number_class',
123 'comparesig':'compare_signal',
124 'comparetotal':'compare_total',
125 'comparetotmag':'compare_total_mag',
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000126 'copy':'copy_decimal',
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000127 'copyabs':'copy_abs',
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000128 'copynegate':'copy_negate',
129 'copysign':'copy_sign',
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000130 'divideint':'divide_int',
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000131 'invert':'logical_invert',
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000132 'iscanonical':'is_canonical',
133 'isfinite':'is_finite',
134 'isinfinite':'is_infinite',
135 'isnan':'is_nan',
136 'isnormal':'is_normal',
137 'isqnan':'is_qnan',
138 'issigned':'is_signed',
139 'issnan':'is_snan',
140 'issubnormal':'is_subnormal',
141 'iszero':'is_zero',
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000142 'maxmag':'max_mag',
143 'minmag':'min_mag',
144 'nextminus':'next_minus',
145 'nextplus':'next_plus',
146 'nexttoward':'next_toward',
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000147 'or':'logical_or',
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000148 'reduce':'normalize',
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000149 'remaindernear':'remainder_near',
150 'samequantum':'same_quantum',
151 'squareroot':'sqrt',
152 'toeng':'to_eng_string',
153 'tointegral':'to_integral_value',
154 'tointegralx':'to_integral_exact',
155 'tosci':'to_sci_string',
156 'xor':'logical_xor',
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000157 }
158
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000159# The following functions return True/False rather than a Decimal instance
160
161LOGICAL_FUNCTIONS = (
162 'is_canonical',
163 'is_finite',
164 'is_infinite',
165 'is_nan',
166 'is_normal',
167 'is_qnan',
168 'is_signed',
169 'is_snan',
170 'is_subnormal',
171 'is_zero',
172 'same_quantum',
173 )
174
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000175# For some operations (currently exp, ln, log10, power), the decNumber
176# reference implementation imposes additional restrictions on the
177# context and operands. These restrictions are not part of the
178# specification; however, the effect of these restrictions does show
179# up in some of the testcases. We skip testcases that violate these
180# restrictions, since Decimal behaves differently from decNumber for
181# these testcases so these testcases would otherwise fail.
182
183decNumberRestricted = ('power', 'ln', 'log10', 'exp')
184DEC_MAX_MATH = 999999
185def outside_decNumber_bounds(v, context):
186 if (context.prec > DEC_MAX_MATH or
187 context.Emax > DEC_MAX_MATH or
188 -context.Emin > DEC_MAX_MATH):
189 return True
190 if not v._is_special and v and (
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000191 v.adjusted() > DEC_MAX_MATH or
192 v.adjusted() < 1-2*DEC_MAX_MATH):
193 return True
194 return False
195
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000196class DecimalTest(unittest.TestCase):
197 """Class which tests the Decimal class against the test cases.
198
199 Changed for unittest.
200 """
201 def setUp(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000202 self.context = Context()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000203 self.ignore_list = ['#']
204 # Basically, a # means return NaN InvalidOperation.
205 # Different from a sNaN in trim
206
207 self.ChangeDict = {'precision' : self.change_precision,
208 'rounding' : self.change_rounding_method,
209 'maxexponent' : self.change_max_exponent,
210 'minexponent' : self.change_min_exponent,
211 'clamp' : self.change_clamp}
212
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000213 def eval_file(self, file):
214 global skip_expected
215 if skip_expected:
Benjamin Petersone549ead2009-03-28 21:42:05 +0000216 raise unittest.SkipTest
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000217 return
Neal Norwitz70967602006-03-17 08:29:44 +0000218 for line in open(file):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000219 line = line.replace('\r\n', '').replace('\n', '')
Raymond Hettinger5aa478b2004-07-09 10:02:53 +0000220 #print line
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000221 try:
222 t = self.eval_line(line)
Guido van Rossumb940e112007-01-10 16:19:56 +0000223 except DecimalException as exception:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000224 #Exception raised where there shoudn't have been one.
225 self.fail('Exception "'+exception.__class__.__name__ + '" raised on line '+line)
226
227 return
228
229 def eval_line(self, s):
230 if s.find(' -> ') >= 0 and s[:2] != '--' and not s.startswith(' --'):
231 s = (s.split('->')[0] + '->' +
232 s.split('->')[1].split('--')[0]).strip()
233 else:
234 s = s.split('--')[0].strip()
235
236 for ignore in self.ignore_list:
237 if s.find(ignore) >= 0:
238 #print s.split()[0], 'NotImplemented--', ignore
239 return
240 if not s:
241 return
242 elif ':' in s:
243 return self.eval_directive(s)
244 else:
245 return self.eval_equation(s)
246
247 def eval_directive(self, s):
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000248 funct, value = (x.strip().lower() for x in s.split(':'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000249 if funct == 'rounding':
250 value = RoundingDict[value]
251 else:
252 try:
253 value = int(value)
254 except ValueError:
255 pass
256
257 funct = self.ChangeDict.get(funct, Nonfunction)
258 funct(value)
259
260 def eval_equation(self, s):
261 #global DEFAULT_PRECISION
262 #print DEFAULT_PRECISION
Raymond Hettingered20ad82004-09-04 20:09:13 +0000263
264 if not TEST_ALL and random.random() < 0.90:
265 return
266
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000267 try:
268 Sides = s.split('->')
269 L = Sides[0].strip().split()
270 id = L[0]
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000271 if DEBUG:
272 print("Test ", id, end=" ")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000273 funct = L[1].lower()
274 valstemp = L[2:]
275 L = Sides[1].strip().split()
276 ans = L[0]
277 exceptions = L[1:]
278 except (TypeError, AttributeError, IndexError):
Raymond Hettingerd87ac8f2004-07-09 10:52:54 +0000279 raise InvalidOperation
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000280 def FixQuotes(val):
281 val = val.replace("''", 'SingleQuote').replace('""', 'DoubleQuote')
282 val = val.replace("'", '').replace('"', '')
283 val = val.replace('SingleQuote', "'").replace('DoubleQuote', '"')
284 return val
Mark Dickinson8a546532009-10-08 16:30:38 +0000285
286 if id in skipped_test_ids:
287 return
288
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000289 fname = nameAdapter.get(funct, funct)
290 if fname == 'rescale':
291 return
292 funct = getattr(self.context, fname)
293 vals = []
294 conglomerate = ''
295 quote = 0
296 theirexceptions = [ErrorNames[x.lower()] for x in exceptions]
297
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000298 for exception in Signals:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000299 self.context.traps[exception] = 1 #Catch these bugs...
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000300 for exception in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000301 self.context.traps[exception] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000302 for i, val in enumerate(valstemp):
303 if val.count("'") % 2 == 1:
304 quote = 1 - quote
305 if quote:
306 conglomerate = conglomerate + ' ' + val
307 continue
308 else:
309 val = conglomerate + val
310 conglomerate = ''
311 v = FixQuotes(val)
312 if fname in ('to_sci_string', 'to_eng_string'):
313 if EXTENDEDERRORTEST:
314 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000315 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000316 try:
317 funct(self.context.create_decimal(v))
318 except error:
319 pass
Guido van Rossumb940e112007-01-10 16:19:56 +0000320 except Signals as e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000321 self.fail("Raised %s in %s when %s disabled" % \
322 (e, s, error))
323 else:
324 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000325 self.context.traps[error] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000326 v = self.context.create_decimal(v)
327 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000328 v = Decimal(v, self.context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000329 vals.append(v)
330
331 ans = FixQuotes(ans)
332
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000333 # skip tests that are related to bounds imposed in the decNumber
334 # reference implementation
335 if fname in decNumberRestricted:
336 if fname == 'power':
337 if not (vals[1]._isinteger() and
338 -1999999997 <= vals[1] <= 999999999):
339 if outside_decNumber_bounds(vals[0], self.context) or \
340 outside_decNumber_bounds(vals[1], self.context):
341 #print "Skipping test %s" % s
342 return
343 else:
344 if outside_decNumber_bounds(vals[0], self.context):
345 #print "Skipping test %s" % s
346 return
347
348
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000349 if EXTENDEDERRORTEST and fname not in ('to_sci_string', 'to_eng_string'):
350 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000351 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000352 try:
353 funct(*vals)
354 except error:
355 pass
Guido van Rossumb940e112007-01-10 16:19:56 +0000356 except Signals as e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000357 self.fail("Raised %s in %s when %s disabled" % \
358 (e, s, error))
359 else:
360 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000361 self.context.traps[error] = 0
Mark Dickinsonc69160e2010-05-04 14:35:33 +0000362
363 # as above, but add traps cumulatively, to check precedence
364 ordered_errors = [e for e in OrderedSignals if e in theirexceptions]
365 for error in ordered_errors:
366 self.context.traps[error] = 1
367 try:
368 funct(*vals)
369 except error:
370 pass
371 except Signals as e:
372 self.fail("Raised %s in %s; expected %s" %
373 (type(e), s, error))
374 else:
375 self.fail("Did not raise %s in %s" % (error, s))
376 # reset traps
377 for error in ordered_errors:
378 self.context.traps[error] = 0
379
380
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000381 if DEBUG:
382 print("--", self.context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000383 try:
384 result = str(funct(*vals))
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000385 if fname in LOGICAL_FUNCTIONS:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000386 result = str(int(eval(result))) # 'True', 'False' -> '1', '0'
Guido van Rossumb940e112007-01-10 16:19:56 +0000387 except Signals as error:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000388 self.fail("Raised %s in %s" % (error, s))
389 except: #Catch any error long enough to state the test case.
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000390 print("ERROR:", s)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000391 raise
392
393 myexceptions = self.getexceptions()
Raymond Hettingerbf440692004-07-10 14:14:37 +0000394 self.context.clear_flags()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000395
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000396 myexceptions.sort(key=repr)
397 theirexceptions.sort(key=repr)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000398
399 self.assertEqual(result, ans,
400 'Incorrect answer for ' + s + ' -- got ' + result)
401 self.assertEqual(myexceptions, theirexceptions,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000402 'Incorrect flags set in ' + s + ' -- got ' + str(myexceptions))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000403 return
404
405 def getexceptions(self):
Raymond Hettingerf63ba432004-08-17 05:42:09 +0000406 return [e for e in Signals if self.context.flags[e]]
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000407
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000408 def change_precision(self, prec):
409 self.context.prec = prec
410 def change_rounding_method(self, rounding):
411 self.context.rounding = rounding
412 def change_min_exponent(self, exp):
413 self.context.Emin = exp
414 def change_max_exponent(self, exp):
415 self.context.Emax = exp
416 def change_clamp(self, clamp):
Mark Dickinsonb1d8e322010-05-22 18:35:36 +0000417 self.context.clamp = clamp
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000418
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000419
420
421# The following classes test the behaviour of Decimal according to PEP 327
422
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000423class DecimalExplicitConstructionTest(unittest.TestCase):
424 '''Unit tests for Explicit Construction cases of Decimal.'''
425
426 def test_explicit_empty(self):
427 self.assertEqual(Decimal(), Decimal("0"))
428
429 def test_explicit_from_None(self):
430 self.assertRaises(TypeError, Decimal, None)
431
432 def test_explicit_from_int(self):
433
434 #positive
435 d = Decimal(45)
436 self.assertEqual(str(d), '45')
437
438 #very large positive
439 d = Decimal(500000123)
440 self.assertEqual(str(d), '500000123')
441
442 #negative
443 d = Decimal(-45)
444 self.assertEqual(str(d), '-45')
445
446 #zero
447 d = Decimal(0)
448 self.assertEqual(str(d), '0')
449
450 def test_explicit_from_string(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000451
452 #empty
453 self.assertEqual(str(Decimal('')), 'NaN')
454
455 #int
456 self.assertEqual(str(Decimal('45')), '45')
457
458 #float
459 self.assertEqual(str(Decimal('45.34')), '45.34')
460
461 #engineer notation
462 self.assertEqual(str(Decimal('45e2')), '4.5E+3')
463
464 #just not a number
465 self.assertEqual(str(Decimal('ugly')), 'NaN')
466
Christian Heimesa62da1d2008-01-12 19:39:10 +0000467 #leading and trailing whitespace permitted
468 self.assertEqual(str(Decimal('1.3E4 \n')), '1.3E+4')
469 self.assertEqual(str(Decimal(' -7.89')), '-7.89')
470
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000471 def test_explicit_from_tuples(self):
472
473 #zero
474 d = Decimal( (0, (0,), 0) )
475 self.assertEqual(str(d), '0')
476
477 #int
478 d = Decimal( (1, (4, 5), 0) )
479 self.assertEqual(str(d), '-45')
480
481 #float
482 d = Decimal( (0, (4, 5, 3, 4), -2) )
483 self.assertEqual(str(d), '45.34')
484
485 #weird
486 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
487 self.assertEqual(str(d), '-4.34913534E-17')
488
489 #wrong number of items
490 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1)) )
491
492 #bad sign
493 self.assertRaises(ValueError, Decimal, (8, (4, 3, 4, 9, 1), 2) )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000494 self.assertRaises(ValueError, Decimal, (0., (4, 3, 4, 9, 1), 2) )
495 self.assertRaises(ValueError, Decimal, (Decimal(1), (4, 3, 4, 9, 1), 2))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000496
497 #bad exp
498 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 'wrong!') )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000499 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 0.) )
500 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), '1') )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000501
502 #bad coefficients
503 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, None, 1), 2) )
504 self.assertRaises(ValueError, Decimal, (1, (4, -3, 4, 9, 1), 2) )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000505 self.assertRaises(ValueError, Decimal, (1, (4, 10, 4, 9, 1), 2) )
Guido van Rossum0d3fb8a2007-11-26 23:23:18 +0000506 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 'a', 1), 2) )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000507
Antoine Pitrou503ab332010-03-30 18:56:19 +0000508 def test_explicit_from_bool(self):
509 self.assertIs(bool(Decimal(0)), False)
510 self.assertIs(bool(Decimal(1)), True)
511 self.assertEqual(Decimal(False), Decimal(0))
512 self.assertEqual(Decimal(True), Decimal(1))
513
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000514 def test_explicit_from_Decimal(self):
515
516 #positive
517 d = Decimal(45)
518 e = Decimal(d)
519 self.assertEqual(str(e), '45')
520 self.assertNotEqual(id(d), id(e))
521
522 #very large positive
523 d = Decimal(500000123)
524 e = Decimal(d)
525 self.assertEqual(str(e), '500000123')
526 self.assertNotEqual(id(d), id(e))
527
528 #negative
529 d = Decimal(-45)
530 e = Decimal(d)
531 self.assertEqual(str(e), '-45')
532 self.assertNotEqual(id(d), id(e))
533
534 #zero
535 d = Decimal(0)
536 e = Decimal(d)
537 self.assertEqual(str(e), '0')
538 self.assertNotEqual(id(d), id(e))
539
Raymond Hettinger96798592010-04-02 16:58:27 +0000540 @requires_IEEE_754
541 def test_explicit_from_float(self):
542 r = Decimal(0.1)
543 self.assertEqual(type(r), Decimal)
544 self.assertEqual(str(r),
545 '0.1000000000000000055511151231257827021181583404541015625')
546 self.assertTrue(Decimal(float('nan')).is_qnan())
547 self.assertTrue(Decimal(float('inf')).is_infinite())
548 self.assertTrue(Decimal(float('-inf')).is_infinite())
549 self.assertEqual(str(Decimal(float('nan'))),
550 str(Decimal('NaN')))
551 self.assertEqual(str(Decimal(float('inf'))),
552 str(Decimal('Infinity')))
553 self.assertEqual(str(Decimal(float('-inf'))),
554 str(Decimal('-Infinity')))
555 self.assertEqual(str(Decimal(float('-0.0'))),
556 str(Decimal('-0')))
557 for i in range(200):
558 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
559 self.assertEqual(x, float(Decimal(x))) # roundtrip
560
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000561 def test_explicit_context_create_decimal(self):
562
563 nc = copy.copy(getcontext())
564 nc.prec = 3
565
566 # empty
Raymond Hettingerfed52962004-07-14 15:41:57 +0000567 d = Decimal()
568 self.assertEqual(str(d), '0')
569 d = nc.create_decimal()
570 self.assertEqual(str(d), '0')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000571
572 # from None
573 self.assertRaises(TypeError, nc.create_decimal, None)
574
575 # from int
576 d = nc.create_decimal(456)
Ezio Melottie9615932010-01-24 19:26:24 +0000577 self.assertIsInstance(d, Decimal)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000578 self.assertEqual(nc.create_decimal(45678),
579 nc.create_decimal('457E+2'))
580
581 # from string
582 d = Decimal('456789')
583 self.assertEqual(str(d), '456789')
584 d = nc.create_decimal('456789')
585 self.assertEqual(str(d), '4.57E+5')
Christian Heimesa62da1d2008-01-12 19:39:10 +0000586 # leading and trailing whitespace should result in a NaN;
587 # spaces are already checked in Cowlishaw's test-suite, so
588 # here we just check that a trailing newline results in a NaN
589 self.assertEqual(str(nc.create_decimal('3.14\n')), 'NaN')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000590
591 # from tuples
592 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
593 self.assertEqual(str(d), '-4.34913534E-17')
594 d = nc.create_decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
595 self.assertEqual(str(d), '-4.35E-17')
596
597 # from Decimal
598 prevdec = Decimal(500000123)
599 d = Decimal(prevdec)
600 self.assertEqual(str(d), '500000123')
601 d = nc.create_decimal(prevdec)
602 self.assertEqual(str(d), '5.00E+8')
603
Mark Dickinson345adc42009-08-02 10:14:23 +0000604 def test_unicode_digits(self):
605 test_values = {
606 '\uff11': '1',
607 '\u0660.\u0660\u0663\u0667\u0662e-\u0663' : '0.0000372',
608 '-nan\u0c68\u0c6a\u0c66\u0c66' : '-NaN2400',
609 }
610 for input, expected in test_values.items():
611 self.assertEqual(str(Decimal(input)), expected)
612
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000613
614class DecimalImplicitConstructionTest(unittest.TestCase):
615 '''Unit tests for Implicit Construction cases of Decimal.'''
616
617 def test_implicit_from_None(self):
618 self.assertRaises(TypeError, eval, 'Decimal(5) + None', globals())
619
620 def test_implicit_from_int(self):
621 #normal
622 self.assertEqual(str(Decimal(5) + 45), '50')
623 #exceeding precision
624 self.assertEqual(Decimal(5) + 123456789000, Decimal(123456789000))
625
626 def test_implicit_from_string(self):
627 self.assertRaises(TypeError, eval, 'Decimal(5) + "3"', globals())
628
629 def test_implicit_from_float(self):
630 self.assertRaises(TypeError, eval, 'Decimal(5) + 2.2', globals())
631
632 def test_implicit_from_Decimal(self):
633 self.assertEqual(Decimal(5) + Decimal(45), Decimal(50))
634
Raymond Hettinger267b8682005-03-27 10:47:39 +0000635 def test_rop(self):
636 # Allow other classes to be trained to interact with Decimals
637 class E:
638 def __divmod__(self, other):
639 return 'divmod ' + str(other)
640 def __rdivmod__(self, other):
641 return str(other) + ' rdivmod'
642 def __lt__(self, other):
643 return 'lt ' + str(other)
644 def __gt__(self, other):
645 return 'gt ' + str(other)
646 def __le__(self, other):
647 return 'le ' + str(other)
648 def __ge__(self, other):
649 return 'ge ' + str(other)
650 def __eq__(self, other):
651 return 'eq ' + str(other)
652 def __ne__(self, other):
653 return 'ne ' + str(other)
654
655 self.assertEqual(divmod(E(), Decimal(10)), 'divmod 10')
656 self.assertEqual(divmod(Decimal(10), E()), '10 rdivmod')
657 self.assertEqual(eval('Decimal(10) < E()'), 'gt 10')
658 self.assertEqual(eval('Decimal(10) > E()'), 'lt 10')
659 self.assertEqual(eval('Decimal(10) <= E()'), 'ge 10')
660 self.assertEqual(eval('Decimal(10) >= E()'), 'le 10')
661 self.assertEqual(eval('Decimal(10) == E()'), 'eq 10')
662 self.assertEqual(eval('Decimal(10) != E()'), 'ne 10')
663
664 # insert operator methods and then exercise them
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000665 oplist = [
666 ('+', '__add__', '__radd__'),
667 ('-', '__sub__', '__rsub__'),
668 ('*', '__mul__', '__rmul__'),
Thomas Woutersdcc6d322006-04-21 11:30:52 +0000669 ('/', '__truediv__', '__rtruediv__'),
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000670 ('%', '__mod__', '__rmod__'),
671 ('//', '__floordiv__', '__rfloordiv__'),
672 ('**', '__pow__', '__rpow__')
673 ]
Raymond Hettinger267b8682005-03-27 10:47:39 +0000674
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000675 for sym, lop, rop in oplist:
Raymond Hettinger267b8682005-03-27 10:47:39 +0000676 setattr(E, lop, lambda self, other: 'str' + lop + str(other))
677 setattr(E, rop, lambda self, other: str(other) + rop + 'str')
678 self.assertEqual(eval('E()' + sym + 'Decimal(10)'),
679 'str' + lop + '10')
680 self.assertEqual(eval('Decimal(10)' + sym + 'E()'),
681 '10' + rop + 'str')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000682
Mark Dickinson79f52032009-03-17 23:12:51 +0000683
Christian Heimesf16baeb2008-02-29 14:57:44 +0000684class DecimalFormatTest(unittest.TestCase):
685 '''Unit tests for the format function.'''
686 def test_formatting(self):
687 # triples giving a format, a Decimal, and the expected result
688 test_values = [
689 ('e', '0E-15', '0e-15'),
690 ('e', '2.3E-15', '2.3e-15'),
691 ('e', '2.30E+2', '2.30e+2'), # preserve significant zeros
692 ('e', '2.30000E-15', '2.30000e-15'),
693 ('e', '1.23456789123456789e40', '1.23456789123456789e+40'),
694 ('e', '1.5', '1.5e+0'),
695 ('e', '0.15', '1.5e-1'),
696 ('e', '0.015', '1.5e-2'),
697 ('e', '0.0000000000015', '1.5e-12'),
698 ('e', '15.0', '1.50e+1'),
699 ('e', '-15', '-1.5e+1'),
700 ('e', '0', '0e+0'),
701 ('e', '0E1', '0e+1'),
702 ('e', '0.0', '0e-1'),
703 ('e', '0.00', '0e-2'),
704 ('.6e', '0E-15', '0.000000e-9'),
705 ('.6e', '0', '0.000000e+6'),
706 ('.6e', '9.999999', '9.999999e+0'),
707 ('.6e', '9.9999999', '1.000000e+1'),
708 ('.6e', '-1.23e5', '-1.230000e+5'),
709 ('.6e', '1.23456789e-3', '1.234568e-3'),
710 ('f', '0', '0'),
711 ('f', '0.0', '0.0'),
712 ('f', '0E-2', '0.00'),
713 ('f', '0.00E-8', '0.0000000000'),
714 ('f', '0E1', '0'), # loses exponent information
715 ('f', '3.2E1', '32'),
716 ('f', '3.2E2', '320'),
717 ('f', '3.20E2', '320'),
718 ('f', '3.200E2', '320.0'),
719 ('f', '3.2E-6', '0.0000032'),
720 ('.6f', '0E-15', '0.000000'), # all zeros treated equally
721 ('.6f', '0E1', '0.000000'),
722 ('.6f', '0', '0.000000'),
723 ('.0f', '0', '0'), # no decimal point
724 ('.0f', '0e-2', '0'),
725 ('.0f', '3.14159265', '3'),
726 ('.1f', '3.14159265', '3.1'),
727 ('.4f', '3.14159265', '3.1416'),
728 ('.6f', '3.14159265', '3.141593'),
729 ('.7f', '3.14159265', '3.1415926'), # round-half-even!
730 ('.8f', '3.14159265', '3.14159265'),
731 ('.9f', '3.14159265', '3.141592650'),
732
733 ('g', '0', '0'),
734 ('g', '0.0', '0.0'),
735 ('g', '0E1', '0e+1'),
736 ('G', '0E1', '0E+1'),
737 ('g', '0E-5', '0.00000'),
738 ('g', '0E-6', '0.000000'),
739 ('g', '0E-7', '0e-7'),
740 ('g', '-0E2', '-0e+2'),
741 ('.0g', '3.14159265', '3'), # 0 sig fig -> 1 sig fig
742 ('.1g', '3.14159265', '3'),
743 ('.2g', '3.14159265', '3.1'),
744 ('.5g', '3.14159265', '3.1416'),
745 ('.7g', '3.14159265', '3.141593'),
746 ('.8g', '3.14159265', '3.1415926'), # round-half-even!
747 ('.9g', '3.14159265', '3.14159265'),
748 ('.10g', '3.14159265', '3.14159265'), # don't pad
749
750 ('%', '0E1', '0%'),
751 ('%', '0E0', '0%'),
752 ('%', '0E-1', '0%'),
753 ('%', '0E-2', '0%'),
754 ('%', '0E-3', '0.0%'),
755 ('%', '0E-4', '0.00%'),
756
757 ('.3%', '0', '0.000%'), # all zeros treated equally
758 ('.3%', '0E10', '0.000%'),
759 ('.3%', '0E-10', '0.000%'),
760 ('.3%', '2.34', '234.000%'),
761 ('.3%', '1.234567', '123.457%'),
762 ('.0%', '1.23', '123%'),
763
764 ('e', 'NaN', 'NaN'),
765 ('f', '-NaN123', '-NaN123'),
766 ('+g', 'NaN456', '+NaN456'),
767 ('.3e', 'Inf', 'Infinity'),
768 ('.16f', '-Inf', '-Infinity'),
769 ('.0g', '-sNaN', '-sNaN'),
770
771 ('', '1.00', '1.00'),
Mark Dickinsonad416342009-03-17 18:10:15 +0000772
Mark Dickinson79f52032009-03-17 23:12:51 +0000773 # test alignment and padding
Mark Dickinson46ab5d02009-09-08 20:22:46 +0000774 ('6', '123', ' 123'),
Mark Dickinsonad416342009-03-17 18:10:15 +0000775 ('<6', '123', '123 '),
776 ('>6', '123', ' 123'),
777 ('^6', '123', ' 123 '),
778 ('=+6', '123', '+ 123'),
Mark Dickinson79f52032009-03-17 23:12:51 +0000779 ('#<10', 'NaN', 'NaN#######'),
780 ('#<10', '-4.3', '-4.3######'),
781 ('#<+10', '0.0130', '+0.0130###'),
782 ('#< 10', '0.0130', ' 0.0130###'),
783 ('@>10', '-Inf', '@-Infinity'),
784 ('#>5', '-Inf', '-Infinity'),
785 ('?^5', '123', '?123?'),
786 ('%^6', '123', '%123%%'),
787 (' ^6', '-45.6', '-45.6 '),
788 ('/=10', '-45.6', '-/////45.6'),
789 ('/=+10', '45.6', '+/////45.6'),
790 ('/= 10', '45.6', ' /////45.6'),
791
792 # thousands separator
793 (',', '1234567', '1,234,567'),
794 (',', '123456', '123,456'),
795 (',', '12345', '12,345'),
796 (',', '1234', '1,234'),
797 (',', '123', '123'),
798 (',', '12', '12'),
799 (',', '1', '1'),
800 (',', '0', '0'),
801 (',', '-1234567', '-1,234,567'),
802 (',', '-123456', '-123,456'),
803 ('7,', '123456', '123,456'),
Mark Dickinson46ab5d02009-09-08 20:22:46 +0000804 ('8,', '123456', ' 123,456'),
Mark Dickinson79f52032009-03-17 23:12:51 +0000805 ('08,', '123456', '0,123,456'), # special case: extra 0 needed
806 ('+08,', '123456', '+123,456'), # but not if there's a sign
807 (' 08,', '123456', ' 123,456'),
808 ('08,', '-123456', '-123,456'),
809 ('+09,', '123456', '+0,123,456'),
810 # ... with fractional part...
811 ('07,', '1234.56', '1,234.56'),
812 ('08,', '1234.56', '1,234.56'),
813 ('09,', '1234.56', '01,234.56'),
814 ('010,', '1234.56', '001,234.56'),
815 ('011,', '1234.56', '0,001,234.56'),
816 ('012,', '1234.56', '0,001,234.56'),
817 ('08,.1f', '1234.5', '01,234.5'),
818 # no thousands separators in fraction part
819 (',', '1.23456789', '1.23456789'),
820 (',%', '123.456789', '12,345.6789%'),
821 (',e', '123456', '1.23456e+5'),
822 (',E', '123456', '1.23456E+5'),
Mark Dickinson7718d2b2009-09-07 16:21:56 +0000823
824 # issue 6850
825 ('a=-7.0', '0.12345', 'aaaa0.1'),
Christian Heimesf16baeb2008-02-29 14:57:44 +0000826 ]
827 for fmt, d, result in test_values:
828 self.assertEqual(format(Decimal(d), fmt), result)
829
Mark Dickinson79f52032009-03-17 23:12:51 +0000830 def test_n_format(self):
831 try:
832 from locale import CHAR_MAX
833 except ImportError:
834 return
835
836 # Set up some localeconv-like dictionaries
837 en_US = {
838 'decimal_point' : '.',
839 'grouping' : [3, 3, 0],
840 'thousands_sep': ','
841 }
842
843 fr_FR = {
844 'decimal_point' : ',',
845 'grouping' : [CHAR_MAX],
846 'thousands_sep' : ''
847 }
848
849 ru_RU = {
850 'decimal_point' : ',',
851 'grouping' : [3, 3, 0],
852 'thousands_sep' : ' '
853 }
854
855 crazy = {
856 'decimal_point' : '&',
857 'grouping' : [1, 4, 2, CHAR_MAX],
858 'thousands_sep' : '-'
859 }
860
861
862 def get_fmt(x, locale, fmt='n'):
863 return Decimal.__format__(Decimal(x), fmt, _localeconv=locale)
864
865 self.assertEqual(get_fmt(Decimal('12.7'), en_US), '12.7')
866 self.assertEqual(get_fmt(Decimal('12.7'), fr_FR), '12,7')
867 self.assertEqual(get_fmt(Decimal('12.7'), ru_RU), '12,7')
868 self.assertEqual(get_fmt(Decimal('12.7'), crazy), '1-2&7')
869
870 self.assertEqual(get_fmt(123456789, en_US), '123,456,789')
871 self.assertEqual(get_fmt(123456789, fr_FR), '123456789')
872 self.assertEqual(get_fmt(123456789, ru_RU), '123 456 789')
873 self.assertEqual(get_fmt(1234567890123, crazy), '123456-78-9012-3')
874
875 self.assertEqual(get_fmt(123456789, en_US, '.6n'), '1.23457e+8')
876 self.assertEqual(get_fmt(123456789, fr_FR, '.6n'), '1,23457e+8')
877 self.assertEqual(get_fmt(123456789, ru_RU, '.6n'), '1,23457e+8')
878 self.assertEqual(get_fmt(123456789, crazy, '.6n'), '1&23457e+8')
879
Mark Dickinson7303b592009-03-18 08:25:36 +0000880 # zero padding
881 self.assertEqual(get_fmt(1234, fr_FR, '03n'), '1234')
882 self.assertEqual(get_fmt(1234, fr_FR, '04n'), '1234')
883 self.assertEqual(get_fmt(1234, fr_FR, '05n'), '01234')
884 self.assertEqual(get_fmt(1234, fr_FR, '06n'), '001234')
885
886 self.assertEqual(get_fmt(12345, en_US, '05n'), '12,345')
887 self.assertEqual(get_fmt(12345, en_US, '06n'), '12,345')
888 self.assertEqual(get_fmt(12345, en_US, '07n'), '012,345')
889 self.assertEqual(get_fmt(12345, en_US, '08n'), '0,012,345')
890 self.assertEqual(get_fmt(12345, en_US, '09n'), '0,012,345')
891 self.assertEqual(get_fmt(12345, en_US, '010n'), '00,012,345')
892
893 self.assertEqual(get_fmt(123456, crazy, '06n'), '1-2345-6')
894 self.assertEqual(get_fmt(123456, crazy, '07n'), '1-2345-6')
895 self.assertEqual(get_fmt(123456, crazy, '08n'), '1-2345-6')
896 self.assertEqual(get_fmt(123456, crazy, '09n'), '01-2345-6')
897 self.assertEqual(get_fmt(123456, crazy, '010n'), '0-01-2345-6')
898 self.assertEqual(get_fmt(123456, crazy, '011n'), '0-01-2345-6')
899 self.assertEqual(get_fmt(123456, crazy, '012n'), '00-01-2345-6')
900 self.assertEqual(get_fmt(123456, crazy, '013n'), '000-01-2345-6')
901
Mark Dickinson79f52032009-03-17 23:12:51 +0000902
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000903class DecimalArithmeticOperatorsTest(unittest.TestCase):
904 '''Unit tests for all arithmetic operators, binary and unary.'''
905
906 def test_addition(self):
907
908 d1 = Decimal('-11.1')
909 d2 = Decimal('22.2')
910
911 #two Decimals
912 self.assertEqual(d1+d2, Decimal('11.1'))
913 self.assertEqual(d2+d1, Decimal('11.1'))
914
915 #with other type, left
916 c = d1 + 5
917 self.assertEqual(c, Decimal('-6.1'))
918 self.assertEqual(type(c), type(d1))
919
920 #with other type, right
921 c = 5 + d1
922 self.assertEqual(c, Decimal('-6.1'))
923 self.assertEqual(type(c), type(d1))
924
925 #inline with decimal
926 d1 += d2
927 self.assertEqual(d1, Decimal('11.1'))
928
929 #inline with other type
930 d1 += 5
931 self.assertEqual(d1, Decimal('16.1'))
932
933 def test_subtraction(self):
934
935 d1 = Decimal('-11.1')
936 d2 = Decimal('22.2')
937
938 #two Decimals
939 self.assertEqual(d1-d2, Decimal('-33.3'))
940 self.assertEqual(d2-d1, Decimal('33.3'))
941
942 #with other type, left
943 c = d1 - 5
944 self.assertEqual(c, Decimal('-16.1'))
945 self.assertEqual(type(c), type(d1))
946
947 #with other type, right
948 c = 5 - d1
949 self.assertEqual(c, Decimal('16.1'))
950 self.assertEqual(type(c), type(d1))
951
952 #inline with decimal
953 d1 -= d2
954 self.assertEqual(d1, Decimal('-33.3'))
955
956 #inline with other type
957 d1 -= 5
958 self.assertEqual(d1, Decimal('-38.3'))
959
960 def test_multiplication(self):
961
962 d1 = Decimal('-5')
963 d2 = Decimal('3')
964
965 #two Decimals
966 self.assertEqual(d1*d2, Decimal('-15'))
967 self.assertEqual(d2*d1, Decimal('-15'))
968
969 #with other type, left
970 c = d1 * 5
971 self.assertEqual(c, Decimal('-25'))
972 self.assertEqual(type(c), type(d1))
973
974 #with other type, right
975 c = 5 * d1
976 self.assertEqual(c, Decimal('-25'))
977 self.assertEqual(type(c), type(d1))
978
979 #inline with decimal
980 d1 *= d2
981 self.assertEqual(d1, Decimal('-15'))
982
983 #inline with other type
984 d1 *= 5
985 self.assertEqual(d1, Decimal('-75'))
986
987 def test_division(self):
988
989 d1 = Decimal('-5')
990 d2 = Decimal('2')
991
992 #two Decimals
993 self.assertEqual(d1/d2, Decimal('-2.5'))
994 self.assertEqual(d2/d1, Decimal('-0.4'))
995
996 #with other type, left
997 c = d1 / 4
998 self.assertEqual(c, Decimal('-1.25'))
999 self.assertEqual(type(c), type(d1))
1000
1001 #with other type, right
1002 c = 4 / d1
1003 self.assertEqual(c, Decimal('-0.8'))
1004 self.assertEqual(type(c), type(d1))
1005
1006 #inline with decimal
1007 d1 /= d2
1008 self.assertEqual(d1, Decimal('-2.5'))
1009
1010 #inline with other type
1011 d1 /= 4
1012 self.assertEqual(d1, Decimal('-0.625'))
1013
1014 def test_floor_division(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001015
1016 d1 = Decimal('5')
1017 d2 = Decimal('2')
1018
1019 #two Decimals
1020 self.assertEqual(d1//d2, Decimal('2'))
1021 self.assertEqual(d2//d1, Decimal('0'))
1022
1023 #with other type, left
1024 c = d1 // 4
1025 self.assertEqual(c, Decimal('1'))
1026 self.assertEqual(type(c), type(d1))
1027
1028 #with other type, right
1029 c = 7 // d1
1030 self.assertEqual(c, Decimal('1'))
1031 self.assertEqual(type(c), type(d1))
1032
1033 #inline with decimal
1034 d1 //= d2
1035 self.assertEqual(d1, Decimal('2'))
1036
1037 #inline with other type
1038 d1 //= 2
1039 self.assertEqual(d1, Decimal('1'))
1040
1041 def test_powering(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001042
1043 d1 = Decimal('5')
1044 d2 = Decimal('2')
1045
1046 #two Decimals
1047 self.assertEqual(d1**d2, Decimal('25'))
1048 self.assertEqual(d2**d1, Decimal('32'))
1049
1050 #with other type, left
1051 c = d1 ** 4
1052 self.assertEqual(c, Decimal('625'))
1053 self.assertEqual(type(c), type(d1))
1054
1055 #with other type, right
1056 c = 7 ** d1
1057 self.assertEqual(c, Decimal('16807'))
1058 self.assertEqual(type(c), type(d1))
1059
1060 #inline with decimal
1061 d1 **= d2
1062 self.assertEqual(d1, Decimal('25'))
1063
1064 #inline with other type
1065 d1 **= 4
1066 self.assertEqual(d1, Decimal('390625'))
1067
1068 def test_module(self):
1069
1070 d1 = Decimal('5')
1071 d2 = Decimal('2')
1072
1073 #two Decimals
1074 self.assertEqual(d1%d2, Decimal('1'))
1075 self.assertEqual(d2%d1, Decimal('2'))
1076
1077 #with other type, left
1078 c = d1 % 4
1079 self.assertEqual(c, Decimal('1'))
1080 self.assertEqual(type(c), type(d1))
1081
1082 #with other type, right
1083 c = 7 % d1
1084 self.assertEqual(c, Decimal('2'))
1085 self.assertEqual(type(c), type(d1))
1086
1087 #inline with decimal
1088 d1 %= d2
1089 self.assertEqual(d1, Decimal('1'))
1090
1091 #inline with other type
1092 d1 %= 4
1093 self.assertEqual(d1, Decimal('1'))
1094
1095 def test_floor_div_module(self):
1096
1097 d1 = Decimal('5')
1098 d2 = Decimal('2')
1099
1100 #two Decimals
1101 (p, q) = divmod(d1, d2)
1102 self.assertEqual(p, Decimal('2'))
1103 self.assertEqual(q, Decimal('1'))
1104 self.assertEqual(type(p), type(d1))
1105 self.assertEqual(type(q), type(d1))
1106
1107 #with other type, left
1108 (p, q) = divmod(d1, 4)
1109 self.assertEqual(p, Decimal('1'))
1110 self.assertEqual(q, Decimal('1'))
1111 self.assertEqual(type(p), type(d1))
1112 self.assertEqual(type(q), type(d1))
1113
1114 #with other type, right
1115 (p, q) = divmod(7, d1)
1116 self.assertEqual(p, Decimal('1'))
1117 self.assertEqual(q, Decimal('2'))
1118 self.assertEqual(type(p), type(d1))
1119 self.assertEqual(type(q), type(d1))
1120
1121 def test_unary_operators(self):
1122 self.assertEqual(+Decimal(45), Decimal(+45)) # +
1123 self.assertEqual(-Decimal(45), Decimal(-45)) # -
1124 self.assertEqual(abs(Decimal(45)), abs(Decimal(-45))) # abs
1125
Christian Heimes77c02eb2008-02-09 02:18:51 +00001126 def test_nan_comparisons(self):
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001127 # comparisons involving signaling nans signal InvalidOperation
1128
1129 # order comparisons (<, <=, >, >=) involving only quiet nans
1130 # also signal InvalidOperation
1131
1132 # equality comparisons (==, !=) involving only quiet nans
1133 # don't signal, but return False or True respectively.
1134
Christian Heimes77c02eb2008-02-09 02:18:51 +00001135 n = Decimal('NaN')
1136 s = Decimal('sNaN')
1137 i = Decimal('Inf')
1138 f = Decimal('2')
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001139
1140 qnan_pairs = (n, n), (n, i), (i, n), (n, f), (f, n)
1141 snan_pairs = (s, n), (n, s), (s, i), (i, s), (s, f), (f, s), (s, s)
1142 order_ops = operator.lt, operator.le, operator.gt, operator.ge
1143 equality_ops = operator.eq, operator.ne
1144
1145 # results when InvalidOperation is not trapped
1146 for x, y in qnan_pairs + snan_pairs:
1147 for op in order_ops + equality_ops:
1148 got = op(x, y)
1149 expected = True if op is operator.ne else False
1150 self.assertIs(expected, got,
1151 "expected {0!r} for operator.{1}({2!r}, {3!r}); "
1152 "got {4!r}".format(
1153 expected, op.__name__, x, y, got))
1154
1155 # repeat the above, but this time trap the InvalidOperation
1156 with localcontext() as ctx:
1157 ctx.traps[InvalidOperation] = 1
1158
1159 for x, y in qnan_pairs:
1160 for op in equality_ops:
1161 got = op(x, y)
1162 expected = True if op is operator.ne else False
1163 self.assertIs(expected, got,
1164 "expected {0!r} for "
1165 "operator.{1}({2!r}, {3!r}); "
1166 "got {4!r}".format(
1167 expected, op.__name__, x, y, got))
1168
1169 for x, y in snan_pairs:
1170 for op in equality_ops:
1171 self.assertRaises(InvalidOperation, operator.eq, x, y)
1172 self.assertRaises(InvalidOperation, operator.ne, x, y)
1173
1174 for x, y in qnan_pairs + snan_pairs:
1175 for op in order_ops:
1176 self.assertRaises(InvalidOperation, op, x, y)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001177
Mark Dickinson84230a12010-02-18 14:49:50 +00001178 def test_copy_sign(self):
1179 d = Decimal(1).copy_sign(Decimal(-2))
1180
1181 self.assertEqual(Decimal(1).copy_sign(-2), d)
1182 self.assertRaises(TypeError, Decimal(1).copy_sign, '-2')
1183
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001184# The following are two functions used to test threading in the next class
1185
1186def thfunc1(cls):
1187 d1 = Decimal(1)
1188 d3 = Decimal(3)
Christian Heimesfe337bf2008-03-23 21:54:12 +00001189 test1 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001190 cls.synchro.wait()
Christian Heimesfe337bf2008-03-23 21:54:12 +00001191 test2 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001192 cls.finish1.set()
Christian Heimesfe337bf2008-03-23 21:54:12 +00001193
Christian Heimes81ee3ef2008-05-04 22:42:01 +00001194 cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
1195 cls.assertEqual(test2, Decimal('0.3333333333333333333333333333'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001196 return
1197
1198def thfunc2(cls):
1199 d1 = Decimal(1)
1200 d3 = Decimal(3)
Christian Heimesfe337bf2008-03-23 21:54:12 +00001201 test1 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001202 thiscontext = getcontext()
1203 thiscontext.prec = 18
Christian Heimesfe337bf2008-03-23 21:54:12 +00001204 test2 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001205 cls.synchro.set()
1206 cls.finish2.set()
Christian Heimesfe337bf2008-03-23 21:54:12 +00001207
Christian Heimes81ee3ef2008-05-04 22:42:01 +00001208 cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
Christian Heimesfe337bf2008-03-23 21:54:12 +00001209 cls.assertEqual(test2, Decimal('0.333333333333333333'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001210 return
1211
1212
1213class DecimalUseOfContextTest(unittest.TestCase):
1214 '''Unit tests for Use of Context cases in Decimal.'''
1215
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001216 try:
1217 import threading
1218 except ImportError:
1219 threading = None
1220
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001221 # Take care executing this test from IDLE, there's an issue in threading
1222 # that hangs IDLE and I couldn't find it
1223
1224 def test_threading(self):
1225 #Test the "threading isolation" of a Context.
1226
1227 self.synchro = threading.Event()
1228 self.finish1 = threading.Event()
1229 self.finish2 = threading.Event()
1230
1231 th1 = threading.Thread(target=thfunc1, args=(self,))
1232 th2 = threading.Thread(target=thfunc2, args=(self,))
1233
1234 th1.start()
1235 th2.start()
1236
1237 self.finish1.wait()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001238 self.finish2.wait()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001239 return
1240
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001241 if threading is None:
1242 del test_threading
1243
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001244
1245class DecimalUsabilityTest(unittest.TestCase):
1246 '''Unit tests for Usability cases of Decimal.'''
1247
1248 def test_comparison_operators(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001249
1250 da = Decimal('23.42')
1251 db = Decimal('23.42')
1252 dc = Decimal('45')
1253
1254 #two Decimals
Ezio Melotti6607d512010-04-03 14:59:49 +00001255 self.assertGreater(dc, da)
1256 self.assertGreaterEqual(dc, da)
1257 self.assertLess(da, dc)
1258 self.assertLessEqual(da, dc)
Guido van Rossume61fd5b2007-07-11 12:20:59 +00001259 self.assertEqual(da, db)
Ezio Melotti6607d512010-04-03 14:59:49 +00001260 self.assertNotEqual(da, dc)
1261 self.assertLessEqual(da, db)
1262 self.assertGreaterEqual(da, db)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001263
1264 #a Decimal and an int
Ezio Melotti6607d512010-04-03 14:59:49 +00001265 self.assertGreater(dc, 23)
1266 self.assertLess(23, dc)
Guido van Rossume61fd5b2007-07-11 12:20:59 +00001267 self.assertEqual(dc, 45)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001268
1269 #a Decimal and uncomparable
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001270 self.assertNotEqual(da, 'ugly')
1271 self.assertNotEqual(da, 32.7)
1272 self.assertNotEqual(da, object())
1273 self.assertNotEqual(da, object)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001274
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001275 # sortable
Guido van Rossumc1f779c2007-07-03 08:25:58 +00001276 a = list(map(Decimal, range(100)))
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001277 b = a[:]
1278 random.shuffle(a)
1279 a.sort()
1280 self.assertEqual(a, b)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001281
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001282 def test_decimal_float_comparison(self):
1283 da = Decimal('0.25')
1284 db = Decimal('3.0')
Ezio Melotti6607d512010-04-03 14:59:49 +00001285 self.assertLess(da, 3.0)
1286 self.assertLessEqual(da, 3.0)
1287 self.assertGreater(db, 0.25)
1288 self.assertGreaterEqual(db, 0.25)
1289 self.assertNotEqual(da, 1.5)
1290 self.assertEqual(da, 0.25)
1291 self.assertGreater(3.0, da)
1292 self.assertGreaterEqual(3.0, da)
1293 self.assertLess(0.25, db)
1294 self.assertLessEqual(0.25, db)
1295 self.assertNotEqual(0.25, db)
1296 self.assertEqual(3.0, db)
1297 self.assertNotEqual(0.1, Decimal('0.1'))
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001298
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001299 def test_copy_and_deepcopy_methods(self):
1300 d = Decimal('43.24')
1301 c = copy.copy(d)
1302 self.assertEqual(id(c), id(d))
1303 dc = copy.deepcopy(d)
1304 self.assertEqual(id(dc), id(d))
1305
1306 def test_hash_method(self):
1307 #just that it's hashable
1308 hash(Decimal(23))
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001309 hash(Decimal('Infinity'))
1310 hash(Decimal('-Infinity'))
1311 hash(Decimal('nan123'))
1312 hash(Decimal('-NaN'))
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001313
1314 test_values = [Decimal(sign*(2**m + n))
1315 for m in [0, 14, 15, 16, 17, 30, 31,
1316 32, 33, 62, 63, 64, 65, 66]
1317 for n in range(-10, 10)
1318 for sign in [-1, 1]]
1319 test_values.extend([
1320 Decimal("-0"), # zeros
1321 Decimal("0.00"),
1322 Decimal("-0.000"),
1323 Decimal("0E10"),
1324 Decimal("-0E12"),
1325 Decimal("10.0"), # negative exponent
1326 Decimal("-23.00000"),
1327 Decimal("1230E100"), # positive exponent
1328 Decimal("-4.5678E50"),
1329 # a value for which hash(n) != hash(n % (2**64-1))
1330 # in Python pre-2.6
1331 Decimal(2**64 + 2**32 - 1),
1332 # selection of values which fail with the old (before
1333 # version 2.6) long.__hash__
1334 Decimal("1.634E100"),
1335 Decimal("90.697E100"),
1336 Decimal("188.83E100"),
1337 Decimal("1652.9E100"),
1338 Decimal("56531E100"),
1339 ])
1340
1341 # check that hash(d) == hash(int(d)) for integral values
1342 for value in test_values:
1343 self.assertEqual(hash(value), hash(int(value)))
1344
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001345 #the same hash that to an int
1346 self.assertEqual(hash(Decimal(23)), hash(23))
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001347 self.assertRaises(TypeError, hash, Decimal('sNaN'))
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001348 self.assertTrue(hash(Decimal('Inf')))
1349 self.assertTrue(hash(Decimal('-Inf')))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001350
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001351 # check that the hashes of a Decimal float match when they
1352 # represent exactly the same values
1353 test_strings = ['inf', '-Inf', '0.0', '-.0e1',
1354 '34.0', '2.5', '112390.625', '-0.515625']
1355 for s in test_strings:
1356 f = float(s)
1357 d = Decimal(s)
1358 self.assertEqual(hash(f), hash(d))
1359
Christian Heimes2380ac72008-01-09 00:17:24 +00001360 # check that the value of the hash doesn't depend on the
1361 # current context (issue #1757)
1362 c = getcontext()
1363 old_precision = c.prec
1364 x = Decimal("123456789.1")
1365
1366 c.prec = 6
1367 h1 = hash(x)
1368 c.prec = 10
1369 h2 = hash(x)
1370 c.prec = 16
1371 h3 = hash(x)
1372
1373 self.assertEqual(h1, h2)
1374 self.assertEqual(h1, h3)
1375 c.prec = old_precision
1376
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001377 def test_min_and_max_methods(self):
1378
1379 d1 = Decimal('15.32')
1380 d2 = Decimal('28.5')
1381 l1 = 15
1382 l2 = 28
1383
1384 #between Decimals
Ezio Melotti6607d512010-04-03 14:59:49 +00001385 self.assertIs(min(d1,d2), d1)
1386 self.assertIs(min(d2,d1), d1)
1387 self.assertIs(max(d1,d2), d2)
1388 self.assertIs(max(d2,d1), d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001389
1390 #between Decimal and long
Ezio Melotti6607d512010-04-03 14:59:49 +00001391 self.assertIs(min(d1,l2), d1)
1392 self.assertIs(min(l2,d1), d1)
1393 self.assertIs(max(l1,d2), d2)
1394 self.assertIs(max(d2,l1), d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001395
1396 def test_as_nonzero(self):
1397 #as false
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001398 self.assertFalse(Decimal(0))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001399 #as true
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001400 self.assertTrue(Decimal('0.372'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001401
1402 def test_tostring_methods(self):
1403 #Test str and repr methods.
1404
1405 d = Decimal('15.32')
1406 self.assertEqual(str(d), '15.32') # str
Christian Heimes68f5fbe2008-02-14 08:27:37 +00001407 self.assertEqual(repr(d), "Decimal('15.32')") # repr
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001408
1409 def test_tonum_methods(self):
Mark Dickinson5c2db372009-12-05 20:28:34 +00001410 #Test float and int methods.
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001411
1412 d1 = Decimal('66')
1413 d2 = Decimal('15.32')
1414
1415 #int
1416 self.assertEqual(int(d1), 66)
1417 self.assertEqual(int(d2), 15)
1418
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001419 #float
1420 self.assertEqual(float(d1), 66)
1421 self.assertEqual(float(d2), 15.32)
1422
Mark Dickinsonb27406c2008-05-09 13:42:33 +00001423 #floor
1424 test_pairs = [
1425 ('123.00', 123),
1426 ('3.2', 3),
1427 ('3.54', 3),
1428 ('3.899', 3),
1429 ('-2.3', -3),
1430 ('-11.0', -11),
1431 ('0.0', 0),
1432 ('-0E3', 0),
1433 ]
1434 for d, i in test_pairs:
1435 self.assertEqual(math.floor(Decimal(d)), i)
1436 self.assertRaises(ValueError, math.floor, Decimal('-NaN'))
1437 self.assertRaises(ValueError, math.floor, Decimal('sNaN'))
1438 self.assertRaises(ValueError, math.floor, Decimal('NaN123'))
1439 self.assertRaises(OverflowError, math.floor, Decimal('Inf'))
1440 self.assertRaises(OverflowError, math.floor, Decimal('-Inf'))
1441
1442 #ceiling
1443 test_pairs = [
1444 ('123.00', 123),
1445 ('3.2', 4),
1446 ('3.54', 4),
1447 ('3.899', 4),
1448 ('-2.3', -2),
1449 ('-11.0', -11),
1450 ('0.0', 0),
1451 ('-0E3', 0),
1452 ]
1453 for d, i in test_pairs:
1454 self.assertEqual(math.ceil(Decimal(d)), i)
1455 self.assertRaises(ValueError, math.ceil, Decimal('-NaN'))
1456 self.assertRaises(ValueError, math.ceil, Decimal('sNaN'))
1457 self.assertRaises(ValueError, math.ceil, Decimal('NaN123'))
1458 self.assertRaises(OverflowError, math.ceil, Decimal('Inf'))
1459 self.assertRaises(OverflowError, math.ceil, Decimal('-Inf'))
1460
1461 #round, single argument
1462 test_pairs = [
1463 ('123.00', 123),
1464 ('3.2', 3),
1465 ('3.54', 4),
1466 ('3.899', 4),
1467 ('-2.3', -2),
1468 ('-11.0', -11),
1469 ('0.0', 0),
1470 ('-0E3', 0),
1471 ('-3.5', -4),
1472 ('-2.5', -2),
1473 ('-1.5', -2),
1474 ('-0.5', 0),
1475 ('0.5', 0),
1476 ('1.5', 2),
1477 ('2.5', 2),
1478 ('3.5', 4),
1479 ]
1480 for d, i in test_pairs:
1481 self.assertEqual(round(Decimal(d)), i)
1482 self.assertRaises(ValueError, round, Decimal('-NaN'))
1483 self.assertRaises(ValueError, round, Decimal('sNaN'))
1484 self.assertRaises(ValueError, round, Decimal('NaN123'))
1485 self.assertRaises(OverflowError, round, Decimal('Inf'))
1486 self.assertRaises(OverflowError, round, Decimal('-Inf'))
1487
1488 #round, two arguments; this is essentially equivalent
1489 #to quantize, which is already extensively tested
1490 test_triples = [
1491 ('123.456', -4, '0E+4'),
1492 ('123.456', -3, '0E+3'),
1493 ('123.456', -2, '1E+2'),
1494 ('123.456', -1, '1.2E+2'),
1495 ('123.456', 0, '123'),
1496 ('123.456', 1, '123.5'),
1497 ('123.456', 2, '123.46'),
1498 ('123.456', 3, '123.456'),
1499 ('123.456', 4, '123.4560'),
1500 ('123.455', 2, '123.46'),
1501 ('123.445', 2, '123.44'),
1502 ('Inf', 4, 'NaN'),
1503 ('-Inf', -23, 'NaN'),
1504 ('sNaN314', 3, 'NaN314'),
1505 ]
1506 for d, n, r in test_triples:
1507 self.assertEqual(str(round(Decimal(d), n)), r)
1508
1509
1510
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001511 def test_eval_round_trip(self):
1512
1513 #with zero
1514 d = Decimal( (0, (0,), 0) )
1515 self.assertEqual(d, eval(repr(d)))
1516
1517 #int
1518 d = Decimal( (1, (4, 5), 0) )
1519 self.assertEqual(d, eval(repr(d)))
1520
1521 #float
1522 d = Decimal( (0, (4, 5, 3, 4), -2) )
1523 self.assertEqual(d, eval(repr(d)))
1524
1525 #weird
1526 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1527 self.assertEqual(d, eval(repr(d)))
1528
1529 def test_as_tuple(self):
1530
1531 #with zero
1532 d = Decimal(0)
1533 self.assertEqual(d.as_tuple(), (0, (0,), 0) )
1534
1535 #int
1536 d = Decimal(-45)
1537 self.assertEqual(d.as_tuple(), (1, (4, 5), 0) )
1538
1539 #complicated string
1540 d = Decimal("-4.34913534E-17")
1541 self.assertEqual(d.as_tuple(), (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1542
1543 #inf
1544 d = Decimal("Infinity")
1545 self.assertEqual(d.as_tuple(), (0, (0,), 'F') )
1546
Guido van Rossum8ce8a782007-11-01 19:42:39 +00001547 #leading zeros in coefficient should be stripped
1548 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), -2) )
1549 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), -2) )
1550 d = Decimal( (1, (0, 0, 0), 37) )
1551 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1552 d = Decimal( (1, (), 37) )
1553 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1554
1555 #leading zeros in NaN diagnostic info should be stripped
1556 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), 'n') )
1557 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), 'n') )
1558 d = Decimal( (1, (0, 0, 0), 'N') )
1559 self.assertEqual(d.as_tuple(), (1, (), 'N') )
1560 d = Decimal( (1, (), 'n') )
1561 self.assertEqual(d.as_tuple(), (1, (), 'n') )
1562
1563 #coefficient in infinity should be ignored
1564 d = Decimal( (0, (4, 5, 3, 4), 'F') )
1565 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
1566 d = Decimal( (1, (0, 2, 7, 1), 'F') )
1567 self.assertEqual(d.as_tuple(), (1, (0,), 'F'))
1568
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001569 def test_immutability_operations(self):
1570 # Do operations and check that it didn't change change internal objects.
1571
1572 d1 = Decimal('-25e55')
1573 b1 = Decimal('-25e55')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001574 d2 = Decimal('33e+33')
1575 b2 = Decimal('33e+33')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001576
1577 def checkSameDec(operation, useOther=False):
1578 if useOther:
1579 eval("d1." + operation + "(d2)")
1580 self.assertEqual(d1._sign, b1._sign)
1581 self.assertEqual(d1._int, b1._int)
1582 self.assertEqual(d1._exp, b1._exp)
1583 self.assertEqual(d2._sign, b2._sign)
1584 self.assertEqual(d2._int, b2._int)
1585 self.assertEqual(d2._exp, b2._exp)
1586 else:
1587 eval("d1." + operation + "()")
1588 self.assertEqual(d1._sign, b1._sign)
1589 self.assertEqual(d1._int, b1._int)
1590 self.assertEqual(d1._exp, b1._exp)
1591 return
1592
1593 Decimal(d1)
1594 self.assertEqual(d1._sign, b1._sign)
1595 self.assertEqual(d1._int, b1._int)
1596 self.assertEqual(d1._exp, b1._exp)
1597
1598 checkSameDec("__abs__")
1599 checkSameDec("__add__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001600 checkSameDec("__divmod__", True)
Christian Heimes77c02eb2008-02-09 02:18:51 +00001601 checkSameDec("__eq__", True)
1602 checkSameDec("__ne__", True)
1603 checkSameDec("__le__", True)
1604 checkSameDec("__lt__", True)
1605 checkSameDec("__ge__", True)
1606 checkSameDec("__gt__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001607 checkSameDec("__float__")
1608 checkSameDec("__floordiv__", True)
1609 checkSameDec("__hash__")
1610 checkSameDec("__int__")
Christian Heimes969fe572008-01-25 11:23:10 +00001611 checkSameDec("__trunc__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001612 checkSameDec("__mod__", True)
1613 checkSameDec("__mul__", True)
1614 checkSameDec("__neg__")
Jack Diederich4dafcc42006-11-28 19:15:13 +00001615 checkSameDec("__bool__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001616 checkSameDec("__pos__")
1617 checkSameDec("__pow__", True)
1618 checkSameDec("__radd__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001619 checkSameDec("__rdivmod__", True)
1620 checkSameDec("__repr__")
1621 checkSameDec("__rfloordiv__", True)
1622 checkSameDec("__rmod__", True)
1623 checkSameDec("__rmul__", True)
1624 checkSameDec("__rpow__", True)
1625 checkSameDec("__rsub__", True)
1626 checkSameDec("__str__")
1627 checkSameDec("__sub__", True)
1628 checkSameDec("__truediv__", True)
1629 checkSameDec("adjusted")
1630 checkSameDec("as_tuple")
1631 checkSameDec("compare", True)
1632 checkSameDec("max", True)
1633 checkSameDec("min", True)
1634 checkSameDec("normalize")
1635 checkSameDec("quantize", True)
1636 checkSameDec("remainder_near", True)
1637 checkSameDec("same_quantum", True)
1638 checkSameDec("sqrt")
1639 checkSameDec("to_eng_string")
1640 checkSameDec("to_integral")
1641
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001642 def test_subclassing(self):
1643 # Different behaviours when subclassing Decimal
1644
1645 class MyDecimal(Decimal):
1646 pass
1647
1648 d1 = MyDecimal(1)
1649 d2 = MyDecimal(2)
1650 d = d1 + d2
Ezio Melotti6607d512010-04-03 14:59:49 +00001651 self.assertIs(type(d), Decimal)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001652
1653 d = d1.max(d2)
Ezio Melotti6607d512010-04-03 14:59:49 +00001654 self.assertIs(type(d), Decimal)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001655
Christian Heimes0348fb62008-03-26 12:55:56 +00001656 def test_implicit_context(self):
1657 # Check results when context given implicitly. (Issue 2478)
1658 c = getcontext()
1659 self.assertEqual(str(Decimal(0).sqrt()),
1660 str(c.sqrt(Decimal(0))))
1661
Mark Dickinsona2d1fe02009-10-29 12:23:02 +00001662 def test_conversions_from_int(self):
1663 # Check that methods taking a second Decimal argument will
1664 # always accept an integer in place of a Decimal.
1665 self.assertEqual(Decimal(4).compare(3),
1666 Decimal(4).compare(Decimal(3)))
1667 self.assertEqual(Decimal(4).compare_signal(3),
1668 Decimal(4).compare_signal(Decimal(3)))
1669 self.assertEqual(Decimal(4).compare_total(3),
1670 Decimal(4).compare_total(Decimal(3)))
1671 self.assertEqual(Decimal(4).compare_total_mag(3),
1672 Decimal(4).compare_total_mag(Decimal(3)))
1673 self.assertEqual(Decimal(10101).logical_and(1001),
1674 Decimal(10101).logical_and(Decimal(1001)))
1675 self.assertEqual(Decimal(10101).logical_or(1001),
1676 Decimal(10101).logical_or(Decimal(1001)))
1677 self.assertEqual(Decimal(10101).logical_xor(1001),
1678 Decimal(10101).logical_xor(Decimal(1001)))
1679 self.assertEqual(Decimal(567).max(123),
1680 Decimal(567).max(Decimal(123)))
1681 self.assertEqual(Decimal(567).max_mag(123),
1682 Decimal(567).max_mag(Decimal(123)))
1683 self.assertEqual(Decimal(567).min(123),
1684 Decimal(567).min(Decimal(123)))
1685 self.assertEqual(Decimal(567).min_mag(123),
1686 Decimal(567).min_mag(Decimal(123)))
1687 self.assertEqual(Decimal(567).next_toward(123),
1688 Decimal(567).next_toward(Decimal(123)))
1689 self.assertEqual(Decimal(1234).quantize(100),
1690 Decimal(1234).quantize(Decimal(100)))
1691 self.assertEqual(Decimal(768).remainder_near(1234),
1692 Decimal(768).remainder_near(Decimal(1234)))
1693 self.assertEqual(Decimal(123).rotate(1),
1694 Decimal(123).rotate(Decimal(1)))
1695 self.assertEqual(Decimal(1234).same_quantum(1000),
1696 Decimal(1234).same_quantum(Decimal(1000)))
1697 self.assertEqual(Decimal('9.123').scaleb(-100),
1698 Decimal('9.123').scaleb(Decimal(-100)))
1699 self.assertEqual(Decimal(456).shift(-1),
1700 Decimal(456).shift(Decimal(-1)))
1701
1702 self.assertEqual(Decimal(-12).fma(Decimal(45), 67),
1703 Decimal(-12).fma(Decimal(45), Decimal(67)))
1704 self.assertEqual(Decimal(-12).fma(45, 67),
1705 Decimal(-12).fma(Decimal(45), Decimal(67)))
1706 self.assertEqual(Decimal(-12).fma(45, Decimal(67)),
1707 Decimal(-12).fma(Decimal(45), Decimal(67)))
1708
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001709
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001710class DecimalPythonAPItests(unittest.TestCase):
1711
Raymond Hettinger82417ca2009-02-03 03:54:28 +00001712 def test_abc(self):
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001713 self.assertTrue(issubclass(Decimal, numbers.Number))
Ezio Melotti6607d512010-04-03 14:59:49 +00001714 self.assertFalse(issubclass(Decimal, numbers.Real))
Ezio Melottie9615932010-01-24 19:26:24 +00001715 self.assertIsInstance(Decimal(0), numbers.Number)
1716 self.assertNotIsInstance(Decimal(0), numbers.Real)
Raymond Hettinger82417ca2009-02-03 03:54:28 +00001717
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001718 def test_pickle(self):
1719 d = Decimal('-3.141590000')
1720 p = pickle.dumps(d)
1721 e = pickle.loads(p)
1722 self.assertEqual(d, e)
1723
Raymond Hettinger5548be22004-07-05 18:49:38 +00001724 def test_int(self):
Raymond Hettinger605ed022004-11-24 07:28:48 +00001725 for x in range(-250, 250):
1726 s = '%0.2f' % (x / 100.0)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001727 # should work the same as for floats
1728 self.assertEqual(int(Decimal(s)), int(float(s)))
Raymond Hettinger605ed022004-11-24 07:28:48 +00001729 # should work the same as to_integral in the ROUND_DOWN mode
Raymond Hettinger5548be22004-07-05 18:49:38 +00001730 d = Decimal(s)
Raymond Hettinger605ed022004-11-24 07:28:48 +00001731 r = d.to_integral(ROUND_DOWN)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001732 self.assertEqual(Decimal(int(d)), r)
1733
Mark Dickinson825fce32009-09-07 18:08:12 +00001734 self.assertRaises(ValueError, int, Decimal('-nan'))
1735 self.assertRaises(ValueError, int, Decimal('snan'))
1736 self.assertRaises(OverflowError, int, Decimal('inf'))
1737 self.assertRaises(OverflowError, int, Decimal('-inf'))
1738
Christian Heimes969fe572008-01-25 11:23:10 +00001739 def test_trunc(self):
1740 for x in range(-250, 250):
1741 s = '%0.2f' % (x / 100.0)
1742 # should work the same as for floats
1743 self.assertEqual(int(Decimal(s)), int(float(s)))
1744 # should work the same as to_integral in the ROUND_DOWN mode
1745 d = Decimal(s)
1746 r = d.to_integral(ROUND_DOWN)
Christian Heimes400adb02008-02-01 08:12:03 +00001747 self.assertEqual(Decimal(math.trunc(d)), r)
Christian Heimes969fe572008-01-25 11:23:10 +00001748
Raymond Hettinger771ed762009-01-03 19:20:32 +00001749 def test_from_float(self):
1750
1751 class MyDecimal(Decimal):
1752 pass
1753
1754 r = MyDecimal.from_float(0.1)
1755 self.assertEqual(type(r), MyDecimal)
1756 self.assertEqual(str(r),
1757 '0.1000000000000000055511151231257827021181583404541015625')
1758 bigint = 12345678901234567890123456789
1759 self.assertEqual(MyDecimal.from_float(bigint), MyDecimal(bigint))
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001760 self.assertTrue(MyDecimal.from_float(float('nan')).is_qnan())
1761 self.assertTrue(MyDecimal.from_float(float('inf')).is_infinite())
1762 self.assertTrue(MyDecimal.from_float(float('-inf')).is_infinite())
Raymond Hettinger771ed762009-01-03 19:20:32 +00001763 self.assertEqual(str(MyDecimal.from_float(float('nan'))),
1764 str(Decimal('NaN')))
1765 self.assertEqual(str(MyDecimal.from_float(float('inf'))),
1766 str(Decimal('Infinity')))
1767 self.assertEqual(str(MyDecimal.from_float(float('-inf'))),
1768 str(Decimal('-Infinity')))
1769 self.assertRaises(TypeError, MyDecimal.from_float, 'abc')
1770 for i in range(200):
1771 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
1772 self.assertEqual(x, float(MyDecimal.from_float(x))) # roundtrip
1773
1774 def test_create_decimal_from_float(self):
1775 context = Context(prec=5, rounding=ROUND_DOWN)
1776 self.assertEqual(
1777 context.create_decimal_from_float(math.pi),
1778 Decimal('3.1415')
1779 )
1780 context = Context(prec=5, rounding=ROUND_UP)
1781 self.assertEqual(
1782 context.create_decimal_from_float(math.pi),
1783 Decimal('3.1416')
1784 )
1785 context = Context(prec=5, traps=[Inexact])
1786 self.assertRaises(
1787 Inexact,
1788 context.create_decimal_from_float,
1789 math.pi
1790 )
1791 self.assertEqual(repr(context.create_decimal_from_float(-0.0)),
1792 "Decimal('-0')")
1793 self.assertEqual(repr(context.create_decimal_from_float(1.0)),
1794 "Decimal('1')")
1795 self.assertEqual(repr(context.create_decimal_from_float(10)),
1796 "Decimal('10')")
1797
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00001798class ContextAPItests(unittest.TestCase):
1799
1800 def test_pickle(self):
1801 c = Context()
1802 e = pickle.loads(pickle.dumps(c))
1803 for k in vars(c):
1804 v1 = vars(c)[k]
1805 v2 = vars(e)[k]
1806 self.assertEqual(v1, v2)
1807
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001808 def test_equality_with_other_types(self):
Benjamin Peterson577473f2010-01-19 00:09:57 +00001809 self.assertIn(Decimal(10), ['a', 1.0, Decimal(10), (1,2), {}])
1810 self.assertNotIn(Decimal(10), ['a', 1.0, (1,2), {}])
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001811
Raymond Hettinger955d2b22004-08-08 20:17:45 +00001812 def test_copy(self):
1813 # All copies should be deep
1814 c = Context()
1815 d = c.copy()
1816 self.assertNotEqual(id(c), id(d))
1817 self.assertNotEqual(id(c.flags), id(d.flags))
1818 self.assertNotEqual(id(c.traps), id(d.traps))
1819
Mark Dickinsonb1d8e322010-05-22 18:35:36 +00001820 def test__clamp(self):
1821 # In Python 3.2, the private attribute `_clamp` was made
1822 # public (issue 8540), with the old `_clamp` becoming a
1823 # property wrapping `clamp`. For the duration of Python 3.2
1824 # only, the attribute should be gettable/settable via both
1825 # `clamp` and `_clamp`; in Python 3.3, `_clamp` should be
1826 # removed.
1827 c = Context(clamp = 0)
1828 self.assertEqual(c.clamp, 0)
1829
1830 with check_warnings(("", DeprecationWarning)):
1831 c._clamp = 1
1832 self.assertEqual(c.clamp, 1)
1833 with check_warnings(("", DeprecationWarning)):
1834 self.assertEqual(c._clamp, 1)
1835 c.clamp = 0
1836 self.assertEqual(c.clamp, 0)
1837 with check_warnings(("", DeprecationWarning)):
1838 self.assertEqual(c._clamp, 0)
1839
Mark Dickinson84230a12010-02-18 14:49:50 +00001840 def test_abs(self):
1841 c = Context()
1842 d = c.abs(Decimal(-1))
1843 self.assertEqual(c.abs(-1), d)
1844 self.assertRaises(TypeError, c.abs, '-1')
1845
1846 def test_add(self):
1847 c = Context()
1848 d = c.add(Decimal(1), Decimal(1))
1849 self.assertEqual(c.add(1, 1), d)
1850 self.assertEqual(c.add(Decimal(1), 1), d)
1851 self.assertEqual(c.add(1, Decimal(1)), d)
1852 self.assertRaises(TypeError, c.add, '1', 1)
1853 self.assertRaises(TypeError, c.add, 1, '1')
1854
1855 def test_compare(self):
1856 c = Context()
1857 d = c.compare(Decimal(1), Decimal(1))
1858 self.assertEqual(c.compare(1, 1), d)
1859 self.assertEqual(c.compare(Decimal(1), 1), d)
1860 self.assertEqual(c.compare(1, Decimal(1)), d)
1861 self.assertRaises(TypeError, c.compare, '1', 1)
1862 self.assertRaises(TypeError, c.compare, 1, '1')
1863
1864 def test_compare_signal(self):
1865 c = Context()
1866 d = c.compare_signal(Decimal(1), Decimal(1))
1867 self.assertEqual(c.compare_signal(1, 1), d)
1868 self.assertEqual(c.compare_signal(Decimal(1), 1), d)
1869 self.assertEqual(c.compare_signal(1, Decimal(1)), d)
1870 self.assertRaises(TypeError, c.compare_signal, '1', 1)
1871 self.assertRaises(TypeError, c.compare_signal, 1, '1')
1872
1873 def test_compare_total(self):
1874 c = Context()
1875 d = c.compare_total(Decimal(1), Decimal(1))
1876 self.assertEqual(c.compare_total(1, 1), d)
1877 self.assertEqual(c.compare_total(Decimal(1), 1), d)
1878 self.assertEqual(c.compare_total(1, Decimal(1)), d)
1879 self.assertRaises(TypeError, c.compare_total, '1', 1)
1880 self.assertRaises(TypeError, c.compare_total, 1, '1')
1881
1882 def test_compare_total_mag(self):
1883 c = Context()
1884 d = c.compare_total_mag(Decimal(1), Decimal(1))
1885 self.assertEqual(c.compare_total_mag(1, 1), d)
1886 self.assertEqual(c.compare_total_mag(Decimal(1), 1), d)
1887 self.assertEqual(c.compare_total_mag(1, Decimal(1)), d)
1888 self.assertRaises(TypeError, c.compare_total_mag, '1', 1)
1889 self.assertRaises(TypeError, c.compare_total_mag, 1, '1')
1890
1891 def test_copy_abs(self):
1892 c = Context()
1893 d = c.copy_abs(Decimal(-1))
1894 self.assertEqual(c.copy_abs(-1), d)
1895 self.assertRaises(TypeError, c.copy_abs, '-1')
1896
1897 def test_copy_decimal(self):
1898 c = Context()
1899 d = c.copy_decimal(Decimal(-1))
1900 self.assertEqual(c.copy_decimal(-1), d)
1901 self.assertRaises(TypeError, c.copy_decimal, '-1')
1902
1903 def test_copy_negate(self):
1904 c = Context()
1905 d = c.copy_negate(Decimal(-1))
1906 self.assertEqual(c.copy_negate(-1), d)
1907 self.assertRaises(TypeError, c.copy_negate, '-1')
1908
1909 def test_copy_sign(self):
1910 c = Context()
1911 d = c.copy_sign(Decimal(1), Decimal(-2))
1912 self.assertEqual(c.copy_sign(1, -2), d)
1913 self.assertEqual(c.copy_sign(Decimal(1), -2), d)
1914 self.assertEqual(c.copy_sign(1, Decimal(-2)), d)
1915 self.assertRaises(TypeError, c.copy_sign, '1', -2)
1916 self.assertRaises(TypeError, c.copy_sign, 1, '-2')
1917
1918 def test_divide(self):
1919 c = Context()
1920 d = c.divide(Decimal(1), Decimal(2))
1921 self.assertEqual(c.divide(1, 2), d)
1922 self.assertEqual(c.divide(Decimal(1), 2), d)
1923 self.assertEqual(c.divide(1, Decimal(2)), d)
1924 self.assertRaises(TypeError, c.divide, '1', 2)
1925 self.assertRaises(TypeError, c.divide, 1, '2')
1926
1927 def test_divide_int(self):
1928 c = Context()
1929 d = c.divide_int(Decimal(1), Decimal(2))
1930 self.assertEqual(c.divide_int(1, 2), d)
1931 self.assertEqual(c.divide_int(Decimal(1), 2), d)
1932 self.assertEqual(c.divide_int(1, Decimal(2)), d)
1933 self.assertRaises(TypeError, c.divide_int, '1', 2)
1934 self.assertRaises(TypeError, c.divide_int, 1, '2')
1935
1936 def test_divmod(self):
1937 c = Context()
1938 d = c.divmod(Decimal(1), Decimal(2))
1939 self.assertEqual(c.divmod(1, 2), d)
1940 self.assertEqual(c.divmod(Decimal(1), 2), d)
1941 self.assertEqual(c.divmod(1, Decimal(2)), d)
1942 self.assertRaises(TypeError, c.divmod, '1', 2)
1943 self.assertRaises(TypeError, c.divmod, 1, '2')
1944
1945 def test_exp(self):
1946 c = Context()
1947 d = c.exp(Decimal(10))
1948 self.assertEqual(c.exp(10), d)
1949 self.assertRaises(TypeError, c.exp, '10')
1950
1951 def test_fma(self):
1952 c = Context()
1953 d = c.fma(Decimal(2), Decimal(3), Decimal(4))
1954 self.assertEqual(c.fma(2, 3, 4), d)
1955 self.assertEqual(c.fma(Decimal(2), 3, 4), d)
1956 self.assertEqual(c.fma(2, Decimal(3), 4), d)
1957 self.assertEqual(c.fma(2, 3, Decimal(4)), d)
1958 self.assertEqual(c.fma(Decimal(2), Decimal(3), 4), d)
1959 self.assertRaises(TypeError, c.fma, '2', 3, 4)
1960 self.assertRaises(TypeError, c.fma, 2, '3', 4)
1961 self.assertRaises(TypeError, c.fma, 2, 3, '4')
1962
1963 def test_is_finite(self):
1964 c = Context()
1965 d = c.is_finite(Decimal(10))
1966 self.assertEqual(c.is_finite(10), d)
1967 self.assertRaises(TypeError, c.is_finite, '10')
1968
1969 def test_is_infinite(self):
1970 c = Context()
1971 d = c.is_infinite(Decimal(10))
1972 self.assertEqual(c.is_infinite(10), d)
1973 self.assertRaises(TypeError, c.is_infinite, '10')
1974
1975 def test_is_nan(self):
1976 c = Context()
1977 d = c.is_nan(Decimal(10))
1978 self.assertEqual(c.is_nan(10), d)
1979 self.assertRaises(TypeError, c.is_nan, '10')
1980
1981 def test_is_normal(self):
1982 c = Context()
1983 d = c.is_normal(Decimal(10))
1984 self.assertEqual(c.is_normal(10), d)
1985 self.assertRaises(TypeError, c.is_normal, '10')
1986
1987 def test_is_qnan(self):
1988 c = Context()
1989 d = c.is_qnan(Decimal(10))
1990 self.assertEqual(c.is_qnan(10), d)
1991 self.assertRaises(TypeError, c.is_qnan, '10')
1992
1993 def test_is_signed(self):
1994 c = Context()
1995 d = c.is_signed(Decimal(10))
1996 self.assertEqual(c.is_signed(10), d)
1997 self.assertRaises(TypeError, c.is_signed, '10')
1998
1999 def test_is_snan(self):
2000 c = Context()
2001 d = c.is_snan(Decimal(10))
2002 self.assertEqual(c.is_snan(10), d)
2003 self.assertRaises(TypeError, c.is_snan, '10')
2004
2005 def test_is_subnormal(self):
2006 c = Context()
2007 d = c.is_subnormal(Decimal(10))
2008 self.assertEqual(c.is_subnormal(10), d)
2009 self.assertRaises(TypeError, c.is_subnormal, '10')
2010
2011 def test_is_zero(self):
2012 c = Context()
2013 d = c.is_zero(Decimal(10))
2014 self.assertEqual(c.is_zero(10), d)
2015 self.assertRaises(TypeError, c.is_zero, '10')
2016
2017 def test_ln(self):
2018 c = Context()
2019 d = c.ln(Decimal(10))
2020 self.assertEqual(c.ln(10), d)
2021 self.assertRaises(TypeError, c.ln, '10')
2022
2023 def test_log10(self):
2024 c = Context()
2025 d = c.log10(Decimal(10))
2026 self.assertEqual(c.log10(10), d)
2027 self.assertRaises(TypeError, c.log10, '10')
2028
2029 def test_logb(self):
2030 c = Context()
2031 d = c.logb(Decimal(10))
2032 self.assertEqual(c.logb(10), d)
2033 self.assertRaises(TypeError, c.logb, '10')
2034
2035 def test_logical_and(self):
2036 c = Context()
2037 d = c.logical_and(Decimal(1), Decimal(1))
2038 self.assertEqual(c.logical_and(1, 1), d)
2039 self.assertEqual(c.logical_and(Decimal(1), 1), d)
2040 self.assertEqual(c.logical_and(1, Decimal(1)), d)
2041 self.assertRaises(TypeError, c.logical_and, '1', 1)
2042 self.assertRaises(TypeError, c.logical_and, 1, '1')
2043
2044 def test_logical_invert(self):
2045 c = Context()
2046 d = c.logical_invert(Decimal(1000))
2047 self.assertEqual(c.logical_invert(1000), d)
2048 self.assertRaises(TypeError, c.logical_invert, '1000')
2049
2050 def test_logical_or(self):
2051 c = Context()
2052 d = c.logical_or(Decimal(1), Decimal(1))
2053 self.assertEqual(c.logical_or(1, 1), d)
2054 self.assertEqual(c.logical_or(Decimal(1), 1), d)
2055 self.assertEqual(c.logical_or(1, Decimal(1)), d)
2056 self.assertRaises(TypeError, c.logical_or, '1', 1)
2057 self.assertRaises(TypeError, c.logical_or, 1, '1')
2058
2059 def test_logical_xor(self):
2060 c = Context()
2061 d = c.logical_xor(Decimal(1), Decimal(1))
2062 self.assertEqual(c.logical_xor(1, 1), d)
2063 self.assertEqual(c.logical_xor(Decimal(1), 1), d)
2064 self.assertEqual(c.logical_xor(1, Decimal(1)), d)
2065 self.assertRaises(TypeError, c.logical_xor, '1', 1)
2066 self.assertRaises(TypeError, c.logical_xor, 1, '1')
2067
2068 def test_max(self):
2069 c = Context()
2070 d = c.max(Decimal(1), Decimal(2))
2071 self.assertEqual(c.max(1, 2), d)
2072 self.assertEqual(c.max(Decimal(1), 2), d)
2073 self.assertEqual(c.max(1, Decimal(2)), d)
2074 self.assertRaises(TypeError, c.max, '1', 2)
2075 self.assertRaises(TypeError, c.max, 1, '2')
2076
2077 def test_max_mag(self):
2078 c = Context()
2079 d = c.max_mag(Decimal(1), Decimal(2))
2080 self.assertEqual(c.max_mag(1, 2), d)
2081 self.assertEqual(c.max_mag(Decimal(1), 2), d)
2082 self.assertEqual(c.max_mag(1, Decimal(2)), d)
2083 self.assertRaises(TypeError, c.max_mag, '1', 2)
2084 self.assertRaises(TypeError, c.max_mag, 1, '2')
2085
2086 def test_min(self):
2087 c = Context()
2088 d = c.min(Decimal(1), Decimal(2))
2089 self.assertEqual(c.min(1, 2), d)
2090 self.assertEqual(c.min(Decimal(1), 2), d)
2091 self.assertEqual(c.min(1, Decimal(2)), d)
2092 self.assertRaises(TypeError, c.min, '1', 2)
2093 self.assertRaises(TypeError, c.min, 1, '2')
2094
2095 def test_min_mag(self):
2096 c = Context()
2097 d = c.min_mag(Decimal(1), Decimal(2))
2098 self.assertEqual(c.min_mag(1, 2), d)
2099 self.assertEqual(c.min_mag(Decimal(1), 2), d)
2100 self.assertEqual(c.min_mag(1, Decimal(2)), d)
2101 self.assertRaises(TypeError, c.min_mag, '1', 2)
2102 self.assertRaises(TypeError, c.min_mag, 1, '2')
2103
2104 def test_minus(self):
2105 c = Context()
2106 d = c.minus(Decimal(10))
2107 self.assertEqual(c.minus(10), d)
2108 self.assertRaises(TypeError, c.minus, '10')
2109
2110 def test_multiply(self):
2111 c = Context()
2112 d = c.multiply(Decimal(1), Decimal(2))
2113 self.assertEqual(c.multiply(1, 2), d)
2114 self.assertEqual(c.multiply(Decimal(1), 2), d)
2115 self.assertEqual(c.multiply(1, Decimal(2)), d)
2116 self.assertRaises(TypeError, c.multiply, '1', 2)
2117 self.assertRaises(TypeError, c.multiply, 1, '2')
2118
2119 def test_next_minus(self):
2120 c = Context()
2121 d = c.next_minus(Decimal(10))
2122 self.assertEqual(c.next_minus(10), d)
2123 self.assertRaises(TypeError, c.next_minus, '10')
2124
2125 def test_next_plus(self):
2126 c = Context()
2127 d = c.next_plus(Decimal(10))
2128 self.assertEqual(c.next_plus(10), d)
2129 self.assertRaises(TypeError, c.next_plus, '10')
2130
2131 def test_next_toward(self):
2132 c = Context()
2133 d = c.next_toward(Decimal(1), Decimal(2))
2134 self.assertEqual(c.next_toward(1, 2), d)
2135 self.assertEqual(c.next_toward(Decimal(1), 2), d)
2136 self.assertEqual(c.next_toward(1, Decimal(2)), d)
2137 self.assertRaises(TypeError, c.next_toward, '1', 2)
2138 self.assertRaises(TypeError, c.next_toward, 1, '2')
2139
2140 def test_normalize(self):
2141 c = Context()
2142 d = c.normalize(Decimal(10))
2143 self.assertEqual(c.normalize(10), d)
2144 self.assertRaises(TypeError, c.normalize, '10')
2145
2146 def test_number_class(self):
2147 c = Context()
2148 self.assertEqual(c.number_class(123), c.number_class(Decimal(123)))
2149 self.assertEqual(c.number_class(0), c.number_class(Decimal(0)))
2150 self.assertEqual(c.number_class(-45), c.number_class(Decimal(-45)))
2151
2152 def test_power(self):
2153 c = Context()
2154 d = c.power(Decimal(1), Decimal(4), Decimal(2))
2155 self.assertEqual(c.power(1, 4, 2), d)
2156 self.assertEqual(c.power(Decimal(1), 4, 2), d)
2157 self.assertEqual(c.power(1, Decimal(4), 2), d)
2158 self.assertEqual(c.power(1, 4, Decimal(2)), d)
2159 self.assertEqual(c.power(Decimal(1), Decimal(4), 2), d)
2160 self.assertRaises(TypeError, c.power, '1', 4, 2)
2161 self.assertRaises(TypeError, c.power, 1, '4', 2)
2162 self.assertRaises(TypeError, c.power, 1, 4, '2')
2163
2164 def test_plus(self):
2165 c = Context()
2166 d = c.plus(Decimal(10))
2167 self.assertEqual(c.plus(10), d)
2168 self.assertRaises(TypeError, c.plus, '10')
2169
2170 def test_quantize(self):
2171 c = Context()
2172 d = c.quantize(Decimal(1), Decimal(2))
2173 self.assertEqual(c.quantize(1, 2), d)
2174 self.assertEqual(c.quantize(Decimal(1), 2), d)
2175 self.assertEqual(c.quantize(1, Decimal(2)), d)
2176 self.assertRaises(TypeError, c.quantize, '1', 2)
2177 self.assertRaises(TypeError, c.quantize, 1, '2')
2178
2179 def test_remainder(self):
2180 c = Context()
2181 d = c.remainder(Decimal(1), Decimal(2))
2182 self.assertEqual(c.remainder(1, 2), d)
2183 self.assertEqual(c.remainder(Decimal(1), 2), d)
2184 self.assertEqual(c.remainder(1, Decimal(2)), d)
2185 self.assertRaises(TypeError, c.remainder, '1', 2)
2186 self.assertRaises(TypeError, c.remainder, 1, '2')
2187
2188 def test_remainder_near(self):
2189 c = Context()
2190 d = c.remainder_near(Decimal(1), Decimal(2))
2191 self.assertEqual(c.remainder_near(1, 2), d)
2192 self.assertEqual(c.remainder_near(Decimal(1), 2), d)
2193 self.assertEqual(c.remainder_near(1, Decimal(2)), d)
2194 self.assertRaises(TypeError, c.remainder_near, '1', 2)
2195 self.assertRaises(TypeError, c.remainder_near, 1, '2')
2196
2197 def test_rotate(self):
2198 c = Context()
2199 d = c.rotate(Decimal(1), Decimal(2))
2200 self.assertEqual(c.rotate(1, 2), d)
2201 self.assertEqual(c.rotate(Decimal(1), 2), d)
2202 self.assertEqual(c.rotate(1, Decimal(2)), d)
2203 self.assertRaises(TypeError, c.rotate, '1', 2)
2204 self.assertRaises(TypeError, c.rotate, 1, '2')
2205
2206 def test_sqrt(self):
2207 c = Context()
2208 d = c.sqrt(Decimal(10))
2209 self.assertEqual(c.sqrt(10), d)
2210 self.assertRaises(TypeError, c.sqrt, '10')
2211
2212 def test_same_quantum(self):
2213 c = Context()
2214 d = c.same_quantum(Decimal(1), Decimal(2))
2215 self.assertEqual(c.same_quantum(1, 2), d)
2216 self.assertEqual(c.same_quantum(Decimal(1), 2), d)
2217 self.assertEqual(c.same_quantum(1, Decimal(2)), d)
2218 self.assertRaises(TypeError, c.same_quantum, '1', 2)
2219 self.assertRaises(TypeError, c.same_quantum, 1, '2')
2220
2221 def test_scaleb(self):
2222 c = Context()
2223 d = c.scaleb(Decimal(1), Decimal(2))
2224 self.assertEqual(c.scaleb(1, 2), d)
2225 self.assertEqual(c.scaleb(Decimal(1), 2), d)
2226 self.assertEqual(c.scaleb(1, Decimal(2)), d)
2227 self.assertRaises(TypeError, c.scaleb, '1', 2)
2228 self.assertRaises(TypeError, c.scaleb, 1, '2')
2229
2230 def test_shift(self):
2231 c = Context()
2232 d = c.shift(Decimal(1), Decimal(2))
2233 self.assertEqual(c.shift(1, 2), d)
2234 self.assertEqual(c.shift(Decimal(1), 2), d)
2235 self.assertEqual(c.shift(1, Decimal(2)), d)
2236 self.assertRaises(TypeError, c.shift, '1', 2)
2237 self.assertRaises(TypeError, c.shift, 1, '2')
2238
2239 def test_subtract(self):
2240 c = Context()
2241 d = c.subtract(Decimal(1), Decimal(2))
2242 self.assertEqual(c.subtract(1, 2), d)
2243 self.assertEqual(c.subtract(Decimal(1), 2), d)
2244 self.assertEqual(c.subtract(1, Decimal(2)), d)
2245 self.assertRaises(TypeError, c.subtract, '1', 2)
2246 self.assertRaises(TypeError, c.subtract, 1, '2')
2247
2248 def test_to_eng_string(self):
2249 c = Context()
2250 d = c.to_eng_string(Decimal(10))
2251 self.assertEqual(c.to_eng_string(10), d)
2252 self.assertRaises(TypeError, c.to_eng_string, '10')
2253
2254 def test_to_sci_string(self):
2255 c = Context()
2256 d = c.to_sci_string(Decimal(10))
2257 self.assertEqual(c.to_sci_string(10), d)
2258 self.assertRaises(TypeError, c.to_sci_string, '10')
2259
2260 def test_to_integral_exact(self):
2261 c = Context()
2262 d = c.to_integral_exact(Decimal(10))
2263 self.assertEqual(c.to_integral_exact(10), d)
2264 self.assertRaises(TypeError, c.to_integral_exact, '10')
2265
2266 def test_to_integral_value(self):
2267 c = Context()
2268 d = c.to_integral_value(Decimal(10))
2269 self.assertEqual(c.to_integral_value(10), d)
2270 self.assertRaises(TypeError, c.to_integral_value, '10')
2271
Thomas Wouters89f507f2006-12-13 04:49:30 +00002272class WithStatementTest(unittest.TestCase):
2273 # Can't do these as docstrings until Python 2.6
2274 # as doctest can't handle __future__ statements
2275
2276 def test_localcontext(self):
2277 # Use a copy of the current context in the block
2278 orig_ctx = getcontext()
2279 with localcontext() as enter_ctx:
2280 set_ctx = getcontext()
2281 final_ctx = getcontext()
Ezio Melotti6607d512010-04-03 14:59:49 +00002282 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
2283 self.assertIsNot(orig_ctx, set_ctx, 'did not copy the context')
2284 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
Thomas Wouters89f507f2006-12-13 04:49:30 +00002285
2286 def test_localcontextarg(self):
2287 # Use a copy of the supplied context in the block
2288 orig_ctx = getcontext()
2289 new_ctx = Context(prec=42)
2290 with localcontext(new_ctx) as enter_ctx:
2291 set_ctx = getcontext()
2292 final_ctx = getcontext()
Ezio Melotti6607d512010-04-03 14:59:49 +00002293 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
2294 self.assertEqual(set_ctx.prec, new_ctx.prec, 'did not set correct context')
2295 self.assertIsNot(new_ctx, set_ctx, 'did not copy the context')
2296 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
Thomas Wouters89f507f2006-12-13 04:49:30 +00002297
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002298class ContextFlags(unittest.TestCase):
2299 def test_flags_irrelevant(self):
2300 # check that the result (numeric result + flags raised) of an
2301 # arithmetic operation doesn't depend on the current flags
2302
2303 context = Context(prec=9, Emin = -999999999, Emax = 999999999,
2304 rounding=ROUND_HALF_EVEN, traps=[], flags=[])
2305
2306 # operations that raise various flags, in the form (function, arglist)
2307 operations = [
2308 (context._apply, [Decimal("100E-1000000009")]),
2309 (context.sqrt, [Decimal(2)]),
2310 (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]),
2311 (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]),
2312 (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]),
2313 ]
2314
2315 # try various flags individually, then a whole lot at once
2316 flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal],
2317 [Inexact, Rounded, Underflow, Clamped, Subnormal]]
2318
2319 for fn, args in operations:
2320 # find answer and flags raised using a clean context
2321 context.clear_flags()
2322 ans = fn(*args)
2323 flags = [k for k, v in context.flags.items() if v]
2324
2325 for extra_flags in flagsets:
2326 # set flags, before calling operation
2327 context.clear_flags()
2328 for flag in extra_flags:
2329 context._raise_error(flag)
2330 new_ans = fn(*args)
2331
2332 # flags that we expect to be set after the operation
2333 expected_flags = list(flags)
2334 for flag in extra_flags:
2335 if flag not in expected_flags:
2336 expected_flags.append(flag)
2337 expected_flags.sort(key=id)
2338
2339 # flags we actually got
2340 new_flags = [k for k,v in context.flags.items() if v]
2341 new_flags.sort(key=id)
2342
2343 self.assertEqual(ans, new_ans,
2344 "operation produces different answers depending on flags set: " +
2345 "expected %s, got %s." % (ans, new_ans))
2346 self.assertEqual(new_flags, expected_flags,
2347 "operation raises different flags depending on flags set: " +
2348 "expected %s, got %s" % (expected_flags, new_flags))
2349
2350def test_main(arith=False, verbose=None, todo_tests=None, debug=None):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002351 """ Execute the tests.
2352
Raymond Hettingered20ad82004-09-04 20:09:13 +00002353 Runs all arithmetic tests if arith is True or if the "decimal" resource
2354 is enabled in regrtest.py
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002355 """
Raymond Hettingered20ad82004-09-04 20:09:13 +00002356
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002357 init()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002358 global TEST_ALL, DEBUG
Raymond Hettingered20ad82004-09-04 20:09:13 +00002359 TEST_ALL = arith or is_resource_enabled('decimal')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002360 DEBUG = debug
Raymond Hettingered20ad82004-09-04 20:09:13 +00002361
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002362 if todo_tests is None:
2363 test_classes = [
2364 DecimalExplicitConstructionTest,
2365 DecimalImplicitConstructionTest,
2366 DecimalArithmeticOperatorsTest,
Christian Heimesf16baeb2008-02-29 14:57:44 +00002367 DecimalFormatTest,
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002368 DecimalUseOfContextTest,
2369 DecimalUsabilityTest,
2370 DecimalPythonAPItests,
2371 ContextAPItests,
2372 DecimalTest,
2373 WithStatementTest,
2374 ContextFlags
2375 ]
2376 else:
2377 test_classes = [DecimalTest]
2378
2379 # Dynamically build custom test definition for each file in the test
2380 # directory and add the definitions to the DecimalTest class. This
2381 # procedure insures that new files do not get skipped.
2382 for filename in os.listdir(directory):
2383 if '.decTest' not in filename or filename.startswith("."):
2384 continue
2385 head, tail = filename.split('.')
2386 if todo_tests is not None and head not in todo_tests:
2387 continue
2388 tester = lambda self, f=filename: self.eval_file(directory + f)
2389 setattr(DecimalTest, 'test_' + head, tester)
2390 del filename, head, tail, tester
2391
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002392
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002393 try:
2394 run_unittest(*test_classes)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002395 if todo_tests is None:
2396 import decimal as DecimalModule
2397 run_doctest(DecimalModule, verbose)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002398 finally:
2399 setcontext(ORIGINAL_CONTEXT)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002400
2401if __name__ == '__main__':
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002402 import optparse
2403 p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]")
2404 p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test')
2405 p.add_option('--skip', '-s', action='store_true', help='skip over 90% of the arithmetic tests')
2406 (opt, args) = p.parse_args()
2407
2408 if opt.skip:
2409 test_main(arith=False, verbose=True)
2410 elif args:
2411 test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002412 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00002413 test_main(arith=True, verbose=True)