blob: 4dbe62d256c12e5b777d9c8c3fd818bb9dc4506a [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')
1667 p = pickle.dumps(d)
1668 e = pickle.loads(p)
1669 self.assertEqual(d, e)
1670
Raymond Hettinger5548be22004-07-05 18:49:38 +00001671 def test_int(self):
Raymond Hettinger605ed022004-11-24 07:28:48 +00001672 for x in range(-250, 250):
1673 s = '%0.2f' % (x / 100.0)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001674 # should work the same as for floats
1675 self.assertEqual(int(Decimal(s)), int(float(s)))
Raymond Hettinger605ed022004-11-24 07:28:48 +00001676 # should work the same as to_integral in the ROUND_DOWN mode
Raymond Hettinger5548be22004-07-05 18:49:38 +00001677 d = Decimal(s)
Raymond Hettinger605ed022004-11-24 07:28:48 +00001678 r = d.to_integral(ROUND_DOWN)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001679 self.assertEqual(Decimal(int(d)), r)
1680
Mark Dickinson968f1692009-09-07 18:04:58 +00001681 self.assertRaises(ValueError, int, Decimal('-nan'))
1682 self.assertRaises(ValueError, int, Decimal('snan'))
1683 self.assertRaises(OverflowError, int, Decimal('inf'))
1684 self.assertRaises(OverflowError, int, Decimal('-inf'))
1685
1686 self.assertRaises(ValueError, long, Decimal('-nan'))
1687 self.assertRaises(ValueError, long, Decimal('snan'))
1688 self.assertRaises(OverflowError, long, Decimal('inf'))
1689 self.assertRaises(OverflowError, long, Decimal('-inf'))
1690
Raymond Hettinger5a053642008-01-24 19:05:29 +00001691 def test_trunc(self):
1692 for x in range(-250, 250):
1693 s = '%0.2f' % (x / 100.0)
1694 # should work the same as for floats
1695 self.assertEqual(int(Decimal(s)), int(float(s)))
1696 # should work the same as to_integral in the ROUND_DOWN mode
1697 d = Decimal(s)
1698 r = d.to_integral(ROUND_DOWN)
Jeffrey Yasskinca2b69f2008-02-01 06:22:46 +00001699 self.assertEqual(Decimal(math.trunc(d)), r)
Raymond Hettinger5a053642008-01-24 19:05:29 +00001700
Raymond Hettingerf4d85972009-01-03 19:02:23 +00001701 def test_from_float(self):
1702
1703 class MyDecimal(Decimal):
1704 pass
1705
1706 r = MyDecimal.from_float(0.1)
1707 self.assertEqual(type(r), MyDecimal)
1708 self.assertEqual(str(r),
1709 '0.1000000000000000055511151231257827021181583404541015625')
1710 bigint = 12345678901234567890123456789
1711 self.assertEqual(MyDecimal.from_float(bigint), MyDecimal(bigint))
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001712 self.assertTrue(MyDecimal.from_float(float('nan')).is_qnan())
1713 self.assertTrue(MyDecimal.from_float(float('inf')).is_infinite())
1714 self.assertTrue(MyDecimal.from_float(float('-inf')).is_infinite())
Raymond Hettingerf4d85972009-01-03 19:02:23 +00001715 self.assertEqual(str(MyDecimal.from_float(float('nan'))),
1716 str(Decimal('NaN')))
1717 self.assertEqual(str(MyDecimal.from_float(float('inf'))),
1718 str(Decimal('Infinity')))
1719 self.assertEqual(str(MyDecimal.from_float(float('-inf'))),
1720 str(Decimal('-Infinity')))
1721 self.assertRaises(TypeError, MyDecimal.from_float, 'abc')
1722 for i in range(200):
1723 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
1724 self.assertEqual(x, float(MyDecimal.from_float(x))) # roundtrip
1725
1726 def test_create_decimal_from_float(self):
1727 context = Context(prec=5, rounding=ROUND_DOWN)
1728 self.assertEqual(
1729 context.create_decimal_from_float(math.pi),
1730 Decimal('3.1415')
1731 )
1732 context = Context(prec=5, rounding=ROUND_UP)
1733 self.assertEqual(
1734 context.create_decimal_from_float(math.pi),
1735 Decimal('3.1416')
1736 )
1737 context = Context(prec=5, traps=[Inexact])
1738 self.assertRaises(
1739 Inexact,
1740 context.create_decimal_from_float,
1741 math.pi
1742 )
1743 self.assertEqual(repr(context.create_decimal_from_float(-0.0)),
1744 "Decimal('-0')")
1745 self.assertEqual(repr(context.create_decimal_from_float(1.0)),
1746 "Decimal('1')")
1747 self.assertEqual(repr(context.create_decimal_from_float(10)),
1748 "Decimal('10')")
1749
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00001750class ContextAPItests(unittest.TestCase):
1751
1752 def test_pickle(self):
1753 c = Context()
1754 e = pickle.loads(pickle.dumps(c))
1755 for k in vars(c):
1756 v1 = vars(c)[k]
1757 v2 = vars(e)[k]
1758 self.assertEqual(v1, v2)
1759
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001760 def test_equality_with_other_types(self):
Ezio Melottiaa980582010-01-23 23:04:36 +00001761 self.assertIn(Decimal(10), ['a', 1.0, Decimal(10), (1,2), {}])
1762 self.assertNotIn(Decimal(10), ['a', 1.0, (1,2), {}])
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001763
Raymond Hettinger955d2b22004-08-08 20:17:45 +00001764 def test_copy(self):
1765 # All copies should be deep
1766 c = Context()
1767 d = c.copy()
1768 self.assertNotEqual(id(c), id(d))
1769 self.assertNotEqual(id(c.flags), id(d.flags))
1770 self.assertNotEqual(id(c.traps), id(d.traps))
1771
Mark Dickinson6d8effb2010-02-18 14:27:02 +00001772 def test_abs(self):
1773 c = Context()
1774 d = c.abs(Decimal(-1))
1775 self.assertEqual(c.abs(-1), d)
1776 self.assertRaises(TypeError, c.abs, '-1')
1777
1778 def test_add(self):
1779 c = Context()
1780 d = c.add(Decimal(1), Decimal(1))
1781 self.assertEqual(c.add(1, 1), d)
1782 self.assertEqual(c.add(Decimal(1), 1), d)
1783 self.assertEqual(c.add(1, Decimal(1)), d)
1784 self.assertRaises(TypeError, c.add, '1', 1)
1785 self.assertRaises(TypeError, c.add, 1, '1')
1786
1787 def test_compare(self):
1788 c = Context()
1789 d = c.compare(Decimal(1), Decimal(1))
1790 self.assertEqual(c.compare(1, 1), d)
1791 self.assertEqual(c.compare(Decimal(1), 1), d)
1792 self.assertEqual(c.compare(1, Decimal(1)), d)
1793 self.assertRaises(TypeError, c.compare, '1', 1)
1794 self.assertRaises(TypeError, c.compare, 1, '1')
1795
1796 def test_compare_signal(self):
1797 c = Context()
1798 d = c.compare_signal(Decimal(1), Decimal(1))
1799 self.assertEqual(c.compare_signal(1, 1), d)
1800 self.assertEqual(c.compare_signal(Decimal(1), 1), d)
1801 self.assertEqual(c.compare_signal(1, Decimal(1)), d)
1802 self.assertRaises(TypeError, c.compare_signal, '1', 1)
1803 self.assertRaises(TypeError, c.compare_signal, 1, '1')
1804
1805 def test_compare_total(self):
1806 c = Context()
1807 d = c.compare_total(Decimal(1), Decimal(1))
1808 self.assertEqual(c.compare_total(1, 1), d)
1809 self.assertEqual(c.compare_total(Decimal(1), 1), d)
1810 self.assertEqual(c.compare_total(1, Decimal(1)), d)
1811 self.assertRaises(TypeError, c.compare_total, '1', 1)
1812 self.assertRaises(TypeError, c.compare_total, 1, '1')
1813
1814 def test_compare_total_mag(self):
1815 c = Context()
1816 d = c.compare_total_mag(Decimal(1), Decimal(1))
1817 self.assertEqual(c.compare_total_mag(1, 1), d)
1818 self.assertEqual(c.compare_total_mag(Decimal(1), 1), d)
1819 self.assertEqual(c.compare_total_mag(1, Decimal(1)), d)
1820 self.assertRaises(TypeError, c.compare_total_mag, '1', 1)
1821 self.assertRaises(TypeError, c.compare_total_mag, 1, '1')
1822
1823 def test_copy_abs(self):
1824 c = Context()
1825 d = c.copy_abs(Decimal(-1))
1826 self.assertEqual(c.copy_abs(-1), d)
1827 self.assertRaises(TypeError, c.copy_abs, '-1')
1828
1829 def test_copy_decimal(self):
1830 c = Context()
1831 d = c.copy_decimal(Decimal(-1))
1832 self.assertEqual(c.copy_decimal(-1), d)
1833 self.assertRaises(TypeError, c.copy_decimal, '-1')
1834
1835 def test_copy_negate(self):
1836 c = Context()
1837 d = c.copy_negate(Decimal(-1))
1838 self.assertEqual(c.copy_negate(-1), d)
1839 self.assertRaises(TypeError, c.copy_negate, '-1')
1840
1841 def test_copy_sign(self):
1842 c = Context()
1843 d = c.copy_sign(Decimal(1), Decimal(-2))
1844 self.assertEqual(c.copy_sign(1, -2), d)
1845 self.assertEqual(c.copy_sign(Decimal(1), -2), d)
1846 self.assertEqual(c.copy_sign(1, Decimal(-2)), d)
1847 self.assertRaises(TypeError, c.copy_sign, '1', -2)
1848 self.assertRaises(TypeError, c.copy_sign, 1, '-2')
1849
1850 def test_divide(self):
1851 c = Context()
1852 d = c.divide(Decimal(1), Decimal(2))
1853 self.assertEqual(c.divide(1, 2), d)
1854 self.assertEqual(c.divide(Decimal(1), 2), d)
1855 self.assertEqual(c.divide(1, Decimal(2)), d)
1856 self.assertRaises(TypeError, c.divide, '1', 2)
1857 self.assertRaises(TypeError, c.divide, 1, '2')
1858
1859 def test_divide_int(self):
1860 c = Context()
1861 d = c.divide_int(Decimal(1), Decimal(2))
1862 self.assertEqual(c.divide_int(1, 2), d)
1863 self.assertEqual(c.divide_int(Decimal(1), 2), d)
1864 self.assertEqual(c.divide_int(1, Decimal(2)), d)
1865 self.assertRaises(TypeError, c.divide_int, '1', 2)
1866 self.assertRaises(TypeError, c.divide_int, 1, '2')
1867
1868 def test_divmod(self):
1869 c = Context()
1870 d = c.divmod(Decimal(1), Decimal(2))
1871 self.assertEqual(c.divmod(1, 2), d)
1872 self.assertEqual(c.divmod(Decimal(1), 2), d)
1873 self.assertEqual(c.divmod(1, Decimal(2)), d)
1874 self.assertRaises(TypeError, c.divmod, '1', 2)
1875 self.assertRaises(TypeError, c.divmod, 1, '2')
1876
1877 def test_exp(self):
1878 c = Context()
1879 d = c.exp(Decimal(10))
1880 self.assertEqual(c.exp(10), d)
1881 self.assertRaises(TypeError, c.exp, '10')
1882
1883 def test_fma(self):
1884 c = Context()
1885 d = c.fma(Decimal(2), Decimal(3), Decimal(4))
1886 self.assertEqual(c.fma(2, 3, 4), d)
1887 self.assertEqual(c.fma(Decimal(2), 3, 4), d)
1888 self.assertEqual(c.fma(2, Decimal(3), 4), d)
1889 self.assertEqual(c.fma(2, 3, Decimal(4)), d)
1890 self.assertEqual(c.fma(Decimal(2), Decimal(3), 4), d)
1891 self.assertRaises(TypeError, c.fma, '2', 3, 4)
1892 self.assertRaises(TypeError, c.fma, 2, '3', 4)
1893 self.assertRaises(TypeError, c.fma, 2, 3, '4')
1894
1895 def test_is_finite(self):
1896 c = Context()
1897 d = c.is_finite(Decimal(10))
1898 self.assertEqual(c.is_finite(10), d)
1899 self.assertRaises(TypeError, c.is_finite, '10')
1900
1901 def test_is_infinite(self):
1902 c = Context()
1903 d = c.is_infinite(Decimal(10))
1904 self.assertEqual(c.is_infinite(10), d)
1905 self.assertRaises(TypeError, c.is_infinite, '10')
1906
1907 def test_is_nan(self):
1908 c = Context()
1909 d = c.is_nan(Decimal(10))
1910 self.assertEqual(c.is_nan(10), d)
1911 self.assertRaises(TypeError, c.is_nan, '10')
1912
1913 def test_is_normal(self):
1914 c = Context()
1915 d = c.is_normal(Decimal(10))
1916 self.assertEqual(c.is_normal(10), d)
1917 self.assertRaises(TypeError, c.is_normal, '10')
1918
1919 def test_is_qnan(self):
1920 c = Context()
1921 d = c.is_qnan(Decimal(10))
1922 self.assertEqual(c.is_qnan(10), d)
1923 self.assertRaises(TypeError, c.is_qnan, '10')
1924
1925 def test_is_signed(self):
1926 c = Context()
1927 d = c.is_signed(Decimal(10))
1928 self.assertEqual(c.is_signed(10), d)
1929 self.assertRaises(TypeError, c.is_signed, '10')
1930
1931 def test_is_snan(self):
1932 c = Context()
1933 d = c.is_snan(Decimal(10))
1934 self.assertEqual(c.is_snan(10), d)
1935 self.assertRaises(TypeError, c.is_snan, '10')
1936
1937 def test_is_subnormal(self):
1938 c = Context()
1939 d = c.is_subnormal(Decimal(10))
1940 self.assertEqual(c.is_subnormal(10), d)
1941 self.assertRaises(TypeError, c.is_subnormal, '10')
1942
1943 def test_is_zero(self):
1944 c = Context()
1945 d = c.is_zero(Decimal(10))
1946 self.assertEqual(c.is_zero(10), d)
1947 self.assertRaises(TypeError, c.is_zero, '10')
1948
1949 def test_ln(self):
1950 c = Context()
1951 d = c.ln(Decimal(10))
1952 self.assertEqual(c.ln(10), d)
1953 self.assertRaises(TypeError, c.ln, '10')
1954
1955 def test_log10(self):
1956 c = Context()
1957 d = c.log10(Decimal(10))
1958 self.assertEqual(c.log10(10), d)
1959 self.assertRaises(TypeError, c.log10, '10')
1960
1961 def test_logb(self):
1962 c = Context()
1963 d = c.logb(Decimal(10))
1964 self.assertEqual(c.logb(10), d)
1965 self.assertRaises(TypeError, c.logb, '10')
1966
1967 def test_logical_and(self):
1968 c = Context()
1969 d = c.logical_and(Decimal(1), Decimal(1))
1970 self.assertEqual(c.logical_and(1, 1), d)
1971 self.assertEqual(c.logical_and(Decimal(1), 1), d)
1972 self.assertEqual(c.logical_and(1, Decimal(1)), d)
1973 self.assertRaises(TypeError, c.logical_and, '1', 1)
1974 self.assertRaises(TypeError, c.logical_and, 1, '1')
1975
1976 def test_logical_invert(self):
1977 c = Context()
1978 d = c.logical_invert(Decimal(1000))
1979 self.assertEqual(c.logical_invert(1000), d)
1980 self.assertRaises(TypeError, c.logical_invert, '1000')
1981
1982 def test_logical_or(self):
1983 c = Context()
1984 d = c.logical_or(Decimal(1), Decimal(1))
1985 self.assertEqual(c.logical_or(1, 1), d)
1986 self.assertEqual(c.logical_or(Decimal(1), 1), d)
1987 self.assertEqual(c.logical_or(1, Decimal(1)), d)
1988 self.assertRaises(TypeError, c.logical_or, '1', 1)
1989 self.assertRaises(TypeError, c.logical_or, 1, '1')
1990
1991 def test_logical_xor(self):
1992 c = Context()
1993 d = c.logical_xor(Decimal(1), Decimal(1))
1994 self.assertEqual(c.logical_xor(1, 1), d)
1995 self.assertEqual(c.logical_xor(Decimal(1), 1), d)
1996 self.assertEqual(c.logical_xor(1, Decimal(1)), d)
1997 self.assertRaises(TypeError, c.logical_xor, '1', 1)
1998 self.assertRaises(TypeError, c.logical_xor, 1, '1')
1999
2000 def test_max(self):
2001 c = Context()
2002 d = c.max(Decimal(1), Decimal(2))
2003 self.assertEqual(c.max(1, 2), d)
2004 self.assertEqual(c.max(Decimal(1), 2), d)
2005 self.assertEqual(c.max(1, Decimal(2)), d)
2006 self.assertRaises(TypeError, c.max, '1', 2)
2007 self.assertRaises(TypeError, c.max, 1, '2')
2008
2009 def test_max_mag(self):
2010 c = Context()
2011 d = c.max_mag(Decimal(1), Decimal(2))
2012 self.assertEqual(c.max_mag(1, 2), d)
2013 self.assertEqual(c.max_mag(Decimal(1), 2), d)
2014 self.assertEqual(c.max_mag(1, Decimal(2)), d)
2015 self.assertRaises(TypeError, c.max_mag, '1', 2)
2016 self.assertRaises(TypeError, c.max_mag, 1, '2')
2017
2018 def test_min(self):
2019 c = Context()
2020 d = c.min(Decimal(1), Decimal(2))
2021 self.assertEqual(c.min(1, 2), d)
2022 self.assertEqual(c.min(Decimal(1), 2), d)
2023 self.assertEqual(c.min(1, Decimal(2)), d)
2024 self.assertRaises(TypeError, c.min, '1', 2)
2025 self.assertRaises(TypeError, c.min, 1, '2')
2026
2027 def test_min_mag(self):
2028 c = Context()
2029 d = c.min_mag(Decimal(1), Decimal(2))
2030 self.assertEqual(c.min_mag(1, 2), d)
2031 self.assertEqual(c.min_mag(Decimal(1), 2), d)
2032 self.assertEqual(c.min_mag(1, Decimal(2)), d)
2033 self.assertRaises(TypeError, c.min_mag, '1', 2)
2034 self.assertRaises(TypeError, c.min_mag, 1, '2')
2035
2036 def test_minus(self):
2037 c = Context()
2038 d = c.minus(Decimal(10))
2039 self.assertEqual(c.minus(10), d)
2040 self.assertRaises(TypeError, c.minus, '10')
2041
2042 def test_multiply(self):
2043 c = Context()
2044 d = c.multiply(Decimal(1), Decimal(2))
2045 self.assertEqual(c.multiply(1, 2), d)
2046 self.assertEqual(c.multiply(Decimal(1), 2), d)
2047 self.assertEqual(c.multiply(1, Decimal(2)), d)
2048 self.assertRaises(TypeError, c.multiply, '1', 2)
2049 self.assertRaises(TypeError, c.multiply, 1, '2')
2050
2051 def test_next_minus(self):
2052 c = Context()
2053 d = c.next_minus(Decimal(10))
2054 self.assertEqual(c.next_minus(10), d)
2055 self.assertRaises(TypeError, c.next_minus, '10')
2056
2057 def test_next_plus(self):
2058 c = Context()
2059 d = c.next_plus(Decimal(10))
2060 self.assertEqual(c.next_plus(10), d)
2061 self.assertRaises(TypeError, c.next_plus, '10')
2062
2063 def test_next_toward(self):
2064 c = Context()
2065 d = c.next_toward(Decimal(1), Decimal(2))
2066 self.assertEqual(c.next_toward(1, 2), d)
2067 self.assertEqual(c.next_toward(Decimal(1), 2), d)
2068 self.assertEqual(c.next_toward(1, Decimal(2)), d)
2069 self.assertRaises(TypeError, c.next_toward, '1', 2)
2070 self.assertRaises(TypeError, c.next_toward, 1, '2')
2071
2072 def test_normalize(self):
2073 c = Context()
2074 d = c.normalize(Decimal(10))
2075 self.assertEqual(c.normalize(10), d)
2076 self.assertRaises(TypeError, c.normalize, '10')
2077
2078 def test_number_class(self):
2079 c = Context()
2080 self.assertEqual(c.number_class(123), c.number_class(Decimal(123)))
2081 self.assertEqual(c.number_class(0), c.number_class(Decimal(0)))
2082 self.assertEqual(c.number_class(-45), c.number_class(Decimal(-45)))
2083
2084 def test_power(self):
2085 c = Context()
2086 d = c.power(Decimal(1), Decimal(4), Decimal(2))
2087 self.assertEqual(c.power(1, 4, 2), d)
2088 self.assertEqual(c.power(Decimal(1), 4, 2), d)
2089 self.assertEqual(c.power(1, Decimal(4), 2), d)
2090 self.assertEqual(c.power(1, 4, Decimal(2)), d)
2091 self.assertEqual(c.power(Decimal(1), Decimal(4), 2), d)
2092 self.assertRaises(TypeError, c.power, '1', 4, 2)
2093 self.assertRaises(TypeError, c.power, 1, '4', 2)
2094 self.assertRaises(TypeError, c.power, 1, 4, '2')
2095
2096 def test_plus(self):
2097 c = Context()
2098 d = c.plus(Decimal(10))
2099 self.assertEqual(c.plus(10), d)
2100 self.assertRaises(TypeError, c.plus, '10')
2101
2102 def test_quantize(self):
2103 c = Context()
2104 d = c.quantize(Decimal(1), Decimal(2))
2105 self.assertEqual(c.quantize(1, 2), d)
2106 self.assertEqual(c.quantize(Decimal(1), 2), d)
2107 self.assertEqual(c.quantize(1, Decimal(2)), d)
2108 self.assertRaises(TypeError, c.quantize, '1', 2)
2109 self.assertRaises(TypeError, c.quantize, 1, '2')
2110
2111 def test_remainder(self):
2112 c = Context()
2113 d = c.remainder(Decimal(1), Decimal(2))
2114 self.assertEqual(c.remainder(1, 2), d)
2115 self.assertEqual(c.remainder(Decimal(1), 2), d)
2116 self.assertEqual(c.remainder(1, Decimal(2)), d)
2117 self.assertRaises(TypeError, c.remainder, '1', 2)
2118 self.assertRaises(TypeError, c.remainder, 1, '2')
2119
2120 def test_remainder_near(self):
2121 c = Context()
2122 d = c.remainder_near(Decimal(1), Decimal(2))
2123 self.assertEqual(c.remainder_near(1, 2), d)
2124 self.assertEqual(c.remainder_near(Decimal(1), 2), d)
2125 self.assertEqual(c.remainder_near(1, Decimal(2)), d)
2126 self.assertRaises(TypeError, c.remainder_near, '1', 2)
2127 self.assertRaises(TypeError, c.remainder_near, 1, '2')
2128
2129 def test_rotate(self):
2130 c = Context()
2131 d = c.rotate(Decimal(1), Decimal(2))
2132 self.assertEqual(c.rotate(1, 2), d)
2133 self.assertEqual(c.rotate(Decimal(1), 2), d)
2134 self.assertEqual(c.rotate(1, Decimal(2)), d)
2135 self.assertRaises(TypeError, c.rotate, '1', 2)
2136 self.assertRaises(TypeError, c.rotate, 1, '2')
2137
2138 def test_sqrt(self):
2139 c = Context()
2140 d = c.sqrt(Decimal(10))
2141 self.assertEqual(c.sqrt(10), d)
2142 self.assertRaises(TypeError, c.sqrt, '10')
2143
2144 def test_same_quantum(self):
2145 c = Context()
2146 d = c.same_quantum(Decimal(1), Decimal(2))
2147 self.assertEqual(c.same_quantum(1, 2), d)
2148 self.assertEqual(c.same_quantum(Decimal(1), 2), d)
2149 self.assertEqual(c.same_quantum(1, Decimal(2)), d)
2150 self.assertRaises(TypeError, c.same_quantum, '1', 2)
2151 self.assertRaises(TypeError, c.same_quantum, 1, '2')
2152
2153 def test_scaleb(self):
2154 c = Context()
2155 d = c.scaleb(Decimal(1), Decimal(2))
2156 self.assertEqual(c.scaleb(1, 2), d)
2157 self.assertEqual(c.scaleb(Decimal(1), 2), d)
2158 self.assertEqual(c.scaleb(1, Decimal(2)), d)
2159 self.assertRaises(TypeError, c.scaleb, '1', 2)
2160 self.assertRaises(TypeError, c.scaleb, 1, '2')
2161
2162 def test_shift(self):
2163 c = Context()
2164 d = c.shift(Decimal(1), Decimal(2))
2165 self.assertEqual(c.shift(1, 2), d)
2166 self.assertEqual(c.shift(Decimal(1), 2), d)
2167 self.assertEqual(c.shift(1, Decimal(2)), d)
2168 self.assertRaises(TypeError, c.shift, '1', 2)
2169 self.assertRaises(TypeError, c.shift, 1, '2')
2170
2171 def test_subtract(self):
2172 c = Context()
2173 d = c.subtract(Decimal(1), Decimal(2))
2174 self.assertEqual(c.subtract(1, 2), d)
2175 self.assertEqual(c.subtract(Decimal(1), 2), d)
2176 self.assertEqual(c.subtract(1, Decimal(2)), d)
2177 self.assertRaises(TypeError, c.subtract, '1', 2)
2178 self.assertRaises(TypeError, c.subtract, 1, '2')
2179
2180 def test_to_eng_string(self):
2181 c = Context()
2182 d = c.to_eng_string(Decimal(10))
2183 self.assertEqual(c.to_eng_string(10), d)
2184 self.assertRaises(TypeError, c.to_eng_string, '10')
2185
2186 def test_to_sci_string(self):
2187 c = Context()
2188 d = c.to_sci_string(Decimal(10))
2189 self.assertEqual(c.to_sci_string(10), d)
2190 self.assertRaises(TypeError, c.to_sci_string, '10')
2191
2192 def test_to_integral_exact(self):
2193 c = Context()
2194 d = c.to_integral_exact(Decimal(10))
2195 self.assertEqual(c.to_integral_exact(10), d)
2196 self.assertRaises(TypeError, c.to_integral_exact, '10')
2197
2198 def test_to_integral_value(self):
2199 c = Context()
2200 d = c.to_integral_value(Decimal(10))
2201 self.assertEqual(c.to_integral_value(10), d)
2202 self.assertRaises(TypeError, c.to_integral_value, '10')
2203
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002204class WithStatementTest(unittest.TestCase):
2205 # Can't do these as docstrings until Python 2.6
2206 # as doctest can't handle __future__ statements
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002207
2208 def test_localcontext(self):
Nick Coghlanced12182006-09-02 03:54:17 +00002209 # Use a copy of the current context in the block
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002210 orig_ctx = getcontext()
2211 with localcontext() as enter_ctx:
2212 set_ctx = getcontext()
2213 final_ctx = getcontext()
Ezio Melotti856a3be2010-04-03 14:51:00 +00002214 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
2215 self.assertIsNot(orig_ctx, set_ctx, 'did not copy the context')
2216 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002217
2218 def test_localcontextarg(self):
Nick Coghlanced12182006-09-02 03:54:17 +00002219 # Use a copy of the supplied context in the block
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002220 orig_ctx = getcontext()
2221 new_ctx = Context(prec=42)
2222 with localcontext(new_ctx) as enter_ctx:
2223 set_ctx = getcontext()
2224 final_ctx = getcontext()
Ezio Melotti856a3be2010-04-03 14:51:00 +00002225 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
2226 self.assertEqual(set_ctx.prec, new_ctx.prec, 'did not set correct context')
2227 self.assertIsNot(new_ctx, set_ctx, 'did not copy the context')
2228 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002229
Facundo Batista353750c2007-09-13 18:13:15 +00002230class ContextFlags(unittest.TestCase):
2231 def test_flags_irrelevant(self):
2232 # check that the result (numeric result + flags raised) of an
2233 # arithmetic operation doesn't depend on the current flags
2234
2235 context = Context(prec=9, Emin = -999999999, Emax = 999999999,
2236 rounding=ROUND_HALF_EVEN, traps=[], flags=[])
2237
2238 # operations that raise various flags, in the form (function, arglist)
2239 operations = [
2240 (context._apply, [Decimal("100E-1000000009")]),
2241 (context.sqrt, [Decimal(2)]),
2242 (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]),
2243 (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]),
2244 (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]),
2245 ]
2246
2247 # try various flags individually, then a whole lot at once
2248 flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal],
2249 [Inexact, Rounded, Underflow, Clamped, Subnormal]]
2250
2251 for fn, args in operations:
2252 # find answer and flags raised using a clean context
2253 context.clear_flags()
2254 ans = fn(*args)
2255 flags = [k for k, v in context.flags.items() if v]
2256
2257 for extra_flags in flagsets:
2258 # set flags, before calling operation
2259 context.clear_flags()
2260 for flag in extra_flags:
2261 context._raise_error(flag)
2262 new_ans = fn(*args)
2263
2264 # flags that we expect to be set after the operation
2265 expected_flags = list(flags)
2266 for flag in extra_flags:
2267 if flag not in expected_flags:
2268 expected_flags.append(flag)
Facundo Batista353750c2007-09-13 18:13:15 +00002269
2270 # flags we actually got
2271 new_flags = [k for k,v in context.flags.items() if v]
Facundo Batista353750c2007-09-13 18:13:15 +00002272
2273 self.assertEqual(ans, new_ans,
2274 "operation produces different answers depending on flags set: " +
2275 "expected %s, got %s." % (ans, new_ans))
Florent Xicluna8f43cec2010-03-21 10:51:40 +00002276 self.assertItemsEqual(new_flags, expected_flags,
Facundo Batista353750c2007-09-13 18:13:15 +00002277 "operation raises different flags depending on flags set: " +
2278 "expected %s, got %s" % (expected_flags, new_flags))
2279
Zachary Ware9ce635f2014-06-02 16:01:16 -05002280def test_main(arith=None, verbose=None, todo_tests=None, debug=None):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002281 """ Execute the tests.
2282
Raymond Hettingered20ad82004-09-04 20:09:13 +00002283 Runs all arithmetic tests if arith is True or if the "decimal" resource
2284 is enabled in regrtest.py
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002285 """
Raymond Hettingered20ad82004-09-04 20:09:13 +00002286
Neal Norwitzce4a9c92006-04-09 08:36:46 +00002287 init()
Facundo Batista353750c2007-09-13 18:13:15 +00002288 global TEST_ALL, DEBUG
Zachary Ware9ce635f2014-06-02 16:01:16 -05002289 TEST_ALL = arith if arith is not None else is_resource_enabled('decimal')
Facundo Batista353750c2007-09-13 18:13:15 +00002290 DEBUG = debug
Raymond Hettingered20ad82004-09-04 20:09:13 +00002291
Facundo Batista353750c2007-09-13 18:13:15 +00002292 if todo_tests is None:
2293 test_classes = [
2294 DecimalExplicitConstructionTest,
2295 DecimalImplicitConstructionTest,
2296 DecimalArithmeticOperatorsTest,
Mark Dickinson1ddf1d82008-02-29 02:16:37 +00002297 DecimalFormatTest,
Facundo Batista353750c2007-09-13 18:13:15 +00002298 DecimalUseOfContextTest,
2299 DecimalUsabilityTest,
2300 DecimalPythonAPItests,
2301 ContextAPItests,
2302 DecimalTest,
2303 WithStatementTest,
2304 ContextFlags
2305 ]
2306 else:
2307 test_classes = [DecimalTest]
2308
2309 # Dynamically build custom test definition for each file in the test
2310 # directory and add the definitions to the DecimalTest class. This
2311 # procedure insures that new files do not get skipped.
2312 for filename in os.listdir(directory):
2313 if '.decTest' not in filename or filename.startswith("."):
2314 continue
2315 head, tail = filename.split('.')
2316 if todo_tests is not None and head not in todo_tests:
2317 continue
2318 tester = lambda self, f=filename: self.eval_file(directory + f)
2319 setattr(DecimalTest, 'test_' + head, tester)
2320 del filename, head, tail, tester
2321
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002322
Tim Peters46cc7022006-03-31 04:11:16 +00002323 try:
2324 run_unittest(*test_classes)
Facundo Batista353750c2007-09-13 18:13:15 +00002325 if todo_tests is None:
2326 import decimal as DecimalModule
2327 run_doctest(DecimalModule, verbose)
Tim Peters46cc7022006-03-31 04:11:16 +00002328 finally:
2329 setcontext(ORIGINAL_CONTEXT)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002330
2331if __name__ == '__main__':
Facundo Batista353750c2007-09-13 18:13:15 +00002332 import optparse
2333 p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]")
2334 p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test')
2335 p.add_option('--skip', '-s', action='store_true', help='skip over 90% of the arithmetic tests')
2336 (opt, args) = p.parse_args()
2337
2338 if opt.skip:
2339 test_main(arith=False, verbose=True)
2340 elif args:
2341 test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002342 else:
Facundo Batista353750c2007-09-13 18:13:15 +00002343 test_main(arith=True, verbose=True)