blob: c9a096a86de7a44c8cb379fb2ceaec253a8123b9 [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
Jeffrey Yasskinca2b69f2008-02-01 06:22:46 +000027import math
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000028import os, sys
Mark Dickinsone096e822010-04-02 10:17:07 +000029import operator
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000030import pickle, copy
Jeffrey Yasskinca2b69f2008-02-01 06:22:46 +000031import unittest
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000032from decimal import *
Raymond Hettinger2c8585b2009-02-03 03:37:03 +000033import numbers
Florent Xicluna8f43cec2010-03-21 10:51:40 +000034from test.test_support import (run_unittest, run_doctest,
35 is_resource_enabled, check_py3k_warnings)
Raymond Hettinger0aeac102004-07-05 22:53:03 +000036import random
Raymond Hettinger7e71fa52004-12-18 19:07:19 +000037try:
38 import threading
39except ImportError:
40 threading = None
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000041
Raymond Hettingerfed52962004-07-14 15:41:57 +000042# Useful Test Constant
Mark Dickinson16cd2be2010-05-01 11:46:20 +000043Signals = tuple(getcontext().flags.keys())
Raymond Hettingerfed52962004-07-14 15:41:57 +000044
Mark Dickinson4f96f5f2010-05-04 14:25:50 +000045# Signals ordered with respect to precedence: when an operation
46# produces multiple signals, signals occurring later in the list
47# should be handled before those occurring earlier in the list.
48OrderedSignals = (Clamped, Rounded, Inexact, Subnormal,
49 Underflow, Overflow, DivisionByZero, InvalidOperation)
50
Tim Peters46cc7022006-03-31 04:11:16 +000051# Tests are built around these assumed context defaults.
52# test_main() restores the original context.
Neal Norwitzce4a9c92006-04-09 08:36:46 +000053def init():
54 global ORIGINAL_CONTEXT
55 ORIGINAL_CONTEXT = getcontext().copy()
Facundo Batistaee340e52008-05-02 17:39:00 +000056 DefaultTestContext = Context(
57 prec = 9,
58 rounding = ROUND_HALF_EVEN,
59 traps = dict.fromkeys(Signals, 0)
60 )
61 setcontext(DefaultTestContext)
Raymond Hettinger6ea48452004-07-03 12:26:21 +000062
Raymond Hettingered171ab2010-04-02 18:39:24 +000063# decorator for skipping tests on non-IEEE 754 platforms
64requires_IEEE_754 = unittest.skipUnless(
65 float.__getformat__("double").startswith("IEEE"),
66 "test requires IEEE 754 doubles")
67
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000068TESTDATADIR = 'decimaltestdata'
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +000069if __name__ == '__main__':
70 file = sys.argv[0]
71else:
72 file = __file__
73testdir = os.path.dirname(file) or os.curdir
Raymond Hettinger267b8682005-03-27 10:47:39 +000074directory = testdir + os.sep + TESTDATADIR + os.sep
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000075
Raymond Hettinger267b8682005-03-27 10:47:39 +000076skip_expected = not os.path.isdir(directory)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000077
Mark Dickinson539bff42009-10-08 16:28:39 +000078# list of individual .decTest test ids that correspond to tests that
79# we're skipping for one reason or another.
80skipped_test_ids = [
81 'scbx164', # skipping apparently implementation-specific scaleb
82 'scbx165', # tests, pending clarification of scaleb rules.
83]
84
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000085# Make sure it actually raises errors when not expected and caught in flags
86# Slower, since it runs some things several times.
87EXTENDEDERRORTEST = False
88
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000089#Map the test cases' error names to the actual errors
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000090ErrorNames = {'clamped' : Clamped,
Raymond Hettinger5aa478b2004-07-09 10:02:53 +000091 'conversion_syntax' : InvalidOperation,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000092 'division_by_zero' : DivisionByZero,
Raymond Hettinger5aa478b2004-07-09 10:02:53 +000093 'division_impossible' : InvalidOperation,
94 'division_undefined' : InvalidOperation,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000095 'inexact' : Inexact,
Raymond Hettinger5aa478b2004-07-09 10:02:53 +000096 'invalid_context' : InvalidOperation,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000097 'invalid_operation' : InvalidOperation,
98 'overflow' : Overflow,
99 'rounded' : Rounded,
100 'subnormal' : Subnormal,
101 'underflow' : Underflow}
102
103
104def Nonfunction(*args):
105 """Doesn't do anything."""
106 return None
107
108RoundingDict = {'ceiling' : ROUND_CEILING, #Maps test-case names to roundings.
109 'down' : ROUND_DOWN,
110 'floor' : ROUND_FLOOR,
111 'half_down' : ROUND_HALF_DOWN,
112 'half_even' : ROUND_HALF_EVEN,
113 'half_up' : ROUND_HALF_UP,
Facundo Batista353750c2007-09-13 18:13:15 +0000114 'up' : ROUND_UP,
115 '05up' : ROUND_05UP}
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000116
117# Name adapter to be able to change the Decimal and Context
118# interface without changing the test files from Cowlishaw
Facundo Batista1a191df2007-10-02 17:01:24 +0000119nameAdapter = {'and':'logical_and',
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000120 'apply':'_apply',
Facundo Batista353750c2007-09-13 18:13:15 +0000121 'class':'number_class',
122 'comparesig':'compare_signal',
123 'comparetotal':'compare_total',
124 'comparetotmag':'compare_total_mag',
Facundo Batista353750c2007-09-13 18:13:15 +0000125 'copy':'copy_decimal',
Facundo Batista1a191df2007-10-02 17:01:24 +0000126 'copyabs':'copy_abs',
Facundo Batista353750c2007-09-13 18:13:15 +0000127 'copynegate':'copy_negate',
128 'copysign':'copy_sign',
Facundo Batista1a191df2007-10-02 17:01:24 +0000129 'divideint':'divide_int',
Facundo Batista353750c2007-09-13 18:13:15 +0000130 'invert':'logical_invert',
Facundo Batista1a191df2007-10-02 17:01:24 +0000131 'iscanonical':'is_canonical',
132 'isfinite':'is_finite',
133 'isinfinite':'is_infinite',
134 'isnan':'is_nan',
135 'isnormal':'is_normal',
136 'isqnan':'is_qnan',
137 'issigned':'is_signed',
138 'issnan':'is_snan',
139 'issubnormal':'is_subnormal',
140 'iszero':'is_zero',
Facundo Batista353750c2007-09-13 18:13:15 +0000141 'maxmag':'max_mag',
142 'minmag':'min_mag',
143 'nextminus':'next_minus',
144 'nextplus':'next_plus',
145 'nexttoward':'next_toward',
Facundo Batista1a191df2007-10-02 17:01:24 +0000146 'or':'logical_or',
Facundo Batista353750c2007-09-13 18:13:15 +0000147 'reduce':'normalize',
Facundo Batista1a191df2007-10-02 17:01:24 +0000148 'remaindernear':'remainder_near',
149 'samequantum':'same_quantum',
150 'squareroot':'sqrt',
151 'toeng':'to_eng_string',
152 'tointegral':'to_integral_value',
153 'tointegralx':'to_integral_exact',
154 'tosci':'to_sci_string',
155 'xor':'logical_xor',
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000156 }
157
Facundo Batista1a191df2007-10-02 17:01:24 +0000158# The following functions return True/False rather than a Decimal instance
159
160LOGICAL_FUNCTIONS = (
161 'is_canonical',
162 'is_finite',
163 'is_infinite',
164 'is_nan',
165 'is_normal',
166 'is_qnan',
167 'is_signed',
168 'is_snan',
169 'is_subnormal',
170 'is_zero',
171 'same_quantum',
172 )
173
Facundo Batista353750c2007-09-13 18:13:15 +0000174# For some operations (currently exp, ln, log10, power), the decNumber
175# reference implementation imposes additional restrictions on the
176# context and operands. These restrictions are not part of the
177# specification; however, the effect of these restrictions does show
178# up in some of the testcases. We skip testcases that violate these
179# restrictions, since Decimal behaves differently from decNumber for
180# these testcases so these testcases would otherwise fail.
181
182decNumberRestricted = ('power', 'ln', 'log10', 'exp')
183DEC_MAX_MATH = 999999
184def outside_decNumber_bounds(v, context):
185 if (context.prec > DEC_MAX_MATH or
186 context.Emax > DEC_MAX_MATH or
187 -context.Emin > DEC_MAX_MATH):
188 return True
189 if not v._is_special and v and (
Facundo Batista353750c2007-09-13 18:13:15 +0000190 v.adjusted() > DEC_MAX_MATH or
191 v.adjusted() < 1-2*DEC_MAX_MATH):
192 return True
193 return False
194
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000195class DecimalTest(unittest.TestCase):
196 """Class which tests the Decimal class against the test cases.
197
198 Changed for unittest.
199 """
200 def setUp(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000201 self.context = Context()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000202 self.ignore_list = ['#']
203 # Basically, a # means return NaN InvalidOperation.
204 # Different from a sNaN in trim
205
206 self.ChangeDict = {'precision' : self.change_precision,
207 'rounding' : self.change_rounding_method,
208 'maxexponent' : self.change_max_exponent,
209 'minexponent' : self.change_min_exponent,
210 'clamp' : self.change_clamp}
211
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000212 def eval_file(self, file):
213 global skip_expected
214 if skip_expected:
Benjamin Petersonbec087f2009-03-26 21:10:30 +0000215 raise unittest.SkipTest
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000216 return
Florent Xicluna8f43cec2010-03-21 10:51:40 +0000217 for line in open(file):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000218 line = line.replace('\r\n', '').replace('\n', '')
Raymond Hettinger5aa478b2004-07-09 10:02:53 +0000219 #print line
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000220 try:
221 t = self.eval_line(line)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000222 except DecimalException, exception:
223 #Exception raised where there shoudn't have been one.
224 self.fail('Exception "'+exception.__class__.__name__ + '" raised on line '+line)
225
226 return
227
228 def eval_line(self, s):
229 if s.find(' -> ') >= 0 and s[:2] != '--' and not s.startswith(' --'):
230 s = (s.split('->')[0] + '->' +
231 s.split('->')[1].split('--')[0]).strip()
232 else:
233 s = s.split('--')[0].strip()
234
235 for ignore in self.ignore_list:
236 if s.find(ignore) >= 0:
237 #print s.split()[0], 'NotImplemented--', ignore
238 return
239 if not s:
240 return
241 elif ':' in s:
242 return self.eval_directive(s)
243 else:
244 return self.eval_equation(s)
245
246 def eval_directive(self, s):
247 funct, value = map(lambda x: x.strip().lower(), s.split(':'))
248 if funct == 'rounding':
249 value = RoundingDict[value]
250 else:
251 try:
252 value = int(value)
253 except ValueError:
254 pass
255
256 funct = self.ChangeDict.get(funct, Nonfunction)
257 funct(value)
258
259 def eval_equation(self, s):
260 #global DEFAULT_PRECISION
261 #print DEFAULT_PRECISION
Raymond Hettingered20ad82004-09-04 20:09:13 +0000262
263 if not TEST_ALL and random.random() < 0.90:
264 return
265
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000266 try:
267 Sides = s.split('->')
268 L = Sides[0].strip().split()
269 id = L[0]
Facundo Batista353750c2007-09-13 18:13:15 +0000270 if DEBUG:
271 print "Test ", id,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000272 funct = L[1].lower()
273 valstemp = L[2:]
274 L = Sides[1].strip().split()
275 ans = L[0]
276 exceptions = L[1:]
277 except (TypeError, AttributeError, IndexError):
Raymond Hettingerd87ac8f2004-07-09 10:52:54 +0000278 raise InvalidOperation
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000279 def FixQuotes(val):
280 val = val.replace("''", 'SingleQuote').replace('""', 'DoubleQuote')
281 val = val.replace("'", '').replace('"', '')
282 val = val.replace('SingleQuote', "'").replace('DoubleQuote', '"')
283 return val
Mark Dickinson539bff42009-10-08 16:28:39 +0000284
285 if id in skipped_test_ids:
286 return
287
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000288 fname = nameAdapter.get(funct, funct)
289 if fname == 'rescale':
290 return
291 funct = getattr(self.context, fname)
292 vals = []
293 conglomerate = ''
294 quote = 0
295 theirexceptions = [ErrorNames[x.lower()] for x in exceptions]
296
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000297 for exception in Signals:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000298 self.context.traps[exception] = 1 #Catch these bugs...
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000299 for exception in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000300 self.context.traps[exception] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000301 for i, val in enumerate(valstemp):
302 if val.count("'") % 2 == 1:
303 quote = 1 - quote
304 if quote:
305 conglomerate = conglomerate + ' ' + val
306 continue
307 else:
308 val = conglomerate + val
309 conglomerate = ''
310 v = FixQuotes(val)
311 if fname in ('to_sci_string', 'to_eng_string'):
312 if EXTENDEDERRORTEST:
313 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000314 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000315 try:
316 funct(self.context.create_decimal(v))
317 except error:
318 pass
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000319 except Signals, e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000320 self.fail("Raised %s in %s when %s disabled" % \
321 (e, s, error))
322 else:
323 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000324 self.context.traps[error] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000325 v = self.context.create_decimal(v)
326 else:
Facundo Batista353750c2007-09-13 18:13:15 +0000327 v = Decimal(v, self.context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000328 vals.append(v)
329
330 ans = FixQuotes(ans)
331
Facundo Batista353750c2007-09-13 18:13:15 +0000332 # skip tests that are related to bounds imposed in the decNumber
333 # reference implementation
334 if fname in decNumberRestricted:
335 if fname == 'power':
336 if not (vals[1]._isinteger() and
337 -1999999997 <= vals[1] <= 999999999):
338 if outside_decNumber_bounds(vals[0], self.context) or \
339 outside_decNumber_bounds(vals[1], self.context):
340 #print "Skipping test %s" % s
341 return
342 else:
343 if outside_decNumber_bounds(vals[0], self.context):
344 #print "Skipping test %s" % s
345 return
346
347
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000348 if EXTENDEDERRORTEST and fname not in ('to_sci_string', 'to_eng_string'):
349 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000350 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000351 try:
352 funct(*vals)
353 except error:
354 pass
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000355 except Signals, e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000356 self.fail("Raised %s in %s when %s disabled" % \
357 (e, s, error))
358 else:
359 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000360 self.context.traps[error] = 0
Mark Dickinson4f96f5f2010-05-04 14:25:50 +0000361
362 # as above, but add traps cumulatively, to check precedence
363 ordered_errors = [e for e in OrderedSignals if e in theirexceptions]
364 for error in ordered_errors:
365 self.context.traps[error] = 1
366 try:
367 funct(*vals)
368 except error:
369 pass
370 except Signals, e:
371 self.fail("Raised %s in %s; expected %s" %
372 (type(e), s, error))
373 else:
374 self.fail("Did not raise %s in %s" % (error, s))
375 # reset traps
376 for error in ordered_errors:
377 self.context.traps[error] = 0
378
379
Facundo Batista353750c2007-09-13 18:13:15 +0000380 if DEBUG:
381 print "--", self.context
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000382 try:
383 result = str(funct(*vals))
Facundo Batista1a191df2007-10-02 17:01:24 +0000384 if fname in LOGICAL_FUNCTIONS:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000385 result = str(int(eval(result))) # 'True', 'False' -> '1', '0'
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000386 except Signals, error:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000387 self.fail("Raised %s in %s" % (error, s))
388 except: #Catch any error long enough to state the test case.
389 print "ERROR:", s
390 raise
391
392 myexceptions = self.getexceptions()
Raymond Hettingerbf440692004-07-10 14:14:37 +0000393 self.context.clear_flags()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000394
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000395 self.assertEqual(result, ans,
396 'Incorrect answer for ' + s + ' -- got ' + result)
Florent Xicluna8f43cec2010-03-21 10:51:40 +0000397 self.assertItemsEqual(myexceptions, theirexceptions,
Facundo Batista353750c2007-09-13 18:13:15 +0000398 'Incorrect flags set in ' + s + ' -- got ' + str(myexceptions))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000399 return
400
401 def getexceptions(self):
Raymond Hettingerf63ba432004-08-17 05:42:09 +0000402 return [e for e in Signals if self.context.flags[e]]
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000403
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000404 def change_precision(self, prec):
405 self.context.prec = prec
406 def change_rounding_method(self, rounding):
407 self.context.rounding = rounding
408 def change_min_exponent(self, exp):
409 self.context.Emin = exp
410 def change_max_exponent(self, exp):
411 self.context.Emax = exp
412 def change_clamp(self, clamp):
413 self.context._clamp = clamp
414
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000415
416
417# The following classes test the behaviour of Decimal according to PEP 327
418
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000419class DecimalExplicitConstructionTest(unittest.TestCase):
420 '''Unit tests for Explicit Construction cases of Decimal.'''
421
422 def test_explicit_empty(self):
423 self.assertEqual(Decimal(), Decimal("0"))
424
425 def test_explicit_from_None(self):
426 self.assertRaises(TypeError, Decimal, None)
427
428 def test_explicit_from_int(self):
429
430 #positive
431 d = Decimal(45)
432 self.assertEqual(str(d), '45')
433
434 #very large positive
435 d = Decimal(500000123)
436 self.assertEqual(str(d), '500000123')
437
438 #negative
439 d = Decimal(-45)
440 self.assertEqual(str(d), '-45')
441
442 #zero
443 d = Decimal(0)
444 self.assertEqual(str(d), '0')
445
446 def test_explicit_from_string(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000447
448 #empty
449 self.assertEqual(str(Decimal('')), 'NaN')
450
451 #int
452 self.assertEqual(str(Decimal('45')), '45')
453
454 #float
455 self.assertEqual(str(Decimal('45.34')), '45.34')
456
457 #engineer notation
458 self.assertEqual(str(Decimal('45e2')), '4.5E+3')
459
460 #just not a number
461 self.assertEqual(str(Decimal('ugly')), 'NaN')
462
Mark Dickinson59bc20b2008-01-12 01:56:00 +0000463 #leading and trailing whitespace permitted
464 self.assertEqual(str(Decimal('1.3E4 \n')), '1.3E+4')
465 self.assertEqual(str(Decimal(' -7.89')), '-7.89')
466
Mark Dickinson8e85ffa2008-03-25 18:47:59 +0000467 #unicode strings should be permitted
468 self.assertEqual(str(Decimal(u'0E-017')), '0E-17')
469 self.assertEqual(str(Decimal(u'45')), '45')
470 self.assertEqual(str(Decimal(u'-Inf')), '-Infinity')
471 self.assertEqual(str(Decimal(u'NaN123')), 'NaN123')
472
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000473 def test_explicit_from_tuples(self):
474
475 #zero
476 d = Decimal( (0, (0,), 0) )
477 self.assertEqual(str(d), '0')
478
479 #int
480 d = Decimal( (1, (4, 5), 0) )
481 self.assertEqual(str(d), '-45')
482
483 #float
484 d = Decimal( (0, (4, 5, 3, 4), -2) )
485 self.assertEqual(str(d), '45.34')
486
487 #weird
488 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
489 self.assertEqual(str(d), '-4.34913534E-17')
490
491 #wrong number of items
492 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1)) )
493
494 #bad sign
495 self.assertRaises(ValueError, Decimal, (8, (4, 3, 4, 9, 1), 2) )
Facundo Batista9b5e2312007-10-19 19:25:57 +0000496 self.assertRaises(ValueError, Decimal, (0., (4, 3, 4, 9, 1), 2) )
497 self.assertRaises(ValueError, Decimal, (Decimal(1), (4, 3, 4, 9, 1), 2))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000498
499 #bad exp
500 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 'wrong!') )
Facundo Batista9b5e2312007-10-19 19:25:57 +0000501 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 0.) )
502 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), '1') )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000503
504 #bad coefficients
505 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, None, 1), 2) )
506 self.assertRaises(ValueError, Decimal, (1, (4, -3, 4, 9, 1), 2) )
Facundo Batista9b5e2312007-10-19 19:25:57 +0000507 self.assertRaises(ValueError, Decimal, (1, (4, 10, 4, 9, 1), 2) )
Facundo Batista72bc54f2007-11-23 17:59:00 +0000508 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 'a', 1), 2) )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000509
Antoine Pitrou6032c252010-03-30 18:49:45 +0000510 def test_explicit_from_bool(self):
511 self.assertIs(bool(Decimal(0)), False)
512 self.assertIs(bool(Decimal(1)), True)
513 self.assertEqual(Decimal(False), Decimal(0))
514 self.assertEqual(Decimal(True), Decimal(1))
515
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000516 def test_explicit_from_Decimal(self):
517
518 #positive
519 d = Decimal(45)
520 e = Decimal(d)
521 self.assertEqual(str(e), '45')
522 self.assertNotEqual(id(d), id(e))
523
524 #very large positive
525 d = Decimal(500000123)
526 e = Decimal(d)
527 self.assertEqual(str(e), '500000123')
528 self.assertNotEqual(id(d), id(e))
529
530 #negative
531 d = Decimal(-45)
532 e = Decimal(d)
533 self.assertEqual(str(e), '-45')
534 self.assertNotEqual(id(d), id(e))
535
536 #zero
537 d = Decimal(0)
538 e = Decimal(d)
539 self.assertEqual(str(e), '0')
540 self.assertNotEqual(id(d), id(e))
541
Raymond Hettingered171ab2010-04-02 18:39:24 +0000542 @requires_IEEE_754
543 def test_explicit_from_float(self):
544 r = Decimal(0.1)
545 self.assertEqual(type(r), Decimal)
546 self.assertEqual(str(r),
547 '0.1000000000000000055511151231257827021181583404541015625')
548 self.assertTrue(Decimal(float('nan')).is_qnan())
549 self.assertTrue(Decimal(float('inf')).is_infinite())
550 self.assertTrue(Decimal(float('-inf')).is_infinite())
551 self.assertEqual(str(Decimal(float('nan'))),
552 str(Decimal('NaN')))
553 self.assertEqual(str(Decimal(float('inf'))),
554 str(Decimal('Infinity')))
555 self.assertEqual(str(Decimal(float('-inf'))),
556 str(Decimal('-Infinity')))
557 self.assertEqual(str(Decimal(float('-0.0'))),
558 str(Decimal('-0')))
559 for i in range(200):
560 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
561 self.assertEqual(x, float(Decimal(x))) # roundtrip
562
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000563 def test_explicit_context_create_decimal(self):
564
565 nc = copy.copy(getcontext())
566 nc.prec = 3
567
568 # empty
Raymond Hettingerfed52962004-07-14 15:41:57 +0000569 d = Decimal()
570 self.assertEqual(str(d), '0')
571 d = nc.create_decimal()
572 self.assertEqual(str(d), '0')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000573
574 # from None
575 self.assertRaises(TypeError, nc.create_decimal, None)
576
577 # from int
578 d = nc.create_decimal(456)
Ezio Melottib0f5adc2010-01-24 16:58:36 +0000579 self.assertIsInstance(d, Decimal)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000580 self.assertEqual(nc.create_decimal(45678),
581 nc.create_decimal('457E+2'))
582
583 # from string
584 d = Decimal('456789')
585 self.assertEqual(str(d), '456789')
586 d = nc.create_decimal('456789')
587 self.assertEqual(str(d), '4.57E+5')
Mark Dickinson59bc20b2008-01-12 01:56:00 +0000588 # leading and trailing whitespace should result in a NaN;
589 # spaces are already checked in Cowlishaw's test-suite, so
590 # here we just check that a trailing newline results in a NaN
591 self.assertEqual(str(nc.create_decimal('3.14\n')), 'NaN')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000592
593 # from tuples
594 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
595 self.assertEqual(str(d), '-4.34913534E-17')
596 d = nc.create_decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
597 self.assertEqual(str(d), '-4.35E-17')
598
599 # from Decimal
600 prevdec = Decimal(500000123)
601 d = Decimal(prevdec)
602 self.assertEqual(str(d), '500000123')
603 d = nc.create_decimal(prevdec)
604 self.assertEqual(str(d), '5.00E+8')
605
Mark Dickinson4326ad82009-08-02 10:59:36 +0000606 def test_unicode_digits(self):
607 test_values = {
608 u'\uff11': '1',
609 u'\u0660.\u0660\u0663\u0667\u0662e-\u0663' : '0.0000372',
610 u'-nan\u0c68\u0c6a\u0c66\u0c66' : '-NaN2400',
611 }
612 for input, expected in test_values.items():
613 self.assertEqual(str(Decimal(input)), expected)
614
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000615
616class DecimalImplicitConstructionTest(unittest.TestCase):
617 '''Unit tests for Implicit Construction cases of Decimal.'''
618
619 def test_implicit_from_None(self):
620 self.assertRaises(TypeError, eval, 'Decimal(5) + None', globals())
621
622 def test_implicit_from_int(self):
623 #normal
624 self.assertEqual(str(Decimal(5) + 45), '50')
625 #exceeding precision
626 self.assertEqual(Decimal(5) + 123456789000, Decimal(123456789000))
627
628 def test_implicit_from_string(self):
629 self.assertRaises(TypeError, eval, 'Decimal(5) + "3"', globals())
630
631 def test_implicit_from_float(self):
632 self.assertRaises(TypeError, eval, 'Decimal(5) + 2.2', globals())
633
634 def test_implicit_from_Decimal(self):
635 self.assertEqual(Decimal(5) + Decimal(45), Decimal(50))
636
Raymond Hettinger267b8682005-03-27 10:47:39 +0000637 def test_rop(self):
638 # Allow other classes to be trained to interact with Decimals
639 class E:
640 def __divmod__(self, other):
641 return 'divmod ' + str(other)
642 def __rdivmod__(self, other):
643 return str(other) + ' rdivmod'
644 def __lt__(self, other):
645 return 'lt ' + str(other)
646 def __gt__(self, other):
647 return 'gt ' + str(other)
648 def __le__(self, other):
649 return 'le ' + str(other)
650 def __ge__(self, other):
651 return 'ge ' + str(other)
652 def __eq__(self, other):
653 return 'eq ' + str(other)
654 def __ne__(self, other):
655 return 'ne ' + str(other)
656
657 self.assertEqual(divmod(E(), Decimal(10)), 'divmod 10')
658 self.assertEqual(divmod(Decimal(10), E()), '10 rdivmod')
659 self.assertEqual(eval('Decimal(10) < E()'), 'gt 10')
660 self.assertEqual(eval('Decimal(10) > E()'), 'lt 10')
661 self.assertEqual(eval('Decimal(10) <= E()'), 'ge 10')
662 self.assertEqual(eval('Decimal(10) >= E()'), 'le 10')
663 self.assertEqual(eval('Decimal(10) == E()'), 'eq 10')
664 self.assertEqual(eval('Decimal(10) != E()'), 'ne 10')
665
666 # insert operator methods and then exercise them
Georg Brandl96c3f7f2006-03-28 08:06:35 +0000667 oplist = [
668 ('+', '__add__', '__radd__'),
669 ('-', '__sub__', '__rsub__'),
670 ('*', '__mul__', '__rmul__'),
671 ('%', '__mod__', '__rmod__'),
672 ('//', '__floordiv__', '__rfloordiv__'),
673 ('**', '__pow__', '__rpow__')
674 ]
Florent Xicluna8f43cec2010-03-21 10:51:40 +0000675 with check_py3k_warnings():
676 if 1 / 2 == 0:
677 # testing with classic division, so add __div__
678 oplist.append(('/', '__div__', '__rdiv__'))
679 else:
680 # testing with -Qnew, so add __truediv__
681 oplist.append(('/', '__truediv__', '__rtruediv__'))
Anthony Baxter4ef3a232006-03-30 12:59:11 +0000682
Georg Brandl96c3f7f2006-03-28 08:06:35 +0000683 for sym, lop, rop in oplist:
Raymond Hettinger267b8682005-03-27 10:47:39 +0000684 setattr(E, lop, lambda self, other: 'str' + lop + str(other))
685 setattr(E, rop, lambda self, other: str(other) + rop + 'str')
686 self.assertEqual(eval('E()' + sym + 'Decimal(10)'),
687 'str' + lop + '10')
688 self.assertEqual(eval('Decimal(10)' + sym + 'E()'),
689 '10' + rop + 'str')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000690
Mark Dickinson277859d2009-03-17 23:03:46 +0000691
Mark Dickinson1ddf1d82008-02-29 02:16:37 +0000692class DecimalFormatTest(unittest.TestCase):
693 '''Unit tests for the format function.'''
694 def test_formatting(self):
695 # triples giving a format, a Decimal, and the expected result
696 test_values = [
697 ('e', '0E-15', '0e-15'),
698 ('e', '2.3E-15', '2.3e-15'),
699 ('e', '2.30E+2', '2.30e+2'), # preserve significant zeros
700 ('e', '2.30000E-15', '2.30000e-15'),
701 ('e', '1.23456789123456789e40', '1.23456789123456789e+40'),
702 ('e', '1.5', '1.5e+0'),
703 ('e', '0.15', '1.5e-1'),
704 ('e', '0.015', '1.5e-2'),
705 ('e', '0.0000000000015', '1.5e-12'),
706 ('e', '15.0', '1.50e+1'),
707 ('e', '-15', '-1.5e+1'),
708 ('e', '0', '0e+0'),
709 ('e', '0E1', '0e+1'),
710 ('e', '0.0', '0e-1'),
711 ('e', '0.00', '0e-2'),
712 ('.6e', '0E-15', '0.000000e-9'),
713 ('.6e', '0', '0.000000e+6'),
714 ('.6e', '9.999999', '9.999999e+0'),
715 ('.6e', '9.9999999', '1.000000e+1'),
716 ('.6e', '-1.23e5', '-1.230000e+5'),
717 ('.6e', '1.23456789e-3', '1.234568e-3'),
718 ('f', '0', '0'),
719 ('f', '0.0', '0.0'),
720 ('f', '0E-2', '0.00'),
721 ('f', '0.00E-8', '0.0000000000'),
722 ('f', '0E1', '0'), # loses exponent information
723 ('f', '3.2E1', '32'),
724 ('f', '3.2E2', '320'),
725 ('f', '3.20E2', '320'),
726 ('f', '3.200E2', '320.0'),
727 ('f', '3.2E-6', '0.0000032'),
728 ('.6f', '0E-15', '0.000000'), # all zeros treated equally
729 ('.6f', '0E1', '0.000000'),
730 ('.6f', '0', '0.000000'),
731 ('.0f', '0', '0'), # no decimal point
732 ('.0f', '0e-2', '0'),
733 ('.0f', '3.14159265', '3'),
734 ('.1f', '3.14159265', '3.1'),
735 ('.4f', '3.14159265', '3.1416'),
736 ('.6f', '3.14159265', '3.141593'),
737 ('.7f', '3.14159265', '3.1415926'), # round-half-even!
738 ('.8f', '3.14159265', '3.14159265'),
739 ('.9f', '3.14159265', '3.141592650'),
740
741 ('g', '0', '0'),
742 ('g', '0.0', '0.0'),
743 ('g', '0E1', '0e+1'),
744 ('G', '0E1', '0E+1'),
745 ('g', '0E-5', '0.00000'),
746 ('g', '0E-6', '0.000000'),
747 ('g', '0E-7', '0e-7'),
748 ('g', '-0E2', '-0e+2'),
749 ('.0g', '3.14159265', '3'), # 0 sig fig -> 1 sig fig
750 ('.1g', '3.14159265', '3'),
751 ('.2g', '3.14159265', '3.1'),
752 ('.5g', '3.14159265', '3.1416'),
753 ('.7g', '3.14159265', '3.141593'),
754 ('.8g', '3.14159265', '3.1415926'), # round-half-even!
755 ('.9g', '3.14159265', '3.14159265'),
756 ('.10g', '3.14159265', '3.14159265'), # don't pad
757
758 ('%', '0E1', '0%'),
759 ('%', '0E0', '0%'),
760 ('%', '0E-1', '0%'),
761 ('%', '0E-2', '0%'),
762 ('%', '0E-3', '0.0%'),
763 ('%', '0E-4', '0.00%'),
764
765 ('.3%', '0', '0.000%'), # all zeros treated equally
766 ('.3%', '0E10', '0.000%'),
767 ('.3%', '0E-10', '0.000%'),
768 ('.3%', '2.34', '234.000%'),
769 ('.3%', '1.234567', '123.457%'),
770 ('.0%', '1.23', '123%'),
771
772 ('e', 'NaN', 'NaN'),
773 ('f', '-NaN123', '-NaN123'),
774 ('+g', 'NaN456', '+NaN456'),
775 ('.3e', 'Inf', 'Infinity'),
776 ('.16f', '-Inf', '-Infinity'),
777 ('.0g', '-sNaN', '-sNaN'),
778
779 ('', '1.00', '1.00'),
Mark Dickinsonb065e522009-03-17 18:01:03 +0000780
Mark Dickinson277859d2009-03-17 23:03:46 +0000781 # test alignment and padding
Mark Dickinson5cfa8042009-09-08 20:20:19 +0000782 ('6', '123', ' 123'),
Mark Dickinsonb065e522009-03-17 18:01:03 +0000783 ('<6', '123', '123 '),
784 ('>6', '123', ' 123'),
785 ('^6', '123', ' 123 '),
786 ('=+6', '123', '+ 123'),
Mark Dickinson277859d2009-03-17 23:03:46 +0000787 ('#<10', 'NaN', 'NaN#######'),
788 ('#<10', '-4.3', '-4.3######'),
789 ('#<+10', '0.0130', '+0.0130###'),
790 ('#< 10', '0.0130', ' 0.0130###'),
791 ('@>10', '-Inf', '@-Infinity'),
792 ('#>5', '-Inf', '-Infinity'),
793 ('?^5', '123', '?123?'),
794 ('%^6', '123', '%123%%'),
795 (' ^6', '-45.6', '-45.6 '),
796 ('/=10', '-45.6', '-/////45.6'),
797 ('/=+10', '45.6', '+/////45.6'),
798 ('/= 10', '45.6', ' /////45.6'),
799
800 # thousands separator
801 (',', '1234567', '1,234,567'),
802 (',', '123456', '123,456'),
803 (',', '12345', '12,345'),
804 (',', '1234', '1,234'),
805 (',', '123', '123'),
806 (',', '12', '12'),
807 (',', '1', '1'),
808 (',', '0', '0'),
809 (',', '-1234567', '-1,234,567'),
810 (',', '-123456', '-123,456'),
811 ('7,', '123456', '123,456'),
Mark Dickinson5cfa8042009-09-08 20:20:19 +0000812 ('8,', '123456', ' 123,456'),
Mark Dickinson277859d2009-03-17 23:03:46 +0000813 ('08,', '123456', '0,123,456'), # special case: extra 0 needed
814 ('+08,', '123456', '+123,456'), # but not if there's a sign
815 (' 08,', '123456', ' 123,456'),
816 ('08,', '-123456', '-123,456'),
817 ('+09,', '123456', '+0,123,456'),
818 # ... with fractional part...
819 ('07,', '1234.56', '1,234.56'),
820 ('08,', '1234.56', '1,234.56'),
821 ('09,', '1234.56', '01,234.56'),
822 ('010,', '1234.56', '001,234.56'),
823 ('011,', '1234.56', '0,001,234.56'),
824 ('012,', '1234.56', '0,001,234.56'),
825 ('08,.1f', '1234.5', '01,234.5'),
826 # no thousands separators in fraction part
827 (',', '1.23456789', '1.23456789'),
828 (',%', '123.456789', '12,345.6789%'),
829 (',e', '123456', '1.23456e+5'),
830 (',E', '123456', '1.23456E+5'),
Mark Dickinson491ea552009-09-07 16:17:41 +0000831
832 # issue 6850
833 ('a=-7.0', '0.12345', 'aaaa0.1'),
Mark Dickinson1ddf1d82008-02-29 02:16:37 +0000834 ]
835 for fmt, d, result in test_values:
836 self.assertEqual(format(Decimal(d), fmt), result)
837
Mark Dickinson277859d2009-03-17 23:03:46 +0000838 def test_n_format(self):
839 try:
840 from locale import CHAR_MAX
841 except ImportError:
842 return
843
844 # Set up some localeconv-like dictionaries
845 en_US = {
846 'decimal_point' : '.',
847 'grouping' : [3, 3, 0],
848 'thousands_sep': ','
849 }
850
851 fr_FR = {
852 'decimal_point' : ',',
853 'grouping' : [CHAR_MAX],
854 'thousands_sep' : ''
855 }
856
857 ru_RU = {
858 'decimal_point' : ',',
859 'grouping' : [3, 3, 0],
860 'thousands_sep' : ' '
861 }
862
863 crazy = {
864 'decimal_point' : '&',
865 'grouping' : [1, 4, 2, CHAR_MAX],
866 'thousands_sep' : '-'
867 }
868
869
870 def get_fmt(x, locale, fmt='n'):
871 return Decimal.__format__(Decimal(x), fmt, _localeconv=locale)
872
873 self.assertEqual(get_fmt(Decimal('12.7'), en_US), '12.7')
874 self.assertEqual(get_fmt(Decimal('12.7'), fr_FR), '12,7')
875 self.assertEqual(get_fmt(Decimal('12.7'), ru_RU), '12,7')
876 self.assertEqual(get_fmt(Decimal('12.7'), crazy), '1-2&7')
877
878 self.assertEqual(get_fmt(123456789, en_US), '123,456,789')
879 self.assertEqual(get_fmt(123456789, fr_FR), '123456789')
880 self.assertEqual(get_fmt(123456789, ru_RU), '123 456 789')
881 self.assertEqual(get_fmt(1234567890123, crazy), '123456-78-9012-3')
882
883 self.assertEqual(get_fmt(123456789, en_US, '.6n'), '1.23457e+8')
884 self.assertEqual(get_fmt(123456789, fr_FR, '.6n'), '1,23457e+8')
885 self.assertEqual(get_fmt(123456789, ru_RU, '.6n'), '1,23457e+8')
886 self.assertEqual(get_fmt(123456789, crazy, '.6n'), '1&23457e+8')
887
Mark Dickinsonb14514a2009-03-18 08:22:51 +0000888 # zero padding
889 self.assertEqual(get_fmt(1234, fr_FR, '03n'), '1234')
890 self.assertEqual(get_fmt(1234, fr_FR, '04n'), '1234')
891 self.assertEqual(get_fmt(1234, fr_FR, '05n'), '01234')
892 self.assertEqual(get_fmt(1234, fr_FR, '06n'), '001234')
893
894 self.assertEqual(get_fmt(12345, en_US, '05n'), '12,345')
895 self.assertEqual(get_fmt(12345, en_US, '06n'), '12,345')
896 self.assertEqual(get_fmt(12345, en_US, '07n'), '012,345')
897 self.assertEqual(get_fmt(12345, en_US, '08n'), '0,012,345')
898 self.assertEqual(get_fmt(12345, en_US, '09n'), '0,012,345')
899 self.assertEqual(get_fmt(12345, en_US, '010n'), '00,012,345')
900
901 self.assertEqual(get_fmt(123456, crazy, '06n'), '1-2345-6')
902 self.assertEqual(get_fmt(123456, crazy, '07n'), '1-2345-6')
903 self.assertEqual(get_fmt(123456, crazy, '08n'), '1-2345-6')
904 self.assertEqual(get_fmt(123456, crazy, '09n'), '01-2345-6')
905 self.assertEqual(get_fmt(123456, crazy, '010n'), '0-01-2345-6')
906 self.assertEqual(get_fmt(123456, crazy, '011n'), '0-01-2345-6')
907 self.assertEqual(get_fmt(123456, crazy, '012n'), '00-01-2345-6')
908 self.assertEqual(get_fmt(123456, crazy, '013n'), '000-01-2345-6')
909
Mark Dickinson277859d2009-03-17 23:03:46 +0000910
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000911class DecimalArithmeticOperatorsTest(unittest.TestCase):
912 '''Unit tests for all arithmetic operators, binary and unary.'''
913
914 def test_addition(self):
915
916 d1 = Decimal('-11.1')
917 d2 = Decimal('22.2')
918
919 #two Decimals
920 self.assertEqual(d1+d2, Decimal('11.1'))
921 self.assertEqual(d2+d1, Decimal('11.1'))
922
923 #with other type, left
924 c = d1 + 5
925 self.assertEqual(c, Decimal('-6.1'))
926 self.assertEqual(type(c), type(d1))
927
928 #with other type, right
929 c = 5 + d1
930 self.assertEqual(c, Decimal('-6.1'))
931 self.assertEqual(type(c), type(d1))
932
933 #inline with decimal
934 d1 += d2
935 self.assertEqual(d1, Decimal('11.1'))
936
937 #inline with other type
938 d1 += 5
939 self.assertEqual(d1, Decimal('16.1'))
940
941 def test_subtraction(self):
942
943 d1 = Decimal('-11.1')
944 d2 = Decimal('22.2')
945
946 #two Decimals
947 self.assertEqual(d1-d2, Decimal('-33.3'))
948 self.assertEqual(d2-d1, Decimal('33.3'))
949
950 #with other type, left
951 c = d1 - 5
952 self.assertEqual(c, Decimal('-16.1'))
953 self.assertEqual(type(c), type(d1))
954
955 #with other type, right
956 c = 5 - d1
957 self.assertEqual(c, Decimal('16.1'))
958 self.assertEqual(type(c), type(d1))
959
960 #inline with decimal
961 d1 -= d2
962 self.assertEqual(d1, Decimal('-33.3'))
963
964 #inline with other type
965 d1 -= 5
966 self.assertEqual(d1, Decimal('-38.3'))
967
968 def test_multiplication(self):
969
970 d1 = Decimal('-5')
971 d2 = Decimal('3')
972
973 #two Decimals
974 self.assertEqual(d1*d2, Decimal('-15'))
975 self.assertEqual(d2*d1, Decimal('-15'))
976
977 #with other type, left
978 c = d1 * 5
979 self.assertEqual(c, Decimal('-25'))
980 self.assertEqual(type(c), type(d1))
981
982 #with other type, right
983 c = 5 * d1
984 self.assertEqual(c, Decimal('-25'))
985 self.assertEqual(type(c), type(d1))
986
987 #inline with decimal
988 d1 *= d2
989 self.assertEqual(d1, Decimal('-15'))
990
991 #inline with other type
992 d1 *= 5
993 self.assertEqual(d1, Decimal('-75'))
994
995 def test_division(self):
996
997 d1 = Decimal('-5')
998 d2 = Decimal('2')
999
1000 #two Decimals
1001 self.assertEqual(d1/d2, Decimal('-2.5'))
1002 self.assertEqual(d2/d1, Decimal('-0.4'))
1003
1004 #with other type, left
1005 c = d1 / 4
1006 self.assertEqual(c, Decimal('-1.25'))
1007 self.assertEqual(type(c), type(d1))
1008
1009 #with other type, right
1010 c = 4 / d1
1011 self.assertEqual(c, Decimal('-0.8'))
1012 self.assertEqual(type(c), type(d1))
1013
1014 #inline with decimal
1015 d1 /= d2
1016 self.assertEqual(d1, Decimal('-2.5'))
1017
1018 #inline with other type
1019 d1 /= 4
1020 self.assertEqual(d1, Decimal('-0.625'))
1021
1022 def test_floor_division(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001023
1024 d1 = Decimal('5')
1025 d2 = Decimal('2')
1026
1027 #two Decimals
1028 self.assertEqual(d1//d2, Decimal('2'))
1029 self.assertEqual(d2//d1, Decimal('0'))
1030
1031 #with other type, left
1032 c = d1 // 4
1033 self.assertEqual(c, Decimal('1'))
1034 self.assertEqual(type(c), type(d1))
1035
1036 #with other type, right
1037 c = 7 // d1
1038 self.assertEqual(c, Decimal('1'))
1039 self.assertEqual(type(c), type(d1))
1040
1041 #inline with decimal
1042 d1 //= d2
1043 self.assertEqual(d1, Decimal('2'))
1044
1045 #inline with other type
1046 d1 //= 2
1047 self.assertEqual(d1, Decimal('1'))
1048
1049 def test_powering(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001050
1051 d1 = Decimal('5')
1052 d2 = Decimal('2')
1053
1054 #two Decimals
1055 self.assertEqual(d1**d2, Decimal('25'))
1056 self.assertEqual(d2**d1, Decimal('32'))
1057
1058 #with other type, left
1059 c = d1 ** 4
1060 self.assertEqual(c, Decimal('625'))
1061 self.assertEqual(type(c), type(d1))
1062
1063 #with other type, right
1064 c = 7 ** d1
1065 self.assertEqual(c, Decimal('16807'))
1066 self.assertEqual(type(c), type(d1))
1067
1068 #inline with decimal
1069 d1 **= d2
1070 self.assertEqual(d1, Decimal('25'))
1071
1072 #inline with other type
1073 d1 **= 4
1074 self.assertEqual(d1, Decimal('390625'))
1075
1076 def test_module(self):
1077
1078 d1 = Decimal('5')
1079 d2 = Decimal('2')
1080
1081 #two Decimals
1082 self.assertEqual(d1%d2, Decimal('1'))
1083 self.assertEqual(d2%d1, Decimal('2'))
1084
1085 #with other type, left
1086 c = d1 % 4
1087 self.assertEqual(c, Decimal('1'))
1088 self.assertEqual(type(c), type(d1))
1089
1090 #with other type, right
1091 c = 7 % d1
1092 self.assertEqual(c, Decimal('2'))
1093 self.assertEqual(type(c), type(d1))
1094
1095 #inline with decimal
1096 d1 %= d2
1097 self.assertEqual(d1, Decimal('1'))
1098
1099 #inline with other type
1100 d1 %= 4
1101 self.assertEqual(d1, Decimal('1'))
1102
1103 def test_floor_div_module(self):
1104
1105 d1 = Decimal('5')
1106 d2 = Decimal('2')
1107
1108 #two Decimals
1109 (p, q) = divmod(d1, d2)
1110 self.assertEqual(p, Decimal('2'))
1111 self.assertEqual(q, Decimal('1'))
1112 self.assertEqual(type(p), type(d1))
1113 self.assertEqual(type(q), type(d1))
1114
1115 #with other type, left
1116 (p, q) = divmod(d1, 4)
1117 self.assertEqual(p, Decimal('1'))
1118 self.assertEqual(q, Decimal('1'))
1119 self.assertEqual(type(p), type(d1))
1120 self.assertEqual(type(q), type(d1))
1121
1122 #with other type, right
1123 (p, q) = divmod(7, d1)
1124 self.assertEqual(p, Decimal('1'))
1125 self.assertEqual(q, Decimal('2'))
1126 self.assertEqual(type(p), type(d1))
1127 self.assertEqual(type(q), type(d1))
1128
1129 def test_unary_operators(self):
1130 self.assertEqual(+Decimal(45), Decimal(+45)) # +
1131 self.assertEqual(-Decimal(45), Decimal(-45)) # -
1132 self.assertEqual(abs(Decimal(45)), abs(Decimal(-45))) # abs
1133
Mark Dickinson2fc92632008-02-06 22:10:50 +00001134 def test_nan_comparisons(self):
Mark Dickinsone096e822010-04-02 10:17:07 +00001135 # comparisons involving signaling nans signal InvalidOperation
1136
1137 # order comparisons (<, <=, >, >=) involving only quiet nans
1138 # also signal InvalidOperation
1139
1140 # equality comparisons (==, !=) involving only quiet nans
1141 # don't signal, but return False or True respectively.
1142
Mark Dickinson2fc92632008-02-06 22:10:50 +00001143 n = Decimal('NaN')
1144 s = Decimal('sNaN')
1145 i = Decimal('Inf')
1146 f = Decimal('2')
Mark Dickinsone096e822010-04-02 10:17:07 +00001147
1148 qnan_pairs = (n, n), (n, i), (i, n), (n, f), (f, n)
1149 snan_pairs = (s, n), (n, s), (s, i), (i, s), (s, f), (f, s), (s, s)
1150 order_ops = operator.lt, operator.le, operator.gt, operator.ge
1151 equality_ops = operator.eq, operator.ne
1152
1153 # results when InvalidOperation is not trapped
1154 for x, y in qnan_pairs + snan_pairs:
1155 for op in order_ops + equality_ops:
1156 got = op(x, y)
1157 expected = True if op is operator.ne else False
1158 self.assertIs(expected, got,
1159 "expected {0!r} for operator.{1}({2!r}, {3!r}); "
1160 "got {4!r}".format(
1161 expected, op.__name__, x, y, got))
1162
1163 # repeat the above, but this time trap the InvalidOperation
1164 with localcontext() as ctx:
1165 ctx.traps[InvalidOperation] = 1
1166
1167 for x, y in qnan_pairs:
1168 for op in equality_ops:
1169 got = op(x, y)
1170 expected = True if op is operator.ne else False
1171 self.assertIs(expected, got,
1172 "expected {0!r} for "
1173 "operator.{1}({2!r}, {3!r}); "
1174 "got {4!r}".format(
1175 expected, op.__name__, x, y, got))
1176
1177 for x, y in snan_pairs:
1178 for op in equality_ops:
1179 self.assertRaises(InvalidOperation, operator.eq, x, y)
1180 self.assertRaises(InvalidOperation, operator.ne, x, y)
1181
1182 for x, y in qnan_pairs + snan_pairs:
1183 for op in order_ops:
1184 self.assertRaises(InvalidOperation, op, x, y)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001185
Mark Dickinson6d8effb2010-02-18 14:27:02 +00001186 def test_copy_sign(self):
1187 d = Decimal(1).copy_sign(Decimal(-2))
1188
1189 self.assertEqual(Decimal(1).copy_sign(-2), d)
1190 self.assertRaises(TypeError, Decimal(1).copy_sign, '-2')
1191
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001192# The following are two functions used to test threading in the next class
1193
1194def thfunc1(cls):
1195 d1 = Decimal(1)
1196 d3 = Decimal(3)
Facundo Batista64156672008-03-22 02:45:37 +00001197 test1 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001198 cls.synchro.wait()
Facundo Batista64156672008-03-22 02:45:37 +00001199 test2 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001200 cls.finish1.set()
Facundo Batista64156672008-03-22 02:45:37 +00001201
Facundo Batistaee340e52008-05-02 17:39:00 +00001202 cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
1203 cls.assertEqual(test2, Decimal('0.3333333333333333333333333333'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001204 return
1205
1206def thfunc2(cls):
1207 d1 = Decimal(1)
1208 d3 = Decimal(3)
Facundo Batista64156672008-03-22 02:45:37 +00001209 test1 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001210 thiscontext = getcontext()
1211 thiscontext.prec = 18
Facundo Batista64156672008-03-22 02:45:37 +00001212 test2 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001213 cls.synchro.set()
1214 cls.finish2.set()
Facundo Batista64156672008-03-22 02:45:37 +00001215
Facundo Batistaee340e52008-05-02 17:39:00 +00001216 cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
Facundo Batista64156672008-03-22 02:45:37 +00001217 cls.assertEqual(test2, Decimal('0.333333333333333333'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001218 return
1219
1220
1221class DecimalUseOfContextTest(unittest.TestCase):
1222 '''Unit tests for Use of Context cases in Decimal.'''
1223
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001224 try:
1225 import threading
1226 except ImportError:
1227 threading = None
1228
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001229 # Take care executing this test from IDLE, there's an issue in threading
1230 # that hangs IDLE and I couldn't find it
1231
1232 def test_threading(self):
1233 #Test the "threading isolation" of a Context.
1234
1235 self.synchro = threading.Event()
1236 self.finish1 = threading.Event()
1237 self.finish2 = threading.Event()
1238
1239 th1 = threading.Thread(target=thfunc1, args=(self,))
1240 th2 = threading.Thread(target=thfunc2, args=(self,))
1241
1242 th1.start()
1243 th2.start()
1244
1245 self.finish1.wait()
Thomas Woutersb3e6e8c2007-09-19 17:27:29 +00001246 self.finish2.wait()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001247 return
1248
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001249 if threading is None:
1250 del test_threading
1251
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001252
1253class DecimalUsabilityTest(unittest.TestCase):
1254 '''Unit tests for Usability cases of Decimal.'''
1255
1256 def test_comparison_operators(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001257
1258 da = Decimal('23.42')
1259 db = Decimal('23.42')
1260 dc = Decimal('45')
1261
1262 #two Decimals
Ezio Melotti856a3be2010-04-03 14:51:00 +00001263 self.assertGreater(dc, da)
1264 self.assertGreaterEqual(dc, da)
1265 self.assertLess(da, dc)
1266 self.assertLessEqual(da, dc)
1267 self.assertEqual(da, db)
1268 self.assertNotEqual(da, dc)
1269 self.assertLessEqual(da, db)
1270 self.assertGreaterEqual(da, db)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001271 self.assertEqual(cmp(dc,da), 1)
1272 self.assertEqual(cmp(da,dc), -1)
1273 self.assertEqual(cmp(da,db), 0)
1274
1275 #a Decimal and an int
Ezio Melotti856a3be2010-04-03 14:51:00 +00001276 self.assertGreater(dc, 23)
1277 self.assertLess(23, dc)
1278 self.assertEqual(dc, 45)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001279 self.assertEqual(cmp(dc,23), 1)
1280 self.assertEqual(cmp(23,dc), -1)
1281 self.assertEqual(cmp(dc,45), 0)
1282
1283 #a Decimal and uncomparable
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001284 self.assertNotEqual(da, 'ugly')
1285 self.assertNotEqual(da, 32.7)
1286 self.assertNotEqual(da, object())
1287 self.assertNotEqual(da, object)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001288
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001289 # sortable
1290 a = map(Decimal, xrange(100))
1291 b = a[:]
1292 random.shuffle(a)
1293 a.sort()
1294 self.assertEqual(a, b)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001295
Facundo Batista353750c2007-09-13 18:13:15 +00001296 # with None
Florent Xicluna8f43cec2010-03-21 10:51:40 +00001297 with check_py3k_warnings():
1298 self.assertFalse(Decimal(1) < None)
1299 self.assertTrue(Decimal(1) > None)
Facundo Batista353750c2007-09-13 18:13:15 +00001300
Mark Dickinson99d80962010-04-02 08:53:22 +00001301 def test_decimal_float_comparison(self):
1302 da = Decimal('0.25')
1303 db = Decimal('3.0')
Ezio Melotti856a3be2010-04-03 14:51:00 +00001304 self.assertLess(da, 3.0)
1305 self.assertLessEqual(da, 3.0)
1306 self.assertGreater(db, 0.25)
1307 self.assertGreaterEqual(db, 0.25)
1308 self.assertNotEqual(da, 1.5)
1309 self.assertEqual(da, 0.25)
1310 self.assertGreater(3.0, da)
1311 self.assertGreaterEqual(3.0, da)
1312 self.assertLess(0.25, db)
1313 self.assertLessEqual(0.25, db)
1314 self.assertNotEqual(0.25, db)
1315 self.assertEqual(3.0, db)
1316 self.assertNotEqual(0.1, Decimal('0.1'))
Mark Dickinson99d80962010-04-02 08:53:22 +00001317
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001318 def test_copy_and_deepcopy_methods(self):
1319 d = Decimal('43.24')
1320 c = copy.copy(d)
1321 self.assertEqual(id(c), id(d))
1322 dc = copy.deepcopy(d)
1323 self.assertEqual(id(dc), id(d))
1324
1325 def test_hash_method(self):
1326 #just that it's hashable
1327 hash(Decimal(23))
Mark Dickinsonf3eeca12010-04-02 10:35:12 +00001328 hash(Decimal('Infinity'))
1329 hash(Decimal('-Infinity'))
1330 hash(Decimal('nan123'))
1331 hash(Decimal('-NaN'))
Facundo Batista8c202442007-09-19 17:53:25 +00001332
1333 test_values = [Decimal(sign*(2**m + n))
1334 for m in [0, 14, 15, 16, 17, 30, 31,
1335 32, 33, 62, 63, 64, 65, 66]
1336 for n in range(-10, 10)
1337 for sign in [-1, 1]]
1338 test_values.extend([
1339 Decimal("-0"), # zeros
1340 Decimal("0.00"),
1341 Decimal("-0.000"),
1342 Decimal("0E10"),
1343 Decimal("-0E12"),
1344 Decimal("10.0"), # negative exponent
1345 Decimal("-23.00000"),
1346 Decimal("1230E100"), # positive exponent
1347 Decimal("-4.5678E50"),
1348 # a value for which hash(n) != hash(n % (2**64-1))
1349 # in Python pre-2.6
1350 Decimal(2**64 + 2**32 - 1),
1351 # selection of values which fail with the old (before
1352 # version 2.6) long.__hash__
1353 Decimal("1.634E100"),
1354 Decimal("90.697E100"),
1355 Decimal("188.83E100"),
1356 Decimal("1652.9E100"),
1357 Decimal("56531E100"),
1358 ])
1359
1360 # check that hash(d) == hash(int(d)) for integral values
1361 for value in test_values:
1362 self.assertEqual(hash(value), hash(int(value)))
1363
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001364 #the same hash that to an int
1365 self.assertEqual(hash(Decimal(23)), hash(23))
Mark Dickinsonf3eeca12010-04-02 10:35:12 +00001366 self.assertRaises(TypeError, hash, Decimal('sNaN'))
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001367 self.assertTrue(hash(Decimal('Inf')))
1368 self.assertTrue(hash(Decimal('-Inf')))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001369
Mark Dickinson99d80962010-04-02 08:53:22 +00001370 # check that the hashes of a Decimal float match when they
1371 # represent exactly the same values
1372 test_strings = ['inf', '-Inf', '0.0', '-.0e1',
1373 '34.0', '2.5', '112390.625', '-0.515625']
1374 for s in test_strings:
1375 f = float(s)
1376 d = Decimal(s)
1377 self.assertEqual(hash(f), hash(d))
1378
Facundo Batista52b25792008-01-08 12:25:20 +00001379 # check that the value of the hash doesn't depend on the
1380 # current context (issue #1757)
1381 c = getcontext()
1382 old_precision = c.prec
1383 x = Decimal("123456789.1")
1384
1385 c.prec = 6
1386 h1 = hash(x)
1387 c.prec = 10
1388 h2 = hash(x)
1389 c.prec = 16
1390 h3 = hash(x)
1391
1392 self.assertEqual(h1, h2)
1393 self.assertEqual(h1, h3)
1394 c.prec = old_precision
1395
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001396 def test_min_and_max_methods(self):
1397
1398 d1 = Decimal('15.32')
1399 d2 = Decimal('28.5')
1400 l1 = 15
1401 l2 = 28
1402
1403 #between Decimals
Ezio Melotti856a3be2010-04-03 14:51:00 +00001404 self.assertIs(min(d1,d2), d1)
1405 self.assertIs(min(d2,d1), d1)
1406 self.assertIs(max(d1,d2), d2)
1407 self.assertIs(max(d2,d1), d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001408
1409 #between Decimal and long
Ezio Melotti856a3be2010-04-03 14:51:00 +00001410 self.assertIs(min(d1,l2), d1)
1411 self.assertIs(min(l2,d1), d1)
1412 self.assertIs(max(l1,d2), d2)
1413 self.assertIs(max(d2,l1), d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001414
1415 def test_as_nonzero(self):
1416 #as false
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001417 self.assertFalse(Decimal(0))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001418 #as true
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001419 self.assertTrue(Decimal('0.372'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001420
1421 def test_tostring_methods(self):
1422 #Test str and repr methods.
1423
1424 d = Decimal('15.32')
1425 self.assertEqual(str(d), '15.32') # str
Raymond Hettingerabe32372008-02-14 02:41:22 +00001426 self.assertEqual(repr(d), "Decimal('15.32')") # repr
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001427
Mark Dickinson8e85ffa2008-03-25 18:47:59 +00001428 # result type of string methods should be str, not unicode
1429 unicode_inputs = [u'123.4', u'0.5E2', u'Infinity', u'sNaN',
1430 u'-0.0E100', u'-NaN001', u'-Inf']
1431
1432 for u in unicode_inputs:
1433 d = Decimal(u)
1434 self.assertEqual(type(str(d)), str)
1435 self.assertEqual(type(repr(d)), str)
1436 self.assertEqual(type(d.to_eng_string()), str)
1437
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001438 def test_tonum_methods(self):
1439 #Test float, int and long methods.
1440
1441 d1 = Decimal('66')
1442 d2 = Decimal('15.32')
1443
1444 #int
1445 self.assertEqual(int(d1), 66)
1446 self.assertEqual(int(d2), 15)
1447
1448 #long
1449 self.assertEqual(long(d1), 66)
1450 self.assertEqual(long(d2), 15)
1451
1452 #float
1453 self.assertEqual(float(d1), 66)
1454 self.assertEqual(float(d2), 15.32)
1455
1456 def test_eval_round_trip(self):
1457
1458 #with zero
1459 d = Decimal( (0, (0,), 0) )
1460 self.assertEqual(d, eval(repr(d)))
1461
1462 #int
1463 d = Decimal( (1, (4, 5), 0) )
1464 self.assertEqual(d, eval(repr(d)))
1465
1466 #float
1467 d = Decimal( (0, (4, 5, 3, 4), -2) )
1468 self.assertEqual(d, eval(repr(d)))
1469
1470 #weird
1471 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1472 self.assertEqual(d, eval(repr(d)))
1473
1474 def test_as_tuple(self):
1475
1476 #with zero
1477 d = Decimal(0)
1478 self.assertEqual(d.as_tuple(), (0, (0,), 0) )
1479
1480 #int
1481 d = Decimal(-45)
1482 self.assertEqual(d.as_tuple(), (1, (4, 5), 0) )
1483
1484 #complicated string
1485 d = Decimal("-4.34913534E-17")
1486 self.assertEqual(d.as_tuple(), (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1487
1488 #inf
1489 d = Decimal("Infinity")
1490 self.assertEqual(d.as_tuple(), (0, (0,), 'F') )
1491
Facundo Batista9b5e2312007-10-19 19:25:57 +00001492 #leading zeros in coefficient should be stripped
1493 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), -2) )
1494 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), -2) )
1495 d = Decimal( (1, (0, 0, 0), 37) )
1496 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1497 d = Decimal( (1, (), 37) )
1498 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1499
1500 #leading zeros in NaN diagnostic info should be stripped
1501 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), 'n') )
1502 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), 'n') )
1503 d = Decimal( (1, (0, 0, 0), 'N') )
1504 self.assertEqual(d.as_tuple(), (1, (), 'N') )
1505 d = Decimal( (1, (), 'n') )
1506 self.assertEqual(d.as_tuple(), (1, (), 'n') )
1507
1508 #coefficient in infinity should be ignored
1509 d = Decimal( (0, (4, 5, 3, 4), 'F') )
1510 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
1511 d = Decimal( (1, (0, 2, 7, 1), 'F') )
1512 self.assertEqual(d.as_tuple(), (1, (0,), 'F'))
1513
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001514 def test_immutability_operations(self):
1515 # Do operations and check that it didn't change change internal objects.
1516
1517 d1 = Decimal('-25e55')
1518 b1 = Decimal('-25e55')
Facundo Batista353750c2007-09-13 18:13:15 +00001519 d2 = Decimal('33e+33')
1520 b2 = Decimal('33e+33')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001521
1522 def checkSameDec(operation, useOther=False):
1523 if useOther:
1524 eval("d1." + operation + "(d2)")
1525 self.assertEqual(d1._sign, b1._sign)
1526 self.assertEqual(d1._int, b1._int)
1527 self.assertEqual(d1._exp, b1._exp)
1528 self.assertEqual(d2._sign, b2._sign)
1529 self.assertEqual(d2._int, b2._int)
1530 self.assertEqual(d2._exp, b2._exp)
1531 else:
1532 eval("d1." + operation + "()")
1533 self.assertEqual(d1._sign, b1._sign)
1534 self.assertEqual(d1._int, b1._int)
1535 self.assertEqual(d1._exp, b1._exp)
1536 return
1537
1538 Decimal(d1)
1539 self.assertEqual(d1._sign, b1._sign)
1540 self.assertEqual(d1._int, b1._int)
1541 self.assertEqual(d1._exp, b1._exp)
1542
1543 checkSameDec("__abs__")
1544 checkSameDec("__add__", True)
1545 checkSameDec("__div__", True)
1546 checkSameDec("__divmod__", True)
Mark Dickinson2fc92632008-02-06 22:10:50 +00001547 checkSameDec("__eq__", True)
1548 checkSameDec("__ne__", True)
1549 checkSameDec("__le__", True)
1550 checkSameDec("__lt__", True)
1551 checkSameDec("__ge__", True)
1552 checkSameDec("__gt__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001553 checkSameDec("__float__")
1554 checkSameDec("__floordiv__", True)
1555 checkSameDec("__hash__")
1556 checkSameDec("__int__")
Raymond Hettinger5a053642008-01-24 19:05:29 +00001557 checkSameDec("__trunc__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001558 checkSameDec("__long__")
1559 checkSameDec("__mod__", True)
1560 checkSameDec("__mul__", True)
1561 checkSameDec("__neg__")
1562 checkSameDec("__nonzero__")
1563 checkSameDec("__pos__")
1564 checkSameDec("__pow__", True)
1565 checkSameDec("__radd__", True)
1566 checkSameDec("__rdiv__", True)
1567 checkSameDec("__rdivmod__", True)
1568 checkSameDec("__repr__")
1569 checkSameDec("__rfloordiv__", True)
1570 checkSameDec("__rmod__", True)
1571 checkSameDec("__rmul__", True)
1572 checkSameDec("__rpow__", True)
1573 checkSameDec("__rsub__", True)
1574 checkSameDec("__str__")
1575 checkSameDec("__sub__", True)
1576 checkSameDec("__truediv__", True)
1577 checkSameDec("adjusted")
1578 checkSameDec("as_tuple")
1579 checkSameDec("compare", True)
1580 checkSameDec("max", True)
1581 checkSameDec("min", True)
1582 checkSameDec("normalize")
1583 checkSameDec("quantize", True)
1584 checkSameDec("remainder_near", True)
1585 checkSameDec("same_quantum", True)
1586 checkSameDec("sqrt")
1587 checkSameDec("to_eng_string")
1588 checkSameDec("to_integral")
1589
Facundo Batista6c398da2007-09-17 17:30:13 +00001590 def test_subclassing(self):
1591 # Different behaviours when subclassing Decimal
1592
1593 class MyDecimal(Decimal):
1594 pass
1595
1596 d1 = MyDecimal(1)
1597 d2 = MyDecimal(2)
1598 d = d1 + d2
Ezio Melotti856a3be2010-04-03 14:51:00 +00001599 self.assertIs(type(d), Decimal)
Facundo Batista6c398da2007-09-17 17:30:13 +00001600
1601 d = d1.max(d2)
Ezio Melotti856a3be2010-04-03 14:51:00 +00001602 self.assertIs(type(d), Decimal)
Facundo Batista6c398da2007-09-17 17:30:13 +00001603
Mark Dickinson3b24ccb2008-03-25 14:33:23 +00001604 def test_implicit_context(self):
1605 # Check results when context given implicitly. (Issue 2478)
1606 c = getcontext()
1607 self.assertEqual(str(Decimal(0).sqrt()),
1608 str(c.sqrt(Decimal(0))))
1609
Mark Dickinson0c673122009-10-29 12:04:00 +00001610 def test_conversions_from_int(self):
1611 # Check that methods taking a second Decimal argument will
1612 # always accept an integer in place of a Decimal.
1613 self.assertEqual(Decimal(4).compare(3),
1614 Decimal(4).compare(Decimal(3)))
1615 self.assertEqual(Decimal(4).compare_signal(3),
1616 Decimal(4).compare_signal(Decimal(3)))
1617 self.assertEqual(Decimal(4).compare_total(3),
1618 Decimal(4).compare_total(Decimal(3)))
1619 self.assertEqual(Decimal(4).compare_total_mag(3),
1620 Decimal(4).compare_total_mag(Decimal(3)))
1621 self.assertEqual(Decimal(10101).logical_and(1001),
1622 Decimal(10101).logical_and(Decimal(1001)))
1623 self.assertEqual(Decimal(10101).logical_or(1001),
1624 Decimal(10101).logical_or(Decimal(1001)))
1625 self.assertEqual(Decimal(10101).logical_xor(1001),
1626 Decimal(10101).logical_xor(Decimal(1001)))
1627 self.assertEqual(Decimal(567).max(123),
1628 Decimal(567).max(Decimal(123)))
1629 self.assertEqual(Decimal(567).max_mag(123),
1630 Decimal(567).max_mag(Decimal(123)))
1631 self.assertEqual(Decimal(567).min(123),
1632 Decimal(567).min(Decimal(123)))
1633 self.assertEqual(Decimal(567).min_mag(123),
1634 Decimal(567).min_mag(Decimal(123)))
1635 self.assertEqual(Decimal(567).next_toward(123),
1636 Decimal(567).next_toward(Decimal(123)))
1637 self.assertEqual(Decimal(1234).quantize(100),
1638 Decimal(1234).quantize(Decimal(100)))
1639 self.assertEqual(Decimal(768).remainder_near(1234),
1640 Decimal(768).remainder_near(Decimal(1234)))
1641 self.assertEqual(Decimal(123).rotate(1),
1642 Decimal(123).rotate(Decimal(1)))
1643 self.assertEqual(Decimal(1234).same_quantum(1000),
1644 Decimal(1234).same_quantum(Decimal(1000)))
1645 self.assertEqual(Decimal('9.123').scaleb(-100),
1646 Decimal('9.123').scaleb(Decimal(-100)))
1647 self.assertEqual(Decimal(456).shift(-1),
1648 Decimal(456).shift(Decimal(-1)))
1649
1650 self.assertEqual(Decimal(-12).fma(Decimal(45), 67),
1651 Decimal(-12).fma(Decimal(45), Decimal(67)))
1652 self.assertEqual(Decimal(-12).fma(45, 67),
1653 Decimal(-12).fma(Decimal(45), Decimal(67)))
1654 self.assertEqual(Decimal(-12).fma(45, Decimal(67)),
1655 Decimal(-12).fma(Decimal(45), Decimal(67)))
1656
Facundo Batista6c398da2007-09-17 17:30:13 +00001657
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001658class DecimalPythonAPItests(unittest.TestCase):
1659
Raymond Hettinger2c8585b2009-02-03 03:37:03 +00001660 def test_abc(self):
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001661 self.assertTrue(issubclass(Decimal, numbers.Number))
Ezio Melotti856a3be2010-04-03 14:51:00 +00001662 self.assertFalse(issubclass(Decimal, numbers.Real))
Ezio Melottib0f5adc2010-01-24 16:58:36 +00001663 self.assertIsInstance(Decimal(0), numbers.Number)
Ezio Melotti856a3be2010-04-03 14:51:00 +00001664 self.assertNotIsInstance(Decimal(0), numbers.Real)
Raymond Hettinger2c8585b2009-02-03 03:37:03 +00001665
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001666 def test_pickle(self):
1667 d = Decimal('-3.141590000')
1668 p = pickle.dumps(d)
1669 e = pickle.loads(p)
1670 self.assertEqual(d, e)
1671
Raymond Hettinger5548be22004-07-05 18:49:38 +00001672 def test_int(self):
Raymond Hettinger605ed022004-11-24 07:28:48 +00001673 for x in range(-250, 250):
1674 s = '%0.2f' % (x / 100.0)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001675 # should work the same as for floats
1676 self.assertEqual(int(Decimal(s)), int(float(s)))
Raymond Hettinger605ed022004-11-24 07:28:48 +00001677 # should work the same as to_integral in the ROUND_DOWN mode
Raymond Hettinger5548be22004-07-05 18:49:38 +00001678 d = Decimal(s)
Raymond Hettinger605ed022004-11-24 07:28:48 +00001679 r = d.to_integral(ROUND_DOWN)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001680 self.assertEqual(Decimal(int(d)), r)
1681
Mark Dickinson968f1692009-09-07 18:04:58 +00001682 self.assertRaises(ValueError, int, Decimal('-nan'))
1683 self.assertRaises(ValueError, int, Decimal('snan'))
1684 self.assertRaises(OverflowError, int, Decimal('inf'))
1685 self.assertRaises(OverflowError, int, Decimal('-inf'))
1686
1687 self.assertRaises(ValueError, long, Decimal('-nan'))
1688 self.assertRaises(ValueError, long, Decimal('snan'))
1689 self.assertRaises(OverflowError, long, Decimal('inf'))
1690 self.assertRaises(OverflowError, long, Decimal('-inf'))
1691
Raymond Hettinger5a053642008-01-24 19:05:29 +00001692 def test_trunc(self):
1693 for x in range(-250, 250):
1694 s = '%0.2f' % (x / 100.0)
1695 # should work the same as for floats
1696 self.assertEqual(int(Decimal(s)), int(float(s)))
1697 # should work the same as to_integral in the ROUND_DOWN mode
1698 d = Decimal(s)
1699 r = d.to_integral(ROUND_DOWN)
Jeffrey Yasskinca2b69f2008-02-01 06:22:46 +00001700 self.assertEqual(Decimal(math.trunc(d)), r)
Raymond Hettinger5a053642008-01-24 19:05:29 +00001701
Raymond Hettingerf4d85972009-01-03 19:02:23 +00001702 def test_from_float(self):
1703
1704 class MyDecimal(Decimal):
1705 pass
1706
1707 r = MyDecimal.from_float(0.1)
1708 self.assertEqual(type(r), MyDecimal)
1709 self.assertEqual(str(r),
1710 '0.1000000000000000055511151231257827021181583404541015625')
1711 bigint = 12345678901234567890123456789
1712 self.assertEqual(MyDecimal.from_float(bigint), MyDecimal(bigint))
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001713 self.assertTrue(MyDecimal.from_float(float('nan')).is_qnan())
1714 self.assertTrue(MyDecimal.from_float(float('inf')).is_infinite())
1715 self.assertTrue(MyDecimal.from_float(float('-inf')).is_infinite())
Raymond Hettingerf4d85972009-01-03 19:02:23 +00001716 self.assertEqual(str(MyDecimal.from_float(float('nan'))),
1717 str(Decimal('NaN')))
1718 self.assertEqual(str(MyDecimal.from_float(float('inf'))),
1719 str(Decimal('Infinity')))
1720 self.assertEqual(str(MyDecimal.from_float(float('-inf'))),
1721 str(Decimal('-Infinity')))
1722 self.assertRaises(TypeError, MyDecimal.from_float, 'abc')
1723 for i in range(200):
1724 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
1725 self.assertEqual(x, float(MyDecimal.from_float(x))) # roundtrip
1726
1727 def test_create_decimal_from_float(self):
1728 context = Context(prec=5, rounding=ROUND_DOWN)
1729 self.assertEqual(
1730 context.create_decimal_from_float(math.pi),
1731 Decimal('3.1415')
1732 )
1733 context = Context(prec=5, rounding=ROUND_UP)
1734 self.assertEqual(
1735 context.create_decimal_from_float(math.pi),
1736 Decimal('3.1416')
1737 )
1738 context = Context(prec=5, traps=[Inexact])
1739 self.assertRaises(
1740 Inexact,
1741 context.create_decimal_from_float,
1742 math.pi
1743 )
1744 self.assertEqual(repr(context.create_decimal_from_float(-0.0)),
1745 "Decimal('-0')")
1746 self.assertEqual(repr(context.create_decimal_from_float(1.0)),
1747 "Decimal('1')")
1748 self.assertEqual(repr(context.create_decimal_from_float(10)),
1749 "Decimal('10')")
1750
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00001751class ContextAPItests(unittest.TestCase):
1752
1753 def test_pickle(self):
1754 c = Context()
1755 e = pickle.loads(pickle.dumps(c))
1756 for k in vars(c):
1757 v1 = vars(c)[k]
1758 v2 = vars(e)[k]
1759 self.assertEqual(v1, v2)
1760
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001761 def test_equality_with_other_types(self):
Ezio Melottiaa980582010-01-23 23:04:36 +00001762 self.assertIn(Decimal(10), ['a', 1.0, Decimal(10), (1,2), {}])
1763 self.assertNotIn(Decimal(10), ['a', 1.0, (1,2), {}])
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001764
Raymond Hettinger955d2b22004-08-08 20:17:45 +00001765 def test_copy(self):
1766 # All copies should be deep
1767 c = Context()
1768 d = c.copy()
1769 self.assertNotEqual(id(c), id(d))
1770 self.assertNotEqual(id(c.flags), id(d.flags))
1771 self.assertNotEqual(id(c.traps), id(d.traps))
1772
Mark Dickinson6d8effb2010-02-18 14:27:02 +00001773 def test_abs(self):
1774 c = Context()
1775 d = c.abs(Decimal(-1))
1776 self.assertEqual(c.abs(-1), d)
1777 self.assertRaises(TypeError, c.abs, '-1')
1778
1779 def test_add(self):
1780 c = Context()
1781 d = c.add(Decimal(1), Decimal(1))
1782 self.assertEqual(c.add(1, 1), d)
1783 self.assertEqual(c.add(Decimal(1), 1), d)
1784 self.assertEqual(c.add(1, Decimal(1)), d)
1785 self.assertRaises(TypeError, c.add, '1', 1)
1786 self.assertRaises(TypeError, c.add, 1, '1')
1787
1788 def test_compare(self):
1789 c = Context()
1790 d = c.compare(Decimal(1), Decimal(1))
1791 self.assertEqual(c.compare(1, 1), d)
1792 self.assertEqual(c.compare(Decimal(1), 1), d)
1793 self.assertEqual(c.compare(1, Decimal(1)), d)
1794 self.assertRaises(TypeError, c.compare, '1', 1)
1795 self.assertRaises(TypeError, c.compare, 1, '1')
1796
1797 def test_compare_signal(self):
1798 c = Context()
1799 d = c.compare_signal(Decimal(1), Decimal(1))
1800 self.assertEqual(c.compare_signal(1, 1), d)
1801 self.assertEqual(c.compare_signal(Decimal(1), 1), d)
1802 self.assertEqual(c.compare_signal(1, Decimal(1)), d)
1803 self.assertRaises(TypeError, c.compare_signal, '1', 1)
1804 self.assertRaises(TypeError, c.compare_signal, 1, '1')
1805
1806 def test_compare_total(self):
1807 c = Context()
1808 d = c.compare_total(Decimal(1), Decimal(1))
1809 self.assertEqual(c.compare_total(1, 1), d)
1810 self.assertEqual(c.compare_total(Decimal(1), 1), d)
1811 self.assertEqual(c.compare_total(1, Decimal(1)), d)
1812 self.assertRaises(TypeError, c.compare_total, '1', 1)
1813 self.assertRaises(TypeError, c.compare_total, 1, '1')
1814
1815 def test_compare_total_mag(self):
1816 c = Context()
1817 d = c.compare_total_mag(Decimal(1), Decimal(1))
1818 self.assertEqual(c.compare_total_mag(1, 1), d)
1819 self.assertEqual(c.compare_total_mag(Decimal(1), 1), d)
1820 self.assertEqual(c.compare_total_mag(1, Decimal(1)), d)
1821 self.assertRaises(TypeError, c.compare_total_mag, '1', 1)
1822 self.assertRaises(TypeError, c.compare_total_mag, 1, '1')
1823
1824 def test_copy_abs(self):
1825 c = Context()
1826 d = c.copy_abs(Decimal(-1))
1827 self.assertEqual(c.copy_abs(-1), d)
1828 self.assertRaises(TypeError, c.copy_abs, '-1')
1829
1830 def test_copy_decimal(self):
1831 c = Context()
1832 d = c.copy_decimal(Decimal(-1))
1833 self.assertEqual(c.copy_decimal(-1), d)
1834 self.assertRaises(TypeError, c.copy_decimal, '-1')
1835
1836 def test_copy_negate(self):
1837 c = Context()
1838 d = c.copy_negate(Decimal(-1))
1839 self.assertEqual(c.copy_negate(-1), d)
1840 self.assertRaises(TypeError, c.copy_negate, '-1')
1841
1842 def test_copy_sign(self):
1843 c = Context()
1844 d = c.copy_sign(Decimal(1), Decimal(-2))
1845 self.assertEqual(c.copy_sign(1, -2), d)
1846 self.assertEqual(c.copy_sign(Decimal(1), -2), d)
1847 self.assertEqual(c.copy_sign(1, Decimal(-2)), d)
1848 self.assertRaises(TypeError, c.copy_sign, '1', -2)
1849 self.assertRaises(TypeError, c.copy_sign, 1, '-2')
1850
1851 def test_divide(self):
1852 c = Context()
1853 d = c.divide(Decimal(1), Decimal(2))
1854 self.assertEqual(c.divide(1, 2), d)
1855 self.assertEqual(c.divide(Decimal(1), 2), d)
1856 self.assertEqual(c.divide(1, Decimal(2)), d)
1857 self.assertRaises(TypeError, c.divide, '1', 2)
1858 self.assertRaises(TypeError, c.divide, 1, '2')
1859
1860 def test_divide_int(self):
1861 c = Context()
1862 d = c.divide_int(Decimal(1), Decimal(2))
1863 self.assertEqual(c.divide_int(1, 2), d)
1864 self.assertEqual(c.divide_int(Decimal(1), 2), d)
1865 self.assertEqual(c.divide_int(1, Decimal(2)), d)
1866 self.assertRaises(TypeError, c.divide_int, '1', 2)
1867 self.assertRaises(TypeError, c.divide_int, 1, '2')
1868
1869 def test_divmod(self):
1870 c = Context()
1871 d = c.divmod(Decimal(1), Decimal(2))
1872 self.assertEqual(c.divmod(1, 2), d)
1873 self.assertEqual(c.divmod(Decimal(1), 2), d)
1874 self.assertEqual(c.divmod(1, Decimal(2)), d)
1875 self.assertRaises(TypeError, c.divmod, '1', 2)
1876 self.assertRaises(TypeError, c.divmod, 1, '2')
1877
1878 def test_exp(self):
1879 c = Context()
1880 d = c.exp(Decimal(10))
1881 self.assertEqual(c.exp(10), d)
1882 self.assertRaises(TypeError, c.exp, '10')
1883
1884 def test_fma(self):
1885 c = Context()
1886 d = c.fma(Decimal(2), Decimal(3), Decimal(4))
1887 self.assertEqual(c.fma(2, 3, 4), d)
1888 self.assertEqual(c.fma(Decimal(2), 3, 4), d)
1889 self.assertEqual(c.fma(2, Decimal(3), 4), d)
1890 self.assertEqual(c.fma(2, 3, Decimal(4)), d)
1891 self.assertEqual(c.fma(Decimal(2), Decimal(3), 4), d)
1892 self.assertRaises(TypeError, c.fma, '2', 3, 4)
1893 self.assertRaises(TypeError, c.fma, 2, '3', 4)
1894 self.assertRaises(TypeError, c.fma, 2, 3, '4')
1895
1896 def test_is_finite(self):
1897 c = Context()
1898 d = c.is_finite(Decimal(10))
1899 self.assertEqual(c.is_finite(10), d)
1900 self.assertRaises(TypeError, c.is_finite, '10')
1901
1902 def test_is_infinite(self):
1903 c = Context()
1904 d = c.is_infinite(Decimal(10))
1905 self.assertEqual(c.is_infinite(10), d)
1906 self.assertRaises(TypeError, c.is_infinite, '10')
1907
1908 def test_is_nan(self):
1909 c = Context()
1910 d = c.is_nan(Decimal(10))
1911 self.assertEqual(c.is_nan(10), d)
1912 self.assertRaises(TypeError, c.is_nan, '10')
1913
1914 def test_is_normal(self):
1915 c = Context()
1916 d = c.is_normal(Decimal(10))
1917 self.assertEqual(c.is_normal(10), d)
1918 self.assertRaises(TypeError, c.is_normal, '10')
1919
1920 def test_is_qnan(self):
1921 c = Context()
1922 d = c.is_qnan(Decimal(10))
1923 self.assertEqual(c.is_qnan(10), d)
1924 self.assertRaises(TypeError, c.is_qnan, '10')
1925
1926 def test_is_signed(self):
1927 c = Context()
1928 d = c.is_signed(Decimal(10))
1929 self.assertEqual(c.is_signed(10), d)
1930 self.assertRaises(TypeError, c.is_signed, '10')
1931
1932 def test_is_snan(self):
1933 c = Context()
1934 d = c.is_snan(Decimal(10))
1935 self.assertEqual(c.is_snan(10), d)
1936 self.assertRaises(TypeError, c.is_snan, '10')
1937
1938 def test_is_subnormal(self):
1939 c = Context()
1940 d = c.is_subnormal(Decimal(10))
1941 self.assertEqual(c.is_subnormal(10), d)
1942 self.assertRaises(TypeError, c.is_subnormal, '10')
1943
1944 def test_is_zero(self):
1945 c = Context()
1946 d = c.is_zero(Decimal(10))
1947 self.assertEqual(c.is_zero(10), d)
1948 self.assertRaises(TypeError, c.is_zero, '10')
1949
1950 def test_ln(self):
1951 c = Context()
1952 d = c.ln(Decimal(10))
1953 self.assertEqual(c.ln(10), d)
1954 self.assertRaises(TypeError, c.ln, '10')
1955
1956 def test_log10(self):
1957 c = Context()
1958 d = c.log10(Decimal(10))
1959 self.assertEqual(c.log10(10), d)
1960 self.assertRaises(TypeError, c.log10, '10')
1961
1962 def test_logb(self):
1963 c = Context()
1964 d = c.logb(Decimal(10))
1965 self.assertEqual(c.logb(10), d)
1966 self.assertRaises(TypeError, c.logb, '10')
1967
1968 def test_logical_and(self):
1969 c = Context()
1970 d = c.logical_and(Decimal(1), Decimal(1))
1971 self.assertEqual(c.logical_and(1, 1), d)
1972 self.assertEqual(c.logical_and(Decimal(1), 1), d)
1973 self.assertEqual(c.logical_and(1, Decimal(1)), d)
1974 self.assertRaises(TypeError, c.logical_and, '1', 1)
1975 self.assertRaises(TypeError, c.logical_and, 1, '1')
1976
1977 def test_logical_invert(self):
1978 c = Context()
1979 d = c.logical_invert(Decimal(1000))
1980 self.assertEqual(c.logical_invert(1000), d)
1981 self.assertRaises(TypeError, c.logical_invert, '1000')
1982
1983 def test_logical_or(self):
1984 c = Context()
1985 d = c.logical_or(Decimal(1), Decimal(1))
1986 self.assertEqual(c.logical_or(1, 1), d)
1987 self.assertEqual(c.logical_or(Decimal(1), 1), d)
1988 self.assertEqual(c.logical_or(1, Decimal(1)), d)
1989 self.assertRaises(TypeError, c.logical_or, '1', 1)
1990 self.assertRaises(TypeError, c.logical_or, 1, '1')
1991
1992 def test_logical_xor(self):
1993 c = Context()
1994 d = c.logical_xor(Decimal(1), Decimal(1))
1995 self.assertEqual(c.logical_xor(1, 1), d)
1996 self.assertEqual(c.logical_xor(Decimal(1), 1), d)
1997 self.assertEqual(c.logical_xor(1, Decimal(1)), d)
1998 self.assertRaises(TypeError, c.logical_xor, '1', 1)
1999 self.assertRaises(TypeError, c.logical_xor, 1, '1')
2000
2001 def test_max(self):
2002 c = Context()
2003 d = c.max(Decimal(1), Decimal(2))
2004 self.assertEqual(c.max(1, 2), d)
2005 self.assertEqual(c.max(Decimal(1), 2), d)
2006 self.assertEqual(c.max(1, Decimal(2)), d)
2007 self.assertRaises(TypeError, c.max, '1', 2)
2008 self.assertRaises(TypeError, c.max, 1, '2')
2009
2010 def test_max_mag(self):
2011 c = Context()
2012 d = c.max_mag(Decimal(1), Decimal(2))
2013 self.assertEqual(c.max_mag(1, 2), d)
2014 self.assertEqual(c.max_mag(Decimal(1), 2), d)
2015 self.assertEqual(c.max_mag(1, Decimal(2)), d)
2016 self.assertRaises(TypeError, c.max_mag, '1', 2)
2017 self.assertRaises(TypeError, c.max_mag, 1, '2')
2018
2019 def test_min(self):
2020 c = Context()
2021 d = c.min(Decimal(1), Decimal(2))
2022 self.assertEqual(c.min(1, 2), d)
2023 self.assertEqual(c.min(Decimal(1), 2), d)
2024 self.assertEqual(c.min(1, Decimal(2)), d)
2025 self.assertRaises(TypeError, c.min, '1', 2)
2026 self.assertRaises(TypeError, c.min, 1, '2')
2027
2028 def test_min_mag(self):
2029 c = Context()
2030 d = c.min_mag(Decimal(1), Decimal(2))
2031 self.assertEqual(c.min_mag(1, 2), d)
2032 self.assertEqual(c.min_mag(Decimal(1), 2), d)
2033 self.assertEqual(c.min_mag(1, Decimal(2)), d)
2034 self.assertRaises(TypeError, c.min_mag, '1', 2)
2035 self.assertRaises(TypeError, c.min_mag, 1, '2')
2036
2037 def test_minus(self):
2038 c = Context()
2039 d = c.minus(Decimal(10))
2040 self.assertEqual(c.minus(10), d)
2041 self.assertRaises(TypeError, c.minus, '10')
2042
2043 def test_multiply(self):
2044 c = Context()
2045 d = c.multiply(Decimal(1), Decimal(2))
2046 self.assertEqual(c.multiply(1, 2), d)
2047 self.assertEqual(c.multiply(Decimal(1), 2), d)
2048 self.assertEqual(c.multiply(1, Decimal(2)), d)
2049 self.assertRaises(TypeError, c.multiply, '1', 2)
2050 self.assertRaises(TypeError, c.multiply, 1, '2')
2051
2052 def test_next_minus(self):
2053 c = Context()
2054 d = c.next_minus(Decimal(10))
2055 self.assertEqual(c.next_minus(10), d)
2056 self.assertRaises(TypeError, c.next_minus, '10')
2057
2058 def test_next_plus(self):
2059 c = Context()
2060 d = c.next_plus(Decimal(10))
2061 self.assertEqual(c.next_plus(10), d)
2062 self.assertRaises(TypeError, c.next_plus, '10')
2063
2064 def test_next_toward(self):
2065 c = Context()
2066 d = c.next_toward(Decimal(1), Decimal(2))
2067 self.assertEqual(c.next_toward(1, 2), d)
2068 self.assertEqual(c.next_toward(Decimal(1), 2), d)
2069 self.assertEqual(c.next_toward(1, Decimal(2)), d)
2070 self.assertRaises(TypeError, c.next_toward, '1', 2)
2071 self.assertRaises(TypeError, c.next_toward, 1, '2')
2072
2073 def test_normalize(self):
2074 c = Context()
2075 d = c.normalize(Decimal(10))
2076 self.assertEqual(c.normalize(10), d)
2077 self.assertRaises(TypeError, c.normalize, '10')
2078
2079 def test_number_class(self):
2080 c = Context()
2081 self.assertEqual(c.number_class(123), c.number_class(Decimal(123)))
2082 self.assertEqual(c.number_class(0), c.number_class(Decimal(0)))
2083 self.assertEqual(c.number_class(-45), c.number_class(Decimal(-45)))
2084
2085 def test_power(self):
2086 c = Context()
2087 d = c.power(Decimal(1), Decimal(4), Decimal(2))
2088 self.assertEqual(c.power(1, 4, 2), d)
2089 self.assertEqual(c.power(Decimal(1), 4, 2), d)
2090 self.assertEqual(c.power(1, Decimal(4), 2), d)
2091 self.assertEqual(c.power(1, 4, Decimal(2)), d)
2092 self.assertEqual(c.power(Decimal(1), Decimal(4), 2), d)
2093 self.assertRaises(TypeError, c.power, '1', 4, 2)
2094 self.assertRaises(TypeError, c.power, 1, '4', 2)
2095 self.assertRaises(TypeError, c.power, 1, 4, '2')
2096
2097 def test_plus(self):
2098 c = Context()
2099 d = c.plus(Decimal(10))
2100 self.assertEqual(c.plus(10), d)
2101 self.assertRaises(TypeError, c.plus, '10')
2102
2103 def test_quantize(self):
2104 c = Context()
2105 d = c.quantize(Decimal(1), Decimal(2))
2106 self.assertEqual(c.quantize(1, 2), d)
2107 self.assertEqual(c.quantize(Decimal(1), 2), d)
2108 self.assertEqual(c.quantize(1, Decimal(2)), d)
2109 self.assertRaises(TypeError, c.quantize, '1', 2)
2110 self.assertRaises(TypeError, c.quantize, 1, '2')
2111
2112 def test_remainder(self):
2113 c = Context()
2114 d = c.remainder(Decimal(1), Decimal(2))
2115 self.assertEqual(c.remainder(1, 2), d)
2116 self.assertEqual(c.remainder(Decimal(1), 2), d)
2117 self.assertEqual(c.remainder(1, Decimal(2)), d)
2118 self.assertRaises(TypeError, c.remainder, '1', 2)
2119 self.assertRaises(TypeError, c.remainder, 1, '2')
2120
2121 def test_remainder_near(self):
2122 c = Context()
2123 d = c.remainder_near(Decimal(1), Decimal(2))
2124 self.assertEqual(c.remainder_near(1, 2), d)
2125 self.assertEqual(c.remainder_near(Decimal(1), 2), d)
2126 self.assertEqual(c.remainder_near(1, Decimal(2)), d)
2127 self.assertRaises(TypeError, c.remainder_near, '1', 2)
2128 self.assertRaises(TypeError, c.remainder_near, 1, '2')
2129
2130 def test_rotate(self):
2131 c = Context()
2132 d = c.rotate(Decimal(1), Decimal(2))
2133 self.assertEqual(c.rotate(1, 2), d)
2134 self.assertEqual(c.rotate(Decimal(1), 2), d)
2135 self.assertEqual(c.rotate(1, Decimal(2)), d)
2136 self.assertRaises(TypeError, c.rotate, '1', 2)
2137 self.assertRaises(TypeError, c.rotate, 1, '2')
2138
2139 def test_sqrt(self):
2140 c = Context()
2141 d = c.sqrt(Decimal(10))
2142 self.assertEqual(c.sqrt(10), d)
2143 self.assertRaises(TypeError, c.sqrt, '10')
2144
2145 def test_same_quantum(self):
2146 c = Context()
2147 d = c.same_quantum(Decimal(1), Decimal(2))
2148 self.assertEqual(c.same_quantum(1, 2), d)
2149 self.assertEqual(c.same_quantum(Decimal(1), 2), d)
2150 self.assertEqual(c.same_quantum(1, Decimal(2)), d)
2151 self.assertRaises(TypeError, c.same_quantum, '1', 2)
2152 self.assertRaises(TypeError, c.same_quantum, 1, '2')
2153
2154 def test_scaleb(self):
2155 c = Context()
2156 d = c.scaleb(Decimal(1), Decimal(2))
2157 self.assertEqual(c.scaleb(1, 2), d)
2158 self.assertEqual(c.scaleb(Decimal(1), 2), d)
2159 self.assertEqual(c.scaleb(1, Decimal(2)), d)
2160 self.assertRaises(TypeError, c.scaleb, '1', 2)
2161 self.assertRaises(TypeError, c.scaleb, 1, '2')
2162
2163 def test_shift(self):
2164 c = Context()
2165 d = c.shift(Decimal(1), Decimal(2))
2166 self.assertEqual(c.shift(1, 2), d)
2167 self.assertEqual(c.shift(Decimal(1), 2), d)
2168 self.assertEqual(c.shift(1, Decimal(2)), d)
2169 self.assertRaises(TypeError, c.shift, '1', 2)
2170 self.assertRaises(TypeError, c.shift, 1, '2')
2171
2172 def test_subtract(self):
2173 c = Context()
2174 d = c.subtract(Decimal(1), Decimal(2))
2175 self.assertEqual(c.subtract(1, 2), d)
2176 self.assertEqual(c.subtract(Decimal(1), 2), d)
2177 self.assertEqual(c.subtract(1, Decimal(2)), d)
2178 self.assertRaises(TypeError, c.subtract, '1', 2)
2179 self.assertRaises(TypeError, c.subtract, 1, '2')
2180
2181 def test_to_eng_string(self):
2182 c = Context()
2183 d = c.to_eng_string(Decimal(10))
2184 self.assertEqual(c.to_eng_string(10), d)
2185 self.assertRaises(TypeError, c.to_eng_string, '10')
2186
2187 def test_to_sci_string(self):
2188 c = Context()
2189 d = c.to_sci_string(Decimal(10))
2190 self.assertEqual(c.to_sci_string(10), d)
2191 self.assertRaises(TypeError, c.to_sci_string, '10')
2192
2193 def test_to_integral_exact(self):
2194 c = Context()
2195 d = c.to_integral_exact(Decimal(10))
2196 self.assertEqual(c.to_integral_exact(10), d)
2197 self.assertRaises(TypeError, c.to_integral_exact, '10')
2198
2199 def test_to_integral_value(self):
2200 c = Context()
2201 d = c.to_integral_value(Decimal(10))
2202 self.assertEqual(c.to_integral_value(10), d)
2203 self.assertRaises(TypeError, c.to_integral_value, '10')
2204
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002205class WithStatementTest(unittest.TestCase):
2206 # Can't do these as docstrings until Python 2.6
2207 # as doctest can't handle __future__ statements
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002208
2209 def test_localcontext(self):
Nick Coghlanced12182006-09-02 03:54:17 +00002210 # Use a copy of the current context in the block
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002211 orig_ctx = getcontext()
2212 with localcontext() as enter_ctx:
2213 set_ctx = getcontext()
2214 final_ctx = getcontext()
Ezio Melotti856a3be2010-04-03 14:51:00 +00002215 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
2216 self.assertIsNot(orig_ctx, set_ctx, 'did not copy the context')
2217 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002218
2219 def test_localcontextarg(self):
Nick Coghlanced12182006-09-02 03:54:17 +00002220 # Use a copy of the supplied context in the block
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002221 orig_ctx = getcontext()
2222 new_ctx = Context(prec=42)
2223 with localcontext(new_ctx) as enter_ctx:
2224 set_ctx = getcontext()
2225 final_ctx = getcontext()
Ezio Melotti856a3be2010-04-03 14:51:00 +00002226 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
2227 self.assertEqual(set_ctx.prec, new_ctx.prec, 'did not set correct context')
2228 self.assertIsNot(new_ctx, set_ctx, 'did not copy the context')
2229 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002230
Facundo Batista353750c2007-09-13 18:13:15 +00002231class ContextFlags(unittest.TestCase):
2232 def test_flags_irrelevant(self):
2233 # check that the result (numeric result + flags raised) of an
2234 # arithmetic operation doesn't depend on the current flags
2235
2236 context = Context(prec=9, Emin = -999999999, Emax = 999999999,
2237 rounding=ROUND_HALF_EVEN, traps=[], flags=[])
2238
2239 # operations that raise various flags, in the form (function, arglist)
2240 operations = [
2241 (context._apply, [Decimal("100E-1000000009")]),
2242 (context.sqrt, [Decimal(2)]),
2243 (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]),
2244 (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]),
2245 (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]),
2246 ]
2247
2248 # try various flags individually, then a whole lot at once
2249 flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal],
2250 [Inexact, Rounded, Underflow, Clamped, Subnormal]]
2251
2252 for fn, args in operations:
2253 # find answer and flags raised using a clean context
2254 context.clear_flags()
2255 ans = fn(*args)
2256 flags = [k for k, v in context.flags.items() if v]
2257
2258 for extra_flags in flagsets:
2259 # set flags, before calling operation
2260 context.clear_flags()
2261 for flag in extra_flags:
2262 context._raise_error(flag)
2263 new_ans = fn(*args)
2264
2265 # flags that we expect to be set after the operation
2266 expected_flags = list(flags)
2267 for flag in extra_flags:
2268 if flag not in expected_flags:
2269 expected_flags.append(flag)
Facundo Batista353750c2007-09-13 18:13:15 +00002270
2271 # flags we actually got
2272 new_flags = [k for k,v in context.flags.items() if v]
Facundo Batista353750c2007-09-13 18:13:15 +00002273
2274 self.assertEqual(ans, new_ans,
2275 "operation produces different answers depending on flags set: " +
2276 "expected %s, got %s." % (ans, new_ans))
Florent Xicluna8f43cec2010-03-21 10:51:40 +00002277 self.assertItemsEqual(new_flags, expected_flags,
Facundo Batista353750c2007-09-13 18:13:15 +00002278 "operation raises different flags depending on flags set: " +
2279 "expected %s, got %s" % (expected_flags, new_flags))
2280
2281def test_main(arith=False, verbose=None, todo_tests=None, debug=None):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002282 """ Execute the tests.
2283
Raymond Hettingered20ad82004-09-04 20:09:13 +00002284 Runs all arithmetic tests if arith is True or if the "decimal" resource
2285 is enabled in regrtest.py
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002286 """
Raymond Hettingered20ad82004-09-04 20:09:13 +00002287
Neal Norwitzce4a9c92006-04-09 08:36:46 +00002288 init()
Facundo Batista353750c2007-09-13 18:13:15 +00002289 global TEST_ALL, DEBUG
Raymond Hettingered20ad82004-09-04 20:09:13 +00002290 TEST_ALL = arith or is_resource_enabled('decimal')
Facundo Batista353750c2007-09-13 18:13:15 +00002291 DEBUG = debug
Raymond Hettingered20ad82004-09-04 20:09:13 +00002292
Facundo Batista353750c2007-09-13 18:13:15 +00002293 if todo_tests is None:
2294 test_classes = [
2295 DecimalExplicitConstructionTest,
2296 DecimalImplicitConstructionTest,
2297 DecimalArithmeticOperatorsTest,
Mark Dickinson1ddf1d82008-02-29 02:16:37 +00002298 DecimalFormatTest,
Facundo Batista353750c2007-09-13 18:13:15 +00002299 DecimalUseOfContextTest,
2300 DecimalUsabilityTest,
2301 DecimalPythonAPItests,
2302 ContextAPItests,
2303 DecimalTest,
2304 WithStatementTest,
2305 ContextFlags
2306 ]
2307 else:
2308 test_classes = [DecimalTest]
2309
2310 # Dynamically build custom test definition for each file in the test
2311 # directory and add the definitions to the DecimalTest class. This
2312 # procedure insures that new files do not get skipped.
2313 for filename in os.listdir(directory):
2314 if '.decTest' not in filename or filename.startswith("."):
2315 continue
2316 head, tail = filename.split('.')
2317 if todo_tests is not None and head not in todo_tests:
2318 continue
2319 tester = lambda self, f=filename: self.eval_file(directory + f)
2320 setattr(DecimalTest, 'test_' + head, tester)
2321 del filename, head, tail, tester
2322
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002323
Tim Peters46cc7022006-03-31 04:11:16 +00002324 try:
2325 run_unittest(*test_classes)
Facundo Batista353750c2007-09-13 18:13:15 +00002326 if todo_tests is None:
2327 import decimal as DecimalModule
2328 run_doctest(DecimalModule, verbose)
Tim Peters46cc7022006-03-31 04:11:16 +00002329 finally:
2330 setcontext(ORIGINAL_CONTEXT)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002331
2332if __name__ == '__main__':
Facundo Batista353750c2007-09-13 18:13:15 +00002333 import optparse
2334 p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]")
2335 p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test')
2336 p.add_option('--skip', '-s', action='store_true', help='skip over 90% of the arithmetic tests')
2337 (opt, args) = p.parse_args()
2338
2339 if opt.skip:
2340 test_main(arith=False, verbose=True)
2341 elif args:
2342 test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002343 else:
Facundo Batista353750c2007-09-13 18:13:15 +00002344 test_main(arith=True, verbose=True)