blob: a011b2f76d767f54892c4a40ea62d5507ecfd24a [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.
Mark Dickinsone85aa732010-07-08 19:24:40 +000080skipped_test_ids = set([
81 # Skip implementation-specific scaleb tests.
82 'scbx164',
83 'scbx165',
84
85 # For some operations (currently exp, ln, log10, power), the decNumber
86 # reference implementation imposes additional restrictions on the context
87 # and operands. These restrictions are not part of the specification;
88 # however, the effect of these restrictions does show up in some of the
89 # testcases. We skip testcases that violate these restrictions, since
90 # Decimal behaves differently from decNumber for these testcases so these
91 # testcases would otherwise fail.
92 'expx901',
93 'expx902',
94 'expx903',
95 'expx905',
96 'lnx901',
97 'lnx902',
98 'lnx903',
99 'lnx905',
100 'logx901',
101 'logx902',
102 'logx903',
103 'logx905',
104 'powx1183',
105 'powx1184',
106 'powx4001',
107 'powx4002',
108 'powx4003',
109 'powx4005',
110 'powx4008',
111 'powx4010',
112 'powx4012',
113 'powx4014',
114 ])
Mark Dickinson539bff42009-10-08 16:28:39 +0000115
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000116# Make sure it actually raises errors when not expected and caught in flags
117# Slower, since it runs some things several times.
118EXTENDEDERRORTEST = False
119
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000120#Map the test cases' error names to the actual errors
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000121ErrorNames = {'clamped' : Clamped,
Raymond Hettinger5aa478b2004-07-09 10:02:53 +0000122 'conversion_syntax' : InvalidOperation,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000123 'division_by_zero' : DivisionByZero,
Raymond Hettinger5aa478b2004-07-09 10:02:53 +0000124 'division_impossible' : InvalidOperation,
125 'division_undefined' : InvalidOperation,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000126 'inexact' : Inexact,
Raymond Hettinger5aa478b2004-07-09 10:02:53 +0000127 'invalid_context' : InvalidOperation,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000128 'invalid_operation' : InvalidOperation,
129 'overflow' : Overflow,
130 'rounded' : Rounded,
131 'subnormal' : Subnormal,
132 'underflow' : Underflow}
133
134
135def Nonfunction(*args):
136 """Doesn't do anything."""
137 return None
138
139RoundingDict = {'ceiling' : ROUND_CEILING, #Maps test-case names to roundings.
140 'down' : ROUND_DOWN,
141 'floor' : ROUND_FLOOR,
142 'half_down' : ROUND_HALF_DOWN,
143 'half_even' : ROUND_HALF_EVEN,
144 'half_up' : ROUND_HALF_UP,
Facundo Batista353750c2007-09-13 18:13:15 +0000145 'up' : ROUND_UP,
146 '05up' : ROUND_05UP}
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000147
148# Name adapter to be able to change the Decimal and Context
149# interface without changing the test files from Cowlishaw
Facundo Batista1a191df2007-10-02 17:01:24 +0000150nameAdapter = {'and':'logical_and',
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000151 'apply':'_apply',
Facundo Batista353750c2007-09-13 18:13:15 +0000152 'class':'number_class',
153 'comparesig':'compare_signal',
154 'comparetotal':'compare_total',
155 'comparetotmag':'compare_total_mag',
Facundo Batista353750c2007-09-13 18:13:15 +0000156 'copy':'copy_decimal',
Facundo Batista1a191df2007-10-02 17:01:24 +0000157 'copyabs':'copy_abs',
Facundo Batista353750c2007-09-13 18:13:15 +0000158 'copynegate':'copy_negate',
159 'copysign':'copy_sign',
Facundo Batista1a191df2007-10-02 17:01:24 +0000160 'divideint':'divide_int',
Facundo Batista353750c2007-09-13 18:13:15 +0000161 'invert':'logical_invert',
Facundo Batista1a191df2007-10-02 17:01:24 +0000162 'iscanonical':'is_canonical',
163 'isfinite':'is_finite',
164 'isinfinite':'is_infinite',
165 'isnan':'is_nan',
166 'isnormal':'is_normal',
167 'isqnan':'is_qnan',
168 'issigned':'is_signed',
169 'issnan':'is_snan',
170 'issubnormal':'is_subnormal',
171 'iszero':'is_zero',
Facundo Batista353750c2007-09-13 18:13:15 +0000172 'maxmag':'max_mag',
173 'minmag':'min_mag',
174 'nextminus':'next_minus',
175 'nextplus':'next_plus',
176 'nexttoward':'next_toward',
Facundo Batista1a191df2007-10-02 17:01:24 +0000177 'or':'logical_or',
Facundo Batista353750c2007-09-13 18:13:15 +0000178 'reduce':'normalize',
Facundo Batista1a191df2007-10-02 17:01:24 +0000179 'remaindernear':'remainder_near',
180 'samequantum':'same_quantum',
181 'squareroot':'sqrt',
182 'toeng':'to_eng_string',
183 'tointegral':'to_integral_value',
184 'tointegralx':'to_integral_exact',
185 'tosci':'to_sci_string',
186 'xor':'logical_xor',
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000187 }
188
Facundo Batista1a191df2007-10-02 17:01:24 +0000189# The following functions return True/False rather than a Decimal instance
190
191LOGICAL_FUNCTIONS = (
192 'is_canonical',
193 'is_finite',
194 'is_infinite',
195 'is_nan',
196 'is_normal',
197 'is_qnan',
198 'is_signed',
199 'is_snan',
200 'is_subnormal',
201 'is_zero',
202 'same_quantum',
203 )
204
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000205class DecimalTest(unittest.TestCase):
206 """Class which tests the Decimal class against the test cases.
207
208 Changed for unittest.
209 """
210 def setUp(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000211 self.context = Context()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000212 self.ignore_list = ['#']
213 # Basically, a # means return NaN InvalidOperation.
214 # Different from a sNaN in trim
215
216 self.ChangeDict = {'precision' : self.change_precision,
217 'rounding' : self.change_rounding_method,
218 'maxexponent' : self.change_max_exponent,
219 'minexponent' : self.change_min_exponent,
220 'clamp' : self.change_clamp}
221
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000222 def eval_file(self, file):
223 global skip_expected
224 if skip_expected:
Benjamin Petersonbec087f2009-03-26 21:10:30 +0000225 raise unittest.SkipTest
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000226 return
Antoine Pitrou99d848b2010-10-14 22:22:30 +0000227 with open(file) as f:
228 for line in f:
229 line = line.replace('\r\n', '').replace('\n', '')
230 #print line
231 try:
232 t = self.eval_line(line)
233 except DecimalException as exception:
Ezio Melottic2077b02011-03-16 12:34:31 +0200234 #Exception raised where there shouldn't have been one.
Antoine Pitrou99d848b2010-10-14 22:22:30 +0000235 self.fail('Exception "'+exception.__class__.__name__ + '" raised on line '+line)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000236
237 return
238
239 def eval_line(self, s):
240 if s.find(' -> ') >= 0 and s[:2] != '--' and not s.startswith(' --'):
241 s = (s.split('->')[0] + '->' +
242 s.split('->')[1].split('--')[0]).strip()
243 else:
244 s = s.split('--')[0].strip()
245
246 for ignore in self.ignore_list:
247 if s.find(ignore) >= 0:
248 #print s.split()[0], 'NotImplemented--', ignore
249 return
250 if not s:
251 return
252 elif ':' in s:
253 return self.eval_directive(s)
254 else:
255 return self.eval_equation(s)
256
257 def eval_directive(self, s):
258 funct, value = map(lambda x: x.strip().lower(), s.split(':'))
259 if funct == 'rounding':
260 value = RoundingDict[value]
261 else:
262 try:
263 value = int(value)
264 except ValueError:
265 pass
266
267 funct = self.ChangeDict.get(funct, Nonfunction)
268 funct(value)
269
270 def eval_equation(self, s):
271 #global DEFAULT_PRECISION
272 #print DEFAULT_PRECISION
Raymond Hettingered20ad82004-09-04 20:09:13 +0000273
274 if not TEST_ALL and random.random() < 0.90:
275 return
276
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000277 try:
278 Sides = s.split('->')
279 L = Sides[0].strip().split()
280 id = L[0]
Facundo Batista353750c2007-09-13 18:13:15 +0000281 if DEBUG:
282 print "Test ", id,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000283 funct = L[1].lower()
284 valstemp = L[2:]
285 L = Sides[1].strip().split()
286 ans = L[0]
287 exceptions = L[1:]
288 except (TypeError, AttributeError, IndexError):
Raymond Hettingerd87ac8f2004-07-09 10:52:54 +0000289 raise InvalidOperation
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000290 def FixQuotes(val):
291 val = val.replace("''", 'SingleQuote').replace('""', 'DoubleQuote')
292 val = val.replace("'", '').replace('"', '')
293 val = val.replace('SingleQuote', "'").replace('DoubleQuote', '"')
294 return val
Mark Dickinson539bff42009-10-08 16:28:39 +0000295
296 if id in skipped_test_ids:
297 return
298
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000299 fname = nameAdapter.get(funct, funct)
300 if fname == 'rescale':
301 return
302 funct = getattr(self.context, fname)
303 vals = []
304 conglomerate = ''
305 quote = 0
306 theirexceptions = [ErrorNames[x.lower()] for x in exceptions]
307
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000308 for exception in Signals:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000309 self.context.traps[exception] = 1 #Catch these bugs...
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000310 for exception in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000311 self.context.traps[exception] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000312 for i, val in enumerate(valstemp):
313 if val.count("'") % 2 == 1:
314 quote = 1 - quote
315 if quote:
316 conglomerate = conglomerate + ' ' + val
317 continue
318 else:
319 val = conglomerate + val
320 conglomerate = ''
321 v = FixQuotes(val)
322 if fname in ('to_sci_string', 'to_eng_string'):
323 if EXTENDEDERRORTEST:
324 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000325 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000326 try:
327 funct(self.context.create_decimal(v))
328 except error:
329 pass
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000330 except Signals, e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000331 self.fail("Raised %s in %s when %s disabled" % \
332 (e, s, error))
333 else:
334 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000335 self.context.traps[error] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000336 v = self.context.create_decimal(v)
337 else:
Facundo Batista353750c2007-09-13 18:13:15 +0000338 v = Decimal(v, self.context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000339 vals.append(v)
340
341 ans = FixQuotes(ans)
342
343 if EXTENDEDERRORTEST and fname not in ('to_sci_string', 'to_eng_string'):
344 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000345 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000346 try:
347 funct(*vals)
348 except error:
349 pass
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000350 except Signals, e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000351 self.fail("Raised %s in %s when %s disabled" % \
352 (e, s, error))
353 else:
354 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000355 self.context.traps[error] = 0
Mark Dickinson4f96f5f2010-05-04 14:25:50 +0000356
357 # as above, but add traps cumulatively, to check precedence
358 ordered_errors = [e for e in OrderedSignals if e in theirexceptions]
359 for error in ordered_errors:
360 self.context.traps[error] = 1
361 try:
362 funct(*vals)
363 except error:
364 pass
365 except Signals, e:
366 self.fail("Raised %s in %s; expected %s" %
367 (type(e), s, error))
368 else:
369 self.fail("Did not raise %s in %s" % (error, s))
370 # reset traps
371 for error in ordered_errors:
372 self.context.traps[error] = 0
373
374
Facundo Batista353750c2007-09-13 18:13:15 +0000375 if DEBUG:
376 print "--", self.context
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000377 try:
378 result = str(funct(*vals))
Facundo Batista1a191df2007-10-02 17:01:24 +0000379 if fname in LOGICAL_FUNCTIONS:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000380 result = str(int(eval(result))) # 'True', 'False' -> '1', '0'
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000381 except Signals, error:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000382 self.fail("Raised %s in %s" % (error, s))
383 except: #Catch any error long enough to state the test case.
384 print "ERROR:", s
385 raise
386
387 myexceptions = self.getexceptions()
Raymond Hettingerbf440692004-07-10 14:14:37 +0000388 self.context.clear_flags()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000389
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000390 self.assertEqual(result, ans,
391 'Incorrect answer for ' + s + ' -- got ' + result)
Florent Xicluna8f43cec2010-03-21 10:51:40 +0000392 self.assertItemsEqual(myexceptions, theirexceptions,
Facundo Batista353750c2007-09-13 18:13:15 +0000393 'Incorrect flags set in ' + s + ' -- got ' + str(myexceptions))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000394 return
395
396 def getexceptions(self):
Raymond Hettingerf63ba432004-08-17 05:42:09 +0000397 return [e for e in Signals if self.context.flags[e]]
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000398
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000399 def change_precision(self, prec):
400 self.context.prec = prec
401 def change_rounding_method(self, rounding):
402 self.context.rounding = rounding
403 def change_min_exponent(self, exp):
404 self.context.Emin = exp
405 def change_max_exponent(self, exp):
406 self.context.Emax = exp
407 def change_clamp(self, clamp):
408 self.context._clamp = clamp
409
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000410
411
412# The following classes test the behaviour of Decimal according to PEP 327
413
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000414class DecimalExplicitConstructionTest(unittest.TestCase):
415 '''Unit tests for Explicit Construction cases of Decimal.'''
416
417 def test_explicit_empty(self):
418 self.assertEqual(Decimal(), Decimal("0"))
419
420 def test_explicit_from_None(self):
421 self.assertRaises(TypeError, Decimal, None)
422
423 def test_explicit_from_int(self):
424
425 #positive
426 d = Decimal(45)
427 self.assertEqual(str(d), '45')
428
429 #very large positive
430 d = Decimal(500000123)
431 self.assertEqual(str(d), '500000123')
432
433 #negative
434 d = Decimal(-45)
435 self.assertEqual(str(d), '-45')
436
437 #zero
438 d = Decimal(0)
439 self.assertEqual(str(d), '0')
440
441 def test_explicit_from_string(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000442
443 #empty
444 self.assertEqual(str(Decimal('')), 'NaN')
445
446 #int
447 self.assertEqual(str(Decimal('45')), '45')
448
449 #float
450 self.assertEqual(str(Decimal('45.34')), '45.34')
451
452 #engineer notation
453 self.assertEqual(str(Decimal('45e2')), '4.5E+3')
454
455 #just not a number
456 self.assertEqual(str(Decimal('ugly')), 'NaN')
457
Mark Dickinson59bc20b2008-01-12 01:56:00 +0000458 #leading and trailing whitespace permitted
459 self.assertEqual(str(Decimal('1.3E4 \n')), '1.3E+4')
460 self.assertEqual(str(Decimal(' -7.89')), '-7.89')
461
Mark Dickinson8e85ffa2008-03-25 18:47:59 +0000462 #unicode strings should be permitted
463 self.assertEqual(str(Decimal(u'0E-017')), '0E-17')
464 self.assertEqual(str(Decimal(u'45')), '45')
465 self.assertEqual(str(Decimal(u'-Inf')), '-Infinity')
466 self.assertEqual(str(Decimal(u'NaN123')), 'NaN123')
467
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000468 def test_explicit_from_tuples(self):
469
470 #zero
471 d = Decimal( (0, (0,), 0) )
472 self.assertEqual(str(d), '0')
473
474 #int
475 d = Decimal( (1, (4, 5), 0) )
476 self.assertEqual(str(d), '-45')
477
478 #float
479 d = Decimal( (0, (4, 5, 3, 4), -2) )
480 self.assertEqual(str(d), '45.34')
481
482 #weird
483 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
484 self.assertEqual(str(d), '-4.34913534E-17')
485
486 #wrong number of items
487 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1)) )
488
489 #bad sign
490 self.assertRaises(ValueError, Decimal, (8, (4, 3, 4, 9, 1), 2) )
Facundo Batista9b5e2312007-10-19 19:25:57 +0000491 self.assertRaises(ValueError, Decimal, (0., (4, 3, 4, 9, 1), 2) )
492 self.assertRaises(ValueError, Decimal, (Decimal(1), (4, 3, 4, 9, 1), 2))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000493
494 #bad exp
495 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 'wrong!') )
Facundo Batista9b5e2312007-10-19 19:25:57 +0000496 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 0.) )
497 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), '1') )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000498
499 #bad coefficients
500 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, None, 1), 2) )
501 self.assertRaises(ValueError, Decimal, (1, (4, -3, 4, 9, 1), 2) )
Facundo Batista9b5e2312007-10-19 19:25:57 +0000502 self.assertRaises(ValueError, Decimal, (1, (4, 10, 4, 9, 1), 2) )
Facundo Batista72bc54f2007-11-23 17:59:00 +0000503 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 'a', 1), 2) )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000504
Antoine Pitrou6032c252010-03-30 18:49:45 +0000505 def test_explicit_from_bool(self):
506 self.assertIs(bool(Decimal(0)), False)
507 self.assertIs(bool(Decimal(1)), True)
508 self.assertEqual(Decimal(False), Decimal(0))
509 self.assertEqual(Decimal(True), Decimal(1))
510
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000511 def test_explicit_from_Decimal(self):
512
513 #positive
514 d = Decimal(45)
515 e = Decimal(d)
516 self.assertEqual(str(e), '45')
517 self.assertNotEqual(id(d), id(e))
518
519 #very large positive
520 d = Decimal(500000123)
521 e = Decimal(d)
522 self.assertEqual(str(e), '500000123')
523 self.assertNotEqual(id(d), id(e))
524
525 #negative
526 d = Decimal(-45)
527 e = Decimal(d)
528 self.assertEqual(str(e), '-45')
529 self.assertNotEqual(id(d), id(e))
530
531 #zero
532 d = Decimal(0)
533 e = Decimal(d)
534 self.assertEqual(str(e), '0')
535 self.assertNotEqual(id(d), id(e))
536
Raymond Hettingered171ab2010-04-02 18:39:24 +0000537 @requires_IEEE_754
538 def test_explicit_from_float(self):
539 r = Decimal(0.1)
540 self.assertEqual(type(r), Decimal)
541 self.assertEqual(str(r),
542 '0.1000000000000000055511151231257827021181583404541015625')
543 self.assertTrue(Decimal(float('nan')).is_qnan())
544 self.assertTrue(Decimal(float('inf')).is_infinite())
545 self.assertTrue(Decimal(float('-inf')).is_infinite())
546 self.assertEqual(str(Decimal(float('nan'))),
547 str(Decimal('NaN')))
548 self.assertEqual(str(Decimal(float('inf'))),
549 str(Decimal('Infinity')))
550 self.assertEqual(str(Decimal(float('-inf'))),
551 str(Decimal('-Infinity')))
552 self.assertEqual(str(Decimal(float('-0.0'))),
553 str(Decimal('-0')))
554 for i in range(200):
555 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
556 self.assertEqual(x, float(Decimal(x))) # roundtrip
557
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000558 def test_explicit_context_create_decimal(self):
559
560 nc = copy.copy(getcontext())
561 nc.prec = 3
562
563 # empty
Raymond Hettingerfed52962004-07-14 15:41:57 +0000564 d = Decimal()
565 self.assertEqual(str(d), '0')
566 d = nc.create_decimal()
567 self.assertEqual(str(d), '0')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000568
569 # from None
570 self.assertRaises(TypeError, nc.create_decimal, None)
571
572 # from int
573 d = nc.create_decimal(456)
Ezio Melottib0f5adc2010-01-24 16:58:36 +0000574 self.assertIsInstance(d, Decimal)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000575 self.assertEqual(nc.create_decimal(45678),
576 nc.create_decimal('457E+2'))
577
578 # from string
579 d = Decimal('456789')
580 self.assertEqual(str(d), '456789')
581 d = nc.create_decimal('456789')
582 self.assertEqual(str(d), '4.57E+5')
Mark Dickinson59bc20b2008-01-12 01:56:00 +0000583 # leading and trailing whitespace should result in a NaN;
584 # spaces are already checked in Cowlishaw's test-suite, so
585 # here we just check that a trailing newline results in a NaN
586 self.assertEqual(str(nc.create_decimal('3.14\n')), 'NaN')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000587
588 # from tuples
589 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
590 self.assertEqual(str(d), '-4.34913534E-17')
591 d = nc.create_decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
592 self.assertEqual(str(d), '-4.35E-17')
593
594 # from Decimal
595 prevdec = Decimal(500000123)
596 d = Decimal(prevdec)
597 self.assertEqual(str(d), '500000123')
598 d = nc.create_decimal(prevdec)
599 self.assertEqual(str(d), '5.00E+8')
600
Mark Dickinson4326ad82009-08-02 10:59:36 +0000601 def test_unicode_digits(self):
602 test_values = {
603 u'\uff11': '1',
604 u'\u0660.\u0660\u0663\u0667\u0662e-\u0663' : '0.0000372',
605 u'-nan\u0c68\u0c6a\u0c66\u0c66' : '-NaN2400',
606 }
607 for input, expected in test_values.items():
608 self.assertEqual(str(Decimal(input)), expected)
609
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000610
611class DecimalImplicitConstructionTest(unittest.TestCase):
612 '''Unit tests for Implicit Construction cases of Decimal.'''
613
614 def test_implicit_from_None(self):
615 self.assertRaises(TypeError, eval, 'Decimal(5) + None', globals())
616
617 def test_implicit_from_int(self):
618 #normal
619 self.assertEqual(str(Decimal(5) + 45), '50')
620 #exceeding precision
621 self.assertEqual(Decimal(5) + 123456789000, Decimal(123456789000))
622
623 def test_implicit_from_string(self):
624 self.assertRaises(TypeError, eval, 'Decimal(5) + "3"', globals())
625
626 def test_implicit_from_float(self):
627 self.assertRaises(TypeError, eval, 'Decimal(5) + 2.2', globals())
628
629 def test_implicit_from_Decimal(self):
630 self.assertEqual(Decimal(5) + Decimal(45), Decimal(50))
631
Raymond Hettinger267b8682005-03-27 10:47:39 +0000632 def test_rop(self):
633 # Allow other classes to be trained to interact with Decimals
634 class E:
635 def __divmod__(self, other):
636 return 'divmod ' + str(other)
637 def __rdivmod__(self, other):
638 return str(other) + ' rdivmod'
639 def __lt__(self, other):
640 return 'lt ' + str(other)
641 def __gt__(self, other):
642 return 'gt ' + str(other)
643 def __le__(self, other):
644 return 'le ' + str(other)
645 def __ge__(self, other):
646 return 'ge ' + str(other)
647 def __eq__(self, other):
648 return 'eq ' + str(other)
649 def __ne__(self, other):
650 return 'ne ' + str(other)
651
652 self.assertEqual(divmod(E(), Decimal(10)), 'divmod 10')
653 self.assertEqual(divmod(Decimal(10), E()), '10 rdivmod')
654 self.assertEqual(eval('Decimal(10) < E()'), 'gt 10')
655 self.assertEqual(eval('Decimal(10) > E()'), 'lt 10')
656 self.assertEqual(eval('Decimal(10) <= E()'), 'ge 10')
657 self.assertEqual(eval('Decimal(10) >= E()'), 'le 10')
658 self.assertEqual(eval('Decimal(10) == E()'), 'eq 10')
659 self.assertEqual(eval('Decimal(10) != E()'), 'ne 10')
660
661 # insert operator methods and then exercise them
Georg Brandl96c3f7f2006-03-28 08:06:35 +0000662 oplist = [
663 ('+', '__add__', '__radd__'),
664 ('-', '__sub__', '__rsub__'),
665 ('*', '__mul__', '__rmul__'),
666 ('%', '__mod__', '__rmod__'),
667 ('//', '__floordiv__', '__rfloordiv__'),
668 ('**', '__pow__', '__rpow__')
669 ]
Florent Xicluna8f43cec2010-03-21 10:51:40 +0000670 with check_py3k_warnings():
671 if 1 / 2 == 0:
672 # testing with classic division, so add __div__
673 oplist.append(('/', '__div__', '__rdiv__'))
674 else:
675 # testing with -Qnew, so add __truediv__
676 oplist.append(('/', '__truediv__', '__rtruediv__'))
Anthony Baxter4ef3a232006-03-30 12:59:11 +0000677
Georg Brandl96c3f7f2006-03-28 08:06:35 +0000678 for sym, lop, rop in oplist:
Raymond Hettinger267b8682005-03-27 10:47:39 +0000679 setattr(E, lop, lambda self, other: 'str' + lop + str(other))
680 setattr(E, rop, lambda self, other: str(other) + rop + 'str')
681 self.assertEqual(eval('E()' + sym + 'Decimal(10)'),
682 'str' + lop + '10')
683 self.assertEqual(eval('Decimal(10)' + sym + 'E()'),
684 '10' + rop + 'str')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000685
Mark Dickinson277859d2009-03-17 23:03:46 +0000686
Mark Dickinson1ddf1d82008-02-29 02:16:37 +0000687class DecimalFormatTest(unittest.TestCase):
688 '''Unit tests for the format function.'''
689 def test_formatting(self):
690 # triples giving a format, a Decimal, and the expected result
691 test_values = [
692 ('e', '0E-15', '0e-15'),
693 ('e', '2.3E-15', '2.3e-15'),
694 ('e', '2.30E+2', '2.30e+2'), # preserve significant zeros
695 ('e', '2.30000E-15', '2.30000e-15'),
696 ('e', '1.23456789123456789e40', '1.23456789123456789e+40'),
697 ('e', '1.5', '1.5e+0'),
698 ('e', '0.15', '1.5e-1'),
699 ('e', '0.015', '1.5e-2'),
700 ('e', '0.0000000000015', '1.5e-12'),
701 ('e', '15.0', '1.50e+1'),
702 ('e', '-15', '-1.5e+1'),
703 ('e', '0', '0e+0'),
704 ('e', '0E1', '0e+1'),
705 ('e', '0.0', '0e-1'),
706 ('e', '0.00', '0e-2'),
707 ('.6e', '0E-15', '0.000000e-9'),
708 ('.6e', '0', '0.000000e+6'),
709 ('.6e', '9.999999', '9.999999e+0'),
710 ('.6e', '9.9999999', '1.000000e+1'),
711 ('.6e', '-1.23e5', '-1.230000e+5'),
712 ('.6e', '1.23456789e-3', '1.234568e-3'),
713 ('f', '0', '0'),
714 ('f', '0.0', '0.0'),
715 ('f', '0E-2', '0.00'),
716 ('f', '0.00E-8', '0.0000000000'),
717 ('f', '0E1', '0'), # loses exponent information
718 ('f', '3.2E1', '32'),
719 ('f', '3.2E2', '320'),
720 ('f', '3.20E2', '320'),
721 ('f', '3.200E2', '320.0'),
722 ('f', '3.2E-6', '0.0000032'),
723 ('.6f', '0E-15', '0.000000'), # all zeros treated equally
724 ('.6f', '0E1', '0.000000'),
725 ('.6f', '0', '0.000000'),
726 ('.0f', '0', '0'), # no decimal point
727 ('.0f', '0e-2', '0'),
728 ('.0f', '3.14159265', '3'),
729 ('.1f', '3.14159265', '3.1'),
730 ('.4f', '3.14159265', '3.1416'),
731 ('.6f', '3.14159265', '3.141593'),
732 ('.7f', '3.14159265', '3.1415926'), # round-half-even!
733 ('.8f', '3.14159265', '3.14159265'),
734 ('.9f', '3.14159265', '3.141592650'),
735
736 ('g', '0', '0'),
737 ('g', '0.0', '0.0'),
738 ('g', '0E1', '0e+1'),
739 ('G', '0E1', '0E+1'),
740 ('g', '0E-5', '0.00000'),
741 ('g', '0E-6', '0.000000'),
742 ('g', '0E-7', '0e-7'),
743 ('g', '-0E2', '-0e+2'),
744 ('.0g', '3.14159265', '3'), # 0 sig fig -> 1 sig fig
745 ('.1g', '3.14159265', '3'),
746 ('.2g', '3.14159265', '3.1'),
747 ('.5g', '3.14159265', '3.1416'),
748 ('.7g', '3.14159265', '3.141593'),
749 ('.8g', '3.14159265', '3.1415926'), # round-half-even!
750 ('.9g', '3.14159265', '3.14159265'),
751 ('.10g', '3.14159265', '3.14159265'), # don't pad
752
753 ('%', '0E1', '0%'),
754 ('%', '0E0', '0%'),
755 ('%', '0E-1', '0%'),
756 ('%', '0E-2', '0%'),
757 ('%', '0E-3', '0.0%'),
758 ('%', '0E-4', '0.00%'),
759
760 ('.3%', '0', '0.000%'), # all zeros treated equally
761 ('.3%', '0E10', '0.000%'),
762 ('.3%', '0E-10', '0.000%'),
763 ('.3%', '2.34', '234.000%'),
764 ('.3%', '1.234567', '123.457%'),
765 ('.0%', '1.23', '123%'),
766
767 ('e', 'NaN', 'NaN'),
768 ('f', '-NaN123', '-NaN123'),
769 ('+g', 'NaN456', '+NaN456'),
770 ('.3e', 'Inf', 'Infinity'),
771 ('.16f', '-Inf', '-Infinity'),
772 ('.0g', '-sNaN', '-sNaN'),
773
774 ('', '1.00', '1.00'),
Mark Dickinsonb065e522009-03-17 18:01:03 +0000775
Mark Dickinson277859d2009-03-17 23:03:46 +0000776 # test alignment and padding
Mark Dickinson5cfa8042009-09-08 20:20:19 +0000777 ('6', '123', ' 123'),
Mark Dickinsonb065e522009-03-17 18:01:03 +0000778 ('<6', '123', '123 '),
779 ('>6', '123', ' 123'),
780 ('^6', '123', ' 123 '),
781 ('=+6', '123', '+ 123'),
Mark Dickinson277859d2009-03-17 23:03:46 +0000782 ('#<10', 'NaN', 'NaN#######'),
783 ('#<10', '-4.3', '-4.3######'),
784 ('#<+10', '0.0130', '+0.0130###'),
785 ('#< 10', '0.0130', ' 0.0130###'),
786 ('@>10', '-Inf', '@-Infinity'),
787 ('#>5', '-Inf', '-Infinity'),
788 ('?^5', '123', '?123?'),
789 ('%^6', '123', '%123%%'),
790 (' ^6', '-45.6', '-45.6 '),
791 ('/=10', '-45.6', '-/////45.6'),
792 ('/=+10', '45.6', '+/////45.6'),
793 ('/= 10', '45.6', ' /////45.6'),
794
795 # thousands separator
796 (',', '1234567', '1,234,567'),
797 (',', '123456', '123,456'),
798 (',', '12345', '12,345'),
799 (',', '1234', '1,234'),
800 (',', '123', '123'),
801 (',', '12', '12'),
802 (',', '1', '1'),
803 (',', '0', '0'),
804 (',', '-1234567', '-1,234,567'),
805 (',', '-123456', '-123,456'),
806 ('7,', '123456', '123,456'),
Mark Dickinson5cfa8042009-09-08 20:20:19 +0000807 ('8,', '123456', ' 123,456'),
Mark Dickinson277859d2009-03-17 23:03:46 +0000808 ('08,', '123456', '0,123,456'), # special case: extra 0 needed
809 ('+08,', '123456', '+123,456'), # but not if there's a sign
810 (' 08,', '123456', ' 123,456'),
811 ('08,', '-123456', '-123,456'),
812 ('+09,', '123456', '+0,123,456'),
813 # ... with fractional part...
814 ('07,', '1234.56', '1,234.56'),
815 ('08,', '1234.56', '1,234.56'),
816 ('09,', '1234.56', '01,234.56'),
817 ('010,', '1234.56', '001,234.56'),
818 ('011,', '1234.56', '0,001,234.56'),
819 ('012,', '1234.56', '0,001,234.56'),
820 ('08,.1f', '1234.5', '01,234.5'),
821 # no thousands separators in fraction part
822 (',', '1.23456789', '1.23456789'),
823 (',%', '123.456789', '12,345.6789%'),
824 (',e', '123456', '1.23456e+5'),
825 (',E', '123456', '1.23456E+5'),
Mark Dickinson491ea552009-09-07 16:17:41 +0000826
827 # issue 6850
828 ('a=-7.0', '0.12345', 'aaaa0.1'),
Mark Dickinson1ddf1d82008-02-29 02:16:37 +0000829 ]
830 for fmt, d, result in test_values:
831 self.assertEqual(format(Decimal(d), fmt), result)
832
Mark Dickinson277859d2009-03-17 23:03:46 +0000833 def test_n_format(self):
834 try:
835 from locale import CHAR_MAX
836 except ImportError:
837 return
838
839 # Set up some localeconv-like dictionaries
840 en_US = {
841 'decimal_point' : '.',
842 'grouping' : [3, 3, 0],
843 'thousands_sep': ','
844 }
845
846 fr_FR = {
847 'decimal_point' : ',',
848 'grouping' : [CHAR_MAX],
849 'thousands_sep' : ''
850 }
851
852 ru_RU = {
853 'decimal_point' : ',',
854 'grouping' : [3, 3, 0],
855 'thousands_sep' : ' '
856 }
857
858 crazy = {
859 'decimal_point' : '&',
860 'grouping' : [1, 4, 2, CHAR_MAX],
861 'thousands_sep' : '-'
862 }
863
864
865 def get_fmt(x, locale, fmt='n'):
866 return Decimal.__format__(Decimal(x), fmt, _localeconv=locale)
867
868 self.assertEqual(get_fmt(Decimal('12.7'), en_US), '12.7')
869 self.assertEqual(get_fmt(Decimal('12.7'), fr_FR), '12,7')
870 self.assertEqual(get_fmt(Decimal('12.7'), ru_RU), '12,7')
871 self.assertEqual(get_fmt(Decimal('12.7'), crazy), '1-2&7')
872
873 self.assertEqual(get_fmt(123456789, en_US), '123,456,789')
874 self.assertEqual(get_fmt(123456789, fr_FR), '123456789')
875 self.assertEqual(get_fmt(123456789, ru_RU), '123 456 789')
876 self.assertEqual(get_fmt(1234567890123, crazy), '123456-78-9012-3')
877
878 self.assertEqual(get_fmt(123456789, en_US, '.6n'), '1.23457e+8')
879 self.assertEqual(get_fmt(123456789, fr_FR, '.6n'), '1,23457e+8')
880 self.assertEqual(get_fmt(123456789, ru_RU, '.6n'), '1,23457e+8')
881 self.assertEqual(get_fmt(123456789, crazy, '.6n'), '1&23457e+8')
882
Mark Dickinsonb14514a2009-03-18 08:22:51 +0000883 # zero padding
884 self.assertEqual(get_fmt(1234, fr_FR, '03n'), '1234')
885 self.assertEqual(get_fmt(1234, fr_FR, '04n'), '1234')
886 self.assertEqual(get_fmt(1234, fr_FR, '05n'), '01234')
887 self.assertEqual(get_fmt(1234, fr_FR, '06n'), '001234')
888
889 self.assertEqual(get_fmt(12345, en_US, '05n'), '12,345')
890 self.assertEqual(get_fmt(12345, en_US, '06n'), '12,345')
891 self.assertEqual(get_fmt(12345, en_US, '07n'), '012,345')
892 self.assertEqual(get_fmt(12345, en_US, '08n'), '0,012,345')
893 self.assertEqual(get_fmt(12345, en_US, '09n'), '0,012,345')
894 self.assertEqual(get_fmt(12345, en_US, '010n'), '00,012,345')
895
896 self.assertEqual(get_fmt(123456, crazy, '06n'), '1-2345-6')
897 self.assertEqual(get_fmt(123456, crazy, '07n'), '1-2345-6')
898 self.assertEqual(get_fmt(123456, crazy, '08n'), '1-2345-6')
899 self.assertEqual(get_fmt(123456, crazy, '09n'), '01-2345-6')
900 self.assertEqual(get_fmt(123456, crazy, '010n'), '0-01-2345-6')
901 self.assertEqual(get_fmt(123456, crazy, '011n'), '0-01-2345-6')
902 self.assertEqual(get_fmt(123456, crazy, '012n'), '00-01-2345-6')
903 self.assertEqual(get_fmt(123456, crazy, '013n'), '000-01-2345-6')
904
Mark Dickinson277859d2009-03-17 23:03:46 +0000905
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000906class DecimalArithmeticOperatorsTest(unittest.TestCase):
907 '''Unit tests for all arithmetic operators, binary and unary.'''
908
909 def test_addition(self):
910
911 d1 = Decimal('-11.1')
912 d2 = Decimal('22.2')
913
914 #two Decimals
915 self.assertEqual(d1+d2, Decimal('11.1'))
916 self.assertEqual(d2+d1, Decimal('11.1'))
917
918 #with other type, left
919 c = d1 + 5
920 self.assertEqual(c, Decimal('-6.1'))
921 self.assertEqual(type(c), type(d1))
922
923 #with other type, right
924 c = 5 + d1
925 self.assertEqual(c, Decimal('-6.1'))
926 self.assertEqual(type(c), type(d1))
927
928 #inline with decimal
929 d1 += d2
930 self.assertEqual(d1, Decimal('11.1'))
931
932 #inline with other type
933 d1 += 5
934 self.assertEqual(d1, Decimal('16.1'))
935
936 def test_subtraction(self):
937
938 d1 = Decimal('-11.1')
939 d2 = Decimal('22.2')
940
941 #two Decimals
942 self.assertEqual(d1-d2, Decimal('-33.3'))
943 self.assertEqual(d2-d1, Decimal('33.3'))
944
945 #with other type, left
946 c = d1 - 5
947 self.assertEqual(c, Decimal('-16.1'))
948 self.assertEqual(type(c), type(d1))
949
950 #with other type, right
951 c = 5 - d1
952 self.assertEqual(c, Decimal('16.1'))
953 self.assertEqual(type(c), type(d1))
954
955 #inline with decimal
956 d1 -= d2
957 self.assertEqual(d1, Decimal('-33.3'))
958
959 #inline with other type
960 d1 -= 5
961 self.assertEqual(d1, Decimal('-38.3'))
962
963 def test_multiplication(self):
964
965 d1 = Decimal('-5')
966 d2 = Decimal('3')
967
968 #two Decimals
969 self.assertEqual(d1*d2, Decimal('-15'))
970 self.assertEqual(d2*d1, Decimal('-15'))
971
972 #with other type, left
973 c = d1 * 5
974 self.assertEqual(c, Decimal('-25'))
975 self.assertEqual(type(c), type(d1))
976
977 #with other type, right
978 c = 5 * d1
979 self.assertEqual(c, Decimal('-25'))
980 self.assertEqual(type(c), type(d1))
981
982 #inline with decimal
983 d1 *= d2
984 self.assertEqual(d1, Decimal('-15'))
985
986 #inline with other type
987 d1 *= 5
988 self.assertEqual(d1, Decimal('-75'))
989
990 def test_division(self):
991
992 d1 = Decimal('-5')
993 d2 = Decimal('2')
994
995 #two Decimals
996 self.assertEqual(d1/d2, Decimal('-2.5'))
997 self.assertEqual(d2/d1, Decimal('-0.4'))
998
999 #with other type, left
1000 c = d1 / 4
1001 self.assertEqual(c, Decimal('-1.25'))
1002 self.assertEqual(type(c), type(d1))
1003
1004 #with other type, right
1005 c = 4 / d1
1006 self.assertEqual(c, Decimal('-0.8'))
1007 self.assertEqual(type(c), type(d1))
1008
1009 #inline with decimal
1010 d1 /= d2
1011 self.assertEqual(d1, Decimal('-2.5'))
1012
1013 #inline with other type
1014 d1 /= 4
1015 self.assertEqual(d1, Decimal('-0.625'))
1016
1017 def test_floor_division(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001018
1019 d1 = Decimal('5')
1020 d2 = Decimal('2')
1021
1022 #two Decimals
1023 self.assertEqual(d1//d2, Decimal('2'))
1024 self.assertEqual(d2//d1, Decimal('0'))
1025
1026 #with other type, left
1027 c = d1 // 4
1028 self.assertEqual(c, Decimal('1'))
1029 self.assertEqual(type(c), type(d1))
1030
1031 #with other type, right
1032 c = 7 // d1
1033 self.assertEqual(c, Decimal('1'))
1034 self.assertEqual(type(c), type(d1))
1035
1036 #inline with decimal
1037 d1 //= d2
1038 self.assertEqual(d1, Decimal('2'))
1039
1040 #inline with other type
1041 d1 //= 2
1042 self.assertEqual(d1, Decimal('1'))
1043
1044 def test_powering(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001045
1046 d1 = Decimal('5')
1047 d2 = Decimal('2')
1048
1049 #two Decimals
1050 self.assertEqual(d1**d2, Decimal('25'))
1051 self.assertEqual(d2**d1, Decimal('32'))
1052
1053 #with other type, left
1054 c = d1 ** 4
1055 self.assertEqual(c, Decimal('625'))
1056 self.assertEqual(type(c), type(d1))
1057
1058 #with other type, right
1059 c = 7 ** d1
1060 self.assertEqual(c, Decimal('16807'))
1061 self.assertEqual(type(c), type(d1))
1062
1063 #inline with decimal
1064 d1 **= d2
1065 self.assertEqual(d1, Decimal('25'))
1066
1067 #inline with other type
1068 d1 **= 4
1069 self.assertEqual(d1, Decimal('390625'))
1070
1071 def test_module(self):
1072
1073 d1 = Decimal('5')
1074 d2 = Decimal('2')
1075
1076 #two Decimals
1077 self.assertEqual(d1%d2, Decimal('1'))
1078 self.assertEqual(d2%d1, Decimal('2'))
1079
1080 #with other type, left
1081 c = d1 % 4
1082 self.assertEqual(c, Decimal('1'))
1083 self.assertEqual(type(c), type(d1))
1084
1085 #with other type, right
1086 c = 7 % d1
1087 self.assertEqual(c, Decimal('2'))
1088 self.assertEqual(type(c), type(d1))
1089
1090 #inline with decimal
1091 d1 %= d2
1092 self.assertEqual(d1, Decimal('1'))
1093
1094 #inline with other type
1095 d1 %= 4
1096 self.assertEqual(d1, Decimal('1'))
1097
1098 def test_floor_div_module(self):
1099
1100 d1 = Decimal('5')
1101 d2 = Decimal('2')
1102
1103 #two Decimals
1104 (p, q) = divmod(d1, d2)
1105 self.assertEqual(p, Decimal('2'))
1106 self.assertEqual(q, Decimal('1'))
1107 self.assertEqual(type(p), type(d1))
1108 self.assertEqual(type(q), type(d1))
1109
1110 #with other type, left
1111 (p, q) = divmod(d1, 4)
1112 self.assertEqual(p, Decimal('1'))
1113 self.assertEqual(q, Decimal('1'))
1114 self.assertEqual(type(p), type(d1))
1115 self.assertEqual(type(q), type(d1))
1116
1117 #with other type, right
1118 (p, q) = divmod(7, d1)
1119 self.assertEqual(p, Decimal('1'))
1120 self.assertEqual(q, Decimal('2'))
1121 self.assertEqual(type(p), type(d1))
1122 self.assertEqual(type(q), type(d1))
1123
1124 def test_unary_operators(self):
1125 self.assertEqual(+Decimal(45), Decimal(+45)) # +
1126 self.assertEqual(-Decimal(45), Decimal(-45)) # -
1127 self.assertEqual(abs(Decimal(45)), abs(Decimal(-45))) # abs
1128
Mark Dickinson2fc92632008-02-06 22:10:50 +00001129 def test_nan_comparisons(self):
Mark Dickinsone096e822010-04-02 10:17:07 +00001130 # comparisons involving signaling nans signal InvalidOperation
1131
1132 # order comparisons (<, <=, >, >=) involving only quiet nans
1133 # also signal InvalidOperation
1134
1135 # equality comparisons (==, !=) involving only quiet nans
1136 # don't signal, but return False or True respectively.
1137
Mark Dickinson2fc92632008-02-06 22:10:50 +00001138 n = Decimal('NaN')
1139 s = Decimal('sNaN')
1140 i = Decimal('Inf')
1141 f = Decimal('2')
Mark Dickinsone096e822010-04-02 10:17:07 +00001142
1143 qnan_pairs = (n, n), (n, i), (i, n), (n, f), (f, n)
1144 snan_pairs = (s, n), (n, s), (s, i), (i, s), (s, f), (f, s), (s, s)
1145 order_ops = operator.lt, operator.le, operator.gt, operator.ge
1146 equality_ops = operator.eq, operator.ne
1147
1148 # results when InvalidOperation is not trapped
1149 for x, y in qnan_pairs + snan_pairs:
1150 for op in order_ops + equality_ops:
1151 got = op(x, y)
1152 expected = True if op is operator.ne else False
1153 self.assertIs(expected, got,
1154 "expected {0!r} for operator.{1}({2!r}, {3!r}); "
1155 "got {4!r}".format(
1156 expected, op.__name__, x, y, got))
1157
1158 # repeat the above, but this time trap the InvalidOperation
1159 with localcontext() as ctx:
1160 ctx.traps[InvalidOperation] = 1
1161
1162 for x, y in qnan_pairs:
1163 for op in equality_ops:
1164 got = op(x, y)
1165 expected = True if op is operator.ne else False
1166 self.assertIs(expected, got,
1167 "expected {0!r} for "
1168 "operator.{1}({2!r}, {3!r}); "
1169 "got {4!r}".format(
1170 expected, op.__name__, x, y, got))
1171
1172 for x, y in snan_pairs:
1173 for op in equality_ops:
1174 self.assertRaises(InvalidOperation, operator.eq, x, y)
1175 self.assertRaises(InvalidOperation, operator.ne, x, y)
1176
1177 for x, y in qnan_pairs + snan_pairs:
1178 for op in order_ops:
1179 self.assertRaises(InvalidOperation, op, x, y)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001180
Mark Dickinson6d8effb2010-02-18 14:27:02 +00001181 def test_copy_sign(self):
1182 d = Decimal(1).copy_sign(Decimal(-2))
1183
1184 self.assertEqual(Decimal(1).copy_sign(-2), d)
1185 self.assertRaises(TypeError, Decimal(1).copy_sign, '-2')
1186
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001187# The following are two functions used to test threading in the next class
1188
1189def thfunc1(cls):
1190 d1 = Decimal(1)
1191 d3 = Decimal(3)
Facundo Batista64156672008-03-22 02:45:37 +00001192 test1 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001193 cls.synchro.wait()
Facundo Batista64156672008-03-22 02:45:37 +00001194 test2 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001195 cls.finish1.set()
Facundo Batista64156672008-03-22 02:45:37 +00001196
Facundo Batistaee340e52008-05-02 17:39:00 +00001197 cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
1198 cls.assertEqual(test2, Decimal('0.3333333333333333333333333333'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001199 return
1200
1201def thfunc2(cls):
1202 d1 = Decimal(1)
1203 d3 = Decimal(3)
Facundo Batista64156672008-03-22 02:45:37 +00001204 test1 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001205 thiscontext = getcontext()
1206 thiscontext.prec = 18
Facundo Batista64156672008-03-22 02:45:37 +00001207 test2 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001208 cls.synchro.set()
1209 cls.finish2.set()
Facundo Batista64156672008-03-22 02:45:37 +00001210
Facundo Batistaee340e52008-05-02 17:39:00 +00001211 cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
Facundo Batista64156672008-03-22 02:45:37 +00001212 cls.assertEqual(test2, Decimal('0.333333333333333333'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001213 return
1214
1215
1216class DecimalUseOfContextTest(unittest.TestCase):
1217 '''Unit tests for Use of Context cases in Decimal.'''
1218
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001219 try:
1220 import threading
1221 except ImportError:
1222 threading = None
1223
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001224 # Take care executing this test from IDLE, there's an issue in threading
1225 # that hangs IDLE and I couldn't find it
1226
1227 def test_threading(self):
1228 #Test the "threading isolation" of a Context.
1229
1230 self.synchro = threading.Event()
1231 self.finish1 = threading.Event()
1232 self.finish2 = threading.Event()
1233
1234 th1 = threading.Thread(target=thfunc1, args=(self,))
1235 th2 = threading.Thread(target=thfunc2, args=(self,))
1236
1237 th1.start()
1238 th2.start()
1239
1240 self.finish1.wait()
Thomas Woutersb3e6e8c2007-09-19 17:27:29 +00001241 self.finish2.wait()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001242 return
1243
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001244 if threading is None:
1245 del test_threading
1246
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001247
1248class DecimalUsabilityTest(unittest.TestCase):
1249 '''Unit tests for Usability cases of Decimal.'''
1250
1251 def test_comparison_operators(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001252
1253 da = Decimal('23.42')
1254 db = Decimal('23.42')
1255 dc = Decimal('45')
1256
1257 #two Decimals
Ezio Melotti856a3be2010-04-03 14:51:00 +00001258 self.assertGreater(dc, da)
1259 self.assertGreaterEqual(dc, da)
1260 self.assertLess(da, dc)
1261 self.assertLessEqual(da, dc)
1262 self.assertEqual(da, db)
1263 self.assertNotEqual(da, dc)
1264 self.assertLessEqual(da, db)
1265 self.assertGreaterEqual(da, db)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001266 self.assertEqual(cmp(dc,da), 1)
1267 self.assertEqual(cmp(da,dc), -1)
1268 self.assertEqual(cmp(da,db), 0)
1269
1270 #a Decimal and an int
Ezio Melotti856a3be2010-04-03 14:51:00 +00001271 self.assertGreater(dc, 23)
1272 self.assertLess(23, dc)
1273 self.assertEqual(dc, 45)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001274 self.assertEqual(cmp(dc,23), 1)
1275 self.assertEqual(cmp(23,dc), -1)
1276 self.assertEqual(cmp(dc,45), 0)
1277
1278 #a Decimal and uncomparable
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001279 self.assertNotEqual(da, 'ugly')
1280 self.assertNotEqual(da, 32.7)
1281 self.assertNotEqual(da, object())
1282 self.assertNotEqual(da, object)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001283
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001284 # sortable
1285 a = map(Decimal, xrange(100))
1286 b = a[:]
1287 random.shuffle(a)
1288 a.sort()
1289 self.assertEqual(a, b)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001290
Facundo Batista353750c2007-09-13 18:13:15 +00001291 # with None
Florent Xicluna8f43cec2010-03-21 10:51:40 +00001292 with check_py3k_warnings():
1293 self.assertFalse(Decimal(1) < None)
1294 self.assertTrue(Decimal(1) > None)
Facundo Batista353750c2007-09-13 18:13:15 +00001295
Mark Dickinson99d80962010-04-02 08:53:22 +00001296 def test_decimal_float_comparison(self):
1297 da = Decimal('0.25')
1298 db = Decimal('3.0')
Ezio Melotti856a3be2010-04-03 14:51:00 +00001299 self.assertLess(da, 3.0)
1300 self.assertLessEqual(da, 3.0)
1301 self.assertGreater(db, 0.25)
1302 self.assertGreaterEqual(db, 0.25)
1303 self.assertNotEqual(da, 1.5)
1304 self.assertEqual(da, 0.25)
1305 self.assertGreater(3.0, da)
1306 self.assertGreaterEqual(3.0, da)
1307 self.assertLess(0.25, db)
1308 self.assertLessEqual(0.25, db)
1309 self.assertNotEqual(0.25, db)
1310 self.assertEqual(3.0, db)
1311 self.assertNotEqual(0.1, Decimal('0.1'))
Mark Dickinson99d80962010-04-02 08:53:22 +00001312
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001313 def test_copy_and_deepcopy_methods(self):
1314 d = Decimal('43.24')
1315 c = copy.copy(d)
1316 self.assertEqual(id(c), id(d))
1317 dc = copy.deepcopy(d)
1318 self.assertEqual(id(dc), id(d))
1319
1320 def test_hash_method(self):
1321 #just that it's hashable
1322 hash(Decimal(23))
Mark Dickinsonf3eeca12010-04-02 10:35:12 +00001323 hash(Decimal('Infinity'))
1324 hash(Decimal('-Infinity'))
1325 hash(Decimal('nan123'))
1326 hash(Decimal('-NaN'))
Facundo Batista8c202442007-09-19 17:53:25 +00001327
1328 test_values = [Decimal(sign*(2**m + n))
1329 for m in [0, 14, 15, 16, 17, 30, 31,
1330 32, 33, 62, 63, 64, 65, 66]
1331 for n in range(-10, 10)
1332 for sign in [-1, 1]]
1333 test_values.extend([
1334 Decimal("-0"), # zeros
1335 Decimal("0.00"),
1336 Decimal("-0.000"),
1337 Decimal("0E10"),
1338 Decimal("-0E12"),
1339 Decimal("10.0"), # negative exponent
1340 Decimal("-23.00000"),
1341 Decimal("1230E100"), # positive exponent
1342 Decimal("-4.5678E50"),
1343 # a value for which hash(n) != hash(n % (2**64-1))
1344 # in Python pre-2.6
1345 Decimal(2**64 + 2**32 - 1),
1346 # selection of values which fail with the old (before
1347 # version 2.6) long.__hash__
1348 Decimal("1.634E100"),
1349 Decimal("90.697E100"),
1350 Decimal("188.83E100"),
1351 Decimal("1652.9E100"),
1352 Decimal("56531E100"),
1353 ])
1354
1355 # check that hash(d) == hash(int(d)) for integral values
1356 for value in test_values:
1357 self.assertEqual(hash(value), hash(int(value)))
1358
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001359 #the same hash that to an int
1360 self.assertEqual(hash(Decimal(23)), hash(23))
Mark Dickinsonf3eeca12010-04-02 10:35:12 +00001361 self.assertRaises(TypeError, hash, Decimal('sNaN'))
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001362 self.assertTrue(hash(Decimal('Inf')))
1363 self.assertTrue(hash(Decimal('-Inf')))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001364
Mark Dickinson99d80962010-04-02 08:53:22 +00001365 # check that the hashes of a Decimal float match when they
1366 # represent exactly the same values
1367 test_strings = ['inf', '-Inf', '0.0', '-.0e1',
1368 '34.0', '2.5', '112390.625', '-0.515625']
1369 for s in test_strings:
1370 f = float(s)
1371 d = Decimal(s)
1372 self.assertEqual(hash(f), hash(d))
1373
Facundo Batista52b25792008-01-08 12:25:20 +00001374 # check that the value of the hash doesn't depend on the
1375 # current context (issue #1757)
1376 c = getcontext()
1377 old_precision = c.prec
1378 x = Decimal("123456789.1")
1379
1380 c.prec = 6
1381 h1 = hash(x)
1382 c.prec = 10
1383 h2 = hash(x)
1384 c.prec = 16
1385 h3 = hash(x)
1386
1387 self.assertEqual(h1, h2)
1388 self.assertEqual(h1, h3)
1389 c.prec = old_precision
1390
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001391 def test_min_and_max_methods(self):
1392
1393 d1 = Decimal('15.32')
1394 d2 = Decimal('28.5')
1395 l1 = 15
1396 l2 = 28
1397
1398 #between Decimals
Ezio Melotti856a3be2010-04-03 14:51:00 +00001399 self.assertIs(min(d1,d2), d1)
1400 self.assertIs(min(d2,d1), d1)
1401 self.assertIs(max(d1,d2), d2)
1402 self.assertIs(max(d2,d1), d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001403
1404 #between Decimal and long
Ezio Melotti856a3be2010-04-03 14:51:00 +00001405 self.assertIs(min(d1,l2), d1)
1406 self.assertIs(min(l2,d1), d1)
1407 self.assertIs(max(l1,d2), d2)
1408 self.assertIs(max(d2,l1), d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001409
1410 def test_as_nonzero(self):
1411 #as false
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001412 self.assertFalse(Decimal(0))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001413 #as true
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001414 self.assertTrue(Decimal('0.372'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001415
1416 def test_tostring_methods(self):
1417 #Test str and repr methods.
1418
1419 d = Decimal('15.32')
1420 self.assertEqual(str(d), '15.32') # str
Raymond Hettingerabe32372008-02-14 02:41:22 +00001421 self.assertEqual(repr(d), "Decimal('15.32')") # repr
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001422
Mark Dickinson8e85ffa2008-03-25 18:47:59 +00001423 # result type of string methods should be str, not unicode
1424 unicode_inputs = [u'123.4', u'0.5E2', u'Infinity', u'sNaN',
1425 u'-0.0E100', u'-NaN001', u'-Inf']
1426
1427 for u in unicode_inputs:
1428 d = Decimal(u)
1429 self.assertEqual(type(str(d)), str)
1430 self.assertEqual(type(repr(d)), str)
1431 self.assertEqual(type(d.to_eng_string()), str)
1432
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001433 def test_tonum_methods(self):
1434 #Test float, int and long methods.
1435
1436 d1 = Decimal('66')
1437 d2 = Decimal('15.32')
1438
1439 #int
1440 self.assertEqual(int(d1), 66)
1441 self.assertEqual(int(d2), 15)
1442
1443 #long
1444 self.assertEqual(long(d1), 66)
1445 self.assertEqual(long(d2), 15)
1446
1447 #float
1448 self.assertEqual(float(d1), 66)
1449 self.assertEqual(float(d2), 15.32)
1450
1451 def test_eval_round_trip(self):
1452
1453 #with zero
1454 d = Decimal( (0, (0,), 0) )
1455 self.assertEqual(d, eval(repr(d)))
1456
1457 #int
1458 d = Decimal( (1, (4, 5), 0) )
1459 self.assertEqual(d, eval(repr(d)))
1460
1461 #float
1462 d = Decimal( (0, (4, 5, 3, 4), -2) )
1463 self.assertEqual(d, eval(repr(d)))
1464
1465 #weird
1466 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1467 self.assertEqual(d, eval(repr(d)))
1468
1469 def test_as_tuple(self):
1470
1471 #with zero
1472 d = Decimal(0)
1473 self.assertEqual(d.as_tuple(), (0, (0,), 0) )
1474
1475 #int
1476 d = Decimal(-45)
1477 self.assertEqual(d.as_tuple(), (1, (4, 5), 0) )
1478
1479 #complicated string
1480 d = Decimal("-4.34913534E-17")
1481 self.assertEqual(d.as_tuple(), (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1482
1483 #inf
1484 d = Decimal("Infinity")
1485 self.assertEqual(d.as_tuple(), (0, (0,), 'F') )
1486
Facundo Batista9b5e2312007-10-19 19:25:57 +00001487 #leading zeros in coefficient should be stripped
1488 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), -2) )
1489 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), -2) )
1490 d = Decimal( (1, (0, 0, 0), 37) )
1491 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1492 d = Decimal( (1, (), 37) )
1493 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1494
1495 #leading zeros in NaN diagnostic info should be stripped
1496 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), 'n') )
1497 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), 'n') )
1498 d = Decimal( (1, (0, 0, 0), 'N') )
1499 self.assertEqual(d.as_tuple(), (1, (), 'N') )
1500 d = Decimal( (1, (), 'n') )
1501 self.assertEqual(d.as_tuple(), (1, (), 'n') )
1502
1503 #coefficient in infinity should be ignored
1504 d = Decimal( (0, (4, 5, 3, 4), 'F') )
1505 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
1506 d = Decimal( (1, (0, 2, 7, 1), 'F') )
1507 self.assertEqual(d.as_tuple(), (1, (0,), 'F'))
1508
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001509 def test_immutability_operations(self):
1510 # Do operations and check that it didn't change change internal objects.
1511
1512 d1 = Decimal('-25e55')
1513 b1 = Decimal('-25e55')
Facundo Batista353750c2007-09-13 18:13:15 +00001514 d2 = Decimal('33e+33')
1515 b2 = Decimal('33e+33')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001516
1517 def checkSameDec(operation, useOther=False):
1518 if useOther:
1519 eval("d1." + operation + "(d2)")
1520 self.assertEqual(d1._sign, b1._sign)
1521 self.assertEqual(d1._int, b1._int)
1522 self.assertEqual(d1._exp, b1._exp)
1523 self.assertEqual(d2._sign, b2._sign)
1524 self.assertEqual(d2._int, b2._int)
1525 self.assertEqual(d2._exp, b2._exp)
1526 else:
1527 eval("d1." + operation + "()")
1528 self.assertEqual(d1._sign, b1._sign)
1529 self.assertEqual(d1._int, b1._int)
1530 self.assertEqual(d1._exp, b1._exp)
1531 return
1532
1533 Decimal(d1)
1534 self.assertEqual(d1._sign, b1._sign)
1535 self.assertEqual(d1._int, b1._int)
1536 self.assertEqual(d1._exp, b1._exp)
1537
1538 checkSameDec("__abs__")
1539 checkSameDec("__add__", True)
1540 checkSameDec("__div__", True)
1541 checkSameDec("__divmod__", True)
Mark Dickinson2fc92632008-02-06 22:10:50 +00001542 checkSameDec("__eq__", True)
1543 checkSameDec("__ne__", True)
1544 checkSameDec("__le__", True)
1545 checkSameDec("__lt__", True)
1546 checkSameDec("__ge__", True)
1547 checkSameDec("__gt__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001548 checkSameDec("__float__")
1549 checkSameDec("__floordiv__", True)
1550 checkSameDec("__hash__")
1551 checkSameDec("__int__")
Raymond Hettinger5a053642008-01-24 19:05:29 +00001552 checkSameDec("__trunc__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001553 checkSameDec("__long__")
1554 checkSameDec("__mod__", True)
1555 checkSameDec("__mul__", True)
1556 checkSameDec("__neg__")
1557 checkSameDec("__nonzero__")
1558 checkSameDec("__pos__")
1559 checkSameDec("__pow__", True)
1560 checkSameDec("__radd__", True)
1561 checkSameDec("__rdiv__", True)
1562 checkSameDec("__rdivmod__", True)
1563 checkSameDec("__repr__")
1564 checkSameDec("__rfloordiv__", True)
1565 checkSameDec("__rmod__", True)
1566 checkSameDec("__rmul__", True)
1567 checkSameDec("__rpow__", True)
1568 checkSameDec("__rsub__", True)
1569 checkSameDec("__str__")
1570 checkSameDec("__sub__", True)
1571 checkSameDec("__truediv__", True)
1572 checkSameDec("adjusted")
1573 checkSameDec("as_tuple")
1574 checkSameDec("compare", True)
1575 checkSameDec("max", True)
1576 checkSameDec("min", True)
1577 checkSameDec("normalize")
1578 checkSameDec("quantize", True)
1579 checkSameDec("remainder_near", True)
1580 checkSameDec("same_quantum", True)
1581 checkSameDec("sqrt")
1582 checkSameDec("to_eng_string")
1583 checkSameDec("to_integral")
1584
Facundo Batista6c398da2007-09-17 17:30:13 +00001585 def test_subclassing(self):
1586 # Different behaviours when subclassing Decimal
1587
1588 class MyDecimal(Decimal):
1589 pass
1590
1591 d1 = MyDecimal(1)
1592 d2 = MyDecimal(2)
1593 d = d1 + d2
Ezio Melotti856a3be2010-04-03 14:51:00 +00001594 self.assertIs(type(d), Decimal)
Facundo Batista6c398da2007-09-17 17:30:13 +00001595
1596 d = d1.max(d2)
Ezio Melotti856a3be2010-04-03 14:51:00 +00001597 self.assertIs(type(d), Decimal)
Facundo Batista6c398da2007-09-17 17:30:13 +00001598
Mark Dickinson3b24ccb2008-03-25 14:33:23 +00001599 def test_implicit_context(self):
1600 # Check results when context given implicitly. (Issue 2478)
1601 c = getcontext()
1602 self.assertEqual(str(Decimal(0).sqrt()),
1603 str(c.sqrt(Decimal(0))))
1604
Mark Dickinson0c673122009-10-29 12:04:00 +00001605 def test_conversions_from_int(self):
1606 # Check that methods taking a second Decimal argument will
1607 # always accept an integer in place of a Decimal.
1608 self.assertEqual(Decimal(4).compare(3),
1609 Decimal(4).compare(Decimal(3)))
1610 self.assertEqual(Decimal(4).compare_signal(3),
1611 Decimal(4).compare_signal(Decimal(3)))
1612 self.assertEqual(Decimal(4).compare_total(3),
1613 Decimal(4).compare_total(Decimal(3)))
1614 self.assertEqual(Decimal(4).compare_total_mag(3),
1615 Decimal(4).compare_total_mag(Decimal(3)))
1616 self.assertEqual(Decimal(10101).logical_and(1001),
1617 Decimal(10101).logical_and(Decimal(1001)))
1618 self.assertEqual(Decimal(10101).logical_or(1001),
1619 Decimal(10101).logical_or(Decimal(1001)))
1620 self.assertEqual(Decimal(10101).logical_xor(1001),
1621 Decimal(10101).logical_xor(Decimal(1001)))
1622 self.assertEqual(Decimal(567).max(123),
1623 Decimal(567).max(Decimal(123)))
1624 self.assertEqual(Decimal(567).max_mag(123),
1625 Decimal(567).max_mag(Decimal(123)))
1626 self.assertEqual(Decimal(567).min(123),
1627 Decimal(567).min(Decimal(123)))
1628 self.assertEqual(Decimal(567).min_mag(123),
1629 Decimal(567).min_mag(Decimal(123)))
1630 self.assertEqual(Decimal(567).next_toward(123),
1631 Decimal(567).next_toward(Decimal(123)))
1632 self.assertEqual(Decimal(1234).quantize(100),
1633 Decimal(1234).quantize(Decimal(100)))
1634 self.assertEqual(Decimal(768).remainder_near(1234),
1635 Decimal(768).remainder_near(Decimal(1234)))
1636 self.assertEqual(Decimal(123).rotate(1),
1637 Decimal(123).rotate(Decimal(1)))
1638 self.assertEqual(Decimal(1234).same_quantum(1000),
1639 Decimal(1234).same_quantum(Decimal(1000)))
1640 self.assertEqual(Decimal('9.123').scaleb(-100),
1641 Decimal('9.123').scaleb(Decimal(-100)))
1642 self.assertEqual(Decimal(456).shift(-1),
1643 Decimal(456).shift(Decimal(-1)))
1644
1645 self.assertEqual(Decimal(-12).fma(Decimal(45), 67),
1646 Decimal(-12).fma(Decimal(45), Decimal(67)))
1647 self.assertEqual(Decimal(-12).fma(45, 67),
1648 Decimal(-12).fma(Decimal(45), Decimal(67)))
1649 self.assertEqual(Decimal(-12).fma(45, Decimal(67)),
1650 Decimal(-12).fma(Decimal(45), Decimal(67)))
1651
Facundo Batista6c398da2007-09-17 17:30:13 +00001652
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001653class DecimalPythonAPItests(unittest.TestCase):
1654
Raymond Hettinger2c8585b2009-02-03 03:37:03 +00001655 def test_abc(self):
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001656 self.assertTrue(issubclass(Decimal, numbers.Number))
Ezio Melotti856a3be2010-04-03 14:51:00 +00001657 self.assertFalse(issubclass(Decimal, numbers.Real))
Ezio Melottib0f5adc2010-01-24 16:58:36 +00001658 self.assertIsInstance(Decimal(0), numbers.Number)
Ezio Melotti856a3be2010-04-03 14:51:00 +00001659 self.assertNotIsInstance(Decimal(0), numbers.Real)
Raymond Hettinger2c8585b2009-02-03 03:37:03 +00001660
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001661 def test_pickle(self):
1662 d = Decimal('-3.141590000')
1663 p = pickle.dumps(d)
1664 e = pickle.loads(p)
1665 self.assertEqual(d, e)
1666
Raymond Hettinger5548be22004-07-05 18:49:38 +00001667 def test_int(self):
Raymond Hettinger605ed022004-11-24 07:28:48 +00001668 for x in range(-250, 250):
1669 s = '%0.2f' % (x / 100.0)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001670 # should work the same as for floats
1671 self.assertEqual(int(Decimal(s)), int(float(s)))
Raymond Hettinger605ed022004-11-24 07:28:48 +00001672 # should work the same as to_integral in the ROUND_DOWN mode
Raymond Hettinger5548be22004-07-05 18:49:38 +00001673 d = Decimal(s)
Raymond Hettinger605ed022004-11-24 07:28:48 +00001674 r = d.to_integral(ROUND_DOWN)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001675 self.assertEqual(Decimal(int(d)), r)
1676
Mark Dickinson968f1692009-09-07 18:04:58 +00001677 self.assertRaises(ValueError, int, Decimal('-nan'))
1678 self.assertRaises(ValueError, int, Decimal('snan'))
1679 self.assertRaises(OverflowError, int, Decimal('inf'))
1680 self.assertRaises(OverflowError, int, Decimal('-inf'))
1681
1682 self.assertRaises(ValueError, long, Decimal('-nan'))
1683 self.assertRaises(ValueError, long, Decimal('snan'))
1684 self.assertRaises(OverflowError, long, Decimal('inf'))
1685 self.assertRaises(OverflowError, long, Decimal('-inf'))
1686
Raymond Hettinger5a053642008-01-24 19:05:29 +00001687 def test_trunc(self):
1688 for x in range(-250, 250):
1689 s = '%0.2f' % (x / 100.0)
1690 # should work the same as for floats
1691 self.assertEqual(int(Decimal(s)), int(float(s)))
1692 # should work the same as to_integral in the ROUND_DOWN mode
1693 d = Decimal(s)
1694 r = d.to_integral(ROUND_DOWN)
Jeffrey Yasskinca2b69f2008-02-01 06:22:46 +00001695 self.assertEqual(Decimal(math.trunc(d)), r)
Raymond Hettinger5a053642008-01-24 19:05:29 +00001696
Raymond Hettingerf4d85972009-01-03 19:02:23 +00001697 def test_from_float(self):
1698
1699 class MyDecimal(Decimal):
1700 pass
1701
1702 r = MyDecimal.from_float(0.1)
1703 self.assertEqual(type(r), MyDecimal)
1704 self.assertEqual(str(r),
1705 '0.1000000000000000055511151231257827021181583404541015625')
1706 bigint = 12345678901234567890123456789
1707 self.assertEqual(MyDecimal.from_float(bigint), MyDecimal(bigint))
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001708 self.assertTrue(MyDecimal.from_float(float('nan')).is_qnan())
1709 self.assertTrue(MyDecimal.from_float(float('inf')).is_infinite())
1710 self.assertTrue(MyDecimal.from_float(float('-inf')).is_infinite())
Raymond Hettingerf4d85972009-01-03 19:02:23 +00001711 self.assertEqual(str(MyDecimal.from_float(float('nan'))),
1712 str(Decimal('NaN')))
1713 self.assertEqual(str(MyDecimal.from_float(float('inf'))),
1714 str(Decimal('Infinity')))
1715 self.assertEqual(str(MyDecimal.from_float(float('-inf'))),
1716 str(Decimal('-Infinity')))
1717 self.assertRaises(TypeError, MyDecimal.from_float, 'abc')
1718 for i in range(200):
1719 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
1720 self.assertEqual(x, float(MyDecimal.from_float(x))) # roundtrip
1721
1722 def test_create_decimal_from_float(self):
1723 context = Context(prec=5, rounding=ROUND_DOWN)
1724 self.assertEqual(
1725 context.create_decimal_from_float(math.pi),
1726 Decimal('3.1415')
1727 )
1728 context = Context(prec=5, rounding=ROUND_UP)
1729 self.assertEqual(
1730 context.create_decimal_from_float(math.pi),
1731 Decimal('3.1416')
1732 )
1733 context = Context(prec=5, traps=[Inexact])
1734 self.assertRaises(
1735 Inexact,
1736 context.create_decimal_from_float,
1737 math.pi
1738 )
1739 self.assertEqual(repr(context.create_decimal_from_float(-0.0)),
1740 "Decimal('-0')")
1741 self.assertEqual(repr(context.create_decimal_from_float(1.0)),
1742 "Decimal('1')")
1743 self.assertEqual(repr(context.create_decimal_from_float(10)),
1744 "Decimal('10')")
1745
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00001746class ContextAPItests(unittest.TestCase):
1747
1748 def test_pickle(self):
1749 c = Context()
1750 e = pickle.loads(pickle.dumps(c))
1751 for k in vars(c):
1752 v1 = vars(c)[k]
1753 v2 = vars(e)[k]
1754 self.assertEqual(v1, v2)
1755
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001756 def test_equality_with_other_types(self):
Ezio Melottiaa980582010-01-23 23:04:36 +00001757 self.assertIn(Decimal(10), ['a', 1.0, Decimal(10), (1,2), {}])
1758 self.assertNotIn(Decimal(10), ['a', 1.0, (1,2), {}])
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001759
Raymond Hettinger955d2b22004-08-08 20:17:45 +00001760 def test_copy(self):
1761 # All copies should be deep
1762 c = Context()
1763 d = c.copy()
1764 self.assertNotEqual(id(c), id(d))
1765 self.assertNotEqual(id(c.flags), id(d.flags))
1766 self.assertNotEqual(id(c.traps), id(d.traps))
1767
Mark Dickinson6d8effb2010-02-18 14:27:02 +00001768 def test_abs(self):
1769 c = Context()
1770 d = c.abs(Decimal(-1))
1771 self.assertEqual(c.abs(-1), d)
1772 self.assertRaises(TypeError, c.abs, '-1')
1773
1774 def test_add(self):
1775 c = Context()
1776 d = c.add(Decimal(1), Decimal(1))
1777 self.assertEqual(c.add(1, 1), d)
1778 self.assertEqual(c.add(Decimal(1), 1), d)
1779 self.assertEqual(c.add(1, Decimal(1)), d)
1780 self.assertRaises(TypeError, c.add, '1', 1)
1781 self.assertRaises(TypeError, c.add, 1, '1')
1782
1783 def test_compare(self):
1784 c = Context()
1785 d = c.compare(Decimal(1), Decimal(1))
1786 self.assertEqual(c.compare(1, 1), d)
1787 self.assertEqual(c.compare(Decimal(1), 1), d)
1788 self.assertEqual(c.compare(1, Decimal(1)), d)
1789 self.assertRaises(TypeError, c.compare, '1', 1)
1790 self.assertRaises(TypeError, c.compare, 1, '1')
1791
1792 def test_compare_signal(self):
1793 c = Context()
1794 d = c.compare_signal(Decimal(1), Decimal(1))
1795 self.assertEqual(c.compare_signal(1, 1), d)
1796 self.assertEqual(c.compare_signal(Decimal(1), 1), d)
1797 self.assertEqual(c.compare_signal(1, Decimal(1)), d)
1798 self.assertRaises(TypeError, c.compare_signal, '1', 1)
1799 self.assertRaises(TypeError, c.compare_signal, 1, '1')
1800
1801 def test_compare_total(self):
1802 c = Context()
1803 d = c.compare_total(Decimal(1), Decimal(1))
1804 self.assertEqual(c.compare_total(1, 1), d)
1805 self.assertEqual(c.compare_total(Decimal(1), 1), d)
1806 self.assertEqual(c.compare_total(1, Decimal(1)), d)
1807 self.assertRaises(TypeError, c.compare_total, '1', 1)
1808 self.assertRaises(TypeError, c.compare_total, 1, '1')
1809
1810 def test_compare_total_mag(self):
1811 c = Context()
1812 d = c.compare_total_mag(Decimal(1), Decimal(1))
1813 self.assertEqual(c.compare_total_mag(1, 1), d)
1814 self.assertEqual(c.compare_total_mag(Decimal(1), 1), d)
1815 self.assertEqual(c.compare_total_mag(1, Decimal(1)), d)
1816 self.assertRaises(TypeError, c.compare_total_mag, '1', 1)
1817 self.assertRaises(TypeError, c.compare_total_mag, 1, '1')
1818
1819 def test_copy_abs(self):
1820 c = Context()
1821 d = c.copy_abs(Decimal(-1))
1822 self.assertEqual(c.copy_abs(-1), d)
1823 self.assertRaises(TypeError, c.copy_abs, '-1')
1824
1825 def test_copy_decimal(self):
1826 c = Context()
1827 d = c.copy_decimal(Decimal(-1))
1828 self.assertEqual(c.copy_decimal(-1), d)
1829 self.assertRaises(TypeError, c.copy_decimal, '-1')
1830
1831 def test_copy_negate(self):
1832 c = Context()
1833 d = c.copy_negate(Decimal(-1))
1834 self.assertEqual(c.copy_negate(-1), d)
1835 self.assertRaises(TypeError, c.copy_negate, '-1')
1836
1837 def test_copy_sign(self):
1838 c = Context()
1839 d = c.copy_sign(Decimal(1), Decimal(-2))
1840 self.assertEqual(c.copy_sign(1, -2), d)
1841 self.assertEqual(c.copy_sign(Decimal(1), -2), d)
1842 self.assertEqual(c.copy_sign(1, Decimal(-2)), d)
1843 self.assertRaises(TypeError, c.copy_sign, '1', -2)
1844 self.assertRaises(TypeError, c.copy_sign, 1, '-2')
1845
1846 def test_divide(self):
1847 c = Context()
1848 d = c.divide(Decimal(1), Decimal(2))
1849 self.assertEqual(c.divide(1, 2), d)
1850 self.assertEqual(c.divide(Decimal(1), 2), d)
1851 self.assertEqual(c.divide(1, Decimal(2)), d)
1852 self.assertRaises(TypeError, c.divide, '1', 2)
1853 self.assertRaises(TypeError, c.divide, 1, '2')
1854
1855 def test_divide_int(self):
1856 c = Context()
1857 d = c.divide_int(Decimal(1), Decimal(2))
1858 self.assertEqual(c.divide_int(1, 2), d)
1859 self.assertEqual(c.divide_int(Decimal(1), 2), d)
1860 self.assertEqual(c.divide_int(1, Decimal(2)), d)
1861 self.assertRaises(TypeError, c.divide_int, '1', 2)
1862 self.assertRaises(TypeError, c.divide_int, 1, '2')
1863
1864 def test_divmod(self):
1865 c = Context()
1866 d = c.divmod(Decimal(1), Decimal(2))
1867 self.assertEqual(c.divmod(1, 2), d)
1868 self.assertEqual(c.divmod(Decimal(1), 2), d)
1869 self.assertEqual(c.divmod(1, Decimal(2)), d)
1870 self.assertRaises(TypeError, c.divmod, '1', 2)
1871 self.assertRaises(TypeError, c.divmod, 1, '2')
1872
1873 def test_exp(self):
1874 c = Context()
1875 d = c.exp(Decimal(10))
1876 self.assertEqual(c.exp(10), d)
1877 self.assertRaises(TypeError, c.exp, '10')
1878
1879 def test_fma(self):
1880 c = Context()
1881 d = c.fma(Decimal(2), Decimal(3), Decimal(4))
1882 self.assertEqual(c.fma(2, 3, 4), d)
1883 self.assertEqual(c.fma(Decimal(2), 3, 4), d)
1884 self.assertEqual(c.fma(2, Decimal(3), 4), d)
1885 self.assertEqual(c.fma(2, 3, Decimal(4)), d)
1886 self.assertEqual(c.fma(Decimal(2), Decimal(3), 4), d)
1887 self.assertRaises(TypeError, c.fma, '2', 3, 4)
1888 self.assertRaises(TypeError, c.fma, 2, '3', 4)
1889 self.assertRaises(TypeError, c.fma, 2, 3, '4')
1890
1891 def test_is_finite(self):
1892 c = Context()
1893 d = c.is_finite(Decimal(10))
1894 self.assertEqual(c.is_finite(10), d)
1895 self.assertRaises(TypeError, c.is_finite, '10')
1896
1897 def test_is_infinite(self):
1898 c = Context()
1899 d = c.is_infinite(Decimal(10))
1900 self.assertEqual(c.is_infinite(10), d)
1901 self.assertRaises(TypeError, c.is_infinite, '10')
1902
1903 def test_is_nan(self):
1904 c = Context()
1905 d = c.is_nan(Decimal(10))
1906 self.assertEqual(c.is_nan(10), d)
1907 self.assertRaises(TypeError, c.is_nan, '10')
1908
1909 def test_is_normal(self):
1910 c = Context()
1911 d = c.is_normal(Decimal(10))
1912 self.assertEqual(c.is_normal(10), d)
1913 self.assertRaises(TypeError, c.is_normal, '10')
1914
1915 def test_is_qnan(self):
1916 c = Context()
1917 d = c.is_qnan(Decimal(10))
1918 self.assertEqual(c.is_qnan(10), d)
1919 self.assertRaises(TypeError, c.is_qnan, '10')
1920
1921 def test_is_signed(self):
1922 c = Context()
1923 d = c.is_signed(Decimal(10))
1924 self.assertEqual(c.is_signed(10), d)
1925 self.assertRaises(TypeError, c.is_signed, '10')
1926
1927 def test_is_snan(self):
1928 c = Context()
1929 d = c.is_snan(Decimal(10))
1930 self.assertEqual(c.is_snan(10), d)
1931 self.assertRaises(TypeError, c.is_snan, '10')
1932
1933 def test_is_subnormal(self):
1934 c = Context()
1935 d = c.is_subnormal(Decimal(10))
1936 self.assertEqual(c.is_subnormal(10), d)
1937 self.assertRaises(TypeError, c.is_subnormal, '10')
1938
1939 def test_is_zero(self):
1940 c = Context()
1941 d = c.is_zero(Decimal(10))
1942 self.assertEqual(c.is_zero(10), d)
1943 self.assertRaises(TypeError, c.is_zero, '10')
1944
1945 def test_ln(self):
1946 c = Context()
1947 d = c.ln(Decimal(10))
1948 self.assertEqual(c.ln(10), d)
1949 self.assertRaises(TypeError, c.ln, '10')
1950
1951 def test_log10(self):
1952 c = Context()
1953 d = c.log10(Decimal(10))
1954 self.assertEqual(c.log10(10), d)
1955 self.assertRaises(TypeError, c.log10, '10')
1956
1957 def test_logb(self):
1958 c = Context()
1959 d = c.logb(Decimal(10))
1960 self.assertEqual(c.logb(10), d)
1961 self.assertRaises(TypeError, c.logb, '10')
1962
1963 def test_logical_and(self):
1964 c = Context()
1965 d = c.logical_and(Decimal(1), Decimal(1))
1966 self.assertEqual(c.logical_and(1, 1), d)
1967 self.assertEqual(c.logical_and(Decimal(1), 1), d)
1968 self.assertEqual(c.logical_and(1, Decimal(1)), d)
1969 self.assertRaises(TypeError, c.logical_and, '1', 1)
1970 self.assertRaises(TypeError, c.logical_and, 1, '1')
1971
1972 def test_logical_invert(self):
1973 c = Context()
1974 d = c.logical_invert(Decimal(1000))
1975 self.assertEqual(c.logical_invert(1000), d)
1976 self.assertRaises(TypeError, c.logical_invert, '1000')
1977
1978 def test_logical_or(self):
1979 c = Context()
1980 d = c.logical_or(Decimal(1), Decimal(1))
1981 self.assertEqual(c.logical_or(1, 1), d)
1982 self.assertEqual(c.logical_or(Decimal(1), 1), d)
1983 self.assertEqual(c.logical_or(1, Decimal(1)), d)
1984 self.assertRaises(TypeError, c.logical_or, '1', 1)
1985 self.assertRaises(TypeError, c.logical_or, 1, '1')
1986
1987 def test_logical_xor(self):
1988 c = Context()
1989 d = c.logical_xor(Decimal(1), Decimal(1))
1990 self.assertEqual(c.logical_xor(1, 1), d)
1991 self.assertEqual(c.logical_xor(Decimal(1), 1), d)
1992 self.assertEqual(c.logical_xor(1, Decimal(1)), d)
1993 self.assertRaises(TypeError, c.logical_xor, '1', 1)
1994 self.assertRaises(TypeError, c.logical_xor, 1, '1')
1995
1996 def test_max(self):
1997 c = Context()
1998 d = c.max(Decimal(1), Decimal(2))
1999 self.assertEqual(c.max(1, 2), d)
2000 self.assertEqual(c.max(Decimal(1), 2), d)
2001 self.assertEqual(c.max(1, Decimal(2)), d)
2002 self.assertRaises(TypeError, c.max, '1', 2)
2003 self.assertRaises(TypeError, c.max, 1, '2')
2004
2005 def test_max_mag(self):
2006 c = Context()
2007 d = c.max_mag(Decimal(1), Decimal(2))
2008 self.assertEqual(c.max_mag(1, 2), d)
2009 self.assertEqual(c.max_mag(Decimal(1), 2), d)
2010 self.assertEqual(c.max_mag(1, Decimal(2)), d)
2011 self.assertRaises(TypeError, c.max_mag, '1', 2)
2012 self.assertRaises(TypeError, c.max_mag, 1, '2')
2013
2014 def test_min(self):
2015 c = Context()
2016 d = c.min(Decimal(1), Decimal(2))
2017 self.assertEqual(c.min(1, 2), d)
2018 self.assertEqual(c.min(Decimal(1), 2), d)
2019 self.assertEqual(c.min(1, Decimal(2)), d)
2020 self.assertRaises(TypeError, c.min, '1', 2)
2021 self.assertRaises(TypeError, c.min, 1, '2')
2022
2023 def test_min_mag(self):
2024 c = Context()
2025 d = c.min_mag(Decimal(1), Decimal(2))
2026 self.assertEqual(c.min_mag(1, 2), d)
2027 self.assertEqual(c.min_mag(Decimal(1), 2), d)
2028 self.assertEqual(c.min_mag(1, Decimal(2)), d)
2029 self.assertRaises(TypeError, c.min_mag, '1', 2)
2030 self.assertRaises(TypeError, c.min_mag, 1, '2')
2031
2032 def test_minus(self):
2033 c = Context()
2034 d = c.minus(Decimal(10))
2035 self.assertEqual(c.minus(10), d)
2036 self.assertRaises(TypeError, c.minus, '10')
2037
2038 def test_multiply(self):
2039 c = Context()
2040 d = c.multiply(Decimal(1), Decimal(2))
2041 self.assertEqual(c.multiply(1, 2), d)
2042 self.assertEqual(c.multiply(Decimal(1), 2), d)
2043 self.assertEqual(c.multiply(1, Decimal(2)), d)
2044 self.assertRaises(TypeError, c.multiply, '1', 2)
2045 self.assertRaises(TypeError, c.multiply, 1, '2')
2046
2047 def test_next_minus(self):
2048 c = Context()
2049 d = c.next_minus(Decimal(10))
2050 self.assertEqual(c.next_minus(10), d)
2051 self.assertRaises(TypeError, c.next_minus, '10')
2052
2053 def test_next_plus(self):
2054 c = Context()
2055 d = c.next_plus(Decimal(10))
2056 self.assertEqual(c.next_plus(10), d)
2057 self.assertRaises(TypeError, c.next_plus, '10')
2058
2059 def test_next_toward(self):
2060 c = Context()
2061 d = c.next_toward(Decimal(1), Decimal(2))
2062 self.assertEqual(c.next_toward(1, 2), d)
2063 self.assertEqual(c.next_toward(Decimal(1), 2), d)
2064 self.assertEqual(c.next_toward(1, Decimal(2)), d)
2065 self.assertRaises(TypeError, c.next_toward, '1', 2)
2066 self.assertRaises(TypeError, c.next_toward, 1, '2')
2067
2068 def test_normalize(self):
2069 c = Context()
2070 d = c.normalize(Decimal(10))
2071 self.assertEqual(c.normalize(10), d)
2072 self.assertRaises(TypeError, c.normalize, '10')
2073
2074 def test_number_class(self):
2075 c = Context()
2076 self.assertEqual(c.number_class(123), c.number_class(Decimal(123)))
2077 self.assertEqual(c.number_class(0), c.number_class(Decimal(0)))
2078 self.assertEqual(c.number_class(-45), c.number_class(Decimal(-45)))
2079
2080 def test_power(self):
2081 c = Context()
2082 d = c.power(Decimal(1), Decimal(4), Decimal(2))
2083 self.assertEqual(c.power(1, 4, 2), d)
2084 self.assertEqual(c.power(Decimal(1), 4, 2), d)
2085 self.assertEqual(c.power(1, Decimal(4), 2), d)
2086 self.assertEqual(c.power(1, 4, Decimal(2)), d)
2087 self.assertEqual(c.power(Decimal(1), Decimal(4), 2), d)
2088 self.assertRaises(TypeError, c.power, '1', 4, 2)
2089 self.assertRaises(TypeError, c.power, 1, '4', 2)
2090 self.assertRaises(TypeError, c.power, 1, 4, '2')
2091
2092 def test_plus(self):
2093 c = Context()
2094 d = c.plus(Decimal(10))
2095 self.assertEqual(c.plus(10), d)
2096 self.assertRaises(TypeError, c.plus, '10')
2097
2098 def test_quantize(self):
2099 c = Context()
2100 d = c.quantize(Decimal(1), Decimal(2))
2101 self.assertEqual(c.quantize(1, 2), d)
2102 self.assertEqual(c.quantize(Decimal(1), 2), d)
2103 self.assertEqual(c.quantize(1, Decimal(2)), d)
2104 self.assertRaises(TypeError, c.quantize, '1', 2)
2105 self.assertRaises(TypeError, c.quantize, 1, '2')
2106
2107 def test_remainder(self):
2108 c = Context()
2109 d = c.remainder(Decimal(1), Decimal(2))
2110 self.assertEqual(c.remainder(1, 2), d)
2111 self.assertEqual(c.remainder(Decimal(1), 2), d)
2112 self.assertEqual(c.remainder(1, Decimal(2)), d)
2113 self.assertRaises(TypeError, c.remainder, '1', 2)
2114 self.assertRaises(TypeError, c.remainder, 1, '2')
2115
2116 def test_remainder_near(self):
2117 c = Context()
2118 d = c.remainder_near(Decimal(1), Decimal(2))
2119 self.assertEqual(c.remainder_near(1, 2), d)
2120 self.assertEqual(c.remainder_near(Decimal(1), 2), d)
2121 self.assertEqual(c.remainder_near(1, Decimal(2)), d)
2122 self.assertRaises(TypeError, c.remainder_near, '1', 2)
2123 self.assertRaises(TypeError, c.remainder_near, 1, '2')
2124
2125 def test_rotate(self):
2126 c = Context()
2127 d = c.rotate(Decimal(1), Decimal(2))
2128 self.assertEqual(c.rotate(1, 2), d)
2129 self.assertEqual(c.rotate(Decimal(1), 2), d)
2130 self.assertEqual(c.rotate(1, Decimal(2)), d)
2131 self.assertRaises(TypeError, c.rotate, '1', 2)
2132 self.assertRaises(TypeError, c.rotate, 1, '2')
2133
2134 def test_sqrt(self):
2135 c = Context()
2136 d = c.sqrt(Decimal(10))
2137 self.assertEqual(c.sqrt(10), d)
2138 self.assertRaises(TypeError, c.sqrt, '10')
2139
2140 def test_same_quantum(self):
2141 c = Context()
2142 d = c.same_quantum(Decimal(1), Decimal(2))
2143 self.assertEqual(c.same_quantum(1, 2), d)
2144 self.assertEqual(c.same_quantum(Decimal(1), 2), d)
2145 self.assertEqual(c.same_quantum(1, Decimal(2)), d)
2146 self.assertRaises(TypeError, c.same_quantum, '1', 2)
2147 self.assertRaises(TypeError, c.same_quantum, 1, '2')
2148
2149 def test_scaleb(self):
2150 c = Context()
2151 d = c.scaleb(Decimal(1), Decimal(2))
2152 self.assertEqual(c.scaleb(1, 2), d)
2153 self.assertEqual(c.scaleb(Decimal(1), 2), d)
2154 self.assertEqual(c.scaleb(1, Decimal(2)), d)
2155 self.assertRaises(TypeError, c.scaleb, '1', 2)
2156 self.assertRaises(TypeError, c.scaleb, 1, '2')
2157
2158 def test_shift(self):
2159 c = Context()
2160 d = c.shift(Decimal(1), Decimal(2))
2161 self.assertEqual(c.shift(1, 2), d)
2162 self.assertEqual(c.shift(Decimal(1), 2), d)
2163 self.assertEqual(c.shift(1, Decimal(2)), d)
2164 self.assertRaises(TypeError, c.shift, '1', 2)
2165 self.assertRaises(TypeError, c.shift, 1, '2')
2166
2167 def test_subtract(self):
2168 c = Context()
2169 d = c.subtract(Decimal(1), Decimal(2))
2170 self.assertEqual(c.subtract(1, 2), d)
2171 self.assertEqual(c.subtract(Decimal(1), 2), d)
2172 self.assertEqual(c.subtract(1, Decimal(2)), d)
2173 self.assertRaises(TypeError, c.subtract, '1', 2)
2174 self.assertRaises(TypeError, c.subtract, 1, '2')
2175
2176 def test_to_eng_string(self):
2177 c = Context()
2178 d = c.to_eng_string(Decimal(10))
2179 self.assertEqual(c.to_eng_string(10), d)
2180 self.assertRaises(TypeError, c.to_eng_string, '10')
2181
2182 def test_to_sci_string(self):
2183 c = Context()
2184 d = c.to_sci_string(Decimal(10))
2185 self.assertEqual(c.to_sci_string(10), d)
2186 self.assertRaises(TypeError, c.to_sci_string, '10')
2187
2188 def test_to_integral_exact(self):
2189 c = Context()
2190 d = c.to_integral_exact(Decimal(10))
2191 self.assertEqual(c.to_integral_exact(10), d)
2192 self.assertRaises(TypeError, c.to_integral_exact, '10')
2193
2194 def test_to_integral_value(self):
2195 c = Context()
2196 d = c.to_integral_value(Decimal(10))
2197 self.assertEqual(c.to_integral_value(10), d)
2198 self.assertRaises(TypeError, c.to_integral_value, '10')
2199
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002200class WithStatementTest(unittest.TestCase):
2201 # Can't do these as docstrings until Python 2.6
2202 # as doctest can't handle __future__ statements
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002203
2204 def test_localcontext(self):
Nick Coghlanced12182006-09-02 03:54:17 +00002205 # Use a copy of the current context in the block
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002206 orig_ctx = getcontext()
2207 with localcontext() as enter_ctx:
2208 set_ctx = getcontext()
2209 final_ctx = getcontext()
Ezio Melotti856a3be2010-04-03 14:51:00 +00002210 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
2211 self.assertIsNot(orig_ctx, set_ctx, 'did not copy the context')
2212 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002213
2214 def test_localcontextarg(self):
Nick Coghlanced12182006-09-02 03:54:17 +00002215 # Use a copy of the supplied context in the block
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002216 orig_ctx = getcontext()
2217 new_ctx = Context(prec=42)
2218 with localcontext(new_ctx) as enter_ctx:
2219 set_ctx = getcontext()
2220 final_ctx = getcontext()
Ezio Melotti856a3be2010-04-03 14:51:00 +00002221 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
2222 self.assertEqual(set_ctx.prec, new_ctx.prec, 'did not set correct context')
2223 self.assertIsNot(new_ctx, set_ctx, 'did not copy the context')
2224 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002225
Facundo Batista353750c2007-09-13 18:13:15 +00002226class ContextFlags(unittest.TestCase):
2227 def test_flags_irrelevant(self):
2228 # check that the result (numeric result + flags raised) of an
2229 # arithmetic operation doesn't depend on the current flags
2230
2231 context = Context(prec=9, Emin = -999999999, Emax = 999999999,
2232 rounding=ROUND_HALF_EVEN, traps=[], flags=[])
2233
2234 # operations that raise various flags, in the form (function, arglist)
2235 operations = [
2236 (context._apply, [Decimal("100E-1000000009")]),
2237 (context.sqrt, [Decimal(2)]),
2238 (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]),
2239 (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]),
2240 (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]),
2241 ]
2242
2243 # try various flags individually, then a whole lot at once
2244 flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal],
2245 [Inexact, Rounded, Underflow, Clamped, Subnormal]]
2246
2247 for fn, args in operations:
2248 # find answer and flags raised using a clean context
2249 context.clear_flags()
2250 ans = fn(*args)
2251 flags = [k for k, v in context.flags.items() if v]
2252
2253 for extra_flags in flagsets:
2254 # set flags, before calling operation
2255 context.clear_flags()
2256 for flag in extra_flags:
2257 context._raise_error(flag)
2258 new_ans = fn(*args)
2259
2260 # flags that we expect to be set after the operation
2261 expected_flags = list(flags)
2262 for flag in extra_flags:
2263 if flag not in expected_flags:
2264 expected_flags.append(flag)
Facundo Batista353750c2007-09-13 18:13:15 +00002265
2266 # flags we actually got
2267 new_flags = [k for k,v in context.flags.items() if v]
Facundo Batista353750c2007-09-13 18:13:15 +00002268
2269 self.assertEqual(ans, new_ans,
2270 "operation produces different answers depending on flags set: " +
2271 "expected %s, got %s." % (ans, new_ans))
Florent Xicluna8f43cec2010-03-21 10:51:40 +00002272 self.assertItemsEqual(new_flags, expected_flags,
Facundo Batista353750c2007-09-13 18:13:15 +00002273 "operation raises different flags depending on flags set: " +
2274 "expected %s, got %s" % (expected_flags, new_flags))
2275
2276def test_main(arith=False, verbose=None, todo_tests=None, debug=None):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002277 """ Execute the tests.
2278
Raymond Hettingered20ad82004-09-04 20:09:13 +00002279 Runs all arithmetic tests if arith is True or if the "decimal" resource
2280 is enabled in regrtest.py
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002281 """
Raymond Hettingered20ad82004-09-04 20:09:13 +00002282
Neal Norwitzce4a9c92006-04-09 08:36:46 +00002283 init()
Facundo Batista353750c2007-09-13 18:13:15 +00002284 global TEST_ALL, DEBUG
Raymond Hettingered20ad82004-09-04 20:09:13 +00002285 TEST_ALL = arith or is_resource_enabled('decimal')
Facundo Batista353750c2007-09-13 18:13:15 +00002286 DEBUG = debug
Raymond Hettingered20ad82004-09-04 20:09:13 +00002287
Facundo Batista353750c2007-09-13 18:13:15 +00002288 if todo_tests is None:
2289 test_classes = [
2290 DecimalExplicitConstructionTest,
2291 DecimalImplicitConstructionTest,
2292 DecimalArithmeticOperatorsTest,
Mark Dickinson1ddf1d82008-02-29 02:16:37 +00002293 DecimalFormatTest,
Facundo Batista353750c2007-09-13 18:13:15 +00002294 DecimalUseOfContextTest,
2295 DecimalUsabilityTest,
2296 DecimalPythonAPItests,
2297 ContextAPItests,
2298 DecimalTest,
2299 WithStatementTest,
2300 ContextFlags
2301 ]
2302 else:
2303 test_classes = [DecimalTest]
2304
2305 # Dynamically build custom test definition for each file in the test
2306 # directory and add the definitions to the DecimalTest class. This
2307 # procedure insures that new files do not get skipped.
2308 for filename in os.listdir(directory):
2309 if '.decTest' not in filename or filename.startswith("."):
2310 continue
2311 head, tail = filename.split('.')
2312 if todo_tests is not None and head not in todo_tests:
2313 continue
2314 tester = lambda self, f=filename: self.eval_file(directory + f)
2315 setattr(DecimalTest, 'test_' + head, tester)
2316 del filename, head, tail, tester
2317
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002318
Tim Peters46cc7022006-03-31 04:11:16 +00002319 try:
2320 run_unittest(*test_classes)
Facundo Batista353750c2007-09-13 18:13:15 +00002321 if todo_tests is None:
2322 import decimal as DecimalModule
2323 run_doctest(DecimalModule, verbose)
Tim Peters46cc7022006-03-31 04:11:16 +00002324 finally:
2325 setcontext(ORIGINAL_CONTEXT)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002326
2327if __name__ == '__main__':
Facundo Batista353750c2007-09-13 18:13:15 +00002328 import optparse
2329 p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]")
2330 p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test')
2331 p.add_option('--skip', '-s', action='store_true', help='skip over 90% of the arithmetic tests')
2332 (opt, args) = p.parse_args()
2333
2334 if opt.skip:
2335 test_main(arith=False, verbose=True)
2336 elif args:
2337 test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002338 else:
Facundo Batista353750c2007-09-13 18:13:15 +00002339 test_main(arith=True, verbose=True)