blob: 3b3d9d1003b8aa38dd60c57a611a45ae541becb2 [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
Serhiy Storchaka20c049d2014-10-14 21:10:56 +030034from test.test_support import (run_unittest, run_doctest, requires_unicode, u,
Serhiy Storchakaad9a1ba2015-02-18 08:04:26 +020035 is_resource_enabled, check_py3k_warnings,
36 run_with_locale)
Raymond Hettinger0aeac102004-07-05 22:53:03 +000037import random
Raymond Hettinger7e71fa52004-12-18 19:07:19 +000038try:
39 import threading
40except ImportError:
41 threading = None
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000042
Raymond Hettingerfed52962004-07-14 15:41:57 +000043# Useful Test Constant
Mark Dickinson16cd2be2010-05-01 11:46:20 +000044Signals = tuple(getcontext().flags.keys())
Raymond Hettingerfed52962004-07-14 15:41:57 +000045
Mark Dickinson4f96f5f2010-05-04 14:25:50 +000046# Signals ordered with respect to precedence: when an operation
47# produces multiple signals, signals occurring later in the list
48# should be handled before those occurring earlier in the list.
49OrderedSignals = (Clamped, Rounded, Inexact, Subnormal,
50 Underflow, Overflow, DivisionByZero, InvalidOperation)
51
Tim Peters46cc7022006-03-31 04:11:16 +000052# Tests are built around these assumed context defaults.
53# test_main() restores the original context.
Neal Norwitzce4a9c92006-04-09 08:36:46 +000054def init():
55 global ORIGINAL_CONTEXT
56 ORIGINAL_CONTEXT = getcontext().copy()
Facundo Batistaee340e52008-05-02 17:39:00 +000057 DefaultTestContext = Context(
58 prec = 9,
59 rounding = ROUND_HALF_EVEN,
60 traps = dict.fromkeys(Signals, 0)
61 )
62 setcontext(DefaultTestContext)
Raymond Hettinger6ea48452004-07-03 12:26:21 +000063
Raymond Hettingered171ab2010-04-02 18:39:24 +000064# decorator for skipping tests on non-IEEE 754 platforms
65requires_IEEE_754 = unittest.skipUnless(
66 float.__getformat__("double").startswith("IEEE"),
67 "test requires IEEE 754 doubles")
68
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000069TESTDATADIR = 'decimaltestdata'
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +000070if __name__ == '__main__':
71 file = sys.argv[0]
72else:
73 file = __file__
74testdir = os.path.dirname(file) or os.curdir
Raymond Hettinger267b8682005-03-27 10:47:39 +000075directory = testdir + os.sep + TESTDATADIR + os.sep
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000076
Raymond Hettinger267b8682005-03-27 10:47:39 +000077skip_expected = not os.path.isdir(directory)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000078
Mark Dickinson539bff42009-10-08 16:28:39 +000079# list of individual .decTest test ids that correspond to tests that
80# we're skipping for one reason or another.
Mark Dickinsone85aa732010-07-08 19:24:40 +000081skipped_test_ids = set([
82 # Skip implementation-specific scaleb tests.
83 'scbx164',
84 'scbx165',
85
86 # For some operations (currently exp, ln, log10, power), the decNumber
87 # reference implementation imposes additional restrictions on the context
88 # and operands. These restrictions are not part of the specification;
89 # however, the effect of these restrictions does show up in some of the
90 # testcases. We skip testcases that violate these restrictions, since
91 # Decimal behaves differently from decNumber for these testcases so these
92 # testcases would otherwise fail.
93 'expx901',
94 'expx902',
95 'expx903',
96 'expx905',
97 'lnx901',
98 'lnx902',
99 'lnx903',
100 'lnx905',
101 'logx901',
102 'logx902',
103 'logx903',
104 'logx905',
105 'powx1183',
106 'powx1184',
107 'powx4001',
108 'powx4002',
109 'powx4003',
110 'powx4005',
111 'powx4008',
112 'powx4010',
113 'powx4012',
114 'powx4014',
115 ])
Mark Dickinson539bff42009-10-08 16:28:39 +0000116
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000117# Make sure it actually raises errors when not expected and caught in flags
118# Slower, since it runs some things several times.
119EXTENDEDERRORTEST = False
120
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000121#Map the test cases' error names to the actual errors
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000122ErrorNames = {'clamped' : Clamped,
Raymond Hettinger5aa478b2004-07-09 10:02:53 +0000123 'conversion_syntax' : InvalidOperation,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000124 'division_by_zero' : DivisionByZero,
Raymond Hettinger5aa478b2004-07-09 10:02:53 +0000125 'division_impossible' : InvalidOperation,
126 'division_undefined' : InvalidOperation,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000127 'inexact' : Inexact,
Raymond Hettinger5aa478b2004-07-09 10:02:53 +0000128 'invalid_context' : InvalidOperation,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000129 'invalid_operation' : InvalidOperation,
130 'overflow' : Overflow,
131 'rounded' : Rounded,
132 'subnormal' : Subnormal,
133 'underflow' : Underflow}
134
135
136def Nonfunction(*args):
137 """Doesn't do anything."""
138 return None
139
140RoundingDict = {'ceiling' : ROUND_CEILING, #Maps test-case names to roundings.
141 'down' : ROUND_DOWN,
142 'floor' : ROUND_FLOOR,
143 'half_down' : ROUND_HALF_DOWN,
144 'half_even' : ROUND_HALF_EVEN,
145 'half_up' : ROUND_HALF_UP,
Facundo Batista353750c2007-09-13 18:13:15 +0000146 'up' : ROUND_UP,
147 '05up' : ROUND_05UP}
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000148
149# Name adapter to be able to change the Decimal and Context
150# interface without changing the test files from Cowlishaw
Facundo Batista1a191df2007-10-02 17:01:24 +0000151nameAdapter = {'and':'logical_and',
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000152 'apply':'_apply',
Facundo Batista353750c2007-09-13 18:13:15 +0000153 'class':'number_class',
154 'comparesig':'compare_signal',
155 'comparetotal':'compare_total',
156 'comparetotmag':'compare_total_mag',
Facundo Batista353750c2007-09-13 18:13:15 +0000157 'copy':'copy_decimal',
Facundo Batista1a191df2007-10-02 17:01:24 +0000158 'copyabs':'copy_abs',
Facundo Batista353750c2007-09-13 18:13:15 +0000159 'copynegate':'copy_negate',
160 'copysign':'copy_sign',
Facundo Batista1a191df2007-10-02 17:01:24 +0000161 'divideint':'divide_int',
Facundo Batista353750c2007-09-13 18:13:15 +0000162 'invert':'logical_invert',
Facundo Batista1a191df2007-10-02 17:01:24 +0000163 'iscanonical':'is_canonical',
164 'isfinite':'is_finite',
165 'isinfinite':'is_infinite',
166 'isnan':'is_nan',
167 'isnormal':'is_normal',
168 'isqnan':'is_qnan',
169 'issigned':'is_signed',
170 'issnan':'is_snan',
171 'issubnormal':'is_subnormal',
172 'iszero':'is_zero',
Facundo Batista353750c2007-09-13 18:13:15 +0000173 'maxmag':'max_mag',
174 'minmag':'min_mag',
175 'nextminus':'next_minus',
176 'nextplus':'next_plus',
177 'nexttoward':'next_toward',
Facundo Batista1a191df2007-10-02 17:01:24 +0000178 'or':'logical_or',
Facundo Batista353750c2007-09-13 18:13:15 +0000179 'reduce':'normalize',
Facundo Batista1a191df2007-10-02 17:01:24 +0000180 'remaindernear':'remainder_near',
181 'samequantum':'same_quantum',
182 'squareroot':'sqrt',
183 'toeng':'to_eng_string',
184 'tointegral':'to_integral_value',
185 'tointegralx':'to_integral_exact',
186 'tosci':'to_sci_string',
187 'xor':'logical_xor',
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000188 }
189
Facundo Batista1a191df2007-10-02 17:01:24 +0000190# The following functions return True/False rather than a Decimal instance
191
192LOGICAL_FUNCTIONS = (
193 'is_canonical',
194 'is_finite',
195 'is_infinite',
196 'is_nan',
197 'is_normal',
198 'is_qnan',
199 'is_signed',
200 'is_snan',
201 'is_subnormal',
202 'is_zero',
203 'same_quantum',
204 )
205
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000206class DecimalTest(unittest.TestCase):
207 """Class which tests the Decimal class against the test cases.
208
209 Changed for unittest.
210 """
211 def setUp(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000212 self.context = Context()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000213 self.ignore_list = ['#']
214 # Basically, a # means return NaN InvalidOperation.
215 # Different from a sNaN in trim
216
217 self.ChangeDict = {'precision' : self.change_precision,
218 'rounding' : self.change_rounding_method,
219 'maxexponent' : self.change_max_exponent,
220 'minexponent' : self.change_min_exponent,
221 'clamp' : self.change_clamp}
222
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000223 def eval_file(self, file):
224 global skip_expected
225 if skip_expected:
Benjamin Petersonbec087f2009-03-26 21:10:30 +0000226 raise unittest.SkipTest
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
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000237
238 def eval_line(self, s):
239 if s.find(' -> ') >= 0 and s[:2] != '--' and not s.startswith(' --'):
240 s = (s.split('->')[0] + '->' +
241 s.split('->')[1].split('--')[0]).strip()
242 else:
243 s = s.split('--')[0].strip()
244
245 for ignore in self.ignore_list:
246 if s.find(ignore) >= 0:
247 #print s.split()[0], 'NotImplemented--', ignore
248 return
249 if not s:
250 return
251 elif ':' in s:
252 return self.eval_directive(s)
253 else:
254 return self.eval_equation(s)
255
256 def eval_directive(self, s):
257 funct, value = map(lambda x: x.strip().lower(), s.split(':'))
258 if funct == 'rounding':
259 value = RoundingDict[value]
260 else:
261 try:
262 value = int(value)
263 except ValueError:
264 pass
265
266 funct = self.ChangeDict.get(funct, Nonfunction)
267 funct(value)
268
269 def eval_equation(self, s):
270 #global DEFAULT_PRECISION
271 #print DEFAULT_PRECISION
Raymond Hettingered20ad82004-09-04 20:09:13 +0000272
273 if not TEST_ALL and random.random() < 0.90:
274 return
275
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000276 try:
277 Sides = s.split('->')
278 L = Sides[0].strip().split()
279 id = L[0]
Facundo Batista353750c2007-09-13 18:13:15 +0000280 if DEBUG:
281 print "Test ", id,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000282 funct = L[1].lower()
283 valstemp = L[2:]
284 L = Sides[1].strip().split()
285 ans = L[0]
286 exceptions = L[1:]
287 except (TypeError, AttributeError, IndexError):
Raymond Hettingerd87ac8f2004-07-09 10:52:54 +0000288 raise InvalidOperation
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000289 def FixQuotes(val):
290 val = val.replace("''", 'SingleQuote').replace('""', 'DoubleQuote')
291 val = val.replace("'", '').replace('"', '')
292 val = val.replace('SingleQuote', "'").replace('DoubleQuote', '"')
293 return val
Mark Dickinson539bff42009-10-08 16:28:39 +0000294
295 if id in skipped_test_ids:
296 return
297
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000298 fname = nameAdapter.get(funct, funct)
299 if fname == 'rescale':
300 return
301 funct = getattr(self.context, fname)
302 vals = []
303 conglomerate = ''
304 quote = 0
305 theirexceptions = [ErrorNames[x.lower()] for x in exceptions]
306
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000307 for exception in Signals:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000308 self.context.traps[exception] = 1 #Catch these bugs...
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000309 for exception in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000310 self.context.traps[exception] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000311 for i, val in enumerate(valstemp):
312 if val.count("'") % 2 == 1:
313 quote = 1 - quote
314 if quote:
315 conglomerate = conglomerate + ' ' + val
316 continue
317 else:
318 val = conglomerate + val
319 conglomerate = ''
320 v = FixQuotes(val)
321 if fname in ('to_sci_string', 'to_eng_string'):
322 if EXTENDEDERRORTEST:
323 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000324 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000325 try:
326 funct(self.context.create_decimal(v))
327 except error:
328 pass
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000329 except Signals, e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000330 self.fail("Raised %s in %s when %s disabled" % \
331 (e, s, error))
332 else:
333 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000334 self.context.traps[error] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000335 v = self.context.create_decimal(v)
336 else:
Facundo Batista353750c2007-09-13 18:13:15 +0000337 v = Decimal(v, self.context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000338 vals.append(v)
339
340 ans = FixQuotes(ans)
341
342 if EXTENDEDERRORTEST and fname not in ('to_sci_string', 'to_eng_string'):
343 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000344 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000345 try:
346 funct(*vals)
347 except error:
348 pass
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000349 except Signals, e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000350 self.fail("Raised %s in %s when %s disabled" % \
351 (e, s, error))
352 else:
353 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000354 self.context.traps[error] = 0
Mark Dickinson4f96f5f2010-05-04 14:25:50 +0000355
356 # as above, but add traps cumulatively, to check precedence
357 ordered_errors = [e for e in OrderedSignals if e in theirexceptions]
358 for error in ordered_errors:
359 self.context.traps[error] = 1
360 try:
361 funct(*vals)
362 except error:
363 pass
364 except Signals, e:
365 self.fail("Raised %s in %s; expected %s" %
366 (type(e), s, error))
367 else:
368 self.fail("Did not raise %s in %s" % (error, s))
369 # reset traps
370 for error in ordered_errors:
371 self.context.traps[error] = 0
372
373
Facundo Batista353750c2007-09-13 18:13:15 +0000374 if DEBUG:
375 print "--", self.context
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000376 try:
377 result = str(funct(*vals))
Facundo Batista1a191df2007-10-02 17:01:24 +0000378 if fname in LOGICAL_FUNCTIONS:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000379 result = str(int(eval(result))) # 'True', 'False' -> '1', '0'
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000380 except Signals, error:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000381 self.fail("Raised %s in %s" % (error, s))
382 except: #Catch any error long enough to state the test case.
383 print "ERROR:", s
384 raise
385
386 myexceptions = self.getexceptions()
Raymond Hettingerbf440692004-07-10 14:14:37 +0000387 self.context.clear_flags()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000388
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000389 self.assertEqual(result, ans,
390 'Incorrect answer for ' + s + ' -- got ' + result)
Florent Xicluna8f43cec2010-03-21 10:51:40 +0000391 self.assertItemsEqual(myexceptions, theirexceptions,
Facundo Batista353750c2007-09-13 18:13:15 +0000392 'Incorrect flags set in ' + s + ' -- got ' + str(myexceptions))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000393
394 def getexceptions(self):
Raymond Hettingerf63ba432004-08-17 05:42:09 +0000395 return [e for e in Signals if self.context.flags[e]]
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000396
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000397 def change_precision(self, prec):
398 self.context.prec = prec
399 def change_rounding_method(self, rounding):
400 self.context.rounding = rounding
401 def change_min_exponent(self, exp):
402 self.context.Emin = exp
403 def change_max_exponent(self, exp):
404 self.context.Emax = exp
405 def change_clamp(self, clamp):
406 self.context._clamp = clamp
407
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000408
409
410# The following classes test the behaviour of Decimal according to PEP 327
411
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000412class DecimalExplicitConstructionTest(unittest.TestCase):
413 '''Unit tests for Explicit Construction cases of Decimal.'''
414
415 def test_explicit_empty(self):
416 self.assertEqual(Decimal(), Decimal("0"))
417
418 def test_explicit_from_None(self):
419 self.assertRaises(TypeError, Decimal, None)
420
421 def test_explicit_from_int(self):
422
423 #positive
424 d = Decimal(45)
425 self.assertEqual(str(d), '45')
426
427 #very large positive
428 d = Decimal(500000123)
429 self.assertEqual(str(d), '500000123')
430
431 #negative
432 d = Decimal(-45)
433 self.assertEqual(str(d), '-45')
434
435 #zero
436 d = Decimal(0)
437 self.assertEqual(str(d), '0')
438
439 def test_explicit_from_string(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000440
441 #empty
442 self.assertEqual(str(Decimal('')), 'NaN')
443
444 #int
445 self.assertEqual(str(Decimal('45')), '45')
446
447 #float
448 self.assertEqual(str(Decimal('45.34')), '45.34')
449
450 #engineer notation
451 self.assertEqual(str(Decimal('45e2')), '4.5E+3')
452
453 #just not a number
454 self.assertEqual(str(Decimal('ugly')), 'NaN')
455
Mark Dickinson59bc20b2008-01-12 01:56:00 +0000456 #leading and trailing whitespace permitted
457 self.assertEqual(str(Decimal('1.3E4 \n')), '1.3E+4')
458 self.assertEqual(str(Decimal(' -7.89')), '-7.89')
459
Mark Dickinson8e85ffa2008-03-25 18:47:59 +0000460 #unicode strings should be permitted
461 self.assertEqual(str(Decimal(u'0E-017')), '0E-17')
462 self.assertEqual(str(Decimal(u'45')), '45')
463 self.assertEqual(str(Decimal(u'-Inf')), '-Infinity')
464 self.assertEqual(str(Decimal(u'NaN123')), 'NaN123')
465
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000466 def test_explicit_from_tuples(self):
467
468 #zero
469 d = Decimal( (0, (0,), 0) )
470 self.assertEqual(str(d), '0')
471
472 #int
473 d = Decimal( (1, (4, 5), 0) )
474 self.assertEqual(str(d), '-45')
475
476 #float
477 d = Decimal( (0, (4, 5, 3, 4), -2) )
478 self.assertEqual(str(d), '45.34')
479
480 #weird
481 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
482 self.assertEqual(str(d), '-4.34913534E-17')
483
484 #wrong number of items
485 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1)) )
486
487 #bad sign
488 self.assertRaises(ValueError, Decimal, (8, (4, 3, 4, 9, 1), 2) )
Facundo Batista9b5e2312007-10-19 19:25:57 +0000489 self.assertRaises(ValueError, Decimal, (0., (4, 3, 4, 9, 1), 2) )
490 self.assertRaises(ValueError, Decimal, (Decimal(1), (4, 3, 4, 9, 1), 2))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000491
492 #bad exp
493 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 'wrong!') )
Facundo Batista9b5e2312007-10-19 19:25:57 +0000494 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 0.) )
495 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), '1') )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000496
497 #bad coefficients
498 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, None, 1), 2) )
499 self.assertRaises(ValueError, Decimal, (1, (4, -3, 4, 9, 1), 2) )
Facundo Batista9b5e2312007-10-19 19:25:57 +0000500 self.assertRaises(ValueError, Decimal, (1, (4, 10, 4, 9, 1), 2) )
Facundo Batista72bc54f2007-11-23 17:59:00 +0000501 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 'a', 1), 2) )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000502
Antoine Pitrou6032c252010-03-30 18:49:45 +0000503 def test_explicit_from_bool(self):
504 self.assertIs(bool(Decimal(0)), False)
505 self.assertIs(bool(Decimal(1)), True)
506 self.assertEqual(Decimal(False), Decimal(0))
507 self.assertEqual(Decimal(True), Decimal(1))
508
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000509 def test_explicit_from_Decimal(self):
510
511 #positive
512 d = Decimal(45)
513 e = Decimal(d)
514 self.assertEqual(str(e), '45')
515 self.assertNotEqual(id(d), id(e))
516
517 #very large positive
518 d = Decimal(500000123)
519 e = Decimal(d)
520 self.assertEqual(str(e), '500000123')
521 self.assertNotEqual(id(d), id(e))
522
523 #negative
524 d = Decimal(-45)
525 e = Decimal(d)
526 self.assertEqual(str(e), '-45')
527 self.assertNotEqual(id(d), id(e))
528
529 #zero
530 d = Decimal(0)
531 e = Decimal(d)
532 self.assertEqual(str(e), '0')
533 self.assertNotEqual(id(d), id(e))
534
Raymond Hettingered171ab2010-04-02 18:39:24 +0000535 @requires_IEEE_754
536 def test_explicit_from_float(self):
537 r = Decimal(0.1)
538 self.assertEqual(type(r), Decimal)
539 self.assertEqual(str(r),
540 '0.1000000000000000055511151231257827021181583404541015625')
541 self.assertTrue(Decimal(float('nan')).is_qnan())
542 self.assertTrue(Decimal(float('inf')).is_infinite())
543 self.assertTrue(Decimal(float('-inf')).is_infinite())
544 self.assertEqual(str(Decimal(float('nan'))),
545 str(Decimal('NaN')))
546 self.assertEqual(str(Decimal(float('inf'))),
547 str(Decimal('Infinity')))
548 self.assertEqual(str(Decimal(float('-inf'))),
549 str(Decimal('-Infinity')))
550 self.assertEqual(str(Decimal(float('-0.0'))),
551 str(Decimal('-0')))
552 for i in range(200):
553 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
554 self.assertEqual(x, float(Decimal(x))) # roundtrip
555
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000556 def test_explicit_context_create_decimal(self):
557
558 nc = copy.copy(getcontext())
559 nc.prec = 3
560
561 # empty
Raymond Hettingerfed52962004-07-14 15:41:57 +0000562 d = Decimal()
563 self.assertEqual(str(d), '0')
564 d = nc.create_decimal()
565 self.assertEqual(str(d), '0')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000566
567 # from None
568 self.assertRaises(TypeError, nc.create_decimal, None)
569
570 # from int
571 d = nc.create_decimal(456)
Ezio Melottib0f5adc2010-01-24 16:58:36 +0000572 self.assertIsInstance(d, Decimal)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000573 self.assertEqual(nc.create_decimal(45678),
574 nc.create_decimal('457E+2'))
575
576 # from string
577 d = Decimal('456789')
578 self.assertEqual(str(d), '456789')
579 d = nc.create_decimal('456789')
580 self.assertEqual(str(d), '4.57E+5')
Mark Dickinson59bc20b2008-01-12 01:56:00 +0000581 # leading and trailing whitespace should result in a NaN;
582 # spaces are already checked in Cowlishaw's test-suite, so
583 # here we just check that a trailing newline results in a NaN
584 self.assertEqual(str(nc.create_decimal('3.14\n')), 'NaN')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000585
586 # from tuples
587 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
588 self.assertEqual(str(d), '-4.34913534E-17')
589 d = nc.create_decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
590 self.assertEqual(str(d), '-4.35E-17')
591
592 # from Decimal
593 prevdec = Decimal(500000123)
594 d = Decimal(prevdec)
595 self.assertEqual(str(d), '500000123')
596 d = nc.create_decimal(prevdec)
597 self.assertEqual(str(d), '5.00E+8')
598
Serhiy Storchaka20c049d2014-10-14 21:10:56 +0300599 @requires_unicode
Mark Dickinson4326ad82009-08-02 10:59:36 +0000600 def test_unicode_digits(self):
601 test_values = {
Serhiy Storchaka20c049d2014-10-14 21:10:56 +0300602 u(r'\uff11'): '1',
603 u(r'\u0660.\u0660\u0663\u0667\u0662e-\u0663') : '0.0000372',
604 u(r'-nan\u0c68\u0c6a\u0c66\u0c66') : '-NaN2400',
Mark Dickinson4326ad82009-08-02 10:59:36 +0000605 }
606 for input, expected in test_values.items():
607 self.assertEqual(str(Decimal(input)), expected)
608
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000609
610class DecimalImplicitConstructionTest(unittest.TestCase):
611 '''Unit tests for Implicit Construction cases of Decimal.'''
612
613 def test_implicit_from_None(self):
614 self.assertRaises(TypeError, eval, 'Decimal(5) + None', globals())
615
616 def test_implicit_from_int(self):
617 #normal
618 self.assertEqual(str(Decimal(5) + 45), '50')
619 #exceeding precision
620 self.assertEqual(Decimal(5) + 123456789000, Decimal(123456789000))
621
622 def test_implicit_from_string(self):
623 self.assertRaises(TypeError, eval, 'Decimal(5) + "3"', globals())
624
625 def test_implicit_from_float(self):
626 self.assertRaises(TypeError, eval, 'Decimal(5) + 2.2', globals())
627
628 def test_implicit_from_Decimal(self):
629 self.assertEqual(Decimal(5) + Decimal(45), Decimal(50))
630
Raymond Hettinger267b8682005-03-27 10:47:39 +0000631 def test_rop(self):
632 # Allow other classes to be trained to interact with Decimals
633 class E:
634 def __divmod__(self, other):
635 return 'divmod ' + str(other)
636 def __rdivmod__(self, other):
637 return str(other) + ' rdivmod'
638 def __lt__(self, other):
639 return 'lt ' + str(other)
640 def __gt__(self, other):
641 return 'gt ' + str(other)
642 def __le__(self, other):
643 return 'le ' + str(other)
644 def __ge__(self, other):
645 return 'ge ' + str(other)
646 def __eq__(self, other):
647 return 'eq ' + str(other)
648 def __ne__(self, other):
649 return 'ne ' + str(other)
650
651 self.assertEqual(divmod(E(), Decimal(10)), 'divmod 10')
652 self.assertEqual(divmod(Decimal(10), E()), '10 rdivmod')
653 self.assertEqual(eval('Decimal(10) < E()'), 'gt 10')
654 self.assertEqual(eval('Decimal(10) > E()'), 'lt 10')
655 self.assertEqual(eval('Decimal(10) <= E()'), 'ge 10')
656 self.assertEqual(eval('Decimal(10) >= E()'), 'le 10')
657 self.assertEqual(eval('Decimal(10) == E()'), 'eq 10')
658 self.assertEqual(eval('Decimal(10) != E()'), 'ne 10')
659
660 # insert operator methods and then exercise them
Georg Brandl96c3f7f2006-03-28 08:06:35 +0000661 oplist = [
662 ('+', '__add__', '__radd__'),
663 ('-', '__sub__', '__rsub__'),
664 ('*', '__mul__', '__rmul__'),
665 ('%', '__mod__', '__rmod__'),
666 ('//', '__floordiv__', '__rfloordiv__'),
667 ('**', '__pow__', '__rpow__')
668 ]
Florent Xicluna8f43cec2010-03-21 10:51:40 +0000669 with check_py3k_warnings():
670 if 1 / 2 == 0:
671 # testing with classic division, so add __div__
672 oplist.append(('/', '__div__', '__rdiv__'))
673 else:
674 # testing with -Qnew, so add __truediv__
675 oplist.append(('/', '__truediv__', '__rtruediv__'))
Anthony Baxter4ef3a232006-03-30 12:59:11 +0000676
Georg Brandl96c3f7f2006-03-28 08:06:35 +0000677 for sym, lop, rop in oplist:
Raymond Hettinger267b8682005-03-27 10:47:39 +0000678 setattr(E, lop, lambda self, other: 'str' + lop + str(other))
679 setattr(E, rop, lambda self, other: str(other) + rop + 'str')
680 self.assertEqual(eval('E()' + sym + 'Decimal(10)'),
681 'str' + lop + '10')
682 self.assertEqual(eval('Decimal(10)' + sym + 'E()'),
683 '10' + rop + 'str')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000684
Mark Dickinson277859d2009-03-17 23:03:46 +0000685
Mark Dickinson1ddf1d82008-02-29 02:16:37 +0000686class DecimalFormatTest(unittest.TestCase):
687 '''Unit tests for the format function.'''
688 def test_formatting(self):
689 # triples giving a format, a Decimal, and the expected result
690 test_values = [
691 ('e', '0E-15', '0e-15'),
692 ('e', '2.3E-15', '2.3e-15'),
693 ('e', '2.30E+2', '2.30e+2'), # preserve significant zeros
694 ('e', '2.30000E-15', '2.30000e-15'),
695 ('e', '1.23456789123456789e40', '1.23456789123456789e+40'),
696 ('e', '1.5', '1.5e+0'),
697 ('e', '0.15', '1.5e-1'),
698 ('e', '0.015', '1.5e-2'),
699 ('e', '0.0000000000015', '1.5e-12'),
700 ('e', '15.0', '1.50e+1'),
701 ('e', '-15', '-1.5e+1'),
702 ('e', '0', '0e+0'),
703 ('e', '0E1', '0e+1'),
704 ('e', '0.0', '0e-1'),
705 ('e', '0.00', '0e-2'),
706 ('.6e', '0E-15', '0.000000e-9'),
707 ('.6e', '0', '0.000000e+6'),
708 ('.6e', '9.999999', '9.999999e+0'),
709 ('.6e', '9.9999999', '1.000000e+1'),
710 ('.6e', '-1.23e5', '-1.230000e+5'),
711 ('.6e', '1.23456789e-3', '1.234568e-3'),
712 ('f', '0', '0'),
713 ('f', '0.0', '0.0'),
714 ('f', '0E-2', '0.00'),
715 ('f', '0.00E-8', '0.0000000000'),
716 ('f', '0E1', '0'), # loses exponent information
717 ('f', '3.2E1', '32'),
718 ('f', '3.2E2', '320'),
719 ('f', '3.20E2', '320'),
720 ('f', '3.200E2', '320.0'),
721 ('f', '3.2E-6', '0.0000032'),
722 ('.6f', '0E-15', '0.000000'), # all zeros treated equally
723 ('.6f', '0E1', '0.000000'),
724 ('.6f', '0', '0.000000'),
725 ('.0f', '0', '0'), # no decimal point
726 ('.0f', '0e-2', '0'),
727 ('.0f', '3.14159265', '3'),
728 ('.1f', '3.14159265', '3.1'),
729 ('.4f', '3.14159265', '3.1416'),
730 ('.6f', '3.14159265', '3.141593'),
731 ('.7f', '3.14159265', '3.1415926'), # round-half-even!
732 ('.8f', '3.14159265', '3.14159265'),
733 ('.9f', '3.14159265', '3.141592650'),
734
735 ('g', '0', '0'),
736 ('g', '0.0', '0.0'),
737 ('g', '0E1', '0e+1'),
738 ('G', '0E1', '0E+1'),
739 ('g', '0E-5', '0.00000'),
740 ('g', '0E-6', '0.000000'),
741 ('g', '0E-7', '0e-7'),
742 ('g', '-0E2', '-0e+2'),
743 ('.0g', '3.14159265', '3'), # 0 sig fig -> 1 sig fig
744 ('.1g', '3.14159265', '3'),
745 ('.2g', '3.14159265', '3.1'),
746 ('.5g', '3.14159265', '3.1416'),
747 ('.7g', '3.14159265', '3.141593'),
748 ('.8g', '3.14159265', '3.1415926'), # round-half-even!
749 ('.9g', '3.14159265', '3.14159265'),
750 ('.10g', '3.14159265', '3.14159265'), # don't pad
751
752 ('%', '0E1', '0%'),
753 ('%', '0E0', '0%'),
754 ('%', '0E-1', '0%'),
755 ('%', '0E-2', '0%'),
756 ('%', '0E-3', '0.0%'),
757 ('%', '0E-4', '0.00%'),
758
759 ('.3%', '0', '0.000%'), # all zeros treated equally
760 ('.3%', '0E10', '0.000%'),
761 ('.3%', '0E-10', '0.000%'),
762 ('.3%', '2.34', '234.000%'),
763 ('.3%', '1.234567', '123.457%'),
764 ('.0%', '1.23', '123%'),
765
766 ('e', 'NaN', 'NaN'),
767 ('f', '-NaN123', '-NaN123'),
768 ('+g', 'NaN456', '+NaN456'),
769 ('.3e', 'Inf', 'Infinity'),
770 ('.16f', '-Inf', '-Infinity'),
771 ('.0g', '-sNaN', '-sNaN'),
772
773 ('', '1.00', '1.00'),
Mark Dickinsonb065e522009-03-17 18:01:03 +0000774
Mark Dickinson277859d2009-03-17 23:03:46 +0000775 # test alignment and padding
Mark Dickinson5cfa8042009-09-08 20:20:19 +0000776 ('6', '123', ' 123'),
Mark Dickinsonb065e522009-03-17 18:01:03 +0000777 ('<6', '123', '123 '),
778 ('>6', '123', ' 123'),
779 ('^6', '123', ' 123 '),
780 ('=+6', '123', '+ 123'),
Mark Dickinson277859d2009-03-17 23:03:46 +0000781 ('#<10', 'NaN', 'NaN#######'),
782 ('#<10', '-4.3', '-4.3######'),
783 ('#<+10', '0.0130', '+0.0130###'),
784 ('#< 10', '0.0130', ' 0.0130###'),
785 ('@>10', '-Inf', '@-Infinity'),
786 ('#>5', '-Inf', '-Infinity'),
787 ('?^5', '123', '?123?'),
788 ('%^6', '123', '%123%%'),
789 (' ^6', '-45.6', '-45.6 '),
790 ('/=10', '-45.6', '-/////45.6'),
791 ('/=+10', '45.6', '+/////45.6'),
792 ('/= 10', '45.6', ' /////45.6'),
793
794 # thousands separator
795 (',', '1234567', '1,234,567'),
796 (',', '123456', '123,456'),
797 (',', '12345', '12,345'),
798 (',', '1234', '1,234'),
799 (',', '123', '123'),
800 (',', '12', '12'),
801 (',', '1', '1'),
802 (',', '0', '0'),
803 (',', '-1234567', '-1,234,567'),
804 (',', '-123456', '-123,456'),
805 ('7,', '123456', '123,456'),
Mark Dickinson5cfa8042009-09-08 20:20:19 +0000806 ('8,', '123456', ' 123,456'),
Mark Dickinson277859d2009-03-17 23:03:46 +0000807 ('08,', '123456', '0,123,456'), # special case: extra 0 needed
808 ('+08,', '123456', '+123,456'), # but not if there's a sign
809 (' 08,', '123456', ' 123,456'),
810 ('08,', '-123456', '-123,456'),
811 ('+09,', '123456', '+0,123,456'),
812 # ... with fractional part...
813 ('07,', '1234.56', '1,234.56'),
814 ('08,', '1234.56', '1,234.56'),
815 ('09,', '1234.56', '01,234.56'),
816 ('010,', '1234.56', '001,234.56'),
817 ('011,', '1234.56', '0,001,234.56'),
818 ('012,', '1234.56', '0,001,234.56'),
819 ('08,.1f', '1234.5', '01,234.5'),
820 # no thousands separators in fraction part
821 (',', '1.23456789', '1.23456789'),
822 (',%', '123.456789', '12,345.6789%'),
823 (',e', '123456', '1.23456e+5'),
824 (',E', '123456', '1.23456E+5'),
Mark Dickinson491ea552009-09-07 16:17:41 +0000825
826 # issue 6850
827 ('a=-7.0', '0.12345', 'aaaa0.1'),
Stefan Krahce2ec492014-08-26 20:49:57 +0200828
829 # issue 22090
830 ('<^+15.20%', 'inf', '<<+Infinity%<<<'),
831 ('\x07>,%', 'sNaN1234567', 'sNaN1234567%'),
832 ('=10.10%', 'NaN123', ' NaN123%'),
Mark Dickinson1ddf1d82008-02-29 02:16:37 +0000833 ]
834 for fmt, d, result in test_values:
835 self.assertEqual(format(Decimal(d), fmt), result)
836
Mark Dickinson277859d2009-03-17 23:03:46 +0000837 def test_n_format(self):
838 try:
839 from locale import CHAR_MAX
840 except ImportError:
Zachary Ware1f702212013-12-10 14:09:20 -0600841 self.skipTest('locale.CHAR_MAX not available')
Mark Dickinson277859d2009-03-17 23:03:46 +0000842
843 # Set up some localeconv-like dictionaries
844 en_US = {
845 'decimal_point' : '.',
846 'grouping' : [3, 3, 0],
847 'thousands_sep': ','
848 }
849
850 fr_FR = {
851 'decimal_point' : ',',
852 'grouping' : [CHAR_MAX],
853 'thousands_sep' : ''
854 }
855
856 ru_RU = {
857 'decimal_point' : ',',
858 'grouping' : [3, 3, 0],
859 'thousands_sep' : ' '
860 }
861
862 crazy = {
863 'decimal_point' : '&',
864 'grouping' : [1, 4, 2, CHAR_MAX],
865 'thousands_sep' : '-'
866 }
867
868
869 def get_fmt(x, locale, fmt='n'):
870 return Decimal.__format__(Decimal(x), fmt, _localeconv=locale)
871
872 self.assertEqual(get_fmt(Decimal('12.7'), en_US), '12.7')
873 self.assertEqual(get_fmt(Decimal('12.7'), fr_FR), '12,7')
874 self.assertEqual(get_fmt(Decimal('12.7'), ru_RU), '12,7')
875 self.assertEqual(get_fmt(Decimal('12.7'), crazy), '1-2&7')
876
877 self.assertEqual(get_fmt(123456789, en_US), '123,456,789')
878 self.assertEqual(get_fmt(123456789, fr_FR), '123456789')
879 self.assertEqual(get_fmt(123456789, ru_RU), '123 456 789')
880 self.assertEqual(get_fmt(1234567890123, crazy), '123456-78-9012-3')
881
882 self.assertEqual(get_fmt(123456789, en_US, '.6n'), '1.23457e+8')
883 self.assertEqual(get_fmt(123456789, fr_FR, '.6n'), '1,23457e+8')
884 self.assertEqual(get_fmt(123456789, ru_RU, '.6n'), '1,23457e+8')
885 self.assertEqual(get_fmt(123456789, crazy, '.6n'), '1&23457e+8')
886
Mark Dickinsonb14514a2009-03-18 08:22:51 +0000887 # zero padding
888 self.assertEqual(get_fmt(1234, fr_FR, '03n'), '1234')
889 self.assertEqual(get_fmt(1234, fr_FR, '04n'), '1234')
890 self.assertEqual(get_fmt(1234, fr_FR, '05n'), '01234')
891 self.assertEqual(get_fmt(1234, fr_FR, '06n'), '001234')
892
893 self.assertEqual(get_fmt(12345, en_US, '05n'), '12,345')
894 self.assertEqual(get_fmt(12345, en_US, '06n'), '12,345')
895 self.assertEqual(get_fmt(12345, en_US, '07n'), '012,345')
896 self.assertEqual(get_fmt(12345, en_US, '08n'), '0,012,345')
897 self.assertEqual(get_fmt(12345, en_US, '09n'), '0,012,345')
898 self.assertEqual(get_fmt(12345, en_US, '010n'), '00,012,345')
899
900 self.assertEqual(get_fmt(123456, crazy, '06n'), '1-2345-6')
901 self.assertEqual(get_fmt(123456, crazy, '07n'), '1-2345-6')
902 self.assertEqual(get_fmt(123456, crazy, '08n'), '1-2345-6')
903 self.assertEqual(get_fmt(123456, crazy, '09n'), '01-2345-6')
904 self.assertEqual(get_fmt(123456, crazy, '010n'), '0-01-2345-6')
905 self.assertEqual(get_fmt(123456, crazy, '011n'), '0-01-2345-6')
906 self.assertEqual(get_fmt(123456, crazy, '012n'), '00-01-2345-6')
907 self.assertEqual(get_fmt(123456, crazy, '013n'), '000-01-2345-6')
908
Serhiy Storchakaad9a1ba2015-02-18 08:04:26 +0200909 @run_with_locale('LC_ALL', 'ps_AF.UTF-8')
910 def test_wide_char_separator_decimal_point(self):
911 # locale with wide char separator and decimal point
912 import locale
913
914 decimal_point = locale.localeconv()['decimal_point']
915 thousands_sep = locale.localeconv()['thousands_sep']
916 if decimal_point != '\xd9\xab':
917 self.skipTest('inappropriate decimal point separator'
918 '({!r} not {!r})'.format(decimal_point, '\xd9\xab'))
919 if thousands_sep != '\xd9\xac':
920 self.skipTest('inappropriate thousands separator'
921 '({!r} not {!r})'.format(thousands_sep, '\xd9\xac'))
922
923 self.assertEqual(format(Decimal('100000000.123'), 'n'),
924 '100\xd9\xac000\xd9\xac000\xd9\xab123')
925
Mark Dickinson277859d2009-03-17 23:03:46 +0000926
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000927class DecimalArithmeticOperatorsTest(unittest.TestCase):
928 '''Unit tests for all arithmetic operators, binary and unary.'''
929
930 def test_addition(self):
931
932 d1 = Decimal('-11.1')
933 d2 = Decimal('22.2')
934
935 #two Decimals
936 self.assertEqual(d1+d2, Decimal('11.1'))
937 self.assertEqual(d2+d1, Decimal('11.1'))
938
939 #with other type, left
940 c = d1 + 5
941 self.assertEqual(c, Decimal('-6.1'))
942 self.assertEqual(type(c), type(d1))
943
944 #with other type, right
945 c = 5 + d1
946 self.assertEqual(c, Decimal('-6.1'))
947 self.assertEqual(type(c), type(d1))
948
949 #inline with decimal
950 d1 += d2
951 self.assertEqual(d1, Decimal('11.1'))
952
953 #inline with other type
954 d1 += 5
955 self.assertEqual(d1, Decimal('16.1'))
956
957 def test_subtraction(self):
958
959 d1 = Decimal('-11.1')
960 d2 = Decimal('22.2')
961
962 #two Decimals
963 self.assertEqual(d1-d2, Decimal('-33.3'))
964 self.assertEqual(d2-d1, Decimal('33.3'))
965
966 #with other type, left
967 c = d1 - 5
968 self.assertEqual(c, Decimal('-16.1'))
969 self.assertEqual(type(c), type(d1))
970
971 #with other type, right
972 c = 5 - d1
973 self.assertEqual(c, Decimal('16.1'))
974 self.assertEqual(type(c), type(d1))
975
976 #inline with decimal
977 d1 -= d2
978 self.assertEqual(d1, Decimal('-33.3'))
979
980 #inline with other type
981 d1 -= 5
982 self.assertEqual(d1, Decimal('-38.3'))
983
984 def test_multiplication(self):
985
986 d1 = Decimal('-5')
987 d2 = Decimal('3')
988
989 #two Decimals
990 self.assertEqual(d1*d2, Decimal('-15'))
991 self.assertEqual(d2*d1, Decimal('-15'))
992
993 #with other type, left
994 c = d1 * 5
995 self.assertEqual(c, Decimal('-25'))
996 self.assertEqual(type(c), type(d1))
997
998 #with other type, right
999 c = 5 * d1
1000 self.assertEqual(c, Decimal('-25'))
1001 self.assertEqual(type(c), type(d1))
1002
1003 #inline with decimal
1004 d1 *= d2
1005 self.assertEqual(d1, Decimal('-15'))
1006
1007 #inline with other type
1008 d1 *= 5
1009 self.assertEqual(d1, Decimal('-75'))
1010
1011 def test_division(self):
1012
1013 d1 = Decimal('-5')
1014 d2 = Decimal('2')
1015
1016 #two Decimals
1017 self.assertEqual(d1/d2, Decimal('-2.5'))
1018 self.assertEqual(d2/d1, Decimal('-0.4'))
1019
1020 #with other type, left
1021 c = d1 / 4
1022 self.assertEqual(c, Decimal('-1.25'))
1023 self.assertEqual(type(c), type(d1))
1024
1025 #with other type, right
1026 c = 4 / d1
1027 self.assertEqual(c, Decimal('-0.8'))
1028 self.assertEqual(type(c), type(d1))
1029
1030 #inline with decimal
1031 d1 /= d2
1032 self.assertEqual(d1, Decimal('-2.5'))
1033
1034 #inline with other type
1035 d1 /= 4
1036 self.assertEqual(d1, Decimal('-0.625'))
1037
1038 def test_floor_division(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001039
1040 d1 = Decimal('5')
1041 d2 = Decimal('2')
1042
1043 #two Decimals
1044 self.assertEqual(d1//d2, Decimal('2'))
1045 self.assertEqual(d2//d1, Decimal('0'))
1046
1047 #with other type, left
1048 c = d1 // 4
1049 self.assertEqual(c, Decimal('1'))
1050 self.assertEqual(type(c), type(d1))
1051
1052 #with other type, right
1053 c = 7 // d1
1054 self.assertEqual(c, Decimal('1'))
1055 self.assertEqual(type(c), type(d1))
1056
1057 #inline with decimal
1058 d1 //= d2
1059 self.assertEqual(d1, Decimal('2'))
1060
1061 #inline with other type
1062 d1 //= 2
1063 self.assertEqual(d1, Decimal('1'))
1064
1065 def test_powering(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001066
1067 d1 = Decimal('5')
1068 d2 = Decimal('2')
1069
1070 #two Decimals
1071 self.assertEqual(d1**d2, Decimal('25'))
1072 self.assertEqual(d2**d1, Decimal('32'))
1073
1074 #with other type, left
1075 c = d1 ** 4
1076 self.assertEqual(c, Decimal('625'))
1077 self.assertEqual(type(c), type(d1))
1078
1079 #with other type, right
1080 c = 7 ** d1
1081 self.assertEqual(c, Decimal('16807'))
1082 self.assertEqual(type(c), type(d1))
1083
1084 #inline with decimal
1085 d1 **= d2
1086 self.assertEqual(d1, Decimal('25'))
1087
1088 #inline with other type
1089 d1 **= 4
1090 self.assertEqual(d1, Decimal('390625'))
1091
1092 def test_module(self):
1093
1094 d1 = Decimal('5')
1095 d2 = Decimal('2')
1096
1097 #two Decimals
1098 self.assertEqual(d1%d2, Decimal('1'))
1099 self.assertEqual(d2%d1, Decimal('2'))
1100
1101 #with other type, left
1102 c = d1 % 4
1103 self.assertEqual(c, Decimal('1'))
1104 self.assertEqual(type(c), type(d1))
1105
1106 #with other type, right
1107 c = 7 % d1
1108 self.assertEqual(c, Decimal('2'))
1109 self.assertEqual(type(c), type(d1))
1110
1111 #inline with decimal
1112 d1 %= d2
1113 self.assertEqual(d1, Decimal('1'))
1114
1115 #inline with other type
1116 d1 %= 4
1117 self.assertEqual(d1, Decimal('1'))
1118
1119 def test_floor_div_module(self):
1120
1121 d1 = Decimal('5')
1122 d2 = Decimal('2')
1123
1124 #two Decimals
1125 (p, q) = divmod(d1, d2)
1126 self.assertEqual(p, Decimal('2'))
1127 self.assertEqual(q, Decimal('1'))
1128 self.assertEqual(type(p), type(d1))
1129 self.assertEqual(type(q), type(d1))
1130
1131 #with other type, left
1132 (p, q) = divmod(d1, 4)
1133 self.assertEqual(p, Decimal('1'))
1134 self.assertEqual(q, Decimal('1'))
1135 self.assertEqual(type(p), type(d1))
1136 self.assertEqual(type(q), type(d1))
1137
1138 #with other type, right
1139 (p, q) = divmod(7, d1)
1140 self.assertEqual(p, Decimal('1'))
1141 self.assertEqual(q, Decimal('2'))
1142 self.assertEqual(type(p), type(d1))
1143 self.assertEqual(type(q), type(d1))
1144
1145 def test_unary_operators(self):
1146 self.assertEqual(+Decimal(45), Decimal(+45)) # +
1147 self.assertEqual(-Decimal(45), Decimal(-45)) # -
1148 self.assertEqual(abs(Decimal(45)), abs(Decimal(-45))) # abs
1149
Mark Dickinson2fc92632008-02-06 22:10:50 +00001150 def test_nan_comparisons(self):
Mark Dickinsone096e822010-04-02 10:17:07 +00001151 # comparisons involving signaling nans signal InvalidOperation
1152
1153 # order comparisons (<, <=, >, >=) involving only quiet nans
1154 # also signal InvalidOperation
1155
1156 # equality comparisons (==, !=) involving only quiet nans
1157 # don't signal, but return False or True respectively.
1158
Mark Dickinson2fc92632008-02-06 22:10:50 +00001159 n = Decimal('NaN')
1160 s = Decimal('sNaN')
1161 i = Decimal('Inf')
1162 f = Decimal('2')
Mark Dickinsone096e822010-04-02 10:17:07 +00001163
1164 qnan_pairs = (n, n), (n, i), (i, n), (n, f), (f, n)
1165 snan_pairs = (s, n), (n, s), (s, i), (i, s), (s, f), (f, s), (s, s)
1166 order_ops = operator.lt, operator.le, operator.gt, operator.ge
1167 equality_ops = operator.eq, operator.ne
1168
1169 # results when InvalidOperation is not trapped
1170 for x, y in qnan_pairs + snan_pairs:
1171 for op in order_ops + equality_ops:
1172 got = op(x, y)
1173 expected = True if op is operator.ne else False
1174 self.assertIs(expected, got,
1175 "expected {0!r} for operator.{1}({2!r}, {3!r}); "
1176 "got {4!r}".format(
1177 expected, op.__name__, x, y, got))
1178
1179 # repeat the above, but this time trap the InvalidOperation
1180 with localcontext() as ctx:
1181 ctx.traps[InvalidOperation] = 1
1182
1183 for x, y in qnan_pairs:
1184 for op in equality_ops:
1185 got = op(x, y)
1186 expected = True if op is operator.ne else False
1187 self.assertIs(expected, got,
1188 "expected {0!r} for "
1189 "operator.{1}({2!r}, {3!r}); "
1190 "got {4!r}".format(
1191 expected, op.__name__, x, y, got))
1192
1193 for x, y in snan_pairs:
1194 for op in equality_ops:
1195 self.assertRaises(InvalidOperation, operator.eq, x, y)
1196 self.assertRaises(InvalidOperation, operator.ne, x, y)
1197
1198 for x, y in qnan_pairs + snan_pairs:
1199 for op in order_ops:
1200 self.assertRaises(InvalidOperation, op, x, y)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001201
Mark Dickinson6d8effb2010-02-18 14:27:02 +00001202 def test_copy_sign(self):
1203 d = Decimal(1).copy_sign(Decimal(-2))
1204
1205 self.assertEqual(Decimal(1).copy_sign(-2), d)
1206 self.assertRaises(TypeError, Decimal(1).copy_sign, '-2')
1207
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001208# The following are two functions used to test threading in the next class
1209
1210def thfunc1(cls):
1211 d1 = Decimal(1)
1212 d3 = Decimal(3)
Facundo Batista64156672008-03-22 02:45:37 +00001213 test1 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001214 cls.synchro.wait()
Facundo Batista64156672008-03-22 02:45:37 +00001215 test2 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001216 cls.finish1.set()
Facundo Batista64156672008-03-22 02:45:37 +00001217
Facundo Batistaee340e52008-05-02 17:39:00 +00001218 cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
1219 cls.assertEqual(test2, Decimal('0.3333333333333333333333333333'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001220
1221def thfunc2(cls):
1222 d1 = Decimal(1)
1223 d3 = Decimal(3)
Facundo Batista64156672008-03-22 02:45:37 +00001224 test1 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001225 thiscontext = getcontext()
1226 thiscontext.prec = 18
Facundo Batista64156672008-03-22 02:45:37 +00001227 test2 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001228 cls.synchro.set()
1229 cls.finish2.set()
Facundo Batista64156672008-03-22 02:45:37 +00001230
Facundo Batistaee340e52008-05-02 17:39:00 +00001231 cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
Facundo Batista64156672008-03-22 02:45:37 +00001232 cls.assertEqual(test2, Decimal('0.333333333333333333'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001233
1234
Zachary Ware1f702212013-12-10 14:09:20 -06001235@unittest.skipUnless(threading, 'threading required')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001236class DecimalUseOfContextTest(unittest.TestCase):
1237 '''Unit tests for Use of Context cases in Decimal.'''
1238
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001239 # Take care executing this test from IDLE, there's an issue in threading
1240 # that hangs IDLE and I couldn't find it
1241
1242 def test_threading(self):
1243 #Test the "threading isolation" of a Context.
1244
1245 self.synchro = threading.Event()
1246 self.finish1 = threading.Event()
1247 self.finish2 = threading.Event()
1248
1249 th1 = threading.Thread(target=thfunc1, args=(self,))
1250 th2 = threading.Thread(target=thfunc2, args=(self,))
1251
1252 th1.start()
1253 th2.start()
1254
1255 self.finish1.wait()
Thomas Woutersb3e6e8c2007-09-19 17:27:29 +00001256 self.finish2.wait()
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001257
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001258
1259class DecimalUsabilityTest(unittest.TestCase):
1260 '''Unit tests for Usability cases of Decimal.'''
1261
1262 def test_comparison_operators(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001263
1264 da = Decimal('23.42')
1265 db = Decimal('23.42')
1266 dc = Decimal('45')
1267
1268 #two Decimals
Ezio Melotti856a3be2010-04-03 14:51:00 +00001269 self.assertGreater(dc, da)
1270 self.assertGreaterEqual(dc, da)
1271 self.assertLess(da, dc)
1272 self.assertLessEqual(da, dc)
1273 self.assertEqual(da, db)
1274 self.assertNotEqual(da, dc)
1275 self.assertLessEqual(da, db)
1276 self.assertGreaterEqual(da, db)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001277 self.assertEqual(cmp(dc,da), 1)
1278 self.assertEqual(cmp(da,dc), -1)
1279 self.assertEqual(cmp(da,db), 0)
1280
1281 #a Decimal and an int
Ezio Melotti856a3be2010-04-03 14:51:00 +00001282 self.assertGreater(dc, 23)
1283 self.assertLess(23, dc)
1284 self.assertEqual(dc, 45)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001285 self.assertEqual(cmp(dc,23), 1)
1286 self.assertEqual(cmp(23,dc), -1)
1287 self.assertEqual(cmp(dc,45), 0)
1288
1289 #a Decimal and uncomparable
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001290 self.assertNotEqual(da, 'ugly')
1291 self.assertNotEqual(da, 32.7)
1292 self.assertNotEqual(da, object())
1293 self.assertNotEqual(da, object)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001294
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001295 # sortable
1296 a = map(Decimal, xrange(100))
1297 b = a[:]
1298 random.shuffle(a)
1299 a.sort()
1300 self.assertEqual(a, b)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001301
Facundo Batista353750c2007-09-13 18:13:15 +00001302 # with None
Florent Xicluna8f43cec2010-03-21 10:51:40 +00001303 with check_py3k_warnings():
1304 self.assertFalse(Decimal(1) < None)
1305 self.assertTrue(Decimal(1) > None)
Facundo Batista353750c2007-09-13 18:13:15 +00001306
Mark Dickinson99d80962010-04-02 08:53:22 +00001307 def test_decimal_float_comparison(self):
1308 da = Decimal('0.25')
1309 db = Decimal('3.0')
Ezio Melotti856a3be2010-04-03 14:51:00 +00001310 self.assertLess(da, 3.0)
1311 self.assertLessEqual(da, 3.0)
1312 self.assertGreater(db, 0.25)
1313 self.assertGreaterEqual(db, 0.25)
1314 self.assertNotEqual(da, 1.5)
1315 self.assertEqual(da, 0.25)
1316 self.assertGreater(3.0, da)
1317 self.assertGreaterEqual(3.0, da)
1318 self.assertLess(0.25, db)
1319 self.assertLessEqual(0.25, db)
1320 self.assertNotEqual(0.25, db)
1321 self.assertEqual(3.0, db)
1322 self.assertNotEqual(0.1, Decimal('0.1'))
Mark Dickinson99d80962010-04-02 08:53:22 +00001323
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001324 def test_copy_and_deepcopy_methods(self):
1325 d = Decimal('43.24')
1326 c = copy.copy(d)
1327 self.assertEqual(id(c), id(d))
1328 dc = copy.deepcopy(d)
1329 self.assertEqual(id(dc), id(d))
1330
1331 def test_hash_method(self):
1332 #just that it's hashable
1333 hash(Decimal(23))
Mark Dickinsonf3eeca12010-04-02 10:35:12 +00001334 hash(Decimal('Infinity'))
1335 hash(Decimal('-Infinity'))
1336 hash(Decimal('nan123'))
1337 hash(Decimal('-NaN'))
Facundo Batista8c202442007-09-19 17:53:25 +00001338
1339 test_values = [Decimal(sign*(2**m + n))
1340 for m in [0, 14, 15, 16, 17, 30, 31,
1341 32, 33, 62, 63, 64, 65, 66]
1342 for n in range(-10, 10)
1343 for sign in [-1, 1]]
1344 test_values.extend([
1345 Decimal("-0"), # zeros
1346 Decimal("0.00"),
1347 Decimal("-0.000"),
1348 Decimal("0E10"),
1349 Decimal("-0E12"),
1350 Decimal("10.0"), # negative exponent
1351 Decimal("-23.00000"),
1352 Decimal("1230E100"), # positive exponent
1353 Decimal("-4.5678E50"),
1354 # a value for which hash(n) != hash(n % (2**64-1))
1355 # in Python pre-2.6
1356 Decimal(2**64 + 2**32 - 1),
1357 # selection of values which fail with the old (before
1358 # version 2.6) long.__hash__
1359 Decimal("1.634E100"),
1360 Decimal("90.697E100"),
1361 Decimal("188.83E100"),
1362 Decimal("1652.9E100"),
1363 Decimal("56531E100"),
1364 ])
1365
1366 # check that hash(d) == hash(int(d)) for integral values
1367 for value in test_values:
1368 self.assertEqual(hash(value), hash(int(value)))
1369
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001370 #the same hash that to an int
1371 self.assertEqual(hash(Decimal(23)), hash(23))
Mark Dickinsonf3eeca12010-04-02 10:35:12 +00001372 self.assertRaises(TypeError, hash, Decimal('sNaN'))
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001373 self.assertTrue(hash(Decimal('Inf')))
1374 self.assertTrue(hash(Decimal('-Inf')))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001375
Mark Dickinson99d80962010-04-02 08:53:22 +00001376 # check that the hashes of a Decimal float match when they
1377 # represent exactly the same values
1378 test_strings = ['inf', '-Inf', '0.0', '-.0e1',
1379 '34.0', '2.5', '112390.625', '-0.515625']
1380 for s in test_strings:
1381 f = float(s)
1382 d = Decimal(s)
1383 self.assertEqual(hash(f), hash(d))
1384
Facundo Batista52b25792008-01-08 12:25:20 +00001385 # check that the value of the hash doesn't depend on the
1386 # current context (issue #1757)
1387 c = getcontext()
1388 old_precision = c.prec
1389 x = Decimal("123456789.1")
1390
1391 c.prec = 6
1392 h1 = hash(x)
1393 c.prec = 10
1394 h2 = hash(x)
1395 c.prec = 16
1396 h3 = hash(x)
1397
1398 self.assertEqual(h1, h2)
1399 self.assertEqual(h1, h3)
1400 c.prec = old_precision
1401
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001402 def test_min_and_max_methods(self):
1403
1404 d1 = Decimal('15.32')
1405 d2 = Decimal('28.5')
1406 l1 = 15
1407 l2 = 28
1408
1409 #between Decimals
Ezio Melotti856a3be2010-04-03 14:51:00 +00001410 self.assertIs(min(d1,d2), d1)
1411 self.assertIs(min(d2,d1), d1)
1412 self.assertIs(max(d1,d2), d2)
1413 self.assertIs(max(d2,d1), d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001414
1415 #between Decimal and long
Ezio Melotti856a3be2010-04-03 14:51:00 +00001416 self.assertIs(min(d1,l2), d1)
1417 self.assertIs(min(l2,d1), d1)
1418 self.assertIs(max(l1,d2), d2)
1419 self.assertIs(max(d2,l1), d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001420
1421 def test_as_nonzero(self):
1422 #as false
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001423 self.assertFalse(Decimal(0))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001424 #as true
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001425 self.assertTrue(Decimal('0.372'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001426
1427 def test_tostring_methods(self):
1428 #Test str and repr methods.
1429
1430 d = Decimal('15.32')
1431 self.assertEqual(str(d), '15.32') # str
Raymond Hettingerabe32372008-02-14 02:41:22 +00001432 self.assertEqual(repr(d), "Decimal('15.32')") # repr
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001433
Mark Dickinson8e85ffa2008-03-25 18:47:59 +00001434 # result type of string methods should be str, not unicode
1435 unicode_inputs = [u'123.4', u'0.5E2', u'Infinity', u'sNaN',
1436 u'-0.0E100', u'-NaN001', u'-Inf']
1437
1438 for u in unicode_inputs:
1439 d = Decimal(u)
1440 self.assertEqual(type(str(d)), str)
1441 self.assertEqual(type(repr(d)), str)
1442 self.assertEqual(type(d.to_eng_string()), str)
1443
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001444 def test_tonum_methods(self):
1445 #Test float, int and long methods.
1446
1447 d1 = Decimal('66')
1448 d2 = Decimal('15.32')
1449
1450 #int
1451 self.assertEqual(int(d1), 66)
1452 self.assertEqual(int(d2), 15)
1453
1454 #long
1455 self.assertEqual(long(d1), 66)
1456 self.assertEqual(long(d2), 15)
1457
1458 #float
1459 self.assertEqual(float(d1), 66)
1460 self.assertEqual(float(d2), 15.32)
1461
Mark Dickinson088cec32012-08-24 20:06:30 +01001462 def test_nan_to_float(self):
1463 # Test conversions of decimal NANs to float.
1464 # See http://bugs.python.org/issue15544
1465 for s in ('nan', 'nan1234', '-nan', '-nan2468'):
1466 f = float(Decimal(s))
1467 self.assertTrue(math.isnan(f))
Mark Dickinson088cec32012-08-24 20:06:30 +01001468
1469 def test_snan_to_float(self):
1470 for s in ('snan', '-snan', 'snan1357', '-snan1234'):
1471 d = Decimal(s)
1472 self.assertRaises(ValueError, float, d)
1473
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001474 def test_eval_round_trip(self):
1475
1476 #with zero
1477 d = Decimal( (0, (0,), 0) )
1478 self.assertEqual(d, eval(repr(d)))
1479
1480 #int
1481 d = Decimal( (1, (4, 5), 0) )
1482 self.assertEqual(d, eval(repr(d)))
1483
1484 #float
1485 d = Decimal( (0, (4, 5, 3, 4), -2) )
1486 self.assertEqual(d, eval(repr(d)))
1487
1488 #weird
1489 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1490 self.assertEqual(d, eval(repr(d)))
1491
1492 def test_as_tuple(self):
1493
1494 #with zero
1495 d = Decimal(0)
1496 self.assertEqual(d.as_tuple(), (0, (0,), 0) )
1497
1498 #int
1499 d = Decimal(-45)
1500 self.assertEqual(d.as_tuple(), (1, (4, 5), 0) )
1501
1502 #complicated string
1503 d = Decimal("-4.34913534E-17")
1504 self.assertEqual(d.as_tuple(), (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1505
1506 #inf
1507 d = Decimal("Infinity")
1508 self.assertEqual(d.as_tuple(), (0, (0,), 'F') )
1509
Facundo Batista9b5e2312007-10-19 19:25:57 +00001510 #leading zeros in coefficient should be stripped
1511 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), -2) )
1512 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), -2) )
1513 d = Decimal( (1, (0, 0, 0), 37) )
1514 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1515 d = Decimal( (1, (), 37) )
1516 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1517
1518 #leading zeros in NaN diagnostic info should be stripped
1519 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), 'n') )
1520 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), 'n') )
1521 d = Decimal( (1, (0, 0, 0), 'N') )
1522 self.assertEqual(d.as_tuple(), (1, (), 'N') )
1523 d = Decimal( (1, (), 'n') )
1524 self.assertEqual(d.as_tuple(), (1, (), 'n') )
1525
1526 #coefficient in infinity should be ignored
1527 d = Decimal( (0, (4, 5, 3, 4), 'F') )
1528 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
1529 d = Decimal( (1, (0, 2, 7, 1), 'F') )
1530 self.assertEqual(d.as_tuple(), (1, (0,), 'F'))
1531
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001532 def test_immutability_operations(self):
1533 # Do operations and check that it didn't change change internal objects.
1534
1535 d1 = Decimal('-25e55')
1536 b1 = Decimal('-25e55')
Facundo Batista353750c2007-09-13 18:13:15 +00001537 d2 = Decimal('33e+33')
1538 b2 = Decimal('33e+33')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001539
1540 def checkSameDec(operation, useOther=False):
1541 if useOther:
1542 eval("d1." + operation + "(d2)")
1543 self.assertEqual(d1._sign, b1._sign)
1544 self.assertEqual(d1._int, b1._int)
1545 self.assertEqual(d1._exp, b1._exp)
1546 self.assertEqual(d2._sign, b2._sign)
1547 self.assertEqual(d2._int, b2._int)
1548 self.assertEqual(d2._exp, b2._exp)
1549 else:
1550 eval("d1." + operation + "()")
1551 self.assertEqual(d1._sign, b1._sign)
1552 self.assertEqual(d1._int, b1._int)
1553 self.assertEqual(d1._exp, b1._exp)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001554
1555 Decimal(d1)
1556 self.assertEqual(d1._sign, b1._sign)
1557 self.assertEqual(d1._int, b1._int)
1558 self.assertEqual(d1._exp, b1._exp)
1559
1560 checkSameDec("__abs__")
1561 checkSameDec("__add__", True)
1562 checkSameDec("__div__", True)
1563 checkSameDec("__divmod__", True)
Mark Dickinson2fc92632008-02-06 22:10:50 +00001564 checkSameDec("__eq__", True)
1565 checkSameDec("__ne__", True)
1566 checkSameDec("__le__", True)
1567 checkSameDec("__lt__", True)
1568 checkSameDec("__ge__", True)
1569 checkSameDec("__gt__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001570 checkSameDec("__float__")
1571 checkSameDec("__floordiv__", True)
1572 checkSameDec("__hash__")
1573 checkSameDec("__int__")
Raymond Hettinger5a053642008-01-24 19:05:29 +00001574 checkSameDec("__trunc__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001575 checkSameDec("__long__")
1576 checkSameDec("__mod__", True)
1577 checkSameDec("__mul__", True)
1578 checkSameDec("__neg__")
1579 checkSameDec("__nonzero__")
1580 checkSameDec("__pos__")
1581 checkSameDec("__pow__", True)
1582 checkSameDec("__radd__", True)
1583 checkSameDec("__rdiv__", True)
1584 checkSameDec("__rdivmod__", True)
1585 checkSameDec("__repr__")
1586 checkSameDec("__rfloordiv__", True)
1587 checkSameDec("__rmod__", True)
1588 checkSameDec("__rmul__", True)
1589 checkSameDec("__rpow__", True)
1590 checkSameDec("__rsub__", True)
1591 checkSameDec("__str__")
1592 checkSameDec("__sub__", True)
1593 checkSameDec("__truediv__", True)
1594 checkSameDec("adjusted")
1595 checkSameDec("as_tuple")
1596 checkSameDec("compare", True)
1597 checkSameDec("max", True)
1598 checkSameDec("min", True)
1599 checkSameDec("normalize")
1600 checkSameDec("quantize", True)
1601 checkSameDec("remainder_near", True)
1602 checkSameDec("same_quantum", True)
1603 checkSameDec("sqrt")
1604 checkSameDec("to_eng_string")
1605 checkSameDec("to_integral")
1606
Facundo Batista6c398da2007-09-17 17:30:13 +00001607 def test_subclassing(self):
1608 # Different behaviours when subclassing Decimal
1609
1610 class MyDecimal(Decimal):
1611 pass
1612
1613 d1 = MyDecimal(1)
1614 d2 = MyDecimal(2)
1615 d = d1 + d2
Ezio Melotti856a3be2010-04-03 14:51:00 +00001616 self.assertIs(type(d), Decimal)
Facundo Batista6c398da2007-09-17 17:30:13 +00001617
1618 d = d1.max(d2)
Ezio Melotti856a3be2010-04-03 14:51:00 +00001619 self.assertIs(type(d), Decimal)
Facundo Batista6c398da2007-09-17 17:30:13 +00001620
Mark Dickinson3b24ccb2008-03-25 14:33:23 +00001621 def test_implicit_context(self):
1622 # Check results when context given implicitly. (Issue 2478)
1623 c = getcontext()
1624 self.assertEqual(str(Decimal(0).sqrt()),
1625 str(c.sqrt(Decimal(0))))
1626
Mark Dickinson0c673122009-10-29 12:04:00 +00001627 def test_conversions_from_int(self):
1628 # Check that methods taking a second Decimal argument will
1629 # always accept an integer in place of a Decimal.
1630 self.assertEqual(Decimal(4).compare(3),
1631 Decimal(4).compare(Decimal(3)))
1632 self.assertEqual(Decimal(4).compare_signal(3),
1633 Decimal(4).compare_signal(Decimal(3)))
1634 self.assertEqual(Decimal(4).compare_total(3),
1635 Decimal(4).compare_total(Decimal(3)))
1636 self.assertEqual(Decimal(4).compare_total_mag(3),
1637 Decimal(4).compare_total_mag(Decimal(3)))
1638 self.assertEqual(Decimal(10101).logical_and(1001),
1639 Decimal(10101).logical_and(Decimal(1001)))
1640 self.assertEqual(Decimal(10101).logical_or(1001),
1641 Decimal(10101).logical_or(Decimal(1001)))
1642 self.assertEqual(Decimal(10101).logical_xor(1001),
1643 Decimal(10101).logical_xor(Decimal(1001)))
1644 self.assertEqual(Decimal(567).max(123),
1645 Decimal(567).max(Decimal(123)))
1646 self.assertEqual(Decimal(567).max_mag(123),
1647 Decimal(567).max_mag(Decimal(123)))
1648 self.assertEqual(Decimal(567).min(123),
1649 Decimal(567).min(Decimal(123)))
1650 self.assertEqual(Decimal(567).min_mag(123),
1651 Decimal(567).min_mag(Decimal(123)))
1652 self.assertEqual(Decimal(567).next_toward(123),
1653 Decimal(567).next_toward(Decimal(123)))
1654 self.assertEqual(Decimal(1234).quantize(100),
1655 Decimal(1234).quantize(Decimal(100)))
1656 self.assertEqual(Decimal(768).remainder_near(1234),
1657 Decimal(768).remainder_near(Decimal(1234)))
1658 self.assertEqual(Decimal(123).rotate(1),
1659 Decimal(123).rotate(Decimal(1)))
1660 self.assertEqual(Decimal(1234).same_quantum(1000),
1661 Decimal(1234).same_quantum(Decimal(1000)))
1662 self.assertEqual(Decimal('9.123').scaleb(-100),
1663 Decimal('9.123').scaleb(Decimal(-100)))
1664 self.assertEqual(Decimal(456).shift(-1),
1665 Decimal(456).shift(Decimal(-1)))
1666
1667 self.assertEqual(Decimal(-12).fma(Decimal(45), 67),
1668 Decimal(-12).fma(Decimal(45), Decimal(67)))
1669 self.assertEqual(Decimal(-12).fma(45, 67),
1670 Decimal(-12).fma(Decimal(45), Decimal(67)))
1671 self.assertEqual(Decimal(-12).fma(45, Decimal(67)),
1672 Decimal(-12).fma(Decimal(45), Decimal(67)))
1673
Facundo Batista6c398da2007-09-17 17:30:13 +00001674
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001675class DecimalPythonAPItests(unittest.TestCase):
1676
Raymond Hettinger2c8585b2009-02-03 03:37:03 +00001677 def test_abc(self):
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001678 self.assertTrue(issubclass(Decimal, numbers.Number))
Ezio Melotti856a3be2010-04-03 14:51:00 +00001679 self.assertFalse(issubclass(Decimal, numbers.Real))
Ezio Melottib0f5adc2010-01-24 16:58:36 +00001680 self.assertIsInstance(Decimal(0), numbers.Number)
Ezio Melotti856a3be2010-04-03 14:51:00 +00001681 self.assertNotIsInstance(Decimal(0), numbers.Real)
Raymond Hettinger2c8585b2009-02-03 03:37:03 +00001682
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001683 def test_pickle(self):
1684 d = Decimal('-3.141590000')
Serhiy Storchaka655720e2014-12-15 14:02:43 +02001685 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
1686 p = pickle.dumps(d, proto)
1687 e = pickle.loads(p)
1688 self.assertEqual(d, e)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001689
Raymond Hettinger5548be22004-07-05 18:49:38 +00001690 def test_int(self):
Raymond Hettinger605ed022004-11-24 07:28:48 +00001691 for x in range(-250, 250):
1692 s = '%0.2f' % (x / 100.0)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001693 # should work the same as for floats
1694 self.assertEqual(int(Decimal(s)), int(float(s)))
Raymond Hettinger605ed022004-11-24 07:28:48 +00001695 # should work the same as to_integral in the ROUND_DOWN mode
Raymond Hettinger5548be22004-07-05 18:49:38 +00001696 d = Decimal(s)
Raymond Hettinger605ed022004-11-24 07:28:48 +00001697 r = d.to_integral(ROUND_DOWN)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001698 self.assertEqual(Decimal(int(d)), r)
1699
Mark Dickinson968f1692009-09-07 18:04:58 +00001700 self.assertRaises(ValueError, int, Decimal('-nan'))
1701 self.assertRaises(ValueError, int, Decimal('snan'))
1702 self.assertRaises(OverflowError, int, Decimal('inf'))
1703 self.assertRaises(OverflowError, int, Decimal('-inf'))
1704
1705 self.assertRaises(ValueError, long, Decimal('-nan'))
1706 self.assertRaises(ValueError, long, Decimal('snan'))
1707 self.assertRaises(OverflowError, long, Decimal('inf'))
1708 self.assertRaises(OverflowError, long, Decimal('-inf'))
1709
Raymond Hettinger5a053642008-01-24 19:05:29 +00001710 def test_trunc(self):
1711 for x in range(-250, 250):
1712 s = '%0.2f' % (x / 100.0)
1713 # should work the same as for floats
1714 self.assertEqual(int(Decimal(s)), int(float(s)))
1715 # should work the same as to_integral in the ROUND_DOWN mode
1716 d = Decimal(s)
1717 r = d.to_integral(ROUND_DOWN)
Jeffrey Yasskinca2b69f2008-02-01 06:22:46 +00001718 self.assertEqual(Decimal(math.trunc(d)), r)
Raymond Hettinger5a053642008-01-24 19:05:29 +00001719
Raymond Hettingerf4d85972009-01-03 19:02:23 +00001720 def test_from_float(self):
1721
1722 class MyDecimal(Decimal):
1723 pass
1724
1725 r = MyDecimal.from_float(0.1)
1726 self.assertEqual(type(r), MyDecimal)
1727 self.assertEqual(str(r),
1728 '0.1000000000000000055511151231257827021181583404541015625')
1729 bigint = 12345678901234567890123456789
1730 self.assertEqual(MyDecimal.from_float(bigint), MyDecimal(bigint))
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001731 self.assertTrue(MyDecimal.from_float(float('nan')).is_qnan())
1732 self.assertTrue(MyDecimal.from_float(float('inf')).is_infinite())
1733 self.assertTrue(MyDecimal.from_float(float('-inf')).is_infinite())
Raymond Hettingerf4d85972009-01-03 19:02:23 +00001734 self.assertEqual(str(MyDecimal.from_float(float('nan'))),
1735 str(Decimal('NaN')))
1736 self.assertEqual(str(MyDecimal.from_float(float('inf'))),
1737 str(Decimal('Infinity')))
1738 self.assertEqual(str(MyDecimal.from_float(float('-inf'))),
1739 str(Decimal('-Infinity')))
1740 self.assertRaises(TypeError, MyDecimal.from_float, 'abc')
1741 for i in range(200):
1742 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
1743 self.assertEqual(x, float(MyDecimal.from_float(x))) # roundtrip
1744
1745 def test_create_decimal_from_float(self):
1746 context = Context(prec=5, rounding=ROUND_DOWN)
1747 self.assertEqual(
1748 context.create_decimal_from_float(math.pi),
1749 Decimal('3.1415')
1750 )
1751 context = Context(prec=5, rounding=ROUND_UP)
1752 self.assertEqual(
1753 context.create_decimal_from_float(math.pi),
1754 Decimal('3.1416')
1755 )
1756 context = Context(prec=5, traps=[Inexact])
1757 self.assertRaises(
1758 Inexact,
1759 context.create_decimal_from_float,
1760 math.pi
1761 )
1762 self.assertEqual(repr(context.create_decimal_from_float(-0.0)),
1763 "Decimal('-0')")
1764 self.assertEqual(repr(context.create_decimal_from_float(1.0)),
1765 "Decimal('1')")
1766 self.assertEqual(repr(context.create_decimal_from_float(10)),
1767 "Decimal('10')")
1768
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00001769class ContextAPItests(unittest.TestCase):
1770
1771 def test_pickle(self):
Serhiy Storchaka655720e2014-12-15 14:02:43 +02001772 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
1773 c = Context()
1774 e = pickle.loads(pickle.dumps(c, proto))
1775 for k in vars(c):
1776 v1 = vars(c)[k]
1777 v2 = vars(e)[k]
1778 self.assertEqual(v1, v2)
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00001779
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001780 def test_equality_with_other_types(self):
Ezio Melottiaa980582010-01-23 23:04:36 +00001781 self.assertIn(Decimal(10), ['a', 1.0, Decimal(10), (1,2), {}])
1782 self.assertNotIn(Decimal(10), ['a', 1.0, (1,2), {}])
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001783
Raymond Hettinger955d2b22004-08-08 20:17:45 +00001784 def test_copy(self):
1785 # All copies should be deep
1786 c = Context()
1787 d = c.copy()
1788 self.assertNotEqual(id(c), id(d))
1789 self.assertNotEqual(id(c.flags), id(d.flags))
1790 self.assertNotEqual(id(c.traps), id(d.traps))
1791
Mark Dickinson6d8effb2010-02-18 14:27:02 +00001792 def test_abs(self):
1793 c = Context()
1794 d = c.abs(Decimal(-1))
1795 self.assertEqual(c.abs(-1), d)
1796 self.assertRaises(TypeError, c.abs, '-1')
1797
1798 def test_add(self):
1799 c = Context()
1800 d = c.add(Decimal(1), Decimal(1))
1801 self.assertEqual(c.add(1, 1), d)
1802 self.assertEqual(c.add(Decimal(1), 1), d)
1803 self.assertEqual(c.add(1, Decimal(1)), d)
1804 self.assertRaises(TypeError, c.add, '1', 1)
1805 self.assertRaises(TypeError, c.add, 1, '1')
1806
1807 def test_compare(self):
1808 c = Context()
1809 d = c.compare(Decimal(1), Decimal(1))
1810 self.assertEqual(c.compare(1, 1), d)
1811 self.assertEqual(c.compare(Decimal(1), 1), d)
1812 self.assertEqual(c.compare(1, Decimal(1)), d)
1813 self.assertRaises(TypeError, c.compare, '1', 1)
1814 self.assertRaises(TypeError, c.compare, 1, '1')
1815
1816 def test_compare_signal(self):
1817 c = Context()
1818 d = c.compare_signal(Decimal(1), Decimal(1))
1819 self.assertEqual(c.compare_signal(1, 1), d)
1820 self.assertEqual(c.compare_signal(Decimal(1), 1), d)
1821 self.assertEqual(c.compare_signal(1, Decimal(1)), d)
1822 self.assertRaises(TypeError, c.compare_signal, '1', 1)
1823 self.assertRaises(TypeError, c.compare_signal, 1, '1')
1824
1825 def test_compare_total(self):
1826 c = Context()
1827 d = c.compare_total(Decimal(1), Decimal(1))
1828 self.assertEqual(c.compare_total(1, 1), d)
1829 self.assertEqual(c.compare_total(Decimal(1), 1), d)
1830 self.assertEqual(c.compare_total(1, Decimal(1)), d)
1831 self.assertRaises(TypeError, c.compare_total, '1', 1)
1832 self.assertRaises(TypeError, c.compare_total, 1, '1')
1833
1834 def test_compare_total_mag(self):
1835 c = Context()
1836 d = c.compare_total_mag(Decimal(1), Decimal(1))
1837 self.assertEqual(c.compare_total_mag(1, 1), d)
1838 self.assertEqual(c.compare_total_mag(Decimal(1), 1), d)
1839 self.assertEqual(c.compare_total_mag(1, Decimal(1)), d)
1840 self.assertRaises(TypeError, c.compare_total_mag, '1', 1)
1841 self.assertRaises(TypeError, c.compare_total_mag, 1, '1')
1842
1843 def test_copy_abs(self):
1844 c = Context()
1845 d = c.copy_abs(Decimal(-1))
1846 self.assertEqual(c.copy_abs(-1), d)
1847 self.assertRaises(TypeError, c.copy_abs, '-1')
1848
1849 def test_copy_decimal(self):
1850 c = Context()
1851 d = c.copy_decimal(Decimal(-1))
1852 self.assertEqual(c.copy_decimal(-1), d)
1853 self.assertRaises(TypeError, c.copy_decimal, '-1')
1854
1855 def test_copy_negate(self):
1856 c = Context()
1857 d = c.copy_negate(Decimal(-1))
1858 self.assertEqual(c.copy_negate(-1), d)
1859 self.assertRaises(TypeError, c.copy_negate, '-1')
1860
1861 def test_copy_sign(self):
1862 c = Context()
1863 d = c.copy_sign(Decimal(1), Decimal(-2))
1864 self.assertEqual(c.copy_sign(1, -2), d)
1865 self.assertEqual(c.copy_sign(Decimal(1), -2), d)
1866 self.assertEqual(c.copy_sign(1, Decimal(-2)), d)
1867 self.assertRaises(TypeError, c.copy_sign, '1', -2)
1868 self.assertRaises(TypeError, c.copy_sign, 1, '-2')
1869
1870 def test_divide(self):
1871 c = Context()
1872 d = c.divide(Decimal(1), Decimal(2))
1873 self.assertEqual(c.divide(1, 2), d)
1874 self.assertEqual(c.divide(Decimal(1), 2), d)
1875 self.assertEqual(c.divide(1, Decimal(2)), d)
1876 self.assertRaises(TypeError, c.divide, '1', 2)
1877 self.assertRaises(TypeError, c.divide, 1, '2')
1878
1879 def test_divide_int(self):
1880 c = Context()
1881 d = c.divide_int(Decimal(1), Decimal(2))
1882 self.assertEqual(c.divide_int(1, 2), d)
1883 self.assertEqual(c.divide_int(Decimal(1), 2), d)
1884 self.assertEqual(c.divide_int(1, Decimal(2)), d)
1885 self.assertRaises(TypeError, c.divide_int, '1', 2)
1886 self.assertRaises(TypeError, c.divide_int, 1, '2')
1887
1888 def test_divmod(self):
1889 c = Context()
1890 d = c.divmod(Decimal(1), Decimal(2))
1891 self.assertEqual(c.divmod(1, 2), d)
1892 self.assertEqual(c.divmod(Decimal(1), 2), d)
1893 self.assertEqual(c.divmod(1, Decimal(2)), d)
1894 self.assertRaises(TypeError, c.divmod, '1', 2)
1895 self.assertRaises(TypeError, c.divmod, 1, '2')
1896
1897 def test_exp(self):
1898 c = Context()
1899 d = c.exp(Decimal(10))
1900 self.assertEqual(c.exp(10), d)
1901 self.assertRaises(TypeError, c.exp, '10')
1902
1903 def test_fma(self):
1904 c = Context()
1905 d = c.fma(Decimal(2), Decimal(3), Decimal(4))
1906 self.assertEqual(c.fma(2, 3, 4), d)
1907 self.assertEqual(c.fma(Decimal(2), 3, 4), d)
1908 self.assertEqual(c.fma(2, Decimal(3), 4), d)
1909 self.assertEqual(c.fma(2, 3, Decimal(4)), d)
1910 self.assertEqual(c.fma(Decimal(2), Decimal(3), 4), d)
1911 self.assertRaises(TypeError, c.fma, '2', 3, 4)
1912 self.assertRaises(TypeError, c.fma, 2, '3', 4)
1913 self.assertRaises(TypeError, c.fma, 2, 3, '4')
1914
1915 def test_is_finite(self):
1916 c = Context()
1917 d = c.is_finite(Decimal(10))
1918 self.assertEqual(c.is_finite(10), d)
1919 self.assertRaises(TypeError, c.is_finite, '10')
1920
1921 def test_is_infinite(self):
1922 c = Context()
1923 d = c.is_infinite(Decimal(10))
1924 self.assertEqual(c.is_infinite(10), d)
1925 self.assertRaises(TypeError, c.is_infinite, '10')
1926
1927 def test_is_nan(self):
1928 c = Context()
1929 d = c.is_nan(Decimal(10))
1930 self.assertEqual(c.is_nan(10), d)
1931 self.assertRaises(TypeError, c.is_nan, '10')
1932
1933 def test_is_normal(self):
1934 c = Context()
1935 d = c.is_normal(Decimal(10))
1936 self.assertEqual(c.is_normal(10), d)
1937 self.assertRaises(TypeError, c.is_normal, '10')
1938
1939 def test_is_qnan(self):
1940 c = Context()
1941 d = c.is_qnan(Decimal(10))
1942 self.assertEqual(c.is_qnan(10), d)
1943 self.assertRaises(TypeError, c.is_qnan, '10')
1944
1945 def test_is_signed(self):
1946 c = Context()
1947 d = c.is_signed(Decimal(10))
1948 self.assertEqual(c.is_signed(10), d)
1949 self.assertRaises(TypeError, c.is_signed, '10')
1950
1951 def test_is_snan(self):
1952 c = Context()
1953 d = c.is_snan(Decimal(10))
1954 self.assertEqual(c.is_snan(10), d)
1955 self.assertRaises(TypeError, c.is_snan, '10')
1956
1957 def test_is_subnormal(self):
1958 c = Context()
1959 d = c.is_subnormal(Decimal(10))
1960 self.assertEqual(c.is_subnormal(10), d)
1961 self.assertRaises(TypeError, c.is_subnormal, '10')
1962
1963 def test_is_zero(self):
1964 c = Context()
1965 d = c.is_zero(Decimal(10))
1966 self.assertEqual(c.is_zero(10), d)
1967 self.assertRaises(TypeError, c.is_zero, '10')
1968
1969 def test_ln(self):
1970 c = Context()
1971 d = c.ln(Decimal(10))
1972 self.assertEqual(c.ln(10), d)
1973 self.assertRaises(TypeError, c.ln, '10')
1974
1975 def test_log10(self):
1976 c = Context()
1977 d = c.log10(Decimal(10))
1978 self.assertEqual(c.log10(10), d)
1979 self.assertRaises(TypeError, c.log10, '10')
1980
1981 def test_logb(self):
1982 c = Context()
1983 d = c.logb(Decimal(10))
1984 self.assertEqual(c.logb(10), d)
1985 self.assertRaises(TypeError, c.logb, '10')
1986
1987 def test_logical_and(self):
1988 c = Context()
1989 d = c.logical_and(Decimal(1), Decimal(1))
1990 self.assertEqual(c.logical_and(1, 1), d)
1991 self.assertEqual(c.logical_and(Decimal(1), 1), d)
1992 self.assertEqual(c.logical_and(1, Decimal(1)), d)
1993 self.assertRaises(TypeError, c.logical_and, '1', 1)
1994 self.assertRaises(TypeError, c.logical_and, 1, '1')
1995
1996 def test_logical_invert(self):
1997 c = Context()
1998 d = c.logical_invert(Decimal(1000))
1999 self.assertEqual(c.logical_invert(1000), d)
2000 self.assertRaises(TypeError, c.logical_invert, '1000')
2001
2002 def test_logical_or(self):
2003 c = Context()
2004 d = c.logical_or(Decimal(1), Decimal(1))
2005 self.assertEqual(c.logical_or(1, 1), d)
2006 self.assertEqual(c.logical_or(Decimal(1), 1), d)
2007 self.assertEqual(c.logical_or(1, Decimal(1)), d)
2008 self.assertRaises(TypeError, c.logical_or, '1', 1)
2009 self.assertRaises(TypeError, c.logical_or, 1, '1')
2010
2011 def test_logical_xor(self):
2012 c = Context()
2013 d = c.logical_xor(Decimal(1), Decimal(1))
2014 self.assertEqual(c.logical_xor(1, 1), d)
2015 self.assertEqual(c.logical_xor(Decimal(1), 1), d)
2016 self.assertEqual(c.logical_xor(1, Decimal(1)), d)
2017 self.assertRaises(TypeError, c.logical_xor, '1', 1)
2018 self.assertRaises(TypeError, c.logical_xor, 1, '1')
2019
2020 def test_max(self):
2021 c = Context()
2022 d = c.max(Decimal(1), Decimal(2))
2023 self.assertEqual(c.max(1, 2), d)
2024 self.assertEqual(c.max(Decimal(1), 2), d)
2025 self.assertEqual(c.max(1, Decimal(2)), d)
2026 self.assertRaises(TypeError, c.max, '1', 2)
2027 self.assertRaises(TypeError, c.max, 1, '2')
2028
2029 def test_max_mag(self):
2030 c = Context()
2031 d = c.max_mag(Decimal(1), Decimal(2))
2032 self.assertEqual(c.max_mag(1, 2), d)
2033 self.assertEqual(c.max_mag(Decimal(1), 2), d)
2034 self.assertEqual(c.max_mag(1, Decimal(2)), d)
2035 self.assertRaises(TypeError, c.max_mag, '1', 2)
2036 self.assertRaises(TypeError, c.max_mag, 1, '2')
2037
2038 def test_min(self):
2039 c = Context()
2040 d = c.min(Decimal(1), Decimal(2))
2041 self.assertEqual(c.min(1, 2), d)
2042 self.assertEqual(c.min(Decimal(1), 2), d)
2043 self.assertEqual(c.min(1, Decimal(2)), d)
2044 self.assertRaises(TypeError, c.min, '1', 2)
2045 self.assertRaises(TypeError, c.min, 1, '2')
2046
2047 def test_min_mag(self):
2048 c = Context()
2049 d = c.min_mag(Decimal(1), Decimal(2))
2050 self.assertEqual(c.min_mag(1, 2), d)
2051 self.assertEqual(c.min_mag(Decimal(1), 2), d)
2052 self.assertEqual(c.min_mag(1, Decimal(2)), d)
2053 self.assertRaises(TypeError, c.min_mag, '1', 2)
2054 self.assertRaises(TypeError, c.min_mag, 1, '2')
2055
2056 def test_minus(self):
2057 c = Context()
2058 d = c.minus(Decimal(10))
2059 self.assertEqual(c.minus(10), d)
2060 self.assertRaises(TypeError, c.minus, '10')
2061
2062 def test_multiply(self):
2063 c = Context()
2064 d = c.multiply(Decimal(1), Decimal(2))
2065 self.assertEqual(c.multiply(1, 2), d)
2066 self.assertEqual(c.multiply(Decimal(1), 2), d)
2067 self.assertEqual(c.multiply(1, Decimal(2)), d)
2068 self.assertRaises(TypeError, c.multiply, '1', 2)
2069 self.assertRaises(TypeError, c.multiply, 1, '2')
2070
2071 def test_next_minus(self):
2072 c = Context()
2073 d = c.next_minus(Decimal(10))
2074 self.assertEqual(c.next_minus(10), d)
2075 self.assertRaises(TypeError, c.next_minus, '10')
2076
2077 def test_next_plus(self):
2078 c = Context()
2079 d = c.next_plus(Decimal(10))
2080 self.assertEqual(c.next_plus(10), d)
2081 self.assertRaises(TypeError, c.next_plus, '10')
2082
2083 def test_next_toward(self):
2084 c = Context()
2085 d = c.next_toward(Decimal(1), Decimal(2))
2086 self.assertEqual(c.next_toward(1, 2), d)
2087 self.assertEqual(c.next_toward(Decimal(1), 2), d)
2088 self.assertEqual(c.next_toward(1, Decimal(2)), d)
2089 self.assertRaises(TypeError, c.next_toward, '1', 2)
2090 self.assertRaises(TypeError, c.next_toward, 1, '2')
2091
2092 def test_normalize(self):
2093 c = Context()
2094 d = c.normalize(Decimal(10))
2095 self.assertEqual(c.normalize(10), d)
2096 self.assertRaises(TypeError, c.normalize, '10')
2097
2098 def test_number_class(self):
2099 c = Context()
2100 self.assertEqual(c.number_class(123), c.number_class(Decimal(123)))
2101 self.assertEqual(c.number_class(0), c.number_class(Decimal(0)))
2102 self.assertEqual(c.number_class(-45), c.number_class(Decimal(-45)))
2103
2104 def test_power(self):
2105 c = Context()
2106 d = c.power(Decimal(1), Decimal(4), Decimal(2))
2107 self.assertEqual(c.power(1, 4, 2), d)
2108 self.assertEqual(c.power(Decimal(1), 4, 2), d)
2109 self.assertEqual(c.power(1, Decimal(4), 2), d)
2110 self.assertEqual(c.power(1, 4, Decimal(2)), d)
2111 self.assertEqual(c.power(Decimal(1), Decimal(4), 2), d)
2112 self.assertRaises(TypeError, c.power, '1', 4, 2)
2113 self.assertRaises(TypeError, c.power, 1, '4', 2)
2114 self.assertRaises(TypeError, c.power, 1, 4, '2')
2115
2116 def test_plus(self):
2117 c = Context()
2118 d = c.plus(Decimal(10))
2119 self.assertEqual(c.plus(10), d)
2120 self.assertRaises(TypeError, c.plus, '10')
2121
2122 def test_quantize(self):
2123 c = Context()
2124 d = c.quantize(Decimal(1), Decimal(2))
2125 self.assertEqual(c.quantize(1, 2), d)
2126 self.assertEqual(c.quantize(Decimal(1), 2), d)
2127 self.assertEqual(c.quantize(1, Decimal(2)), d)
2128 self.assertRaises(TypeError, c.quantize, '1', 2)
2129 self.assertRaises(TypeError, c.quantize, 1, '2')
2130
2131 def test_remainder(self):
2132 c = Context()
2133 d = c.remainder(Decimal(1), Decimal(2))
2134 self.assertEqual(c.remainder(1, 2), d)
2135 self.assertEqual(c.remainder(Decimal(1), 2), d)
2136 self.assertEqual(c.remainder(1, Decimal(2)), d)
2137 self.assertRaises(TypeError, c.remainder, '1', 2)
2138 self.assertRaises(TypeError, c.remainder, 1, '2')
2139
2140 def test_remainder_near(self):
2141 c = Context()
2142 d = c.remainder_near(Decimal(1), Decimal(2))
2143 self.assertEqual(c.remainder_near(1, 2), d)
2144 self.assertEqual(c.remainder_near(Decimal(1), 2), d)
2145 self.assertEqual(c.remainder_near(1, Decimal(2)), d)
2146 self.assertRaises(TypeError, c.remainder_near, '1', 2)
2147 self.assertRaises(TypeError, c.remainder_near, 1, '2')
2148
2149 def test_rotate(self):
2150 c = Context()
2151 d = c.rotate(Decimal(1), Decimal(2))
2152 self.assertEqual(c.rotate(1, 2), d)
2153 self.assertEqual(c.rotate(Decimal(1), 2), d)
2154 self.assertEqual(c.rotate(1, Decimal(2)), d)
2155 self.assertRaises(TypeError, c.rotate, '1', 2)
2156 self.assertRaises(TypeError, c.rotate, 1, '2')
2157
2158 def test_sqrt(self):
2159 c = Context()
2160 d = c.sqrt(Decimal(10))
2161 self.assertEqual(c.sqrt(10), d)
2162 self.assertRaises(TypeError, c.sqrt, '10')
2163
2164 def test_same_quantum(self):
2165 c = Context()
2166 d = c.same_quantum(Decimal(1), Decimal(2))
2167 self.assertEqual(c.same_quantum(1, 2), d)
2168 self.assertEqual(c.same_quantum(Decimal(1), 2), d)
2169 self.assertEqual(c.same_quantum(1, Decimal(2)), d)
2170 self.assertRaises(TypeError, c.same_quantum, '1', 2)
2171 self.assertRaises(TypeError, c.same_quantum, 1, '2')
2172
2173 def test_scaleb(self):
2174 c = Context()
2175 d = c.scaleb(Decimal(1), Decimal(2))
2176 self.assertEqual(c.scaleb(1, 2), d)
2177 self.assertEqual(c.scaleb(Decimal(1), 2), d)
2178 self.assertEqual(c.scaleb(1, Decimal(2)), d)
2179 self.assertRaises(TypeError, c.scaleb, '1', 2)
2180 self.assertRaises(TypeError, c.scaleb, 1, '2')
2181
2182 def test_shift(self):
2183 c = Context()
2184 d = c.shift(Decimal(1), Decimal(2))
2185 self.assertEqual(c.shift(1, 2), d)
2186 self.assertEqual(c.shift(Decimal(1), 2), d)
2187 self.assertEqual(c.shift(1, Decimal(2)), d)
2188 self.assertRaises(TypeError, c.shift, '1', 2)
2189 self.assertRaises(TypeError, c.shift, 1, '2')
2190
2191 def test_subtract(self):
2192 c = Context()
2193 d = c.subtract(Decimal(1), Decimal(2))
2194 self.assertEqual(c.subtract(1, 2), d)
2195 self.assertEqual(c.subtract(Decimal(1), 2), d)
2196 self.assertEqual(c.subtract(1, Decimal(2)), d)
2197 self.assertRaises(TypeError, c.subtract, '1', 2)
2198 self.assertRaises(TypeError, c.subtract, 1, '2')
2199
2200 def test_to_eng_string(self):
2201 c = Context()
2202 d = c.to_eng_string(Decimal(10))
2203 self.assertEqual(c.to_eng_string(10), d)
2204 self.assertRaises(TypeError, c.to_eng_string, '10')
2205
2206 def test_to_sci_string(self):
2207 c = Context()
2208 d = c.to_sci_string(Decimal(10))
2209 self.assertEqual(c.to_sci_string(10), d)
2210 self.assertRaises(TypeError, c.to_sci_string, '10')
2211
2212 def test_to_integral_exact(self):
2213 c = Context()
2214 d = c.to_integral_exact(Decimal(10))
2215 self.assertEqual(c.to_integral_exact(10), d)
2216 self.assertRaises(TypeError, c.to_integral_exact, '10')
2217
2218 def test_to_integral_value(self):
2219 c = Context()
2220 d = c.to_integral_value(Decimal(10))
2221 self.assertEqual(c.to_integral_value(10), d)
2222 self.assertRaises(TypeError, c.to_integral_value, '10')
2223
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002224class WithStatementTest(unittest.TestCase):
2225 # Can't do these as docstrings until Python 2.6
2226 # as doctest can't handle __future__ statements
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002227
2228 def test_localcontext(self):
Nick Coghlanced12182006-09-02 03:54:17 +00002229 # Use a copy of the current context in the block
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002230 orig_ctx = getcontext()
2231 with localcontext() as enter_ctx:
2232 set_ctx = getcontext()
2233 final_ctx = getcontext()
Ezio Melotti856a3be2010-04-03 14:51:00 +00002234 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
2235 self.assertIsNot(orig_ctx, set_ctx, 'did not copy the context')
2236 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002237
2238 def test_localcontextarg(self):
Nick Coghlanced12182006-09-02 03:54:17 +00002239 # Use a copy of the supplied context in the block
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002240 orig_ctx = getcontext()
2241 new_ctx = Context(prec=42)
2242 with localcontext(new_ctx) as enter_ctx:
2243 set_ctx = getcontext()
2244 final_ctx = getcontext()
Ezio Melotti856a3be2010-04-03 14:51:00 +00002245 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
2246 self.assertEqual(set_ctx.prec, new_ctx.prec, 'did not set correct context')
2247 self.assertIsNot(new_ctx, set_ctx, 'did not copy the context')
2248 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002249
Facundo Batista353750c2007-09-13 18:13:15 +00002250class ContextFlags(unittest.TestCase):
2251 def test_flags_irrelevant(self):
2252 # check that the result (numeric result + flags raised) of an
2253 # arithmetic operation doesn't depend on the current flags
2254
2255 context = Context(prec=9, Emin = -999999999, Emax = 999999999,
2256 rounding=ROUND_HALF_EVEN, traps=[], flags=[])
2257
2258 # operations that raise various flags, in the form (function, arglist)
2259 operations = [
2260 (context._apply, [Decimal("100E-1000000009")]),
2261 (context.sqrt, [Decimal(2)]),
2262 (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]),
2263 (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]),
2264 (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]),
2265 ]
2266
2267 # try various flags individually, then a whole lot at once
2268 flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal],
2269 [Inexact, Rounded, Underflow, Clamped, Subnormal]]
2270
2271 for fn, args in operations:
2272 # find answer and flags raised using a clean context
2273 context.clear_flags()
2274 ans = fn(*args)
2275 flags = [k for k, v in context.flags.items() if v]
2276
2277 for extra_flags in flagsets:
2278 # set flags, before calling operation
2279 context.clear_flags()
2280 for flag in extra_flags:
2281 context._raise_error(flag)
2282 new_ans = fn(*args)
2283
2284 # flags that we expect to be set after the operation
2285 expected_flags = list(flags)
2286 for flag in extra_flags:
2287 if flag not in expected_flags:
2288 expected_flags.append(flag)
Facundo Batista353750c2007-09-13 18:13:15 +00002289
2290 # flags we actually got
2291 new_flags = [k for k,v in context.flags.items() if v]
Facundo Batista353750c2007-09-13 18:13:15 +00002292
2293 self.assertEqual(ans, new_ans,
2294 "operation produces different answers depending on flags set: " +
2295 "expected %s, got %s." % (ans, new_ans))
Florent Xicluna8f43cec2010-03-21 10:51:40 +00002296 self.assertItemsEqual(new_flags, expected_flags,
Facundo Batista353750c2007-09-13 18:13:15 +00002297 "operation raises different flags depending on flags set: " +
2298 "expected %s, got %s" % (expected_flags, new_flags))
2299
Zachary Ware9ce635f2014-06-02 16:01:16 -05002300def test_main(arith=None, verbose=None, todo_tests=None, debug=None):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002301 """ Execute the tests.
2302
Raymond Hettingered20ad82004-09-04 20:09:13 +00002303 Runs all arithmetic tests if arith is True or if the "decimal" resource
2304 is enabled in regrtest.py
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002305 """
Raymond Hettingered20ad82004-09-04 20:09:13 +00002306
Neal Norwitzce4a9c92006-04-09 08:36:46 +00002307 init()
Facundo Batista353750c2007-09-13 18:13:15 +00002308 global TEST_ALL, DEBUG
Zachary Ware9ce635f2014-06-02 16:01:16 -05002309 TEST_ALL = arith if arith is not None else is_resource_enabled('decimal')
Facundo Batista353750c2007-09-13 18:13:15 +00002310 DEBUG = debug
Raymond Hettingered20ad82004-09-04 20:09:13 +00002311
Facundo Batista353750c2007-09-13 18:13:15 +00002312 if todo_tests is None:
2313 test_classes = [
2314 DecimalExplicitConstructionTest,
2315 DecimalImplicitConstructionTest,
2316 DecimalArithmeticOperatorsTest,
Mark Dickinson1ddf1d82008-02-29 02:16:37 +00002317 DecimalFormatTest,
Facundo Batista353750c2007-09-13 18:13:15 +00002318 DecimalUseOfContextTest,
2319 DecimalUsabilityTest,
2320 DecimalPythonAPItests,
2321 ContextAPItests,
2322 DecimalTest,
2323 WithStatementTest,
2324 ContextFlags
2325 ]
2326 else:
2327 test_classes = [DecimalTest]
2328
2329 # Dynamically build custom test definition for each file in the test
2330 # directory and add the definitions to the DecimalTest class. This
2331 # procedure insures that new files do not get skipped.
2332 for filename in os.listdir(directory):
2333 if '.decTest' not in filename or filename.startswith("."):
2334 continue
2335 head, tail = filename.split('.')
2336 if todo_tests is not None and head not in todo_tests:
2337 continue
2338 tester = lambda self, f=filename: self.eval_file(directory + f)
2339 setattr(DecimalTest, 'test_' + head, tester)
2340 del filename, head, tail, tester
2341
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002342
Tim Peters46cc7022006-03-31 04:11:16 +00002343 try:
2344 run_unittest(*test_classes)
Facundo Batista353750c2007-09-13 18:13:15 +00002345 if todo_tests is None:
2346 import decimal as DecimalModule
2347 run_doctest(DecimalModule, verbose)
Tim Peters46cc7022006-03-31 04:11:16 +00002348 finally:
2349 setcontext(ORIGINAL_CONTEXT)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002350
2351if __name__ == '__main__':
Facundo Batista353750c2007-09-13 18:13:15 +00002352 import optparse
2353 p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]")
2354 p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test')
2355 p.add_option('--skip', '-s', action='store_true', help='skip over 90% of the arithmetic tests')
2356 (opt, args) = p.parse_args()
2357
2358 if opt.skip:
2359 test_main(arith=False, verbose=True)
2360 elif args:
2361 test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002362 else:
Facundo Batista353750c2007-09-13 18:13:15 +00002363 test_main(arith=True, verbose=True)