blob: 87e8816bdebfe3df48e5f82ae9399401fe19fd39 [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
Antoine Pitrou99d848b2010-10-14 22:22:30 +0000226 with open(file) as f:
227 for line in f:
228 line = line.replace('\r\n', '').replace('\n', '')
229 #print line
230 try:
231 t = self.eval_line(line)
232 except DecimalException as exception:
Ezio Melottic2077b02011-03-16 12:34:31 +0200233 #Exception raised where there shouldn't have been one.
Antoine Pitrou99d848b2010-10-14 22:22:30 +0000234 self.fail('Exception "'+exception.__class__.__name__ + '" raised on line '+line)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000235
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000236
237 def eval_line(self, s):
238 if s.find(' -> ') >= 0 and s[:2] != '--' and not s.startswith(' --'):
239 s = (s.split('->')[0] + '->' +
240 s.split('->')[1].split('--')[0]).strip()
241 else:
242 s = s.split('--')[0].strip()
243
244 for ignore in self.ignore_list:
245 if s.find(ignore) >= 0:
246 #print s.split()[0], 'NotImplemented--', ignore
247 return
248 if not s:
249 return
250 elif ':' in s:
251 return self.eval_directive(s)
252 else:
253 return self.eval_equation(s)
254
255 def eval_directive(self, s):
256 funct, value = map(lambda x: x.strip().lower(), s.split(':'))
257 if funct == 'rounding':
258 value = RoundingDict[value]
259 else:
260 try:
261 value = int(value)
262 except ValueError:
263 pass
264
265 funct = self.ChangeDict.get(funct, Nonfunction)
266 funct(value)
267
268 def eval_equation(self, s):
269 #global DEFAULT_PRECISION
270 #print DEFAULT_PRECISION
Raymond Hettingered20ad82004-09-04 20:09:13 +0000271
272 if not TEST_ALL and random.random() < 0.90:
273 return
274
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000275 try:
276 Sides = s.split('->')
277 L = Sides[0].strip().split()
278 id = L[0]
Facundo Batista353750c2007-09-13 18:13:15 +0000279 if DEBUG:
280 print "Test ", id,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000281 funct = L[1].lower()
282 valstemp = L[2:]
283 L = Sides[1].strip().split()
284 ans = L[0]
285 exceptions = L[1:]
286 except (TypeError, AttributeError, IndexError):
Raymond Hettingerd87ac8f2004-07-09 10:52:54 +0000287 raise InvalidOperation
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000288 def FixQuotes(val):
289 val = val.replace("''", 'SingleQuote').replace('""', 'DoubleQuote')
290 val = val.replace("'", '').replace('"', '')
291 val = val.replace('SingleQuote', "'").replace('DoubleQuote', '"')
292 return val
Mark Dickinson539bff42009-10-08 16:28:39 +0000293
294 if id in skipped_test_ids:
295 return
296
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000297 fname = nameAdapter.get(funct, funct)
298 if fname == 'rescale':
299 return
300 funct = getattr(self.context, fname)
301 vals = []
302 conglomerate = ''
303 quote = 0
304 theirexceptions = [ErrorNames[x.lower()] for x in exceptions]
305
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000306 for exception in Signals:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000307 self.context.traps[exception] = 1 #Catch these bugs...
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000308 for exception in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000309 self.context.traps[exception] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000310 for i, val in enumerate(valstemp):
311 if val.count("'") % 2 == 1:
312 quote = 1 - quote
313 if quote:
314 conglomerate = conglomerate + ' ' + val
315 continue
316 else:
317 val = conglomerate + val
318 conglomerate = ''
319 v = FixQuotes(val)
320 if fname in ('to_sci_string', 'to_eng_string'):
321 if EXTENDEDERRORTEST:
322 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000323 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000324 try:
325 funct(self.context.create_decimal(v))
326 except error:
327 pass
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000328 except Signals, e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000329 self.fail("Raised %s in %s when %s disabled" % \
330 (e, s, error))
331 else:
332 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000333 self.context.traps[error] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000334 v = self.context.create_decimal(v)
335 else:
Facundo Batista353750c2007-09-13 18:13:15 +0000336 v = Decimal(v, self.context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000337 vals.append(v)
338
339 ans = FixQuotes(ans)
340
341 if EXTENDEDERRORTEST and fname not in ('to_sci_string', 'to_eng_string'):
342 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000343 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000344 try:
345 funct(*vals)
346 except error:
347 pass
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000348 except Signals, e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000349 self.fail("Raised %s in %s when %s disabled" % \
350 (e, s, error))
351 else:
352 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000353 self.context.traps[error] = 0
Mark Dickinson4f96f5f2010-05-04 14:25:50 +0000354
355 # as above, but add traps cumulatively, to check precedence
356 ordered_errors = [e for e in OrderedSignals if e in theirexceptions]
357 for error in ordered_errors:
358 self.context.traps[error] = 1
359 try:
360 funct(*vals)
361 except error:
362 pass
363 except Signals, e:
364 self.fail("Raised %s in %s; expected %s" %
365 (type(e), s, error))
366 else:
367 self.fail("Did not raise %s in %s" % (error, s))
368 # reset traps
369 for error in ordered_errors:
370 self.context.traps[error] = 0
371
372
Facundo Batista353750c2007-09-13 18:13:15 +0000373 if DEBUG:
374 print "--", self.context
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000375 try:
376 result = str(funct(*vals))
Facundo Batista1a191df2007-10-02 17:01:24 +0000377 if fname in LOGICAL_FUNCTIONS:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000378 result = str(int(eval(result))) # 'True', 'False' -> '1', '0'
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000379 except Signals, error:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000380 self.fail("Raised %s in %s" % (error, s))
381 except: #Catch any error long enough to state the test case.
382 print "ERROR:", s
383 raise
384
385 myexceptions = self.getexceptions()
Raymond Hettingerbf440692004-07-10 14:14:37 +0000386 self.context.clear_flags()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000387
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000388 self.assertEqual(result, ans,
389 'Incorrect answer for ' + s + ' -- got ' + result)
Florent Xicluna8f43cec2010-03-21 10:51:40 +0000390 self.assertItemsEqual(myexceptions, theirexceptions,
Facundo Batista353750c2007-09-13 18:13:15 +0000391 'Incorrect flags set in ' + s + ' -- got ' + str(myexceptions))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000392
393 def getexceptions(self):
Raymond Hettingerf63ba432004-08-17 05:42:09 +0000394 return [e for e in Signals if self.context.flags[e]]
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000395
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000396 def change_precision(self, prec):
397 self.context.prec = prec
398 def change_rounding_method(self, rounding):
399 self.context.rounding = rounding
400 def change_min_exponent(self, exp):
401 self.context.Emin = exp
402 def change_max_exponent(self, exp):
403 self.context.Emax = exp
404 def change_clamp(self, clamp):
405 self.context._clamp = clamp
406
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000407
408
409# The following classes test the behaviour of Decimal according to PEP 327
410
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000411class DecimalExplicitConstructionTest(unittest.TestCase):
412 '''Unit tests for Explicit Construction cases of Decimal.'''
413
414 def test_explicit_empty(self):
415 self.assertEqual(Decimal(), Decimal("0"))
416
417 def test_explicit_from_None(self):
418 self.assertRaises(TypeError, Decimal, None)
419
420 def test_explicit_from_int(self):
421
422 #positive
423 d = Decimal(45)
424 self.assertEqual(str(d), '45')
425
426 #very large positive
427 d = Decimal(500000123)
428 self.assertEqual(str(d), '500000123')
429
430 #negative
431 d = Decimal(-45)
432 self.assertEqual(str(d), '-45')
433
434 #zero
435 d = Decimal(0)
436 self.assertEqual(str(d), '0')
437
438 def test_explicit_from_string(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000439
440 #empty
441 self.assertEqual(str(Decimal('')), 'NaN')
442
443 #int
444 self.assertEqual(str(Decimal('45')), '45')
445
446 #float
447 self.assertEqual(str(Decimal('45.34')), '45.34')
448
449 #engineer notation
450 self.assertEqual(str(Decimal('45e2')), '4.5E+3')
451
452 #just not a number
453 self.assertEqual(str(Decimal('ugly')), 'NaN')
454
Mark Dickinson59bc20b2008-01-12 01:56:00 +0000455 #leading and trailing whitespace permitted
456 self.assertEqual(str(Decimal('1.3E4 \n')), '1.3E+4')
457 self.assertEqual(str(Decimal(' -7.89')), '-7.89')
458
Mark Dickinson8e85ffa2008-03-25 18:47:59 +0000459 #unicode strings should be permitted
460 self.assertEqual(str(Decimal(u'0E-017')), '0E-17')
461 self.assertEqual(str(Decimal(u'45')), '45')
462 self.assertEqual(str(Decimal(u'-Inf')), '-Infinity')
463 self.assertEqual(str(Decimal(u'NaN123')), 'NaN123')
464
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000465 def test_explicit_from_tuples(self):
466
467 #zero
468 d = Decimal( (0, (0,), 0) )
469 self.assertEqual(str(d), '0')
470
471 #int
472 d = Decimal( (1, (4, 5), 0) )
473 self.assertEqual(str(d), '-45')
474
475 #float
476 d = Decimal( (0, (4, 5, 3, 4), -2) )
477 self.assertEqual(str(d), '45.34')
478
479 #weird
480 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
481 self.assertEqual(str(d), '-4.34913534E-17')
482
483 #wrong number of items
484 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1)) )
485
486 #bad sign
487 self.assertRaises(ValueError, Decimal, (8, (4, 3, 4, 9, 1), 2) )
Facundo Batista9b5e2312007-10-19 19:25:57 +0000488 self.assertRaises(ValueError, Decimal, (0., (4, 3, 4, 9, 1), 2) )
489 self.assertRaises(ValueError, Decimal, (Decimal(1), (4, 3, 4, 9, 1), 2))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000490
491 #bad exp
492 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 'wrong!') )
Facundo Batista9b5e2312007-10-19 19:25:57 +0000493 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 0.) )
494 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), '1') )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000495
496 #bad coefficients
497 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, None, 1), 2) )
498 self.assertRaises(ValueError, Decimal, (1, (4, -3, 4, 9, 1), 2) )
Facundo Batista9b5e2312007-10-19 19:25:57 +0000499 self.assertRaises(ValueError, Decimal, (1, (4, 10, 4, 9, 1), 2) )
Facundo Batista72bc54f2007-11-23 17:59:00 +0000500 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 'a', 1), 2) )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000501
Antoine Pitrou6032c252010-03-30 18:49:45 +0000502 def test_explicit_from_bool(self):
503 self.assertIs(bool(Decimal(0)), False)
504 self.assertIs(bool(Decimal(1)), True)
505 self.assertEqual(Decimal(False), Decimal(0))
506 self.assertEqual(Decimal(True), Decimal(1))
507
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000508 def test_explicit_from_Decimal(self):
509
510 #positive
511 d = Decimal(45)
512 e = Decimal(d)
513 self.assertEqual(str(e), '45')
514 self.assertNotEqual(id(d), id(e))
515
516 #very large positive
517 d = Decimal(500000123)
518 e = Decimal(d)
519 self.assertEqual(str(e), '500000123')
520 self.assertNotEqual(id(d), id(e))
521
522 #negative
523 d = Decimal(-45)
524 e = Decimal(d)
525 self.assertEqual(str(e), '-45')
526 self.assertNotEqual(id(d), id(e))
527
528 #zero
529 d = Decimal(0)
530 e = Decimal(d)
531 self.assertEqual(str(e), '0')
532 self.assertNotEqual(id(d), id(e))
533
Raymond Hettingered171ab2010-04-02 18:39:24 +0000534 @requires_IEEE_754
535 def test_explicit_from_float(self):
536 r = Decimal(0.1)
537 self.assertEqual(type(r), Decimal)
538 self.assertEqual(str(r),
539 '0.1000000000000000055511151231257827021181583404541015625')
540 self.assertTrue(Decimal(float('nan')).is_qnan())
541 self.assertTrue(Decimal(float('inf')).is_infinite())
542 self.assertTrue(Decimal(float('-inf')).is_infinite())
543 self.assertEqual(str(Decimal(float('nan'))),
544 str(Decimal('NaN')))
545 self.assertEqual(str(Decimal(float('inf'))),
546 str(Decimal('Infinity')))
547 self.assertEqual(str(Decimal(float('-inf'))),
548 str(Decimal('-Infinity')))
549 self.assertEqual(str(Decimal(float('-0.0'))),
550 str(Decimal('-0')))
551 for i in range(200):
552 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
553 self.assertEqual(x, float(Decimal(x))) # roundtrip
554
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000555 def test_explicit_context_create_decimal(self):
556
557 nc = copy.copy(getcontext())
558 nc.prec = 3
559
560 # empty
Raymond Hettingerfed52962004-07-14 15:41:57 +0000561 d = Decimal()
562 self.assertEqual(str(d), '0')
563 d = nc.create_decimal()
564 self.assertEqual(str(d), '0')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000565
566 # from None
567 self.assertRaises(TypeError, nc.create_decimal, None)
568
569 # from int
570 d = nc.create_decimal(456)
Ezio Melottib0f5adc2010-01-24 16:58:36 +0000571 self.assertIsInstance(d, Decimal)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000572 self.assertEqual(nc.create_decimal(45678),
573 nc.create_decimal('457E+2'))
574
575 # from string
576 d = Decimal('456789')
577 self.assertEqual(str(d), '456789')
578 d = nc.create_decimal('456789')
579 self.assertEqual(str(d), '4.57E+5')
Mark Dickinson59bc20b2008-01-12 01:56:00 +0000580 # leading and trailing whitespace should result in a NaN;
581 # spaces are already checked in Cowlishaw's test-suite, so
582 # here we just check that a trailing newline results in a NaN
583 self.assertEqual(str(nc.create_decimal('3.14\n')), 'NaN')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000584
585 # from tuples
586 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
587 self.assertEqual(str(d), '-4.34913534E-17')
588 d = nc.create_decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
589 self.assertEqual(str(d), '-4.35E-17')
590
591 # from Decimal
592 prevdec = Decimal(500000123)
593 d = Decimal(prevdec)
594 self.assertEqual(str(d), '500000123')
595 d = nc.create_decimal(prevdec)
596 self.assertEqual(str(d), '5.00E+8')
597
Mark Dickinson4326ad82009-08-02 10:59:36 +0000598 def test_unicode_digits(self):
599 test_values = {
600 u'\uff11': '1',
601 u'\u0660.\u0660\u0663\u0667\u0662e-\u0663' : '0.0000372',
602 u'-nan\u0c68\u0c6a\u0c66\u0c66' : '-NaN2400',
603 }
604 for input, expected in test_values.items():
605 self.assertEqual(str(Decimal(input)), expected)
606
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000607
608class DecimalImplicitConstructionTest(unittest.TestCase):
609 '''Unit tests for Implicit Construction cases of Decimal.'''
610
611 def test_implicit_from_None(self):
612 self.assertRaises(TypeError, eval, 'Decimal(5) + None', globals())
613
614 def test_implicit_from_int(self):
615 #normal
616 self.assertEqual(str(Decimal(5) + 45), '50')
617 #exceeding precision
618 self.assertEqual(Decimal(5) + 123456789000, Decimal(123456789000))
619
620 def test_implicit_from_string(self):
621 self.assertRaises(TypeError, eval, 'Decimal(5) + "3"', globals())
622
623 def test_implicit_from_float(self):
624 self.assertRaises(TypeError, eval, 'Decimal(5) + 2.2', globals())
625
626 def test_implicit_from_Decimal(self):
627 self.assertEqual(Decimal(5) + Decimal(45), Decimal(50))
628
Raymond Hettinger267b8682005-03-27 10:47:39 +0000629 def test_rop(self):
630 # Allow other classes to be trained to interact with Decimals
631 class E:
632 def __divmod__(self, other):
633 return 'divmod ' + str(other)
634 def __rdivmod__(self, other):
635 return str(other) + ' rdivmod'
636 def __lt__(self, other):
637 return 'lt ' + str(other)
638 def __gt__(self, other):
639 return 'gt ' + str(other)
640 def __le__(self, other):
641 return 'le ' + str(other)
642 def __ge__(self, other):
643 return 'ge ' + str(other)
644 def __eq__(self, other):
645 return 'eq ' + str(other)
646 def __ne__(self, other):
647 return 'ne ' + str(other)
648
649 self.assertEqual(divmod(E(), Decimal(10)), 'divmod 10')
650 self.assertEqual(divmod(Decimal(10), E()), '10 rdivmod')
651 self.assertEqual(eval('Decimal(10) < E()'), 'gt 10')
652 self.assertEqual(eval('Decimal(10) > E()'), 'lt 10')
653 self.assertEqual(eval('Decimal(10) <= E()'), 'ge 10')
654 self.assertEqual(eval('Decimal(10) >= E()'), 'le 10')
655 self.assertEqual(eval('Decimal(10) == E()'), 'eq 10')
656 self.assertEqual(eval('Decimal(10) != E()'), 'ne 10')
657
658 # insert operator methods and then exercise them
Georg Brandl96c3f7f2006-03-28 08:06:35 +0000659 oplist = [
660 ('+', '__add__', '__radd__'),
661 ('-', '__sub__', '__rsub__'),
662 ('*', '__mul__', '__rmul__'),
663 ('%', '__mod__', '__rmod__'),
664 ('//', '__floordiv__', '__rfloordiv__'),
665 ('**', '__pow__', '__rpow__')
666 ]
Florent Xicluna8f43cec2010-03-21 10:51:40 +0000667 with check_py3k_warnings():
668 if 1 / 2 == 0:
669 # testing with classic division, so add __div__
670 oplist.append(('/', '__div__', '__rdiv__'))
671 else:
672 # testing with -Qnew, so add __truediv__
673 oplist.append(('/', '__truediv__', '__rtruediv__'))
Anthony Baxter4ef3a232006-03-30 12:59:11 +0000674
Georg Brandl96c3f7f2006-03-28 08:06:35 +0000675 for sym, lop, rop in oplist:
Raymond Hettinger267b8682005-03-27 10:47:39 +0000676 setattr(E, lop, lambda self, other: 'str' + lop + str(other))
677 setattr(E, rop, lambda self, other: str(other) + rop + 'str')
678 self.assertEqual(eval('E()' + sym + 'Decimal(10)'),
679 'str' + lop + '10')
680 self.assertEqual(eval('Decimal(10)' + sym + 'E()'),
681 '10' + rop + 'str')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000682
Mark Dickinson277859d2009-03-17 23:03:46 +0000683
Mark Dickinson1ddf1d82008-02-29 02:16:37 +0000684class DecimalFormatTest(unittest.TestCase):
685 '''Unit tests for the format function.'''
686 def test_formatting(self):
687 # triples giving a format, a Decimal, and the expected result
688 test_values = [
689 ('e', '0E-15', '0e-15'),
690 ('e', '2.3E-15', '2.3e-15'),
691 ('e', '2.30E+2', '2.30e+2'), # preserve significant zeros
692 ('e', '2.30000E-15', '2.30000e-15'),
693 ('e', '1.23456789123456789e40', '1.23456789123456789e+40'),
694 ('e', '1.5', '1.5e+0'),
695 ('e', '0.15', '1.5e-1'),
696 ('e', '0.015', '1.5e-2'),
697 ('e', '0.0000000000015', '1.5e-12'),
698 ('e', '15.0', '1.50e+1'),
699 ('e', '-15', '-1.5e+1'),
700 ('e', '0', '0e+0'),
701 ('e', '0E1', '0e+1'),
702 ('e', '0.0', '0e-1'),
703 ('e', '0.00', '0e-2'),
704 ('.6e', '0E-15', '0.000000e-9'),
705 ('.6e', '0', '0.000000e+6'),
706 ('.6e', '9.999999', '9.999999e+0'),
707 ('.6e', '9.9999999', '1.000000e+1'),
708 ('.6e', '-1.23e5', '-1.230000e+5'),
709 ('.6e', '1.23456789e-3', '1.234568e-3'),
710 ('f', '0', '0'),
711 ('f', '0.0', '0.0'),
712 ('f', '0E-2', '0.00'),
713 ('f', '0.00E-8', '0.0000000000'),
714 ('f', '0E1', '0'), # loses exponent information
715 ('f', '3.2E1', '32'),
716 ('f', '3.2E2', '320'),
717 ('f', '3.20E2', '320'),
718 ('f', '3.200E2', '320.0'),
719 ('f', '3.2E-6', '0.0000032'),
720 ('.6f', '0E-15', '0.000000'), # all zeros treated equally
721 ('.6f', '0E1', '0.000000'),
722 ('.6f', '0', '0.000000'),
723 ('.0f', '0', '0'), # no decimal point
724 ('.0f', '0e-2', '0'),
725 ('.0f', '3.14159265', '3'),
726 ('.1f', '3.14159265', '3.1'),
727 ('.4f', '3.14159265', '3.1416'),
728 ('.6f', '3.14159265', '3.141593'),
729 ('.7f', '3.14159265', '3.1415926'), # round-half-even!
730 ('.8f', '3.14159265', '3.14159265'),
731 ('.9f', '3.14159265', '3.141592650'),
732
733 ('g', '0', '0'),
734 ('g', '0.0', '0.0'),
735 ('g', '0E1', '0e+1'),
736 ('G', '0E1', '0E+1'),
737 ('g', '0E-5', '0.00000'),
738 ('g', '0E-6', '0.000000'),
739 ('g', '0E-7', '0e-7'),
740 ('g', '-0E2', '-0e+2'),
741 ('.0g', '3.14159265', '3'), # 0 sig fig -> 1 sig fig
742 ('.1g', '3.14159265', '3'),
743 ('.2g', '3.14159265', '3.1'),
744 ('.5g', '3.14159265', '3.1416'),
745 ('.7g', '3.14159265', '3.141593'),
746 ('.8g', '3.14159265', '3.1415926'), # round-half-even!
747 ('.9g', '3.14159265', '3.14159265'),
748 ('.10g', '3.14159265', '3.14159265'), # don't pad
749
750 ('%', '0E1', '0%'),
751 ('%', '0E0', '0%'),
752 ('%', '0E-1', '0%'),
753 ('%', '0E-2', '0%'),
754 ('%', '0E-3', '0.0%'),
755 ('%', '0E-4', '0.00%'),
756
757 ('.3%', '0', '0.000%'), # all zeros treated equally
758 ('.3%', '0E10', '0.000%'),
759 ('.3%', '0E-10', '0.000%'),
760 ('.3%', '2.34', '234.000%'),
761 ('.3%', '1.234567', '123.457%'),
762 ('.0%', '1.23', '123%'),
763
764 ('e', 'NaN', 'NaN'),
765 ('f', '-NaN123', '-NaN123'),
766 ('+g', 'NaN456', '+NaN456'),
767 ('.3e', 'Inf', 'Infinity'),
768 ('.16f', '-Inf', '-Infinity'),
769 ('.0g', '-sNaN', '-sNaN'),
770
771 ('', '1.00', '1.00'),
Mark Dickinsonb065e522009-03-17 18:01:03 +0000772
Mark Dickinson277859d2009-03-17 23:03:46 +0000773 # test alignment and padding
Mark Dickinson5cfa8042009-09-08 20:20:19 +0000774 ('6', '123', ' 123'),
Mark Dickinsonb065e522009-03-17 18:01:03 +0000775 ('<6', '123', '123 '),
776 ('>6', '123', ' 123'),
777 ('^6', '123', ' 123 '),
778 ('=+6', '123', '+ 123'),
Mark Dickinson277859d2009-03-17 23:03:46 +0000779 ('#<10', 'NaN', 'NaN#######'),
780 ('#<10', '-4.3', '-4.3######'),
781 ('#<+10', '0.0130', '+0.0130###'),
782 ('#< 10', '0.0130', ' 0.0130###'),
783 ('@>10', '-Inf', '@-Infinity'),
784 ('#>5', '-Inf', '-Infinity'),
785 ('?^5', '123', '?123?'),
786 ('%^6', '123', '%123%%'),
787 (' ^6', '-45.6', '-45.6 '),
788 ('/=10', '-45.6', '-/////45.6'),
789 ('/=+10', '45.6', '+/////45.6'),
790 ('/= 10', '45.6', ' /////45.6'),
791
792 # thousands separator
793 (',', '1234567', '1,234,567'),
794 (',', '123456', '123,456'),
795 (',', '12345', '12,345'),
796 (',', '1234', '1,234'),
797 (',', '123', '123'),
798 (',', '12', '12'),
799 (',', '1', '1'),
800 (',', '0', '0'),
801 (',', '-1234567', '-1,234,567'),
802 (',', '-123456', '-123,456'),
803 ('7,', '123456', '123,456'),
Mark Dickinson5cfa8042009-09-08 20:20:19 +0000804 ('8,', '123456', ' 123,456'),
Mark Dickinson277859d2009-03-17 23:03:46 +0000805 ('08,', '123456', '0,123,456'), # special case: extra 0 needed
806 ('+08,', '123456', '+123,456'), # but not if there's a sign
807 (' 08,', '123456', ' 123,456'),
808 ('08,', '-123456', '-123,456'),
809 ('+09,', '123456', '+0,123,456'),
810 # ... with fractional part...
811 ('07,', '1234.56', '1,234.56'),
812 ('08,', '1234.56', '1,234.56'),
813 ('09,', '1234.56', '01,234.56'),
814 ('010,', '1234.56', '001,234.56'),
815 ('011,', '1234.56', '0,001,234.56'),
816 ('012,', '1234.56', '0,001,234.56'),
817 ('08,.1f', '1234.5', '01,234.5'),
818 # no thousands separators in fraction part
819 (',', '1.23456789', '1.23456789'),
820 (',%', '123.456789', '12,345.6789%'),
821 (',e', '123456', '1.23456e+5'),
822 (',E', '123456', '1.23456E+5'),
Mark Dickinson491ea552009-09-07 16:17:41 +0000823
824 # issue 6850
825 ('a=-7.0', '0.12345', 'aaaa0.1'),
Mark Dickinson1ddf1d82008-02-29 02:16:37 +0000826 ]
827 for fmt, d, result in test_values:
828 self.assertEqual(format(Decimal(d), fmt), result)
829
Mark Dickinson277859d2009-03-17 23:03:46 +0000830 def test_n_format(self):
831 try:
832 from locale import CHAR_MAX
833 except ImportError:
Zachary Ware1f702212013-12-10 14:09:20 -0600834 self.skipTest('locale.CHAR_MAX not available')
Mark Dickinson277859d2009-03-17 23:03:46 +0000835
836 # Set up some localeconv-like dictionaries
837 en_US = {
838 'decimal_point' : '.',
839 'grouping' : [3, 3, 0],
840 'thousands_sep': ','
841 }
842
843 fr_FR = {
844 'decimal_point' : ',',
845 'grouping' : [CHAR_MAX],
846 'thousands_sep' : ''
847 }
848
849 ru_RU = {
850 'decimal_point' : ',',
851 'grouping' : [3, 3, 0],
852 'thousands_sep' : ' '
853 }
854
855 crazy = {
856 'decimal_point' : '&',
857 'grouping' : [1, 4, 2, CHAR_MAX],
858 'thousands_sep' : '-'
859 }
860
861
862 def get_fmt(x, locale, fmt='n'):
863 return Decimal.__format__(Decimal(x), fmt, _localeconv=locale)
864
865 self.assertEqual(get_fmt(Decimal('12.7'), en_US), '12.7')
866 self.assertEqual(get_fmt(Decimal('12.7'), fr_FR), '12,7')
867 self.assertEqual(get_fmt(Decimal('12.7'), ru_RU), '12,7')
868 self.assertEqual(get_fmt(Decimal('12.7'), crazy), '1-2&7')
869
870 self.assertEqual(get_fmt(123456789, en_US), '123,456,789')
871 self.assertEqual(get_fmt(123456789, fr_FR), '123456789')
872 self.assertEqual(get_fmt(123456789, ru_RU), '123 456 789')
873 self.assertEqual(get_fmt(1234567890123, crazy), '123456-78-9012-3')
874
875 self.assertEqual(get_fmt(123456789, en_US, '.6n'), '1.23457e+8')
876 self.assertEqual(get_fmt(123456789, fr_FR, '.6n'), '1,23457e+8')
877 self.assertEqual(get_fmt(123456789, ru_RU, '.6n'), '1,23457e+8')
878 self.assertEqual(get_fmt(123456789, crazy, '.6n'), '1&23457e+8')
879
Mark Dickinsonb14514a2009-03-18 08:22:51 +0000880 # zero padding
881 self.assertEqual(get_fmt(1234, fr_FR, '03n'), '1234')
882 self.assertEqual(get_fmt(1234, fr_FR, '04n'), '1234')
883 self.assertEqual(get_fmt(1234, fr_FR, '05n'), '01234')
884 self.assertEqual(get_fmt(1234, fr_FR, '06n'), '001234')
885
886 self.assertEqual(get_fmt(12345, en_US, '05n'), '12,345')
887 self.assertEqual(get_fmt(12345, en_US, '06n'), '12,345')
888 self.assertEqual(get_fmt(12345, en_US, '07n'), '012,345')
889 self.assertEqual(get_fmt(12345, en_US, '08n'), '0,012,345')
890 self.assertEqual(get_fmt(12345, en_US, '09n'), '0,012,345')
891 self.assertEqual(get_fmt(12345, en_US, '010n'), '00,012,345')
892
893 self.assertEqual(get_fmt(123456, crazy, '06n'), '1-2345-6')
894 self.assertEqual(get_fmt(123456, crazy, '07n'), '1-2345-6')
895 self.assertEqual(get_fmt(123456, crazy, '08n'), '1-2345-6')
896 self.assertEqual(get_fmt(123456, crazy, '09n'), '01-2345-6')
897 self.assertEqual(get_fmt(123456, crazy, '010n'), '0-01-2345-6')
898 self.assertEqual(get_fmt(123456, crazy, '011n'), '0-01-2345-6')
899 self.assertEqual(get_fmt(123456, crazy, '012n'), '00-01-2345-6')
900 self.assertEqual(get_fmt(123456, crazy, '013n'), '000-01-2345-6')
901
Mark Dickinson277859d2009-03-17 23:03:46 +0000902
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000903class DecimalArithmeticOperatorsTest(unittest.TestCase):
904 '''Unit tests for all arithmetic operators, binary and unary.'''
905
906 def test_addition(self):
907
908 d1 = Decimal('-11.1')
909 d2 = Decimal('22.2')
910
911 #two Decimals
912 self.assertEqual(d1+d2, Decimal('11.1'))
913 self.assertEqual(d2+d1, Decimal('11.1'))
914
915 #with other type, left
916 c = d1 + 5
917 self.assertEqual(c, Decimal('-6.1'))
918 self.assertEqual(type(c), type(d1))
919
920 #with other type, right
921 c = 5 + d1
922 self.assertEqual(c, Decimal('-6.1'))
923 self.assertEqual(type(c), type(d1))
924
925 #inline with decimal
926 d1 += d2
927 self.assertEqual(d1, Decimal('11.1'))
928
929 #inline with other type
930 d1 += 5
931 self.assertEqual(d1, Decimal('16.1'))
932
933 def test_subtraction(self):
934
935 d1 = Decimal('-11.1')
936 d2 = Decimal('22.2')
937
938 #two Decimals
939 self.assertEqual(d1-d2, Decimal('-33.3'))
940 self.assertEqual(d2-d1, Decimal('33.3'))
941
942 #with other type, left
943 c = d1 - 5
944 self.assertEqual(c, Decimal('-16.1'))
945 self.assertEqual(type(c), type(d1))
946
947 #with other type, right
948 c = 5 - d1
949 self.assertEqual(c, Decimal('16.1'))
950 self.assertEqual(type(c), type(d1))
951
952 #inline with decimal
953 d1 -= d2
954 self.assertEqual(d1, Decimal('-33.3'))
955
956 #inline with other type
957 d1 -= 5
958 self.assertEqual(d1, Decimal('-38.3'))
959
960 def test_multiplication(self):
961
962 d1 = Decimal('-5')
963 d2 = Decimal('3')
964
965 #two Decimals
966 self.assertEqual(d1*d2, Decimal('-15'))
967 self.assertEqual(d2*d1, Decimal('-15'))
968
969 #with other type, left
970 c = d1 * 5
971 self.assertEqual(c, Decimal('-25'))
972 self.assertEqual(type(c), type(d1))
973
974 #with other type, right
975 c = 5 * d1
976 self.assertEqual(c, Decimal('-25'))
977 self.assertEqual(type(c), type(d1))
978
979 #inline with decimal
980 d1 *= d2
981 self.assertEqual(d1, Decimal('-15'))
982
983 #inline with other type
984 d1 *= 5
985 self.assertEqual(d1, Decimal('-75'))
986
987 def test_division(self):
988
989 d1 = Decimal('-5')
990 d2 = Decimal('2')
991
992 #two Decimals
993 self.assertEqual(d1/d2, Decimal('-2.5'))
994 self.assertEqual(d2/d1, Decimal('-0.4'))
995
996 #with other type, left
997 c = d1 / 4
998 self.assertEqual(c, Decimal('-1.25'))
999 self.assertEqual(type(c), type(d1))
1000
1001 #with other type, right
1002 c = 4 / d1
1003 self.assertEqual(c, Decimal('-0.8'))
1004 self.assertEqual(type(c), type(d1))
1005
1006 #inline with decimal
1007 d1 /= d2
1008 self.assertEqual(d1, Decimal('-2.5'))
1009
1010 #inline with other type
1011 d1 /= 4
1012 self.assertEqual(d1, Decimal('-0.625'))
1013
1014 def test_floor_division(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001015
1016 d1 = Decimal('5')
1017 d2 = Decimal('2')
1018
1019 #two Decimals
1020 self.assertEqual(d1//d2, Decimal('2'))
1021 self.assertEqual(d2//d1, Decimal('0'))
1022
1023 #with other type, left
1024 c = d1 // 4
1025 self.assertEqual(c, Decimal('1'))
1026 self.assertEqual(type(c), type(d1))
1027
1028 #with other type, right
1029 c = 7 // d1
1030 self.assertEqual(c, Decimal('1'))
1031 self.assertEqual(type(c), type(d1))
1032
1033 #inline with decimal
1034 d1 //= d2
1035 self.assertEqual(d1, Decimal('2'))
1036
1037 #inline with other type
1038 d1 //= 2
1039 self.assertEqual(d1, Decimal('1'))
1040
1041 def test_powering(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001042
1043 d1 = Decimal('5')
1044 d2 = Decimal('2')
1045
1046 #two Decimals
1047 self.assertEqual(d1**d2, Decimal('25'))
1048 self.assertEqual(d2**d1, Decimal('32'))
1049
1050 #with other type, left
1051 c = d1 ** 4
1052 self.assertEqual(c, Decimal('625'))
1053 self.assertEqual(type(c), type(d1))
1054
1055 #with other type, right
1056 c = 7 ** d1
1057 self.assertEqual(c, Decimal('16807'))
1058 self.assertEqual(type(c), type(d1))
1059
1060 #inline with decimal
1061 d1 **= d2
1062 self.assertEqual(d1, Decimal('25'))
1063
1064 #inline with other type
1065 d1 **= 4
1066 self.assertEqual(d1, Decimal('390625'))
1067
1068 def test_module(self):
1069
1070 d1 = Decimal('5')
1071 d2 = Decimal('2')
1072
1073 #two Decimals
1074 self.assertEqual(d1%d2, Decimal('1'))
1075 self.assertEqual(d2%d1, Decimal('2'))
1076
1077 #with other type, left
1078 c = d1 % 4
1079 self.assertEqual(c, Decimal('1'))
1080 self.assertEqual(type(c), type(d1))
1081
1082 #with other type, right
1083 c = 7 % d1
1084 self.assertEqual(c, Decimal('2'))
1085 self.assertEqual(type(c), type(d1))
1086
1087 #inline with decimal
1088 d1 %= d2
1089 self.assertEqual(d1, Decimal('1'))
1090
1091 #inline with other type
1092 d1 %= 4
1093 self.assertEqual(d1, Decimal('1'))
1094
1095 def test_floor_div_module(self):
1096
1097 d1 = Decimal('5')
1098 d2 = Decimal('2')
1099
1100 #two Decimals
1101 (p, q) = divmod(d1, d2)
1102 self.assertEqual(p, Decimal('2'))
1103 self.assertEqual(q, Decimal('1'))
1104 self.assertEqual(type(p), type(d1))
1105 self.assertEqual(type(q), type(d1))
1106
1107 #with other type, left
1108 (p, q) = divmod(d1, 4)
1109 self.assertEqual(p, Decimal('1'))
1110 self.assertEqual(q, Decimal('1'))
1111 self.assertEqual(type(p), type(d1))
1112 self.assertEqual(type(q), type(d1))
1113
1114 #with other type, right
1115 (p, q) = divmod(7, d1)
1116 self.assertEqual(p, Decimal('1'))
1117 self.assertEqual(q, Decimal('2'))
1118 self.assertEqual(type(p), type(d1))
1119 self.assertEqual(type(q), type(d1))
1120
1121 def test_unary_operators(self):
1122 self.assertEqual(+Decimal(45), Decimal(+45)) # +
1123 self.assertEqual(-Decimal(45), Decimal(-45)) # -
1124 self.assertEqual(abs(Decimal(45)), abs(Decimal(-45))) # abs
1125
Mark Dickinson2fc92632008-02-06 22:10:50 +00001126 def test_nan_comparisons(self):
Mark Dickinsone096e822010-04-02 10:17:07 +00001127 # comparisons involving signaling nans signal InvalidOperation
1128
1129 # order comparisons (<, <=, >, >=) involving only quiet nans
1130 # also signal InvalidOperation
1131
1132 # equality comparisons (==, !=) involving only quiet nans
1133 # don't signal, but return False or True respectively.
1134
Mark Dickinson2fc92632008-02-06 22:10:50 +00001135 n = Decimal('NaN')
1136 s = Decimal('sNaN')
1137 i = Decimal('Inf')
1138 f = Decimal('2')
Mark Dickinsone096e822010-04-02 10:17:07 +00001139
1140 qnan_pairs = (n, n), (n, i), (i, n), (n, f), (f, n)
1141 snan_pairs = (s, n), (n, s), (s, i), (i, s), (s, f), (f, s), (s, s)
1142 order_ops = operator.lt, operator.le, operator.gt, operator.ge
1143 equality_ops = operator.eq, operator.ne
1144
1145 # results when InvalidOperation is not trapped
1146 for x, y in qnan_pairs + snan_pairs:
1147 for op in order_ops + equality_ops:
1148 got = op(x, y)
1149 expected = True if op is operator.ne else False
1150 self.assertIs(expected, got,
1151 "expected {0!r} for operator.{1}({2!r}, {3!r}); "
1152 "got {4!r}".format(
1153 expected, op.__name__, x, y, got))
1154
1155 # repeat the above, but this time trap the InvalidOperation
1156 with localcontext() as ctx:
1157 ctx.traps[InvalidOperation] = 1
1158
1159 for x, y in qnan_pairs:
1160 for op in equality_ops:
1161 got = op(x, y)
1162 expected = True if op is operator.ne else False
1163 self.assertIs(expected, got,
1164 "expected {0!r} for "
1165 "operator.{1}({2!r}, {3!r}); "
1166 "got {4!r}".format(
1167 expected, op.__name__, x, y, got))
1168
1169 for x, y in snan_pairs:
1170 for op in equality_ops:
1171 self.assertRaises(InvalidOperation, operator.eq, x, y)
1172 self.assertRaises(InvalidOperation, operator.ne, x, y)
1173
1174 for x, y in qnan_pairs + snan_pairs:
1175 for op in order_ops:
1176 self.assertRaises(InvalidOperation, op, x, y)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001177
Mark Dickinson6d8effb2010-02-18 14:27:02 +00001178 def test_copy_sign(self):
1179 d = Decimal(1).copy_sign(Decimal(-2))
1180
1181 self.assertEqual(Decimal(1).copy_sign(-2), d)
1182 self.assertRaises(TypeError, Decimal(1).copy_sign, '-2')
1183
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001184# The following are two functions used to test threading in the next class
1185
1186def thfunc1(cls):
1187 d1 = Decimal(1)
1188 d3 = Decimal(3)
Facundo Batista64156672008-03-22 02:45:37 +00001189 test1 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001190 cls.synchro.wait()
Facundo Batista64156672008-03-22 02:45:37 +00001191 test2 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001192 cls.finish1.set()
Facundo Batista64156672008-03-22 02:45:37 +00001193
Facundo Batistaee340e52008-05-02 17:39:00 +00001194 cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
1195 cls.assertEqual(test2, Decimal('0.3333333333333333333333333333'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001196
1197def thfunc2(cls):
1198 d1 = Decimal(1)
1199 d3 = Decimal(3)
Facundo Batista64156672008-03-22 02:45:37 +00001200 test1 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001201 thiscontext = getcontext()
1202 thiscontext.prec = 18
Facundo Batista64156672008-03-22 02:45:37 +00001203 test2 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001204 cls.synchro.set()
1205 cls.finish2.set()
Facundo Batista64156672008-03-22 02:45:37 +00001206
Facundo Batistaee340e52008-05-02 17:39:00 +00001207 cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
Facundo Batista64156672008-03-22 02:45:37 +00001208 cls.assertEqual(test2, Decimal('0.333333333333333333'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001209
1210
Zachary Ware1f702212013-12-10 14:09:20 -06001211@unittest.skipUnless(threading, 'threading required')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001212class DecimalUseOfContextTest(unittest.TestCase):
1213 '''Unit tests for Use of Context cases in Decimal.'''
1214
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001215 # Take care executing this test from IDLE, there's an issue in threading
1216 # that hangs IDLE and I couldn't find it
1217
1218 def test_threading(self):
1219 #Test the "threading isolation" of a Context.
1220
1221 self.synchro = threading.Event()
1222 self.finish1 = threading.Event()
1223 self.finish2 = threading.Event()
1224
1225 th1 = threading.Thread(target=thfunc1, args=(self,))
1226 th2 = threading.Thread(target=thfunc2, args=(self,))
1227
1228 th1.start()
1229 th2.start()
1230
1231 self.finish1.wait()
Thomas Woutersb3e6e8c2007-09-19 17:27:29 +00001232 self.finish2.wait()
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001233
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001234
1235class DecimalUsabilityTest(unittest.TestCase):
1236 '''Unit tests for Usability cases of Decimal.'''
1237
1238 def test_comparison_operators(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001239
1240 da = Decimal('23.42')
1241 db = Decimal('23.42')
1242 dc = Decimal('45')
1243
1244 #two Decimals
Ezio Melotti856a3be2010-04-03 14:51:00 +00001245 self.assertGreater(dc, da)
1246 self.assertGreaterEqual(dc, da)
1247 self.assertLess(da, dc)
1248 self.assertLessEqual(da, dc)
1249 self.assertEqual(da, db)
1250 self.assertNotEqual(da, dc)
1251 self.assertLessEqual(da, db)
1252 self.assertGreaterEqual(da, db)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001253 self.assertEqual(cmp(dc,da), 1)
1254 self.assertEqual(cmp(da,dc), -1)
1255 self.assertEqual(cmp(da,db), 0)
1256
1257 #a Decimal and an int
Ezio Melotti856a3be2010-04-03 14:51:00 +00001258 self.assertGreater(dc, 23)
1259 self.assertLess(23, dc)
1260 self.assertEqual(dc, 45)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001261 self.assertEqual(cmp(dc,23), 1)
1262 self.assertEqual(cmp(23,dc), -1)
1263 self.assertEqual(cmp(dc,45), 0)
1264
1265 #a Decimal and uncomparable
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001266 self.assertNotEqual(da, 'ugly')
1267 self.assertNotEqual(da, 32.7)
1268 self.assertNotEqual(da, object())
1269 self.assertNotEqual(da, object)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001270
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001271 # sortable
1272 a = map(Decimal, xrange(100))
1273 b = a[:]
1274 random.shuffle(a)
1275 a.sort()
1276 self.assertEqual(a, b)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001277
Facundo Batista353750c2007-09-13 18:13:15 +00001278 # with None
Florent Xicluna8f43cec2010-03-21 10:51:40 +00001279 with check_py3k_warnings():
1280 self.assertFalse(Decimal(1) < None)
1281 self.assertTrue(Decimal(1) > None)
Facundo Batista353750c2007-09-13 18:13:15 +00001282
Mark Dickinson99d80962010-04-02 08:53:22 +00001283 def test_decimal_float_comparison(self):
1284 da = Decimal('0.25')
1285 db = Decimal('3.0')
Ezio Melotti856a3be2010-04-03 14:51:00 +00001286 self.assertLess(da, 3.0)
1287 self.assertLessEqual(da, 3.0)
1288 self.assertGreater(db, 0.25)
1289 self.assertGreaterEqual(db, 0.25)
1290 self.assertNotEqual(da, 1.5)
1291 self.assertEqual(da, 0.25)
1292 self.assertGreater(3.0, da)
1293 self.assertGreaterEqual(3.0, da)
1294 self.assertLess(0.25, db)
1295 self.assertLessEqual(0.25, db)
1296 self.assertNotEqual(0.25, db)
1297 self.assertEqual(3.0, db)
1298 self.assertNotEqual(0.1, Decimal('0.1'))
Mark Dickinson99d80962010-04-02 08:53:22 +00001299
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001300 def test_copy_and_deepcopy_methods(self):
1301 d = Decimal('43.24')
1302 c = copy.copy(d)
1303 self.assertEqual(id(c), id(d))
1304 dc = copy.deepcopy(d)
1305 self.assertEqual(id(dc), id(d))
1306
1307 def test_hash_method(self):
1308 #just that it's hashable
1309 hash(Decimal(23))
Mark Dickinsonf3eeca12010-04-02 10:35:12 +00001310 hash(Decimal('Infinity'))
1311 hash(Decimal('-Infinity'))
1312 hash(Decimal('nan123'))
1313 hash(Decimal('-NaN'))
Facundo Batista8c202442007-09-19 17:53:25 +00001314
1315 test_values = [Decimal(sign*(2**m + n))
1316 for m in [0, 14, 15, 16, 17, 30, 31,
1317 32, 33, 62, 63, 64, 65, 66]
1318 for n in range(-10, 10)
1319 for sign in [-1, 1]]
1320 test_values.extend([
1321 Decimal("-0"), # zeros
1322 Decimal("0.00"),
1323 Decimal("-0.000"),
1324 Decimal("0E10"),
1325 Decimal("-0E12"),
1326 Decimal("10.0"), # negative exponent
1327 Decimal("-23.00000"),
1328 Decimal("1230E100"), # positive exponent
1329 Decimal("-4.5678E50"),
1330 # a value for which hash(n) != hash(n % (2**64-1))
1331 # in Python pre-2.6
1332 Decimal(2**64 + 2**32 - 1),
1333 # selection of values which fail with the old (before
1334 # version 2.6) long.__hash__
1335 Decimal("1.634E100"),
1336 Decimal("90.697E100"),
1337 Decimal("188.83E100"),
1338 Decimal("1652.9E100"),
1339 Decimal("56531E100"),
1340 ])
1341
1342 # check that hash(d) == hash(int(d)) for integral values
1343 for value in test_values:
1344 self.assertEqual(hash(value), hash(int(value)))
1345
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001346 #the same hash that to an int
1347 self.assertEqual(hash(Decimal(23)), hash(23))
Mark Dickinsonf3eeca12010-04-02 10:35:12 +00001348 self.assertRaises(TypeError, hash, Decimal('sNaN'))
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001349 self.assertTrue(hash(Decimal('Inf')))
1350 self.assertTrue(hash(Decimal('-Inf')))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001351
Mark Dickinson99d80962010-04-02 08:53:22 +00001352 # check that the hashes of a Decimal float match when they
1353 # represent exactly the same values
1354 test_strings = ['inf', '-Inf', '0.0', '-.0e1',
1355 '34.0', '2.5', '112390.625', '-0.515625']
1356 for s in test_strings:
1357 f = float(s)
1358 d = Decimal(s)
1359 self.assertEqual(hash(f), hash(d))
1360
Facundo Batista52b25792008-01-08 12:25:20 +00001361 # check that the value of the hash doesn't depend on the
1362 # current context (issue #1757)
1363 c = getcontext()
1364 old_precision = c.prec
1365 x = Decimal("123456789.1")
1366
1367 c.prec = 6
1368 h1 = hash(x)
1369 c.prec = 10
1370 h2 = hash(x)
1371 c.prec = 16
1372 h3 = hash(x)
1373
1374 self.assertEqual(h1, h2)
1375 self.assertEqual(h1, h3)
1376 c.prec = old_precision
1377
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001378 def test_min_and_max_methods(self):
1379
1380 d1 = Decimal('15.32')
1381 d2 = Decimal('28.5')
1382 l1 = 15
1383 l2 = 28
1384
1385 #between Decimals
Ezio Melotti856a3be2010-04-03 14:51:00 +00001386 self.assertIs(min(d1,d2), d1)
1387 self.assertIs(min(d2,d1), d1)
1388 self.assertIs(max(d1,d2), d2)
1389 self.assertIs(max(d2,d1), d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001390
1391 #between Decimal and long
Ezio Melotti856a3be2010-04-03 14:51:00 +00001392 self.assertIs(min(d1,l2), d1)
1393 self.assertIs(min(l2,d1), d1)
1394 self.assertIs(max(l1,d2), d2)
1395 self.assertIs(max(d2,l1), d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001396
1397 def test_as_nonzero(self):
1398 #as false
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001399 self.assertFalse(Decimal(0))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001400 #as true
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001401 self.assertTrue(Decimal('0.372'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001402
1403 def test_tostring_methods(self):
1404 #Test str and repr methods.
1405
1406 d = Decimal('15.32')
1407 self.assertEqual(str(d), '15.32') # str
Raymond Hettingerabe32372008-02-14 02:41:22 +00001408 self.assertEqual(repr(d), "Decimal('15.32')") # repr
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001409
Mark Dickinson8e85ffa2008-03-25 18:47:59 +00001410 # result type of string methods should be str, not unicode
1411 unicode_inputs = [u'123.4', u'0.5E2', u'Infinity', u'sNaN',
1412 u'-0.0E100', u'-NaN001', u'-Inf']
1413
1414 for u in unicode_inputs:
1415 d = Decimal(u)
1416 self.assertEqual(type(str(d)), str)
1417 self.assertEqual(type(repr(d)), str)
1418 self.assertEqual(type(d.to_eng_string()), str)
1419
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001420 def test_tonum_methods(self):
1421 #Test float, int and long methods.
1422
1423 d1 = Decimal('66')
1424 d2 = Decimal('15.32')
1425
1426 #int
1427 self.assertEqual(int(d1), 66)
1428 self.assertEqual(int(d2), 15)
1429
1430 #long
1431 self.assertEqual(long(d1), 66)
1432 self.assertEqual(long(d2), 15)
1433
1434 #float
1435 self.assertEqual(float(d1), 66)
1436 self.assertEqual(float(d2), 15.32)
1437
Mark Dickinson088cec32012-08-24 20:06:30 +01001438 def test_nan_to_float(self):
1439 # Test conversions of decimal NANs to float.
1440 # See http://bugs.python.org/issue15544
1441 for s in ('nan', 'nan1234', '-nan', '-nan2468'):
1442 f = float(Decimal(s))
1443 self.assertTrue(math.isnan(f))
Mark Dickinson088cec32012-08-24 20:06:30 +01001444
1445 def test_snan_to_float(self):
1446 for s in ('snan', '-snan', 'snan1357', '-snan1234'):
1447 d = Decimal(s)
1448 self.assertRaises(ValueError, float, d)
1449
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001450 def test_eval_round_trip(self):
1451
1452 #with zero
1453 d = Decimal( (0, (0,), 0) )
1454 self.assertEqual(d, eval(repr(d)))
1455
1456 #int
1457 d = Decimal( (1, (4, 5), 0) )
1458 self.assertEqual(d, eval(repr(d)))
1459
1460 #float
1461 d = Decimal( (0, (4, 5, 3, 4), -2) )
1462 self.assertEqual(d, eval(repr(d)))
1463
1464 #weird
1465 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1466 self.assertEqual(d, eval(repr(d)))
1467
1468 def test_as_tuple(self):
1469
1470 #with zero
1471 d = Decimal(0)
1472 self.assertEqual(d.as_tuple(), (0, (0,), 0) )
1473
1474 #int
1475 d = Decimal(-45)
1476 self.assertEqual(d.as_tuple(), (1, (4, 5), 0) )
1477
1478 #complicated string
1479 d = Decimal("-4.34913534E-17")
1480 self.assertEqual(d.as_tuple(), (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1481
1482 #inf
1483 d = Decimal("Infinity")
1484 self.assertEqual(d.as_tuple(), (0, (0,), 'F') )
1485
Facundo Batista9b5e2312007-10-19 19:25:57 +00001486 #leading zeros in coefficient should be stripped
1487 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), -2) )
1488 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), -2) )
1489 d = Decimal( (1, (0, 0, 0), 37) )
1490 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1491 d = Decimal( (1, (), 37) )
1492 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1493
1494 #leading zeros in NaN diagnostic info should be stripped
1495 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), 'n') )
1496 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), 'n') )
1497 d = Decimal( (1, (0, 0, 0), 'N') )
1498 self.assertEqual(d.as_tuple(), (1, (), 'N') )
1499 d = Decimal( (1, (), 'n') )
1500 self.assertEqual(d.as_tuple(), (1, (), 'n') )
1501
1502 #coefficient in infinity should be ignored
1503 d = Decimal( (0, (4, 5, 3, 4), 'F') )
1504 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
1505 d = Decimal( (1, (0, 2, 7, 1), 'F') )
1506 self.assertEqual(d.as_tuple(), (1, (0,), 'F'))
1507
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001508 def test_immutability_operations(self):
1509 # Do operations and check that it didn't change change internal objects.
1510
1511 d1 = Decimal('-25e55')
1512 b1 = Decimal('-25e55')
Facundo Batista353750c2007-09-13 18:13:15 +00001513 d2 = Decimal('33e+33')
1514 b2 = Decimal('33e+33')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001515
1516 def checkSameDec(operation, useOther=False):
1517 if useOther:
1518 eval("d1." + operation + "(d2)")
1519 self.assertEqual(d1._sign, b1._sign)
1520 self.assertEqual(d1._int, b1._int)
1521 self.assertEqual(d1._exp, b1._exp)
1522 self.assertEqual(d2._sign, b2._sign)
1523 self.assertEqual(d2._int, b2._int)
1524 self.assertEqual(d2._exp, b2._exp)
1525 else:
1526 eval("d1." + operation + "()")
1527 self.assertEqual(d1._sign, b1._sign)
1528 self.assertEqual(d1._int, b1._int)
1529 self.assertEqual(d1._exp, b1._exp)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001530
1531 Decimal(d1)
1532 self.assertEqual(d1._sign, b1._sign)
1533 self.assertEqual(d1._int, b1._int)
1534 self.assertEqual(d1._exp, b1._exp)
1535
1536 checkSameDec("__abs__")
1537 checkSameDec("__add__", True)
1538 checkSameDec("__div__", True)
1539 checkSameDec("__divmod__", True)
Mark Dickinson2fc92632008-02-06 22:10:50 +00001540 checkSameDec("__eq__", True)
1541 checkSameDec("__ne__", True)
1542 checkSameDec("__le__", True)
1543 checkSameDec("__lt__", True)
1544 checkSameDec("__ge__", True)
1545 checkSameDec("__gt__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001546 checkSameDec("__float__")
1547 checkSameDec("__floordiv__", True)
1548 checkSameDec("__hash__")
1549 checkSameDec("__int__")
Raymond Hettinger5a053642008-01-24 19:05:29 +00001550 checkSameDec("__trunc__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001551 checkSameDec("__long__")
1552 checkSameDec("__mod__", True)
1553 checkSameDec("__mul__", True)
1554 checkSameDec("__neg__")
1555 checkSameDec("__nonzero__")
1556 checkSameDec("__pos__")
1557 checkSameDec("__pow__", True)
1558 checkSameDec("__radd__", True)
1559 checkSameDec("__rdiv__", True)
1560 checkSameDec("__rdivmod__", True)
1561 checkSameDec("__repr__")
1562 checkSameDec("__rfloordiv__", True)
1563 checkSameDec("__rmod__", True)
1564 checkSameDec("__rmul__", True)
1565 checkSameDec("__rpow__", True)
1566 checkSameDec("__rsub__", True)
1567 checkSameDec("__str__")
1568 checkSameDec("__sub__", True)
1569 checkSameDec("__truediv__", True)
1570 checkSameDec("adjusted")
1571 checkSameDec("as_tuple")
1572 checkSameDec("compare", True)
1573 checkSameDec("max", True)
1574 checkSameDec("min", True)
1575 checkSameDec("normalize")
1576 checkSameDec("quantize", True)
1577 checkSameDec("remainder_near", True)
1578 checkSameDec("same_quantum", True)
1579 checkSameDec("sqrt")
1580 checkSameDec("to_eng_string")
1581 checkSameDec("to_integral")
1582
Facundo Batista6c398da2007-09-17 17:30:13 +00001583 def test_subclassing(self):
1584 # Different behaviours when subclassing Decimal
1585
1586 class MyDecimal(Decimal):
1587 pass
1588
1589 d1 = MyDecimal(1)
1590 d2 = MyDecimal(2)
1591 d = d1 + d2
Ezio Melotti856a3be2010-04-03 14:51:00 +00001592 self.assertIs(type(d), Decimal)
Facundo Batista6c398da2007-09-17 17:30:13 +00001593
1594 d = d1.max(d2)
Ezio Melotti856a3be2010-04-03 14:51:00 +00001595 self.assertIs(type(d), Decimal)
Facundo Batista6c398da2007-09-17 17:30:13 +00001596
Mark Dickinson3b24ccb2008-03-25 14:33:23 +00001597 def test_implicit_context(self):
1598 # Check results when context given implicitly. (Issue 2478)
1599 c = getcontext()
1600 self.assertEqual(str(Decimal(0).sqrt()),
1601 str(c.sqrt(Decimal(0))))
1602
Mark Dickinson0c673122009-10-29 12:04:00 +00001603 def test_conversions_from_int(self):
1604 # Check that methods taking a second Decimal argument will
1605 # always accept an integer in place of a Decimal.
1606 self.assertEqual(Decimal(4).compare(3),
1607 Decimal(4).compare(Decimal(3)))
1608 self.assertEqual(Decimal(4).compare_signal(3),
1609 Decimal(4).compare_signal(Decimal(3)))
1610 self.assertEqual(Decimal(4).compare_total(3),
1611 Decimal(4).compare_total(Decimal(3)))
1612 self.assertEqual(Decimal(4).compare_total_mag(3),
1613 Decimal(4).compare_total_mag(Decimal(3)))
1614 self.assertEqual(Decimal(10101).logical_and(1001),
1615 Decimal(10101).logical_and(Decimal(1001)))
1616 self.assertEqual(Decimal(10101).logical_or(1001),
1617 Decimal(10101).logical_or(Decimal(1001)))
1618 self.assertEqual(Decimal(10101).logical_xor(1001),
1619 Decimal(10101).logical_xor(Decimal(1001)))
1620 self.assertEqual(Decimal(567).max(123),
1621 Decimal(567).max(Decimal(123)))
1622 self.assertEqual(Decimal(567).max_mag(123),
1623 Decimal(567).max_mag(Decimal(123)))
1624 self.assertEqual(Decimal(567).min(123),
1625 Decimal(567).min(Decimal(123)))
1626 self.assertEqual(Decimal(567).min_mag(123),
1627 Decimal(567).min_mag(Decimal(123)))
1628 self.assertEqual(Decimal(567).next_toward(123),
1629 Decimal(567).next_toward(Decimal(123)))
1630 self.assertEqual(Decimal(1234).quantize(100),
1631 Decimal(1234).quantize(Decimal(100)))
1632 self.assertEqual(Decimal(768).remainder_near(1234),
1633 Decimal(768).remainder_near(Decimal(1234)))
1634 self.assertEqual(Decimal(123).rotate(1),
1635 Decimal(123).rotate(Decimal(1)))
1636 self.assertEqual(Decimal(1234).same_quantum(1000),
1637 Decimal(1234).same_quantum(Decimal(1000)))
1638 self.assertEqual(Decimal('9.123').scaleb(-100),
1639 Decimal('9.123').scaleb(Decimal(-100)))
1640 self.assertEqual(Decimal(456).shift(-1),
1641 Decimal(456).shift(Decimal(-1)))
1642
1643 self.assertEqual(Decimal(-12).fma(Decimal(45), 67),
1644 Decimal(-12).fma(Decimal(45), Decimal(67)))
1645 self.assertEqual(Decimal(-12).fma(45, 67),
1646 Decimal(-12).fma(Decimal(45), Decimal(67)))
1647 self.assertEqual(Decimal(-12).fma(45, Decimal(67)),
1648 Decimal(-12).fma(Decimal(45), Decimal(67)))
1649
Facundo Batista6c398da2007-09-17 17:30:13 +00001650
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001651class DecimalPythonAPItests(unittest.TestCase):
1652
Raymond Hettinger2c8585b2009-02-03 03:37:03 +00001653 def test_abc(self):
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001654 self.assertTrue(issubclass(Decimal, numbers.Number))
Ezio Melotti856a3be2010-04-03 14:51:00 +00001655 self.assertFalse(issubclass(Decimal, numbers.Real))
Ezio Melottib0f5adc2010-01-24 16:58:36 +00001656 self.assertIsInstance(Decimal(0), numbers.Number)
Ezio Melotti856a3be2010-04-03 14:51:00 +00001657 self.assertNotIsInstance(Decimal(0), numbers.Real)
Raymond Hettinger2c8585b2009-02-03 03:37:03 +00001658
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001659 def test_pickle(self):
1660 d = Decimal('-3.141590000')
1661 p = pickle.dumps(d)
1662 e = pickle.loads(p)
1663 self.assertEqual(d, e)
1664
Raymond Hettinger5548be22004-07-05 18:49:38 +00001665 def test_int(self):
Raymond Hettinger605ed022004-11-24 07:28:48 +00001666 for x in range(-250, 250):
1667 s = '%0.2f' % (x / 100.0)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001668 # should work the same as for floats
1669 self.assertEqual(int(Decimal(s)), int(float(s)))
Raymond Hettinger605ed022004-11-24 07:28:48 +00001670 # should work the same as to_integral in the ROUND_DOWN mode
Raymond Hettinger5548be22004-07-05 18:49:38 +00001671 d = Decimal(s)
Raymond Hettinger605ed022004-11-24 07:28:48 +00001672 r = d.to_integral(ROUND_DOWN)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001673 self.assertEqual(Decimal(int(d)), r)
1674
Mark Dickinson968f1692009-09-07 18:04:58 +00001675 self.assertRaises(ValueError, int, Decimal('-nan'))
1676 self.assertRaises(ValueError, int, Decimal('snan'))
1677 self.assertRaises(OverflowError, int, Decimal('inf'))
1678 self.assertRaises(OverflowError, int, Decimal('-inf'))
1679
1680 self.assertRaises(ValueError, long, Decimal('-nan'))
1681 self.assertRaises(ValueError, long, Decimal('snan'))
1682 self.assertRaises(OverflowError, long, Decimal('inf'))
1683 self.assertRaises(OverflowError, long, Decimal('-inf'))
1684
Raymond Hettinger5a053642008-01-24 19:05:29 +00001685 def test_trunc(self):
1686 for x in range(-250, 250):
1687 s = '%0.2f' % (x / 100.0)
1688 # should work the same as for floats
1689 self.assertEqual(int(Decimal(s)), int(float(s)))
1690 # should work the same as to_integral in the ROUND_DOWN mode
1691 d = Decimal(s)
1692 r = d.to_integral(ROUND_DOWN)
Jeffrey Yasskinca2b69f2008-02-01 06:22:46 +00001693 self.assertEqual(Decimal(math.trunc(d)), r)
Raymond Hettinger5a053642008-01-24 19:05:29 +00001694
Raymond Hettingerf4d85972009-01-03 19:02:23 +00001695 def test_from_float(self):
1696
1697 class MyDecimal(Decimal):
1698 pass
1699
1700 r = MyDecimal.from_float(0.1)
1701 self.assertEqual(type(r), MyDecimal)
1702 self.assertEqual(str(r),
1703 '0.1000000000000000055511151231257827021181583404541015625')
1704 bigint = 12345678901234567890123456789
1705 self.assertEqual(MyDecimal.from_float(bigint), MyDecimal(bigint))
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001706 self.assertTrue(MyDecimal.from_float(float('nan')).is_qnan())
1707 self.assertTrue(MyDecimal.from_float(float('inf')).is_infinite())
1708 self.assertTrue(MyDecimal.from_float(float('-inf')).is_infinite())
Raymond Hettingerf4d85972009-01-03 19:02:23 +00001709 self.assertEqual(str(MyDecimal.from_float(float('nan'))),
1710 str(Decimal('NaN')))
1711 self.assertEqual(str(MyDecimal.from_float(float('inf'))),
1712 str(Decimal('Infinity')))
1713 self.assertEqual(str(MyDecimal.from_float(float('-inf'))),
1714 str(Decimal('-Infinity')))
1715 self.assertRaises(TypeError, MyDecimal.from_float, 'abc')
1716 for i in range(200):
1717 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
1718 self.assertEqual(x, float(MyDecimal.from_float(x))) # roundtrip
1719
1720 def test_create_decimal_from_float(self):
1721 context = Context(prec=5, rounding=ROUND_DOWN)
1722 self.assertEqual(
1723 context.create_decimal_from_float(math.pi),
1724 Decimal('3.1415')
1725 )
1726 context = Context(prec=5, rounding=ROUND_UP)
1727 self.assertEqual(
1728 context.create_decimal_from_float(math.pi),
1729 Decimal('3.1416')
1730 )
1731 context = Context(prec=5, traps=[Inexact])
1732 self.assertRaises(
1733 Inexact,
1734 context.create_decimal_from_float,
1735 math.pi
1736 )
1737 self.assertEqual(repr(context.create_decimal_from_float(-0.0)),
1738 "Decimal('-0')")
1739 self.assertEqual(repr(context.create_decimal_from_float(1.0)),
1740 "Decimal('1')")
1741 self.assertEqual(repr(context.create_decimal_from_float(10)),
1742 "Decimal('10')")
1743
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00001744class ContextAPItests(unittest.TestCase):
1745
1746 def test_pickle(self):
1747 c = Context()
1748 e = pickle.loads(pickle.dumps(c))
1749 for k in vars(c):
1750 v1 = vars(c)[k]
1751 v2 = vars(e)[k]
1752 self.assertEqual(v1, v2)
1753
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001754 def test_equality_with_other_types(self):
Ezio Melottiaa980582010-01-23 23:04:36 +00001755 self.assertIn(Decimal(10), ['a', 1.0, Decimal(10), (1,2), {}])
1756 self.assertNotIn(Decimal(10), ['a', 1.0, (1,2), {}])
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001757
Raymond Hettinger955d2b22004-08-08 20:17:45 +00001758 def test_copy(self):
1759 # All copies should be deep
1760 c = Context()
1761 d = c.copy()
1762 self.assertNotEqual(id(c), id(d))
1763 self.assertNotEqual(id(c.flags), id(d.flags))
1764 self.assertNotEqual(id(c.traps), id(d.traps))
1765
Mark Dickinson6d8effb2010-02-18 14:27:02 +00001766 def test_abs(self):
1767 c = Context()
1768 d = c.abs(Decimal(-1))
1769 self.assertEqual(c.abs(-1), d)
1770 self.assertRaises(TypeError, c.abs, '-1')
1771
1772 def test_add(self):
1773 c = Context()
1774 d = c.add(Decimal(1), Decimal(1))
1775 self.assertEqual(c.add(1, 1), d)
1776 self.assertEqual(c.add(Decimal(1), 1), d)
1777 self.assertEqual(c.add(1, Decimal(1)), d)
1778 self.assertRaises(TypeError, c.add, '1', 1)
1779 self.assertRaises(TypeError, c.add, 1, '1')
1780
1781 def test_compare(self):
1782 c = Context()
1783 d = c.compare(Decimal(1), Decimal(1))
1784 self.assertEqual(c.compare(1, 1), d)
1785 self.assertEqual(c.compare(Decimal(1), 1), d)
1786 self.assertEqual(c.compare(1, Decimal(1)), d)
1787 self.assertRaises(TypeError, c.compare, '1', 1)
1788 self.assertRaises(TypeError, c.compare, 1, '1')
1789
1790 def test_compare_signal(self):
1791 c = Context()
1792 d = c.compare_signal(Decimal(1), Decimal(1))
1793 self.assertEqual(c.compare_signal(1, 1), d)
1794 self.assertEqual(c.compare_signal(Decimal(1), 1), d)
1795 self.assertEqual(c.compare_signal(1, Decimal(1)), d)
1796 self.assertRaises(TypeError, c.compare_signal, '1', 1)
1797 self.assertRaises(TypeError, c.compare_signal, 1, '1')
1798
1799 def test_compare_total(self):
1800 c = Context()
1801 d = c.compare_total(Decimal(1), Decimal(1))
1802 self.assertEqual(c.compare_total(1, 1), d)
1803 self.assertEqual(c.compare_total(Decimal(1), 1), d)
1804 self.assertEqual(c.compare_total(1, Decimal(1)), d)
1805 self.assertRaises(TypeError, c.compare_total, '1', 1)
1806 self.assertRaises(TypeError, c.compare_total, 1, '1')
1807
1808 def test_compare_total_mag(self):
1809 c = Context()
1810 d = c.compare_total_mag(Decimal(1), Decimal(1))
1811 self.assertEqual(c.compare_total_mag(1, 1), d)
1812 self.assertEqual(c.compare_total_mag(Decimal(1), 1), d)
1813 self.assertEqual(c.compare_total_mag(1, Decimal(1)), d)
1814 self.assertRaises(TypeError, c.compare_total_mag, '1', 1)
1815 self.assertRaises(TypeError, c.compare_total_mag, 1, '1')
1816
1817 def test_copy_abs(self):
1818 c = Context()
1819 d = c.copy_abs(Decimal(-1))
1820 self.assertEqual(c.copy_abs(-1), d)
1821 self.assertRaises(TypeError, c.copy_abs, '-1')
1822
1823 def test_copy_decimal(self):
1824 c = Context()
1825 d = c.copy_decimal(Decimal(-1))
1826 self.assertEqual(c.copy_decimal(-1), d)
1827 self.assertRaises(TypeError, c.copy_decimal, '-1')
1828
1829 def test_copy_negate(self):
1830 c = Context()
1831 d = c.copy_negate(Decimal(-1))
1832 self.assertEqual(c.copy_negate(-1), d)
1833 self.assertRaises(TypeError, c.copy_negate, '-1')
1834
1835 def test_copy_sign(self):
1836 c = Context()
1837 d = c.copy_sign(Decimal(1), Decimal(-2))
1838 self.assertEqual(c.copy_sign(1, -2), d)
1839 self.assertEqual(c.copy_sign(Decimal(1), -2), d)
1840 self.assertEqual(c.copy_sign(1, Decimal(-2)), d)
1841 self.assertRaises(TypeError, c.copy_sign, '1', -2)
1842 self.assertRaises(TypeError, c.copy_sign, 1, '-2')
1843
1844 def test_divide(self):
1845 c = Context()
1846 d = c.divide(Decimal(1), Decimal(2))
1847 self.assertEqual(c.divide(1, 2), d)
1848 self.assertEqual(c.divide(Decimal(1), 2), d)
1849 self.assertEqual(c.divide(1, Decimal(2)), d)
1850 self.assertRaises(TypeError, c.divide, '1', 2)
1851 self.assertRaises(TypeError, c.divide, 1, '2')
1852
1853 def test_divide_int(self):
1854 c = Context()
1855 d = c.divide_int(Decimal(1), Decimal(2))
1856 self.assertEqual(c.divide_int(1, 2), d)
1857 self.assertEqual(c.divide_int(Decimal(1), 2), d)
1858 self.assertEqual(c.divide_int(1, Decimal(2)), d)
1859 self.assertRaises(TypeError, c.divide_int, '1', 2)
1860 self.assertRaises(TypeError, c.divide_int, 1, '2')
1861
1862 def test_divmod(self):
1863 c = Context()
1864 d = c.divmod(Decimal(1), Decimal(2))
1865 self.assertEqual(c.divmod(1, 2), d)
1866 self.assertEqual(c.divmod(Decimal(1), 2), d)
1867 self.assertEqual(c.divmod(1, Decimal(2)), d)
1868 self.assertRaises(TypeError, c.divmod, '1', 2)
1869 self.assertRaises(TypeError, c.divmod, 1, '2')
1870
1871 def test_exp(self):
1872 c = Context()
1873 d = c.exp(Decimal(10))
1874 self.assertEqual(c.exp(10), d)
1875 self.assertRaises(TypeError, c.exp, '10')
1876
1877 def test_fma(self):
1878 c = Context()
1879 d = c.fma(Decimal(2), Decimal(3), Decimal(4))
1880 self.assertEqual(c.fma(2, 3, 4), d)
1881 self.assertEqual(c.fma(Decimal(2), 3, 4), d)
1882 self.assertEqual(c.fma(2, Decimal(3), 4), d)
1883 self.assertEqual(c.fma(2, 3, Decimal(4)), d)
1884 self.assertEqual(c.fma(Decimal(2), Decimal(3), 4), d)
1885 self.assertRaises(TypeError, c.fma, '2', 3, 4)
1886 self.assertRaises(TypeError, c.fma, 2, '3', 4)
1887 self.assertRaises(TypeError, c.fma, 2, 3, '4')
1888
1889 def test_is_finite(self):
1890 c = Context()
1891 d = c.is_finite(Decimal(10))
1892 self.assertEqual(c.is_finite(10), d)
1893 self.assertRaises(TypeError, c.is_finite, '10')
1894
1895 def test_is_infinite(self):
1896 c = Context()
1897 d = c.is_infinite(Decimal(10))
1898 self.assertEqual(c.is_infinite(10), d)
1899 self.assertRaises(TypeError, c.is_infinite, '10')
1900
1901 def test_is_nan(self):
1902 c = Context()
1903 d = c.is_nan(Decimal(10))
1904 self.assertEqual(c.is_nan(10), d)
1905 self.assertRaises(TypeError, c.is_nan, '10')
1906
1907 def test_is_normal(self):
1908 c = Context()
1909 d = c.is_normal(Decimal(10))
1910 self.assertEqual(c.is_normal(10), d)
1911 self.assertRaises(TypeError, c.is_normal, '10')
1912
1913 def test_is_qnan(self):
1914 c = Context()
1915 d = c.is_qnan(Decimal(10))
1916 self.assertEqual(c.is_qnan(10), d)
1917 self.assertRaises(TypeError, c.is_qnan, '10')
1918
1919 def test_is_signed(self):
1920 c = Context()
1921 d = c.is_signed(Decimal(10))
1922 self.assertEqual(c.is_signed(10), d)
1923 self.assertRaises(TypeError, c.is_signed, '10')
1924
1925 def test_is_snan(self):
1926 c = Context()
1927 d = c.is_snan(Decimal(10))
1928 self.assertEqual(c.is_snan(10), d)
1929 self.assertRaises(TypeError, c.is_snan, '10')
1930
1931 def test_is_subnormal(self):
1932 c = Context()
1933 d = c.is_subnormal(Decimal(10))
1934 self.assertEqual(c.is_subnormal(10), d)
1935 self.assertRaises(TypeError, c.is_subnormal, '10')
1936
1937 def test_is_zero(self):
1938 c = Context()
1939 d = c.is_zero(Decimal(10))
1940 self.assertEqual(c.is_zero(10), d)
1941 self.assertRaises(TypeError, c.is_zero, '10')
1942
1943 def test_ln(self):
1944 c = Context()
1945 d = c.ln(Decimal(10))
1946 self.assertEqual(c.ln(10), d)
1947 self.assertRaises(TypeError, c.ln, '10')
1948
1949 def test_log10(self):
1950 c = Context()
1951 d = c.log10(Decimal(10))
1952 self.assertEqual(c.log10(10), d)
1953 self.assertRaises(TypeError, c.log10, '10')
1954
1955 def test_logb(self):
1956 c = Context()
1957 d = c.logb(Decimal(10))
1958 self.assertEqual(c.logb(10), d)
1959 self.assertRaises(TypeError, c.logb, '10')
1960
1961 def test_logical_and(self):
1962 c = Context()
1963 d = c.logical_and(Decimal(1), Decimal(1))
1964 self.assertEqual(c.logical_and(1, 1), d)
1965 self.assertEqual(c.logical_and(Decimal(1), 1), d)
1966 self.assertEqual(c.logical_and(1, Decimal(1)), d)
1967 self.assertRaises(TypeError, c.logical_and, '1', 1)
1968 self.assertRaises(TypeError, c.logical_and, 1, '1')
1969
1970 def test_logical_invert(self):
1971 c = Context()
1972 d = c.logical_invert(Decimal(1000))
1973 self.assertEqual(c.logical_invert(1000), d)
1974 self.assertRaises(TypeError, c.logical_invert, '1000')
1975
1976 def test_logical_or(self):
1977 c = Context()
1978 d = c.logical_or(Decimal(1), Decimal(1))
1979 self.assertEqual(c.logical_or(1, 1), d)
1980 self.assertEqual(c.logical_or(Decimal(1), 1), d)
1981 self.assertEqual(c.logical_or(1, Decimal(1)), d)
1982 self.assertRaises(TypeError, c.logical_or, '1', 1)
1983 self.assertRaises(TypeError, c.logical_or, 1, '1')
1984
1985 def test_logical_xor(self):
1986 c = Context()
1987 d = c.logical_xor(Decimal(1), Decimal(1))
1988 self.assertEqual(c.logical_xor(1, 1), d)
1989 self.assertEqual(c.logical_xor(Decimal(1), 1), d)
1990 self.assertEqual(c.logical_xor(1, Decimal(1)), d)
1991 self.assertRaises(TypeError, c.logical_xor, '1', 1)
1992 self.assertRaises(TypeError, c.logical_xor, 1, '1')
1993
1994 def test_max(self):
1995 c = Context()
1996 d = c.max(Decimal(1), Decimal(2))
1997 self.assertEqual(c.max(1, 2), d)
1998 self.assertEqual(c.max(Decimal(1), 2), d)
1999 self.assertEqual(c.max(1, Decimal(2)), d)
2000 self.assertRaises(TypeError, c.max, '1', 2)
2001 self.assertRaises(TypeError, c.max, 1, '2')
2002
2003 def test_max_mag(self):
2004 c = Context()
2005 d = c.max_mag(Decimal(1), Decimal(2))
2006 self.assertEqual(c.max_mag(1, 2), d)
2007 self.assertEqual(c.max_mag(Decimal(1), 2), d)
2008 self.assertEqual(c.max_mag(1, Decimal(2)), d)
2009 self.assertRaises(TypeError, c.max_mag, '1', 2)
2010 self.assertRaises(TypeError, c.max_mag, 1, '2')
2011
2012 def test_min(self):
2013 c = Context()
2014 d = c.min(Decimal(1), Decimal(2))
2015 self.assertEqual(c.min(1, 2), d)
2016 self.assertEqual(c.min(Decimal(1), 2), d)
2017 self.assertEqual(c.min(1, Decimal(2)), d)
2018 self.assertRaises(TypeError, c.min, '1', 2)
2019 self.assertRaises(TypeError, c.min, 1, '2')
2020
2021 def test_min_mag(self):
2022 c = Context()
2023 d = c.min_mag(Decimal(1), Decimal(2))
2024 self.assertEqual(c.min_mag(1, 2), d)
2025 self.assertEqual(c.min_mag(Decimal(1), 2), d)
2026 self.assertEqual(c.min_mag(1, Decimal(2)), d)
2027 self.assertRaises(TypeError, c.min_mag, '1', 2)
2028 self.assertRaises(TypeError, c.min_mag, 1, '2')
2029
2030 def test_minus(self):
2031 c = Context()
2032 d = c.minus(Decimal(10))
2033 self.assertEqual(c.minus(10), d)
2034 self.assertRaises(TypeError, c.minus, '10')
2035
2036 def test_multiply(self):
2037 c = Context()
2038 d = c.multiply(Decimal(1), Decimal(2))
2039 self.assertEqual(c.multiply(1, 2), d)
2040 self.assertEqual(c.multiply(Decimal(1), 2), d)
2041 self.assertEqual(c.multiply(1, Decimal(2)), d)
2042 self.assertRaises(TypeError, c.multiply, '1', 2)
2043 self.assertRaises(TypeError, c.multiply, 1, '2')
2044
2045 def test_next_minus(self):
2046 c = Context()
2047 d = c.next_minus(Decimal(10))
2048 self.assertEqual(c.next_minus(10), d)
2049 self.assertRaises(TypeError, c.next_minus, '10')
2050
2051 def test_next_plus(self):
2052 c = Context()
2053 d = c.next_plus(Decimal(10))
2054 self.assertEqual(c.next_plus(10), d)
2055 self.assertRaises(TypeError, c.next_plus, '10')
2056
2057 def test_next_toward(self):
2058 c = Context()
2059 d = c.next_toward(Decimal(1), Decimal(2))
2060 self.assertEqual(c.next_toward(1, 2), d)
2061 self.assertEqual(c.next_toward(Decimal(1), 2), d)
2062 self.assertEqual(c.next_toward(1, Decimal(2)), d)
2063 self.assertRaises(TypeError, c.next_toward, '1', 2)
2064 self.assertRaises(TypeError, c.next_toward, 1, '2')
2065
2066 def test_normalize(self):
2067 c = Context()
2068 d = c.normalize(Decimal(10))
2069 self.assertEqual(c.normalize(10), d)
2070 self.assertRaises(TypeError, c.normalize, '10')
2071
2072 def test_number_class(self):
2073 c = Context()
2074 self.assertEqual(c.number_class(123), c.number_class(Decimal(123)))
2075 self.assertEqual(c.number_class(0), c.number_class(Decimal(0)))
2076 self.assertEqual(c.number_class(-45), c.number_class(Decimal(-45)))
2077
2078 def test_power(self):
2079 c = Context()
2080 d = c.power(Decimal(1), Decimal(4), Decimal(2))
2081 self.assertEqual(c.power(1, 4, 2), d)
2082 self.assertEqual(c.power(Decimal(1), 4, 2), d)
2083 self.assertEqual(c.power(1, Decimal(4), 2), d)
2084 self.assertEqual(c.power(1, 4, Decimal(2)), d)
2085 self.assertEqual(c.power(Decimal(1), Decimal(4), 2), d)
2086 self.assertRaises(TypeError, c.power, '1', 4, 2)
2087 self.assertRaises(TypeError, c.power, 1, '4', 2)
2088 self.assertRaises(TypeError, c.power, 1, 4, '2')
2089
2090 def test_plus(self):
2091 c = Context()
2092 d = c.plus(Decimal(10))
2093 self.assertEqual(c.plus(10), d)
2094 self.assertRaises(TypeError, c.plus, '10')
2095
2096 def test_quantize(self):
2097 c = Context()
2098 d = c.quantize(Decimal(1), Decimal(2))
2099 self.assertEqual(c.quantize(1, 2), d)
2100 self.assertEqual(c.quantize(Decimal(1), 2), d)
2101 self.assertEqual(c.quantize(1, Decimal(2)), d)
2102 self.assertRaises(TypeError, c.quantize, '1', 2)
2103 self.assertRaises(TypeError, c.quantize, 1, '2')
2104
2105 def test_remainder(self):
2106 c = Context()
2107 d = c.remainder(Decimal(1), Decimal(2))
2108 self.assertEqual(c.remainder(1, 2), d)
2109 self.assertEqual(c.remainder(Decimal(1), 2), d)
2110 self.assertEqual(c.remainder(1, Decimal(2)), d)
2111 self.assertRaises(TypeError, c.remainder, '1', 2)
2112 self.assertRaises(TypeError, c.remainder, 1, '2')
2113
2114 def test_remainder_near(self):
2115 c = Context()
2116 d = c.remainder_near(Decimal(1), Decimal(2))
2117 self.assertEqual(c.remainder_near(1, 2), d)
2118 self.assertEqual(c.remainder_near(Decimal(1), 2), d)
2119 self.assertEqual(c.remainder_near(1, Decimal(2)), d)
2120 self.assertRaises(TypeError, c.remainder_near, '1', 2)
2121 self.assertRaises(TypeError, c.remainder_near, 1, '2')
2122
2123 def test_rotate(self):
2124 c = Context()
2125 d = c.rotate(Decimal(1), Decimal(2))
2126 self.assertEqual(c.rotate(1, 2), d)
2127 self.assertEqual(c.rotate(Decimal(1), 2), d)
2128 self.assertEqual(c.rotate(1, Decimal(2)), d)
2129 self.assertRaises(TypeError, c.rotate, '1', 2)
2130 self.assertRaises(TypeError, c.rotate, 1, '2')
2131
2132 def test_sqrt(self):
2133 c = Context()
2134 d = c.sqrt(Decimal(10))
2135 self.assertEqual(c.sqrt(10), d)
2136 self.assertRaises(TypeError, c.sqrt, '10')
2137
2138 def test_same_quantum(self):
2139 c = Context()
2140 d = c.same_quantum(Decimal(1), Decimal(2))
2141 self.assertEqual(c.same_quantum(1, 2), d)
2142 self.assertEqual(c.same_quantum(Decimal(1), 2), d)
2143 self.assertEqual(c.same_quantum(1, Decimal(2)), d)
2144 self.assertRaises(TypeError, c.same_quantum, '1', 2)
2145 self.assertRaises(TypeError, c.same_quantum, 1, '2')
2146
2147 def test_scaleb(self):
2148 c = Context()
2149 d = c.scaleb(Decimal(1), Decimal(2))
2150 self.assertEqual(c.scaleb(1, 2), d)
2151 self.assertEqual(c.scaleb(Decimal(1), 2), d)
2152 self.assertEqual(c.scaleb(1, Decimal(2)), d)
2153 self.assertRaises(TypeError, c.scaleb, '1', 2)
2154 self.assertRaises(TypeError, c.scaleb, 1, '2')
2155
2156 def test_shift(self):
2157 c = Context()
2158 d = c.shift(Decimal(1), Decimal(2))
2159 self.assertEqual(c.shift(1, 2), d)
2160 self.assertEqual(c.shift(Decimal(1), 2), d)
2161 self.assertEqual(c.shift(1, Decimal(2)), d)
2162 self.assertRaises(TypeError, c.shift, '1', 2)
2163 self.assertRaises(TypeError, c.shift, 1, '2')
2164
2165 def test_subtract(self):
2166 c = Context()
2167 d = c.subtract(Decimal(1), Decimal(2))
2168 self.assertEqual(c.subtract(1, 2), d)
2169 self.assertEqual(c.subtract(Decimal(1), 2), d)
2170 self.assertEqual(c.subtract(1, Decimal(2)), d)
2171 self.assertRaises(TypeError, c.subtract, '1', 2)
2172 self.assertRaises(TypeError, c.subtract, 1, '2')
2173
2174 def test_to_eng_string(self):
2175 c = Context()
2176 d = c.to_eng_string(Decimal(10))
2177 self.assertEqual(c.to_eng_string(10), d)
2178 self.assertRaises(TypeError, c.to_eng_string, '10')
2179
2180 def test_to_sci_string(self):
2181 c = Context()
2182 d = c.to_sci_string(Decimal(10))
2183 self.assertEqual(c.to_sci_string(10), d)
2184 self.assertRaises(TypeError, c.to_sci_string, '10')
2185
2186 def test_to_integral_exact(self):
2187 c = Context()
2188 d = c.to_integral_exact(Decimal(10))
2189 self.assertEqual(c.to_integral_exact(10), d)
2190 self.assertRaises(TypeError, c.to_integral_exact, '10')
2191
2192 def test_to_integral_value(self):
2193 c = Context()
2194 d = c.to_integral_value(Decimal(10))
2195 self.assertEqual(c.to_integral_value(10), d)
2196 self.assertRaises(TypeError, c.to_integral_value, '10')
2197
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002198class WithStatementTest(unittest.TestCase):
2199 # Can't do these as docstrings until Python 2.6
2200 # as doctest can't handle __future__ statements
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002201
2202 def test_localcontext(self):
Nick Coghlanced12182006-09-02 03:54:17 +00002203 # Use a copy of the current context in the block
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002204 orig_ctx = getcontext()
2205 with localcontext() as enter_ctx:
2206 set_ctx = getcontext()
2207 final_ctx = getcontext()
Ezio Melotti856a3be2010-04-03 14:51:00 +00002208 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
2209 self.assertIsNot(orig_ctx, set_ctx, 'did not copy the context')
2210 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002211
2212 def test_localcontextarg(self):
Nick Coghlanced12182006-09-02 03:54:17 +00002213 # Use a copy of the supplied context in the block
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002214 orig_ctx = getcontext()
2215 new_ctx = Context(prec=42)
2216 with localcontext(new_ctx) as enter_ctx:
2217 set_ctx = getcontext()
2218 final_ctx = getcontext()
Ezio Melotti856a3be2010-04-03 14:51:00 +00002219 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
2220 self.assertEqual(set_ctx.prec, new_ctx.prec, 'did not set correct context')
2221 self.assertIsNot(new_ctx, set_ctx, 'did not copy the context')
2222 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002223
Facundo Batista353750c2007-09-13 18:13:15 +00002224class ContextFlags(unittest.TestCase):
2225 def test_flags_irrelevant(self):
2226 # check that the result (numeric result + flags raised) of an
2227 # arithmetic operation doesn't depend on the current flags
2228
2229 context = Context(prec=9, Emin = -999999999, Emax = 999999999,
2230 rounding=ROUND_HALF_EVEN, traps=[], flags=[])
2231
2232 # operations that raise various flags, in the form (function, arglist)
2233 operations = [
2234 (context._apply, [Decimal("100E-1000000009")]),
2235 (context.sqrt, [Decimal(2)]),
2236 (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]),
2237 (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]),
2238 (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]),
2239 ]
2240
2241 # try various flags individually, then a whole lot at once
2242 flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal],
2243 [Inexact, Rounded, Underflow, Clamped, Subnormal]]
2244
2245 for fn, args in operations:
2246 # find answer and flags raised using a clean context
2247 context.clear_flags()
2248 ans = fn(*args)
2249 flags = [k for k, v in context.flags.items() if v]
2250
2251 for extra_flags in flagsets:
2252 # set flags, before calling operation
2253 context.clear_flags()
2254 for flag in extra_flags:
2255 context._raise_error(flag)
2256 new_ans = fn(*args)
2257
2258 # flags that we expect to be set after the operation
2259 expected_flags = list(flags)
2260 for flag in extra_flags:
2261 if flag not in expected_flags:
2262 expected_flags.append(flag)
Facundo Batista353750c2007-09-13 18:13:15 +00002263
2264 # flags we actually got
2265 new_flags = [k for k,v in context.flags.items() if v]
Facundo Batista353750c2007-09-13 18:13:15 +00002266
2267 self.assertEqual(ans, new_ans,
2268 "operation produces different answers depending on flags set: " +
2269 "expected %s, got %s." % (ans, new_ans))
Florent Xicluna8f43cec2010-03-21 10:51:40 +00002270 self.assertItemsEqual(new_flags, expected_flags,
Facundo Batista353750c2007-09-13 18:13:15 +00002271 "operation raises different flags depending on flags set: " +
2272 "expected %s, got %s" % (expected_flags, new_flags))
2273
2274def test_main(arith=False, verbose=None, todo_tests=None, debug=None):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002275 """ Execute the tests.
2276
Raymond Hettingered20ad82004-09-04 20:09:13 +00002277 Runs all arithmetic tests if arith is True or if the "decimal" resource
2278 is enabled in regrtest.py
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002279 """
Raymond Hettingered20ad82004-09-04 20:09:13 +00002280
Neal Norwitzce4a9c92006-04-09 08:36:46 +00002281 init()
Facundo Batista353750c2007-09-13 18:13:15 +00002282 global TEST_ALL, DEBUG
Raymond Hettingered20ad82004-09-04 20:09:13 +00002283 TEST_ALL = arith or is_resource_enabled('decimal')
Facundo Batista353750c2007-09-13 18:13:15 +00002284 DEBUG = debug
Raymond Hettingered20ad82004-09-04 20:09:13 +00002285
Facundo Batista353750c2007-09-13 18:13:15 +00002286 if todo_tests is None:
2287 test_classes = [
2288 DecimalExplicitConstructionTest,
2289 DecimalImplicitConstructionTest,
2290 DecimalArithmeticOperatorsTest,
Mark Dickinson1ddf1d82008-02-29 02:16:37 +00002291 DecimalFormatTest,
Facundo Batista353750c2007-09-13 18:13:15 +00002292 DecimalUseOfContextTest,
2293 DecimalUsabilityTest,
2294 DecimalPythonAPItests,
2295 ContextAPItests,
2296 DecimalTest,
2297 WithStatementTest,
2298 ContextFlags
2299 ]
2300 else:
2301 test_classes = [DecimalTest]
2302
2303 # Dynamically build custom test definition for each file in the test
2304 # directory and add the definitions to the DecimalTest class. This
2305 # procedure insures that new files do not get skipped.
2306 for filename in os.listdir(directory):
2307 if '.decTest' not in filename or filename.startswith("."):
2308 continue
2309 head, tail = filename.split('.')
2310 if todo_tests is not None and head not in todo_tests:
2311 continue
2312 tester = lambda self, f=filename: self.eval_file(directory + f)
2313 setattr(DecimalTest, 'test_' + head, tester)
2314 del filename, head, tail, tester
2315
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002316
Tim Peters46cc7022006-03-31 04:11:16 +00002317 try:
2318 run_unittest(*test_classes)
Facundo Batista353750c2007-09-13 18:13:15 +00002319 if todo_tests is None:
2320 import decimal as DecimalModule
2321 run_doctest(DecimalModule, verbose)
Tim Peters46cc7022006-03-31 04:11:16 +00002322 finally:
2323 setcontext(ORIGINAL_CONTEXT)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002324
2325if __name__ == '__main__':
Facundo Batista353750c2007-09-13 18:13:15 +00002326 import optparse
2327 p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]")
2328 p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test')
2329 p.add_option('--skip', '-s', action='store_true', help='skip over 90% of the arithmetic tests')
2330 (opt, args) = p.parse_args()
2331
2332 if opt.skip:
2333 test_main(arith=False, verbose=True)
2334 elif args:
2335 test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002336 else:
Facundo Batista353750c2007-09-13 18:13:15 +00002337 test_main(arith=True, verbose=True)