blob: de309ba327cad387b5e3225897a4403336d9fba4 [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,
Florent Xicluna8f43cec2010-03-21 10:51:40 +000035 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
Serhiy Storchaka20c049d2014-10-14 21:10:56 +0300598 @requires_unicode
Mark Dickinson4326ad82009-08-02 10:59:36 +0000599 def test_unicode_digits(self):
600 test_values = {
Serhiy Storchaka20c049d2014-10-14 21:10:56 +0300601 u(r'\uff11'): '1',
602 u(r'\u0660.\u0660\u0663\u0667\u0662e-\u0663') : '0.0000372',
603 u(r'-nan\u0c68\u0c6a\u0c66\u0c66') : '-NaN2400',
Mark Dickinson4326ad82009-08-02 10:59:36 +0000604 }
605 for input, expected in test_values.items():
606 self.assertEqual(str(Decimal(input)), expected)
607
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000608
609class DecimalImplicitConstructionTest(unittest.TestCase):
610 '''Unit tests for Implicit Construction cases of Decimal.'''
611
612 def test_implicit_from_None(self):
613 self.assertRaises(TypeError, eval, 'Decimal(5) + None', globals())
614
615 def test_implicit_from_int(self):
616 #normal
617 self.assertEqual(str(Decimal(5) + 45), '50')
618 #exceeding precision
619 self.assertEqual(Decimal(5) + 123456789000, Decimal(123456789000))
620
621 def test_implicit_from_string(self):
622 self.assertRaises(TypeError, eval, 'Decimal(5) + "3"', globals())
623
624 def test_implicit_from_float(self):
625 self.assertRaises(TypeError, eval, 'Decimal(5) + 2.2', globals())
626
627 def test_implicit_from_Decimal(self):
628 self.assertEqual(Decimal(5) + Decimal(45), Decimal(50))
629
Raymond Hettinger267b8682005-03-27 10:47:39 +0000630 def test_rop(self):
631 # Allow other classes to be trained to interact with Decimals
632 class E:
633 def __divmod__(self, other):
634 return 'divmod ' + str(other)
635 def __rdivmod__(self, other):
636 return str(other) + ' rdivmod'
637 def __lt__(self, other):
638 return 'lt ' + str(other)
639 def __gt__(self, other):
640 return 'gt ' + str(other)
641 def __le__(self, other):
642 return 'le ' + str(other)
643 def __ge__(self, other):
644 return 'ge ' + str(other)
645 def __eq__(self, other):
646 return 'eq ' + str(other)
647 def __ne__(self, other):
648 return 'ne ' + str(other)
649
650 self.assertEqual(divmod(E(), Decimal(10)), 'divmod 10')
651 self.assertEqual(divmod(Decimal(10), E()), '10 rdivmod')
652 self.assertEqual(eval('Decimal(10) < E()'), 'gt 10')
653 self.assertEqual(eval('Decimal(10) > E()'), 'lt 10')
654 self.assertEqual(eval('Decimal(10) <= E()'), 'ge 10')
655 self.assertEqual(eval('Decimal(10) >= E()'), 'le 10')
656 self.assertEqual(eval('Decimal(10) == E()'), 'eq 10')
657 self.assertEqual(eval('Decimal(10) != E()'), 'ne 10')
658
659 # insert operator methods and then exercise them
Georg Brandl96c3f7f2006-03-28 08:06:35 +0000660 oplist = [
661 ('+', '__add__', '__radd__'),
662 ('-', '__sub__', '__rsub__'),
663 ('*', '__mul__', '__rmul__'),
664 ('%', '__mod__', '__rmod__'),
665 ('//', '__floordiv__', '__rfloordiv__'),
666 ('**', '__pow__', '__rpow__')
667 ]
Florent Xicluna8f43cec2010-03-21 10:51:40 +0000668 with check_py3k_warnings():
669 if 1 / 2 == 0:
670 # testing with classic division, so add __div__
671 oplist.append(('/', '__div__', '__rdiv__'))
672 else:
673 # testing with -Qnew, so add __truediv__
674 oplist.append(('/', '__truediv__', '__rtruediv__'))
Anthony Baxter4ef3a232006-03-30 12:59:11 +0000675
Georg Brandl96c3f7f2006-03-28 08:06:35 +0000676 for sym, lop, rop in oplist:
Raymond Hettinger267b8682005-03-27 10:47:39 +0000677 setattr(E, lop, lambda self, other: 'str' + lop + str(other))
678 setattr(E, rop, lambda self, other: str(other) + rop + 'str')
679 self.assertEqual(eval('E()' + sym + 'Decimal(10)'),
680 'str' + lop + '10')
681 self.assertEqual(eval('Decimal(10)' + sym + 'E()'),
682 '10' + rop + 'str')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000683
Mark Dickinson277859d2009-03-17 23:03:46 +0000684
Mark Dickinson1ddf1d82008-02-29 02:16:37 +0000685class DecimalFormatTest(unittest.TestCase):
686 '''Unit tests for the format function.'''
687 def test_formatting(self):
688 # triples giving a format, a Decimal, and the expected result
689 test_values = [
690 ('e', '0E-15', '0e-15'),
691 ('e', '2.3E-15', '2.3e-15'),
692 ('e', '2.30E+2', '2.30e+2'), # preserve significant zeros
693 ('e', '2.30000E-15', '2.30000e-15'),
694 ('e', '1.23456789123456789e40', '1.23456789123456789e+40'),
695 ('e', '1.5', '1.5e+0'),
696 ('e', '0.15', '1.5e-1'),
697 ('e', '0.015', '1.5e-2'),
698 ('e', '0.0000000000015', '1.5e-12'),
699 ('e', '15.0', '1.50e+1'),
700 ('e', '-15', '-1.5e+1'),
701 ('e', '0', '0e+0'),
702 ('e', '0E1', '0e+1'),
703 ('e', '0.0', '0e-1'),
704 ('e', '0.00', '0e-2'),
705 ('.6e', '0E-15', '0.000000e-9'),
706 ('.6e', '0', '0.000000e+6'),
707 ('.6e', '9.999999', '9.999999e+0'),
708 ('.6e', '9.9999999', '1.000000e+1'),
709 ('.6e', '-1.23e5', '-1.230000e+5'),
710 ('.6e', '1.23456789e-3', '1.234568e-3'),
711 ('f', '0', '0'),
712 ('f', '0.0', '0.0'),
713 ('f', '0E-2', '0.00'),
714 ('f', '0.00E-8', '0.0000000000'),
715 ('f', '0E1', '0'), # loses exponent information
716 ('f', '3.2E1', '32'),
717 ('f', '3.2E2', '320'),
718 ('f', '3.20E2', '320'),
719 ('f', '3.200E2', '320.0'),
720 ('f', '3.2E-6', '0.0000032'),
721 ('.6f', '0E-15', '0.000000'), # all zeros treated equally
722 ('.6f', '0E1', '0.000000'),
723 ('.6f', '0', '0.000000'),
724 ('.0f', '0', '0'), # no decimal point
725 ('.0f', '0e-2', '0'),
726 ('.0f', '3.14159265', '3'),
727 ('.1f', '3.14159265', '3.1'),
728 ('.4f', '3.14159265', '3.1416'),
729 ('.6f', '3.14159265', '3.141593'),
730 ('.7f', '3.14159265', '3.1415926'), # round-half-even!
731 ('.8f', '3.14159265', '3.14159265'),
732 ('.9f', '3.14159265', '3.141592650'),
733
734 ('g', '0', '0'),
735 ('g', '0.0', '0.0'),
736 ('g', '0E1', '0e+1'),
737 ('G', '0E1', '0E+1'),
738 ('g', '0E-5', '0.00000'),
739 ('g', '0E-6', '0.000000'),
740 ('g', '0E-7', '0e-7'),
741 ('g', '-0E2', '-0e+2'),
742 ('.0g', '3.14159265', '3'), # 0 sig fig -> 1 sig fig
743 ('.1g', '3.14159265', '3'),
744 ('.2g', '3.14159265', '3.1'),
745 ('.5g', '3.14159265', '3.1416'),
746 ('.7g', '3.14159265', '3.141593'),
747 ('.8g', '3.14159265', '3.1415926'), # round-half-even!
748 ('.9g', '3.14159265', '3.14159265'),
749 ('.10g', '3.14159265', '3.14159265'), # don't pad
750
751 ('%', '0E1', '0%'),
752 ('%', '0E0', '0%'),
753 ('%', '0E-1', '0%'),
754 ('%', '0E-2', '0%'),
755 ('%', '0E-3', '0.0%'),
756 ('%', '0E-4', '0.00%'),
757
758 ('.3%', '0', '0.000%'), # all zeros treated equally
759 ('.3%', '0E10', '0.000%'),
760 ('.3%', '0E-10', '0.000%'),
761 ('.3%', '2.34', '234.000%'),
762 ('.3%', '1.234567', '123.457%'),
763 ('.0%', '1.23', '123%'),
764
765 ('e', 'NaN', 'NaN'),
766 ('f', '-NaN123', '-NaN123'),
767 ('+g', 'NaN456', '+NaN456'),
768 ('.3e', 'Inf', 'Infinity'),
769 ('.16f', '-Inf', '-Infinity'),
770 ('.0g', '-sNaN', '-sNaN'),
771
772 ('', '1.00', '1.00'),
Mark Dickinsonb065e522009-03-17 18:01:03 +0000773
Mark Dickinson277859d2009-03-17 23:03:46 +0000774 # test alignment and padding
Mark Dickinson5cfa8042009-09-08 20:20:19 +0000775 ('6', '123', ' 123'),
Mark Dickinsonb065e522009-03-17 18:01:03 +0000776 ('<6', '123', '123 '),
777 ('>6', '123', ' 123'),
778 ('^6', '123', ' 123 '),
779 ('=+6', '123', '+ 123'),
Mark Dickinson277859d2009-03-17 23:03:46 +0000780 ('#<10', 'NaN', 'NaN#######'),
781 ('#<10', '-4.3', '-4.3######'),
782 ('#<+10', '0.0130', '+0.0130###'),
783 ('#< 10', '0.0130', ' 0.0130###'),
784 ('@>10', '-Inf', '@-Infinity'),
785 ('#>5', '-Inf', '-Infinity'),
786 ('?^5', '123', '?123?'),
787 ('%^6', '123', '%123%%'),
788 (' ^6', '-45.6', '-45.6 '),
789 ('/=10', '-45.6', '-/////45.6'),
790 ('/=+10', '45.6', '+/////45.6'),
791 ('/= 10', '45.6', ' /////45.6'),
792
793 # thousands separator
794 (',', '1234567', '1,234,567'),
795 (',', '123456', '123,456'),
796 (',', '12345', '12,345'),
797 (',', '1234', '1,234'),
798 (',', '123', '123'),
799 (',', '12', '12'),
800 (',', '1', '1'),
801 (',', '0', '0'),
802 (',', '-1234567', '-1,234,567'),
803 (',', '-123456', '-123,456'),
804 ('7,', '123456', '123,456'),
Mark Dickinson5cfa8042009-09-08 20:20:19 +0000805 ('8,', '123456', ' 123,456'),
Mark Dickinson277859d2009-03-17 23:03:46 +0000806 ('08,', '123456', '0,123,456'), # special case: extra 0 needed
807 ('+08,', '123456', '+123,456'), # but not if there's a sign
808 (' 08,', '123456', ' 123,456'),
809 ('08,', '-123456', '-123,456'),
810 ('+09,', '123456', '+0,123,456'),
811 # ... with fractional part...
812 ('07,', '1234.56', '1,234.56'),
813 ('08,', '1234.56', '1,234.56'),
814 ('09,', '1234.56', '01,234.56'),
815 ('010,', '1234.56', '001,234.56'),
816 ('011,', '1234.56', '0,001,234.56'),
817 ('012,', '1234.56', '0,001,234.56'),
818 ('08,.1f', '1234.5', '01,234.5'),
819 # no thousands separators in fraction part
820 (',', '1.23456789', '1.23456789'),
821 (',%', '123.456789', '12,345.6789%'),
822 (',e', '123456', '1.23456e+5'),
823 (',E', '123456', '1.23456E+5'),
Mark Dickinson491ea552009-09-07 16:17:41 +0000824
825 # issue 6850
826 ('a=-7.0', '0.12345', 'aaaa0.1'),
Stefan Krahce2ec492014-08-26 20:49:57 +0200827
828 # issue 22090
829 ('<^+15.20%', 'inf', '<<+Infinity%<<<'),
830 ('\x07>,%', 'sNaN1234567', 'sNaN1234567%'),
831 ('=10.10%', 'NaN123', ' NaN123%'),
Mark Dickinson1ddf1d82008-02-29 02:16:37 +0000832 ]
833 for fmt, d, result in test_values:
834 self.assertEqual(format(Decimal(d), fmt), result)
835
Mark Dickinson277859d2009-03-17 23:03:46 +0000836 def test_n_format(self):
837 try:
838 from locale import CHAR_MAX
839 except ImportError:
Zachary Ware1f702212013-12-10 14:09:20 -0600840 self.skipTest('locale.CHAR_MAX not available')
Mark Dickinson277859d2009-03-17 23:03:46 +0000841
842 # Set up some localeconv-like dictionaries
843 en_US = {
844 'decimal_point' : '.',
845 'grouping' : [3, 3, 0],
846 'thousands_sep': ','
847 }
848
849 fr_FR = {
850 'decimal_point' : ',',
851 'grouping' : [CHAR_MAX],
852 'thousands_sep' : ''
853 }
854
855 ru_RU = {
856 'decimal_point' : ',',
857 'grouping' : [3, 3, 0],
858 'thousands_sep' : ' '
859 }
860
861 crazy = {
862 'decimal_point' : '&',
863 'grouping' : [1, 4, 2, CHAR_MAX],
864 'thousands_sep' : '-'
865 }
866
867
868 def get_fmt(x, locale, fmt='n'):
869 return Decimal.__format__(Decimal(x), fmt, _localeconv=locale)
870
871 self.assertEqual(get_fmt(Decimal('12.7'), en_US), '12.7')
872 self.assertEqual(get_fmt(Decimal('12.7'), fr_FR), '12,7')
873 self.assertEqual(get_fmt(Decimal('12.7'), ru_RU), '12,7')
874 self.assertEqual(get_fmt(Decimal('12.7'), crazy), '1-2&7')
875
876 self.assertEqual(get_fmt(123456789, en_US), '123,456,789')
877 self.assertEqual(get_fmt(123456789, fr_FR), '123456789')
878 self.assertEqual(get_fmt(123456789, ru_RU), '123 456 789')
879 self.assertEqual(get_fmt(1234567890123, crazy), '123456-78-9012-3')
880
881 self.assertEqual(get_fmt(123456789, en_US, '.6n'), '1.23457e+8')
882 self.assertEqual(get_fmt(123456789, fr_FR, '.6n'), '1,23457e+8')
883 self.assertEqual(get_fmt(123456789, ru_RU, '.6n'), '1,23457e+8')
884 self.assertEqual(get_fmt(123456789, crazy, '.6n'), '1&23457e+8')
885
Mark Dickinsonb14514a2009-03-18 08:22:51 +0000886 # zero padding
887 self.assertEqual(get_fmt(1234, fr_FR, '03n'), '1234')
888 self.assertEqual(get_fmt(1234, fr_FR, '04n'), '1234')
889 self.assertEqual(get_fmt(1234, fr_FR, '05n'), '01234')
890 self.assertEqual(get_fmt(1234, fr_FR, '06n'), '001234')
891
892 self.assertEqual(get_fmt(12345, en_US, '05n'), '12,345')
893 self.assertEqual(get_fmt(12345, en_US, '06n'), '12,345')
894 self.assertEqual(get_fmt(12345, en_US, '07n'), '012,345')
895 self.assertEqual(get_fmt(12345, en_US, '08n'), '0,012,345')
896 self.assertEqual(get_fmt(12345, en_US, '09n'), '0,012,345')
897 self.assertEqual(get_fmt(12345, en_US, '010n'), '00,012,345')
898
899 self.assertEqual(get_fmt(123456, crazy, '06n'), '1-2345-6')
900 self.assertEqual(get_fmt(123456, crazy, '07n'), '1-2345-6')
901 self.assertEqual(get_fmt(123456, crazy, '08n'), '1-2345-6')
902 self.assertEqual(get_fmt(123456, crazy, '09n'), '01-2345-6')
903 self.assertEqual(get_fmt(123456, crazy, '010n'), '0-01-2345-6')
904 self.assertEqual(get_fmt(123456, crazy, '011n'), '0-01-2345-6')
905 self.assertEqual(get_fmt(123456, crazy, '012n'), '00-01-2345-6')
906 self.assertEqual(get_fmt(123456, crazy, '013n'), '000-01-2345-6')
907
Mark Dickinson277859d2009-03-17 23:03:46 +0000908
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000909class DecimalArithmeticOperatorsTest(unittest.TestCase):
910 '''Unit tests for all arithmetic operators, binary and unary.'''
911
912 def test_addition(self):
913
914 d1 = Decimal('-11.1')
915 d2 = Decimal('22.2')
916
917 #two Decimals
918 self.assertEqual(d1+d2, Decimal('11.1'))
919 self.assertEqual(d2+d1, Decimal('11.1'))
920
921 #with other type, left
922 c = d1 + 5
923 self.assertEqual(c, Decimal('-6.1'))
924 self.assertEqual(type(c), type(d1))
925
926 #with other type, right
927 c = 5 + d1
928 self.assertEqual(c, Decimal('-6.1'))
929 self.assertEqual(type(c), type(d1))
930
931 #inline with decimal
932 d1 += d2
933 self.assertEqual(d1, Decimal('11.1'))
934
935 #inline with other type
936 d1 += 5
937 self.assertEqual(d1, Decimal('16.1'))
938
939 def test_subtraction(self):
940
941 d1 = Decimal('-11.1')
942 d2 = Decimal('22.2')
943
944 #two Decimals
945 self.assertEqual(d1-d2, Decimal('-33.3'))
946 self.assertEqual(d2-d1, Decimal('33.3'))
947
948 #with other type, left
949 c = d1 - 5
950 self.assertEqual(c, Decimal('-16.1'))
951 self.assertEqual(type(c), type(d1))
952
953 #with other type, right
954 c = 5 - d1
955 self.assertEqual(c, Decimal('16.1'))
956 self.assertEqual(type(c), type(d1))
957
958 #inline with decimal
959 d1 -= d2
960 self.assertEqual(d1, Decimal('-33.3'))
961
962 #inline with other type
963 d1 -= 5
964 self.assertEqual(d1, Decimal('-38.3'))
965
966 def test_multiplication(self):
967
968 d1 = Decimal('-5')
969 d2 = Decimal('3')
970
971 #two Decimals
972 self.assertEqual(d1*d2, Decimal('-15'))
973 self.assertEqual(d2*d1, Decimal('-15'))
974
975 #with other type, left
976 c = d1 * 5
977 self.assertEqual(c, Decimal('-25'))
978 self.assertEqual(type(c), type(d1))
979
980 #with other type, right
981 c = 5 * d1
982 self.assertEqual(c, Decimal('-25'))
983 self.assertEqual(type(c), type(d1))
984
985 #inline with decimal
986 d1 *= d2
987 self.assertEqual(d1, Decimal('-15'))
988
989 #inline with other type
990 d1 *= 5
991 self.assertEqual(d1, Decimal('-75'))
992
993 def test_division(self):
994
995 d1 = Decimal('-5')
996 d2 = Decimal('2')
997
998 #two Decimals
999 self.assertEqual(d1/d2, Decimal('-2.5'))
1000 self.assertEqual(d2/d1, Decimal('-0.4'))
1001
1002 #with other type, left
1003 c = d1 / 4
1004 self.assertEqual(c, Decimal('-1.25'))
1005 self.assertEqual(type(c), type(d1))
1006
1007 #with other type, right
1008 c = 4 / d1
1009 self.assertEqual(c, Decimal('-0.8'))
1010 self.assertEqual(type(c), type(d1))
1011
1012 #inline with decimal
1013 d1 /= d2
1014 self.assertEqual(d1, Decimal('-2.5'))
1015
1016 #inline with other type
1017 d1 /= 4
1018 self.assertEqual(d1, Decimal('-0.625'))
1019
1020 def test_floor_division(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001021
1022 d1 = Decimal('5')
1023 d2 = Decimal('2')
1024
1025 #two Decimals
1026 self.assertEqual(d1//d2, Decimal('2'))
1027 self.assertEqual(d2//d1, Decimal('0'))
1028
1029 #with other type, left
1030 c = d1 // 4
1031 self.assertEqual(c, Decimal('1'))
1032 self.assertEqual(type(c), type(d1))
1033
1034 #with other type, right
1035 c = 7 // d1
1036 self.assertEqual(c, Decimal('1'))
1037 self.assertEqual(type(c), type(d1))
1038
1039 #inline with decimal
1040 d1 //= d2
1041 self.assertEqual(d1, Decimal('2'))
1042
1043 #inline with other type
1044 d1 //= 2
1045 self.assertEqual(d1, Decimal('1'))
1046
1047 def test_powering(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001048
1049 d1 = Decimal('5')
1050 d2 = Decimal('2')
1051
1052 #two Decimals
1053 self.assertEqual(d1**d2, Decimal('25'))
1054 self.assertEqual(d2**d1, Decimal('32'))
1055
1056 #with other type, left
1057 c = d1 ** 4
1058 self.assertEqual(c, Decimal('625'))
1059 self.assertEqual(type(c), type(d1))
1060
1061 #with other type, right
1062 c = 7 ** d1
1063 self.assertEqual(c, Decimal('16807'))
1064 self.assertEqual(type(c), type(d1))
1065
1066 #inline with decimal
1067 d1 **= d2
1068 self.assertEqual(d1, Decimal('25'))
1069
1070 #inline with other type
1071 d1 **= 4
1072 self.assertEqual(d1, Decimal('390625'))
1073
1074 def test_module(self):
1075
1076 d1 = Decimal('5')
1077 d2 = Decimal('2')
1078
1079 #two Decimals
1080 self.assertEqual(d1%d2, Decimal('1'))
1081 self.assertEqual(d2%d1, Decimal('2'))
1082
1083 #with other type, left
1084 c = d1 % 4
1085 self.assertEqual(c, Decimal('1'))
1086 self.assertEqual(type(c), type(d1))
1087
1088 #with other type, right
1089 c = 7 % d1
1090 self.assertEqual(c, Decimal('2'))
1091 self.assertEqual(type(c), type(d1))
1092
1093 #inline with decimal
1094 d1 %= d2
1095 self.assertEqual(d1, Decimal('1'))
1096
1097 #inline with other type
1098 d1 %= 4
1099 self.assertEqual(d1, Decimal('1'))
1100
1101 def test_floor_div_module(self):
1102
1103 d1 = Decimal('5')
1104 d2 = Decimal('2')
1105
1106 #two Decimals
1107 (p, q) = divmod(d1, d2)
1108 self.assertEqual(p, Decimal('2'))
1109 self.assertEqual(q, Decimal('1'))
1110 self.assertEqual(type(p), type(d1))
1111 self.assertEqual(type(q), type(d1))
1112
1113 #with other type, left
1114 (p, q) = divmod(d1, 4)
1115 self.assertEqual(p, Decimal('1'))
1116 self.assertEqual(q, Decimal('1'))
1117 self.assertEqual(type(p), type(d1))
1118 self.assertEqual(type(q), type(d1))
1119
1120 #with other type, right
1121 (p, q) = divmod(7, d1)
1122 self.assertEqual(p, Decimal('1'))
1123 self.assertEqual(q, Decimal('2'))
1124 self.assertEqual(type(p), type(d1))
1125 self.assertEqual(type(q), type(d1))
1126
1127 def test_unary_operators(self):
1128 self.assertEqual(+Decimal(45), Decimal(+45)) # +
1129 self.assertEqual(-Decimal(45), Decimal(-45)) # -
1130 self.assertEqual(abs(Decimal(45)), abs(Decimal(-45))) # abs
1131
Mark Dickinson2fc92632008-02-06 22:10:50 +00001132 def test_nan_comparisons(self):
Mark Dickinsone096e822010-04-02 10:17:07 +00001133 # comparisons involving signaling nans signal InvalidOperation
1134
1135 # order comparisons (<, <=, >, >=) involving only quiet nans
1136 # also signal InvalidOperation
1137
1138 # equality comparisons (==, !=) involving only quiet nans
1139 # don't signal, but return False or True respectively.
1140
Mark Dickinson2fc92632008-02-06 22:10:50 +00001141 n = Decimal('NaN')
1142 s = Decimal('sNaN')
1143 i = Decimal('Inf')
1144 f = Decimal('2')
Mark Dickinsone096e822010-04-02 10:17:07 +00001145
1146 qnan_pairs = (n, n), (n, i), (i, n), (n, f), (f, n)
1147 snan_pairs = (s, n), (n, s), (s, i), (i, s), (s, f), (f, s), (s, s)
1148 order_ops = operator.lt, operator.le, operator.gt, operator.ge
1149 equality_ops = operator.eq, operator.ne
1150
1151 # results when InvalidOperation is not trapped
1152 for x, y in qnan_pairs + snan_pairs:
1153 for op in order_ops + equality_ops:
1154 got = op(x, y)
1155 expected = True if op is operator.ne else False
1156 self.assertIs(expected, got,
1157 "expected {0!r} for operator.{1}({2!r}, {3!r}); "
1158 "got {4!r}".format(
1159 expected, op.__name__, x, y, got))
1160
1161 # repeat the above, but this time trap the InvalidOperation
1162 with localcontext() as ctx:
1163 ctx.traps[InvalidOperation] = 1
1164
1165 for x, y in qnan_pairs:
1166 for op in equality_ops:
1167 got = op(x, y)
1168 expected = True if op is operator.ne else False
1169 self.assertIs(expected, got,
1170 "expected {0!r} for "
1171 "operator.{1}({2!r}, {3!r}); "
1172 "got {4!r}".format(
1173 expected, op.__name__, x, y, got))
1174
1175 for x, y in snan_pairs:
1176 for op in equality_ops:
1177 self.assertRaises(InvalidOperation, operator.eq, x, y)
1178 self.assertRaises(InvalidOperation, operator.ne, x, y)
1179
1180 for x, y in qnan_pairs + snan_pairs:
1181 for op in order_ops:
1182 self.assertRaises(InvalidOperation, op, x, y)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001183
Mark Dickinson6d8effb2010-02-18 14:27:02 +00001184 def test_copy_sign(self):
1185 d = Decimal(1).copy_sign(Decimal(-2))
1186
1187 self.assertEqual(Decimal(1).copy_sign(-2), d)
1188 self.assertRaises(TypeError, Decimal(1).copy_sign, '-2')
1189
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001190# The following are two functions used to test threading in the next class
1191
1192def thfunc1(cls):
1193 d1 = Decimal(1)
1194 d3 = Decimal(3)
Facundo Batista64156672008-03-22 02:45:37 +00001195 test1 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001196 cls.synchro.wait()
Facundo Batista64156672008-03-22 02:45:37 +00001197 test2 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001198 cls.finish1.set()
Facundo Batista64156672008-03-22 02:45:37 +00001199
Facundo Batistaee340e52008-05-02 17:39:00 +00001200 cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
1201 cls.assertEqual(test2, Decimal('0.3333333333333333333333333333'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001202
1203def thfunc2(cls):
1204 d1 = Decimal(1)
1205 d3 = Decimal(3)
Facundo Batista64156672008-03-22 02:45:37 +00001206 test1 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001207 thiscontext = getcontext()
1208 thiscontext.prec = 18
Facundo Batista64156672008-03-22 02:45:37 +00001209 test2 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001210 cls.synchro.set()
1211 cls.finish2.set()
Facundo Batista64156672008-03-22 02:45:37 +00001212
Facundo Batistaee340e52008-05-02 17:39:00 +00001213 cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
Facundo Batista64156672008-03-22 02:45:37 +00001214 cls.assertEqual(test2, Decimal('0.333333333333333333'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001215
1216
Zachary Ware1f702212013-12-10 14:09:20 -06001217@unittest.skipUnless(threading, 'threading required')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001218class DecimalUseOfContextTest(unittest.TestCase):
1219 '''Unit tests for Use of Context cases in Decimal.'''
1220
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001221 # Take care executing this test from IDLE, there's an issue in threading
1222 # that hangs IDLE and I couldn't find it
1223
1224 def test_threading(self):
1225 #Test the "threading isolation" of a Context.
1226
1227 self.synchro = threading.Event()
1228 self.finish1 = threading.Event()
1229 self.finish2 = threading.Event()
1230
1231 th1 = threading.Thread(target=thfunc1, args=(self,))
1232 th2 = threading.Thread(target=thfunc2, args=(self,))
1233
1234 th1.start()
1235 th2.start()
1236
1237 self.finish1.wait()
Thomas Woutersb3e6e8c2007-09-19 17:27:29 +00001238 self.finish2.wait()
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001239
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001240
1241class DecimalUsabilityTest(unittest.TestCase):
1242 '''Unit tests for Usability cases of Decimal.'''
1243
1244 def test_comparison_operators(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001245
1246 da = Decimal('23.42')
1247 db = Decimal('23.42')
1248 dc = Decimal('45')
1249
1250 #two Decimals
Ezio Melotti856a3be2010-04-03 14:51:00 +00001251 self.assertGreater(dc, da)
1252 self.assertGreaterEqual(dc, da)
1253 self.assertLess(da, dc)
1254 self.assertLessEqual(da, dc)
1255 self.assertEqual(da, db)
1256 self.assertNotEqual(da, dc)
1257 self.assertLessEqual(da, db)
1258 self.assertGreaterEqual(da, db)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001259 self.assertEqual(cmp(dc,da), 1)
1260 self.assertEqual(cmp(da,dc), -1)
1261 self.assertEqual(cmp(da,db), 0)
1262
1263 #a Decimal and an int
Ezio Melotti856a3be2010-04-03 14:51:00 +00001264 self.assertGreater(dc, 23)
1265 self.assertLess(23, dc)
1266 self.assertEqual(dc, 45)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001267 self.assertEqual(cmp(dc,23), 1)
1268 self.assertEqual(cmp(23,dc), -1)
1269 self.assertEqual(cmp(dc,45), 0)
1270
1271 #a Decimal and uncomparable
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001272 self.assertNotEqual(da, 'ugly')
1273 self.assertNotEqual(da, 32.7)
1274 self.assertNotEqual(da, object())
1275 self.assertNotEqual(da, object)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001276
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001277 # sortable
1278 a = map(Decimal, xrange(100))
1279 b = a[:]
1280 random.shuffle(a)
1281 a.sort()
1282 self.assertEqual(a, b)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001283
Facundo Batista353750c2007-09-13 18:13:15 +00001284 # with None
Florent Xicluna8f43cec2010-03-21 10:51:40 +00001285 with check_py3k_warnings():
1286 self.assertFalse(Decimal(1) < None)
1287 self.assertTrue(Decimal(1) > None)
Facundo Batista353750c2007-09-13 18:13:15 +00001288
Mark Dickinson99d80962010-04-02 08:53:22 +00001289 def test_decimal_float_comparison(self):
1290 da = Decimal('0.25')
1291 db = Decimal('3.0')
Ezio Melotti856a3be2010-04-03 14:51:00 +00001292 self.assertLess(da, 3.0)
1293 self.assertLessEqual(da, 3.0)
1294 self.assertGreater(db, 0.25)
1295 self.assertGreaterEqual(db, 0.25)
1296 self.assertNotEqual(da, 1.5)
1297 self.assertEqual(da, 0.25)
1298 self.assertGreater(3.0, da)
1299 self.assertGreaterEqual(3.0, da)
1300 self.assertLess(0.25, db)
1301 self.assertLessEqual(0.25, db)
1302 self.assertNotEqual(0.25, db)
1303 self.assertEqual(3.0, db)
1304 self.assertNotEqual(0.1, Decimal('0.1'))
Mark Dickinson99d80962010-04-02 08:53:22 +00001305
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001306 def test_copy_and_deepcopy_methods(self):
1307 d = Decimal('43.24')
1308 c = copy.copy(d)
1309 self.assertEqual(id(c), id(d))
1310 dc = copy.deepcopy(d)
1311 self.assertEqual(id(dc), id(d))
1312
1313 def test_hash_method(self):
1314 #just that it's hashable
1315 hash(Decimal(23))
Mark Dickinsonf3eeca12010-04-02 10:35:12 +00001316 hash(Decimal('Infinity'))
1317 hash(Decimal('-Infinity'))
1318 hash(Decimal('nan123'))
1319 hash(Decimal('-NaN'))
Facundo Batista8c202442007-09-19 17:53:25 +00001320
1321 test_values = [Decimal(sign*(2**m + n))
1322 for m in [0, 14, 15, 16, 17, 30, 31,
1323 32, 33, 62, 63, 64, 65, 66]
1324 for n in range(-10, 10)
1325 for sign in [-1, 1]]
1326 test_values.extend([
1327 Decimal("-0"), # zeros
1328 Decimal("0.00"),
1329 Decimal("-0.000"),
1330 Decimal("0E10"),
1331 Decimal("-0E12"),
1332 Decimal("10.0"), # negative exponent
1333 Decimal("-23.00000"),
1334 Decimal("1230E100"), # positive exponent
1335 Decimal("-4.5678E50"),
1336 # a value for which hash(n) != hash(n % (2**64-1))
1337 # in Python pre-2.6
1338 Decimal(2**64 + 2**32 - 1),
1339 # selection of values which fail with the old (before
1340 # version 2.6) long.__hash__
1341 Decimal("1.634E100"),
1342 Decimal("90.697E100"),
1343 Decimal("188.83E100"),
1344 Decimal("1652.9E100"),
1345 Decimal("56531E100"),
1346 ])
1347
1348 # check that hash(d) == hash(int(d)) for integral values
1349 for value in test_values:
1350 self.assertEqual(hash(value), hash(int(value)))
1351
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001352 #the same hash that to an int
1353 self.assertEqual(hash(Decimal(23)), hash(23))
Mark Dickinsonf3eeca12010-04-02 10:35:12 +00001354 self.assertRaises(TypeError, hash, Decimal('sNaN'))
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001355 self.assertTrue(hash(Decimal('Inf')))
1356 self.assertTrue(hash(Decimal('-Inf')))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001357
Mark Dickinson99d80962010-04-02 08:53:22 +00001358 # check that the hashes of a Decimal float match when they
1359 # represent exactly the same values
1360 test_strings = ['inf', '-Inf', '0.0', '-.0e1',
1361 '34.0', '2.5', '112390.625', '-0.515625']
1362 for s in test_strings:
1363 f = float(s)
1364 d = Decimal(s)
1365 self.assertEqual(hash(f), hash(d))
1366
Facundo Batista52b25792008-01-08 12:25:20 +00001367 # check that the value of the hash doesn't depend on the
1368 # current context (issue #1757)
1369 c = getcontext()
1370 old_precision = c.prec
1371 x = Decimal("123456789.1")
1372
1373 c.prec = 6
1374 h1 = hash(x)
1375 c.prec = 10
1376 h2 = hash(x)
1377 c.prec = 16
1378 h3 = hash(x)
1379
1380 self.assertEqual(h1, h2)
1381 self.assertEqual(h1, h3)
1382 c.prec = old_precision
1383
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001384 def test_min_and_max_methods(self):
1385
1386 d1 = Decimal('15.32')
1387 d2 = Decimal('28.5')
1388 l1 = 15
1389 l2 = 28
1390
1391 #between Decimals
Ezio Melotti856a3be2010-04-03 14:51:00 +00001392 self.assertIs(min(d1,d2), d1)
1393 self.assertIs(min(d2,d1), d1)
1394 self.assertIs(max(d1,d2), d2)
1395 self.assertIs(max(d2,d1), d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001396
1397 #between Decimal and long
Ezio Melotti856a3be2010-04-03 14:51:00 +00001398 self.assertIs(min(d1,l2), d1)
1399 self.assertIs(min(l2,d1), d1)
1400 self.assertIs(max(l1,d2), d2)
1401 self.assertIs(max(d2,l1), d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001402
1403 def test_as_nonzero(self):
1404 #as false
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001405 self.assertFalse(Decimal(0))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001406 #as true
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001407 self.assertTrue(Decimal('0.372'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001408
1409 def test_tostring_methods(self):
1410 #Test str and repr methods.
1411
1412 d = Decimal('15.32')
1413 self.assertEqual(str(d), '15.32') # str
Raymond Hettingerabe32372008-02-14 02:41:22 +00001414 self.assertEqual(repr(d), "Decimal('15.32')") # repr
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001415
Mark Dickinson8e85ffa2008-03-25 18:47:59 +00001416 # result type of string methods should be str, not unicode
1417 unicode_inputs = [u'123.4', u'0.5E2', u'Infinity', u'sNaN',
1418 u'-0.0E100', u'-NaN001', u'-Inf']
1419
1420 for u in unicode_inputs:
1421 d = Decimal(u)
1422 self.assertEqual(type(str(d)), str)
1423 self.assertEqual(type(repr(d)), str)
1424 self.assertEqual(type(d.to_eng_string()), str)
1425
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001426 def test_tonum_methods(self):
1427 #Test float, int and long methods.
1428
1429 d1 = Decimal('66')
1430 d2 = Decimal('15.32')
1431
1432 #int
1433 self.assertEqual(int(d1), 66)
1434 self.assertEqual(int(d2), 15)
1435
1436 #long
1437 self.assertEqual(long(d1), 66)
1438 self.assertEqual(long(d2), 15)
1439
1440 #float
1441 self.assertEqual(float(d1), 66)
1442 self.assertEqual(float(d2), 15.32)
1443
Mark Dickinson088cec32012-08-24 20:06:30 +01001444 def test_nan_to_float(self):
1445 # Test conversions of decimal NANs to float.
1446 # See http://bugs.python.org/issue15544
1447 for s in ('nan', 'nan1234', '-nan', '-nan2468'):
1448 f = float(Decimal(s))
1449 self.assertTrue(math.isnan(f))
Mark Dickinson088cec32012-08-24 20:06:30 +01001450
1451 def test_snan_to_float(self):
1452 for s in ('snan', '-snan', 'snan1357', '-snan1234'):
1453 d = Decimal(s)
1454 self.assertRaises(ValueError, float, d)
1455
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001456 def test_eval_round_trip(self):
1457
1458 #with zero
1459 d = Decimal( (0, (0,), 0) )
1460 self.assertEqual(d, eval(repr(d)))
1461
1462 #int
1463 d = Decimal( (1, (4, 5), 0) )
1464 self.assertEqual(d, eval(repr(d)))
1465
1466 #float
1467 d = Decimal( (0, (4, 5, 3, 4), -2) )
1468 self.assertEqual(d, eval(repr(d)))
1469
1470 #weird
1471 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1472 self.assertEqual(d, eval(repr(d)))
1473
1474 def test_as_tuple(self):
1475
1476 #with zero
1477 d = Decimal(0)
1478 self.assertEqual(d.as_tuple(), (0, (0,), 0) )
1479
1480 #int
1481 d = Decimal(-45)
1482 self.assertEqual(d.as_tuple(), (1, (4, 5), 0) )
1483
1484 #complicated string
1485 d = Decimal("-4.34913534E-17")
1486 self.assertEqual(d.as_tuple(), (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1487
1488 #inf
1489 d = Decimal("Infinity")
1490 self.assertEqual(d.as_tuple(), (0, (0,), 'F') )
1491
Facundo Batista9b5e2312007-10-19 19:25:57 +00001492 #leading zeros in coefficient should be stripped
1493 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), -2) )
1494 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), -2) )
1495 d = Decimal( (1, (0, 0, 0), 37) )
1496 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1497 d = Decimal( (1, (), 37) )
1498 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1499
1500 #leading zeros in NaN diagnostic info should be stripped
1501 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), 'n') )
1502 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), 'n') )
1503 d = Decimal( (1, (0, 0, 0), 'N') )
1504 self.assertEqual(d.as_tuple(), (1, (), 'N') )
1505 d = Decimal( (1, (), 'n') )
1506 self.assertEqual(d.as_tuple(), (1, (), 'n') )
1507
1508 #coefficient in infinity should be ignored
1509 d = Decimal( (0, (4, 5, 3, 4), 'F') )
1510 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
1511 d = Decimal( (1, (0, 2, 7, 1), 'F') )
1512 self.assertEqual(d.as_tuple(), (1, (0,), 'F'))
1513
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001514 def test_immutability_operations(self):
1515 # Do operations and check that it didn't change change internal objects.
1516
1517 d1 = Decimal('-25e55')
1518 b1 = Decimal('-25e55')
Facundo Batista353750c2007-09-13 18:13:15 +00001519 d2 = Decimal('33e+33')
1520 b2 = Decimal('33e+33')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001521
1522 def checkSameDec(operation, useOther=False):
1523 if useOther:
1524 eval("d1." + operation + "(d2)")
1525 self.assertEqual(d1._sign, b1._sign)
1526 self.assertEqual(d1._int, b1._int)
1527 self.assertEqual(d1._exp, b1._exp)
1528 self.assertEqual(d2._sign, b2._sign)
1529 self.assertEqual(d2._int, b2._int)
1530 self.assertEqual(d2._exp, b2._exp)
1531 else:
1532 eval("d1." + operation + "()")
1533 self.assertEqual(d1._sign, b1._sign)
1534 self.assertEqual(d1._int, b1._int)
1535 self.assertEqual(d1._exp, b1._exp)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001536
1537 Decimal(d1)
1538 self.assertEqual(d1._sign, b1._sign)
1539 self.assertEqual(d1._int, b1._int)
1540 self.assertEqual(d1._exp, b1._exp)
1541
1542 checkSameDec("__abs__")
1543 checkSameDec("__add__", True)
1544 checkSameDec("__div__", True)
1545 checkSameDec("__divmod__", True)
Mark Dickinson2fc92632008-02-06 22:10:50 +00001546 checkSameDec("__eq__", True)
1547 checkSameDec("__ne__", True)
1548 checkSameDec("__le__", True)
1549 checkSameDec("__lt__", True)
1550 checkSameDec("__ge__", True)
1551 checkSameDec("__gt__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001552 checkSameDec("__float__")
1553 checkSameDec("__floordiv__", True)
1554 checkSameDec("__hash__")
1555 checkSameDec("__int__")
Raymond Hettinger5a053642008-01-24 19:05:29 +00001556 checkSameDec("__trunc__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001557 checkSameDec("__long__")
1558 checkSameDec("__mod__", True)
1559 checkSameDec("__mul__", True)
1560 checkSameDec("__neg__")
1561 checkSameDec("__nonzero__")
1562 checkSameDec("__pos__")
1563 checkSameDec("__pow__", True)
1564 checkSameDec("__radd__", True)
1565 checkSameDec("__rdiv__", True)
1566 checkSameDec("__rdivmod__", True)
1567 checkSameDec("__repr__")
1568 checkSameDec("__rfloordiv__", True)
1569 checkSameDec("__rmod__", True)
1570 checkSameDec("__rmul__", True)
1571 checkSameDec("__rpow__", True)
1572 checkSameDec("__rsub__", True)
1573 checkSameDec("__str__")
1574 checkSameDec("__sub__", True)
1575 checkSameDec("__truediv__", True)
1576 checkSameDec("adjusted")
1577 checkSameDec("as_tuple")
1578 checkSameDec("compare", True)
1579 checkSameDec("max", True)
1580 checkSameDec("min", True)
1581 checkSameDec("normalize")
1582 checkSameDec("quantize", True)
1583 checkSameDec("remainder_near", True)
1584 checkSameDec("same_quantum", True)
1585 checkSameDec("sqrt")
1586 checkSameDec("to_eng_string")
1587 checkSameDec("to_integral")
1588
Facundo Batista6c398da2007-09-17 17:30:13 +00001589 def test_subclassing(self):
1590 # Different behaviours when subclassing Decimal
1591
1592 class MyDecimal(Decimal):
1593 pass
1594
1595 d1 = MyDecimal(1)
1596 d2 = MyDecimal(2)
1597 d = d1 + d2
Ezio Melotti856a3be2010-04-03 14:51:00 +00001598 self.assertIs(type(d), Decimal)
Facundo Batista6c398da2007-09-17 17:30:13 +00001599
1600 d = d1.max(d2)
Ezio Melotti856a3be2010-04-03 14:51:00 +00001601 self.assertIs(type(d), Decimal)
Facundo Batista6c398da2007-09-17 17:30:13 +00001602
Mark Dickinson3b24ccb2008-03-25 14:33:23 +00001603 def test_implicit_context(self):
1604 # Check results when context given implicitly. (Issue 2478)
1605 c = getcontext()
1606 self.assertEqual(str(Decimal(0).sqrt()),
1607 str(c.sqrt(Decimal(0))))
1608
Mark Dickinson0c673122009-10-29 12:04:00 +00001609 def test_conversions_from_int(self):
1610 # Check that methods taking a second Decimal argument will
1611 # always accept an integer in place of a Decimal.
1612 self.assertEqual(Decimal(4).compare(3),
1613 Decimal(4).compare(Decimal(3)))
1614 self.assertEqual(Decimal(4).compare_signal(3),
1615 Decimal(4).compare_signal(Decimal(3)))
1616 self.assertEqual(Decimal(4).compare_total(3),
1617 Decimal(4).compare_total(Decimal(3)))
1618 self.assertEqual(Decimal(4).compare_total_mag(3),
1619 Decimal(4).compare_total_mag(Decimal(3)))
1620 self.assertEqual(Decimal(10101).logical_and(1001),
1621 Decimal(10101).logical_and(Decimal(1001)))
1622 self.assertEqual(Decimal(10101).logical_or(1001),
1623 Decimal(10101).logical_or(Decimal(1001)))
1624 self.assertEqual(Decimal(10101).logical_xor(1001),
1625 Decimal(10101).logical_xor(Decimal(1001)))
1626 self.assertEqual(Decimal(567).max(123),
1627 Decimal(567).max(Decimal(123)))
1628 self.assertEqual(Decimal(567).max_mag(123),
1629 Decimal(567).max_mag(Decimal(123)))
1630 self.assertEqual(Decimal(567).min(123),
1631 Decimal(567).min(Decimal(123)))
1632 self.assertEqual(Decimal(567).min_mag(123),
1633 Decimal(567).min_mag(Decimal(123)))
1634 self.assertEqual(Decimal(567).next_toward(123),
1635 Decimal(567).next_toward(Decimal(123)))
1636 self.assertEqual(Decimal(1234).quantize(100),
1637 Decimal(1234).quantize(Decimal(100)))
1638 self.assertEqual(Decimal(768).remainder_near(1234),
1639 Decimal(768).remainder_near(Decimal(1234)))
1640 self.assertEqual(Decimal(123).rotate(1),
1641 Decimal(123).rotate(Decimal(1)))
1642 self.assertEqual(Decimal(1234).same_quantum(1000),
1643 Decimal(1234).same_quantum(Decimal(1000)))
1644 self.assertEqual(Decimal('9.123').scaleb(-100),
1645 Decimal('9.123').scaleb(Decimal(-100)))
1646 self.assertEqual(Decimal(456).shift(-1),
1647 Decimal(456).shift(Decimal(-1)))
1648
1649 self.assertEqual(Decimal(-12).fma(Decimal(45), 67),
1650 Decimal(-12).fma(Decimal(45), Decimal(67)))
1651 self.assertEqual(Decimal(-12).fma(45, 67),
1652 Decimal(-12).fma(Decimal(45), Decimal(67)))
1653 self.assertEqual(Decimal(-12).fma(45, Decimal(67)),
1654 Decimal(-12).fma(Decimal(45), Decimal(67)))
1655
Facundo Batista6c398da2007-09-17 17:30:13 +00001656
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001657class DecimalPythonAPItests(unittest.TestCase):
1658
Raymond Hettinger2c8585b2009-02-03 03:37:03 +00001659 def test_abc(self):
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001660 self.assertTrue(issubclass(Decimal, numbers.Number))
Ezio Melotti856a3be2010-04-03 14:51:00 +00001661 self.assertFalse(issubclass(Decimal, numbers.Real))
Ezio Melottib0f5adc2010-01-24 16:58:36 +00001662 self.assertIsInstance(Decimal(0), numbers.Number)
Ezio Melotti856a3be2010-04-03 14:51:00 +00001663 self.assertNotIsInstance(Decimal(0), numbers.Real)
Raymond Hettinger2c8585b2009-02-03 03:37:03 +00001664
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001665 def test_pickle(self):
1666 d = Decimal('-3.141590000')
Serhiy Storchaka655720e2014-12-15 14:02:43 +02001667 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
1668 p = pickle.dumps(d, proto)
1669 e = pickle.loads(p)
1670 self.assertEqual(d, e)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001671
Raymond Hettinger5548be22004-07-05 18:49:38 +00001672 def test_int(self):
Raymond Hettinger605ed022004-11-24 07:28:48 +00001673 for x in range(-250, 250):
1674 s = '%0.2f' % (x / 100.0)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001675 # should work the same as for floats
1676 self.assertEqual(int(Decimal(s)), int(float(s)))
Raymond Hettinger605ed022004-11-24 07:28:48 +00001677 # should work the same as to_integral in the ROUND_DOWN mode
Raymond Hettinger5548be22004-07-05 18:49:38 +00001678 d = Decimal(s)
Raymond Hettinger605ed022004-11-24 07:28:48 +00001679 r = d.to_integral(ROUND_DOWN)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001680 self.assertEqual(Decimal(int(d)), r)
1681
Mark Dickinson968f1692009-09-07 18:04:58 +00001682 self.assertRaises(ValueError, int, Decimal('-nan'))
1683 self.assertRaises(ValueError, int, Decimal('snan'))
1684 self.assertRaises(OverflowError, int, Decimal('inf'))
1685 self.assertRaises(OverflowError, int, Decimal('-inf'))
1686
1687 self.assertRaises(ValueError, long, Decimal('-nan'))
1688 self.assertRaises(ValueError, long, Decimal('snan'))
1689 self.assertRaises(OverflowError, long, Decimal('inf'))
1690 self.assertRaises(OverflowError, long, Decimal('-inf'))
1691
Raymond Hettinger5a053642008-01-24 19:05:29 +00001692 def test_trunc(self):
1693 for x in range(-250, 250):
1694 s = '%0.2f' % (x / 100.0)
1695 # should work the same as for floats
1696 self.assertEqual(int(Decimal(s)), int(float(s)))
1697 # should work the same as to_integral in the ROUND_DOWN mode
1698 d = Decimal(s)
1699 r = d.to_integral(ROUND_DOWN)
Jeffrey Yasskinca2b69f2008-02-01 06:22:46 +00001700 self.assertEqual(Decimal(math.trunc(d)), r)
Raymond Hettinger5a053642008-01-24 19:05:29 +00001701
Raymond Hettingerf4d85972009-01-03 19:02:23 +00001702 def test_from_float(self):
1703
1704 class MyDecimal(Decimal):
1705 pass
1706
1707 r = MyDecimal.from_float(0.1)
1708 self.assertEqual(type(r), MyDecimal)
1709 self.assertEqual(str(r),
1710 '0.1000000000000000055511151231257827021181583404541015625')
1711 bigint = 12345678901234567890123456789
1712 self.assertEqual(MyDecimal.from_float(bigint), MyDecimal(bigint))
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001713 self.assertTrue(MyDecimal.from_float(float('nan')).is_qnan())
1714 self.assertTrue(MyDecimal.from_float(float('inf')).is_infinite())
1715 self.assertTrue(MyDecimal.from_float(float('-inf')).is_infinite())
Raymond Hettingerf4d85972009-01-03 19:02:23 +00001716 self.assertEqual(str(MyDecimal.from_float(float('nan'))),
1717 str(Decimal('NaN')))
1718 self.assertEqual(str(MyDecimal.from_float(float('inf'))),
1719 str(Decimal('Infinity')))
1720 self.assertEqual(str(MyDecimal.from_float(float('-inf'))),
1721 str(Decimal('-Infinity')))
1722 self.assertRaises(TypeError, MyDecimal.from_float, 'abc')
1723 for i in range(200):
1724 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
1725 self.assertEqual(x, float(MyDecimal.from_float(x))) # roundtrip
1726
1727 def test_create_decimal_from_float(self):
1728 context = Context(prec=5, rounding=ROUND_DOWN)
1729 self.assertEqual(
1730 context.create_decimal_from_float(math.pi),
1731 Decimal('3.1415')
1732 )
1733 context = Context(prec=5, rounding=ROUND_UP)
1734 self.assertEqual(
1735 context.create_decimal_from_float(math.pi),
1736 Decimal('3.1416')
1737 )
1738 context = Context(prec=5, traps=[Inexact])
1739 self.assertRaises(
1740 Inexact,
1741 context.create_decimal_from_float,
1742 math.pi
1743 )
1744 self.assertEqual(repr(context.create_decimal_from_float(-0.0)),
1745 "Decimal('-0')")
1746 self.assertEqual(repr(context.create_decimal_from_float(1.0)),
1747 "Decimal('1')")
1748 self.assertEqual(repr(context.create_decimal_from_float(10)),
1749 "Decimal('10')")
1750
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00001751class ContextAPItests(unittest.TestCase):
1752
1753 def test_pickle(self):
Serhiy Storchaka655720e2014-12-15 14:02:43 +02001754 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
1755 c = Context()
1756 e = pickle.loads(pickle.dumps(c, proto))
1757 for k in vars(c):
1758 v1 = vars(c)[k]
1759 v2 = vars(e)[k]
1760 self.assertEqual(v1, v2)
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00001761
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001762 def test_equality_with_other_types(self):
Ezio Melottiaa980582010-01-23 23:04:36 +00001763 self.assertIn(Decimal(10), ['a', 1.0, Decimal(10), (1,2), {}])
1764 self.assertNotIn(Decimal(10), ['a', 1.0, (1,2), {}])
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001765
Raymond Hettinger955d2b22004-08-08 20:17:45 +00001766 def test_copy(self):
1767 # All copies should be deep
1768 c = Context()
1769 d = c.copy()
1770 self.assertNotEqual(id(c), id(d))
1771 self.assertNotEqual(id(c.flags), id(d.flags))
1772 self.assertNotEqual(id(c.traps), id(d.traps))
1773
Mark Dickinson6d8effb2010-02-18 14:27:02 +00001774 def test_abs(self):
1775 c = Context()
1776 d = c.abs(Decimal(-1))
1777 self.assertEqual(c.abs(-1), d)
1778 self.assertRaises(TypeError, c.abs, '-1')
1779
1780 def test_add(self):
1781 c = Context()
1782 d = c.add(Decimal(1), Decimal(1))
1783 self.assertEqual(c.add(1, 1), d)
1784 self.assertEqual(c.add(Decimal(1), 1), d)
1785 self.assertEqual(c.add(1, Decimal(1)), d)
1786 self.assertRaises(TypeError, c.add, '1', 1)
1787 self.assertRaises(TypeError, c.add, 1, '1')
1788
1789 def test_compare(self):
1790 c = Context()
1791 d = c.compare(Decimal(1), Decimal(1))
1792 self.assertEqual(c.compare(1, 1), d)
1793 self.assertEqual(c.compare(Decimal(1), 1), d)
1794 self.assertEqual(c.compare(1, Decimal(1)), d)
1795 self.assertRaises(TypeError, c.compare, '1', 1)
1796 self.assertRaises(TypeError, c.compare, 1, '1')
1797
1798 def test_compare_signal(self):
1799 c = Context()
1800 d = c.compare_signal(Decimal(1), Decimal(1))
1801 self.assertEqual(c.compare_signal(1, 1), d)
1802 self.assertEqual(c.compare_signal(Decimal(1), 1), d)
1803 self.assertEqual(c.compare_signal(1, Decimal(1)), d)
1804 self.assertRaises(TypeError, c.compare_signal, '1', 1)
1805 self.assertRaises(TypeError, c.compare_signal, 1, '1')
1806
1807 def test_compare_total(self):
1808 c = Context()
1809 d = c.compare_total(Decimal(1), Decimal(1))
1810 self.assertEqual(c.compare_total(1, 1), d)
1811 self.assertEqual(c.compare_total(Decimal(1), 1), d)
1812 self.assertEqual(c.compare_total(1, Decimal(1)), d)
1813 self.assertRaises(TypeError, c.compare_total, '1', 1)
1814 self.assertRaises(TypeError, c.compare_total, 1, '1')
1815
1816 def test_compare_total_mag(self):
1817 c = Context()
1818 d = c.compare_total_mag(Decimal(1), Decimal(1))
1819 self.assertEqual(c.compare_total_mag(1, 1), d)
1820 self.assertEqual(c.compare_total_mag(Decimal(1), 1), d)
1821 self.assertEqual(c.compare_total_mag(1, Decimal(1)), d)
1822 self.assertRaises(TypeError, c.compare_total_mag, '1', 1)
1823 self.assertRaises(TypeError, c.compare_total_mag, 1, '1')
1824
1825 def test_copy_abs(self):
1826 c = Context()
1827 d = c.copy_abs(Decimal(-1))
1828 self.assertEqual(c.copy_abs(-1), d)
1829 self.assertRaises(TypeError, c.copy_abs, '-1')
1830
1831 def test_copy_decimal(self):
1832 c = Context()
1833 d = c.copy_decimal(Decimal(-1))
1834 self.assertEqual(c.copy_decimal(-1), d)
1835 self.assertRaises(TypeError, c.copy_decimal, '-1')
1836
1837 def test_copy_negate(self):
1838 c = Context()
1839 d = c.copy_negate(Decimal(-1))
1840 self.assertEqual(c.copy_negate(-1), d)
1841 self.assertRaises(TypeError, c.copy_negate, '-1')
1842
1843 def test_copy_sign(self):
1844 c = Context()
1845 d = c.copy_sign(Decimal(1), Decimal(-2))
1846 self.assertEqual(c.copy_sign(1, -2), d)
1847 self.assertEqual(c.copy_sign(Decimal(1), -2), d)
1848 self.assertEqual(c.copy_sign(1, Decimal(-2)), d)
1849 self.assertRaises(TypeError, c.copy_sign, '1', -2)
1850 self.assertRaises(TypeError, c.copy_sign, 1, '-2')
1851
1852 def test_divide(self):
1853 c = Context()
1854 d = c.divide(Decimal(1), Decimal(2))
1855 self.assertEqual(c.divide(1, 2), d)
1856 self.assertEqual(c.divide(Decimal(1), 2), d)
1857 self.assertEqual(c.divide(1, Decimal(2)), d)
1858 self.assertRaises(TypeError, c.divide, '1', 2)
1859 self.assertRaises(TypeError, c.divide, 1, '2')
1860
1861 def test_divide_int(self):
1862 c = Context()
1863 d = c.divide_int(Decimal(1), Decimal(2))
1864 self.assertEqual(c.divide_int(1, 2), d)
1865 self.assertEqual(c.divide_int(Decimal(1), 2), d)
1866 self.assertEqual(c.divide_int(1, Decimal(2)), d)
1867 self.assertRaises(TypeError, c.divide_int, '1', 2)
1868 self.assertRaises(TypeError, c.divide_int, 1, '2')
1869
1870 def test_divmod(self):
1871 c = Context()
1872 d = c.divmod(Decimal(1), Decimal(2))
1873 self.assertEqual(c.divmod(1, 2), d)
1874 self.assertEqual(c.divmod(Decimal(1), 2), d)
1875 self.assertEqual(c.divmod(1, Decimal(2)), d)
1876 self.assertRaises(TypeError, c.divmod, '1', 2)
1877 self.assertRaises(TypeError, c.divmod, 1, '2')
1878
1879 def test_exp(self):
1880 c = Context()
1881 d = c.exp(Decimal(10))
1882 self.assertEqual(c.exp(10), d)
1883 self.assertRaises(TypeError, c.exp, '10')
1884
1885 def test_fma(self):
1886 c = Context()
1887 d = c.fma(Decimal(2), Decimal(3), Decimal(4))
1888 self.assertEqual(c.fma(2, 3, 4), d)
1889 self.assertEqual(c.fma(Decimal(2), 3, 4), d)
1890 self.assertEqual(c.fma(2, Decimal(3), 4), d)
1891 self.assertEqual(c.fma(2, 3, Decimal(4)), d)
1892 self.assertEqual(c.fma(Decimal(2), Decimal(3), 4), d)
1893 self.assertRaises(TypeError, c.fma, '2', 3, 4)
1894 self.assertRaises(TypeError, c.fma, 2, '3', 4)
1895 self.assertRaises(TypeError, c.fma, 2, 3, '4')
1896
1897 def test_is_finite(self):
1898 c = Context()
1899 d = c.is_finite(Decimal(10))
1900 self.assertEqual(c.is_finite(10), d)
1901 self.assertRaises(TypeError, c.is_finite, '10')
1902
1903 def test_is_infinite(self):
1904 c = Context()
1905 d = c.is_infinite(Decimal(10))
1906 self.assertEqual(c.is_infinite(10), d)
1907 self.assertRaises(TypeError, c.is_infinite, '10')
1908
1909 def test_is_nan(self):
1910 c = Context()
1911 d = c.is_nan(Decimal(10))
1912 self.assertEqual(c.is_nan(10), d)
1913 self.assertRaises(TypeError, c.is_nan, '10')
1914
1915 def test_is_normal(self):
1916 c = Context()
1917 d = c.is_normal(Decimal(10))
1918 self.assertEqual(c.is_normal(10), d)
1919 self.assertRaises(TypeError, c.is_normal, '10')
1920
1921 def test_is_qnan(self):
1922 c = Context()
1923 d = c.is_qnan(Decimal(10))
1924 self.assertEqual(c.is_qnan(10), d)
1925 self.assertRaises(TypeError, c.is_qnan, '10')
1926
1927 def test_is_signed(self):
1928 c = Context()
1929 d = c.is_signed(Decimal(10))
1930 self.assertEqual(c.is_signed(10), d)
1931 self.assertRaises(TypeError, c.is_signed, '10')
1932
1933 def test_is_snan(self):
1934 c = Context()
1935 d = c.is_snan(Decimal(10))
1936 self.assertEqual(c.is_snan(10), d)
1937 self.assertRaises(TypeError, c.is_snan, '10')
1938
1939 def test_is_subnormal(self):
1940 c = Context()
1941 d = c.is_subnormal(Decimal(10))
1942 self.assertEqual(c.is_subnormal(10), d)
1943 self.assertRaises(TypeError, c.is_subnormal, '10')
1944
1945 def test_is_zero(self):
1946 c = Context()
1947 d = c.is_zero(Decimal(10))
1948 self.assertEqual(c.is_zero(10), d)
1949 self.assertRaises(TypeError, c.is_zero, '10')
1950
1951 def test_ln(self):
1952 c = Context()
1953 d = c.ln(Decimal(10))
1954 self.assertEqual(c.ln(10), d)
1955 self.assertRaises(TypeError, c.ln, '10')
1956
1957 def test_log10(self):
1958 c = Context()
1959 d = c.log10(Decimal(10))
1960 self.assertEqual(c.log10(10), d)
1961 self.assertRaises(TypeError, c.log10, '10')
1962
1963 def test_logb(self):
1964 c = Context()
1965 d = c.logb(Decimal(10))
1966 self.assertEqual(c.logb(10), d)
1967 self.assertRaises(TypeError, c.logb, '10')
1968
1969 def test_logical_and(self):
1970 c = Context()
1971 d = c.logical_and(Decimal(1), Decimal(1))
1972 self.assertEqual(c.logical_and(1, 1), d)
1973 self.assertEqual(c.logical_and(Decimal(1), 1), d)
1974 self.assertEqual(c.logical_and(1, Decimal(1)), d)
1975 self.assertRaises(TypeError, c.logical_and, '1', 1)
1976 self.assertRaises(TypeError, c.logical_and, 1, '1')
1977
1978 def test_logical_invert(self):
1979 c = Context()
1980 d = c.logical_invert(Decimal(1000))
1981 self.assertEqual(c.logical_invert(1000), d)
1982 self.assertRaises(TypeError, c.logical_invert, '1000')
1983
1984 def test_logical_or(self):
1985 c = Context()
1986 d = c.logical_or(Decimal(1), Decimal(1))
1987 self.assertEqual(c.logical_or(1, 1), d)
1988 self.assertEqual(c.logical_or(Decimal(1), 1), d)
1989 self.assertEqual(c.logical_or(1, Decimal(1)), d)
1990 self.assertRaises(TypeError, c.logical_or, '1', 1)
1991 self.assertRaises(TypeError, c.logical_or, 1, '1')
1992
1993 def test_logical_xor(self):
1994 c = Context()
1995 d = c.logical_xor(Decimal(1), Decimal(1))
1996 self.assertEqual(c.logical_xor(1, 1), d)
1997 self.assertEqual(c.logical_xor(Decimal(1), 1), d)
1998 self.assertEqual(c.logical_xor(1, Decimal(1)), d)
1999 self.assertRaises(TypeError, c.logical_xor, '1', 1)
2000 self.assertRaises(TypeError, c.logical_xor, 1, '1')
2001
2002 def test_max(self):
2003 c = Context()
2004 d = c.max(Decimal(1), Decimal(2))
2005 self.assertEqual(c.max(1, 2), d)
2006 self.assertEqual(c.max(Decimal(1), 2), d)
2007 self.assertEqual(c.max(1, Decimal(2)), d)
2008 self.assertRaises(TypeError, c.max, '1', 2)
2009 self.assertRaises(TypeError, c.max, 1, '2')
2010
2011 def test_max_mag(self):
2012 c = Context()
2013 d = c.max_mag(Decimal(1), Decimal(2))
2014 self.assertEqual(c.max_mag(1, 2), d)
2015 self.assertEqual(c.max_mag(Decimal(1), 2), d)
2016 self.assertEqual(c.max_mag(1, Decimal(2)), d)
2017 self.assertRaises(TypeError, c.max_mag, '1', 2)
2018 self.assertRaises(TypeError, c.max_mag, 1, '2')
2019
2020 def test_min(self):
2021 c = Context()
2022 d = c.min(Decimal(1), Decimal(2))
2023 self.assertEqual(c.min(1, 2), d)
2024 self.assertEqual(c.min(Decimal(1), 2), d)
2025 self.assertEqual(c.min(1, Decimal(2)), d)
2026 self.assertRaises(TypeError, c.min, '1', 2)
2027 self.assertRaises(TypeError, c.min, 1, '2')
2028
2029 def test_min_mag(self):
2030 c = Context()
2031 d = c.min_mag(Decimal(1), Decimal(2))
2032 self.assertEqual(c.min_mag(1, 2), d)
2033 self.assertEqual(c.min_mag(Decimal(1), 2), d)
2034 self.assertEqual(c.min_mag(1, Decimal(2)), d)
2035 self.assertRaises(TypeError, c.min_mag, '1', 2)
2036 self.assertRaises(TypeError, c.min_mag, 1, '2')
2037
2038 def test_minus(self):
2039 c = Context()
2040 d = c.minus(Decimal(10))
2041 self.assertEqual(c.minus(10), d)
2042 self.assertRaises(TypeError, c.minus, '10')
2043
2044 def test_multiply(self):
2045 c = Context()
2046 d = c.multiply(Decimal(1), Decimal(2))
2047 self.assertEqual(c.multiply(1, 2), d)
2048 self.assertEqual(c.multiply(Decimal(1), 2), d)
2049 self.assertEqual(c.multiply(1, Decimal(2)), d)
2050 self.assertRaises(TypeError, c.multiply, '1', 2)
2051 self.assertRaises(TypeError, c.multiply, 1, '2')
2052
2053 def test_next_minus(self):
2054 c = Context()
2055 d = c.next_minus(Decimal(10))
2056 self.assertEqual(c.next_minus(10), d)
2057 self.assertRaises(TypeError, c.next_minus, '10')
2058
2059 def test_next_plus(self):
2060 c = Context()
2061 d = c.next_plus(Decimal(10))
2062 self.assertEqual(c.next_plus(10), d)
2063 self.assertRaises(TypeError, c.next_plus, '10')
2064
2065 def test_next_toward(self):
2066 c = Context()
2067 d = c.next_toward(Decimal(1), Decimal(2))
2068 self.assertEqual(c.next_toward(1, 2), d)
2069 self.assertEqual(c.next_toward(Decimal(1), 2), d)
2070 self.assertEqual(c.next_toward(1, Decimal(2)), d)
2071 self.assertRaises(TypeError, c.next_toward, '1', 2)
2072 self.assertRaises(TypeError, c.next_toward, 1, '2')
2073
2074 def test_normalize(self):
2075 c = Context()
2076 d = c.normalize(Decimal(10))
2077 self.assertEqual(c.normalize(10), d)
2078 self.assertRaises(TypeError, c.normalize, '10')
2079
2080 def test_number_class(self):
2081 c = Context()
2082 self.assertEqual(c.number_class(123), c.number_class(Decimal(123)))
2083 self.assertEqual(c.number_class(0), c.number_class(Decimal(0)))
2084 self.assertEqual(c.number_class(-45), c.number_class(Decimal(-45)))
2085
2086 def test_power(self):
2087 c = Context()
2088 d = c.power(Decimal(1), Decimal(4), Decimal(2))
2089 self.assertEqual(c.power(1, 4, 2), d)
2090 self.assertEqual(c.power(Decimal(1), 4, 2), d)
2091 self.assertEqual(c.power(1, Decimal(4), 2), d)
2092 self.assertEqual(c.power(1, 4, Decimal(2)), d)
2093 self.assertEqual(c.power(Decimal(1), Decimal(4), 2), d)
2094 self.assertRaises(TypeError, c.power, '1', 4, 2)
2095 self.assertRaises(TypeError, c.power, 1, '4', 2)
2096 self.assertRaises(TypeError, c.power, 1, 4, '2')
2097
2098 def test_plus(self):
2099 c = Context()
2100 d = c.plus(Decimal(10))
2101 self.assertEqual(c.plus(10), d)
2102 self.assertRaises(TypeError, c.plus, '10')
2103
2104 def test_quantize(self):
2105 c = Context()
2106 d = c.quantize(Decimal(1), Decimal(2))
2107 self.assertEqual(c.quantize(1, 2), d)
2108 self.assertEqual(c.quantize(Decimal(1), 2), d)
2109 self.assertEqual(c.quantize(1, Decimal(2)), d)
2110 self.assertRaises(TypeError, c.quantize, '1', 2)
2111 self.assertRaises(TypeError, c.quantize, 1, '2')
2112
2113 def test_remainder(self):
2114 c = Context()
2115 d = c.remainder(Decimal(1), Decimal(2))
2116 self.assertEqual(c.remainder(1, 2), d)
2117 self.assertEqual(c.remainder(Decimal(1), 2), d)
2118 self.assertEqual(c.remainder(1, Decimal(2)), d)
2119 self.assertRaises(TypeError, c.remainder, '1', 2)
2120 self.assertRaises(TypeError, c.remainder, 1, '2')
2121
2122 def test_remainder_near(self):
2123 c = Context()
2124 d = c.remainder_near(Decimal(1), Decimal(2))
2125 self.assertEqual(c.remainder_near(1, 2), d)
2126 self.assertEqual(c.remainder_near(Decimal(1), 2), d)
2127 self.assertEqual(c.remainder_near(1, Decimal(2)), d)
2128 self.assertRaises(TypeError, c.remainder_near, '1', 2)
2129 self.assertRaises(TypeError, c.remainder_near, 1, '2')
2130
2131 def test_rotate(self):
2132 c = Context()
2133 d = c.rotate(Decimal(1), Decimal(2))
2134 self.assertEqual(c.rotate(1, 2), d)
2135 self.assertEqual(c.rotate(Decimal(1), 2), d)
2136 self.assertEqual(c.rotate(1, Decimal(2)), d)
2137 self.assertRaises(TypeError, c.rotate, '1', 2)
2138 self.assertRaises(TypeError, c.rotate, 1, '2')
2139
2140 def test_sqrt(self):
2141 c = Context()
2142 d = c.sqrt(Decimal(10))
2143 self.assertEqual(c.sqrt(10), d)
2144 self.assertRaises(TypeError, c.sqrt, '10')
2145
2146 def test_same_quantum(self):
2147 c = Context()
2148 d = c.same_quantum(Decimal(1), Decimal(2))
2149 self.assertEqual(c.same_quantum(1, 2), d)
2150 self.assertEqual(c.same_quantum(Decimal(1), 2), d)
2151 self.assertEqual(c.same_quantum(1, Decimal(2)), d)
2152 self.assertRaises(TypeError, c.same_quantum, '1', 2)
2153 self.assertRaises(TypeError, c.same_quantum, 1, '2')
2154
2155 def test_scaleb(self):
2156 c = Context()
2157 d = c.scaleb(Decimal(1), Decimal(2))
2158 self.assertEqual(c.scaleb(1, 2), d)
2159 self.assertEqual(c.scaleb(Decimal(1), 2), d)
2160 self.assertEqual(c.scaleb(1, Decimal(2)), d)
2161 self.assertRaises(TypeError, c.scaleb, '1', 2)
2162 self.assertRaises(TypeError, c.scaleb, 1, '2')
2163
2164 def test_shift(self):
2165 c = Context()
2166 d = c.shift(Decimal(1), Decimal(2))
2167 self.assertEqual(c.shift(1, 2), d)
2168 self.assertEqual(c.shift(Decimal(1), 2), d)
2169 self.assertEqual(c.shift(1, Decimal(2)), d)
2170 self.assertRaises(TypeError, c.shift, '1', 2)
2171 self.assertRaises(TypeError, c.shift, 1, '2')
2172
2173 def test_subtract(self):
2174 c = Context()
2175 d = c.subtract(Decimal(1), Decimal(2))
2176 self.assertEqual(c.subtract(1, 2), d)
2177 self.assertEqual(c.subtract(Decimal(1), 2), d)
2178 self.assertEqual(c.subtract(1, Decimal(2)), d)
2179 self.assertRaises(TypeError, c.subtract, '1', 2)
2180 self.assertRaises(TypeError, c.subtract, 1, '2')
2181
2182 def test_to_eng_string(self):
2183 c = Context()
2184 d = c.to_eng_string(Decimal(10))
2185 self.assertEqual(c.to_eng_string(10), d)
2186 self.assertRaises(TypeError, c.to_eng_string, '10')
2187
2188 def test_to_sci_string(self):
2189 c = Context()
2190 d = c.to_sci_string(Decimal(10))
2191 self.assertEqual(c.to_sci_string(10), d)
2192 self.assertRaises(TypeError, c.to_sci_string, '10')
2193
2194 def test_to_integral_exact(self):
2195 c = Context()
2196 d = c.to_integral_exact(Decimal(10))
2197 self.assertEqual(c.to_integral_exact(10), d)
2198 self.assertRaises(TypeError, c.to_integral_exact, '10')
2199
2200 def test_to_integral_value(self):
2201 c = Context()
2202 d = c.to_integral_value(Decimal(10))
2203 self.assertEqual(c.to_integral_value(10), d)
2204 self.assertRaises(TypeError, c.to_integral_value, '10')
2205
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002206class WithStatementTest(unittest.TestCase):
2207 # Can't do these as docstrings until Python 2.6
2208 # as doctest can't handle __future__ statements
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002209
2210 def test_localcontext(self):
Nick Coghlanced12182006-09-02 03:54:17 +00002211 # Use a copy of the current context in the block
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002212 orig_ctx = getcontext()
2213 with localcontext() as enter_ctx:
2214 set_ctx = getcontext()
2215 final_ctx = getcontext()
Ezio Melotti856a3be2010-04-03 14:51:00 +00002216 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
2217 self.assertIsNot(orig_ctx, set_ctx, 'did not copy the context')
2218 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002219
2220 def test_localcontextarg(self):
Nick Coghlanced12182006-09-02 03:54:17 +00002221 # Use a copy of the supplied context in the block
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002222 orig_ctx = getcontext()
2223 new_ctx = Context(prec=42)
2224 with localcontext(new_ctx) as enter_ctx:
2225 set_ctx = getcontext()
2226 final_ctx = getcontext()
Ezio Melotti856a3be2010-04-03 14:51:00 +00002227 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
2228 self.assertEqual(set_ctx.prec, new_ctx.prec, 'did not set correct context')
2229 self.assertIsNot(new_ctx, set_ctx, 'did not copy the context')
2230 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002231
Facundo Batista353750c2007-09-13 18:13:15 +00002232class ContextFlags(unittest.TestCase):
2233 def test_flags_irrelevant(self):
2234 # check that the result (numeric result + flags raised) of an
2235 # arithmetic operation doesn't depend on the current flags
2236
2237 context = Context(prec=9, Emin = -999999999, Emax = 999999999,
2238 rounding=ROUND_HALF_EVEN, traps=[], flags=[])
2239
2240 # operations that raise various flags, in the form (function, arglist)
2241 operations = [
2242 (context._apply, [Decimal("100E-1000000009")]),
2243 (context.sqrt, [Decimal(2)]),
2244 (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]),
2245 (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]),
2246 (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]),
2247 ]
2248
2249 # try various flags individually, then a whole lot at once
2250 flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal],
2251 [Inexact, Rounded, Underflow, Clamped, Subnormal]]
2252
2253 for fn, args in operations:
2254 # find answer and flags raised using a clean context
2255 context.clear_flags()
2256 ans = fn(*args)
2257 flags = [k for k, v in context.flags.items() if v]
2258
2259 for extra_flags in flagsets:
2260 # set flags, before calling operation
2261 context.clear_flags()
2262 for flag in extra_flags:
2263 context._raise_error(flag)
2264 new_ans = fn(*args)
2265
2266 # flags that we expect to be set after the operation
2267 expected_flags = list(flags)
2268 for flag in extra_flags:
2269 if flag not in expected_flags:
2270 expected_flags.append(flag)
Facundo Batista353750c2007-09-13 18:13:15 +00002271
2272 # flags we actually got
2273 new_flags = [k for k,v in context.flags.items() if v]
Facundo Batista353750c2007-09-13 18:13:15 +00002274
2275 self.assertEqual(ans, new_ans,
2276 "operation produces different answers depending on flags set: " +
2277 "expected %s, got %s." % (ans, new_ans))
Florent Xicluna8f43cec2010-03-21 10:51:40 +00002278 self.assertItemsEqual(new_flags, expected_flags,
Facundo Batista353750c2007-09-13 18:13:15 +00002279 "operation raises different flags depending on flags set: " +
2280 "expected %s, got %s" % (expected_flags, new_flags))
2281
Zachary Ware9ce635f2014-06-02 16:01:16 -05002282def test_main(arith=None, verbose=None, todo_tests=None, debug=None):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002283 """ Execute the tests.
2284
Raymond Hettingered20ad82004-09-04 20:09:13 +00002285 Runs all arithmetic tests if arith is True or if the "decimal" resource
2286 is enabled in regrtest.py
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002287 """
Raymond Hettingered20ad82004-09-04 20:09:13 +00002288
Neal Norwitzce4a9c92006-04-09 08:36:46 +00002289 init()
Facundo Batista353750c2007-09-13 18:13:15 +00002290 global TEST_ALL, DEBUG
Zachary Ware9ce635f2014-06-02 16:01:16 -05002291 TEST_ALL = arith if arith is not None else is_resource_enabled('decimal')
Facundo Batista353750c2007-09-13 18:13:15 +00002292 DEBUG = debug
Raymond Hettingered20ad82004-09-04 20:09:13 +00002293
Facundo Batista353750c2007-09-13 18:13:15 +00002294 if todo_tests is None:
2295 test_classes = [
2296 DecimalExplicitConstructionTest,
2297 DecimalImplicitConstructionTest,
2298 DecimalArithmeticOperatorsTest,
Mark Dickinson1ddf1d82008-02-29 02:16:37 +00002299 DecimalFormatTest,
Facundo Batista353750c2007-09-13 18:13:15 +00002300 DecimalUseOfContextTest,
2301 DecimalUsabilityTest,
2302 DecimalPythonAPItests,
2303 ContextAPItests,
2304 DecimalTest,
2305 WithStatementTest,
2306 ContextFlags
2307 ]
2308 else:
2309 test_classes = [DecimalTest]
2310
2311 # Dynamically build custom test definition for each file in the test
2312 # directory and add the definitions to the DecimalTest class. This
2313 # procedure insures that new files do not get skipped.
2314 for filename in os.listdir(directory):
2315 if '.decTest' not in filename or filename.startswith("."):
2316 continue
2317 head, tail = filename.split('.')
2318 if todo_tests is not None and head not in todo_tests:
2319 continue
2320 tester = lambda self, f=filename: self.eval_file(directory + f)
2321 setattr(DecimalTest, 'test_' + head, tester)
2322 del filename, head, tail, tester
2323
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002324
Tim Peters46cc7022006-03-31 04:11:16 +00002325 try:
2326 run_unittest(*test_classes)
Facundo Batista353750c2007-09-13 18:13:15 +00002327 if todo_tests is None:
2328 import decimal as DecimalModule
2329 run_doctest(DecimalModule, verbose)
Tim Peters46cc7022006-03-31 04:11:16 +00002330 finally:
2331 setcontext(ORIGINAL_CONTEXT)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002332
2333if __name__ == '__main__':
Facundo Batista353750c2007-09-13 18:13:15 +00002334 import optparse
2335 p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]")
2336 p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test')
2337 p.add_option('--skip', '-s', action='store_true', help='skip over 90% of the arithmetic tests')
2338 (opt, args) = p.parse_args()
2339
2340 if opt.skip:
2341 test_main(arith=False, verbose=True)
2342 elif args:
2343 test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002344 else:
Facundo Batista353750c2007-09-13 18:13:15 +00002345 test_main(arith=True, verbose=True)