blob: 6cc3327d76e1df1ab342f557e6aa502b658d4876 [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
Mark Dickinson088cec32012-08-24 20:06:30 +01001451 def test_nan_to_float(self):
1452 # Test conversions of decimal NANs to float.
1453 # See http://bugs.python.org/issue15544
1454 for s in ('nan', 'nan1234', '-nan', '-nan2468'):
1455 f = float(Decimal(s))
1456 self.assertTrue(math.isnan(f))
1457 sign = math.copysign(1.0, f)
1458 self.assertEqual(sign, -1.0 if s.startswith('-') else 1.0)
1459
1460 def test_snan_to_float(self):
1461 for s in ('snan', '-snan', 'snan1357', '-snan1234'):
1462 d = Decimal(s)
1463 self.assertRaises(ValueError, float, d)
1464
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001465 def test_eval_round_trip(self):
1466
1467 #with zero
1468 d = Decimal( (0, (0,), 0) )
1469 self.assertEqual(d, eval(repr(d)))
1470
1471 #int
1472 d = Decimal( (1, (4, 5), 0) )
1473 self.assertEqual(d, eval(repr(d)))
1474
1475 #float
1476 d = Decimal( (0, (4, 5, 3, 4), -2) )
1477 self.assertEqual(d, eval(repr(d)))
1478
1479 #weird
1480 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1481 self.assertEqual(d, eval(repr(d)))
1482
1483 def test_as_tuple(self):
1484
1485 #with zero
1486 d = Decimal(0)
1487 self.assertEqual(d.as_tuple(), (0, (0,), 0) )
1488
1489 #int
1490 d = Decimal(-45)
1491 self.assertEqual(d.as_tuple(), (1, (4, 5), 0) )
1492
1493 #complicated string
1494 d = Decimal("-4.34913534E-17")
1495 self.assertEqual(d.as_tuple(), (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1496
1497 #inf
1498 d = Decimal("Infinity")
1499 self.assertEqual(d.as_tuple(), (0, (0,), 'F') )
1500
Facundo Batista9b5e2312007-10-19 19:25:57 +00001501 #leading zeros in coefficient should be stripped
1502 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), -2) )
1503 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), -2) )
1504 d = Decimal( (1, (0, 0, 0), 37) )
1505 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1506 d = Decimal( (1, (), 37) )
1507 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1508
1509 #leading zeros in NaN diagnostic info should be stripped
1510 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), 'n') )
1511 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), 'n') )
1512 d = Decimal( (1, (0, 0, 0), 'N') )
1513 self.assertEqual(d.as_tuple(), (1, (), 'N') )
1514 d = Decimal( (1, (), 'n') )
1515 self.assertEqual(d.as_tuple(), (1, (), 'n') )
1516
1517 #coefficient in infinity should be ignored
1518 d = Decimal( (0, (4, 5, 3, 4), 'F') )
1519 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
1520 d = Decimal( (1, (0, 2, 7, 1), 'F') )
1521 self.assertEqual(d.as_tuple(), (1, (0,), 'F'))
1522
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001523 def test_immutability_operations(self):
1524 # Do operations and check that it didn't change change internal objects.
1525
1526 d1 = Decimal('-25e55')
1527 b1 = Decimal('-25e55')
Facundo Batista353750c2007-09-13 18:13:15 +00001528 d2 = Decimal('33e+33')
1529 b2 = Decimal('33e+33')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001530
1531 def checkSameDec(operation, useOther=False):
1532 if useOther:
1533 eval("d1." + operation + "(d2)")
1534 self.assertEqual(d1._sign, b1._sign)
1535 self.assertEqual(d1._int, b1._int)
1536 self.assertEqual(d1._exp, b1._exp)
1537 self.assertEqual(d2._sign, b2._sign)
1538 self.assertEqual(d2._int, b2._int)
1539 self.assertEqual(d2._exp, b2._exp)
1540 else:
1541 eval("d1." + operation + "()")
1542 self.assertEqual(d1._sign, b1._sign)
1543 self.assertEqual(d1._int, b1._int)
1544 self.assertEqual(d1._exp, b1._exp)
1545 return
1546
1547 Decimal(d1)
1548 self.assertEqual(d1._sign, b1._sign)
1549 self.assertEqual(d1._int, b1._int)
1550 self.assertEqual(d1._exp, b1._exp)
1551
1552 checkSameDec("__abs__")
1553 checkSameDec("__add__", True)
1554 checkSameDec("__div__", True)
1555 checkSameDec("__divmod__", True)
Mark Dickinson2fc92632008-02-06 22:10:50 +00001556 checkSameDec("__eq__", True)
1557 checkSameDec("__ne__", True)
1558 checkSameDec("__le__", True)
1559 checkSameDec("__lt__", True)
1560 checkSameDec("__ge__", True)
1561 checkSameDec("__gt__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001562 checkSameDec("__float__")
1563 checkSameDec("__floordiv__", True)
1564 checkSameDec("__hash__")
1565 checkSameDec("__int__")
Raymond Hettinger5a053642008-01-24 19:05:29 +00001566 checkSameDec("__trunc__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001567 checkSameDec("__long__")
1568 checkSameDec("__mod__", True)
1569 checkSameDec("__mul__", True)
1570 checkSameDec("__neg__")
1571 checkSameDec("__nonzero__")
1572 checkSameDec("__pos__")
1573 checkSameDec("__pow__", True)
1574 checkSameDec("__radd__", True)
1575 checkSameDec("__rdiv__", True)
1576 checkSameDec("__rdivmod__", True)
1577 checkSameDec("__repr__")
1578 checkSameDec("__rfloordiv__", True)
1579 checkSameDec("__rmod__", True)
1580 checkSameDec("__rmul__", True)
1581 checkSameDec("__rpow__", True)
1582 checkSameDec("__rsub__", True)
1583 checkSameDec("__str__")
1584 checkSameDec("__sub__", True)
1585 checkSameDec("__truediv__", True)
1586 checkSameDec("adjusted")
1587 checkSameDec("as_tuple")
1588 checkSameDec("compare", True)
1589 checkSameDec("max", True)
1590 checkSameDec("min", True)
1591 checkSameDec("normalize")
1592 checkSameDec("quantize", True)
1593 checkSameDec("remainder_near", True)
1594 checkSameDec("same_quantum", True)
1595 checkSameDec("sqrt")
1596 checkSameDec("to_eng_string")
1597 checkSameDec("to_integral")
1598
Facundo Batista6c398da2007-09-17 17:30:13 +00001599 def test_subclassing(self):
1600 # Different behaviours when subclassing Decimal
1601
1602 class MyDecimal(Decimal):
1603 pass
1604
1605 d1 = MyDecimal(1)
1606 d2 = MyDecimal(2)
1607 d = d1 + d2
Ezio Melotti856a3be2010-04-03 14:51:00 +00001608 self.assertIs(type(d), Decimal)
Facundo Batista6c398da2007-09-17 17:30:13 +00001609
1610 d = d1.max(d2)
Ezio Melotti856a3be2010-04-03 14:51:00 +00001611 self.assertIs(type(d), Decimal)
Facundo Batista6c398da2007-09-17 17:30:13 +00001612
Mark Dickinson3b24ccb2008-03-25 14:33:23 +00001613 def test_implicit_context(self):
1614 # Check results when context given implicitly. (Issue 2478)
1615 c = getcontext()
1616 self.assertEqual(str(Decimal(0).sqrt()),
1617 str(c.sqrt(Decimal(0))))
1618
Mark Dickinson0c673122009-10-29 12:04:00 +00001619 def test_conversions_from_int(self):
1620 # Check that methods taking a second Decimal argument will
1621 # always accept an integer in place of a Decimal.
1622 self.assertEqual(Decimal(4).compare(3),
1623 Decimal(4).compare(Decimal(3)))
1624 self.assertEqual(Decimal(4).compare_signal(3),
1625 Decimal(4).compare_signal(Decimal(3)))
1626 self.assertEqual(Decimal(4).compare_total(3),
1627 Decimal(4).compare_total(Decimal(3)))
1628 self.assertEqual(Decimal(4).compare_total_mag(3),
1629 Decimal(4).compare_total_mag(Decimal(3)))
1630 self.assertEqual(Decimal(10101).logical_and(1001),
1631 Decimal(10101).logical_and(Decimal(1001)))
1632 self.assertEqual(Decimal(10101).logical_or(1001),
1633 Decimal(10101).logical_or(Decimal(1001)))
1634 self.assertEqual(Decimal(10101).logical_xor(1001),
1635 Decimal(10101).logical_xor(Decimal(1001)))
1636 self.assertEqual(Decimal(567).max(123),
1637 Decimal(567).max(Decimal(123)))
1638 self.assertEqual(Decimal(567).max_mag(123),
1639 Decimal(567).max_mag(Decimal(123)))
1640 self.assertEqual(Decimal(567).min(123),
1641 Decimal(567).min(Decimal(123)))
1642 self.assertEqual(Decimal(567).min_mag(123),
1643 Decimal(567).min_mag(Decimal(123)))
1644 self.assertEqual(Decimal(567).next_toward(123),
1645 Decimal(567).next_toward(Decimal(123)))
1646 self.assertEqual(Decimal(1234).quantize(100),
1647 Decimal(1234).quantize(Decimal(100)))
1648 self.assertEqual(Decimal(768).remainder_near(1234),
1649 Decimal(768).remainder_near(Decimal(1234)))
1650 self.assertEqual(Decimal(123).rotate(1),
1651 Decimal(123).rotate(Decimal(1)))
1652 self.assertEqual(Decimal(1234).same_quantum(1000),
1653 Decimal(1234).same_quantum(Decimal(1000)))
1654 self.assertEqual(Decimal('9.123').scaleb(-100),
1655 Decimal('9.123').scaleb(Decimal(-100)))
1656 self.assertEqual(Decimal(456).shift(-1),
1657 Decimal(456).shift(Decimal(-1)))
1658
1659 self.assertEqual(Decimal(-12).fma(Decimal(45), 67),
1660 Decimal(-12).fma(Decimal(45), Decimal(67)))
1661 self.assertEqual(Decimal(-12).fma(45, 67),
1662 Decimal(-12).fma(Decimal(45), Decimal(67)))
1663 self.assertEqual(Decimal(-12).fma(45, Decimal(67)),
1664 Decimal(-12).fma(Decimal(45), Decimal(67)))
1665
Facundo Batista6c398da2007-09-17 17:30:13 +00001666
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001667class DecimalPythonAPItests(unittest.TestCase):
1668
Raymond Hettinger2c8585b2009-02-03 03:37:03 +00001669 def test_abc(self):
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001670 self.assertTrue(issubclass(Decimal, numbers.Number))
Ezio Melotti856a3be2010-04-03 14:51:00 +00001671 self.assertFalse(issubclass(Decimal, numbers.Real))
Ezio Melottib0f5adc2010-01-24 16:58:36 +00001672 self.assertIsInstance(Decimal(0), numbers.Number)
Ezio Melotti856a3be2010-04-03 14:51:00 +00001673 self.assertNotIsInstance(Decimal(0), numbers.Real)
Raymond Hettinger2c8585b2009-02-03 03:37:03 +00001674
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001675 def test_pickle(self):
1676 d = Decimal('-3.141590000')
1677 p = pickle.dumps(d)
1678 e = pickle.loads(p)
1679 self.assertEqual(d, e)
1680
Raymond Hettinger5548be22004-07-05 18:49:38 +00001681 def test_int(self):
Raymond Hettinger605ed022004-11-24 07:28:48 +00001682 for x in range(-250, 250):
1683 s = '%0.2f' % (x / 100.0)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001684 # should work the same as for floats
1685 self.assertEqual(int(Decimal(s)), int(float(s)))
Raymond Hettinger605ed022004-11-24 07:28:48 +00001686 # should work the same as to_integral in the ROUND_DOWN mode
Raymond Hettinger5548be22004-07-05 18:49:38 +00001687 d = Decimal(s)
Raymond Hettinger605ed022004-11-24 07:28:48 +00001688 r = d.to_integral(ROUND_DOWN)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001689 self.assertEqual(Decimal(int(d)), r)
1690
Mark Dickinson968f1692009-09-07 18:04:58 +00001691 self.assertRaises(ValueError, int, Decimal('-nan'))
1692 self.assertRaises(ValueError, int, Decimal('snan'))
1693 self.assertRaises(OverflowError, int, Decimal('inf'))
1694 self.assertRaises(OverflowError, int, Decimal('-inf'))
1695
1696 self.assertRaises(ValueError, long, Decimal('-nan'))
1697 self.assertRaises(ValueError, long, Decimal('snan'))
1698 self.assertRaises(OverflowError, long, Decimal('inf'))
1699 self.assertRaises(OverflowError, long, Decimal('-inf'))
1700
Raymond Hettinger5a053642008-01-24 19:05:29 +00001701 def test_trunc(self):
1702 for x in range(-250, 250):
1703 s = '%0.2f' % (x / 100.0)
1704 # should work the same as for floats
1705 self.assertEqual(int(Decimal(s)), int(float(s)))
1706 # should work the same as to_integral in the ROUND_DOWN mode
1707 d = Decimal(s)
1708 r = d.to_integral(ROUND_DOWN)
Jeffrey Yasskinca2b69f2008-02-01 06:22:46 +00001709 self.assertEqual(Decimal(math.trunc(d)), r)
Raymond Hettinger5a053642008-01-24 19:05:29 +00001710
Raymond Hettingerf4d85972009-01-03 19:02:23 +00001711 def test_from_float(self):
1712
1713 class MyDecimal(Decimal):
1714 pass
1715
1716 r = MyDecimal.from_float(0.1)
1717 self.assertEqual(type(r), MyDecimal)
1718 self.assertEqual(str(r),
1719 '0.1000000000000000055511151231257827021181583404541015625')
1720 bigint = 12345678901234567890123456789
1721 self.assertEqual(MyDecimal.from_float(bigint), MyDecimal(bigint))
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001722 self.assertTrue(MyDecimal.from_float(float('nan')).is_qnan())
1723 self.assertTrue(MyDecimal.from_float(float('inf')).is_infinite())
1724 self.assertTrue(MyDecimal.from_float(float('-inf')).is_infinite())
Raymond Hettingerf4d85972009-01-03 19:02:23 +00001725 self.assertEqual(str(MyDecimal.from_float(float('nan'))),
1726 str(Decimal('NaN')))
1727 self.assertEqual(str(MyDecimal.from_float(float('inf'))),
1728 str(Decimal('Infinity')))
1729 self.assertEqual(str(MyDecimal.from_float(float('-inf'))),
1730 str(Decimal('-Infinity')))
1731 self.assertRaises(TypeError, MyDecimal.from_float, 'abc')
1732 for i in range(200):
1733 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
1734 self.assertEqual(x, float(MyDecimal.from_float(x))) # roundtrip
1735
1736 def test_create_decimal_from_float(self):
1737 context = Context(prec=5, rounding=ROUND_DOWN)
1738 self.assertEqual(
1739 context.create_decimal_from_float(math.pi),
1740 Decimal('3.1415')
1741 )
1742 context = Context(prec=5, rounding=ROUND_UP)
1743 self.assertEqual(
1744 context.create_decimal_from_float(math.pi),
1745 Decimal('3.1416')
1746 )
1747 context = Context(prec=5, traps=[Inexact])
1748 self.assertRaises(
1749 Inexact,
1750 context.create_decimal_from_float,
1751 math.pi
1752 )
1753 self.assertEqual(repr(context.create_decimal_from_float(-0.0)),
1754 "Decimal('-0')")
1755 self.assertEqual(repr(context.create_decimal_from_float(1.0)),
1756 "Decimal('1')")
1757 self.assertEqual(repr(context.create_decimal_from_float(10)),
1758 "Decimal('10')")
1759
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00001760class ContextAPItests(unittest.TestCase):
1761
1762 def test_pickle(self):
1763 c = Context()
1764 e = pickle.loads(pickle.dumps(c))
1765 for k in vars(c):
1766 v1 = vars(c)[k]
1767 v2 = vars(e)[k]
1768 self.assertEqual(v1, v2)
1769
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001770 def test_equality_with_other_types(self):
Ezio Melottiaa980582010-01-23 23:04:36 +00001771 self.assertIn(Decimal(10), ['a', 1.0, Decimal(10), (1,2), {}])
1772 self.assertNotIn(Decimal(10), ['a', 1.0, (1,2), {}])
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001773
Raymond Hettinger955d2b22004-08-08 20:17:45 +00001774 def test_copy(self):
1775 # All copies should be deep
1776 c = Context()
1777 d = c.copy()
1778 self.assertNotEqual(id(c), id(d))
1779 self.assertNotEqual(id(c.flags), id(d.flags))
1780 self.assertNotEqual(id(c.traps), id(d.traps))
1781
Mark Dickinson6d8effb2010-02-18 14:27:02 +00001782 def test_abs(self):
1783 c = Context()
1784 d = c.abs(Decimal(-1))
1785 self.assertEqual(c.abs(-1), d)
1786 self.assertRaises(TypeError, c.abs, '-1')
1787
1788 def test_add(self):
1789 c = Context()
1790 d = c.add(Decimal(1), Decimal(1))
1791 self.assertEqual(c.add(1, 1), d)
1792 self.assertEqual(c.add(Decimal(1), 1), d)
1793 self.assertEqual(c.add(1, Decimal(1)), d)
1794 self.assertRaises(TypeError, c.add, '1', 1)
1795 self.assertRaises(TypeError, c.add, 1, '1')
1796
1797 def test_compare(self):
1798 c = Context()
1799 d = c.compare(Decimal(1), Decimal(1))
1800 self.assertEqual(c.compare(1, 1), d)
1801 self.assertEqual(c.compare(Decimal(1), 1), d)
1802 self.assertEqual(c.compare(1, Decimal(1)), d)
1803 self.assertRaises(TypeError, c.compare, '1', 1)
1804 self.assertRaises(TypeError, c.compare, 1, '1')
1805
1806 def test_compare_signal(self):
1807 c = Context()
1808 d = c.compare_signal(Decimal(1), Decimal(1))
1809 self.assertEqual(c.compare_signal(1, 1), d)
1810 self.assertEqual(c.compare_signal(Decimal(1), 1), d)
1811 self.assertEqual(c.compare_signal(1, Decimal(1)), d)
1812 self.assertRaises(TypeError, c.compare_signal, '1', 1)
1813 self.assertRaises(TypeError, c.compare_signal, 1, '1')
1814
1815 def test_compare_total(self):
1816 c = Context()
1817 d = c.compare_total(Decimal(1), Decimal(1))
1818 self.assertEqual(c.compare_total(1, 1), d)
1819 self.assertEqual(c.compare_total(Decimal(1), 1), d)
1820 self.assertEqual(c.compare_total(1, Decimal(1)), d)
1821 self.assertRaises(TypeError, c.compare_total, '1', 1)
1822 self.assertRaises(TypeError, c.compare_total, 1, '1')
1823
1824 def test_compare_total_mag(self):
1825 c = Context()
1826 d = c.compare_total_mag(Decimal(1), Decimal(1))
1827 self.assertEqual(c.compare_total_mag(1, 1), d)
1828 self.assertEqual(c.compare_total_mag(Decimal(1), 1), d)
1829 self.assertEqual(c.compare_total_mag(1, Decimal(1)), d)
1830 self.assertRaises(TypeError, c.compare_total_mag, '1', 1)
1831 self.assertRaises(TypeError, c.compare_total_mag, 1, '1')
1832
1833 def test_copy_abs(self):
1834 c = Context()
1835 d = c.copy_abs(Decimal(-1))
1836 self.assertEqual(c.copy_abs(-1), d)
1837 self.assertRaises(TypeError, c.copy_abs, '-1')
1838
1839 def test_copy_decimal(self):
1840 c = Context()
1841 d = c.copy_decimal(Decimal(-1))
1842 self.assertEqual(c.copy_decimal(-1), d)
1843 self.assertRaises(TypeError, c.copy_decimal, '-1')
1844
1845 def test_copy_negate(self):
1846 c = Context()
1847 d = c.copy_negate(Decimal(-1))
1848 self.assertEqual(c.copy_negate(-1), d)
1849 self.assertRaises(TypeError, c.copy_negate, '-1')
1850
1851 def test_copy_sign(self):
1852 c = Context()
1853 d = c.copy_sign(Decimal(1), Decimal(-2))
1854 self.assertEqual(c.copy_sign(1, -2), d)
1855 self.assertEqual(c.copy_sign(Decimal(1), -2), d)
1856 self.assertEqual(c.copy_sign(1, Decimal(-2)), d)
1857 self.assertRaises(TypeError, c.copy_sign, '1', -2)
1858 self.assertRaises(TypeError, c.copy_sign, 1, '-2')
1859
1860 def test_divide(self):
1861 c = Context()
1862 d = c.divide(Decimal(1), Decimal(2))
1863 self.assertEqual(c.divide(1, 2), d)
1864 self.assertEqual(c.divide(Decimal(1), 2), d)
1865 self.assertEqual(c.divide(1, Decimal(2)), d)
1866 self.assertRaises(TypeError, c.divide, '1', 2)
1867 self.assertRaises(TypeError, c.divide, 1, '2')
1868
1869 def test_divide_int(self):
1870 c = Context()
1871 d = c.divide_int(Decimal(1), Decimal(2))
1872 self.assertEqual(c.divide_int(1, 2), d)
1873 self.assertEqual(c.divide_int(Decimal(1), 2), d)
1874 self.assertEqual(c.divide_int(1, Decimal(2)), d)
1875 self.assertRaises(TypeError, c.divide_int, '1', 2)
1876 self.assertRaises(TypeError, c.divide_int, 1, '2')
1877
1878 def test_divmod(self):
1879 c = Context()
1880 d = c.divmod(Decimal(1), Decimal(2))
1881 self.assertEqual(c.divmod(1, 2), d)
1882 self.assertEqual(c.divmod(Decimal(1), 2), d)
1883 self.assertEqual(c.divmod(1, Decimal(2)), d)
1884 self.assertRaises(TypeError, c.divmod, '1', 2)
1885 self.assertRaises(TypeError, c.divmod, 1, '2')
1886
1887 def test_exp(self):
1888 c = Context()
1889 d = c.exp(Decimal(10))
1890 self.assertEqual(c.exp(10), d)
1891 self.assertRaises(TypeError, c.exp, '10')
1892
1893 def test_fma(self):
1894 c = Context()
1895 d = c.fma(Decimal(2), Decimal(3), Decimal(4))
1896 self.assertEqual(c.fma(2, 3, 4), d)
1897 self.assertEqual(c.fma(Decimal(2), 3, 4), d)
1898 self.assertEqual(c.fma(2, Decimal(3), 4), d)
1899 self.assertEqual(c.fma(2, 3, Decimal(4)), d)
1900 self.assertEqual(c.fma(Decimal(2), Decimal(3), 4), d)
1901 self.assertRaises(TypeError, c.fma, '2', 3, 4)
1902 self.assertRaises(TypeError, c.fma, 2, '3', 4)
1903 self.assertRaises(TypeError, c.fma, 2, 3, '4')
1904
1905 def test_is_finite(self):
1906 c = Context()
1907 d = c.is_finite(Decimal(10))
1908 self.assertEqual(c.is_finite(10), d)
1909 self.assertRaises(TypeError, c.is_finite, '10')
1910
1911 def test_is_infinite(self):
1912 c = Context()
1913 d = c.is_infinite(Decimal(10))
1914 self.assertEqual(c.is_infinite(10), d)
1915 self.assertRaises(TypeError, c.is_infinite, '10')
1916
1917 def test_is_nan(self):
1918 c = Context()
1919 d = c.is_nan(Decimal(10))
1920 self.assertEqual(c.is_nan(10), d)
1921 self.assertRaises(TypeError, c.is_nan, '10')
1922
1923 def test_is_normal(self):
1924 c = Context()
1925 d = c.is_normal(Decimal(10))
1926 self.assertEqual(c.is_normal(10), d)
1927 self.assertRaises(TypeError, c.is_normal, '10')
1928
1929 def test_is_qnan(self):
1930 c = Context()
1931 d = c.is_qnan(Decimal(10))
1932 self.assertEqual(c.is_qnan(10), d)
1933 self.assertRaises(TypeError, c.is_qnan, '10')
1934
1935 def test_is_signed(self):
1936 c = Context()
1937 d = c.is_signed(Decimal(10))
1938 self.assertEqual(c.is_signed(10), d)
1939 self.assertRaises(TypeError, c.is_signed, '10')
1940
1941 def test_is_snan(self):
1942 c = Context()
1943 d = c.is_snan(Decimal(10))
1944 self.assertEqual(c.is_snan(10), d)
1945 self.assertRaises(TypeError, c.is_snan, '10')
1946
1947 def test_is_subnormal(self):
1948 c = Context()
1949 d = c.is_subnormal(Decimal(10))
1950 self.assertEqual(c.is_subnormal(10), d)
1951 self.assertRaises(TypeError, c.is_subnormal, '10')
1952
1953 def test_is_zero(self):
1954 c = Context()
1955 d = c.is_zero(Decimal(10))
1956 self.assertEqual(c.is_zero(10), d)
1957 self.assertRaises(TypeError, c.is_zero, '10')
1958
1959 def test_ln(self):
1960 c = Context()
1961 d = c.ln(Decimal(10))
1962 self.assertEqual(c.ln(10), d)
1963 self.assertRaises(TypeError, c.ln, '10')
1964
1965 def test_log10(self):
1966 c = Context()
1967 d = c.log10(Decimal(10))
1968 self.assertEqual(c.log10(10), d)
1969 self.assertRaises(TypeError, c.log10, '10')
1970
1971 def test_logb(self):
1972 c = Context()
1973 d = c.logb(Decimal(10))
1974 self.assertEqual(c.logb(10), d)
1975 self.assertRaises(TypeError, c.logb, '10')
1976
1977 def test_logical_and(self):
1978 c = Context()
1979 d = c.logical_and(Decimal(1), Decimal(1))
1980 self.assertEqual(c.logical_and(1, 1), d)
1981 self.assertEqual(c.logical_and(Decimal(1), 1), d)
1982 self.assertEqual(c.logical_and(1, Decimal(1)), d)
1983 self.assertRaises(TypeError, c.logical_and, '1', 1)
1984 self.assertRaises(TypeError, c.logical_and, 1, '1')
1985
1986 def test_logical_invert(self):
1987 c = Context()
1988 d = c.logical_invert(Decimal(1000))
1989 self.assertEqual(c.logical_invert(1000), d)
1990 self.assertRaises(TypeError, c.logical_invert, '1000')
1991
1992 def test_logical_or(self):
1993 c = Context()
1994 d = c.logical_or(Decimal(1), Decimal(1))
1995 self.assertEqual(c.logical_or(1, 1), d)
1996 self.assertEqual(c.logical_or(Decimal(1), 1), d)
1997 self.assertEqual(c.logical_or(1, Decimal(1)), d)
1998 self.assertRaises(TypeError, c.logical_or, '1', 1)
1999 self.assertRaises(TypeError, c.logical_or, 1, '1')
2000
2001 def test_logical_xor(self):
2002 c = Context()
2003 d = c.logical_xor(Decimal(1), Decimal(1))
2004 self.assertEqual(c.logical_xor(1, 1), d)
2005 self.assertEqual(c.logical_xor(Decimal(1), 1), d)
2006 self.assertEqual(c.logical_xor(1, Decimal(1)), d)
2007 self.assertRaises(TypeError, c.logical_xor, '1', 1)
2008 self.assertRaises(TypeError, c.logical_xor, 1, '1')
2009
2010 def test_max(self):
2011 c = Context()
2012 d = c.max(Decimal(1), Decimal(2))
2013 self.assertEqual(c.max(1, 2), d)
2014 self.assertEqual(c.max(Decimal(1), 2), d)
2015 self.assertEqual(c.max(1, Decimal(2)), d)
2016 self.assertRaises(TypeError, c.max, '1', 2)
2017 self.assertRaises(TypeError, c.max, 1, '2')
2018
2019 def test_max_mag(self):
2020 c = Context()
2021 d = c.max_mag(Decimal(1), Decimal(2))
2022 self.assertEqual(c.max_mag(1, 2), d)
2023 self.assertEqual(c.max_mag(Decimal(1), 2), d)
2024 self.assertEqual(c.max_mag(1, Decimal(2)), d)
2025 self.assertRaises(TypeError, c.max_mag, '1', 2)
2026 self.assertRaises(TypeError, c.max_mag, 1, '2')
2027
2028 def test_min(self):
2029 c = Context()
2030 d = c.min(Decimal(1), Decimal(2))
2031 self.assertEqual(c.min(1, 2), d)
2032 self.assertEqual(c.min(Decimal(1), 2), d)
2033 self.assertEqual(c.min(1, Decimal(2)), d)
2034 self.assertRaises(TypeError, c.min, '1', 2)
2035 self.assertRaises(TypeError, c.min, 1, '2')
2036
2037 def test_min_mag(self):
2038 c = Context()
2039 d = c.min_mag(Decimal(1), Decimal(2))
2040 self.assertEqual(c.min_mag(1, 2), d)
2041 self.assertEqual(c.min_mag(Decimal(1), 2), d)
2042 self.assertEqual(c.min_mag(1, Decimal(2)), d)
2043 self.assertRaises(TypeError, c.min_mag, '1', 2)
2044 self.assertRaises(TypeError, c.min_mag, 1, '2')
2045
2046 def test_minus(self):
2047 c = Context()
2048 d = c.minus(Decimal(10))
2049 self.assertEqual(c.minus(10), d)
2050 self.assertRaises(TypeError, c.minus, '10')
2051
2052 def test_multiply(self):
2053 c = Context()
2054 d = c.multiply(Decimal(1), Decimal(2))
2055 self.assertEqual(c.multiply(1, 2), d)
2056 self.assertEqual(c.multiply(Decimal(1), 2), d)
2057 self.assertEqual(c.multiply(1, Decimal(2)), d)
2058 self.assertRaises(TypeError, c.multiply, '1', 2)
2059 self.assertRaises(TypeError, c.multiply, 1, '2')
2060
2061 def test_next_minus(self):
2062 c = Context()
2063 d = c.next_minus(Decimal(10))
2064 self.assertEqual(c.next_minus(10), d)
2065 self.assertRaises(TypeError, c.next_minus, '10')
2066
2067 def test_next_plus(self):
2068 c = Context()
2069 d = c.next_plus(Decimal(10))
2070 self.assertEqual(c.next_plus(10), d)
2071 self.assertRaises(TypeError, c.next_plus, '10')
2072
2073 def test_next_toward(self):
2074 c = Context()
2075 d = c.next_toward(Decimal(1), Decimal(2))
2076 self.assertEqual(c.next_toward(1, 2), d)
2077 self.assertEqual(c.next_toward(Decimal(1), 2), d)
2078 self.assertEqual(c.next_toward(1, Decimal(2)), d)
2079 self.assertRaises(TypeError, c.next_toward, '1', 2)
2080 self.assertRaises(TypeError, c.next_toward, 1, '2')
2081
2082 def test_normalize(self):
2083 c = Context()
2084 d = c.normalize(Decimal(10))
2085 self.assertEqual(c.normalize(10), d)
2086 self.assertRaises(TypeError, c.normalize, '10')
2087
2088 def test_number_class(self):
2089 c = Context()
2090 self.assertEqual(c.number_class(123), c.number_class(Decimal(123)))
2091 self.assertEqual(c.number_class(0), c.number_class(Decimal(0)))
2092 self.assertEqual(c.number_class(-45), c.number_class(Decimal(-45)))
2093
2094 def test_power(self):
2095 c = Context()
2096 d = c.power(Decimal(1), Decimal(4), Decimal(2))
2097 self.assertEqual(c.power(1, 4, 2), d)
2098 self.assertEqual(c.power(Decimal(1), 4, 2), d)
2099 self.assertEqual(c.power(1, Decimal(4), 2), d)
2100 self.assertEqual(c.power(1, 4, Decimal(2)), d)
2101 self.assertEqual(c.power(Decimal(1), Decimal(4), 2), d)
2102 self.assertRaises(TypeError, c.power, '1', 4, 2)
2103 self.assertRaises(TypeError, c.power, 1, '4', 2)
2104 self.assertRaises(TypeError, c.power, 1, 4, '2')
2105
2106 def test_plus(self):
2107 c = Context()
2108 d = c.plus(Decimal(10))
2109 self.assertEqual(c.plus(10), d)
2110 self.assertRaises(TypeError, c.plus, '10')
2111
2112 def test_quantize(self):
2113 c = Context()
2114 d = c.quantize(Decimal(1), Decimal(2))
2115 self.assertEqual(c.quantize(1, 2), d)
2116 self.assertEqual(c.quantize(Decimal(1), 2), d)
2117 self.assertEqual(c.quantize(1, Decimal(2)), d)
2118 self.assertRaises(TypeError, c.quantize, '1', 2)
2119 self.assertRaises(TypeError, c.quantize, 1, '2')
2120
2121 def test_remainder(self):
2122 c = Context()
2123 d = c.remainder(Decimal(1), Decimal(2))
2124 self.assertEqual(c.remainder(1, 2), d)
2125 self.assertEqual(c.remainder(Decimal(1), 2), d)
2126 self.assertEqual(c.remainder(1, Decimal(2)), d)
2127 self.assertRaises(TypeError, c.remainder, '1', 2)
2128 self.assertRaises(TypeError, c.remainder, 1, '2')
2129
2130 def test_remainder_near(self):
2131 c = Context()
2132 d = c.remainder_near(Decimal(1), Decimal(2))
2133 self.assertEqual(c.remainder_near(1, 2), d)
2134 self.assertEqual(c.remainder_near(Decimal(1), 2), d)
2135 self.assertEqual(c.remainder_near(1, Decimal(2)), d)
2136 self.assertRaises(TypeError, c.remainder_near, '1', 2)
2137 self.assertRaises(TypeError, c.remainder_near, 1, '2')
2138
2139 def test_rotate(self):
2140 c = Context()
2141 d = c.rotate(Decimal(1), Decimal(2))
2142 self.assertEqual(c.rotate(1, 2), d)
2143 self.assertEqual(c.rotate(Decimal(1), 2), d)
2144 self.assertEqual(c.rotate(1, Decimal(2)), d)
2145 self.assertRaises(TypeError, c.rotate, '1', 2)
2146 self.assertRaises(TypeError, c.rotate, 1, '2')
2147
2148 def test_sqrt(self):
2149 c = Context()
2150 d = c.sqrt(Decimal(10))
2151 self.assertEqual(c.sqrt(10), d)
2152 self.assertRaises(TypeError, c.sqrt, '10')
2153
2154 def test_same_quantum(self):
2155 c = Context()
2156 d = c.same_quantum(Decimal(1), Decimal(2))
2157 self.assertEqual(c.same_quantum(1, 2), d)
2158 self.assertEqual(c.same_quantum(Decimal(1), 2), d)
2159 self.assertEqual(c.same_quantum(1, Decimal(2)), d)
2160 self.assertRaises(TypeError, c.same_quantum, '1', 2)
2161 self.assertRaises(TypeError, c.same_quantum, 1, '2')
2162
2163 def test_scaleb(self):
2164 c = Context()
2165 d = c.scaleb(Decimal(1), Decimal(2))
2166 self.assertEqual(c.scaleb(1, 2), d)
2167 self.assertEqual(c.scaleb(Decimal(1), 2), d)
2168 self.assertEqual(c.scaleb(1, Decimal(2)), d)
2169 self.assertRaises(TypeError, c.scaleb, '1', 2)
2170 self.assertRaises(TypeError, c.scaleb, 1, '2')
2171
2172 def test_shift(self):
2173 c = Context()
2174 d = c.shift(Decimal(1), Decimal(2))
2175 self.assertEqual(c.shift(1, 2), d)
2176 self.assertEqual(c.shift(Decimal(1), 2), d)
2177 self.assertEqual(c.shift(1, Decimal(2)), d)
2178 self.assertRaises(TypeError, c.shift, '1', 2)
2179 self.assertRaises(TypeError, c.shift, 1, '2')
2180
2181 def test_subtract(self):
2182 c = Context()
2183 d = c.subtract(Decimal(1), Decimal(2))
2184 self.assertEqual(c.subtract(1, 2), d)
2185 self.assertEqual(c.subtract(Decimal(1), 2), d)
2186 self.assertEqual(c.subtract(1, Decimal(2)), d)
2187 self.assertRaises(TypeError, c.subtract, '1', 2)
2188 self.assertRaises(TypeError, c.subtract, 1, '2')
2189
2190 def test_to_eng_string(self):
2191 c = Context()
2192 d = c.to_eng_string(Decimal(10))
2193 self.assertEqual(c.to_eng_string(10), d)
2194 self.assertRaises(TypeError, c.to_eng_string, '10')
2195
2196 def test_to_sci_string(self):
2197 c = Context()
2198 d = c.to_sci_string(Decimal(10))
2199 self.assertEqual(c.to_sci_string(10), d)
2200 self.assertRaises(TypeError, c.to_sci_string, '10')
2201
2202 def test_to_integral_exact(self):
2203 c = Context()
2204 d = c.to_integral_exact(Decimal(10))
2205 self.assertEqual(c.to_integral_exact(10), d)
2206 self.assertRaises(TypeError, c.to_integral_exact, '10')
2207
2208 def test_to_integral_value(self):
2209 c = Context()
2210 d = c.to_integral_value(Decimal(10))
2211 self.assertEqual(c.to_integral_value(10), d)
2212 self.assertRaises(TypeError, c.to_integral_value, '10')
2213
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002214class WithStatementTest(unittest.TestCase):
2215 # Can't do these as docstrings until Python 2.6
2216 # as doctest can't handle __future__ statements
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002217
2218 def test_localcontext(self):
Nick Coghlanced12182006-09-02 03:54:17 +00002219 # Use a copy of the current context in the block
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002220 orig_ctx = getcontext()
2221 with localcontext() as enter_ctx:
2222 set_ctx = getcontext()
2223 final_ctx = getcontext()
Ezio Melotti856a3be2010-04-03 14:51:00 +00002224 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
2225 self.assertIsNot(orig_ctx, set_ctx, 'did not copy the context')
2226 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002227
2228 def test_localcontextarg(self):
Nick Coghlanced12182006-09-02 03:54:17 +00002229 # Use a copy of the supplied context in the block
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002230 orig_ctx = getcontext()
2231 new_ctx = Context(prec=42)
2232 with localcontext(new_ctx) as enter_ctx:
2233 set_ctx = getcontext()
2234 final_ctx = getcontext()
Ezio Melotti856a3be2010-04-03 14:51:00 +00002235 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
2236 self.assertEqual(set_ctx.prec, new_ctx.prec, 'did not set correct context')
2237 self.assertIsNot(new_ctx, set_ctx, 'did not copy the context')
2238 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002239
Facundo Batista353750c2007-09-13 18:13:15 +00002240class ContextFlags(unittest.TestCase):
2241 def test_flags_irrelevant(self):
2242 # check that the result (numeric result + flags raised) of an
2243 # arithmetic operation doesn't depend on the current flags
2244
2245 context = Context(prec=9, Emin = -999999999, Emax = 999999999,
2246 rounding=ROUND_HALF_EVEN, traps=[], flags=[])
2247
2248 # operations that raise various flags, in the form (function, arglist)
2249 operations = [
2250 (context._apply, [Decimal("100E-1000000009")]),
2251 (context.sqrt, [Decimal(2)]),
2252 (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]),
2253 (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]),
2254 (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]),
2255 ]
2256
2257 # try various flags individually, then a whole lot at once
2258 flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal],
2259 [Inexact, Rounded, Underflow, Clamped, Subnormal]]
2260
2261 for fn, args in operations:
2262 # find answer and flags raised using a clean context
2263 context.clear_flags()
2264 ans = fn(*args)
2265 flags = [k for k, v in context.flags.items() if v]
2266
2267 for extra_flags in flagsets:
2268 # set flags, before calling operation
2269 context.clear_flags()
2270 for flag in extra_flags:
2271 context._raise_error(flag)
2272 new_ans = fn(*args)
2273
2274 # flags that we expect to be set after the operation
2275 expected_flags = list(flags)
2276 for flag in extra_flags:
2277 if flag not in expected_flags:
2278 expected_flags.append(flag)
Facundo Batista353750c2007-09-13 18:13:15 +00002279
2280 # flags we actually got
2281 new_flags = [k for k,v in context.flags.items() if v]
Facundo Batista353750c2007-09-13 18:13:15 +00002282
2283 self.assertEqual(ans, new_ans,
2284 "operation produces different answers depending on flags set: " +
2285 "expected %s, got %s." % (ans, new_ans))
Florent Xicluna8f43cec2010-03-21 10:51:40 +00002286 self.assertItemsEqual(new_flags, expected_flags,
Facundo Batista353750c2007-09-13 18:13:15 +00002287 "operation raises different flags depending on flags set: " +
2288 "expected %s, got %s" % (expected_flags, new_flags))
2289
2290def test_main(arith=False, verbose=None, todo_tests=None, debug=None):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002291 """ Execute the tests.
2292
Raymond Hettingered20ad82004-09-04 20:09:13 +00002293 Runs all arithmetic tests if arith is True or if the "decimal" resource
2294 is enabled in regrtest.py
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002295 """
Raymond Hettingered20ad82004-09-04 20:09:13 +00002296
Neal Norwitzce4a9c92006-04-09 08:36:46 +00002297 init()
Facundo Batista353750c2007-09-13 18:13:15 +00002298 global TEST_ALL, DEBUG
Raymond Hettingered20ad82004-09-04 20:09:13 +00002299 TEST_ALL = arith or is_resource_enabled('decimal')
Facundo Batista353750c2007-09-13 18:13:15 +00002300 DEBUG = debug
Raymond Hettingered20ad82004-09-04 20:09:13 +00002301
Facundo Batista353750c2007-09-13 18:13:15 +00002302 if todo_tests is None:
2303 test_classes = [
2304 DecimalExplicitConstructionTest,
2305 DecimalImplicitConstructionTest,
2306 DecimalArithmeticOperatorsTest,
Mark Dickinson1ddf1d82008-02-29 02:16:37 +00002307 DecimalFormatTest,
Facundo Batista353750c2007-09-13 18:13:15 +00002308 DecimalUseOfContextTest,
2309 DecimalUsabilityTest,
2310 DecimalPythonAPItests,
2311 ContextAPItests,
2312 DecimalTest,
2313 WithStatementTest,
2314 ContextFlags
2315 ]
2316 else:
2317 test_classes = [DecimalTest]
2318
2319 # Dynamically build custom test definition for each file in the test
2320 # directory and add the definitions to the DecimalTest class. This
2321 # procedure insures that new files do not get skipped.
2322 for filename in os.listdir(directory):
2323 if '.decTest' not in filename or filename.startswith("."):
2324 continue
2325 head, tail = filename.split('.')
2326 if todo_tests is not None and head not in todo_tests:
2327 continue
2328 tester = lambda self, f=filename: self.eval_file(directory + f)
2329 setattr(DecimalTest, 'test_' + head, tester)
2330 del filename, head, tail, tester
2331
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002332
Tim Peters46cc7022006-03-31 04:11:16 +00002333 try:
2334 run_unittest(*test_classes)
Facundo Batista353750c2007-09-13 18:13:15 +00002335 if todo_tests is None:
2336 import decimal as DecimalModule
2337 run_doctest(DecimalModule, verbose)
Tim Peters46cc7022006-03-31 04:11:16 +00002338 finally:
2339 setcontext(ORIGINAL_CONTEXT)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002340
2341if __name__ == '__main__':
Facundo Batista353750c2007-09-13 18:13:15 +00002342 import optparse
2343 p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]")
2344 p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test')
2345 p.add_option('--skip', '-s', action='store_true', help='skip over 90% of the arithmetic tests')
2346 (opt, args) = p.parse_args()
2347
2348 if opt.skip:
2349 test_main(arith=False, verbose=True)
2350 elif args:
2351 test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002352 else:
Facundo Batista353750c2007-09-13 18:13:15 +00002353 test_main(arith=True, verbose=True)