blob: 3d55bc15ab68916ac70e270637f36c4c42f9940a [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
29import pickle, copy
Jeffrey Yasskinca2b69f2008-02-01 06:22:46 +000030import unittest
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000031from decimal import *
Raymond Hettinger2c8585b2009-02-03 03:37:03 +000032import numbers
Florent Xicluna8f43cec2010-03-21 10:51:40 +000033from test.test_support import (run_unittest, run_doctest,
34 is_resource_enabled, check_py3k_warnings)
Raymond Hettinger0aeac102004-07-05 22:53:03 +000035import random
Raymond Hettinger7e71fa52004-12-18 19:07:19 +000036try:
37 import threading
38except ImportError:
39 threading = None
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000040
Raymond Hettingerfed52962004-07-14 15:41:57 +000041# Useful Test Constant
42Signals = getcontext().flags.keys()
43
Tim Peters46cc7022006-03-31 04:11:16 +000044# Tests are built around these assumed context defaults.
45# test_main() restores the original context.
Neal Norwitzce4a9c92006-04-09 08:36:46 +000046def init():
47 global ORIGINAL_CONTEXT
48 ORIGINAL_CONTEXT = getcontext().copy()
Facundo Batistaee340e52008-05-02 17:39:00 +000049 DefaultTestContext = Context(
50 prec = 9,
51 rounding = ROUND_HALF_EVEN,
52 traps = dict.fromkeys(Signals, 0)
53 )
54 setcontext(DefaultTestContext)
Raymond Hettinger6ea48452004-07-03 12:26:21 +000055
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000056TESTDATADIR = 'decimaltestdata'
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +000057if __name__ == '__main__':
58 file = sys.argv[0]
59else:
60 file = __file__
61testdir = os.path.dirname(file) or os.curdir
Raymond Hettinger267b8682005-03-27 10:47:39 +000062directory = testdir + os.sep + TESTDATADIR + os.sep
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000063
Raymond Hettinger267b8682005-03-27 10:47:39 +000064skip_expected = not os.path.isdir(directory)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000065
Mark Dickinson539bff42009-10-08 16:28:39 +000066# list of individual .decTest test ids that correspond to tests that
67# we're skipping for one reason or another.
68skipped_test_ids = [
69 'scbx164', # skipping apparently implementation-specific scaleb
70 'scbx165', # tests, pending clarification of scaleb rules.
71]
72
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000073# Make sure it actually raises errors when not expected and caught in flags
74# Slower, since it runs some things several times.
75EXTENDEDERRORTEST = False
76
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000077#Map the test cases' error names to the actual errors
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000078ErrorNames = {'clamped' : Clamped,
Raymond Hettinger5aa478b2004-07-09 10:02:53 +000079 'conversion_syntax' : InvalidOperation,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000080 'division_by_zero' : DivisionByZero,
Raymond Hettinger5aa478b2004-07-09 10:02:53 +000081 'division_impossible' : InvalidOperation,
82 'division_undefined' : InvalidOperation,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000083 'inexact' : Inexact,
Raymond Hettinger5aa478b2004-07-09 10:02:53 +000084 'invalid_context' : InvalidOperation,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000085 'invalid_operation' : InvalidOperation,
86 'overflow' : Overflow,
87 'rounded' : Rounded,
88 'subnormal' : Subnormal,
89 'underflow' : Underflow}
90
91
92def Nonfunction(*args):
93 """Doesn't do anything."""
94 return None
95
96RoundingDict = {'ceiling' : ROUND_CEILING, #Maps test-case names to roundings.
97 'down' : ROUND_DOWN,
98 'floor' : ROUND_FLOOR,
99 'half_down' : ROUND_HALF_DOWN,
100 'half_even' : ROUND_HALF_EVEN,
101 'half_up' : ROUND_HALF_UP,
Facundo Batista353750c2007-09-13 18:13:15 +0000102 'up' : ROUND_UP,
103 '05up' : ROUND_05UP}
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000104
105# Name adapter to be able to change the Decimal and Context
106# interface without changing the test files from Cowlishaw
Facundo Batista1a191df2007-10-02 17:01:24 +0000107nameAdapter = {'and':'logical_and',
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000108 'apply':'_apply',
Facundo Batista353750c2007-09-13 18:13:15 +0000109 'class':'number_class',
110 'comparesig':'compare_signal',
111 'comparetotal':'compare_total',
112 'comparetotmag':'compare_total_mag',
Facundo Batista353750c2007-09-13 18:13:15 +0000113 'copy':'copy_decimal',
Facundo Batista1a191df2007-10-02 17:01:24 +0000114 'copyabs':'copy_abs',
Facundo Batista353750c2007-09-13 18:13:15 +0000115 'copynegate':'copy_negate',
116 'copysign':'copy_sign',
Facundo Batista1a191df2007-10-02 17:01:24 +0000117 'divideint':'divide_int',
Facundo Batista353750c2007-09-13 18:13:15 +0000118 'invert':'logical_invert',
Facundo Batista1a191df2007-10-02 17:01:24 +0000119 'iscanonical':'is_canonical',
120 'isfinite':'is_finite',
121 'isinfinite':'is_infinite',
122 'isnan':'is_nan',
123 'isnormal':'is_normal',
124 'isqnan':'is_qnan',
125 'issigned':'is_signed',
126 'issnan':'is_snan',
127 'issubnormal':'is_subnormal',
128 'iszero':'is_zero',
Facundo Batista353750c2007-09-13 18:13:15 +0000129 'maxmag':'max_mag',
130 'minmag':'min_mag',
131 'nextminus':'next_minus',
132 'nextplus':'next_plus',
133 'nexttoward':'next_toward',
Facundo Batista1a191df2007-10-02 17:01:24 +0000134 'or':'logical_or',
Facundo Batista353750c2007-09-13 18:13:15 +0000135 'reduce':'normalize',
Facundo Batista1a191df2007-10-02 17:01:24 +0000136 'remaindernear':'remainder_near',
137 'samequantum':'same_quantum',
138 'squareroot':'sqrt',
139 'toeng':'to_eng_string',
140 'tointegral':'to_integral_value',
141 'tointegralx':'to_integral_exact',
142 'tosci':'to_sci_string',
143 'xor':'logical_xor',
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000144 }
145
Facundo Batista1a191df2007-10-02 17:01:24 +0000146# The following functions return True/False rather than a Decimal instance
147
148LOGICAL_FUNCTIONS = (
149 'is_canonical',
150 'is_finite',
151 'is_infinite',
152 'is_nan',
153 'is_normal',
154 'is_qnan',
155 'is_signed',
156 'is_snan',
157 'is_subnormal',
158 'is_zero',
159 'same_quantum',
160 )
161
Facundo Batista353750c2007-09-13 18:13:15 +0000162# For some operations (currently exp, ln, log10, power), the decNumber
163# reference implementation imposes additional restrictions on the
164# context and operands. These restrictions are not part of the
165# specification; however, the effect of these restrictions does show
166# up in some of the testcases. We skip testcases that violate these
167# restrictions, since Decimal behaves differently from decNumber for
168# these testcases so these testcases would otherwise fail.
169
170decNumberRestricted = ('power', 'ln', 'log10', 'exp')
171DEC_MAX_MATH = 999999
172def outside_decNumber_bounds(v, context):
173 if (context.prec > DEC_MAX_MATH or
174 context.Emax > DEC_MAX_MATH or
175 -context.Emin > DEC_MAX_MATH):
176 return True
177 if not v._is_special and v and (
Facundo Batista353750c2007-09-13 18:13:15 +0000178 v.adjusted() > DEC_MAX_MATH or
179 v.adjusted() < 1-2*DEC_MAX_MATH):
180 return True
181 return False
182
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000183class DecimalTest(unittest.TestCase):
184 """Class which tests the Decimal class against the test cases.
185
186 Changed for unittest.
187 """
188 def setUp(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000189 self.context = Context()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000190 self.ignore_list = ['#']
191 # Basically, a # means return NaN InvalidOperation.
192 # Different from a sNaN in trim
193
194 self.ChangeDict = {'precision' : self.change_precision,
195 'rounding' : self.change_rounding_method,
196 'maxexponent' : self.change_max_exponent,
197 'minexponent' : self.change_min_exponent,
198 'clamp' : self.change_clamp}
199
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000200 def eval_file(self, file):
201 global skip_expected
202 if skip_expected:
Benjamin Petersonbec087f2009-03-26 21:10:30 +0000203 raise unittest.SkipTest
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000204 return
Florent Xicluna8f43cec2010-03-21 10:51:40 +0000205 for line in open(file):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000206 line = line.replace('\r\n', '').replace('\n', '')
Raymond Hettinger5aa478b2004-07-09 10:02:53 +0000207 #print line
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000208 try:
209 t = self.eval_line(line)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000210 except DecimalException, exception:
211 #Exception raised where there shoudn't have been one.
212 self.fail('Exception "'+exception.__class__.__name__ + '" raised on line '+line)
213
214 return
215
216 def eval_line(self, s):
217 if s.find(' -> ') >= 0 and s[:2] != '--' and not s.startswith(' --'):
218 s = (s.split('->')[0] + '->' +
219 s.split('->')[1].split('--')[0]).strip()
220 else:
221 s = s.split('--')[0].strip()
222
223 for ignore in self.ignore_list:
224 if s.find(ignore) >= 0:
225 #print s.split()[0], 'NotImplemented--', ignore
226 return
227 if not s:
228 return
229 elif ':' in s:
230 return self.eval_directive(s)
231 else:
232 return self.eval_equation(s)
233
234 def eval_directive(self, s):
235 funct, value = map(lambda x: x.strip().lower(), s.split(':'))
236 if funct == 'rounding':
237 value = RoundingDict[value]
238 else:
239 try:
240 value = int(value)
241 except ValueError:
242 pass
243
244 funct = self.ChangeDict.get(funct, Nonfunction)
245 funct(value)
246
247 def eval_equation(self, s):
248 #global DEFAULT_PRECISION
249 #print DEFAULT_PRECISION
Raymond Hettingered20ad82004-09-04 20:09:13 +0000250
251 if not TEST_ALL and random.random() < 0.90:
252 return
253
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000254 try:
255 Sides = s.split('->')
256 L = Sides[0].strip().split()
257 id = L[0]
Facundo Batista353750c2007-09-13 18:13:15 +0000258 if DEBUG:
259 print "Test ", id,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000260 funct = L[1].lower()
261 valstemp = L[2:]
262 L = Sides[1].strip().split()
263 ans = L[0]
264 exceptions = L[1:]
265 except (TypeError, AttributeError, IndexError):
Raymond Hettingerd87ac8f2004-07-09 10:52:54 +0000266 raise InvalidOperation
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000267 def FixQuotes(val):
268 val = val.replace("''", 'SingleQuote').replace('""', 'DoubleQuote')
269 val = val.replace("'", '').replace('"', '')
270 val = val.replace('SingleQuote', "'").replace('DoubleQuote', '"')
271 return val
Mark Dickinson539bff42009-10-08 16:28:39 +0000272
273 if id in skipped_test_ids:
274 return
275
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000276 fname = nameAdapter.get(funct, funct)
277 if fname == 'rescale':
278 return
279 funct = getattr(self.context, fname)
280 vals = []
281 conglomerate = ''
282 quote = 0
283 theirexceptions = [ErrorNames[x.lower()] for x in exceptions]
284
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000285 for exception in Signals:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000286 self.context.traps[exception] = 1 #Catch these bugs...
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000287 for exception in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000288 self.context.traps[exception] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000289 for i, val in enumerate(valstemp):
290 if val.count("'") % 2 == 1:
291 quote = 1 - quote
292 if quote:
293 conglomerate = conglomerate + ' ' + val
294 continue
295 else:
296 val = conglomerate + val
297 conglomerate = ''
298 v = FixQuotes(val)
299 if fname in ('to_sci_string', 'to_eng_string'):
300 if EXTENDEDERRORTEST:
301 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000302 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000303 try:
304 funct(self.context.create_decimal(v))
305 except error:
306 pass
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000307 except Signals, e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000308 self.fail("Raised %s in %s when %s disabled" % \
309 (e, s, error))
310 else:
311 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000312 self.context.traps[error] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000313 v = self.context.create_decimal(v)
314 else:
Facundo Batista353750c2007-09-13 18:13:15 +0000315 v = Decimal(v, self.context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000316 vals.append(v)
317
318 ans = FixQuotes(ans)
319
Facundo Batista353750c2007-09-13 18:13:15 +0000320 # skip tests that are related to bounds imposed in the decNumber
321 # reference implementation
322 if fname in decNumberRestricted:
323 if fname == 'power':
324 if not (vals[1]._isinteger() and
325 -1999999997 <= vals[1] <= 999999999):
326 if outside_decNumber_bounds(vals[0], self.context) or \
327 outside_decNumber_bounds(vals[1], self.context):
328 #print "Skipping test %s" % s
329 return
330 else:
331 if outside_decNumber_bounds(vals[0], self.context):
332 #print "Skipping test %s" % s
333 return
334
335
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000336 if EXTENDEDERRORTEST and fname not in ('to_sci_string', 'to_eng_string'):
337 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000338 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000339 try:
340 funct(*vals)
341 except error:
342 pass
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000343 except Signals, e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000344 self.fail("Raised %s in %s when %s disabled" % \
345 (e, s, error))
346 else:
347 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000348 self.context.traps[error] = 0
Facundo Batista353750c2007-09-13 18:13:15 +0000349 if DEBUG:
350 print "--", self.context
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000351 try:
352 result = str(funct(*vals))
Facundo Batista1a191df2007-10-02 17:01:24 +0000353 if fname in LOGICAL_FUNCTIONS:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000354 result = str(int(eval(result))) # 'True', 'False' -> '1', '0'
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000355 except Signals, error:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000356 self.fail("Raised %s in %s" % (error, s))
357 except: #Catch any error long enough to state the test case.
358 print "ERROR:", s
359 raise
360
361 myexceptions = self.getexceptions()
Raymond Hettingerbf440692004-07-10 14:14:37 +0000362 self.context.clear_flags()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000363
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000364 self.assertEqual(result, ans,
365 'Incorrect answer for ' + s + ' -- got ' + result)
Florent Xicluna8f43cec2010-03-21 10:51:40 +0000366 self.assertItemsEqual(myexceptions, theirexceptions,
Facundo Batista353750c2007-09-13 18:13:15 +0000367 'Incorrect flags set in ' + s + ' -- got ' + str(myexceptions))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000368 return
369
370 def getexceptions(self):
Raymond Hettingerf63ba432004-08-17 05:42:09 +0000371 return [e for e in Signals if self.context.flags[e]]
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000372
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000373 def change_precision(self, prec):
374 self.context.prec = prec
375 def change_rounding_method(self, rounding):
376 self.context.rounding = rounding
377 def change_min_exponent(self, exp):
378 self.context.Emin = exp
379 def change_max_exponent(self, exp):
380 self.context.Emax = exp
381 def change_clamp(self, clamp):
382 self.context._clamp = clamp
383
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000384
385
386# The following classes test the behaviour of Decimal according to PEP 327
387
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000388class DecimalExplicitConstructionTest(unittest.TestCase):
389 '''Unit tests for Explicit Construction cases of Decimal.'''
390
391 def test_explicit_empty(self):
392 self.assertEqual(Decimal(), Decimal("0"))
393
394 def test_explicit_from_None(self):
395 self.assertRaises(TypeError, Decimal, None)
396
397 def test_explicit_from_int(self):
398
399 #positive
400 d = Decimal(45)
401 self.assertEqual(str(d), '45')
402
403 #very large positive
404 d = Decimal(500000123)
405 self.assertEqual(str(d), '500000123')
406
407 #negative
408 d = Decimal(-45)
409 self.assertEqual(str(d), '-45')
410
411 #zero
412 d = Decimal(0)
413 self.assertEqual(str(d), '0')
414
415 def test_explicit_from_string(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000416
417 #empty
418 self.assertEqual(str(Decimal('')), 'NaN')
419
420 #int
421 self.assertEqual(str(Decimal('45')), '45')
422
423 #float
424 self.assertEqual(str(Decimal('45.34')), '45.34')
425
426 #engineer notation
427 self.assertEqual(str(Decimal('45e2')), '4.5E+3')
428
429 #just not a number
430 self.assertEqual(str(Decimal('ugly')), 'NaN')
431
Mark Dickinson59bc20b2008-01-12 01:56:00 +0000432 #leading and trailing whitespace permitted
433 self.assertEqual(str(Decimal('1.3E4 \n')), '1.3E+4')
434 self.assertEqual(str(Decimal(' -7.89')), '-7.89')
435
Mark Dickinson8e85ffa2008-03-25 18:47:59 +0000436 #unicode strings should be permitted
437 self.assertEqual(str(Decimal(u'0E-017')), '0E-17')
438 self.assertEqual(str(Decimal(u'45')), '45')
439 self.assertEqual(str(Decimal(u'-Inf')), '-Infinity')
440 self.assertEqual(str(Decimal(u'NaN123')), 'NaN123')
441
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000442 def test_explicit_from_tuples(self):
443
444 #zero
445 d = Decimal( (0, (0,), 0) )
446 self.assertEqual(str(d), '0')
447
448 #int
449 d = Decimal( (1, (4, 5), 0) )
450 self.assertEqual(str(d), '-45')
451
452 #float
453 d = Decimal( (0, (4, 5, 3, 4), -2) )
454 self.assertEqual(str(d), '45.34')
455
456 #weird
457 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
458 self.assertEqual(str(d), '-4.34913534E-17')
459
460 #wrong number of items
461 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1)) )
462
463 #bad sign
464 self.assertRaises(ValueError, Decimal, (8, (4, 3, 4, 9, 1), 2) )
Facundo Batista9b5e2312007-10-19 19:25:57 +0000465 self.assertRaises(ValueError, Decimal, (0., (4, 3, 4, 9, 1), 2) )
466 self.assertRaises(ValueError, Decimal, (Decimal(1), (4, 3, 4, 9, 1), 2))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000467
468 #bad exp
469 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 'wrong!') )
Facundo Batista9b5e2312007-10-19 19:25:57 +0000470 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 0.) )
471 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), '1') )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000472
473 #bad coefficients
474 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, None, 1), 2) )
475 self.assertRaises(ValueError, Decimal, (1, (4, -3, 4, 9, 1), 2) )
Facundo Batista9b5e2312007-10-19 19:25:57 +0000476 self.assertRaises(ValueError, Decimal, (1, (4, 10, 4, 9, 1), 2) )
Facundo Batista72bc54f2007-11-23 17:59:00 +0000477 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 'a', 1), 2) )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000478
479 def test_explicit_from_Decimal(self):
480
481 #positive
482 d = Decimal(45)
483 e = Decimal(d)
484 self.assertEqual(str(e), '45')
485 self.assertNotEqual(id(d), id(e))
486
487 #very large positive
488 d = Decimal(500000123)
489 e = Decimal(d)
490 self.assertEqual(str(e), '500000123')
491 self.assertNotEqual(id(d), id(e))
492
493 #negative
494 d = Decimal(-45)
495 e = Decimal(d)
496 self.assertEqual(str(e), '-45')
497 self.assertNotEqual(id(d), id(e))
498
499 #zero
500 d = Decimal(0)
501 e = Decimal(d)
502 self.assertEqual(str(e), '0')
503 self.assertNotEqual(id(d), id(e))
504
505 def test_explicit_context_create_decimal(self):
506
507 nc = copy.copy(getcontext())
508 nc.prec = 3
509
510 # empty
Raymond Hettingerfed52962004-07-14 15:41:57 +0000511 d = Decimal()
512 self.assertEqual(str(d), '0')
513 d = nc.create_decimal()
514 self.assertEqual(str(d), '0')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000515
516 # from None
517 self.assertRaises(TypeError, nc.create_decimal, None)
518
519 # from int
520 d = nc.create_decimal(456)
Ezio Melottib0f5adc2010-01-24 16:58:36 +0000521 self.assertIsInstance(d, Decimal)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000522 self.assertEqual(nc.create_decimal(45678),
523 nc.create_decimal('457E+2'))
524
525 # from string
526 d = Decimal('456789')
527 self.assertEqual(str(d), '456789')
528 d = nc.create_decimal('456789')
529 self.assertEqual(str(d), '4.57E+5')
Mark Dickinson59bc20b2008-01-12 01:56:00 +0000530 # leading and trailing whitespace should result in a NaN;
531 # spaces are already checked in Cowlishaw's test-suite, so
532 # here we just check that a trailing newline results in a NaN
533 self.assertEqual(str(nc.create_decimal('3.14\n')), 'NaN')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000534
535 # from tuples
536 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
537 self.assertEqual(str(d), '-4.34913534E-17')
538 d = nc.create_decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
539 self.assertEqual(str(d), '-4.35E-17')
540
541 # from Decimal
542 prevdec = Decimal(500000123)
543 d = Decimal(prevdec)
544 self.assertEqual(str(d), '500000123')
545 d = nc.create_decimal(prevdec)
546 self.assertEqual(str(d), '5.00E+8')
547
Mark Dickinson4326ad82009-08-02 10:59:36 +0000548 def test_unicode_digits(self):
549 test_values = {
550 u'\uff11': '1',
551 u'\u0660.\u0660\u0663\u0667\u0662e-\u0663' : '0.0000372',
552 u'-nan\u0c68\u0c6a\u0c66\u0c66' : '-NaN2400',
553 }
554 for input, expected in test_values.items():
555 self.assertEqual(str(Decimal(input)), expected)
556
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000557
558class DecimalImplicitConstructionTest(unittest.TestCase):
559 '''Unit tests for Implicit Construction cases of Decimal.'''
560
561 def test_implicit_from_None(self):
562 self.assertRaises(TypeError, eval, 'Decimal(5) + None', globals())
563
564 def test_implicit_from_int(self):
565 #normal
566 self.assertEqual(str(Decimal(5) + 45), '50')
567 #exceeding precision
568 self.assertEqual(Decimal(5) + 123456789000, Decimal(123456789000))
569
570 def test_implicit_from_string(self):
571 self.assertRaises(TypeError, eval, 'Decimal(5) + "3"', globals())
572
573 def test_implicit_from_float(self):
574 self.assertRaises(TypeError, eval, 'Decimal(5) + 2.2', globals())
575
576 def test_implicit_from_Decimal(self):
577 self.assertEqual(Decimal(5) + Decimal(45), Decimal(50))
578
Raymond Hettinger267b8682005-03-27 10:47:39 +0000579 def test_rop(self):
580 # Allow other classes to be trained to interact with Decimals
581 class E:
582 def __divmod__(self, other):
583 return 'divmod ' + str(other)
584 def __rdivmod__(self, other):
585 return str(other) + ' rdivmod'
586 def __lt__(self, other):
587 return 'lt ' + str(other)
588 def __gt__(self, other):
589 return 'gt ' + str(other)
590 def __le__(self, other):
591 return 'le ' + str(other)
592 def __ge__(self, other):
593 return 'ge ' + str(other)
594 def __eq__(self, other):
595 return 'eq ' + str(other)
596 def __ne__(self, other):
597 return 'ne ' + str(other)
598
599 self.assertEqual(divmod(E(), Decimal(10)), 'divmod 10')
600 self.assertEqual(divmod(Decimal(10), E()), '10 rdivmod')
601 self.assertEqual(eval('Decimal(10) < E()'), 'gt 10')
602 self.assertEqual(eval('Decimal(10) > E()'), 'lt 10')
603 self.assertEqual(eval('Decimal(10) <= E()'), 'ge 10')
604 self.assertEqual(eval('Decimal(10) >= E()'), 'le 10')
605 self.assertEqual(eval('Decimal(10) == E()'), 'eq 10')
606 self.assertEqual(eval('Decimal(10) != E()'), 'ne 10')
607
608 # insert operator methods and then exercise them
Georg Brandl96c3f7f2006-03-28 08:06:35 +0000609 oplist = [
610 ('+', '__add__', '__radd__'),
611 ('-', '__sub__', '__rsub__'),
612 ('*', '__mul__', '__rmul__'),
613 ('%', '__mod__', '__rmod__'),
614 ('//', '__floordiv__', '__rfloordiv__'),
615 ('**', '__pow__', '__rpow__')
616 ]
Florent Xicluna8f43cec2010-03-21 10:51:40 +0000617 with check_py3k_warnings():
618 if 1 / 2 == 0:
619 # testing with classic division, so add __div__
620 oplist.append(('/', '__div__', '__rdiv__'))
621 else:
622 # testing with -Qnew, so add __truediv__
623 oplist.append(('/', '__truediv__', '__rtruediv__'))
Anthony Baxter4ef3a232006-03-30 12:59:11 +0000624
Georg Brandl96c3f7f2006-03-28 08:06:35 +0000625 for sym, lop, rop in oplist:
Raymond Hettinger267b8682005-03-27 10:47:39 +0000626 setattr(E, lop, lambda self, other: 'str' + lop + str(other))
627 setattr(E, rop, lambda self, other: str(other) + rop + 'str')
628 self.assertEqual(eval('E()' + sym + 'Decimal(10)'),
629 'str' + lop + '10')
630 self.assertEqual(eval('Decimal(10)' + sym + 'E()'),
631 '10' + rop + 'str')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000632
Mark Dickinson277859d2009-03-17 23:03:46 +0000633
Mark Dickinson1ddf1d82008-02-29 02:16:37 +0000634class DecimalFormatTest(unittest.TestCase):
635 '''Unit tests for the format function.'''
636 def test_formatting(self):
637 # triples giving a format, a Decimal, and the expected result
638 test_values = [
639 ('e', '0E-15', '0e-15'),
640 ('e', '2.3E-15', '2.3e-15'),
641 ('e', '2.30E+2', '2.30e+2'), # preserve significant zeros
642 ('e', '2.30000E-15', '2.30000e-15'),
643 ('e', '1.23456789123456789e40', '1.23456789123456789e+40'),
644 ('e', '1.5', '1.5e+0'),
645 ('e', '0.15', '1.5e-1'),
646 ('e', '0.015', '1.5e-2'),
647 ('e', '0.0000000000015', '1.5e-12'),
648 ('e', '15.0', '1.50e+1'),
649 ('e', '-15', '-1.5e+1'),
650 ('e', '0', '0e+0'),
651 ('e', '0E1', '0e+1'),
652 ('e', '0.0', '0e-1'),
653 ('e', '0.00', '0e-2'),
654 ('.6e', '0E-15', '0.000000e-9'),
655 ('.6e', '0', '0.000000e+6'),
656 ('.6e', '9.999999', '9.999999e+0'),
657 ('.6e', '9.9999999', '1.000000e+1'),
658 ('.6e', '-1.23e5', '-1.230000e+5'),
659 ('.6e', '1.23456789e-3', '1.234568e-3'),
660 ('f', '0', '0'),
661 ('f', '0.0', '0.0'),
662 ('f', '0E-2', '0.00'),
663 ('f', '0.00E-8', '0.0000000000'),
664 ('f', '0E1', '0'), # loses exponent information
665 ('f', '3.2E1', '32'),
666 ('f', '3.2E2', '320'),
667 ('f', '3.20E2', '320'),
668 ('f', '3.200E2', '320.0'),
669 ('f', '3.2E-6', '0.0000032'),
670 ('.6f', '0E-15', '0.000000'), # all zeros treated equally
671 ('.6f', '0E1', '0.000000'),
672 ('.6f', '0', '0.000000'),
673 ('.0f', '0', '0'), # no decimal point
674 ('.0f', '0e-2', '0'),
675 ('.0f', '3.14159265', '3'),
676 ('.1f', '3.14159265', '3.1'),
677 ('.4f', '3.14159265', '3.1416'),
678 ('.6f', '3.14159265', '3.141593'),
679 ('.7f', '3.14159265', '3.1415926'), # round-half-even!
680 ('.8f', '3.14159265', '3.14159265'),
681 ('.9f', '3.14159265', '3.141592650'),
682
683 ('g', '0', '0'),
684 ('g', '0.0', '0.0'),
685 ('g', '0E1', '0e+1'),
686 ('G', '0E1', '0E+1'),
687 ('g', '0E-5', '0.00000'),
688 ('g', '0E-6', '0.000000'),
689 ('g', '0E-7', '0e-7'),
690 ('g', '-0E2', '-0e+2'),
691 ('.0g', '3.14159265', '3'), # 0 sig fig -> 1 sig fig
692 ('.1g', '3.14159265', '3'),
693 ('.2g', '3.14159265', '3.1'),
694 ('.5g', '3.14159265', '3.1416'),
695 ('.7g', '3.14159265', '3.141593'),
696 ('.8g', '3.14159265', '3.1415926'), # round-half-even!
697 ('.9g', '3.14159265', '3.14159265'),
698 ('.10g', '3.14159265', '3.14159265'), # don't pad
699
700 ('%', '0E1', '0%'),
701 ('%', '0E0', '0%'),
702 ('%', '0E-1', '0%'),
703 ('%', '0E-2', '0%'),
704 ('%', '0E-3', '0.0%'),
705 ('%', '0E-4', '0.00%'),
706
707 ('.3%', '0', '0.000%'), # all zeros treated equally
708 ('.3%', '0E10', '0.000%'),
709 ('.3%', '0E-10', '0.000%'),
710 ('.3%', '2.34', '234.000%'),
711 ('.3%', '1.234567', '123.457%'),
712 ('.0%', '1.23', '123%'),
713
714 ('e', 'NaN', 'NaN'),
715 ('f', '-NaN123', '-NaN123'),
716 ('+g', 'NaN456', '+NaN456'),
717 ('.3e', 'Inf', 'Infinity'),
718 ('.16f', '-Inf', '-Infinity'),
719 ('.0g', '-sNaN', '-sNaN'),
720
721 ('', '1.00', '1.00'),
Mark Dickinsonb065e522009-03-17 18:01:03 +0000722
Mark Dickinson277859d2009-03-17 23:03:46 +0000723 # test alignment and padding
Mark Dickinson5cfa8042009-09-08 20:20:19 +0000724 ('6', '123', ' 123'),
Mark Dickinsonb065e522009-03-17 18:01:03 +0000725 ('<6', '123', '123 '),
726 ('>6', '123', ' 123'),
727 ('^6', '123', ' 123 '),
728 ('=+6', '123', '+ 123'),
Mark Dickinson277859d2009-03-17 23:03:46 +0000729 ('#<10', 'NaN', 'NaN#######'),
730 ('#<10', '-4.3', '-4.3######'),
731 ('#<+10', '0.0130', '+0.0130###'),
732 ('#< 10', '0.0130', ' 0.0130###'),
733 ('@>10', '-Inf', '@-Infinity'),
734 ('#>5', '-Inf', '-Infinity'),
735 ('?^5', '123', '?123?'),
736 ('%^6', '123', '%123%%'),
737 (' ^6', '-45.6', '-45.6 '),
738 ('/=10', '-45.6', '-/////45.6'),
739 ('/=+10', '45.6', '+/////45.6'),
740 ('/= 10', '45.6', ' /////45.6'),
741
742 # thousands separator
743 (',', '1234567', '1,234,567'),
744 (',', '123456', '123,456'),
745 (',', '12345', '12,345'),
746 (',', '1234', '1,234'),
747 (',', '123', '123'),
748 (',', '12', '12'),
749 (',', '1', '1'),
750 (',', '0', '0'),
751 (',', '-1234567', '-1,234,567'),
752 (',', '-123456', '-123,456'),
753 ('7,', '123456', '123,456'),
Mark Dickinson5cfa8042009-09-08 20:20:19 +0000754 ('8,', '123456', ' 123,456'),
Mark Dickinson277859d2009-03-17 23:03:46 +0000755 ('08,', '123456', '0,123,456'), # special case: extra 0 needed
756 ('+08,', '123456', '+123,456'), # but not if there's a sign
757 (' 08,', '123456', ' 123,456'),
758 ('08,', '-123456', '-123,456'),
759 ('+09,', '123456', '+0,123,456'),
760 # ... with fractional part...
761 ('07,', '1234.56', '1,234.56'),
762 ('08,', '1234.56', '1,234.56'),
763 ('09,', '1234.56', '01,234.56'),
764 ('010,', '1234.56', '001,234.56'),
765 ('011,', '1234.56', '0,001,234.56'),
766 ('012,', '1234.56', '0,001,234.56'),
767 ('08,.1f', '1234.5', '01,234.5'),
768 # no thousands separators in fraction part
769 (',', '1.23456789', '1.23456789'),
770 (',%', '123.456789', '12,345.6789%'),
771 (',e', '123456', '1.23456e+5'),
772 (',E', '123456', '1.23456E+5'),
Mark Dickinson491ea552009-09-07 16:17:41 +0000773
774 # issue 6850
775 ('a=-7.0', '0.12345', 'aaaa0.1'),
Mark Dickinson1ddf1d82008-02-29 02:16:37 +0000776 ]
777 for fmt, d, result in test_values:
778 self.assertEqual(format(Decimal(d), fmt), result)
779
Mark Dickinson277859d2009-03-17 23:03:46 +0000780 def test_n_format(self):
781 try:
782 from locale import CHAR_MAX
783 except ImportError:
784 return
785
786 # Set up some localeconv-like dictionaries
787 en_US = {
788 'decimal_point' : '.',
789 'grouping' : [3, 3, 0],
790 'thousands_sep': ','
791 }
792
793 fr_FR = {
794 'decimal_point' : ',',
795 'grouping' : [CHAR_MAX],
796 'thousands_sep' : ''
797 }
798
799 ru_RU = {
800 'decimal_point' : ',',
801 'grouping' : [3, 3, 0],
802 'thousands_sep' : ' '
803 }
804
805 crazy = {
806 'decimal_point' : '&',
807 'grouping' : [1, 4, 2, CHAR_MAX],
808 'thousands_sep' : '-'
809 }
810
811
812 def get_fmt(x, locale, fmt='n'):
813 return Decimal.__format__(Decimal(x), fmt, _localeconv=locale)
814
815 self.assertEqual(get_fmt(Decimal('12.7'), en_US), '12.7')
816 self.assertEqual(get_fmt(Decimal('12.7'), fr_FR), '12,7')
817 self.assertEqual(get_fmt(Decimal('12.7'), ru_RU), '12,7')
818 self.assertEqual(get_fmt(Decimal('12.7'), crazy), '1-2&7')
819
820 self.assertEqual(get_fmt(123456789, en_US), '123,456,789')
821 self.assertEqual(get_fmt(123456789, fr_FR), '123456789')
822 self.assertEqual(get_fmt(123456789, ru_RU), '123 456 789')
823 self.assertEqual(get_fmt(1234567890123, crazy), '123456-78-9012-3')
824
825 self.assertEqual(get_fmt(123456789, en_US, '.6n'), '1.23457e+8')
826 self.assertEqual(get_fmt(123456789, fr_FR, '.6n'), '1,23457e+8')
827 self.assertEqual(get_fmt(123456789, ru_RU, '.6n'), '1,23457e+8')
828 self.assertEqual(get_fmt(123456789, crazy, '.6n'), '1&23457e+8')
829
Mark Dickinsonb14514a2009-03-18 08:22:51 +0000830 # zero padding
831 self.assertEqual(get_fmt(1234, fr_FR, '03n'), '1234')
832 self.assertEqual(get_fmt(1234, fr_FR, '04n'), '1234')
833 self.assertEqual(get_fmt(1234, fr_FR, '05n'), '01234')
834 self.assertEqual(get_fmt(1234, fr_FR, '06n'), '001234')
835
836 self.assertEqual(get_fmt(12345, en_US, '05n'), '12,345')
837 self.assertEqual(get_fmt(12345, en_US, '06n'), '12,345')
838 self.assertEqual(get_fmt(12345, en_US, '07n'), '012,345')
839 self.assertEqual(get_fmt(12345, en_US, '08n'), '0,012,345')
840 self.assertEqual(get_fmt(12345, en_US, '09n'), '0,012,345')
841 self.assertEqual(get_fmt(12345, en_US, '010n'), '00,012,345')
842
843 self.assertEqual(get_fmt(123456, crazy, '06n'), '1-2345-6')
844 self.assertEqual(get_fmt(123456, crazy, '07n'), '1-2345-6')
845 self.assertEqual(get_fmt(123456, crazy, '08n'), '1-2345-6')
846 self.assertEqual(get_fmt(123456, crazy, '09n'), '01-2345-6')
847 self.assertEqual(get_fmt(123456, crazy, '010n'), '0-01-2345-6')
848 self.assertEqual(get_fmt(123456, crazy, '011n'), '0-01-2345-6')
849 self.assertEqual(get_fmt(123456, crazy, '012n'), '00-01-2345-6')
850 self.assertEqual(get_fmt(123456, crazy, '013n'), '000-01-2345-6')
851
Mark Dickinson277859d2009-03-17 23:03:46 +0000852
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000853class DecimalArithmeticOperatorsTest(unittest.TestCase):
854 '''Unit tests for all arithmetic operators, binary and unary.'''
855
856 def test_addition(self):
857
858 d1 = Decimal('-11.1')
859 d2 = Decimal('22.2')
860
861 #two Decimals
862 self.assertEqual(d1+d2, Decimal('11.1'))
863 self.assertEqual(d2+d1, Decimal('11.1'))
864
865 #with other type, left
866 c = d1 + 5
867 self.assertEqual(c, Decimal('-6.1'))
868 self.assertEqual(type(c), type(d1))
869
870 #with other type, right
871 c = 5 + d1
872 self.assertEqual(c, Decimal('-6.1'))
873 self.assertEqual(type(c), type(d1))
874
875 #inline with decimal
876 d1 += d2
877 self.assertEqual(d1, Decimal('11.1'))
878
879 #inline with other type
880 d1 += 5
881 self.assertEqual(d1, Decimal('16.1'))
882
883 def test_subtraction(self):
884
885 d1 = Decimal('-11.1')
886 d2 = Decimal('22.2')
887
888 #two Decimals
889 self.assertEqual(d1-d2, Decimal('-33.3'))
890 self.assertEqual(d2-d1, Decimal('33.3'))
891
892 #with other type, left
893 c = d1 - 5
894 self.assertEqual(c, Decimal('-16.1'))
895 self.assertEqual(type(c), type(d1))
896
897 #with other type, right
898 c = 5 - d1
899 self.assertEqual(c, Decimal('16.1'))
900 self.assertEqual(type(c), type(d1))
901
902 #inline with decimal
903 d1 -= d2
904 self.assertEqual(d1, Decimal('-33.3'))
905
906 #inline with other type
907 d1 -= 5
908 self.assertEqual(d1, Decimal('-38.3'))
909
910 def test_multiplication(self):
911
912 d1 = Decimal('-5')
913 d2 = Decimal('3')
914
915 #two Decimals
916 self.assertEqual(d1*d2, Decimal('-15'))
917 self.assertEqual(d2*d1, Decimal('-15'))
918
919 #with other type, left
920 c = d1 * 5
921 self.assertEqual(c, Decimal('-25'))
922 self.assertEqual(type(c), type(d1))
923
924 #with other type, right
925 c = 5 * d1
926 self.assertEqual(c, Decimal('-25'))
927 self.assertEqual(type(c), type(d1))
928
929 #inline with decimal
930 d1 *= d2
931 self.assertEqual(d1, Decimal('-15'))
932
933 #inline with other type
934 d1 *= 5
935 self.assertEqual(d1, Decimal('-75'))
936
937 def test_division(self):
938
939 d1 = Decimal('-5')
940 d2 = Decimal('2')
941
942 #two Decimals
943 self.assertEqual(d1/d2, Decimal('-2.5'))
944 self.assertEqual(d2/d1, Decimal('-0.4'))
945
946 #with other type, left
947 c = d1 / 4
948 self.assertEqual(c, Decimal('-1.25'))
949 self.assertEqual(type(c), type(d1))
950
951 #with other type, right
952 c = 4 / d1
953 self.assertEqual(c, Decimal('-0.8'))
954 self.assertEqual(type(c), type(d1))
955
956 #inline with decimal
957 d1 /= d2
958 self.assertEqual(d1, Decimal('-2.5'))
959
960 #inline with other type
961 d1 /= 4
962 self.assertEqual(d1, Decimal('-0.625'))
963
964 def test_floor_division(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000965
966 d1 = Decimal('5')
967 d2 = Decimal('2')
968
969 #two Decimals
970 self.assertEqual(d1//d2, Decimal('2'))
971 self.assertEqual(d2//d1, Decimal('0'))
972
973 #with other type, left
974 c = d1 // 4
975 self.assertEqual(c, Decimal('1'))
976 self.assertEqual(type(c), type(d1))
977
978 #with other type, right
979 c = 7 // d1
980 self.assertEqual(c, Decimal('1'))
981 self.assertEqual(type(c), type(d1))
982
983 #inline with decimal
984 d1 //= d2
985 self.assertEqual(d1, Decimal('2'))
986
987 #inline with other type
988 d1 //= 2
989 self.assertEqual(d1, Decimal('1'))
990
991 def test_powering(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000992
993 d1 = Decimal('5')
994 d2 = Decimal('2')
995
996 #two Decimals
997 self.assertEqual(d1**d2, Decimal('25'))
998 self.assertEqual(d2**d1, Decimal('32'))
999
1000 #with other type, left
1001 c = d1 ** 4
1002 self.assertEqual(c, Decimal('625'))
1003 self.assertEqual(type(c), type(d1))
1004
1005 #with other type, right
1006 c = 7 ** d1
1007 self.assertEqual(c, Decimal('16807'))
1008 self.assertEqual(type(c), type(d1))
1009
1010 #inline with decimal
1011 d1 **= d2
1012 self.assertEqual(d1, Decimal('25'))
1013
1014 #inline with other type
1015 d1 **= 4
1016 self.assertEqual(d1, Decimal('390625'))
1017
1018 def test_module(self):
1019
1020 d1 = Decimal('5')
1021 d2 = Decimal('2')
1022
1023 #two Decimals
1024 self.assertEqual(d1%d2, Decimal('1'))
1025 self.assertEqual(d2%d1, Decimal('2'))
1026
1027 #with other type, left
1028 c = d1 % 4
1029 self.assertEqual(c, Decimal('1'))
1030 self.assertEqual(type(c), type(d1))
1031
1032 #with other type, right
1033 c = 7 % d1
1034 self.assertEqual(c, Decimal('2'))
1035 self.assertEqual(type(c), type(d1))
1036
1037 #inline with decimal
1038 d1 %= d2
1039 self.assertEqual(d1, Decimal('1'))
1040
1041 #inline with other type
1042 d1 %= 4
1043 self.assertEqual(d1, Decimal('1'))
1044
1045 def test_floor_div_module(self):
1046
1047 d1 = Decimal('5')
1048 d2 = Decimal('2')
1049
1050 #two Decimals
1051 (p, q) = divmod(d1, d2)
1052 self.assertEqual(p, Decimal('2'))
1053 self.assertEqual(q, Decimal('1'))
1054 self.assertEqual(type(p), type(d1))
1055 self.assertEqual(type(q), type(d1))
1056
1057 #with other type, left
1058 (p, q) = divmod(d1, 4)
1059 self.assertEqual(p, Decimal('1'))
1060 self.assertEqual(q, Decimal('1'))
1061 self.assertEqual(type(p), type(d1))
1062 self.assertEqual(type(q), type(d1))
1063
1064 #with other type, right
1065 (p, q) = divmod(7, d1)
1066 self.assertEqual(p, Decimal('1'))
1067 self.assertEqual(q, Decimal('2'))
1068 self.assertEqual(type(p), type(d1))
1069 self.assertEqual(type(q), type(d1))
1070
1071 def test_unary_operators(self):
1072 self.assertEqual(+Decimal(45), Decimal(+45)) # +
1073 self.assertEqual(-Decimal(45), Decimal(-45)) # -
1074 self.assertEqual(abs(Decimal(45)), abs(Decimal(-45))) # abs
1075
Mark Dickinson2fc92632008-02-06 22:10:50 +00001076 def test_nan_comparisons(self):
1077 n = Decimal('NaN')
1078 s = Decimal('sNaN')
1079 i = Decimal('Inf')
1080 f = Decimal('2')
1081 for x, y in [(n, n), (n, i), (i, n), (n, f), (f, n),
1082 (s, n), (n, s), (s, i), (i, s), (s, f), (f, s), (s, s)]:
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001083 self.assertTrue(x != y)
1084 self.assertTrue(not (x == y))
1085 self.assertTrue(not (x < y))
1086 self.assertTrue(not (x <= y))
1087 self.assertTrue(not (x > y))
1088 self.assertTrue(not (x >= y))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001089
Mark Dickinson6d8effb2010-02-18 14:27:02 +00001090 def test_copy_sign(self):
1091 d = Decimal(1).copy_sign(Decimal(-2))
1092
1093 self.assertEqual(Decimal(1).copy_sign(-2), d)
1094 self.assertRaises(TypeError, Decimal(1).copy_sign, '-2')
1095
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001096# The following are two functions used to test threading in the next class
1097
1098def thfunc1(cls):
1099 d1 = Decimal(1)
1100 d3 = Decimal(3)
Facundo Batista64156672008-03-22 02:45:37 +00001101 test1 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001102 cls.synchro.wait()
Facundo Batista64156672008-03-22 02:45:37 +00001103 test2 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001104 cls.finish1.set()
Facundo Batista64156672008-03-22 02:45:37 +00001105
Facundo Batistaee340e52008-05-02 17:39:00 +00001106 cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
1107 cls.assertEqual(test2, Decimal('0.3333333333333333333333333333'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001108 return
1109
1110def thfunc2(cls):
1111 d1 = Decimal(1)
1112 d3 = Decimal(3)
Facundo Batista64156672008-03-22 02:45:37 +00001113 test1 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001114 thiscontext = getcontext()
1115 thiscontext.prec = 18
Facundo Batista64156672008-03-22 02:45:37 +00001116 test2 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001117 cls.synchro.set()
1118 cls.finish2.set()
Facundo Batista64156672008-03-22 02:45:37 +00001119
Facundo Batistaee340e52008-05-02 17:39:00 +00001120 cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
Facundo Batista64156672008-03-22 02:45:37 +00001121 cls.assertEqual(test2, Decimal('0.333333333333333333'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001122 return
1123
1124
1125class DecimalUseOfContextTest(unittest.TestCase):
1126 '''Unit tests for Use of Context cases in Decimal.'''
1127
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001128 try:
1129 import threading
1130 except ImportError:
1131 threading = None
1132
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001133 # Take care executing this test from IDLE, there's an issue in threading
1134 # that hangs IDLE and I couldn't find it
1135
1136 def test_threading(self):
1137 #Test the "threading isolation" of a Context.
1138
1139 self.synchro = threading.Event()
1140 self.finish1 = threading.Event()
1141 self.finish2 = threading.Event()
1142
1143 th1 = threading.Thread(target=thfunc1, args=(self,))
1144 th2 = threading.Thread(target=thfunc2, args=(self,))
1145
1146 th1.start()
1147 th2.start()
1148
1149 self.finish1.wait()
Thomas Woutersb3e6e8c2007-09-19 17:27:29 +00001150 self.finish2.wait()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001151 return
1152
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001153 if threading is None:
1154 del test_threading
1155
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001156
1157class DecimalUsabilityTest(unittest.TestCase):
1158 '''Unit tests for Usability cases of Decimal.'''
1159
1160 def test_comparison_operators(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001161
1162 da = Decimal('23.42')
1163 db = Decimal('23.42')
1164 dc = Decimal('45')
1165
1166 #two Decimals
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001167 self.assertTrue(dc > da)
1168 self.assertTrue(dc >= da)
1169 self.assertTrue(da < dc)
1170 self.assertTrue(da <= dc)
1171 self.assertTrue(da == db)
1172 self.assertTrue(da != dc)
1173 self.assertTrue(da <= db)
1174 self.assertTrue(da >= db)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001175 self.assertEqual(cmp(dc,da), 1)
1176 self.assertEqual(cmp(da,dc), -1)
1177 self.assertEqual(cmp(da,db), 0)
1178
1179 #a Decimal and an int
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001180 self.assertTrue(dc > 23)
1181 self.assertTrue(23 < dc)
1182 self.assertTrue(dc == 45)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001183 self.assertEqual(cmp(dc,23), 1)
1184 self.assertEqual(cmp(23,dc), -1)
1185 self.assertEqual(cmp(dc,45), 0)
1186
1187 #a Decimal and uncomparable
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001188 self.assertNotEqual(da, 'ugly')
1189 self.assertNotEqual(da, 32.7)
1190 self.assertNotEqual(da, object())
1191 self.assertNotEqual(da, object)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001192
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001193 # sortable
1194 a = map(Decimal, xrange(100))
1195 b = a[:]
1196 random.shuffle(a)
1197 a.sort()
1198 self.assertEqual(a, b)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001199
Facundo Batista353750c2007-09-13 18:13:15 +00001200 # with None
Florent Xicluna8f43cec2010-03-21 10:51:40 +00001201 with check_py3k_warnings():
1202 self.assertFalse(Decimal(1) < None)
1203 self.assertTrue(Decimal(1) > None)
Facundo Batista353750c2007-09-13 18:13:15 +00001204
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001205 def test_copy_and_deepcopy_methods(self):
1206 d = Decimal('43.24')
1207 c = copy.copy(d)
1208 self.assertEqual(id(c), id(d))
1209 dc = copy.deepcopy(d)
1210 self.assertEqual(id(dc), id(d))
1211
1212 def test_hash_method(self):
1213 #just that it's hashable
1214 hash(Decimal(23))
Facundo Batista8c202442007-09-19 17:53:25 +00001215
1216 test_values = [Decimal(sign*(2**m + n))
1217 for m in [0, 14, 15, 16, 17, 30, 31,
1218 32, 33, 62, 63, 64, 65, 66]
1219 for n in range(-10, 10)
1220 for sign in [-1, 1]]
1221 test_values.extend([
1222 Decimal("-0"), # zeros
1223 Decimal("0.00"),
1224 Decimal("-0.000"),
1225 Decimal("0E10"),
1226 Decimal("-0E12"),
1227 Decimal("10.0"), # negative exponent
1228 Decimal("-23.00000"),
1229 Decimal("1230E100"), # positive exponent
1230 Decimal("-4.5678E50"),
1231 # a value for which hash(n) != hash(n % (2**64-1))
1232 # in Python pre-2.6
1233 Decimal(2**64 + 2**32 - 1),
1234 # selection of values which fail with the old (before
1235 # version 2.6) long.__hash__
1236 Decimal("1.634E100"),
1237 Decimal("90.697E100"),
1238 Decimal("188.83E100"),
1239 Decimal("1652.9E100"),
1240 Decimal("56531E100"),
1241 ])
1242
1243 # check that hash(d) == hash(int(d)) for integral values
1244 for value in test_values:
1245 self.assertEqual(hash(value), hash(int(value)))
1246
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001247 #the same hash that to an int
1248 self.assertEqual(hash(Decimal(23)), hash(23))
Raymond Hettingerbea3f6f2005-03-15 04:59:17 +00001249 self.assertRaises(TypeError, hash, Decimal('NaN'))
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001250 self.assertTrue(hash(Decimal('Inf')))
1251 self.assertTrue(hash(Decimal('-Inf')))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001252
Facundo Batista52b25792008-01-08 12:25:20 +00001253 # check that the value of the hash doesn't depend on the
1254 # current context (issue #1757)
1255 c = getcontext()
1256 old_precision = c.prec
1257 x = Decimal("123456789.1")
1258
1259 c.prec = 6
1260 h1 = hash(x)
1261 c.prec = 10
1262 h2 = hash(x)
1263 c.prec = 16
1264 h3 = hash(x)
1265
1266 self.assertEqual(h1, h2)
1267 self.assertEqual(h1, h3)
1268 c.prec = old_precision
1269
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001270 def test_min_and_max_methods(self):
1271
1272 d1 = Decimal('15.32')
1273 d2 = Decimal('28.5')
1274 l1 = 15
1275 l2 = 28
1276
1277 #between Decimals
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001278 self.assertTrue(min(d1,d2) is d1)
1279 self.assertTrue(min(d2,d1) is d1)
1280 self.assertTrue(max(d1,d2) is d2)
1281 self.assertTrue(max(d2,d1) is d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001282
1283 #between Decimal and long
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001284 self.assertTrue(min(d1,l2) is d1)
1285 self.assertTrue(min(l2,d1) is d1)
1286 self.assertTrue(max(l1,d2) is d2)
1287 self.assertTrue(max(d2,l1) is d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001288
1289 def test_as_nonzero(self):
1290 #as false
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001291 self.assertFalse(Decimal(0))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001292 #as true
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001293 self.assertTrue(Decimal('0.372'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001294
1295 def test_tostring_methods(self):
1296 #Test str and repr methods.
1297
1298 d = Decimal('15.32')
1299 self.assertEqual(str(d), '15.32') # str
Raymond Hettingerabe32372008-02-14 02:41:22 +00001300 self.assertEqual(repr(d), "Decimal('15.32')") # repr
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001301
Mark Dickinson8e85ffa2008-03-25 18:47:59 +00001302 # result type of string methods should be str, not unicode
1303 unicode_inputs = [u'123.4', u'0.5E2', u'Infinity', u'sNaN',
1304 u'-0.0E100', u'-NaN001', u'-Inf']
1305
1306 for u in unicode_inputs:
1307 d = Decimal(u)
1308 self.assertEqual(type(str(d)), str)
1309 self.assertEqual(type(repr(d)), str)
1310 self.assertEqual(type(d.to_eng_string()), str)
1311
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001312 def test_tonum_methods(self):
1313 #Test float, int and long methods.
1314
1315 d1 = Decimal('66')
1316 d2 = Decimal('15.32')
1317
1318 #int
1319 self.assertEqual(int(d1), 66)
1320 self.assertEqual(int(d2), 15)
1321
1322 #long
1323 self.assertEqual(long(d1), 66)
1324 self.assertEqual(long(d2), 15)
1325
1326 #float
1327 self.assertEqual(float(d1), 66)
1328 self.assertEqual(float(d2), 15.32)
1329
1330 def test_eval_round_trip(self):
1331
1332 #with zero
1333 d = Decimal( (0, (0,), 0) )
1334 self.assertEqual(d, eval(repr(d)))
1335
1336 #int
1337 d = Decimal( (1, (4, 5), 0) )
1338 self.assertEqual(d, eval(repr(d)))
1339
1340 #float
1341 d = Decimal( (0, (4, 5, 3, 4), -2) )
1342 self.assertEqual(d, eval(repr(d)))
1343
1344 #weird
1345 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1346 self.assertEqual(d, eval(repr(d)))
1347
1348 def test_as_tuple(self):
1349
1350 #with zero
1351 d = Decimal(0)
1352 self.assertEqual(d.as_tuple(), (0, (0,), 0) )
1353
1354 #int
1355 d = Decimal(-45)
1356 self.assertEqual(d.as_tuple(), (1, (4, 5), 0) )
1357
1358 #complicated string
1359 d = Decimal("-4.34913534E-17")
1360 self.assertEqual(d.as_tuple(), (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1361
1362 #inf
1363 d = Decimal("Infinity")
1364 self.assertEqual(d.as_tuple(), (0, (0,), 'F') )
1365
Facundo Batista9b5e2312007-10-19 19:25:57 +00001366 #leading zeros in coefficient should be stripped
1367 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), -2) )
1368 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), -2) )
1369 d = Decimal( (1, (0, 0, 0), 37) )
1370 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1371 d = Decimal( (1, (), 37) )
1372 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1373
1374 #leading zeros in NaN diagnostic info should be stripped
1375 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), 'n') )
1376 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), 'n') )
1377 d = Decimal( (1, (0, 0, 0), 'N') )
1378 self.assertEqual(d.as_tuple(), (1, (), 'N') )
1379 d = Decimal( (1, (), 'n') )
1380 self.assertEqual(d.as_tuple(), (1, (), 'n') )
1381
1382 #coefficient in infinity should be ignored
1383 d = Decimal( (0, (4, 5, 3, 4), 'F') )
1384 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
1385 d = Decimal( (1, (0, 2, 7, 1), 'F') )
1386 self.assertEqual(d.as_tuple(), (1, (0,), 'F'))
1387
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001388 def test_immutability_operations(self):
1389 # Do operations and check that it didn't change change internal objects.
1390
1391 d1 = Decimal('-25e55')
1392 b1 = Decimal('-25e55')
Facundo Batista353750c2007-09-13 18:13:15 +00001393 d2 = Decimal('33e+33')
1394 b2 = Decimal('33e+33')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001395
1396 def checkSameDec(operation, useOther=False):
1397 if useOther:
1398 eval("d1." + operation + "(d2)")
1399 self.assertEqual(d1._sign, b1._sign)
1400 self.assertEqual(d1._int, b1._int)
1401 self.assertEqual(d1._exp, b1._exp)
1402 self.assertEqual(d2._sign, b2._sign)
1403 self.assertEqual(d2._int, b2._int)
1404 self.assertEqual(d2._exp, b2._exp)
1405 else:
1406 eval("d1." + operation + "()")
1407 self.assertEqual(d1._sign, b1._sign)
1408 self.assertEqual(d1._int, b1._int)
1409 self.assertEqual(d1._exp, b1._exp)
1410 return
1411
1412 Decimal(d1)
1413 self.assertEqual(d1._sign, b1._sign)
1414 self.assertEqual(d1._int, b1._int)
1415 self.assertEqual(d1._exp, b1._exp)
1416
1417 checkSameDec("__abs__")
1418 checkSameDec("__add__", True)
1419 checkSameDec("__div__", True)
1420 checkSameDec("__divmod__", True)
Mark Dickinson2fc92632008-02-06 22:10:50 +00001421 checkSameDec("__eq__", True)
1422 checkSameDec("__ne__", True)
1423 checkSameDec("__le__", True)
1424 checkSameDec("__lt__", True)
1425 checkSameDec("__ge__", True)
1426 checkSameDec("__gt__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001427 checkSameDec("__float__")
1428 checkSameDec("__floordiv__", True)
1429 checkSameDec("__hash__")
1430 checkSameDec("__int__")
Raymond Hettinger5a053642008-01-24 19:05:29 +00001431 checkSameDec("__trunc__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001432 checkSameDec("__long__")
1433 checkSameDec("__mod__", True)
1434 checkSameDec("__mul__", True)
1435 checkSameDec("__neg__")
1436 checkSameDec("__nonzero__")
1437 checkSameDec("__pos__")
1438 checkSameDec("__pow__", True)
1439 checkSameDec("__radd__", True)
1440 checkSameDec("__rdiv__", True)
1441 checkSameDec("__rdivmod__", True)
1442 checkSameDec("__repr__")
1443 checkSameDec("__rfloordiv__", True)
1444 checkSameDec("__rmod__", True)
1445 checkSameDec("__rmul__", True)
1446 checkSameDec("__rpow__", True)
1447 checkSameDec("__rsub__", True)
1448 checkSameDec("__str__")
1449 checkSameDec("__sub__", True)
1450 checkSameDec("__truediv__", True)
1451 checkSameDec("adjusted")
1452 checkSameDec("as_tuple")
1453 checkSameDec("compare", True)
1454 checkSameDec("max", True)
1455 checkSameDec("min", True)
1456 checkSameDec("normalize")
1457 checkSameDec("quantize", True)
1458 checkSameDec("remainder_near", True)
1459 checkSameDec("same_quantum", True)
1460 checkSameDec("sqrt")
1461 checkSameDec("to_eng_string")
1462 checkSameDec("to_integral")
1463
Facundo Batista6c398da2007-09-17 17:30:13 +00001464 def test_subclassing(self):
1465 # Different behaviours when subclassing Decimal
1466
1467 class MyDecimal(Decimal):
1468 pass
1469
1470 d1 = MyDecimal(1)
1471 d2 = MyDecimal(2)
1472 d = d1 + d2
1473 self.assertTrue(type(d) is Decimal)
1474
1475 d = d1.max(d2)
1476 self.assertTrue(type(d) is Decimal)
1477
Mark Dickinson3b24ccb2008-03-25 14:33:23 +00001478 def test_implicit_context(self):
1479 # Check results when context given implicitly. (Issue 2478)
1480 c = getcontext()
1481 self.assertEqual(str(Decimal(0).sqrt()),
1482 str(c.sqrt(Decimal(0))))
1483
Mark Dickinson0c673122009-10-29 12:04:00 +00001484 def test_conversions_from_int(self):
1485 # Check that methods taking a second Decimal argument will
1486 # always accept an integer in place of a Decimal.
1487 self.assertEqual(Decimal(4).compare(3),
1488 Decimal(4).compare(Decimal(3)))
1489 self.assertEqual(Decimal(4).compare_signal(3),
1490 Decimal(4).compare_signal(Decimal(3)))
1491 self.assertEqual(Decimal(4).compare_total(3),
1492 Decimal(4).compare_total(Decimal(3)))
1493 self.assertEqual(Decimal(4).compare_total_mag(3),
1494 Decimal(4).compare_total_mag(Decimal(3)))
1495 self.assertEqual(Decimal(10101).logical_and(1001),
1496 Decimal(10101).logical_and(Decimal(1001)))
1497 self.assertEqual(Decimal(10101).logical_or(1001),
1498 Decimal(10101).logical_or(Decimal(1001)))
1499 self.assertEqual(Decimal(10101).logical_xor(1001),
1500 Decimal(10101).logical_xor(Decimal(1001)))
1501 self.assertEqual(Decimal(567).max(123),
1502 Decimal(567).max(Decimal(123)))
1503 self.assertEqual(Decimal(567).max_mag(123),
1504 Decimal(567).max_mag(Decimal(123)))
1505 self.assertEqual(Decimal(567).min(123),
1506 Decimal(567).min(Decimal(123)))
1507 self.assertEqual(Decimal(567).min_mag(123),
1508 Decimal(567).min_mag(Decimal(123)))
1509 self.assertEqual(Decimal(567).next_toward(123),
1510 Decimal(567).next_toward(Decimal(123)))
1511 self.assertEqual(Decimal(1234).quantize(100),
1512 Decimal(1234).quantize(Decimal(100)))
1513 self.assertEqual(Decimal(768).remainder_near(1234),
1514 Decimal(768).remainder_near(Decimal(1234)))
1515 self.assertEqual(Decimal(123).rotate(1),
1516 Decimal(123).rotate(Decimal(1)))
1517 self.assertEqual(Decimal(1234).same_quantum(1000),
1518 Decimal(1234).same_quantum(Decimal(1000)))
1519 self.assertEqual(Decimal('9.123').scaleb(-100),
1520 Decimal('9.123').scaleb(Decimal(-100)))
1521 self.assertEqual(Decimal(456).shift(-1),
1522 Decimal(456).shift(Decimal(-1)))
1523
1524 self.assertEqual(Decimal(-12).fma(Decimal(45), 67),
1525 Decimal(-12).fma(Decimal(45), Decimal(67)))
1526 self.assertEqual(Decimal(-12).fma(45, 67),
1527 Decimal(-12).fma(Decimal(45), Decimal(67)))
1528 self.assertEqual(Decimal(-12).fma(45, Decimal(67)),
1529 Decimal(-12).fma(Decimal(45), Decimal(67)))
1530
Facundo Batista6c398da2007-09-17 17:30:13 +00001531
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001532class DecimalPythonAPItests(unittest.TestCase):
1533
Raymond Hettinger2c8585b2009-02-03 03:37:03 +00001534 def test_abc(self):
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001535 self.assertTrue(issubclass(Decimal, numbers.Number))
1536 self.assertTrue(not issubclass(Decimal, numbers.Real))
Ezio Melottib0f5adc2010-01-24 16:58:36 +00001537 self.assertIsInstance(Decimal(0), numbers.Number)
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001538 self.assertTrue(not isinstance(Decimal(0), numbers.Real))
Raymond Hettinger2c8585b2009-02-03 03:37:03 +00001539
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001540 def test_pickle(self):
1541 d = Decimal('-3.141590000')
1542 p = pickle.dumps(d)
1543 e = pickle.loads(p)
1544 self.assertEqual(d, e)
1545
Raymond Hettinger5548be22004-07-05 18:49:38 +00001546 def test_int(self):
Raymond Hettinger605ed022004-11-24 07:28:48 +00001547 for x in range(-250, 250):
1548 s = '%0.2f' % (x / 100.0)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001549 # should work the same as for floats
1550 self.assertEqual(int(Decimal(s)), int(float(s)))
Raymond Hettinger605ed022004-11-24 07:28:48 +00001551 # should work the same as to_integral in the ROUND_DOWN mode
Raymond Hettinger5548be22004-07-05 18:49:38 +00001552 d = Decimal(s)
Raymond Hettinger605ed022004-11-24 07:28:48 +00001553 r = d.to_integral(ROUND_DOWN)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001554 self.assertEqual(Decimal(int(d)), r)
1555
Mark Dickinson968f1692009-09-07 18:04:58 +00001556 self.assertRaises(ValueError, int, Decimal('-nan'))
1557 self.assertRaises(ValueError, int, Decimal('snan'))
1558 self.assertRaises(OverflowError, int, Decimal('inf'))
1559 self.assertRaises(OverflowError, int, Decimal('-inf'))
1560
1561 self.assertRaises(ValueError, long, Decimal('-nan'))
1562 self.assertRaises(ValueError, long, Decimal('snan'))
1563 self.assertRaises(OverflowError, long, Decimal('inf'))
1564 self.assertRaises(OverflowError, long, Decimal('-inf'))
1565
Raymond Hettinger5a053642008-01-24 19:05:29 +00001566 def test_trunc(self):
1567 for x in range(-250, 250):
1568 s = '%0.2f' % (x / 100.0)
1569 # should work the same as for floats
1570 self.assertEqual(int(Decimal(s)), int(float(s)))
1571 # should work the same as to_integral in the ROUND_DOWN mode
1572 d = Decimal(s)
1573 r = d.to_integral(ROUND_DOWN)
Jeffrey Yasskinca2b69f2008-02-01 06:22:46 +00001574 self.assertEqual(Decimal(math.trunc(d)), r)
Raymond Hettinger5a053642008-01-24 19:05:29 +00001575
Raymond Hettingerf4d85972009-01-03 19:02:23 +00001576 def test_from_float(self):
1577
1578 class MyDecimal(Decimal):
1579 pass
1580
1581 r = MyDecimal.from_float(0.1)
1582 self.assertEqual(type(r), MyDecimal)
1583 self.assertEqual(str(r),
1584 '0.1000000000000000055511151231257827021181583404541015625')
1585 bigint = 12345678901234567890123456789
1586 self.assertEqual(MyDecimal.from_float(bigint), MyDecimal(bigint))
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001587 self.assertTrue(MyDecimal.from_float(float('nan')).is_qnan())
1588 self.assertTrue(MyDecimal.from_float(float('inf')).is_infinite())
1589 self.assertTrue(MyDecimal.from_float(float('-inf')).is_infinite())
Raymond Hettingerf4d85972009-01-03 19:02:23 +00001590 self.assertEqual(str(MyDecimal.from_float(float('nan'))),
1591 str(Decimal('NaN')))
1592 self.assertEqual(str(MyDecimal.from_float(float('inf'))),
1593 str(Decimal('Infinity')))
1594 self.assertEqual(str(MyDecimal.from_float(float('-inf'))),
1595 str(Decimal('-Infinity')))
1596 self.assertRaises(TypeError, MyDecimal.from_float, 'abc')
1597 for i in range(200):
1598 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
1599 self.assertEqual(x, float(MyDecimal.from_float(x))) # roundtrip
1600
1601 def test_create_decimal_from_float(self):
1602 context = Context(prec=5, rounding=ROUND_DOWN)
1603 self.assertEqual(
1604 context.create_decimal_from_float(math.pi),
1605 Decimal('3.1415')
1606 )
1607 context = Context(prec=5, rounding=ROUND_UP)
1608 self.assertEqual(
1609 context.create_decimal_from_float(math.pi),
1610 Decimal('3.1416')
1611 )
1612 context = Context(prec=5, traps=[Inexact])
1613 self.assertRaises(
1614 Inexact,
1615 context.create_decimal_from_float,
1616 math.pi
1617 )
1618 self.assertEqual(repr(context.create_decimal_from_float(-0.0)),
1619 "Decimal('-0')")
1620 self.assertEqual(repr(context.create_decimal_from_float(1.0)),
1621 "Decimal('1')")
1622 self.assertEqual(repr(context.create_decimal_from_float(10)),
1623 "Decimal('10')")
1624
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00001625class ContextAPItests(unittest.TestCase):
1626
1627 def test_pickle(self):
1628 c = Context()
1629 e = pickle.loads(pickle.dumps(c))
1630 for k in vars(c):
1631 v1 = vars(c)[k]
1632 v2 = vars(e)[k]
1633 self.assertEqual(v1, v2)
1634
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001635 def test_equality_with_other_types(self):
Ezio Melottiaa980582010-01-23 23:04:36 +00001636 self.assertIn(Decimal(10), ['a', 1.0, Decimal(10), (1,2), {}])
1637 self.assertNotIn(Decimal(10), ['a', 1.0, (1,2), {}])
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001638
Raymond Hettinger955d2b22004-08-08 20:17:45 +00001639 def test_copy(self):
1640 # All copies should be deep
1641 c = Context()
1642 d = c.copy()
1643 self.assertNotEqual(id(c), id(d))
1644 self.assertNotEqual(id(c.flags), id(d.flags))
1645 self.assertNotEqual(id(c.traps), id(d.traps))
1646
Mark Dickinson6d8effb2010-02-18 14:27:02 +00001647 def test_abs(self):
1648 c = Context()
1649 d = c.abs(Decimal(-1))
1650 self.assertEqual(c.abs(-1), d)
1651 self.assertRaises(TypeError, c.abs, '-1')
1652
1653 def test_add(self):
1654 c = Context()
1655 d = c.add(Decimal(1), Decimal(1))
1656 self.assertEqual(c.add(1, 1), d)
1657 self.assertEqual(c.add(Decimal(1), 1), d)
1658 self.assertEqual(c.add(1, Decimal(1)), d)
1659 self.assertRaises(TypeError, c.add, '1', 1)
1660 self.assertRaises(TypeError, c.add, 1, '1')
1661
1662 def test_compare(self):
1663 c = Context()
1664 d = c.compare(Decimal(1), Decimal(1))
1665 self.assertEqual(c.compare(1, 1), d)
1666 self.assertEqual(c.compare(Decimal(1), 1), d)
1667 self.assertEqual(c.compare(1, Decimal(1)), d)
1668 self.assertRaises(TypeError, c.compare, '1', 1)
1669 self.assertRaises(TypeError, c.compare, 1, '1')
1670
1671 def test_compare_signal(self):
1672 c = Context()
1673 d = c.compare_signal(Decimal(1), Decimal(1))
1674 self.assertEqual(c.compare_signal(1, 1), d)
1675 self.assertEqual(c.compare_signal(Decimal(1), 1), d)
1676 self.assertEqual(c.compare_signal(1, Decimal(1)), d)
1677 self.assertRaises(TypeError, c.compare_signal, '1', 1)
1678 self.assertRaises(TypeError, c.compare_signal, 1, '1')
1679
1680 def test_compare_total(self):
1681 c = Context()
1682 d = c.compare_total(Decimal(1), Decimal(1))
1683 self.assertEqual(c.compare_total(1, 1), d)
1684 self.assertEqual(c.compare_total(Decimal(1), 1), d)
1685 self.assertEqual(c.compare_total(1, Decimal(1)), d)
1686 self.assertRaises(TypeError, c.compare_total, '1', 1)
1687 self.assertRaises(TypeError, c.compare_total, 1, '1')
1688
1689 def test_compare_total_mag(self):
1690 c = Context()
1691 d = c.compare_total_mag(Decimal(1), Decimal(1))
1692 self.assertEqual(c.compare_total_mag(1, 1), d)
1693 self.assertEqual(c.compare_total_mag(Decimal(1), 1), d)
1694 self.assertEqual(c.compare_total_mag(1, Decimal(1)), d)
1695 self.assertRaises(TypeError, c.compare_total_mag, '1', 1)
1696 self.assertRaises(TypeError, c.compare_total_mag, 1, '1')
1697
1698 def test_copy_abs(self):
1699 c = Context()
1700 d = c.copy_abs(Decimal(-1))
1701 self.assertEqual(c.copy_abs(-1), d)
1702 self.assertRaises(TypeError, c.copy_abs, '-1')
1703
1704 def test_copy_decimal(self):
1705 c = Context()
1706 d = c.copy_decimal(Decimal(-1))
1707 self.assertEqual(c.copy_decimal(-1), d)
1708 self.assertRaises(TypeError, c.copy_decimal, '-1')
1709
1710 def test_copy_negate(self):
1711 c = Context()
1712 d = c.copy_negate(Decimal(-1))
1713 self.assertEqual(c.copy_negate(-1), d)
1714 self.assertRaises(TypeError, c.copy_negate, '-1')
1715
1716 def test_copy_sign(self):
1717 c = Context()
1718 d = c.copy_sign(Decimal(1), Decimal(-2))
1719 self.assertEqual(c.copy_sign(1, -2), d)
1720 self.assertEqual(c.copy_sign(Decimal(1), -2), d)
1721 self.assertEqual(c.copy_sign(1, Decimal(-2)), d)
1722 self.assertRaises(TypeError, c.copy_sign, '1', -2)
1723 self.assertRaises(TypeError, c.copy_sign, 1, '-2')
1724
1725 def test_divide(self):
1726 c = Context()
1727 d = c.divide(Decimal(1), Decimal(2))
1728 self.assertEqual(c.divide(1, 2), d)
1729 self.assertEqual(c.divide(Decimal(1), 2), d)
1730 self.assertEqual(c.divide(1, Decimal(2)), d)
1731 self.assertRaises(TypeError, c.divide, '1', 2)
1732 self.assertRaises(TypeError, c.divide, 1, '2')
1733
1734 def test_divide_int(self):
1735 c = Context()
1736 d = c.divide_int(Decimal(1), Decimal(2))
1737 self.assertEqual(c.divide_int(1, 2), d)
1738 self.assertEqual(c.divide_int(Decimal(1), 2), d)
1739 self.assertEqual(c.divide_int(1, Decimal(2)), d)
1740 self.assertRaises(TypeError, c.divide_int, '1', 2)
1741 self.assertRaises(TypeError, c.divide_int, 1, '2')
1742
1743 def test_divmod(self):
1744 c = Context()
1745 d = c.divmod(Decimal(1), Decimal(2))
1746 self.assertEqual(c.divmod(1, 2), d)
1747 self.assertEqual(c.divmod(Decimal(1), 2), d)
1748 self.assertEqual(c.divmod(1, Decimal(2)), d)
1749 self.assertRaises(TypeError, c.divmod, '1', 2)
1750 self.assertRaises(TypeError, c.divmod, 1, '2')
1751
1752 def test_exp(self):
1753 c = Context()
1754 d = c.exp(Decimal(10))
1755 self.assertEqual(c.exp(10), d)
1756 self.assertRaises(TypeError, c.exp, '10')
1757
1758 def test_fma(self):
1759 c = Context()
1760 d = c.fma(Decimal(2), Decimal(3), Decimal(4))
1761 self.assertEqual(c.fma(2, 3, 4), d)
1762 self.assertEqual(c.fma(Decimal(2), 3, 4), d)
1763 self.assertEqual(c.fma(2, Decimal(3), 4), d)
1764 self.assertEqual(c.fma(2, 3, Decimal(4)), d)
1765 self.assertEqual(c.fma(Decimal(2), Decimal(3), 4), d)
1766 self.assertRaises(TypeError, c.fma, '2', 3, 4)
1767 self.assertRaises(TypeError, c.fma, 2, '3', 4)
1768 self.assertRaises(TypeError, c.fma, 2, 3, '4')
1769
1770 def test_is_finite(self):
1771 c = Context()
1772 d = c.is_finite(Decimal(10))
1773 self.assertEqual(c.is_finite(10), d)
1774 self.assertRaises(TypeError, c.is_finite, '10')
1775
1776 def test_is_infinite(self):
1777 c = Context()
1778 d = c.is_infinite(Decimal(10))
1779 self.assertEqual(c.is_infinite(10), d)
1780 self.assertRaises(TypeError, c.is_infinite, '10')
1781
1782 def test_is_nan(self):
1783 c = Context()
1784 d = c.is_nan(Decimal(10))
1785 self.assertEqual(c.is_nan(10), d)
1786 self.assertRaises(TypeError, c.is_nan, '10')
1787
1788 def test_is_normal(self):
1789 c = Context()
1790 d = c.is_normal(Decimal(10))
1791 self.assertEqual(c.is_normal(10), d)
1792 self.assertRaises(TypeError, c.is_normal, '10')
1793
1794 def test_is_qnan(self):
1795 c = Context()
1796 d = c.is_qnan(Decimal(10))
1797 self.assertEqual(c.is_qnan(10), d)
1798 self.assertRaises(TypeError, c.is_qnan, '10')
1799
1800 def test_is_signed(self):
1801 c = Context()
1802 d = c.is_signed(Decimal(10))
1803 self.assertEqual(c.is_signed(10), d)
1804 self.assertRaises(TypeError, c.is_signed, '10')
1805
1806 def test_is_snan(self):
1807 c = Context()
1808 d = c.is_snan(Decimal(10))
1809 self.assertEqual(c.is_snan(10), d)
1810 self.assertRaises(TypeError, c.is_snan, '10')
1811
1812 def test_is_subnormal(self):
1813 c = Context()
1814 d = c.is_subnormal(Decimal(10))
1815 self.assertEqual(c.is_subnormal(10), d)
1816 self.assertRaises(TypeError, c.is_subnormal, '10')
1817
1818 def test_is_zero(self):
1819 c = Context()
1820 d = c.is_zero(Decimal(10))
1821 self.assertEqual(c.is_zero(10), d)
1822 self.assertRaises(TypeError, c.is_zero, '10')
1823
1824 def test_ln(self):
1825 c = Context()
1826 d = c.ln(Decimal(10))
1827 self.assertEqual(c.ln(10), d)
1828 self.assertRaises(TypeError, c.ln, '10')
1829
1830 def test_log10(self):
1831 c = Context()
1832 d = c.log10(Decimal(10))
1833 self.assertEqual(c.log10(10), d)
1834 self.assertRaises(TypeError, c.log10, '10')
1835
1836 def test_logb(self):
1837 c = Context()
1838 d = c.logb(Decimal(10))
1839 self.assertEqual(c.logb(10), d)
1840 self.assertRaises(TypeError, c.logb, '10')
1841
1842 def test_logical_and(self):
1843 c = Context()
1844 d = c.logical_and(Decimal(1), Decimal(1))
1845 self.assertEqual(c.logical_and(1, 1), d)
1846 self.assertEqual(c.logical_and(Decimal(1), 1), d)
1847 self.assertEqual(c.logical_and(1, Decimal(1)), d)
1848 self.assertRaises(TypeError, c.logical_and, '1', 1)
1849 self.assertRaises(TypeError, c.logical_and, 1, '1')
1850
1851 def test_logical_invert(self):
1852 c = Context()
1853 d = c.logical_invert(Decimal(1000))
1854 self.assertEqual(c.logical_invert(1000), d)
1855 self.assertRaises(TypeError, c.logical_invert, '1000')
1856
1857 def test_logical_or(self):
1858 c = Context()
1859 d = c.logical_or(Decimal(1), Decimal(1))
1860 self.assertEqual(c.logical_or(1, 1), d)
1861 self.assertEqual(c.logical_or(Decimal(1), 1), d)
1862 self.assertEqual(c.logical_or(1, Decimal(1)), d)
1863 self.assertRaises(TypeError, c.logical_or, '1', 1)
1864 self.assertRaises(TypeError, c.logical_or, 1, '1')
1865
1866 def test_logical_xor(self):
1867 c = Context()
1868 d = c.logical_xor(Decimal(1), Decimal(1))
1869 self.assertEqual(c.logical_xor(1, 1), d)
1870 self.assertEqual(c.logical_xor(Decimal(1), 1), d)
1871 self.assertEqual(c.logical_xor(1, Decimal(1)), d)
1872 self.assertRaises(TypeError, c.logical_xor, '1', 1)
1873 self.assertRaises(TypeError, c.logical_xor, 1, '1')
1874
1875 def test_max(self):
1876 c = Context()
1877 d = c.max(Decimal(1), Decimal(2))
1878 self.assertEqual(c.max(1, 2), d)
1879 self.assertEqual(c.max(Decimal(1), 2), d)
1880 self.assertEqual(c.max(1, Decimal(2)), d)
1881 self.assertRaises(TypeError, c.max, '1', 2)
1882 self.assertRaises(TypeError, c.max, 1, '2')
1883
1884 def test_max_mag(self):
1885 c = Context()
1886 d = c.max_mag(Decimal(1), Decimal(2))
1887 self.assertEqual(c.max_mag(1, 2), d)
1888 self.assertEqual(c.max_mag(Decimal(1), 2), d)
1889 self.assertEqual(c.max_mag(1, Decimal(2)), d)
1890 self.assertRaises(TypeError, c.max_mag, '1', 2)
1891 self.assertRaises(TypeError, c.max_mag, 1, '2')
1892
1893 def test_min(self):
1894 c = Context()
1895 d = c.min(Decimal(1), Decimal(2))
1896 self.assertEqual(c.min(1, 2), d)
1897 self.assertEqual(c.min(Decimal(1), 2), d)
1898 self.assertEqual(c.min(1, Decimal(2)), d)
1899 self.assertRaises(TypeError, c.min, '1', 2)
1900 self.assertRaises(TypeError, c.min, 1, '2')
1901
1902 def test_min_mag(self):
1903 c = Context()
1904 d = c.min_mag(Decimal(1), Decimal(2))
1905 self.assertEqual(c.min_mag(1, 2), d)
1906 self.assertEqual(c.min_mag(Decimal(1), 2), d)
1907 self.assertEqual(c.min_mag(1, Decimal(2)), d)
1908 self.assertRaises(TypeError, c.min_mag, '1', 2)
1909 self.assertRaises(TypeError, c.min_mag, 1, '2')
1910
1911 def test_minus(self):
1912 c = Context()
1913 d = c.minus(Decimal(10))
1914 self.assertEqual(c.minus(10), d)
1915 self.assertRaises(TypeError, c.minus, '10')
1916
1917 def test_multiply(self):
1918 c = Context()
1919 d = c.multiply(Decimal(1), Decimal(2))
1920 self.assertEqual(c.multiply(1, 2), d)
1921 self.assertEqual(c.multiply(Decimal(1), 2), d)
1922 self.assertEqual(c.multiply(1, Decimal(2)), d)
1923 self.assertRaises(TypeError, c.multiply, '1', 2)
1924 self.assertRaises(TypeError, c.multiply, 1, '2')
1925
1926 def test_next_minus(self):
1927 c = Context()
1928 d = c.next_minus(Decimal(10))
1929 self.assertEqual(c.next_minus(10), d)
1930 self.assertRaises(TypeError, c.next_minus, '10')
1931
1932 def test_next_plus(self):
1933 c = Context()
1934 d = c.next_plus(Decimal(10))
1935 self.assertEqual(c.next_plus(10), d)
1936 self.assertRaises(TypeError, c.next_plus, '10')
1937
1938 def test_next_toward(self):
1939 c = Context()
1940 d = c.next_toward(Decimal(1), Decimal(2))
1941 self.assertEqual(c.next_toward(1, 2), d)
1942 self.assertEqual(c.next_toward(Decimal(1), 2), d)
1943 self.assertEqual(c.next_toward(1, Decimal(2)), d)
1944 self.assertRaises(TypeError, c.next_toward, '1', 2)
1945 self.assertRaises(TypeError, c.next_toward, 1, '2')
1946
1947 def test_normalize(self):
1948 c = Context()
1949 d = c.normalize(Decimal(10))
1950 self.assertEqual(c.normalize(10), d)
1951 self.assertRaises(TypeError, c.normalize, '10')
1952
1953 def test_number_class(self):
1954 c = Context()
1955 self.assertEqual(c.number_class(123), c.number_class(Decimal(123)))
1956 self.assertEqual(c.number_class(0), c.number_class(Decimal(0)))
1957 self.assertEqual(c.number_class(-45), c.number_class(Decimal(-45)))
1958
1959 def test_power(self):
1960 c = Context()
1961 d = c.power(Decimal(1), Decimal(4), Decimal(2))
1962 self.assertEqual(c.power(1, 4, 2), d)
1963 self.assertEqual(c.power(Decimal(1), 4, 2), d)
1964 self.assertEqual(c.power(1, Decimal(4), 2), d)
1965 self.assertEqual(c.power(1, 4, Decimal(2)), d)
1966 self.assertEqual(c.power(Decimal(1), Decimal(4), 2), d)
1967 self.assertRaises(TypeError, c.power, '1', 4, 2)
1968 self.assertRaises(TypeError, c.power, 1, '4', 2)
1969 self.assertRaises(TypeError, c.power, 1, 4, '2')
1970
1971 def test_plus(self):
1972 c = Context()
1973 d = c.plus(Decimal(10))
1974 self.assertEqual(c.plus(10), d)
1975 self.assertRaises(TypeError, c.plus, '10')
1976
1977 def test_quantize(self):
1978 c = Context()
1979 d = c.quantize(Decimal(1), Decimal(2))
1980 self.assertEqual(c.quantize(1, 2), d)
1981 self.assertEqual(c.quantize(Decimal(1), 2), d)
1982 self.assertEqual(c.quantize(1, Decimal(2)), d)
1983 self.assertRaises(TypeError, c.quantize, '1', 2)
1984 self.assertRaises(TypeError, c.quantize, 1, '2')
1985
1986 def test_remainder(self):
1987 c = Context()
1988 d = c.remainder(Decimal(1), Decimal(2))
1989 self.assertEqual(c.remainder(1, 2), d)
1990 self.assertEqual(c.remainder(Decimal(1), 2), d)
1991 self.assertEqual(c.remainder(1, Decimal(2)), d)
1992 self.assertRaises(TypeError, c.remainder, '1', 2)
1993 self.assertRaises(TypeError, c.remainder, 1, '2')
1994
1995 def test_remainder_near(self):
1996 c = Context()
1997 d = c.remainder_near(Decimal(1), Decimal(2))
1998 self.assertEqual(c.remainder_near(1, 2), d)
1999 self.assertEqual(c.remainder_near(Decimal(1), 2), d)
2000 self.assertEqual(c.remainder_near(1, Decimal(2)), d)
2001 self.assertRaises(TypeError, c.remainder_near, '1', 2)
2002 self.assertRaises(TypeError, c.remainder_near, 1, '2')
2003
2004 def test_rotate(self):
2005 c = Context()
2006 d = c.rotate(Decimal(1), Decimal(2))
2007 self.assertEqual(c.rotate(1, 2), d)
2008 self.assertEqual(c.rotate(Decimal(1), 2), d)
2009 self.assertEqual(c.rotate(1, Decimal(2)), d)
2010 self.assertRaises(TypeError, c.rotate, '1', 2)
2011 self.assertRaises(TypeError, c.rotate, 1, '2')
2012
2013 def test_sqrt(self):
2014 c = Context()
2015 d = c.sqrt(Decimal(10))
2016 self.assertEqual(c.sqrt(10), d)
2017 self.assertRaises(TypeError, c.sqrt, '10')
2018
2019 def test_same_quantum(self):
2020 c = Context()
2021 d = c.same_quantum(Decimal(1), Decimal(2))
2022 self.assertEqual(c.same_quantum(1, 2), d)
2023 self.assertEqual(c.same_quantum(Decimal(1), 2), d)
2024 self.assertEqual(c.same_quantum(1, Decimal(2)), d)
2025 self.assertRaises(TypeError, c.same_quantum, '1', 2)
2026 self.assertRaises(TypeError, c.same_quantum, 1, '2')
2027
2028 def test_scaleb(self):
2029 c = Context()
2030 d = c.scaleb(Decimal(1), Decimal(2))
2031 self.assertEqual(c.scaleb(1, 2), d)
2032 self.assertEqual(c.scaleb(Decimal(1), 2), d)
2033 self.assertEqual(c.scaleb(1, Decimal(2)), d)
2034 self.assertRaises(TypeError, c.scaleb, '1', 2)
2035 self.assertRaises(TypeError, c.scaleb, 1, '2')
2036
2037 def test_shift(self):
2038 c = Context()
2039 d = c.shift(Decimal(1), Decimal(2))
2040 self.assertEqual(c.shift(1, 2), d)
2041 self.assertEqual(c.shift(Decimal(1), 2), d)
2042 self.assertEqual(c.shift(1, Decimal(2)), d)
2043 self.assertRaises(TypeError, c.shift, '1', 2)
2044 self.assertRaises(TypeError, c.shift, 1, '2')
2045
2046 def test_subtract(self):
2047 c = Context()
2048 d = c.subtract(Decimal(1), Decimal(2))
2049 self.assertEqual(c.subtract(1, 2), d)
2050 self.assertEqual(c.subtract(Decimal(1), 2), d)
2051 self.assertEqual(c.subtract(1, Decimal(2)), d)
2052 self.assertRaises(TypeError, c.subtract, '1', 2)
2053 self.assertRaises(TypeError, c.subtract, 1, '2')
2054
2055 def test_to_eng_string(self):
2056 c = Context()
2057 d = c.to_eng_string(Decimal(10))
2058 self.assertEqual(c.to_eng_string(10), d)
2059 self.assertRaises(TypeError, c.to_eng_string, '10')
2060
2061 def test_to_sci_string(self):
2062 c = Context()
2063 d = c.to_sci_string(Decimal(10))
2064 self.assertEqual(c.to_sci_string(10), d)
2065 self.assertRaises(TypeError, c.to_sci_string, '10')
2066
2067 def test_to_integral_exact(self):
2068 c = Context()
2069 d = c.to_integral_exact(Decimal(10))
2070 self.assertEqual(c.to_integral_exact(10), d)
2071 self.assertRaises(TypeError, c.to_integral_exact, '10')
2072
2073 def test_to_integral_value(self):
2074 c = Context()
2075 d = c.to_integral_value(Decimal(10))
2076 self.assertEqual(c.to_integral_value(10), d)
2077 self.assertRaises(TypeError, c.to_integral_value, '10')
2078
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002079class WithStatementTest(unittest.TestCase):
2080 # Can't do these as docstrings until Python 2.6
2081 # as doctest can't handle __future__ statements
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002082
2083 def test_localcontext(self):
Nick Coghlanced12182006-09-02 03:54:17 +00002084 # Use a copy of the current context in the block
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002085 orig_ctx = getcontext()
2086 with localcontext() as enter_ctx:
2087 set_ctx = getcontext()
2088 final_ctx = getcontext()
Benjamin Peterson5c8da862009-06-30 22:57:08 +00002089 self.assertTrue(orig_ctx is final_ctx, 'did not restore context correctly')
2090 self.assertTrue(orig_ctx is not set_ctx, 'did not copy the context')
2091 self.assertTrue(set_ctx is enter_ctx, '__enter__ returned wrong context')
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002092
2093 def test_localcontextarg(self):
Nick Coghlanced12182006-09-02 03:54:17 +00002094 # Use a copy of the supplied context in the block
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002095 orig_ctx = getcontext()
2096 new_ctx = Context(prec=42)
2097 with localcontext(new_ctx) as enter_ctx:
2098 set_ctx = getcontext()
2099 final_ctx = getcontext()
Benjamin Peterson5c8da862009-06-30 22:57:08 +00002100 self.assertTrue(orig_ctx is final_ctx, 'did not restore context correctly')
2101 self.assertTrue(set_ctx.prec == new_ctx.prec, 'did not set correct context')
2102 self.assertTrue(new_ctx is not set_ctx, 'did not copy the context')
2103 self.assertTrue(set_ctx is enter_ctx, '__enter__ returned wrong context')
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002104
Facundo Batista353750c2007-09-13 18:13:15 +00002105class ContextFlags(unittest.TestCase):
2106 def test_flags_irrelevant(self):
2107 # check that the result (numeric result + flags raised) of an
2108 # arithmetic operation doesn't depend on the current flags
2109
2110 context = Context(prec=9, Emin = -999999999, Emax = 999999999,
2111 rounding=ROUND_HALF_EVEN, traps=[], flags=[])
2112
2113 # operations that raise various flags, in the form (function, arglist)
2114 operations = [
2115 (context._apply, [Decimal("100E-1000000009")]),
2116 (context.sqrt, [Decimal(2)]),
2117 (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]),
2118 (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]),
2119 (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]),
2120 ]
2121
2122 # try various flags individually, then a whole lot at once
2123 flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal],
2124 [Inexact, Rounded, Underflow, Clamped, Subnormal]]
2125
2126 for fn, args in operations:
2127 # find answer and flags raised using a clean context
2128 context.clear_flags()
2129 ans = fn(*args)
2130 flags = [k for k, v in context.flags.items() if v]
2131
2132 for extra_flags in flagsets:
2133 # set flags, before calling operation
2134 context.clear_flags()
2135 for flag in extra_flags:
2136 context._raise_error(flag)
2137 new_ans = fn(*args)
2138
2139 # flags that we expect to be set after the operation
2140 expected_flags = list(flags)
2141 for flag in extra_flags:
2142 if flag not in expected_flags:
2143 expected_flags.append(flag)
Facundo Batista353750c2007-09-13 18:13:15 +00002144
2145 # flags we actually got
2146 new_flags = [k for k,v in context.flags.items() if v]
Facundo Batista353750c2007-09-13 18:13:15 +00002147
2148 self.assertEqual(ans, new_ans,
2149 "operation produces different answers depending on flags set: " +
2150 "expected %s, got %s." % (ans, new_ans))
Florent Xicluna8f43cec2010-03-21 10:51:40 +00002151 self.assertItemsEqual(new_flags, expected_flags,
Facundo Batista353750c2007-09-13 18:13:15 +00002152 "operation raises different flags depending on flags set: " +
2153 "expected %s, got %s" % (expected_flags, new_flags))
2154
2155def test_main(arith=False, verbose=None, todo_tests=None, debug=None):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002156 """ Execute the tests.
2157
Raymond Hettingered20ad82004-09-04 20:09:13 +00002158 Runs all arithmetic tests if arith is True or if the "decimal" resource
2159 is enabled in regrtest.py
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002160 """
Raymond Hettingered20ad82004-09-04 20:09:13 +00002161
Neal Norwitzce4a9c92006-04-09 08:36:46 +00002162 init()
Facundo Batista353750c2007-09-13 18:13:15 +00002163 global TEST_ALL, DEBUG
Raymond Hettingered20ad82004-09-04 20:09:13 +00002164 TEST_ALL = arith or is_resource_enabled('decimal')
Facundo Batista353750c2007-09-13 18:13:15 +00002165 DEBUG = debug
Raymond Hettingered20ad82004-09-04 20:09:13 +00002166
Facundo Batista353750c2007-09-13 18:13:15 +00002167 if todo_tests is None:
2168 test_classes = [
2169 DecimalExplicitConstructionTest,
2170 DecimalImplicitConstructionTest,
2171 DecimalArithmeticOperatorsTest,
Mark Dickinson1ddf1d82008-02-29 02:16:37 +00002172 DecimalFormatTest,
Facundo Batista353750c2007-09-13 18:13:15 +00002173 DecimalUseOfContextTest,
2174 DecimalUsabilityTest,
2175 DecimalPythonAPItests,
2176 ContextAPItests,
2177 DecimalTest,
2178 WithStatementTest,
2179 ContextFlags
2180 ]
2181 else:
2182 test_classes = [DecimalTest]
2183
2184 # Dynamically build custom test definition for each file in the test
2185 # directory and add the definitions to the DecimalTest class. This
2186 # procedure insures that new files do not get skipped.
2187 for filename in os.listdir(directory):
2188 if '.decTest' not in filename or filename.startswith("."):
2189 continue
2190 head, tail = filename.split('.')
2191 if todo_tests is not None and head not in todo_tests:
2192 continue
2193 tester = lambda self, f=filename: self.eval_file(directory + f)
2194 setattr(DecimalTest, 'test_' + head, tester)
2195 del filename, head, tail, tester
2196
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002197
Tim Peters46cc7022006-03-31 04:11:16 +00002198 try:
2199 run_unittest(*test_classes)
Facundo Batista353750c2007-09-13 18:13:15 +00002200 if todo_tests is None:
2201 import decimal as DecimalModule
2202 run_doctest(DecimalModule, verbose)
Tim Peters46cc7022006-03-31 04:11:16 +00002203 finally:
2204 setcontext(ORIGINAL_CONTEXT)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002205
2206if __name__ == '__main__':
Facundo Batista353750c2007-09-13 18:13:15 +00002207 import optparse
2208 p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]")
2209 p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test')
2210 p.add_option('--skip', '-s', action='store_true', help='skip over 90% of the arithmetic tests')
2211 (opt, args) = p.parse_args()
2212
2213 if opt.skip:
2214 test_main(arith=False, verbose=True)
2215 elif args:
2216 test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002217 else:
Facundo Batista353750c2007-09-13 18:13:15 +00002218 test_main(arith=True, verbose=True)