blob: 610a696076128880516e8dc492a4ead634761033 [file] [log] [blame]
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001# Copyright (c) 2004 Python Software Foundation.
2# All rights reserved.
3
4# Written by Eric Price <eprice at tjhsst.edu>
5# and Facundo Batista <facundo at taniquetil.com.ar>
6# and Raymond Hettinger <python at rcn.com>
7# and Aahz (aahz at pobox.com)
8# and Tim Peters
9
10"""
11These are the test cases for the Decimal module.
12
13There are two groups of tests, Arithmetic and Behaviour. The former test
14the Decimal arithmetic using the tests provided by Mike Cowlishaw. The latter
15test the pythonic behaviour according to PEP 327.
16
17Cowlishaw's tests can be downloaded from:
18
19 www2.hursley.ibm.com/decimal/dectest.zip
20
21This test module can be called from command line with one parameter (Arithmetic
22or Behaviour) to test each part, or without parameter to test both parts. If
23you're working through IDLE, you can import this test module and call test_main()
24with the corresponding argument.
25"""
26
Jeffrey Yasskinca2b69f2008-02-01 06:22:46 +000027import math
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000028import os, sys
Mark Dickinsone096e822010-04-02 10:17:07 +000029import operator
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000030import pickle, copy
Jeffrey Yasskinca2b69f2008-02-01 06:22:46 +000031import unittest
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000032from decimal import *
Raymond Hettinger2c8585b2009-02-03 03:37:03 +000033import numbers
Florent Xicluna8f43cec2010-03-21 10:51:40 +000034from test.test_support import (run_unittest, run_doctest,
35 is_resource_enabled, check_py3k_warnings)
Raymond Hettinger0aeac102004-07-05 22:53:03 +000036import random
Raymond Hettinger7e71fa52004-12-18 19:07:19 +000037try:
38 import threading
39except ImportError:
40 threading = None
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000041
Raymond Hettingerfed52962004-07-14 15:41:57 +000042# Useful Test Constant
Mark Dickinson16cd2be2010-05-01 11:46:20 +000043Signals = tuple(getcontext().flags.keys())
Raymond Hettingerfed52962004-07-14 15:41:57 +000044
Mark Dickinson4f96f5f2010-05-04 14:25:50 +000045# Signals ordered with respect to precedence: when an operation
46# produces multiple signals, signals occurring later in the list
47# should be handled before those occurring earlier in the list.
48OrderedSignals = (Clamped, Rounded, Inexact, Subnormal,
49 Underflow, Overflow, DivisionByZero, InvalidOperation)
50
Tim Peters46cc7022006-03-31 04:11:16 +000051# Tests are built around these assumed context defaults.
52# test_main() restores the original context.
Neal Norwitzce4a9c92006-04-09 08:36:46 +000053def init():
54 global ORIGINAL_CONTEXT
55 ORIGINAL_CONTEXT = getcontext().copy()
Facundo Batistaee340e52008-05-02 17:39:00 +000056 DefaultTestContext = Context(
57 prec = 9,
58 rounding = ROUND_HALF_EVEN,
59 traps = dict.fromkeys(Signals, 0)
60 )
61 setcontext(DefaultTestContext)
Raymond Hettinger6ea48452004-07-03 12:26:21 +000062
Raymond Hettingered171ab2010-04-02 18:39:24 +000063# decorator for skipping tests on non-IEEE 754 platforms
64requires_IEEE_754 = unittest.skipUnless(
65 float.__getformat__("double").startswith("IEEE"),
66 "test requires IEEE 754 doubles")
67
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000068TESTDATADIR = 'decimaltestdata'
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +000069if __name__ == '__main__':
70 file = sys.argv[0]
71else:
72 file = __file__
73testdir = os.path.dirname(file) or os.curdir
Raymond Hettinger267b8682005-03-27 10:47:39 +000074directory = testdir + os.sep + TESTDATADIR + os.sep
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000075
Raymond Hettinger267b8682005-03-27 10:47:39 +000076skip_expected = not os.path.isdir(directory)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000077
Mark Dickinson539bff42009-10-08 16:28:39 +000078# list of individual .decTest test ids that correspond to tests that
79# we're skipping for one reason or another.
Mark Dickinsone85aa732010-07-08 19:24:40 +000080skipped_test_ids = set([
81 # Skip implementation-specific scaleb tests.
82 'scbx164',
83 'scbx165',
84
85 # For some operations (currently exp, ln, log10, power), the decNumber
86 # reference implementation imposes additional restrictions on the context
87 # and operands. These restrictions are not part of the specification;
88 # however, the effect of these restrictions does show up in some of the
89 # testcases. We skip testcases that violate these restrictions, since
90 # Decimal behaves differently from decNumber for these testcases so these
91 # testcases would otherwise fail.
92 'expx901',
93 'expx902',
94 'expx903',
95 'expx905',
96 'lnx901',
97 'lnx902',
98 'lnx903',
99 'lnx905',
100 'logx901',
101 'logx902',
102 'logx903',
103 'logx905',
104 'powx1183',
105 'powx1184',
106 'powx4001',
107 'powx4002',
108 'powx4003',
109 'powx4005',
110 'powx4008',
111 'powx4010',
112 'powx4012',
113 'powx4014',
114 ])
Mark Dickinson539bff42009-10-08 16:28:39 +0000115
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000116# Make sure it actually raises errors when not expected and caught in flags
117# Slower, since it runs some things several times.
118EXTENDEDERRORTEST = False
119
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000120#Map the test cases' error names to the actual errors
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000121ErrorNames = {'clamped' : Clamped,
Raymond Hettinger5aa478b2004-07-09 10:02:53 +0000122 'conversion_syntax' : InvalidOperation,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000123 'division_by_zero' : DivisionByZero,
Raymond Hettinger5aa478b2004-07-09 10:02:53 +0000124 'division_impossible' : InvalidOperation,
125 'division_undefined' : InvalidOperation,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000126 'inexact' : Inexact,
Raymond Hettinger5aa478b2004-07-09 10:02:53 +0000127 'invalid_context' : InvalidOperation,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000128 'invalid_operation' : InvalidOperation,
129 'overflow' : Overflow,
130 'rounded' : Rounded,
131 'subnormal' : Subnormal,
132 'underflow' : Underflow}
133
134
135def Nonfunction(*args):
136 """Doesn't do anything."""
137 return None
138
139RoundingDict = {'ceiling' : ROUND_CEILING, #Maps test-case names to roundings.
140 'down' : ROUND_DOWN,
141 'floor' : ROUND_FLOOR,
142 'half_down' : ROUND_HALF_DOWN,
143 'half_even' : ROUND_HALF_EVEN,
144 'half_up' : ROUND_HALF_UP,
Facundo Batista353750c2007-09-13 18:13:15 +0000145 'up' : ROUND_UP,
146 '05up' : ROUND_05UP}
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000147
148# Name adapter to be able to change the Decimal and Context
149# interface without changing the test files from Cowlishaw
Facundo Batista1a191df2007-10-02 17:01:24 +0000150nameAdapter = {'and':'logical_and',
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000151 'apply':'_apply',
Facundo Batista353750c2007-09-13 18:13:15 +0000152 'class':'number_class',
153 'comparesig':'compare_signal',
154 'comparetotal':'compare_total',
155 'comparetotmag':'compare_total_mag',
Facundo Batista353750c2007-09-13 18:13:15 +0000156 'copy':'copy_decimal',
Facundo Batista1a191df2007-10-02 17:01:24 +0000157 'copyabs':'copy_abs',
Facundo Batista353750c2007-09-13 18:13:15 +0000158 'copynegate':'copy_negate',
159 'copysign':'copy_sign',
Facundo Batista1a191df2007-10-02 17:01:24 +0000160 'divideint':'divide_int',
Facundo Batista353750c2007-09-13 18:13:15 +0000161 'invert':'logical_invert',
Facundo Batista1a191df2007-10-02 17:01:24 +0000162 'iscanonical':'is_canonical',
163 'isfinite':'is_finite',
164 'isinfinite':'is_infinite',
165 'isnan':'is_nan',
166 'isnormal':'is_normal',
167 'isqnan':'is_qnan',
168 'issigned':'is_signed',
169 'issnan':'is_snan',
170 'issubnormal':'is_subnormal',
171 'iszero':'is_zero',
Facundo Batista353750c2007-09-13 18:13:15 +0000172 'maxmag':'max_mag',
173 'minmag':'min_mag',
174 'nextminus':'next_minus',
175 'nextplus':'next_plus',
176 'nexttoward':'next_toward',
Facundo Batista1a191df2007-10-02 17:01:24 +0000177 'or':'logical_or',
Facundo Batista353750c2007-09-13 18:13:15 +0000178 'reduce':'normalize',
Facundo Batista1a191df2007-10-02 17:01:24 +0000179 'remaindernear':'remainder_near',
180 'samequantum':'same_quantum',
181 'squareroot':'sqrt',
182 'toeng':'to_eng_string',
183 'tointegral':'to_integral_value',
184 'tointegralx':'to_integral_exact',
185 'tosci':'to_sci_string',
186 'xor':'logical_xor',
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000187 }
188
Facundo Batista1a191df2007-10-02 17:01:24 +0000189# The following functions return True/False rather than a Decimal instance
190
191LOGICAL_FUNCTIONS = (
192 'is_canonical',
193 'is_finite',
194 'is_infinite',
195 'is_nan',
196 'is_normal',
197 'is_qnan',
198 'is_signed',
199 'is_snan',
200 'is_subnormal',
201 'is_zero',
202 'same_quantum',
203 )
204
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000205class DecimalTest(unittest.TestCase):
206 """Class which tests the Decimal class against the test cases.
207
208 Changed for unittest.
209 """
210 def setUp(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000211 self.context = Context()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000212 self.ignore_list = ['#']
213 # Basically, a # means return NaN InvalidOperation.
214 # Different from a sNaN in trim
215
216 self.ChangeDict = {'precision' : self.change_precision,
217 'rounding' : self.change_rounding_method,
218 'maxexponent' : self.change_max_exponent,
219 'minexponent' : self.change_min_exponent,
220 'clamp' : self.change_clamp}
221
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000222 def eval_file(self, file):
223 global skip_expected
224 if skip_expected:
Benjamin Petersonbec087f2009-03-26 21:10:30 +0000225 raise unittest.SkipTest
Antoine Pitrou99d848b2010-10-14 22:22:30 +0000226 with open(file) as f:
227 for line in f:
228 line = line.replace('\r\n', '').replace('\n', '')
229 #print line
230 try:
231 t = self.eval_line(line)
232 except DecimalException as exception:
Ezio Melottic2077b02011-03-16 12:34:31 +0200233 #Exception raised where there shouldn't have been one.
Antoine Pitrou99d848b2010-10-14 22:22:30 +0000234 self.fail('Exception "'+exception.__class__.__name__ + '" raised on line '+line)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000235
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000236
237 def eval_line(self, s):
238 if s.find(' -> ') >= 0 and s[:2] != '--' and not s.startswith(' --'):
239 s = (s.split('->')[0] + '->' +
240 s.split('->')[1].split('--')[0]).strip()
241 else:
242 s = s.split('--')[0].strip()
243
244 for ignore in self.ignore_list:
245 if s.find(ignore) >= 0:
246 #print s.split()[0], 'NotImplemented--', ignore
247 return
248 if not s:
249 return
250 elif ':' in s:
251 return self.eval_directive(s)
252 else:
253 return self.eval_equation(s)
254
255 def eval_directive(self, s):
256 funct, value = map(lambda x: x.strip().lower(), s.split(':'))
257 if funct == 'rounding':
258 value = RoundingDict[value]
259 else:
260 try:
261 value = int(value)
262 except ValueError:
263 pass
264
265 funct = self.ChangeDict.get(funct, Nonfunction)
266 funct(value)
267
268 def eval_equation(self, s):
269 #global DEFAULT_PRECISION
270 #print DEFAULT_PRECISION
Raymond Hettingered20ad82004-09-04 20:09:13 +0000271
272 if not TEST_ALL and random.random() < 0.90:
273 return
274
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000275 try:
276 Sides = s.split('->')
277 L = Sides[0].strip().split()
278 id = L[0]
Facundo Batista353750c2007-09-13 18:13:15 +0000279 if DEBUG:
280 print "Test ", id,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000281 funct = L[1].lower()
282 valstemp = L[2:]
283 L = Sides[1].strip().split()
284 ans = L[0]
285 exceptions = L[1:]
286 except (TypeError, AttributeError, IndexError):
Raymond Hettingerd87ac8f2004-07-09 10:52:54 +0000287 raise InvalidOperation
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000288 def FixQuotes(val):
289 val = val.replace("''", 'SingleQuote').replace('""', 'DoubleQuote')
290 val = val.replace("'", '').replace('"', '')
291 val = val.replace('SingleQuote', "'").replace('DoubleQuote', '"')
292 return val
Mark Dickinson539bff42009-10-08 16:28:39 +0000293
294 if id in skipped_test_ids:
295 return
296
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000297 fname = nameAdapter.get(funct, funct)
298 if fname == 'rescale':
299 return
300 funct = getattr(self.context, fname)
301 vals = []
302 conglomerate = ''
303 quote = 0
304 theirexceptions = [ErrorNames[x.lower()] for x in exceptions]
305
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000306 for exception in Signals:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000307 self.context.traps[exception] = 1 #Catch these bugs...
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000308 for exception in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000309 self.context.traps[exception] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000310 for i, val in enumerate(valstemp):
311 if val.count("'") % 2 == 1:
312 quote = 1 - quote
313 if quote:
314 conglomerate = conglomerate + ' ' + val
315 continue
316 else:
317 val = conglomerate + val
318 conglomerate = ''
319 v = FixQuotes(val)
320 if fname in ('to_sci_string', 'to_eng_string'):
321 if EXTENDEDERRORTEST:
322 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000323 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000324 try:
325 funct(self.context.create_decimal(v))
326 except error:
327 pass
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000328 except Signals, e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000329 self.fail("Raised %s in %s when %s disabled" % \
330 (e, s, error))
331 else:
332 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000333 self.context.traps[error] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000334 v = self.context.create_decimal(v)
335 else:
Facundo Batista353750c2007-09-13 18:13:15 +0000336 v = Decimal(v, self.context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000337 vals.append(v)
338
339 ans = FixQuotes(ans)
340
341 if EXTENDEDERRORTEST and fname not in ('to_sci_string', 'to_eng_string'):
342 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000343 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000344 try:
345 funct(*vals)
346 except error:
347 pass
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000348 except Signals, e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000349 self.fail("Raised %s in %s when %s disabled" % \
350 (e, s, error))
351 else:
352 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000353 self.context.traps[error] = 0
Mark Dickinson4f96f5f2010-05-04 14:25:50 +0000354
355 # as above, but add traps cumulatively, to check precedence
356 ordered_errors = [e for e in OrderedSignals if e in theirexceptions]
357 for error in ordered_errors:
358 self.context.traps[error] = 1
359 try:
360 funct(*vals)
361 except error:
362 pass
363 except Signals, e:
364 self.fail("Raised %s in %s; expected %s" %
365 (type(e), s, error))
366 else:
367 self.fail("Did not raise %s in %s" % (error, s))
368 # reset traps
369 for error in ordered_errors:
370 self.context.traps[error] = 0
371
372
Facundo Batista353750c2007-09-13 18:13:15 +0000373 if DEBUG:
374 print "--", self.context
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000375 try:
376 result = str(funct(*vals))
Facundo Batista1a191df2007-10-02 17:01:24 +0000377 if fname in LOGICAL_FUNCTIONS:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000378 result = str(int(eval(result))) # 'True', 'False' -> '1', '0'
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000379 except Signals, error:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000380 self.fail("Raised %s in %s" % (error, s))
381 except: #Catch any error long enough to state the test case.
382 print "ERROR:", s
383 raise
384
385 myexceptions = self.getexceptions()
Raymond Hettingerbf440692004-07-10 14:14:37 +0000386 self.context.clear_flags()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000387
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000388 self.assertEqual(result, ans,
389 'Incorrect answer for ' + s + ' -- got ' + result)
Florent Xicluna8f43cec2010-03-21 10:51:40 +0000390 self.assertItemsEqual(myexceptions, theirexceptions,
Facundo Batista353750c2007-09-13 18:13:15 +0000391 'Incorrect flags set in ' + s + ' -- got ' + str(myexceptions))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000392
393 def getexceptions(self):
Raymond Hettingerf63ba432004-08-17 05:42:09 +0000394 return [e for e in Signals if self.context.flags[e]]
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000395
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000396 def change_precision(self, prec):
397 self.context.prec = prec
398 def change_rounding_method(self, rounding):
399 self.context.rounding = rounding
400 def change_min_exponent(self, exp):
401 self.context.Emin = exp
402 def change_max_exponent(self, exp):
403 self.context.Emax = exp
404 def change_clamp(self, clamp):
405 self.context._clamp = clamp
406
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000407
408
409# The following classes test the behaviour of Decimal according to PEP 327
410
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000411class DecimalExplicitConstructionTest(unittest.TestCase):
412 '''Unit tests for Explicit Construction cases of Decimal.'''
413
414 def test_explicit_empty(self):
415 self.assertEqual(Decimal(), Decimal("0"))
416
417 def test_explicit_from_None(self):
418 self.assertRaises(TypeError, Decimal, None)
419
420 def test_explicit_from_int(self):
421
422 #positive
423 d = Decimal(45)
424 self.assertEqual(str(d), '45')
425
426 #very large positive
427 d = Decimal(500000123)
428 self.assertEqual(str(d), '500000123')
429
430 #negative
431 d = Decimal(-45)
432 self.assertEqual(str(d), '-45')
433
434 #zero
435 d = Decimal(0)
436 self.assertEqual(str(d), '0')
437
438 def test_explicit_from_string(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000439
440 #empty
441 self.assertEqual(str(Decimal('')), 'NaN')
442
443 #int
444 self.assertEqual(str(Decimal('45')), '45')
445
446 #float
447 self.assertEqual(str(Decimal('45.34')), '45.34')
448
449 #engineer notation
450 self.assertEqual(str(Decimal('45e2')), '4.5E+3')
451
452 #just not a number
453 self.assertEqual(str(Decimal('ugly')), 'NaN')
454
Mark Dickinson59bc20b2008-01-12 01:56:00 +0000455 #leading and trailing whitespace permitted
456 self.assertEqual(str(Decimal('1.3E4 \n')), '1.3E+4')
457 self.assertEqual(str(Decimal(' -7.89')), '-7.89')
458
Mark Dickinson8e85ffa2008-03-25 18:47:59 +0000459 #unicode strings should be permitted
460 self.assertEqual(str(Decimal(u'0E-017')), '0E-17')
461 self.assertEqual(str(Decimal(u'45')), '45')
462 self.assertEqual(str(Decimal(u'-Inf')), '-Infinity')
463 self.assertEqual(str(Decimal(u'NaN123')), 'NaN123')
464
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000465 def test_explicit_from_tuples(self):
466
467 #zero
468 d = Decimal( (0, (0,), 0) )
469 self.assertEqual(str(d), '0')
470
471 #int
472 d = Decimal( (1, (4, 5), 0) )
473 self.assertEqual(str(d), '-45')
474
475 #float
476 d = Decimal( (0, (4, 5, 3, 4), -2) )
477 self.assertEqual(str(d), '45.34')
478
479 #weird
480 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
481 self.assertEqual(str(d), '-4.34913534E-17')
482
483 #wrong number of items
484 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1)) )
485
486 #bad sign
487 self.assertRaises(ValueError, Decimal, (8, (4, 3, 4, 9, 1), 2) )
Facundo Batista9b5e2312007-10-19 19:25:57 +0000488 self.assertRaises(ValueError, Decimal, (0., (4, 3, 4, 9, 1), 2) )
489 self.assertRaises(ValueError, Decimal, (Decimal(1), (4, 3, 4, 9, 1), 2))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000490
491 #bad exp
492 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 'wrong!') )
Facundo Batista9b5e2312007-10-19 19:25:57 +0000493 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 0.) )
494 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), '1') )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000495
496 #bad coefficients
497 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, None, 1), 2) )
498 self.assertRaises(ValueError, Decimal, (1, (4, -3, 4, 9, 1), 2) )
Facundo Batista9b5e2312007-10-19 19:25:57 +0000499 self.assertRaises(ValueError, Decimal, (1, (4, 10, 4, 9, 1), 2) )
Facundo Batista72bc54f2007-11-23 17:59:00 +0000500 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 'a', 1), 2) )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000501
Antoine Pitrou6032c252010-03-30 18:49:45 +0000502 def test_explicit_from_bool(self):
503 self.assertIs(bool(Decimal(0)), False)
504 self.assertIs(bool(Decimal(1)), True)
505 self.assertEqual(Decimal(False), Decimal(0))
506 self.assertEqual(Decimal(True), Decimal(1))
507
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000508 def test_explicit_from_Decimal(self):
509
510 #positive
511 d = Decimal(45)
512 e = Decimal(d)
513 self.assertEqual(str(e), '45')
514 self.assertNotEqual(id(d), id(e))
515
516 #very large positive
517 d = Decimal(500000123)
518 e = Decimal(d)
519 self.assertEqual(str(e), '500000123')
520 self.assertNotEqual(id(d), id(e))
521
522 #negative
523 d = Decimal(-45)
524 e = Decimal(d)
525 self.assertEqual(str(e), '-45')
526 self.assertNotEqual(id(d), id(e))
527
528 #zero
529 d = Decimal(0)
530 e = Decimal(d)
531 self.assertEqual(str(e), '0')
532 self.assertNotEqual(id(d), id(e))
533
Raymond Hettingered171ab2010-04-02 18:39:24 +0000534 @requires_IEEE_754
535 def test_explicit_from_float(self):
536 r = Decimal(0.1)
537 self.assertEqual(type(r), Decimal)
538 self.assertEqual(str(r),
539 '0.1000000000000000055511151231257827021181583404541015625')
540 self.assertTrue(Decimal(float('nan')).is_qnan())
541 self.assertTrue(Decimal(float('inf')).is_infinite())
542 self.assertTrue(Decimal(float('-inf')).is_infinite())
543 self.assertEqual(str(Decimal(float('nan'))),
544 str(Decimal('NaN')))
545 self.assertEqual(str(Decimal(float('inf'))),
546 str(Decimal('Infinity')))
547 self.assertEqual(str(Decimal(float('-inf'))),
548 str(Decimal('-Infinity')))
549 self.assertEqual(str(Decimal(float('-0.0'))),
550 str(Decimal('-0')))
551 for i in range(200):
552 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
553 self.assertEqual(x, float(Decimal(x))) # roundtrip
554
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000555 def test_explicit_context_create_decimal(self):
556
557 nc = copy.copy(getcontext())
558 nc.prec = 3
559
560 # empty
Raymond Hettingerfed52962004-07-14 15:41:57 +0000561 d = Decimal()
562 self.assertEqual(str(d), '0')
563 d = nc.create_decimal()
564 self.assertEqual(str(d), '0')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000565
566 # from None
567 self.assertRaises(TypeError, nc.create_decimal, None)
568
569 # from int
570 d = nc.create_decimal(456)
Ezio Melottib0f5adc2010-01-24 16:58:36 +0000571 self.assertIsInstance(d, Decimal)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000572 self.assertEqual(nc.create_decimal(45678),
573 nc.create_decimal('457E+2'))
574
575 # from string
576 d = Decimal('456789')
577 self.assertEqual(str(d), '456789')
578 d = nc.create_decimal('456789')
579 self.assertEqual(str(d), '4.57E+5')
Mark Dickinson59bc20b2008-01-12 01:56:00 +0000580 # leading and trailing whitespace should result in a NaN;
581 # spaces are already checked in Cowlishaw's test-suite, so
582 # here we just check that a trailing newline results in a NaN
583 self.assertEqual(str(nc.create_decimal('3.14\n')), 'NaN')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000584
585 # from tuples
586 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
587 self.assertEqual(str(d), '-4.34913534E-17')
588 d = nc.create_decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
589 self.assertEqual(str(d), '-4.35E-17')
590
591 # from Decimal
592 prevdec = Decimal(500000123)
593 d = Decimal(prevdec)
594 self.assertEqual(str(d), '500000123')
595 d = nc.create_decimal(prevdec)
596 self.assertEqual(str(d), '5.00E+8')
597
Mark Dickinson4326ad82009-08-02 10:59:36 +0000598 def test_unicode_digits(self):
599 test_values = {
600 u'\uff11': '1',
601 u'\u0660.\u0660\u0663\u0667\u0662e-\u0663' : '0.0000372',
602 u'-nan\u0c68\u0c6a\u0c66\u0c66' : '-NaN2400',
603 }
604 for input, expected in test_values.items():
605 self.assertEqual(str(Decimal(input)), expected)
606
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000607
608class DecimalImplicitConstructionTest(unittest.TestCase):
609 '''Unit tests for Implicit Construction cases of Decimal.'''
610
611 def test_implicit_from_None(self):
612 self.assertRaises(TypeError, eval, 'Decimal(5) + None', globals())
613
614 def test_implicit_from_int(self):
615 #normal
616 self.assertEqual(str(Decimal(5) + 45), '50')
617 #exceeding precision
618 self.assertEqual(Decimal(5) + 123456789000, Decimal(123456789000))
619
620 def test_implicit_from_string(self):
621 self.assertRaises(TypeError, eval, 'Decimal(5) + "3"', globals())
622
623 def test_implicit_from_float(self):
624 self.assertRaises(TypeError, eval, 'Decimal(5) + 2.2', globals())
625
626 def test_implicit_from_Decimal(self):
627 self.assertEqual(Decimal(5) + Decimal(45), Decimal(50))
628
Raymond Hettinger267b8682005-03-27 10:47:39 +0000629 def test_rop(self):
630 # Allow other classes to be trained to interact with Decimals
631 class E:
632 def __divmod__(self, other):
633 return 'divmod ' + str(other)
634 def __rdivmod__(self, other):
635 return str(other) + ' rdivmod'
636 def __lt__(self, other):
637 return 'lt ' + str(other)
638 def __gt__(self, other):
639 return 'gt ' + str(other)
640 def __le__(self, other):
641 return 'le ' + str(other)
642 def __ge__(self, other):
643 return 'ge ' + str(other)
644 def __eq__(self, other):
645 return 'eq ' + str(other)
646 def __ne__(self, other):
647 return 'ne ' + str(other)
648
649 self.assertEqual(divmod(E(), Decimal(10)), 'divmod 10')
650 self.assertEqual(divmod(Decimal(10), E()), '10 rdivmod')
651 self.assertEqual(eval('Decimal(10) < E()'), 'gt 10')
652 self.assertEqual(eval('Decimal(10) > E()'), 'lt 10')
653 self.assertEqual(eval('Decimal(10) <= E()'), 'ge 10')
654 self.assertEqual(eval('Decimal(10) >= E()'), 'le 10')
655 self.assertEqual(eval('Decimal(10) == E()'), 'eq 10')
656 self.assertEqual(eval('Decimal(10) != E()'), 'ne 10')
657
658 # insert operator methods and then exercise them
Georg Brandl96c3f7f2006-03-28 08:06:35 +0000659 oplist = [
660 ('+', '__add__', '__radd__'),
661 ('-', '__sub__', '__rsub__'),
662 ('*', '__mul__', '__rmul__'),
663 ('%', '__mod__', '__rmod__'),
664 ('//', '__floordiv__', '__rfloordiv__'),
665 ('**', '__pow__', '__rpow__')
666 ]
Florent Xicluna8f43cec2010-03-21 10:51:40 +0000667 with check_py3k_warnings():
668 if 1 / 2 == 0:
669 # testing with classic division, so add __div__
670 oplist.append(('/', '__div__', '__rdiv__'))
671 else:
672 # testing with -Qnew, so add __truediv__
673 oplist.append(('/', '__truediv__', '__rtruediv__'))
Anthony Baxter4ef3a232006-03-30 12:59:11 +0000674
Georg Brandl96c3f7f2006-03-28 08:06:35 +0000675 for sym, lop, rop in oplist:
Raymond Hettinger267b8682005-03-27 10:47:39 +0000676 setattr(E, lop, lambda self, other: 'str' + lop + str(other))
677 setattr(E, rop, lambda self, other: str(other) + rop + 'str')
678 self.assertEqual(eval('E()' + sym + 'Decimal(10)'),
679 'str' + lop + '10')
680 self.assertEqual(eval('Decimal(10)' + sym + 'E()'),
681 '10' + rop + 'str')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000682
Mark Dickinson277859d2009-03-17 23:03:46 +0000683
Mark Dickinson1ddf1d82008-02-29 02:16:37 +0000684class DecimalFormatTest(unittest.TestCase):
685 '''Unit tests for the format function.'''
686 def test_formatting(self):
687 # triples giving a format, a Decimal, and the expected result
688 test_values = [
689 ('e', '0E-15', '0e-15'),
690 ('e', '2.3E-15', '2.3e-15'),
691 ('e', '2.30E+2', '2.30e+2'), # preserve significant zeros
692 ('e', '2.30000E-15', '2.30000e-15'),
693 ('e', '1.23456789123456789e40', '1.23456789123456789e+40'),
694 ('e', '1.5', '1.5e+0'),
695 ('e', '0.15', '1.5e-1'),
696 ('e', '0.015', '1.5e-2'),
697 ('e', '0.0000000000015', '1.5e-12'),
698 ('e', '15.0', '1.50e+1'),
699 ('e', '-15', '-1.5e+1'),
700 ('e', '0', '0e+0'),
701 ('e', '0E1', '0e+1'),
702 ('e', '0.0', '0e-1'),
703 ('e', '0.00', '0e-2'),
704 ('.6e', '0E-15', '0.000000e-9'),
705 ('.6e', '0', '0.000000e+6'),
706 ('.6e', '9.999999', '9.999999e+0'),
707 ('.6e', '9.9999999', '1.000000e+1'),
708 ('.6e', '-1.23e5', '-1.230000e+5'),
709 ('.6e', '1.23456789e-3', '1.234568e-3'),
710 ('f', '0', '0'),
711 ('f', '0.0', '0.0'),
712 ('f', '0E-2', '0.00'),
713 ('f', '0.00E-8', '0.0000000000'),
714 ('f', '0E1', '0'), # loses exponent information
715 ('f', '3.2E1', '32'),
716 ('f', '3.2E2', '320'),
717 ('f', '3.20E2', '320'),
718 ('f', '3.200E2', '320.0'),
719 ('f', '3.2E-6', '0.0000032'),
720 ('.6f', '0E-15', '0.000000'), # all zeros treated equally
721 ('.6f', '0E1', '0.000000'),
722 ('.6f', '0', '0.000000'),
723 ('.0f', '0', '0'), # no decimal point
724 ('.0f', '0e-2', '0'),
725 ('.0f', '3.14159265', '3'),
726 ('.1f', '3.14159265', '3.1'),
727 ('.4f', '3.14159265', '3.1416'),
728 ('.6f', '3.14159265', '3.141593'),
729 ('.7f', '3.14159265', '3.1415926'), # round-half-even!
730 ('.8f', '3.14159265', '3.14159265'),
731 ('.9f', '3.14159265', '3.141592650'),
732
733 ('g', '0', '0'),
734 ('g', '0.0', '0.0'),
735 ('g', '0E1', '0e+1'),
736 ('G', '0E1', '0E+1'),
737 ('g', '0E-5', '0.00000'),
738 ('g', '0E-6', '0.000000'),
739 ('g', '0E-7', '0e-7'),
740 ('g', '-0E2', '-0e+2'),
741 ('.0g', '3.14159265', '3'), # 0 sig fig -> 1 sig fig
742 ('.1g', '3.14159265', '3'),
743 ('.2g', '3.14159265', '3.1'),
744 ('.5g', '3.14159265', '3.1416'),
745 ('.7g', '3.14159265', '3.141593'),
746 ('.8g', '3.14159265', '3.1415926'), # round-half-even!
747 ('.9g', '3.14159265', '3.14159265'),
748 ('.10g', '3.14159265', '3.14159265'), # don't pad
749
750 ('%', '0E1', '0%'),
751 ('%', '0E0', '0%'),
752 ('%', '0E-1', '0%'),
753 ('%', '0E-2', '0%'),
754 ('%', '0E-3', '0.0%'),
755 ('%', '0E-4', '0.00%'),
756
757 ('.3%', '0', '0.000%'), # all zeros treated equally
758 ('.3%', '0E10', '0.000%'),
759 ('.3%', '0E-10', '0.000%'),
760 ('.3%', '2.34', '234.000%'),
761 ('.3%', '1.234567', '123.457%'),
762 ('.0%', '1.23', '123%'),
763
764 ('e', 'NaN', 'NaN'),
765 ('f', '-NaN123', '-NaN123'),
766 ('+g', 'NaN456', '+NaN456'),
767 ('.3e', 'Inf', 'Infinity'),
768 ('.16f', '-Inf', '-Infinity'),
769 ('.0g', '-sNaN', '-sNaN'),
770
771 ('', '1.00', '1.00'),
Mark Dickinsonb065e522009-03-17 18:01:03 +0000772
Mark Dickinson277859d2009-03-17 23:03:46 +0000773 # test alignment and padding
Mark Dickinson5cfa8042009-09-08 20:20:19 +0000774 ('6', '123', ' 123'),
Mark Dickinsonb065e522009-03-17 18:01:03 +0000775 ('<6', '123', '123 '),
776 ('>6', '123', ' 123'),
777 ('^6', '123', ' 123 '),
778 ('=+6', '123', '+ 123'),
Mark Dickinson277859d2009-03-17 23:03:46 +0000779 ('#<10', 'NaN', 'NaN#######'),
780 ('#<10', '-4.3', '-4.3######'),
781 ('#<+10', '0.0130', '+0.0130###'),
782 ('#< 10', '0.0130', ' 0.0130###'),
783 ('@>10', '-Inf', '@-Infinity'),
784 ('#>5', '-Inf', '-Infinity'),
785 ('?^5', '123', '?123?'),
786 ('%^6', '123', '%123%%'),
787 (' ^6', '-45.6', '-45.6 '),
788 ('/=10', '-45.6', '-/////45.6'),
789 ('/=+10', '45.6', '+/////45.6'),
790 ('/= 10', '45.6', ' /////45.6'),
791
792 # thousands separator
793 (',', '1234567', '1,234,567'),
794 (',', '123456', '123,456'),
795 (',', '12345', '12,345'),
796 (',', '1234', '1,234'),
797 (',', '123', '123'),
798 (',', '12', '12'),
799 (',', '1', '1'),
800 (',', '0', '0'),
801 (',', '-1234567', '-1,234,567'),
802 (',', '-123456', '-123,456'),
803 ('7,', '123456', '123,456'),
Mark Dickinson5cfa8042009-09-08 20:20:19 +0000804 ('8,', '123456', ' 123,456'),
Mark Dickinson277859d2009-03-17 23:03:46 +0000805 ('08,', '123456', '0,123,456'), # special case: extra 0 needed
806 ('+08,', '123456', '+123,456'), # but not if there's a sign
807 (' 08,', '123456', ' 123,456'),
808 ('08,', '-123456', '-123,456'),
809 ('+09,', '123456', '+0,123,456'),
810 # ... with fractional part...
811 ('07,', '1234.56', '1,234.56'),
812 ('08,', '1234.56', '1,234.56'),
813 ('09,', '1234.56', '01,234.56'),
814 ('010,', '1234.56', '001,234.56'),
815 ('011,', '1234.56', '0,001,234.56'),
816 ('012,', '1234.56', '0,001,234.56'),
817 ('08,.1f', '1234.5', '01,234.5'),
818 # no thousands separators in fraction part
819 (',', '1.23456789', '1.23456789'),
820 (',%', '123.456789', '12,345.6789%'),
821 (',e', '123456', '1.23456e+5'),
822 (',E', '123456', '1.23456E+5'),
Mark Dickinson491ea552009-09-07 16:17:41 +0000823
824 # issue 6850
825 ('a=-7.0', '0.12345', 'aaaa0.1'),
Stefan Krahce2ec492014-08-26 20:49:57 +0200826
827 # issue 22090
828 ('<^+15.20%', 'inf', '<<+Infinity%<<<'),
829 ('\x07>,%', 'sNaN1234567', 'sNaN1234567%'),
830 ('=10.10%', 'NaN123', ' NaN123%'),
Mark Dickinson1ddf1d82008-02-29 02:16:37 +0000831 ]
832 for fmt, d, result in test_values:
833 self.assertEqual(format(Decimal(d), fmt), result)
834
Mark Dickinson277859d2009-03-17 23:03:46 +0000835 def test_n_format(self):
836 try:
837 from locale import CHAR_MAX
838 except ImportError:
Zachary Ware1f702212013-12-10 14:09:20 -0600839 self.skipTest('locale.CHAR_MAX not available')
Mark Dickinson277859d2009-03-17 23:03:46 +0000840
841 # Set up some localeconv-like dictionaries
842 en_US = {
843 'decimal_point' : '.',
844 'grouping' : [3, 3, 0],
845 'thousands_sep': ','
846 }
847
848 fr_FR = {
849 'decimal_point' : ',',
850 'grouping' : [CHAR_MAX],
851 'thousands_sep' : ''
852 }
853
854 ru_RU = {
855 'decimal_point' : ',',
856 'grouping' : [3, 3, 0],
857 'thousands_sep' : ' '
858 }
859
860 crazy = {
861 'decimal_point' : '&',
862 'grouping' : [1, 4, 2, CHAR_MAX],
863 'thousands_sep' : '-'
864 }
865
866
867 def get_fmt(x, locale, fmt='n'):
868 return Decimal.__format__(Decimal(x), fmt, _localeconv=locale)
869
870 self.assertEqual(get_fmt(Decimal('12.7'), en_US), '12.7')
871 self.assertEqual(get_fmt(Decimal('12.7'), fr_FR), '12,7')
872 self.assertEqual(get_fmt(Decimal('12.7'), ru_RU), '12,7')
873 self.assertEqual(get_fmt(Decimal('12.7'), crazy), '1-2&7')
874
875 self.assertEqual(get_fmt(123456789, en_US), '123,456,789')
876 self.assertEqual(get_fmt(123456789, fr_FR), '123456789')
877 self.assertEqual(get_fmt(123456789, ru_RU), '123 456 789')
878 self.assertEqual(get_fmt(1234567890123, crazy), '123456-78-9012-3')
879
880 self.assertEqual(get_fmt(123456789, en_US, '.6n'), '1.23457e+8')
881 self.assertEqual(get_fmt(123456789, fr_FR, '.6n'), '1,23457e+8')
882 self.assertEqual(get_fmt(123456789, ru_RU, '.6n'), '1,23457e+8')
883 self.assertEqual(get_fmt(123456789, crazy, '.6n'), '1&23457e+8')
884
Mark Dickinsonb14514a2009-03-18 08:22:51 +0000885 # zero padding
886 self.assertEqual(get_fmt(1234, fr_FR, '03n'), '1234')
887 self.assertEqual(get_fmt(1234, fr_FR, '04n'), '1234')
888 self.assertEqual(get_fmt(1234, fr_FR, '05n'), '01234')
889 self.assertEqual(get_fmt(1234, fr_FR, '06n'), '001234')
890
891 self.assertEqual(get_fmt(12345, en_US, '05n'), '12,345')
892 self.assertEqual(get_fmt(12345, en_US, '06n'), '12,345')
893 self.assertEqual(get_fmt(12345, en_US, '07n'), '012,345')
894 self.assertEqual(get_fmt(12345, en_US, '08n'), '0,012,345')
895 self.assertEqual(get_fmt(12345, en_US, '09n'), '0,012,345')
896 self.assertEqual(get_fmt(12345, en_US, '010n'), '00,012,345')
897
898 self.assertEqual(get_fmt(123456, crazy, '06n'), '1-2345-6')
899 self.assertEqual(get_fmt(123456, crazy, '07n'), '1-2345-6')
900 self.assertEqual(get_fmt(123456, crazy, '08n'), '1-2345-6')
901 self.assertEqual(get_fmt(123456, crazy, '09n'), '01-2345-6')
902 self.assertEqual(get_fmt(123456, crazy, '010n'), '0-01-2345-6')
903 self.assertEqual(get_fmt(123456, crazy, '011n'), '0-01-2345-6')
904 self.assertEqual(get_fmt(123456, crazy, '012n'), '00-01-2345-6')
905 self.assertEqual(get_fmt(123456, crazy, '013n'), '000-01-2345-6')
906
Mark Dickinson277859d2009-03-17 23:03:46 +0000907
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000908class DecimalArithmeticOperatorsTest(unittest.TestCase):
909 '''Unit tests for all arithmetic operators, binary and unary.'''
910
911 def test_addition(self):
912
913 d1 = Decimal('-11.1')
914 d2 = Decimal('22.2')
915
916 #two Decimals
917 self.assertEqual(d1+d2, Decimal('11.1'))
918 self.assertEqual(d2+d1, Decimal('11.1'))
919
920 #with other type, left
921 c = d1 + 5
922 self.assertEqual(c, Decimal('-6.1'))
923 self.assertEqual(type(c), type(d1))
924
925 #with other type, right
926 c = 5 + d1
927 self.assertEqual(c, Decimal('-6.1'))
928 self.assertEqual(type(c), type(d1))
929
930 #inline with decimal
931 d1 += d2
932 self.assertEqual(d1, Decimal('11.1'))
933
934 #inline with other type
935 d1 += 5
936 self.assertEqual(d1, Decimal('16.1'))
937
938 def test_subtraction(self):
939
940 d1 = Decimal('-11.1')
941 d2 = Decimal('22.2')
942
943 #two Decimals
944 self.assertEqual(d1-d2, Decimal('-33.3'))
945 self.assertEqual(d2-d1, Decimal('33.3'))
946
947 #with other type, left
948 c = d1 - 5
949 self.assertEqual(c, Decimal('-16.1'))
950 self.assertEqual(type(c), type(d1))
951
952 #with other type, right
953 c = 5 - d1
954 self.assertEqual(c, Decimal('16.1'))
955 self.assertEqual(type(c), type(d1))
956
957 #inline with decimal
958 d1 -= d2
959 self.assertEqual(d1, Decimal('-33.3'))
960
961 #inline with other type
962 d1 -= 5
963 self.assertEqual(d1, Decimal('-38.3'))
964
965 def test_multiplication(self):
966
967 d1 = Decimal('-5')
968 d2 = Decimal('3')
969
970 #two Decimals
971 self.assertEqual(d1*d2, Decimal('-15'))
972 self.assertEqual(d2*d1, Decimal('-15'))
973
974 #with other type, left
975 c = d1 * 5
976 self.assertEqual(c, Decimal('-25'))
977 self.assertEqual(type(c), type(d1))
978
979 #with other type, right
980 c = 5 * d1
981 self.assertEqual(c, Decimal('-25'))
982 self.assertEqual(type(c), type(d1))
983
984 #inline with decimal
985 d1 *= d2
986 self.assertEqual(d1, Decimal('-15'))
987
988 #inline with other type
989 d1 *= 5
990 self.assertEqual(d1, Decimal('-75'))
991
992 def test_division(self):
993
994 d1 = Decimal('-5')
995 d2 = Decimal('2')
996
997 #two Decimals
998 self.assertEqual(d1/d2, Decimal('-2.5'))
999 self.assertEqual(d2/d1, Decimal('-0.4'))
1000
1001 #with other type, left
1002 c = d1 / 4
1003 self.assertEqual(c, Decimal('-1.25'))
1004 self.assertEqual(type(c), type(d1))
1005
1006 #with other type, right
1007 c = 4 / d1
1008 self.assertEqual(c, Decimal('-0.8'))
1009 self.assertEqual(type(c), type(d1))
1010
1011 #inline with decimal
1012 d1 /= d2
1013 self.assertEqual(d1, Decimal('-2.5'))
1014
1015 #inline with other type
1016 d1 /= 4
1017 self.assertEqual(d1, Decimal('-0.625'))
1018
1019 def test_floor_division(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001020
1021 d1 = Decimal('5')
1022 d2 = Decimal('2')
1023
1024 #two Decimals
1025 self.assertEqual(d1//d2, Decimal('2'))
1026 self.assertEqual(d2//d1, Decimal('0'))
1027
1028 #with other type, left
1029 c = d1 // 4
1030 self.assertEqual(c, Decimal('1'))
1031 self.assertEqual(type(c), type(d1))
1032
1033 #with other type, right
1034 c = 7 // d1
1035 self.assertEqual(c, Decimal('1'))
1036 self.assertEqual(type(c), type(d1))
1037
1038 #inline with decimal
1039 d1 //= d2
1040 self.assertEqual(d1, Decimal('2'))
1041
1042 #inline with other type
1043 d1 //= 2
1044 self.assertEqual(d1, Decimal('1'))
1045
1046 def test_powering(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001047
1048 d1 = Decimal('5')
1049 d2 = Decimal('2')
1050
1051 #two Decimals
1052 self.assertEqual(d1**d2, Decimal('25'))
1053 self.assertEqual(d2**d1, Decimal('32'))
1054
1055 #with other type, left
1056 c = d1 ** 4
1057 self.assertEqual(c, Decimal('625'))
1058 self.assertEqual(type(c), type(d1))
1059
1060 #with other type, right
1061 c = 7 ** d1
1062 self.assertEqual(c, Decimal('16807'))
1063 self.assertEqual(type(c), type(d1))
1064
1065 #inline with decimal
1066 d1 **= d2
1067 self.assertEqual(d1, Decimal('25'))
1068
1069 #inline with other type
1070 d1 **= 4
1071 self.assertEqual(d1, Decimal('390625'))
1072
1073 def test_module(self):
1074
1075 d1 = Decimal('5')
1076 d2 = Decimal('2')
1077
1078 #two Decimals
1079 self.assertEqual(d1%d2, Decimal('1'))
1080 self.assertEqual(d2%d1, Decimal('2'))
1081
1082 #with other type, left
1083 c = d1 % 4
1084 self.assertEqual(c, Decimal('1'))
1085 self.assertEqual(type(c), type(d1))
1086
1087 #with other type, right
1088 c = 7 % d1
1089 self.assertEqual(c, Decimal('2'))
1090 self.assertEqual(type(c), type(d1))
1091
1092 #inline with decimal
1093 d1 %= d2
1094 self.assertEqual(d1, Decimal('1'))
1095
1096 #inline with other type
1097 d1 %= 4
1098 self.assertEqual(d1, Decimal('1'))
1099
1100 def test_floor_div_module(self):
1101
1102 d1 = Decimal('5')
1103 d2 = Decimal('2')
1104
1105 #two Decimals
1106 (p, q) = divmod(d1, d2)
1107 self.assertEqual(p, Decimal('2'))
1108 self.assertEqual(q, Decimal('1'))
1109 self.assertEqual(type(p), type(d1))
1110 self.assertEqual(type(q), type(d1))
1111
1112 #with other type, left
1113 (p, q) = divmod(d1, 4)
1114 self.assertEqual(p, Decimal('1'))
1115 self.assertEqual(q, Decimal('1'))
1116 self.assertEqual(type(p), type(d1))
1117 self.assertEqual(type(q), type(d1))
1118
1119 #with other type, right
1120 (p, q) = divmod(7, d1)
1121 self.assertEqual(p, Decimal('1'))
1122 self.assertEqual(q, Decimal('2'))
1123 self.assertEqual(type(p), type(d1))
1124 self.assertEqual(type(q), type(d1))
1125
1126 def test_unary_operators(self):
1127 self.assertEqual(+Decimal(45), Decimal(+45)) # +
1128 self.assertEqual(-Decimal(45), Decimal(-45)) # -
1129 self.assertEqual(abs(Decimal(45)), abs(Decimal(-45))) # abs
1130
Mark Dickinson2fc92632008-02-06 22:10:50 +00001131 def test_nan_comparisons(self):
Mark Dickinsone096e822010-04-02 10:17:07 +00001132 # comparisons involving signaling nans signal InvalidOperation
1133
1134 # order comparisons (<, <=, >, >=) involving only quiet nans
1135 # also signal InvalidOperation
1136
1137 # equality comparisons (==, !=) involving only quiet nans
1138 # don't signal, but return False or True respectively.
1139
Mark Dickinson2fc92632008-02-06 22:10:50 +00001140 n = Decimal('NaN')
1141 s = Decimal('sNaN')
1142 i = Decimal('Inf')
1143 f = Decimal('2')
Mark Dickinsone096e822010-04-02 10:17:07 +00001144
1145 qnan_pairs = (n, n), (n, i), (i, n), (n, f), (f, n)
1146 snan_pairs = (s, n), (n, s), (s, i), (i, s), (s, f), (f, s), (s, s)
1147 order_ops = operator.lt, operator.le, operator.gt, operator.ge
1148 equality_ops = operator.eq, operator.ne
1149
1150 # results when InvalidOperation is not trapped
1151 for x, y in qnan_pairs + snan_pairs:
1152 for op in order_ops + equality_ops:
1153 got = op(x, y)
1154 expected = True if op is operator.ne else False
1155 self.assertIs(expected, got,
1156 "expected {0!r} for operator.{1}({2!r}, {3!r}); "
1157 "got {4!r}".format(
1158 expected, op.__name__, x, y, got))
1159
1160 # repeat the above, but this time trap the InvalidOperation
1161 with localcontext() as ctx:
1162 ctx.traps[InvalidOperation] = 1
1163
1164 for x, y in qnan_pairs:
1165 for op in equality_ops:
1166 got = op(x, y)
1167 expected = True if op is operator.ne else False
1168 self.assertIs(expected, got,
1169 "expected {0!r} for "
1170 "operator.{1}({2!r}, {3!r}); "
1171 "got {4!r}".format(
1172 expected, op.__name__, x, y, got))
1173
1174 for x, y in snan_pairs:
1175 for op in equality_ops:
1176 self.assertRaises(InvalidOperation, operator.eq, x, y)
1177 self.assertRaises(InvalidOperation, operator.ne, x, y)
1178
1179 for x, y in qnan_pairs + snan_pairs:
1180 for op in order_ops:
1181 self.assertRaises(InvalidOperation, op, x, y)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001182
Mark Dickinson6d8effb2010-02-18 14:27:02 +00001183 def test_copy_sign(self):
1184 d = Decimal(1).copy_sign(Decimal(-2))
1185
1186 self.assertEqual(Decimal(1).copy_sign(-2), d)
1187 self.assertRaises(TypeError, Decimal(1).copy_sign, '-2')
1188
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001189# The following are two functions used to test threading in the next class
1190
1191def thfunc1(cls):
1192 d1 = Decimal(1)
1193 d3 = Decimal(3)
Facundo Batista64156672008-03-22 02:45:37 +00001194 test1 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001195 cls.synchro.wait()
Facundo Batista64156672008-03-22 02:45:37 +00001196 test2 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001197 cls.finish1.set()
Facundo Batista64156672008-03-22 02:45:37 +00001198
Facundo Batistaee340e52008-05-02 17:39:00 +00001199 cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
1200 cls.assertEqual(test2, Decimal('0.3333333333333333333333333333'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001201
1202def thfunc2(cls):
1203 d1 = Decimal(1)
1204 d3 = Decimal(3)
Facundo Batista64156672008-03-22 02:45:37 +00001205 test1 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001206 thiscontext = getcontext()
1207 thiscontext.prec = 18
Facundo Batista64156672008-03-22 02:45:37 +00001208 test2 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001209 cls.synchro.set()
1210 cls.finish2.set()
Facundo Batista64156672008-03-22 02:45:37 +00001211
Facundo Batistaee340e52008-05-02 17:39:00 +00001212 cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
Facundo Batista64156672008-03-22 02:45:37 +00001213 cls.assertEqual(test2, Decimal('0.333333333333333333'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001214
1215
Zachary Ware1f702212013-12-10 14:09:20 -06001216@unittest.skipUnless(threading, 'threading required')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001217class DecimalUseOfContextTest(unittest.TestCase):
1218 '''Unit tests for Use of Context cases in Decimal.'''
1219
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001220 # Take care executing this test from IDLE, there's an issue in threading
1221 # that hangs IDLE and I couldn't find it
1222
1223 def test_threading(self):
1224 #Test the "threading isolation" of a Context.
1225
1226 self.synchro = threading.Event()
1227 self.finish1 = threading.Event()
1228 self.finish2 = threading.Event()
1229
1230 th1 = threading.Thread(target=thfunc1, args=(self,))
1231 th2 = threading.Thread(target=thfunc2, args=(self,))
1232
1233 th1.start()
1234 th2.start()
1235
1236 self.finish1.wait()
Thomas Woutersb3e6e8c2007-09-19 17:27:29 +00001237 self.finish2.wait()
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001238
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001239
1240class DecimalUsabilityTest(unittest.TestCase):
1241 '''Unit tests for Usability cases of Decimal.'''
1242
1243 def test_comparison_operators(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001244
1245 da = Decimal('23.42')
1246 db = Decimal('23.42')
1247 dc = Decimal('45')
1248
1249 #two Decimals
Ezio Melotti856a3be2010-04-03 14:51:00 +00001250 self.assertGreater(dc, da)
1251 self.assertGreaterEqual(dc, da)
1252 self.assertLess(da, dc)
1253 self.assertLessEqual(da, dc)
1254 self.assertEqual(da, db)
1255 self.assertNotEqual(da, dc)
1256 self.assertLessEqual(da, db)
1257 self.assertGreaterEqual(da, db)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001258 self.assertEqual(cmp(dc,da), 1)
1259 self.assertEqual(cmp(da,dc), -1)
1260 self.assertEqual(cmp(da,db), 0)
1261
1262 #a Decimal and an int
Ezio Melotti856a3be2010-04-03 14:51:00 +00001263 self.assertGreater(dc, 23)
1264 self.assertLess(23, dc)
1265 self.assertEqual(dc, 45)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001266 self.assertEqual(cmp(dc,23), 1)
1267 self.assertEqual(cmp(23,dc), -1)
1268 self.assertEqual(cmp(dc,45), 0)
1269
1270 #a Decimal and uncomparable
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001271 self.assertNotEqual(da, 'ugly')
1272 self.assertNotEqual(da, 32.7)
1273 self.assertNotEqual(da, object())
1274 self.assertNotEqual(da, object)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001275
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001276 # sortable
1277 a = map(Decimal, xrange(100))
1278 b = a[:]
1279 random.shuffle(a)
1280 a.sort()
1281 self.assertEqual(a, b)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001282
Facundo Batista353750c2007-09-13 18:13:15 +00001283 # with None
Florent Xicluna8f43cec2010-03-21 10:51:40 +00001284 with check_py3k_warnings():
1285 self.assertFalse(Decimal(1) < None)
1286 self.assertTrue(Decimal(1) > None)
Facundo Batista353750c2007-09-13 18:13:15 +00001287
Mark Dickinson99d80962010-04-02 08:53:22 +00001288 def test_decimal_float_comparison(self):
1289 da = Decimal('0.25')
1290 db = Decimal('3.0')
Ezio Melotti856a3be2010-04-03 14:51:00 +00001291 self.assertLess(da, 3.0)
1292 self.assertLessEqual(da, 3.0)
1293 self.assertGreater(db, 0.25)
1294 self.assertGreaterEqual(db, 0.25)
1295 self.assertNotEqual(da, 1.5)
1296 self.assertEqual(da, 0.25)
1297 self.assertGreater(3.0, da)
1298 self.assertGreaterEqual(3.0, da)
1299 self.assertLess(0.25, db)
1300 self.assertLessEqual(0.25, db)
1301 self.assertNotEqual(0.25, db)
1302 self.assertEqual(3.0, db)
1303 self.assertNotEqual(0.1, Decimal('0.1'))
Mark Dickinson99d80962010-04-02 08:53:22 +00001304
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001305 def test_copy_and_deepcopy_methods(self):
1306 d = Decimal('43.24')
1307 c = copy.copy(d)
1308 self.assertEqual(id(c), id(d))
1309 dc = copy.deepcopy(d)
1310 self.assertEqual(id(dc), id(d))
1311
1312 def test_hash_method(self):
1313 #just that it's hashable
1314 hash(Decimal(23))
Mark Dickinsonf3eeca12010-04-02 10:35:12 +00001315 hash(Decimal('Infinity'))
1316 hash(Decimal('-Infinity'))
1317 hash(Decimal('nan123'))
1318 hash(Decimal('-NaN'))
Facundo Batista8c202442007-09-19 17:53:25 +00001319
1320 test_values = [Decimal(sign*(2**m + n))
1321 for m in [0, 14, 15, 16, 17, 30, 31,
1322 32, 33, 62, 63, 64, 65, 66]
1323 for n in range(-10, 10)
1324 for sign in [-1, 1]]
1325 test_values.extend([
1326 Decimal("-0"), # zeros
1327 Decimal("0.00"),
1328 Decimal("-0.000"),
1329 Decimal("0E10"),
1330 Decimal("-0E12"),
1331 Decimal("10.0"), # negative exponent
1332 Decimal("-23.00000"),
1333 Decimal("1230E100"), # positive exponent
1334 Decimal("-4.5678E50"),
1335 # a value for which hash(n) != hash(n % (2**64-1))
1336 # in Python pre-2.6
1337 Decimal(2**64 + 2**32 - 1),
1338 # selection of values which fail with the old (before
1339 # version 2.6) long.__hash__
1340 Decimal("1.634E100"),
1341 Decimal("90.697E100"),
1342 Decimal("188.83E100"),
1343 Decimal("1652.9E100"),
1344 Decimal("56531E100"),
1345 ])
1346
1347 # check that hash(d) == hash(int(d)) for integral values
1348 for value in test_values:
1349 self.assertEqual(hash(value), hash(int(value)))
1350
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001351 #the same hash that to an int
1352 self.assertEqual(hash(Decimal(23)), hash(23))
Mark Dickinsonf3eeca12010-04-02 10:35:12 +00001353 self.assertRaises(TypeError, hash, Decimal('sNaN'))
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001354 self.assertTrue(hash(Decimal('Inf')))
1355 self.assertTrue(hash(Decimal('-Inf')))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001356
Mark Dickinson99d80962010-04-02 08:53:22 +00001357 # check that the hashes of a Decimal float match when they
1358 # represent exactly the same values
1359 test_strings = ['inf', '-Inf', '0.0', '-.0e1',
1360 '34.0', '2.5', '112390.625', '-0.515625']
1361 for s in test_strings:
1362 f = float(s)
1363 d = Decimal(s)
1364 self.assertEqual(hash(f), hash(d))
1365
Facundo Batista52b25792008-01-08 12:25:20 +00001366 # check that the value of the hash doesn't depend on the
1367 # current context (issue #1757)
1368 c = getcontext()
1369 old_precision = c.prec
1370 x = Decimal("123456789.1")
1371
1372 c.prec = 6
1373 h1 = hash(x)
1374 c.prec = 10
1375 h2 = hash(x)
1376 c.prec = 16
1377 h3 = hash(x)
1378
1379 self.assertEqual(h1, h2)
1380 self.assertEqual(h1, h3)
1381 c.prec = old_precision
1382
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001383 def test_min_and_max_methods(self):
1384
1385 d1 = Decimal('15.32')
1386 d2 = Decimal('28.5')
1387 l1 = 15
1388 l2 = 28
1389
1390 #between Decimals
Ezio Melotti856a3be2010-04-03 14:51:00 +00001391 self.assertIs(min(d1,d2), d1)
1392 self.assertIs(min(d2,d1), d1)
1393 self.assertIs(max(d1,d2), d2)
1394 self.assertIs(max(d2,d1), d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001395
1396 #between Decimal and long
Ezio Melotti856a3be2010-04-03 14:51:00 +00001397 self.assertIs(min(d1,l2), d1)
1398 self.assertIs(min(l2,d1), d1)
1399 self.assertIs(max(l1,d2), d2)
1400 self.assertIs(max(d2,l1), d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001401
1402 def test_as_nonzero(self):
1403 #as false
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001404 self.assertFalse(Decimal(0))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001405 #as true
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001406 self.assertTrue(Decimal('0.372'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001407
1408 def test_tostring_methods(self):
1409 #Test str and repr methods.
1410
1411 d = Decimal('15.32')
1412 self.assertEqual(str(d), '15.32') # str
Raymond Hettingerabe32372008-02-14 02:41:22 +00001413 self.assertEqual(repr(d), "Decimal('15.32')") # repr
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001414
Mark Dickinson8e85ffa2008-03-25 18:47:59 +00001415 # result type of string methods should be str, not unicode
1416 unicode_inputs = [u'123.4', u'0.5E2', u'Infinity', u'sNaN',
1417 u'-0.0E100', u'-NaN001', u'-Inf']
1418
1419 for u in unicode_inputs:
1420 d = Decimal(u)
1421 self.assertEqual(type(str(d)), str)
1422 self.assertEqual(type(repr(d)), str)
1423 self.assertEqual(type(d.to_eng_string()), str)
1424
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001425 def test_tonum_methods(self):
1426 #Test float, int and long methods.
1427
1428 d1 = Decimal('66')
1429 d2 = Decimal('15.32')
1430
1431 #int
1432 self.assertEqual(int(d1), 66)
1433 self.assertEqual(int(d2), 15)
1434
1435 #long
1436 self.assertEqual(long(d1), 66)
1437 self.assertEqual(long(d2), 15)
1438
1439 #float
1440 self.assertEqual(float(d1), 66)
1441 self.assertEqual(float(d2), 15.32)
1442
Mark Dickinson088cec32012-08-24 20:06:30 +01001443 def test_nan_to_float(self):
1444 # Test conversions of decimal NANs to float.
1445 # See http://bugs.python.org/issue15544
1446 for s in ('nan', 'nan1234', '-nan', '-nan2468'):
1447 f = float(Decimal(s))
1448 self.assertTrue(math.isnan(f))
Mark Dickinson088cec32012-08-24 20:06:30 +01001449
1450 def test_snan_to_float(self):
1451 for s in ('snan', '-snan', 'snan1357', '-snan1234'):
1452 d = Decimal(s)
1453 self.assertRaises(ValueError, float, d)
1454
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001455 def test_eval_round_trip(self):
1456
1457 #with zero
1458 d = Decimal( (0, (0,), 0) )
1459 self.assertEqual(d, eval(repr(d)))
1460
1461 #int
1462 d = Decimal( (1, (4, 5), 0) )
1463 self.assertEqual(d, eval(repr(d)))
1464
1465 #float
1466 d = Decimal( (0, (4, 5, 3, 4), -2) )
1467 self.assertEqual(d, eval(repr(d)))
1468
1469 #weird
1470 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1471 self.assertEqual(d, eval(repr(d)))
1472
1473 def test_as_tuple(self):
1474
1475 #with zero
1476 d = Decimal(0)
1477 self.assertEqual(d.as_tuple(), (0, (0,), 0) )
1478
1479 #int
1480 d = Decimal(-45)
1481 self.assertEqual(d.as_tuple(), (1, (4, 5), 0) )
1482
1483 #complicated string
1484 d = Decimal("-4.34913534E-17")
1485 self.assertEqual(d.as_tuple(), (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1486
1487 #inf
1488 d = Decimal("Infinity")
1489 self.assertEqual(d.as_tuple(), (0, (0,), 'F') )
1490
Facundo Batista9b5e2312007-10-19 19:25:57 +00001491 #leading zeros in coefficient should be stripped
1492 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), -2) )
1493 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), -2) )
1494 d = Decimal( (1, (0, 0, 0), 37) )
1495 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1496 d = Decimal( (1, (), 37) )
1497 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1498
1499 #leading zeros in NaN diagnostic info should be stripped
1500 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), 'n') )
1501 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), 'n') )
1502 d = Decimal( (1, (0, 0, 0), 'N') )
1503 self.assertEqual(d.as_tuple(), (1, (), 'N') )
1504 d = Decimal( (1, (), 'n') )
1505 self.assertEqual(d.as_tuple(), (1, (), 'n') )
1506
1507 #coefficient in infinity should be ignored
1508 d = Decimal( (0, (4, 5, 3, 4), 'F') )
1509 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
1510 d = Decimal( (1, (0, 2, 7, 1), 'F') )
1511 self.assertEqual(d.as_tuple(), (1, (0,), 'F'))
1512
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001513 def test_immutability_operations(self):
1514 # Do operations and check that it didn't change change internal objects.
1515
1516 d1 = Decimal('-25e55')
1517 b1 = Decimal('-25e55')
Facundo Batista353750c2007-09-13 18:13:15 +00001518 d2 = Decimal('33e+33')
1519 b2 = Decimal('33e+33')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001520
1521 def checkSameDec(operation, useOther=False):
1522 if useOther:
1523 eval("d1." + operation + "(d2)")
1524 self.assertEqual(d1._sign, b1._sign)
1525 self.assertEqual(d1._int, b1._int)
1526 self.assertEqual(d1._exp, b1._exp)
1527 self.assertEqual(d2._sign, b2._sign)
1528 self.assertEqual(d2._int, b2._int)
1529 self.assertEqual(d2._exp, b2._exp)
1530 else:
1531 eval("d1." + operation + "()")
1532 self.assertEqual(d1._sign, b1._sign)
1533 self.assertEqual(d1._int, b1._int)
1534 self.assertEqual(d1._exp, b1._exp)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001535
1536 Decimal(d1)
1537 self.assertEqual(d1._sign, b1._sign)
1538 self.assertEqual(d1._int, b1._int)
1539 self.assertEqual(d1._exp, b1._exp)
1540
1541 checkSameDec("__abs__")
1542 checkSameDec("__add__", True)
1543 checkSameDec("__div__", True)
1544 checkSameDec("__divmod__", True)
Mark Dickinson2fc92632008-02-06 22:10:50 +00001545 checkSameDec("__eq__", True)
1546 checkSameDec("__ne__", True)
1547 checkSameDec("__le__", True)
1548 checkSameDec("__lt__", True)
1549 checkSameDec("__ge__", True)
1550 checkSameDec("__gt__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001551 checkSameDec("__float__")
1552 checkSameDec("__floordiv__", True)
1553 checkSameDec("__hash__")
1554 checkSameDec("__int__")
Raymond Hettinger5a053642008-01-24 19:05:29 +00001555 checkSameDec("__trunc__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001556 checkSameDec("__long__")
1557 checkSameDec("__mod__", True)
1558 checkSameDec("__mul__", True)
1559 checkSameDec("__neg__")
1560 checkSameDec("__nonzero__")
1561 checkSameDec("__pos__")
1562 checkSameDec("__pow__", True)
1563 checkSameDec("__radd__", True)
1564 checkSameDec("__rdiv__", True)
1565 checkSameDec("__rdivmod__", True)
1566 checkSameDec("__repr__")
1567 checkSameDec("__rfloordiv__", True)
1568 checkSameDec("__rmod__", True)
1569 checkSameDec("__rmul__", True)
1570 checkSameDec("__rpow__", True)
1571 checkSameDec("__rsub__", True)
1572 checkSameDec("__str__")
1573 checkSameDec("__sub__", True)
1574 checkSameDec("__truediv__", True)
1575 checkSameDec("adjusted")
1576 checkSameDec("as_tuple")
1577 checkSameDec("compare", True)
1578 checkSameDec("max", True)
1579 checkSameDec("min", True)
1580 checkSameDec("normalize")
1581 checkSameDec("quantize", True)
1582 checkSameDec("remainder_near", True)
1583 checkSameDec("same_quantum", True)
1584 checkSameDec("sqrt")
1585 checkSameDec("to_eng_string")
1586 checkSameDec("to_integral")
1587
Facundo Batista6c398da2007-09-17 17:30:13 +00001588 def test_subclassing(self):
1589 # Different behaviours when subclassing Decimal
1590
1591 class MyDecimal(Decimal):
1592 pass
1593
1594 d1 = MyDecimal(1)
1595 d2 = MyDecimal(2)
1596 d = d1 + d2
Ezio Melotti856a3be2010-04-03 14:51:00 +00001597 self.assertIs(type(d), Decimal)
Facundo Batista6c398da2007-09-17 17:30:13 +00001598
1599 d = d1.max(d2)
Ezio Melotti856a3be2010-04-03 14:51:00 +00001600 self.assertIs(type(d), Decimal)
Facundo Batista6c398da2007-09-17 17:30:13 +00001601
Mark Dickinson3b24ccb2008-03-25 14:33:23 +00001602 def test_implicit_context(self):
1603 # Check results when context given implicitly. (Issue 2478)
1604 c = getcontext()
1605 self.assertEqual(str(Decimal(0).sqrt()),
1606 str(c.sqrt(Decimal(0))))
1607
Mark Dickinson0c673122009-10-29 12:04:00 +00001608 def test_conversions_from_int(self):
1609 # Check that methods taking a second Decimal argument will
1610 # always accept an integer in place of a Decimal.
1611 self.assertEqual(Decimal(4).compare(3),
1612 Decimal(4).compare(Decimal(3)))
1613 self.assertEqual(Decimal(4).compare_signal(3),
1614 Decimal(4).compare_signal(Decimal(3)))
1615 self.assertEqual(Decimal(4).compare_total(3),
1616 Decimal(4).compare_total(Decimal(3)))
1617 self.assertEqual(Decimal(4).compare_total_mag(3),
1618 Decimal(4).compare_total_mag(Decimal(3)))
1619 self.assertEqual(Decimal(10101).logical_and(1001),
1620 Decimal(10101).logical_and(Decimal(1001)))
1621 self.assertEqual(Decimal(10101).logical_or(1001),
1622 Decimal(10101).logical_or(Decimal(1001)))
1623 self.assertEqual(Decimal(10101).logical_xor(1001),
1624 Decimal(10101).logical_xor(Decimal(1001)))
1625 self.assertEqual(Decimal(567).max(123),
1626 Decimal(567).max(Decimal(123)))
1627 self.assertEqual(Decimal(567).max_mag(123),
1628 Decimal(567).max_mag(Decimal(123)))
1629 self.assertEqual(Decimal(567).min(123),
1630 Decimal(567).min(Decimal(123)))
1631 self.assertEqual(Decimal(567).min_mag(123),
1632 Decimal(567).min_mag(Decimal(123)))
1633 self.assertEqual(Decimal(567).next_toward(123),
1634 Decimal(567).next_toward(Decimal(123)))
1635 self.assertEqual(Decimal(1234).quantize(100),
1636 Decimal(1234).quantize(Decimal(100)))
1637 self.assertEqual(Decimal(768).remainder_near(1234),
1638 Decimal(768).remainder_near(Decimal(1234)))
1639 self.assertEqual(Decimal(123).rotate(1),
1640 Decimal(123).rotate(Decimal(1)))
1641 self.assertEqual(Decimal(1234).same_quantum(1000),
1642 Decimal(1234).same_quantum(Decimal(1000)))
1643 self.assertEqual(Decimal('9.123').scaleb(-100),
1644 Decimal('9.123').scaleb(Decimal(-100)))
1645 self.assertEqual(Decimal(456).shift(-1),
1646 Decimal(456).shift(Decimal(-1)))
1647
1648 self.assertEqual(Decimal(-12).fma(Decimal(45), 67),
1649 Decimal(-12).fma(Decimal(45), Decimal(67)))
1650 self.assertEqual(Decimal(-12).fma(45, 67),
1651 Decimal(-12).fma(Decimal(45), Decimal(67)))
1652 self.assertEqual(Decimal(-12).fma(45, Decimal(67)),
1653 Decimal(-12).fma(Decimal(45), Decimal(67)))
1654
Facundo Batista6c398da2007-09-17 17:30:13 +00001655
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001656class DecimalPythonAPItests(unittest.TestCase):
1657
Raymond Hettinger2c8585b2009-02-03 03:37:03 +00001658 def test_abc(self):
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001659 self.assertTrue(issubclass(Decimal, numbers.Number))
Ezio Melotti856a3be2010-04-03 14:51:00 +00001660 self.assertFalse(issubclass(Decimal, numbers.Real))
Ezio Melottib0f5adc2010-01-24 16:58:36 +00001661 self.assertIsInstance(Decimal(0), numbers.Number)
Ezio Melotti856a3be2010-04-03 14:51:00 +00001662 self.assertNotIsInstance(Decimal(0), numbers.Real)
Raymond Hettinger2c8585b2009-02-03 03:37:03 +00001663
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001664 def test_pickle(self):
1665 d = Decimal('-3.141590000')
1666 p = pickle.dumps(d)
1667 e = pickle.loads(p)
1668 self.assertEqual(d, e)
1669
Raymond Hettinger5548be22004-07-05 18:49:38 +00001670 def test_int(self):
Raymond Hettinger605ed022004-11-24 07:28:48 +00001671 for x in range(-250, 250):
1672 s = '%0.2f' % (x / 100.0)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001673 # should work the same as for floats
1674 self.assertEqual(int(Decimal(s)), int(float(s)))
Raymond Hettinger605ed022004-11-24 07:28:48 +00001675 # should work the same as to_integral in the ROUND_DOWN mode
Raymond Hettinger5548be22004-07-05 18:49:38 +00001676 d = Decimal(s)
Raymond Hettinger605ed022004-11-24 07:28:48 +00001677 r = d.to_integral(ROUND_DOWN)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001678 self.assertEqual(Decimal(int(d)), r)
1679
Mark Dickinson968f1692009-09-07 18:04:58 +00001680 self.assertRaises(ValueError, int, Decimal('-nan'))
1681 self.assertRaises(ValueError, int, Decimal('snan'))
1682 self.assertRaises(OverflowError, int, Decimal('inf'))
1683 self.assertRaises(OverflowError, int, Decimal('-inf'))
1684
1685 self.assertRaises(ValueError, long, Decimal('-nan'))
1686 self.assertRaises(ValueError, long, Decimal('snan'))
1687 self.assertRaises(OverflowError, long, Decimal('inf'))
1688 self.assertRaises(OverflowError, long, Decimal('-inf'))
1689
Raymond Hettinger5a053642008-01-24 19:05:29 +00001690 def test_trunc(self):
1691 for x in range(-250, 250):
1692 s = '%0.2f' % (x / 100.0)
1693 # should work the same as for floats
1694 self.assertEqual(int(Decimal(s)), int(float(s)))
1695 # should work the same as to_integral in the ROUND_DOWN mode
1696 d = Decimal(s)
1697 r = d.to_integral(ROUND_DOWN)
Jeffrey Yasskinca2b69f2008-02-01 06:22:46 +00001698 self.assertEqual(Decimal(math.trunc(d)), r)
Raymond Hettinger5a053642008-01-24 19:05:29 +00001699
Raymond Hettingerf4d85972009-01-03 19:02:23 +00001700 def test_from_float(self):
1701
1702 class MyDecimal(Decimal):
1703 pass
1704
1705 r = MyDecimal.from_float(0.1)
1706 self.assertEqual(type(r), MyDecimal)
1707 self.assertEqual(str(r),
1708 '0.1000000000000000055511151231257827021181583404541015625')
1709 bigint = 12345678901234567890123456789
1710 self.assertEqual(MyDecimal.from_float(bigint), MyDecimal(bigint))
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001711 self.assertTrue(MyDecimal.from_float(float('nan')).is_qnan())
1712 self.assertTrue(MyDecimal.from_float(float('inf')).is_infinite())
1713 self.assertTrue(MyDecimal.from_float(float('-inf')).is_infinite())
Raymond Hettingerf4d85972009-01-03 19:02:23 +00001714 self.assertEqual(str(MyDecimal.from_float(float('nan'))),
1715 str(Decimal('NaN')))
1716 self.assertEqual(str(MyDecimal.from_float(float('inf'))),
1717 str(Decimal('Infinity')))
1718 self.assertEqual(str(MyDecimal.from_float(float('-inf'))),
1719 str(Decimal('-Infinity')))
1720 self.assertRaises(TypeError, MyDecimal.from_float, 'abc')
1721 for i in range(200):
1722 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
1723 self.assertEqual(x, float(MyDecimal.from_float(x))) # roundtrip
1724
1725 def test_create_decimal_from_float(self):
1726 context = Context(prec=5, rounding=ROUND_DOWN)
1727 self.assertEqual(
1728 context.create_decimal_from_float(math.pi),
1729 Decimal('3.1415')
1730 )
1731 context = Context(prec=5, rounding=ROUND_UP)
1732 self.assertEqual(
1733 context.create_decimal_from_float(math.pi),
1734 Decimal('3.1416')
1735 )
1736 context = Context(prec=5, traps=[Inexact])
1737 self.assertRaises(
1738 Inexact,
1739 context.create_decimal_from_float,
1740 math.pi
1741 )
1742 self.assertEqual(repr(context.create_decimal_from_float(-0.0)),
1743 "Decimal('-0')")
1744 self.assertEqual(repr(context.create_decimal_from_float(1.0)),
1745 "Decimal('1')")
1746 self.assertEqual(repr(context.create_decimal_from_float(10)),
1747 "Decimal('10')")
1748
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00001749class ContextAPItests(unittest.TestCase):
1750
1751 def test_pickle(self):
1752 c = Context()
1753 e = pickle.loads(pickle.dumps(c))
1754 for k in vars(c):
1755 v1 = vars(c)[k]
1756 v2 = vars(e)[k]
1757 self.assertEqual(v1, v2)
1758
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001759 def test_equality_with_other_types(self):
Ezio Melottiaa980582010-01-23 23:04:36 +00001760 self.assertIn(Decimal(10), ['a', 1.0, Decimal(10), (1,2), {}])
1761 self.assertNotIn(Decimal(10), ['a', 1.0, (1,2), {}])
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001762
Raymond Hettinger955d2b22004-08-08 20:17:45 +00001763 def test_copy(self):
1764 # All copies should be deep
1765 c = Context()
1766 d = c.copy()
1767 self.assertNotEqual(id(c), id(d))
1768 self.assertNotEqual(id(c.flags), id(d.flags))
1769 self.assertNotEqual(id(c.traps), id(d.traps))
1770
Mark Dickinson6d8effb2010-02-18 14:27:02 +00001771 def test_abs(self):
1772 c = Context()
1773 d = c.abs(Decimal(-1))
1774 self.assertEqual(c.abs(-1), d)
1775 self.assertRaises(TypeError, c.abs, '-1')
1776
1777 def test_add(self):
1778 c = Context()
1779 d = c.add(Decimal(1), Decimal(1))
1780 self.assertEqual(c.add(1, 1), d)
1781 self.assertEqual(c.add(Decimal(1), 1), d)
1782 self.assertEqual(c.add(1, Decimal(1)), d)
1783 self.assertRaises(TypeError, c.add, '1', 1)
1784 self.assertRaises(TypeError, c.add, 1, '1')
1785
1786 def test_compare(self):
1787 c = Context()
1788 d = c.compare(Decimal(1), Decimal(1))
1789 self.assertEqual(c.compare(1, 1), d)
1790 self.assertEqual(c.compare(Decimal(1), 1), d)
1791 self.assertEqual(c.compare(1, Decimal(1)), d)
1792 self.assertRaises(TypeError, c.compare, '1', 1)
1793 self.assertRaises(TypeError, c.compare, 1, '1')
1794
1795 def test_compare_signal(self):
1796 c = Context()
1797 d = c.compare_signal(Decimal(1), Decimal(1))
1798 self.assertEqual(c.compare_signal(1, 1), d)
1799 self.assertEqual(c.compare_signal(Decimal(1), 1), d)
1800 self.assertEqual(c.compare_signal(1, Decimal(1)), d)
1801 self.assertRaises(TypeError, c.compare_signal, '1', 1)
1802 self.assertRaises(TypeError, c.compare_signal, 1, '1')
1803
1804 def test_compare_total(self):
1805 c = Context()
1806 d = c.compare_total(Decimal(1), Decimal(1))
1807 self.assertEqual(c.compare_total(1, 1), d)
1808 self.assertEqual(c.compare_total(Decimal(1), 1), d)
1809 self.assertEqual(c.compare_total(1, Decimal(1)), d)
1810 self.assertRaises(TypeError, c.compare_total, '1', 1)
1811 self.assertRaises(TypeError, c.compare_total, 1, '1')
1812
1813 def test_compare_total_mag(self):
1814 c = Context()
1815 d = c.compare_total_mag(Decimal(1), Decimal(1))
1816 self.assertEqual(c.compare_total_mag(1, 1), d)
1817 self.assertEqual(c.compare_total_mag(Decimal(1), 1), d)
1818 self.assertEqual(c.compare_total_mag(1, Decimal(1)), d)
1819 self.assertRaises(TypeError, c.compare_total_mag, '1', 1)
1820 self.assertRaises(TypeError, c.compare_total_mag, 1, '1')
1821
1822 def test_copy_abs(self):
1823 c = Context()
1824 d = c.copy_abs(Decimal(-1))
1825 self.assertEqual(c.copy_abs(-1), d)
1826 self.assertRaises(TypeError, c.copy_abs, '-1')
1827
1828 def test_copy_decimal(self):
1829 c = Context()
1830 d = c.copy_decimal(Decimal(-1))
1831 self.assertEqual(c.copy_decimal(-1), d)
1832 self.assertRaises(TypeError, c.copy_decimal, '-1')
1833
1834 def test_copy_negate(self):
1835 c = Context()
1836 d = c.copy_negate(Decimal(-1))
1837 self.assertEqual(c.copy_negate(-1), d)
1838 self.assertRaises(TypeError, c.copy_negate, '-1')
1839
1840 def test_copy_sign(self):
1841 c = Context()
1842 d = c.copy_sign(Decimal(1), Decimal(-2))
1843 self.assertEqual(c.copy_sign(1, -2), d)
1844 self.assertEqual(c.copy_sign(Decimal(1), -2), d)
1845 self.assertEqual(c.copy_sign(1, Decimal(-2)), d)
1846 self.assertRaises(TypeError, c.copy_sign, '1', -2)
1847 self.assertRaises(TypeError, c.copy_sign, 1, '-2')
1848
1849 def test_divide(self):
1850 c = Context()
1851 d = c.divide(Decimal(1), Decimal(2))
1852 self.assertEqual(c.divide(1, 2), d)
1853 self.assertEqual(c.divide(Decimal(1), 2), d)
1854 self.assertEqual(c.divide(1, Decimal(2)), d)
1855 self.assertRaises(TypeError, c.divide, '1', 2)
1856 self.assertRaises(TypeError, c.divide, 1, '2')
1857
1858 def test_divide_int(self):
1859 c = Context()
1860 d = c.divide_int(Decimal(1), Decimal(2))
1861 self.assertEqual(c.divide_int(1, 2), d)
1862 self.assertEqual(c.divide_int(Decimal(1), 2), d)
1863 self.assertEqual(c.divide_int(1, Decimal(2)), d)
1864 self.assertRaises(TypeError, c.divide_int, '1', 2)
1865 self.assertRaises(TypeError, c.divide_int, 1, '2')
1866
1867 def test_divmod(self):
1868 c = Context()
1869 d = c.divmod(Decimal(1), Decimal(2))
1870 self.assertEqual(c.divmod(1, 2), d)
1871 self.assertEqual(c.divmod(Decimal(1), 2), d)
1872 self.assertEqual(c.divmod(1, Decimal(2)), d)
1873 self.assertRaises(TypeError, c.divmod, '1', 2)
1874 self.assertRaises(TypeError, c.divmod, 1, '2')
1875
1876 def test_exp(self):
1877 c = Context()
1878 d = c.exp(Decimal(10))
1879 self.assertEqual(c.exp(10), d)
1880 self.assertRaises(TypeError, c.exp, '10')
1881
1882 def test_fma(self):
1883 c = Context()
1884 d = c.fma(Decimal(2), Decimal(3), Decimal(4))
1885 self.assertEqual(c.fma(2, 3, 4), d)
1886 self.assertEqual(c.fma(Decimal(2), 3, 4), d)
1887 self.assertEqual(c.fma(2, Decimal(3), 4), d)
1888 self.assertEqual(c.fma(2, 3, Decimal(4)), d)
1889 self.assertEqual(c.fma(Decimal(2), Decimal(3), 4), d)
1890 self.assertRaises(TypeError, c.fma, '2', 3, 4)
1891 self.assertRaises(TypeError, c.fma, 2, '3', 4)
1892 self.assertRaises(TypeError, c.fma, 2, 3, '4')
1893
1894 def test_is_finite(self):
1895 c = Context()
1896 d = c.is_finite(Decimal(10))
1897 self.assertEqual(c.is_finite(10), d)
1898 self.assertRaises(TypeError, c.is_finite, '10')
1899
1900 def test_is_infinite(self):
1901 c = Context()
1902 d = c.is_infinite(Decimal(10))
1903 self.assertEqual(c.is_infinite(10), d)
1904 self.assertRaises(TypeError, c.is_infinite, '10')
1905
1906 def test_is_nan(self):
1907 c = Context()
1908 d = c.is_nan(Decimal(10))
1909 self.assertEqual(c.is_nan(10), d)
1910 self.assertRaises(TypeError, c.is_nan, '10')
1911
1912 def test_is_normal(self):
1913 c = Context()
1914 d = c.is_normal(Decimal(10))
1915 self.assertEqual(c.is_normal(10), d)
1916 self.assertRaises(TypeError, c.is_normal, '10')
1917
1918 def test_is_qnan(self):
1919 c = Context()
1920 d = c.is_qnan(Decimal(10))
1921 self.assertEqual(c.is_qnan(10), d)
1922 self.assertRaises(TypeError, c.is_qnan, '10')
1923
1924 def test_is_signed(self):
1925 c = Context()
1926 d = c.is_signed(Decimal(10))
1927 self.assertEqual(c.is_signed(10), d)
1928 self.assertRaises(TypeError, c.is_signed, '10')
1929
1930 def test_is_snan(self):
1931 c = Context()
1932 d = c.is_snan(Decimal(10))
1933 self.assertEqual(c.is_snan(10), d)
1934 self.assertRaises(TypeError, c.is_snan, '10')
1935
1936 def test_is_subnormal(self):
1937 c = Context()
1938 d = c.is_subnormal(Decimal(10))
1939 self.assertEqual(c.is_subnormal(10), d)
1940 self.assertRaises(TypeError, c.is_subnormal, '10')
1941
1942 def test_is_zero(self):
1943 c = Context()
1944 d = c.is_zero(Decimal(10))
1945 self.assertEqual(c.is_zero(10), d)
1946 self.assertRaises(TypeError, c.is_zero, '10')
1947
1948 def test_ln(self):
1949 c = Context()
1950 d = c.ln(Decimal(10))
1951 self.assertEqual(c.ln(10), d)
1952 self.assertRaises(TypeError, c.ln, '10')
1953
1954 def test_log10(self):
1955 c = Context()
1956 d = c.log10(Decimal(10))
1957 self.assertEqual(c.log10(10), d)
1958 self.assertRaises(TypeError, c.log10, '10')
1959
1960 def test_logb(self):
1961 c = Context()
1962 d = c.logb(Decimal(10))
1963 self.assertEqual(c.logb(10), d)
1964 self.assertRaises(TypeError, c.logb, '10')
1965
1966 def test_logical_and(self):
1967 c = Context()
1968 d = c.logical_and(Decimal(1), Decimal(1))
1969 self.assertEqual(c.logical_and(1, 1), d)
1970 self.assertEqual(c.logical_and(Decimal(1), 1), d)
1971 self.assertEqual(c.logical_and(1, Decimal(1)), d)
1972 self.assertRaises(TypeError, c.logical_and, '1', 1)
1973 self.assertRaises(TypeError, c.logical_and, 1, '1')
1974
1975 def test_logical_invert(self):
1976 c = Context()
1977 d = c.logical_invert(Decimal(1000))
1978 self.assertEqual(c.logical_invert(1000), d)
1979 self.assertRaises(TypeError, c.logical_invert, '1000')
1980
1981 def test_logical_or(self):
1982 c = Context()
1983 d = c.logical_or(Decimal(1), Decimal(1))
1984 self.assertEqual(c.logical_or(1, 1), d)
1985 self.assertEqual(c.logical_or(Decimal(1), 1), d)
1986 self.assertEqual(c.logical_or(1, Decimal(1)), d)
1987 self.assertRaises(TypeError, c.logical_or, '1', 1)
1988 self.assertRaises(TypeError, c.logical_or, 1, '1')
1989
1990 def test_logical_xor(self):
1991 c = Context()
1992 d = c.logical_xor(Decimal(1), Decimal(1))
1993 self.assertEqual(c.logical_xor(1, 1), d)
1994 self.assertEqual(c.logical_xor(Decimal(1), 1), d)
1995 self.assertEqual(c.logical_xor(1, Decimal(1)), d)
1996 self.assertRaises(TypeError, c.logical_xor, '1', 1)
1997 self.assertRaises(TypeError, c.logical_xor, 1, '1')
1998
1999 def test_max(self):
2000 c = Context()
2001 d = c.max(Decimal(1), Decimal(2))
2002 self.assertEqual(c.max(1, 2), d)
2003 self.assertEqual(c.max(Decimal(1), 2), d)
2004 self.assertEqual(c.max(1, Decimal(2)), d)
2005 self.assertRaises(TypeError, c.max, '1', 2)
2006 self.assertRaises(TypeError, c.max, 1, '2')
2007
2008 def test_max_mag(self):
2009 c = Context()
2010 d = c.max_mag(Decimal(1), Decimal(2))
2011 self.assertEqual(c.max_mag(1, 2), d)
2012 self.assertEqual(c.max_mag(Decimal(1), 2), d)
2013 self.assertEqual(c.max_mag(1, Decimal(2)), d)
2014 self.assertRaises(TypeError, c.max_mag, '1', 2)
2015 self.assertRaises(TypeError, c.max_mag, 1, '2')
2016
2017 def test_min(self):
2018 c = Context()
2019 d = c.min(Decimal(1), Decimal(2))
2020 self.assertEqual(c.min(1, 2), d)
2021 self.assertEqual(c.min(Decimal(1), 2), d)
2022 self.assertEqual(c.min(1, Decimal(2)), d)
2023 self.assertRaises(TypeError, c.min, '1', 2)
2024 self.assertRaises(TypeError, c.min, 1, '2')
2025
2026 def test_min_mag(self):
2027 c = Context()
2028 d = c.min_mag(Decimal(1), Decimal(2))
2029 self.assertEqual(c.min_mag(1, 2), d)
2030 self.assertEqual(c.min_mag(Decimal(1), 2), d)
2031 self.assertEqual(c.min_mag(1, Decimal(2)), d)
2032 self.assertRaises(TypeError, c.min_mag, '1', 2)
2033 self.assertRaises(TypeError, c.min_mag, 1, '2')
2034
2035 def test_minus(self):
2036 c = Context()
2037 d = c.minus(Decimal(10))
2038 self.assertEqual(c.minus(10), d)
2039 self.assertRaises(TypeError, c.minus, '10')
2040
2041 def test_multiply(self):
2042 c = Context()
2043 d = c.multiply(Decimal(1), Decimal(2))
2044 self.assertEqual(c.multiply(1, 2), d)
2045 self.assertEqual(c.multiply(Decimal(1), 2), d)
2046 self.assertEqual(c.multiply(1, Decimal(2)), d)
2047 self.assertRaises(TypeError, c.multiply, '1', 2)
2048 self.assertRaises(TypeError, c.multiply, 1, '2')
2049
2050 def test_next_minus(self):
2051 c = Context()
2052 d = c.next_minus(Decimal(10))
2053 self.assertEqual(c.next_minus(10), d)
2054 self.assertRaises(TypeError, c.next_minus, '10')
2055
2056 def test_next_plus(self):
2057 c = Context()
2058 d = c.next_plus(Decimal(10))
2059 self.assertEqual(c.next_plus(10), d)
2060 self.assertRaises(TypeError, c.next_plus, '10')
2061
2062 def test_next_toward(self):
2063 c = Context()
2064 d = c.next_toward(Decimal(1), Decimal(2))
2065 self.assertEqual(c.next_toward(1, 2), d)
2066 self.assertEqual(c.next_toward(Decimal(1), 2), d)
2067 self.assertEqual(c.next_toward(1, Decimal(2)), d)
2068 self.assertRaises(TypeError, c.next_toward, '1', 2)
2069 self.assertRaises(TypeError, c.next_toward, 1, '2')
2070
2071 def test_normalize(self):
2072 c = Context()
2073 d = c.normalize(Decimal(10))
2074 self.assertEqual(c.normalize(10), d)
2075 self.assertRaises(TypeError, c.normalize, '10')
2076
2077 def test_number_class(self):
2078 c = Context()
2079 self.assertEqual(c.number_class(123), c.number_class(Decimal(123)))
2080 self.assertEqual(c.number_class(0), c.number_class(Decimal(0)))
2081 self.assertEqual(c.number_class(-45), c.number_class(Decimal(-45)))
2082
2083 def test_power(self):
2084 c = Context()
2085 d = c.power(Decimal(1), Decimal(4), Decimal(2))
2086 self.assertEqual(c.power(1, 4, 2), d)
2087 self.assertEqual(c.power(Decimal(1), 4, 2), d)
2088 self.assertEqual(c.power(1, Decimal(4), 2), d)
2089 self.assertEqual(c.power(1, 4, Decimal(2)), d)
2090 self.assertEqual(c.power(Decimal(1), Decimal(4), 2), d)
2091 self.assertRaises(TypeError, c.power, '1', 4, 2)
2092 self.assertRaises(TypeError, c.power, 1, '4', 2)
2093 self.assertRaises(TypeError, c.power, 1, 4, '2')
2094
2095 def test_plus(self):
2096 c = Context()
2097 d = c.plus(Decimal(10))
2098 self.assertEqual(c.plus(10), d)
2099 self.assertRaises(TypeError, c.plus, '10')
2100
2101 def test_quantize(self):
2102 c = Context()
2103 d = c.quantize(Decimal(1), Decimal(2))
2104 self.assertEqual(c.quantize(1, 2), d)
2105 self.assertEqual(c.quantize(Decimal(1), 2), d)
2106 self.assertEqual(c.quantize(1, Decimal(2)), d)
2107 self.assertRaises(TypeError, c.quantize, '1', 2)
2108 self.assertRaises(TypeError, c.quantize, 1, '2')
2109
2110 def test_remainder(self):
2111 c = Context()
2112 d = c.remainder(Decimal(1), Decimal(2))
2113 self.assertEqual(c.remainder(1, 2), d)
2114 self.assertEqual(c.remainder(Decimal(1), 2), d)
2115 self.assertEqual(c.remainder(1, Decimal(2)), d)
2116 self.assertRaises(TypeError, c.remainder, '1', 2)
2117 self.assertRaises(TypeError, c.remainder, 1, '2')
2118
2119 def test_remainder_near(self):
2120 c = Context()
2121 d = c.remainder_near(Decimal(1), Decimal(2))
2122 self.assertEqual(c.remainder_near(1, 2), d)
2123 self.assertEqual(c.remainder_near(Decimal(1), 2), d)
2124 self.assertEqual(c.remainder_near(1, Decimal(2)), d)
2125 self.assertRaises(TypeError, c.remainder_near, '1', 2)
2126 self.assertRaises(TypeError, c.remainder_near, 1, '2')
2127
2128 def test_rotate(self):
2129 c = Context()
2130 d = c.rotate(Decimal(1), Decimal(2))
2131 self.assertEqual(c.rotate(1, 2), d)
2132 self.assertEqual(c.rotate(Decimal(1), 2), d)
2133 self.assertEqual(c.rotate(1, Decimal(2)), d)
2134 self.assertRaises(TypeError, c.rotate, '1', 2)
2135 self.assertRaises(TypeError, c.rotate, 1, '2')
2136
2137 def test_sqrt(self):
2138 c = Context()
2139 d = c.sqrt(Decimal(10))
2140 self.assertEqual(c.sqrt(10), d)
2141 self.assertRaises(TypeError, c.sqrt, '10')
2142
2143 def test_same_quantum(self):
2144 c = Context()
2145 d = c.same_quantum(Decimal(1), Decimal(2))
2146 self.assertEqual(c.same_quantum(1, 2), d)
2147 self.assertEqual(c.same_quantum(Decimal(1), 2), d)
2148 self.assertEqual(c.same_quantum(1, Decimal(2)), d)
2149 self.assertRaises(TypeError, c.same_quantum, '1', 2)
2150 self.assertRaises(TypeError, c.same_quantum, 1, '2')
2151
2152 def test_scaleb(self):
2153 c = Context()
2154 d = c.scaleb(Decimal(1), Decimal(2))
2155 self.assertEqual(c.scaleb(1, 2), d)
2156 self.assertEqual(c.scaleb(Decimal(1), 2), d)
2157 self.assertEqual(c.scaleb(1, Decimal(2)), d)
2158 self.assertRaises(TypeError, c.scaleb, '1', 2)
2159 self.assertRaises(TypeError, c.scaleb, 1, '2')
2160
2161 def test_shift(self):
2162 c = Context()
2163 d = c.shift(Decimal(1), Decimal(2))
2164 self.assertEqual(c.shift(1, 2), d)
2165 self.assertEqual(c.shift(Decimal(1), 2), d)
2166 self.assertEqual(c.shift(1, Decimal(2)), d)
2167 self.assertRaises(TypeError, c.shift, '1', 2)
2168 self.assertRaises(TypeError, c.shift, 1, '2')
2169
2170 def test_subtract(self):
2171 c = Context()
2172 d = c.subtract(Decimal(1), Decimal(2))
2173 self.assertEqual(c.subtract(1, 2), d)
2174 self.assertEqual(c.subtract(Decimal(1), 2), d)
2175 self.assertEqual(c.subtract(1, Decimal(2)), d)
2176 self.assertRaises(TypeError, c.subtract, '1', 2)
2177 self.assertRaises(TypeError, c.subtract, 1, '2')
2178
2179 def test_to_eng_string(self):
2180 c = Context()
2181 d = c.to_eng_string(Decimal(10))
2182 self.assertEqual(c.to_eng_string(10), d)
2183 self.assertRaises(TypeError, c.to_eng_string, '10')
2184
2185 def test_to_sci_string(self):
2186 c = Context()
2187 d = c.to_sci_string(Decimal(10))
2188 self.assertEqual(c.to_sci_string(10), d)
2189 self.assertRaises(TypeError, c.to_sci_string, '10')
2190
2191 def test_to_integral_exact(self):
2192 c = Context()
2193 d = c.to_integral_exact(Decimal(10))
2194 self.assertEqual(c.to_integral_exact(10), d)
2195 self.assertRaises(TypeError, c.to_integral_exact, '10')
2196
2197 def test_to_integral_value(self):
2198 c = Context()
2199 d = c.to_integral_value(Decimal(10))
2200 self.assertEqual(c.to_integral_value(10), d)
2201 self.assertRaises(TypeError, c.to_integral_value, '10')
2202
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002203class WithStatementTest(unittest.TestCase):
2204 # Can't do these as docstrings until Python 2.6
2205 # as doctest can't handle __future__ statements
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002206
2207 def test_localcontext(self):
Nick Coghlanced12182006-09-02 03:54:17 +00002208 # Use a copy of the current context in the block
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002209 orig_ctx = getcontext()
2210 with localcontext() as enter_ctx:
2211 set_ctx = getcontext()
2212 final_ctx = getcontext()
Ezio Melotti856a3be2010-04-03 14:51:00 +00002213 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
2214 self.assertIsNot(orig_ctx, set_ctx, 'did not copy the context')
2215 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002216
2217 def test_localcontextarg(self):
Nick Coghlanced12182006-09-02 03:54:17 +00002218 # Use a copy of the supplied context in the block
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002219 orig_ctx = getcontext()
2220 new_ctx = Context(prec=42)
2221 with localcontext(new_ctx) as enter_ctx:
2222 set_ctx = getcontext()
2223 final_ctx = getcontext()
Ezio Melotti856a3be2010-04-03 14:51:00 +00002224 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
2225 self.assertEqual(set_ctx.prec, new_ctx.prec, 'did not set correct context')
2226 self.assertIsNot(new_ctx, set_ctx, 'did not copy the context')
2227 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002228
Facundo Batista353750c2007-09-13 18:13:15 +00002229class ContextFlags(unittest.TestCase):
2230 def test_flags_irrelevant(self):
2231 # check that the result (numeric result + flags raised) of an
2232 # arithmetic operation doesn't depend on the current flags
2233
2234 context = Context(prec=9, Emin = -999999999, Emax = 999999999,
2235 rounding=ROUND_HALF_EVEN, traps=[], flags=[])
2236
2237 # operations that raise various flags, in the form (function, arglist)
2238 operations = [
2239 (context._apply, [Decimal("100E-1000000009")]),
2240 (context.sqrt, [Decimal(2)]),
2241 (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]),
2242 (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]),
2243 (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]),
2244 ]
2245
2246 # try various flags individually, then a whole lot at once
2247 flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal],
2248 [Inexact, Rounded, Underflow, Clamped, Subnormal]]
2249
2250 for fn, args in operations:
2251 # find answer and flags raised using a clean context
2252 context.clear_flags()
2253 ans = fn(*args)
2254 flags = [k for k, v in context.flags.items() if v]
2255
2256 for extra_flags in flagsets:
2257 # set flags, before calling operation
2258 context.clear_flags()
2259 for flag in extra_flags:
2260 context._raise_error(flag)
2261 new_ans = fn(*args)
2262
2263 # flags that we expect to be set after the operation
2264 expected_flags = list(flags)
2265 for flag in extra_flags:
2266 if flag not in expected_flags:
2267 expected_flags.append(flag)
Facundo Batista353750c2007-09-13 18:13:15 +00002268
2269 # flags we actually got
2270 new_flags = [k for k,v in context.flags.items() if v]
Facundo Batista353750c2007-09-13 18:13:15 +00002271
2272 self.assertEqual(ans, new_ans,
2273 "operation produces different answers depending on flags set: " +
2274 "expected %s, got %s." % (ans, new_ans))
Florent Xicluna8f43cec2010-03-21 10:51:40 +00002275 self.assertItemsEqual(new_flags, expected_flags,
Facundo Batista353750c2007-09-13 18:13:15 +00002276 "operation raises different flags depending on flags set: " +
2277 "expected %s, got %s" % (expected_flags, new_flags))
2278
Zachary Ware9ce635f2014-06-02 16:01:16 -05002279def test_main(arith=None, verbose=None, todo_tests=None, debug=None):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002280 """ Execute the tests.
2281
Raymond Hettingered20ad82004-09-04 20:09:13 +00002282 Runs all arithmetic tests if arith is True or if the "decimal" resource
2283 is enabled in regrtest.py
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002284 """
Raymond Hettingered20ad82004-09-04 20:09:13 +00002285
Neal Norwitzce4a9c92006-04-09 08:36:46 +00002286 init()
Facundo Batista353750c2007-09-13 18:13:15 +00002287 global TEST_ALL, DEBUG
Zachary Ware9ce635f2014-06-02 16:01:16 -05002288 TEST_ALL = arith if arith is not None else is_resource_enabled('decimal')
Facundo Batista353750c2007-09-13 18:13:15 +00002289 DEBUG = debug
Raymond Hettingered20ad82004-09-04 20:09:13 +00002290
Facundo Batista353750c2007-09-13 18:13:15 +00002291 if todo_tests is None:
2292 test_classes = [
2293 DecimalExplicitConstructionTest,
2294 DecimalImplicitConstructionTest,
2295 DecimalArithmeticOperatorsTest,
Mark Dickinson1ddf1d82008-02-29 02:16:37 +00002296 DecimalFormatTest,
Facundo Batista353750c2007-09-13 18:13:15 +00002297 DecimalUseOfContextTest,
2298 DecimalUsabilityTest,
2299 DecimalPythonAPItests,
2300 ContextAPItests,
2301 DecimalTest,
2302 WithStatementTest,
2303 ContextFlags
2304 ]
2305 else:
2306 test_classes = [DecimalTest]
2307
2308 # Dynamically build custom test definition for each file in the test
2309 # directory and add the definitions to the DecimalTest class. This
2310 # procedure insures that new files do not get skipped.
2311 for filename in os.listdir(directory):
2312 if '.decTest' not in filename or filename.startswith("."):
2313 continue
2314 head, tail = filename.split('.')
2315 if todo_tests is not None and head not in todo_tests:
2316 continue
2317 tester = lambda self, f=filename: self.eval_file(directory + f)
2318 setattr(DecimalTest, 'test_' + head, tester)
2319 del filename, head, tail, tester
2320
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002321
Tim Peters46cc7022006-03-31 04:11:16 +00002322 try:
2323 run_unittest(*test_classes)
Facundo Batista353750c2007-09-13 18:13:15 +00002324 if todo_tests is None:
2325 import decimal as DecimalModule
2326 run_doctest(DecimalModule, verbose)
Tim Peters46cc7022006-03-31 04:11:16 +00002327 finally:
2328 setcontext(ORIGINAL_CONTEXT)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002329
2330if __name__ == '__main__':
Facundo Batista353750c2007-09-13 18:13:15 +00002331 import optparse
2332 p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]")
2333 p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test')
2334 p.add_option('--skip', '-s', action='store_true', help='skip over 90% of the arithmetic tests')
2335 (opt, args) = p.parse_args()
2336
2337 if opt.skip:
2338 test_main(arith=False, verbose=True)
2339 elif args:
2340 test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002341 else:
Facundo Batista353750c2007-09-13 18:13:15 +00002342 test_main(arith=True, verbose=True)