blob: f8d8dec5ade73c3bf0b6f92261602ce402cfa0e7 [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
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000226 return
Florent Xicluna8f43cec2010-03-21 10:51:40 +0000227 for line in open(file):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000228 line = line.replace('\r\n', '').replace('\n', '')
Raymond Hettinger5aa478b2004-07-09 10:02:53 +0000229 #print line
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000230 try:
231 t = self.eval_line(line)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000232 except DecimalException, exception:
233 #Exception raised where there shoudn't have been one.
234 self.fail('Exception "'+exception.__class__.__name__ + '" raised on line '+line)
235
236 return
237
238 def eval_line(self, s):
239 if s.find(' -> ') >= 0 and s[:2] != '--' and not s.startswith(' --'):
240 s = (s.split('->')[0] + '->' +
241 s.split('->')[1].split('--')[0]).strip()
242 else:
243 s = s.split('--')[0].strip()
244
245 for ignore in self.ignore_list:
246 if s.find(ignore) >= 0:
247 #print s.split()[0], 'NotImplemented--', ignore
248 return
249 if not s:
250 return
251 elif ':' in s:
252 return self.eval_directive(s)
253 else:
254 return self.eval_equation(s)
255
256 def eval_directive(self, s):
257 funct, value = map(lambda x: x.strip().lower(), s.split(':'))
258 if funct == 'rounding':
259 value = RoundingDict[value]
260 else:
261 try:
262 value = int(value)
263 except ValueError:
264 pass
265
266 funct = self.ChangeDict.get(funct, Nonfunction)
267 funct(value)
268
269 def eval_equation(self, s):
270 #global DEFAULT_PRECISION
271 #print DEFAULT_PRECISION
Raymond Hettingered20ad82004-09-04 20:09:13 +0000272
273 if not TEST_ALL and random.random() < 0.90:
274 return
275
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000276 try:
277 Sides = s.split('->')
278 L = Sides[0].strip().split()
279 id = L[0]
Facundo Batista353750c2007-09-13 18:13:15 +0000280 if DEBUG:
281 print "Test ", id,
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000282 funct = L[1].lower()
283 valstemp = L[2:]
284 L = Sides[1].strip().split()
285 ans = L[0]
286 exceptions = L[1:]
287 except (TypeError, AttributeError, IndexError):
Raymond Hettingerd87ac8f2004-07-09 10:52:54 +0000288 raise InvalidOperation
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000289 def FixQuotes(val):
290 val = val.replace("''", 'SingleQuote').replace('""', 'DoubleQuote')
291 val = val.replace("'", '').replace('"', '')
292 val = val.replace('SingleQuote', "'").replace('DoubleQuote', '"')
293 return val
Mark Dickinson539bff42009-10-08 16:28:39 +0000294
295 if id in skipped_test_ids:
296 return
297
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000298 fname = nameAdapter.get(funct, funct)
299 if fname == 'rescale':
300 return
301 funct = getattr(self.context, fname)
302 vals = []
303 conglomerate = ''
304 quote = 0
305 theirexceptions = [ErrorNames[x.lower()] for x in exceptions]
306
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000307 for exception in Signals:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000308 self.context.traps[exception] = 1 #Catch these bugs...
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000309 for exception in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000310 self.context.traps[exception] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000311 for i, val in enumerate(valstemp):
312 if val.count("'") % 2 == 1:
313 quote = 1 - quote
314 if quote:
315 conglomerate = conglomerate + ' ' + val
316 continue
317 else:
318 val = conglomerate + val
319 conglomerate = ''
320 v = FixQuotes(val)
321 if fname in ('to_sci_string', 'to_eng_string'):
322 if EXTENDEDERRORTEST:
323 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000324 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000325 try:
326 funct(self.context.create_decimal(v))
327 except error:
328 pass
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000329 except Signals, e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000330 self.fail("Raised %s in %s when %s disabled" % \
331 (e, s, error))
332 else:
333 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000334 self.context.traps[error] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000335 v = self.context.create_decimal(v)
336 else:
Facundo Batista353750c2007-09-13 18:13:15 +0000337 v = Decimal(v, self.context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000338 vals.append(v)
339
340 ans = FixQuotes(ans)
341
342 if EXTENDEDERRORTEST and fname not in ('to_sci_string', 'to_eng_string'):
343 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000344 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000345 try:
346 funct(*vals)
347 except error:
348 pass
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000349 except Signals, e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000350 self.fail("Raised %s in %s when %s disabled" % \
351 (e, s, error))
352 else:
353 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000354 self.context.traps[error] = 0
Mark Dickinson4f96f5f2010-05-04 14:25:50 +0000355
356 # as above, but add traps cumulatively, to check precedence
357 ordered_errors = [e for e in OrderedSignals if e in theirexceptions]
358 for error in ordered_errors:
359 self.context.traps[error] = 1
360 try:
361 funct(*vals)
362 except error:
363 pass
364 except Signals, e:
365 self.fail("Raised %s in %s; expected %s" %
366 (type(e), s, error))
367 else:
368 self.fail("Did not raise %s in %s" % (error, s))
369 # reset traps
370 for error in ordered_errors:
371 self.context.traps[error] = 0
372
373
Facundo Batista353750c2007-09-13 18:13:15 +0000374 if DEBUG:
375 print "--", self.context
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000376 try:
377 result = str(funct(*vals))
Facundo Batista1a191df2007-10-02 17:01:24 +0000378 if fname in LOGICAL_FUNCTIONS:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000379 result = str(int(eval(result))) # 'True', 'False' -> '1', '0'
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000380 except Signals, error:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000381 self.fail("Raised %s in %s" % (error, s))
382 except: #Catch any error long enough to state the test case.
383 print "ERROR:", s
384 raise
385
386 myexceptions = self.getexceptions()
Raymond Hettingerbf440692004-07-10 14:14:37 +0000387 self.context.clear_flags()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000388
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000389 self.assertEqual(result, ans,
390 'Incorrect answer for ' + s + ' -- got ' + result)
Florent Xicluna8f43cec2010-03-21 10:51:40 +0000391 self.assertItemsEqual(myexceptions, theirexceptions,
Facundo Batista353750c2007-09-13 18:13:15 +0000392 'Incorrect flags set in ' + s + ' -- got ' + str(myexceptions))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000393 return
394
395 def getexceptions(self):
Raymond Hettingerf63ba432004-08-17 05:42:09 +0000396 return [e for e in Signals if self.context.flags[e]]
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000397
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000398 def change_precision(self, prec):
399 self.context.prec = prec
400 def change_rounding_method(self, rounding):
401 self.context.rounding = rounding
402 def change_min_exponent(self, exp):
403 self.context.Emin = exp
404 def change_max_exponent(self, exp):
405 self.context.Emax = exp
406 def change_clamp(self, clamp):
407 self.context._clamp = clamp
408
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000409
410
411# The following classes test the behaviour of Decimal according to PEP 327
412
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000413class DecimalExplicitConstructionTest(unittest.TestCase):
414 '''Unit tests for Explicit Construction cases of Decimal.'''
415
416 def test_explicit_empty(self):
417 self.assertEqual(Decimal(), Decimal("0"))
418
419 def test_explicit_from_None(self):
420 self.assertRaises(TypeError, Decimal, None)
421
422 def test_explicit_from_int(self):
423
424 #positive
425 d = Decimal(45)
426 self.assertEqual(str(d), '45')
427
428 #very large positive
429 d = Decimal(500000123)
430 self.assertEqual(str(d), '500000123')
431
432 #negative
433 d = Decimal(-45)
434 self.assertEqual(str(d), '-45')
435
436 #zero
437 d = Decimal(0)
438 self.assertEqual(str(d), '0')
439
440 def test_explicit_from_string(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000441
442 #empty
443 self.assertEqual(str(Decimal('')), 'NaN')
444
445 #int
446 self.assertEqual(str(Decimal('45')), '45')
447
448 #float
449 self.assertEqual(str(Decimal('45.34')), '45.34')
450
451 #engineer notation
452 self.assertEqual(str(Decimal('45e2')), '4.5E+3')
453
454 #just not a number
455 self.assertEqual(str(Decimal('ugly')), 'NaN')
456
Mark Dickinson59bc20b2008-01-12 01:56:00 +0000457 #leading and trailing whitespace permitted
458 self.assertEqual(str(Decimal('1.3E4 \n')), '1.3E+4')
459 self.assertEqual(str(Decimal(' -7.89')), '-7.89')
460
Mark Dickinson8e85ffa2008-03-25 18:47:59 +0000461 #unicode strings should be permitted
462 self.assertEqual(str(Decimal(u'0E-017')), '0E-17')
463 self.assertEqual(str(Decimal(u'45')), '45')
464 self.assertEqual(str(Decimal(u'-Inf')), '-Infinity')
465 self.assertEqual(str(Decimal(u'NaN123')), 'NaN123')
466
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000467 def test_explicit_from_tuples(self):
468
469 #zero
470 d = Decimal( (0, (0,), 0) )
471 self.assertEqual(str(d), '0')
472
473 #int
474 d = Decimal( (1, (4, 5), 0) )
475 self.assertEqual(str(d), '-45')
476
477 #float
478 d = Decimal( (0, (4, 5, 3, 4), -2) )
479 self.assertEqual(str(d), '45.34')
480
481 #weird
482 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
483 self.assertEqual(str(d), '-4.34913534E-17')
484
485 #wrong number of items
486 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1)) )
487
488 #bad sign
489 self.assertRaises(ValueError, Decimal, (8, (4, 3, 4, 9, 1), 2) )
Facundo Batista9b5e2312007-10-19 19:25:57 +0000490 self.assertRaises(ValueError, Decimal, (0., (4, 3, 4, 9, 1), 2) )
491 self.assertRaises(ValueError, Decimal, (Decimal(1), (4, 3, 4, 9, 1), 2))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000492
493 #bad exp
494 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 'wrong!') )
Facundo Batista9b5e2312007-10-19 19:25:57 +0000495 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 0.) )
496 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), '1') )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000497
498 #bad coefficients
499 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, None, 1), 2) )
500 self.assertRaises(ValueError, Decimal, (1, (4, -3, 4, 9, 1), 2) )
Facundo Batista9b5e2312007-10-19 19:25:57 +0000501 self.assertRaises(ValueError, Decimal, (1, (4, 10, 4, 9, 1), 2) )
Facundo Batista72bc54f2007-11-23 17:59:00 +0000502 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 'a', 1), 2) )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000503
Antoine Pitrou6032c252010-03-30 18:49:45 +0000504 def test_explicit_from_bool(self):
505 self.assertIs(bool(Decimal(0)), False)
506 self.assertIs(bool(Decimal(1)), True)
507 self.assertEqual(Decimal(False), Decimal(0))
508 self.assertEqual(Decimal(True), Decimal(1))
509
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000510 def test_explicit_from_Decimal(self):
511
512 #positive
513 d = Decimal(45)
514 e = Decimal(d)
515 self.assertEqual(str(e), '45')
516 self.assertNotEqual(id(d), id(e))
517
518 #very large positive
519 d = Decimal(500000123)
520 e = Decimal(d)
521 self.assertEqual(str(e), '500000123')
522 self.assertNotEqual(id(d), id(e))
523
524 #negative
525 d = Decimal(-45)
526 e = Decimal(d)
527 self.assertEqual(str(e), '-45')
528 self.assertNotEqual(id(d), id(e))
529
530 #zero
531 d = Decimal(0)
532 e = Decimal(d)
533 self.assertEqual(str(e), '0')
534 self.assertNotEqual(id(d), id(e))
535
Raymond Hettingered171ab2010-04-02 18:39:24 +0000536 @requires_IEEE_754
537 def test_explicit_from_float(self):
538 r = Decimal(0.1)
539 self.assertEqual(type(r), Decimal)
540 self.assertEqual(str(r),
541 '0.1000000000000000055511151231257827021181583404541015625')
542 self.assertTrue(Decimal(float('nan')).is_qnan())
543 self.assertTrue(Decimal(float('inf')).is_infinite())
544 self.assertTrue(Decimal(float('-inf')).is_infinite())
545 self.assertEqual(str(Decimal(float('nan'))),
546 str(Decimal('NaN')))
547 self.assertEqual(str(Decimal(float('inf'))),
548 str(Decimal('Infinity')))
549 self.assertEqual(str(Decimal(float('-inf'))),
550 str(Decimal('-Infinity')))
551 self.assertEqual(str(Decimal(float('-0.0'))),
552 str(Decimal('-0')))
553 for i in range(200):
554 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
555 self.assertEqual(x, float(Decimal(x))) # roundtrip
556
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000557 def test_explicit_context_create_decimal(self):
558
559 nc = copy.copy(getcontext())
560 nc.prec = 3
561
562 # empty
Raymond Hettingerfed52962004-07-14 15:41:57 +0000563 d = Decimal()
564 self.assertEqual(str(d), '0')
565 d = nc.create_decimal()
566 self.assertEqual(str(d), '0')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000567
568 # from None
569 self.assertRaises(TypeError, nc.create_decimal, None)
570
571 # from int
572 d = nc.create_decimal(456)
Ezio Melottib0f5adc2010-01-24 16:58:36 +0000573 self.assertIsInstance(d, Decimal)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000574 self.assertEqual(nc.create_decimal(45678),
575 nc.create_decimal('457E+2'))
576
577 # from string
578 d = Decimal('456789')
579 self.assertEqual(str(d), '456789')
580 d = nc.create_decimal('456789')
581 self.assertEqual(str(d), '4.57E+5')
Mark Dickinson59bc20b2008-01-12 01:56:00 +0000582 # leading and trailing whitespace should result in a NaN;
583 # spaces are already checked in Cowlishaw's test-suite, so
584 # here we just check that a trailing newline results in a NaN
585 self.assertEqual(str(nc.create_decimal('3.14\n')), 'NaN')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000586
587 # from tuples
588 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
589 self.assertEqual(str(d), '-4.34913534E-17')
590 d = nc.create_decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
591 self.assertEqual(str(d), '-4.35E-17')
592
593 # from Decimal
594 prevdec = Decimal(500000123)
595 d = Decimal(prevdec)
596 self.assertEqual(str(d), '500000123')
597 d = nc.create_decimal(prevdec)
598 self.assertEqual(str(d), '5.00E+8')
599
Mark Dickinson4326ad82009-08-02 10:59:36 +0000600 def test_unicode_digits(self):
601 test_values = {
602 u'\uff11': '1',
603 u'\u0660.\u0660\u0663\u0667\u0662e-\u0663' : '0.0000372',
604 u'-nan\u0c68\u0c6a\u0c66\u0c66' : '-NaN2400',
605 }
606 for input, expected in test_values.items():
607 self.assertEqual(str(Decimal(input)), expected)
608
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000609
610class DecimalImplicitConstructionTest(unittest.TestCase):
611 '''Unit tests for Implicit Construction cases of Decimal.'''
612
613 def test_implicit_from_None(self):
614 self.assertRaises(TypeError, eval, 'Decimal(5) + None', globals())
615
616 def test_implicit_from_int(self):
617 #normal
618 self.assertEqual(str(Decimal(5) + 45), '50')
619 #exceeding precision
620 self.assertEqual(Decimal(5) + 123456789000, Decimal(123456789000))
621
622 def test_implicit_from_string(self):
623 self.assertRaises(TypeError, eval, 'Decimal(5) + "3"', globals())
624
625 def test_implicit_from_float(self):
626 self.assertRaises(TypeError, eval, 'Decimal(5) + 2.2', globals())
627
628 def test_implicit_from_Decimal(self):
629 self.assertEqual(Decimal(5) + Decimal(45), Decimal(50))
630
Raymond Hettinger267b8682005-03-27 10:47:39 +0000631 def test_rop(self):
632 # Allow other classes to be trained to interact with Decimals
633 class E:
634 def __divmod__(self, other):
635 return 'divmod ' + str(other)
636 def __rdivmod__(self, other):
637 return str(other) + ' rdivmod'
638 def __lt__(self, other):
639 return 'lt ' + str(other)
640 def __gt__(self, other):
641 return 'gt ' + str(other)
642 def __le__(self, other):
643 return 'le ' + str(other)
644 def __ge__(self, other):
645 return 'ge ' + str(other)
646 def __eq__(self, other):
647 return 'eq ' + str(other)
648 def __ne__(self, other):
649 return 'ne ' + str(other)
650
651 self.assertEqual(divmod(E(), Decimal(10)), 'divmod 10')
652 self.assertEqual(divmod(Decimal(10), E()), '10 rdivmod')
653 self.assertEqual(eval('Decimal(10) < E()'), 'gt 10')
654 self.assertEqual(eval('Decimal(10) > E()'), 'lt 10')
655 self.assertEqual(eval('Decimal(10) <= E()'), 'ge 10')
656 self.assertEqual(eval('Decimal(10) >= E()'), 'le 10')
657 self.assertEqual(eval('Decimal(10) == E()'), 'eq 10')
658 self.assertEqual(eval('Decimal(10) != E()'), 'ne 10')
659
660 # insert operator methods and then exercise them
Georg Brandl96c3f7f2006-03-28 08:06:35 +0000661 oplist = [
662 ('+', '__add__', '__radd__'),
663 ('-', '__sub__', '__rsub__'),
664 ('*', '__mul__', '__rmul__'),
665 ('%', '__mod__', '__rmod__'),
666 ('//', '__floordiv__', '__rfloordiv__'),
667 ('**', '__pow__', '__rpow__')
668 ]
Florent Xicluna8f43cec2010-03-21 10:51:40 +0000669 with check_py3k_warnings():
670 if 1 / 2 == 0:
671 # testing with classic division, so add __div__
672 oplist.append(('/', '__div__', '__rdiv__'))
673 else:
674 # testing with -Qnew, so add __truediv__
675 oplist.append(('/', '__truediv__', '__rtruediv__'))
Anthony Baxter4ef3a232006-03-30 12:59:11 +0000676
Georg Brandl96c3f7f2006-03-28 08:06:35 +0000677 for sym, lop, rop in oplist:
Raymond Hettinger267b8682005-03-27 10:47:39 +0000678 setattr(E, lop, lambda self, other: 'str' + lop + str(other))
679 setattr(E, rop, lambda self, other: str(other) + rop + 'str')
680 self.assertEqual(eval('E()' + sym + 'Decimal(10)'),
681 'str' + lop + '10')
682 self.assertEqual(eval('Decimal(10)' + sym + 'E()'),
683 '10' + rop + 'str')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000684
Mark Dickinson277859d2009-03-17 23:03:46 +0000685
Mark Dickinson1ddf1d82008-02-29 02:16:37 +0000686class DecimalFormatTest(unittest.TestCase):
687 '''Unit tests for the format function.'''
688 def test_formatting(self):
689 # triples giving a format, a Decimal, and the expected result
690 test_values = [
691 ('e', '0E-15', '0e-15'),
692 ('e', '2.3E-15', '2.3e-15'),
693 ('e', '2.30E+2', '2.30e+2'), # preserve significant zeros
694 ('e', '2.30000E-15', '2.30000e-15'),
695 ('e', '1.23456789123456789e40', '1.23456789123456789e+40'),
696 ('e', '1.5', '1.5e+0'),
697 ('e', '0.15', '1.5e-1'),
698 ('e', '0.015', '1.5e-2'),
699 ('e', '0.0000000000015', '1.5e-12'),
700 ('e', '15.0', '1.50e+1'),
701 ('e', '-15', '-1.5e+1'),
702 ('e', '0', '0e+0'),
703 ('e', '0E1', '0e+1'),
704 ('e', '0.0', '0e-1'),
705 ('e', '0.00', '0e-2'),
706 ('.6e', '0E-15', '0.000000e-9'),
707 ('.6e', '0', '0.000000e+6'),
708 ('.6e', '9.999999', '9.999999e+0'),
709 ('.6e', '9.9999999', '1.000000e+1'),
710 ('.6e', '-1.23e5', '-1.230000e+5'),
711 ('.6e', '1.23456789e-3', '1.234568e-3'),
712 ('f', '0', '0'),
713 ('f', '0.0', '0.0'),
714 ('f', '0E-2', '0.00'),
715 ('f', '0.00E-8', '0.0000000000'),
716 ('f', '0E1', '0'), # loses exponent information
717 ('f', '3.2E1', '32'),
718 ('f', '3.2E2', '320'),
719 ('f', '3.20E2', '320'),
720 ('f', '3.200E2', '320.0'),
721 ('f', '3.2E-6', '0.0000032'),
722 ('.6f', '0E-15', '0.000000'), # all zeros treated equally
723 ('.6f', '0E1', '0.000000'),
724 ('.6f', '0', '0.000000'),
725 ('.0f', '0', '0'), # no decimal point
726 ('.0f', '0e-2', '0'),
727 ('.0f', '3.14159265', '3'),
728 ('.1f', '3.14159265', '3.1'),
729 ('.4f', '3.14159265', '3.1416'),
730 ('.6f', '3.14159265', '3.141593'),
731 ('.7f', '3.14159265', '3.1415926'), # round-half-even!
732 ('.8f', '3.14159265', '3.14159265'),
733 ('.9f', '3.14159265', '3.141592650'),
734
735 ('g', '0', '0'),
736 ('g', '0.0', '0.0'),
737 ('g', '0E1', '0e+1'),
738 ('G', '0E1', '0E+1'),
739 ('g', '0E-5', '0.00000'),
740 ('g', '0E-6', '0.000000'),
741 ('g', '0E-7', '0e-7'),
742 ('g', '-0E2', '-0e+2'),
743 ('.0g', '3.14159265', '3'), # 0 sig fig -> 1 sig fig
744 ('.1g', '3.14159265', '3'),
745 ('.2g', '3.14159265', '3.1'),
746 ('.5g', '3.14159265', '3.1416'),
747 ('.7g', '3.14159265', '3.141593'),
748 ('.8g', '3.14159265', '3.1415926'), # round-half-even!
749 ('.9g', '3.14159265', '3.14159265'),
750 ('.10g', '3.14159265', '3.14159265'), # don't pad
751
752 ('%', '0E1', '0%'),
753 ('%', '0E0', '0%'),
754 ('%', '0E-1', '0%'),
755 ('%', '0E-2', '0%'),
756 ('%', '0E-3', '0.0%'),
757 ('%', '0E-4', '0.00%'),
758
759 ('.3%', '0', '0.000%'), # all zeros treated equally
760 ('.3%', '0E10', '0.000%'),
761 ('.3%', '0E-10', '0.000%'),
762 ('.3%', '2.34', '234.000%'),
763 ('.3%', '1.234567', '123.457%'),
764 ('.0%', '1.23', '123%'),
765
766 ('e', 'NaN', 'NaN'),
767 ('f', '-NaN123', '-NaN123'),
768 ('+g', 'NaN456', '+NaN456'),
769 ('.3e', 'Inf', 'Infinity'),
770 ('.16f', '-Inf', '-Infinity'),
771 ('.0g', '-sNaN', '-sNaN'),
772
773 ('', '1.00', '1.00'),
Mark Dickinsonb065e522009-03-17 18:01:03 +0000774
Mark Dickinson277859d2009-03-17 23:03:46 +0000775 # test alignment and padding
Mark Dickinson5cfa8042009-09-08 20:20:19 +0000776 ('6', '123', ' 123'),
Mark Dickinsonb065e522009-03-17 18:01:03 +0000777 ('<6', '123', '123 '),
778 ('>6', '123', ' 123'),
779 ('^6', '123', ' 123 '),
780 ('=+6', '123', '+ 123'),
Mark Dickinson277859d2009-03-17 23:03:46 +0000781 ('#<10', 'NaN', 'NaN#######'),
782 ('#<10', '-4.3', '-4.3######'),
783 ('#<+10', '0.0130', '+0.0130###'),
784 ('#< 10', '0.0130', ' 0.0130###'),
785 ('@>10', '-Inf', '@-Infinity'),
786 ('#>5', '-Inf', '-Infinity'),
787 ('?^5', '123', '?123?'),
788 ('%^6', '123', '%123%%'),
789 (' ^6', '-45.6', '-45.6 '),
790 ('/=10', '-45.6', '-/////45.6'),
791 ('/=+10', '45.6', '+/////45.6'),
792 ('/= 10', '45.6', ' /////45.6'),
793
794 # thousands separator
795 (',', '1234567', '1,234,567'),
796 (',', '123456', '123,456'),
797 (',', '12345', '12,345'),
798 (',', '1234', '1,234'),
799 (',', '123', '123'),
800 (',', '12', '12'),
801 (',', '1', '1'),
802 (',', '0', '0'),
803 (',', '-1234567', '-1,234,567'),
804 (',', '-123456', '-123,456'),
805 ('7,', '123456', '123,456'),
Mark Dickinson5cfa8042009-09-08 20:20:19 +0000806 ('8,', '123456', ' 123,456'),
Mark Dickinson277859d2009-03-17 23:03:46 +0000807 ('08,', '123456', '0,123,456'), # special case: extra 0 needed
808 ('+08,', '123456', '+123,456'), # but not if there's a sign
809 (' 08,', '123456', ' 123,456'),
810 ('08,', '-123456', '-123,456'),
811 ('+09,', '123456', '+0,123,456'),
812 # ... with fractional part...
813 ('07,', '1234.56', '1,234.56'),
814 ('08,', '1234.56', '1,234.56'),
815 ('09,', '1234.56', '01,234.56'),
816 ('010,', '1234.56', '001,234.56'),
817 ('011,', '1234.56', '0,001,234.56'),
818 ('012,', '1234.56', '0,001,234.56'),
819 ('08,.1f', '1234.5', '01,234.5'),
820 # no thousands separators in fraction part
821 (',', '1.23456789', '1.23456789'),
822 (',%', '123.456789', '12,345.6789%'),
823 (',e', '123456', '1.23456e+5'),
824 (',E', '123456', '1.23456E+5'),
Mark Dickinson491ea552009-09-07 16:17:41 +0000825
826 # issue 6850
827 ('a=-7.0', '0.12345', 'aaaa0.1'),
Mark Dickinson1ddf1d82008-02-29 02:16:37 +0000828 ]
829 for fmt, d, result in test_values:
830 self.assertEqual(format(Decimal(d), fmt), result)
831
Mark Dickinson277859d2009-03-17 23:03:46 +0000832 def test_n_format(self):
833 try:
834 from locale import CHAR_MAX
835 except ImportError:
836 return
837
838 # Set up some localeconv-like dictionaries
839 en_US = {
840 'decimal_point' : '.',
841 'grouping' : [3, 3, 0],
842 'thousands_sep': ','
843 }
844
845 fr_FR = {
846 'decimal_point' : ',',
847 'grouping' : [CHAR_MAX],
848 'thousands_sep' : ''
849 }
850
851 ru_RU = {
852 'decimal_point' : ',',
853 'grouping' : [3, 3, 0],
854 'thousands_sep' : ' '
855 }
856
857 crazy = {
858 'decimal_point' : '&',
859 'grouping' : [1, 4, 2, CHAR_MAX],
860 'thousands_sep' : '-'
861 }
862
863
864 def get_fmt(x, locale, fmt='n'):
865 return Decimal.__format__(Decimal(x), fmt, _localeconv=locale)
866
867 self.assertEqual(get_fmt(Decimal('12.7'), en_US), '12.7')
868 self.assertEqual(get_fmt(Decimal('12.7'), fr_FR), '12,7')
869 self.assertEqual(get_fmt(Decimal('12.7'), ru_RU), '12,7')
870 self.assertEqual(get_fmt(Decimal('12.7'), crazy), '1-2&7')
871
872 self.assertEqual(get_fmt(123456789, en_US), '123,456,789')
873 self.assertEqual(get_fmt(123456789, fr_FR), '123456789')
874 self.assertEqual(get_fmt(123456789, ru_RU), '123 456 789')
875 self.assertEqual(get_fmt(1234567890123, crazy), '123456-78-9012-3')
876
877 self.assertEqual(get_fmt(123456789, en_US, '.6n'), '1.23457e+8')
878 self.assertEqual(get_fmt(123456789, fr_FR, '.6n'), '1,23457e+8')
879 self.assertEqual(get_fmt(123456789, ru_RU, '.6n'), '1,23457e+8')
880 self.assertEqual(get_fmt(123456789, crazy, '.6n'), '1&23457e+8')
881
Mark Dickinsonb14514a2009-03-18 08:22:51 +0000882 # zero padding
883 self.assertEqual(get_fmt(1234, fr_FR, '03n'), '1234')
884 self.assertEqual(get_fmt(1234, fr_FR, '04n'), '1234')
885 self.assertEqual(get_fmt(1234, fr_FR, '05n'), '01234')
886 self.assertEqual(get_fmt(1234, fr_FR, '06n'), '001234')
887
888 self.assertEqual(get_fmt(12345, en_US, '05n'), '12,345')
889 self.assertEqual(get_fmt(12345, en_US, '06n'), '12,345')
890 self.assertEqual(get_fmt(12345, en_US, '07n'), '012,345')
891 self.assertEqual(get_fmt(12345, en_US, '08n'), '0,012,345')
892 self.assertEqual(get_fmt(12345, en_US, '09n'), '0,012,345')
893 self.assertEqual(get_fmt(12345, en_US, '010n'), '00,012,345')
894
895 self.assertEqual(get_fmt(123456, crazy, '06n'), '1-2345-6')
896 self.assertEqual(get_fmt(123456, crazy, '07n'), '1-2345-6')
897 self.assertEqual(get_fmt(123456, crazy, '08n'), '1-2345-6')
898 self.assertEqual(get_fmt(123456, crazy, '09n'), '01-2345-6')
899 self.assertEqual(get_fmt(123456, crazy, '010n'), '0-01-2345-6')
900 self.assertEqual(get_fmt(123456, crazy, '011n'), '0-01-2345-6')
901 self.assertEqual(get_fmt(123456, crazy, '012n'), '00-01-2345-6')
902 self.assertEqual(get_fmt(123456, crazy, '013n'), '000-01-2345-6')
903
Mark Dickinson277859d2009-03-17 23:03:46 +0000904
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000905class DecimalArithmeticOperatorsTest(unittest.TestCase):
906 '''Unit tests for all arithmetic operators, binary and unary.'''
907
908 def test_addition(self):
909
910 d1 = Decimal('-11.1')
911 d2 = Decimal('22.2')
912
913 #two Decimals
914 self.assertEqual(d1+d2, Decimal('11.1'))
915 self.assertEqual(d2+d1, Decimal('11.1'))
916
917 #with other type, left
918 c = d1 + 5
919 self.assertEqual(c, Decimal('-6.1'))
920 self.assertEqual(type(c), type(d1))
921
922 #with other type, right
923 c = 5 + d1
924 self.assertEqual(c, Decimal('-6.1'))
925 self.assertEqual(type(c), type(d1))
926
927 #inline with decimal
928 d1 += d2
929 self.assertEqual(d1, Decimal('11.1'))
930
931 #inline with other type
932 d1 += 5
933 self.assertEqual(d1, Decimal('16.1'))
934
935 def test_subtraction(self):
936
937 d1 = Decimal('-11.1')
938 d2 = Decimal('22.2')
939
940 #two Decimals
941 self.assertEqual(d1-d2, Decimal('-33.3'))
942 self.assertEqual(d2-d1, Decimal('33.3'))
943
944 #with other type, left
945 c = d1 - 5
946 self.assertEqual(c, Decimal('-16.1'))
947 self.assertEqual(type(c), type(d1))
948
949 #with other type, right
950 c = 5 - d1
951 self.assertEqual(c, Decimal('16.1'))
952 self.assertEqual(type(c), type(d1))
953
954 #inline with decimal
955 d1 -= d2
956 self.assertEqual(d1, Decimal('-33.3'))
957
958 #inline with other type
959 d1 -= 5
960 self.assertEqual(d1, Decimal('-38.3'))
961
962 def test_multiplication(self):
963
964 d1 = Decimal('-5')
965 d2 = Decimal('3')
966
967 #two Decimals
968 self.assertEqual(d1*d2, Decimal('-15'))
969 self.assertEqual(d2*d1, Decimal('-15'))
970
971 #with other type, left
972 c = d1 * 5
973 self.assertEqual(c, Decimal('-25'))
974 self.assertEqual(type(c), type(d1))
975
976 #with other type, right
977 c = 5 * d1
978 self.assertEqual(c, Decimal('-25'))
979 self.assertEqual(type(c), type(d1))
980
981 #inline with decimal
982 d1 *= d2
983 self.assertEqual(d1, Decimal('-15'))
984
985 #inline with other type
986 d1 *= 5
987 self.assertEqual(d1, Decimal('-75'))
988
989 def test_division(self):
990
991 d1 = Decimal('-5')
992 d2 = Decimal('2')
993
994 #two Decimals
995 self.assertEqual(d1/d2, Decimal('-2.5'))
996 self.assertEqual(d2/d1, Decimal('-0.4'))
997
998 #with other type, left
999 c = d1 / 4
1000 self.assertEqual(c, Decimal('-1.25'))
1001 self.assertEqual(type(c), type(d1))
1002
1003 #with other type, right
1004 c = 4 / d1
1005 self.assertEqual(c, Decimal('-0.8'))
1006 self.assertEqual(type(c), type(d1))
1007
1008 #inline with decimal
1009 d1 /= d2
1010 self.assertEqual(d1, Decimal('-2.5'))
1011
1012 #inline with other type
1013 d1 /= 4
1014 self.assertEqual(d1, Decimal('-0.625'))
1015
1016 def test_floor_division(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001017
1018 d1 = Decimal('5')
1019 d2 = Decimal('2')
1020
1021 #two Decimals
1022 self.assertEqual(d1//d2, Decimal('2'))
1023 self.assertEqual(d2//d1, Decimal('0'))
1024
1025 #with other type, left
1026 c = d1 // 4
1027 self.assertEqual(c, Decimal('1'))
1028 self.assertEqual(type(c), type(d1))
1029
1030 #with other type, right
1031 c = 7 // d1
1032 self.assertEqual(c, Decimal('1'))
1033 self.assertEqual(type(c), type(d1))
1034
1035 #inline with decimal
1036 d1 //= d2
1037 self.assertEqual(d1, Decimal('2'))
1038
1039 #inline with other type
1040 d1 //= 2
1041 self.assertEqual(d1, Decimal('1'))
1042
1043 def test_powering(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001044
1045 d1 = Decimal('5')
1046 d2 = Decimal('2')
1047
1048 #two Decimals
1049 self.assertEqual(d1**d2, Decimal('25'))
1050 self.assertEqual(d2**d1, Decimal('32'))
1051
1052 #with other type, left
1053 c = d1 ** 4
1054 self.assertEqual(c, Decimal('625'))
1055 self.assertEqual(type(c), type(d1))
1056
1057 #with other type, right
1058 c = 7 ** d1
1059 self.assertEqual(c, Decimal('16807'))
1060 self.assertEqual(type(c), type(d1))
1061
1062 #inline with decimal
1063 d1 **= d2
1064 self.assertEqual(d1, Decimal('25'))
1065
1066 #inline with other type
1067 d1 **= 4
1068 self.assertEqual(d1, Decimal('390625'))
1069
1070 def test_module(self):
1071
1072 d1 = Decimal('5')
1073 d2 = Decimal('2')
1074
1075 #two Decimals
1076 self.assertEqual(d1%d2, Decimal('1'))
1077 self.assertEqual(d2%d1, Decimal('2'))
1078
1079 #with other type, left
1080 c = d1 % 4
1081 self.assertEqual(c, Decimal('1'))
1082 self.assertEqual(type(c), type(d1))
1083
1084 #with other type, right
1085 c = 7 % d1
1086 self.assertEqual(c, Decimal('2'))
1087 self.assertEqual(type(c), type(d1))
1088
1089 #inline with decimal
1090 d1 %= d2
1091 self.assertEqual(d1, Decimal('1'))
1092
1093 #inline with other type
1094 d1 %= 4
1095 self.assertEqual(d1, Decimal('1'))
1096
1097 def test_floor_div_module(self):
1098
1099 d1 = Decimal('5')
1100 d2 = Decimal('2')
1101
1102 #two Decimals
1103 (p, q) = divmod(d1, d2)
1104 self.assertEqual(p, Decimal('2'))
1105 self.assertEqual(q, Decimal('1'))
1106 self.assertEqual(type(p), type(d1))
1107 self.assertEqual(type(q), type(d1))
1108
1109 #with other type, left
1110 (p, q) = divmod(d1, 4)
1111 self.assertEqual(p, Decimal('1'))
1112 self.assertEqual(q, Decimal('1'))
1113 self.assertEqual(type(p), type(d1))
1114 self.assertEqual(type(q), type(d1))
1115
1116 #with other type, right
1117 (p, q) = divmod(7, d1)
1118 self.assertEqual(p, Decimal('1'))
1119 self.assertEqual(q, Decimal('2'))
1120 self.assertEqual(type(p), type(d1))
1121 self.assertEqual(type(q), type(d1))
1122
1123 def test_unary_operators(self):
1124 self.assertEqual(+Decimal(45), Decimal(+45)) # +
1125 self.assertEqual(-Decimal(45), Decimal(-45)) # -
1126 self.assertEqual(abs(Decimal(45)), abs(Decimal(-45))) # abs
1127
Mark Dickinson2fc92632008-02-06 22:10:50 +00001128 def test_nan_comparisons(self):
Mark Dickinsone096e822010-04-02 10:17:07 +00001129 # comparisons involving signaling nans signal InvalidOperation
1130
1131 # order comparisons (<, <=, >, >=) involving only quiet nans
1132 # also signal InvalidOperation
1133
1134 # equality comparisons (==, !=) involving only quiet nans
1135 # don't signal, but return False or True respectively.
1136
Mark Dickinson2fc92632008-02-06 22:10:50 +00001137 n = Decimal('NaN')
1138 s = Decimal('sNaN')
1139 i = Decimal('Inf')
1140 f = Decimal('2')
Mark Dickinsone096e822010-04-02 10:17:07 +00001141
1142 qnan_pairs = (n, n), (n, i), (i, n), (n, f), (f, n)
1143 snan_pairs = (s, n), (n, s), (s, i), (i, s), (s, f), (f, s), (s, s)
1144 order_ops = operator.lt, operator.le, operator.gt, operator.ge
1145 equality_ops = operator.eq, operator.ne
1146
1147 # results when InvalidOperation is not trapped
1148 for x, y in qnan_pairs + snan_pairs:
1149 for op in order_ops + equality_ops:
1150 got = op(x, y)
1151 expected = True if op is operator.ne else False
1152 self.assertIs(expected, got,
1153 "expected {0!r} for operator.{1}({2!r}, {3!r}); "
1154 "got {4!r}".format(
1155 expected, op.__name__, x, y, got))
1156
1157 # repeat the above, but this time trap the InvalidOperation
1158 with localcontext() as ctx:
1159 ctx.traps[InvalidOperation] = 1
1160
1161 for x, y in qnan_pairs:
1162 for op in equality_ops:
1163 got = op(x, y)
1164 expected = True if op is operator.ne else False
1165 self.assertIs(expected, got,
1166 "expected {0!r} for "
1167 "operator.{1}({2!r}, {3!r}); "
1168 "got {4!r}".format(
1169 expected, op.__name__, x, y, got))
1170
1171 for x, y in snan_pairs:
1172 for op in equality_ops:
1173 self.assertRaises(InvalidOperation, operator.eq, x, y)
1174 self.assertRaises(InvalidOperation, operator.ne, x, y)
1175
1176 for x, y in qnan_pairs + snan_pairs:
1177 for op in order_ops:
1178 self.assertRaises(InvalidOperation, op, x, y)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001179
Mark Dickinson6d8effb2010-02-18 14:27:02 +00001180 def test_copy_sign(self):
1181 d = Decimal(1).copy_sign(Decimal(-2))
1182
1183 self.assertEqual(Decimal(1).copy_sign(-2), d)
1184 self.assertRaises(TypeError, Decimal(1).copy_sign, '-2')
1185
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001186# The following are two functions used to test threading in the next class
1187
1188def thfunc1(cls):
1189 d1 = Decimal(1)
1190 d3 = Decimal(3)
Facundo Batista64156672008-03-22 02:45:37 +00001191 test1 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001192 cls.synchro.wait()
Facundo Batista64156672008-03-22 02:45:37 +00001193 test2 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001194 cls.finish1.set()
Facundo Batista64156672008-03-22 02:45:37 +00001195
Facundo Batistaee340e52008-05-02 17:39:00 +00001196 cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
1197 cls.assertEqual(test2, Decimal('0.3333333333333333333333333333'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001198 return
1199
1200def thfunc2(cls):
1201 d1 = Decimal(1)
1202 d3 = Decimal(3)
Facundo Batista64156672008-03-22 02:45:37 +00001203 test1 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001204 thiscontext = getcontext()
1205 thiscontext.prec = 18
Facundo Batista64156672008-03-22 02:45:37 +00001206 test2 = d1/d3
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001207 cls.synchro.set()
1208 cls.finish2.set()
Facundo Batista64156672008-03-22 02:45:37 +00001209
Facundo Batistaee340e52008-05-02 17:39:00 +00001210 cls.assertEqual(test1, Decimal('0.3333333333333333333333333333'))
Facundo Batista64156672008-03-22 02:45:37 +00001211 cls.assertEqual(test2, Decimal('0.333333333333333333'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001212 return
1213
1214
1215class DecimalUseOfContextTest(unittest.TestCase):
1216 '''Unit tests for Use of Context cases in Decimal.'''
1217
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001218 try:
1219 import threading
1220 except ImportError:
1221 threading = None
1222
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001223 # Take care executing this test from IDLE, there's an issue in threading
1224 # that hangs IDLE and I couldn't find it
1225
1226 def test_threading(self):
1227 #Test the "threading isolation" of a Context.
1228
1229 self.synchro = threading.Event()
1230 self.finish1 = threading.Event()
1231 self.finish2 = threading.Event()
1232
1233 th1 = threading.Thread(target=thfunc1, args=(self,))
1234 th2 = threading.Thread(target=thfunc2, args=(self,))
1235
1236 th1.start()
1237 th2.start()
1238
1239 self.finish1.wait()
Thomas Woutersb3e6e8c2007-09-19 17:27:29 +00001240 self.finish2.wait()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001241 return
1242
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001243 if threading is None:
1244 del test_threading
1245
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001246
1247class DecimalUsabilityTest(unittest.TestCase):
1248 '''Unit tests for Usability cases of Decimal.'''
1249
1250 def test_comparison_operators(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001251
1252 da = Decimal('23.42')
1253 db = Decimal('23.42')
1254 dc = Decimal('45')
1255
1256 #two Decimals
Ezio Melotti856a3be2010-04-03 14:51:00 +00001257 self.assertGreater(dc, da)
1258 self.assertGreaterEqual(dc, da)
1259 self.assertLess(da, dc)
1260 self.assertLessEqual(da, dc)
1261 self.assertEqual(da, db)
1262 self.assertNotEqual(da, dc)
1263 self.assertLessEqual(da, db)
1264 self.assertGreaterEqual(da, db)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001265 self.assertEqual(cmp(dc,da), 1)
1266 self.assertEqual(cmp(da,dc), -1)
1267 self.assertEqual(cmp(da,db), 0)
1268
1269 #a Decimal and an int
Ezio Melotti856a3be2010-04-03 14:51:00 +00001270 self.assertGreater(dc, 23)
1271 self.assertLess(23, dc)
1272 self.assertEqual(dc, 45)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001273 self.assertEqual(cmp(dc,23), 1)
1274 self.assertEqual(cmp(23,dc), -1)
1275 self.assertEqual(cmp(dc,45), 0)
1276
1277 #a Decimal and uncomparable
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001278 self.assertNotEqual(da, 'ugly')
1279 self.assertNotEqual(da, 32.7)
1280 self.assertNotEqual(da, object())
1281 self.assertNotEqual(da, object)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001282
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001283 # sortable
1284 a = map(Decimal, xrange(100))
1285 b = a[:]
1286 random.shuffle(a)
1287 a.sort()
1288 self.assertEqual(a, b)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001289
Facundo Batista353750c2007-09-13 18:13:15 +00001290 # with None
Florent Xicluna8f43cec2010-03-21 10:51:40 +00001291 with check_py3k_warnings():
1292 self.assertFalse(Decimal(1) < None)
1293 self.assertTrue(Decimal(1) > None)
Facundo Batista353750c2007-09-13 18:13:15 +00001294
Mark Dickinson99d80962010-04-02 08:53:22 +00001295 def test_decimal_float_comparison(self):
1296 da = Decimal('0.25')
1297 db = Decimal('3.0')
Ezio Melotti856a3be2010-04-03 14:51:00 +00001298 self.assertLess(da, 3.0)
1299 self.assertLessEqual(da, 3.0)
1300 self.assertGreater(db, 0.25)
1301 self.assertGreaterEqual(db, 0.25)
1302 self.assertNotEqual(da, 1.5)
1303 self.assertEqual(da, 0.25)
1304 self.assertGreater(3.0, da)
1305 self.assertGreaterEqual(3.0, da)
1306 self.assertLess(0.25, db)
1307 self.assertLessEqual(0.25, db)
1308 self.assertNotEqual(0.25, db)
1309 self.assertEqual(3.0, db)
1310 self.assertNotEqual(0.1, Decimal('0.1'))
Mark Dickinson99d80962010-04-02 08:53:22 +00001311
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001312 def test_copy_and_deepcopy_methods(self):
1313 d = Decimal('43.24')
1314 c = copy.copy(d)
1315 self.assertEqual(id(c), id(d))
1316 dc = copy.deepcopy(d)
1317 self.assertEqual(id(dc), id(d))
1318
1319 def test_hash_method(self):
1320 #just that it's hashable
1321 hash(Decimal(23))
Mark Dickinsonf3eeca12010-04-02 10:35:12 +00001322 hash(Decimal('Infinity'))
1323 hash(Decimal('-Infinity'))
1324 hash(Decimal('nan123'))
1325 hash(Decimal('-NaN'))
Facundo Batista8c202442007-09-19 17:53:25 +00001326
1327 test_values = [Decimal(sign*(2**m + n))
1328 for m in [0, 14, 15, 16, 17, 30, 31,
1329 32, 33, 62, 63, 64, 65, 66]
1330 for n in range(-10, 10)
1331 for sign in [-1, 1]]
1332 test_values.extend([
1333 Decimal("-0"), # zeros
1334 Decimal("0.00"),
1335 Decimal("-0.000"),
1336 Decimal("0E10"),
1337 Decimal("-0E12"),
1338 Decimal("10.0"), # negative exponent
1339 Decimal("-23.00000"),
1340 Decimal("1230E100"), # positive exponent
1341 Decimal("-4.5678E50"),
1342 # a value for which hash(n) != hash(n % (2**64-1))
1343 # in Python pre-2.6
1344 Decimal(2**64 + 2**32 - 1),
1345 # selection of values which fail with the old (before
1346 # version 2.6) long.__hash__
1347 Decimal("1.634E100"),
1348 Decimal("90.697E100"),
1349 Decimal("188.83E100"),
1350 Decimal("1652.9E100"),
1351 Decimal("56531E100"),
1352 ])
1353
1354 # check that hash(d) == hash(int(d)) for integral values
1355 for value in test_values:
1356 self.assertEqual(hash(value), hash(int(value)))
1357
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001358 #the same hash that to an int
1359 self.assertEqual(hash(Decimal(23)), hash(23))
Mark Dickinsonf3eeca12010-04-02 10:35:12 +00001360 self.assertRaises(TypeError, hash, Decimal('sNaN'))
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001361 self.assertTrue(hash(Decimal('Inf')))
1362 self.assertTrue(hash(Decimal('-Inf')))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001363
Mark Dickinson99d80962010-04-02 08:53:22 +00001364 # check that the hashes of a Decimal float match when they
1365 # represent exactly the same values
1366 test_strings = ['inf', '-Inf', '0.0', '-.0e1',
1367 '34.0', '2.5', '112390.625', '-0.515625']
1368 for s in test_strings:
1369 f = float(s)
1370 d = Decimal(s)
1371 self.assertEqual(hash(f), hash(d))
1372
Facundo Batista52b25792008-01-08 12:25:20 +00001373 # check that the value of the hash doesn't depend on the
1374 # current context (issue #1757)
1375 c = getcontext()
1376 old_precision = c.prec
1377 x = Decimal("123456789.1")
1378
1379 c.prec = 6
1380 h1 = hash(x)
1381 c.prec = 10
1382 h2 = hash(x)
1383 c.prec = 16
1384 h3 = hash(x)
1385
1386 self.assertEqual(h1, h2)
1387 self.assertEqual(h1, h3)
1388 c.prec = old_precision
1389
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001390 def test_min_and_max_methods(self):
1391
1392 d1 = Decimal('15.32')
1393 d2 = Decimal('28.5')
1394 l1 = 15
1395 l2 = 28
1396
1397 #between Decimals
Ezio Melotti856a3be2010-04-03 14:51:00 +00001398 self.assertIs(min(d1,d2), d1)
1399 self.assertIs(min(d2,d1), d1)
1400 self.assertIs(max(d1,d2), d2)
1401 self.assertIs(max(d2,d1), d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001402
1403 #between Decimal and long
Ezio Melotti856a3be2010-04-03 14:51:00 +00001404 self.assertIs(min(d1,l2), d1)
1405 self.assertIs(min(l2,d1), d1)
1406 self.assertIs(max(l1,d2), d2)
1407 self.assertIs(max(d2,l1), d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001408
1409 def test_as_nonzero(self):
1410 #as false
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001411 self.assertFalse(Decimal(0))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001412 #as true
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001413 self.assertTrue(Decimal('0.372'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001414
1415 def test_tostring_methods(self):
1416 #Test str and repr methods.
1417
1418 d = Decimal('15.32')
1419 self.assertEqual(str(d), '15.32') # str
Raymond Hettingerabe32372008-02-14 02:41:22 +00001420 self.assertEqual(repr(d), "Decimal('15.32')") # repr
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001421
Mark Dickinson8e85ffa2008-03-25 18:47:59 +00001422 # result type of string methods should be str, not unicode
1423 unicode_inputs = [u'123.4', u'0.5E2', u'Infinity', u'sNaN',
1424 u'-0.0E100', u'-NaN001', u'-Inf']
1425
1426 for u in unicode_inputs:
1427 d = Decimal(u)
1428 self.assertEqual(type(str(d)), str)
1429 self.assertEqual(type(repr(d)), str)
1430 self.assertEqual(type(d.to_eng_string()), str)
1431
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001432 def test_tonum_methods(self):
1433 #Test float, int and long methods.
1434
1435 d1 = Decimal('66')
1436 d2 = Decimal('15.32')
1437
1438 #int
1439 self.assertEqual(int(d1), 66)
1440 self.assertEqual(int(d2), 15)
1441
1442 #long
1443 self.assertEqual(long(d1), 66)
1444 self.assertEqual(long(d2), 15)
1445
1446 #float
1447 self.assertEqual(float(d1), 66)
1448 self.assertEqual(float(d2), 15.32)
1449
1450 def test_eval_round_trip(self):
1451
1452 #with zero
1453 d = Decimal( (0, (0,), 0) )
1454 self.assertEqual(d, eval(repr(d)))
1455
1456 #int
1457 d = Decimal( (1, (4, 5), 0) )
1458 self.assertEqual(d, eval(repr(d)))
1459
1460 #float
1461 d = Decimal( (0, (4, 5, 3, 4), -2) )
1462 self.assertEqual(d, eval(repr(d)))
1463
1464 #weird
1465 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1466 self.assertEqual(d, eval(repr(d)))
1467
1468 def test_as_tuple(self):
1469
1470 #with zero
1471 d = Decimal(0)
1472 self.assertEqual(d.as_tuple(), (0, (0,), 0) )
1473
1474 #int
1475 d = Decimal(-45)
1476 self.assertEqual(d.as_tuple(), (1, (4, 5), 0) )
1477
1478 #complicated string
1479 d = Decimal("-4.34913534E-17")
1480 self.assertEqual(d.as_tuple(), (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1481
1482 #inf
1483 d = Decimal("Infinity")
1484 self.assertEqual(d.as_tuple(), (0, (0,), 'F') )
1485
Facundo Batista9b5e2312007-10-19 19:25:57 +00001486 #leading zeros in coefficient should be stripped
1487 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), -2) )
1488 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), -2) )
1489 d = Decimal( (1, (0, 0, 0), 37) )
1490 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1491 d = Decimal( (1, (), 37) )
1492 self.assertEqual(d.as_tuple(), (1, (0,), 37))
1493
1494 #leading zeros in NaN diagnostic info should be stripped
1495 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), 'n') )
1496 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), 'n') )
1497 d = Decimal( (1, (0, 0, 0), 'N') )
1498 self.assertEqual(d.as_tuple(), (1, (), 'N') )
1499 d = Decimal( (1, (), 'n') )
1500 self.assertEqual(d.as_tuple(), (1, (), 'n') )
1501
1502 #coefficient in infinity should be ignored
1503 d = Decimal( (0, (4, 5, 3, 4), 'F') )
1504 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
1505 d = Decimal( (1, (0, 2, 7, 1), 'F') )
1506 self.assertEqual(d.as_tuple(), (1, (0,), 'F'))
1507
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001508 def test_immutability_operations(self):
1509 # Do operations and check that it didn't change change internal objects.
1510
1511 d1 = Decimal('-25e55')
1512 b1 = Decimal('-25e55')
Facundo Batista353750c2007-09-13 18:13:15 +00001513 d2 = Decimal('33e+33')
1514 b2 = Decimal('33e+33')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001515
1516 def checkSameDec(operation, useOther=False):
1517 if useOther:
1518 eval("d1." + operation + "(d2)")
1519 self.assertEqual(d1._sign, b1._sign)
1520 self.assertEqual(d1._int, b1._int)
1521 self.assertEqual(d1._exp, b1._exp)
1522 self.assertEqual(d2._sign, b2._sign)
1523 self.assertEqual(d2._int, b2._int)
1524 self.assertEqual(d2._exp, b2._exp)
1525 else:
1526 eval("d1." + operation + "()")
1527 self.assertEqual(d1._sign, b1._sign)
1528 self.assertEqual(d1._int, b1._int)
1529 self.assertEqual(d1._exp, b1._exp)
1530 return
1531
1532 Decimal(d1)
1533 self.assertEqual(d1._sign, b1._sign)
1534 self.assertEqual(d1._int, b1._int)
1535 self.assertEqual(d1._exp, b1._exp)
1536
1537 checkSameDec("__abs__")
1538 checkSameDec("__add__", True)
1539 checkSameDec("__div__", True)
1540 checkSameDec("__divmod__", True)
Mark Dickinson2fc92632008-02-06 22:10:50 +00001541 checkSameDec("__eq__", True)
1542 checkSameDec("__ne__", True)
1543 checkSameDec("__le__", True)
1544 checkSameDec("__lt__", True)
1545 checkSameDec("__ge__", True)
1546 checkSameDec("__gt__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001547 checkSameDec("__float__")
1548 checkSameDec("__floordiv__", True)
1549 checkSameDec("__hash__")
1550 checkSameDec("__int__")
Raymond Hettinger5a053642008-01-24 19:05:29 +00001551 checkSameDec("__trunc__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001552 checkSameDec("__long__")
1553 checkSameDec("__mod__", True)
1554 checkSameDec("__mul__", True)
1555 checkSameDec("__neg__")
1556 checkSameDec("__nonzero__")
1557 checkSameDec("__pos__")
1558 checkSameDec("__pow__", True)
1559 checkSameDec("__radd__", True)
1560 checkSameDec("__rdiv__", True)
1561 checkSameDec("__rdivmod__", True)
1562 checkSameDec("__repr__")
1563 checkSameDec("__rfloordiv__", True)
1564 checkSameDec("__rmod__", True)
1565 checkSameDec("__rmul__", True)
1566 checkSameDec("__rpow__", True)
1567 checkSameDec("__rsub__", True)
1568 checkSameDec("__str__")
1569 checkSameDec("__sub__", True)
1570 checkSameDec("__truediv__", True)
1571 checkSameDec("adjusted")
1572 checkSameDec("as_tuple")
1573 checkSameDec("compare", True)
1574 checkSameDec("max", True)
1575 checkSameDec("min", True)
1576 checkSameDec("normalize")
1577 checkSameDec("quantize", True)
1578 checkSameDec("remainder_near", True)
1579 checkSameDec("same_quantum", True)
1580 checkSameDec("sqrt")
1581 checkSameDec("to_eng_string")
1582 checkSameDec("to_integral")
1583
Facundo Batista6c398da2007-09-17 17:30:13 +00001584 def test_subclassing(self):
1585 # Different behaviours when subclassing Decimal
1586
1587 class MyDecimal(Decimal):
1588 pass
1589
1590 d1 = MyDecimal(1)
1591 d2 = MyDecimal(2)
1592 d = d1 + d2
Ezio Melotti856a3be2010-04-03 14:51:00 +00001593 self.assertIs(type(d), Decimal)
Facundo Batista6c398da2007-09-17 17:30:13 +00001594
1595 d = d1.max(d2)
Ezio Melotti856a3be2010-04-03 14:51:00 +00001596 self.assertIs(type(d), Decimal)
Facundo Batista6c398da2007-09-17 17:30:13 +00001597
Mark Dickinson3b24ccb2008-03-25 14:33:23 +00001598 def test_implicit_context(self):
1599 # Check results when context given implicitly. (Issue 2478)
1600 c = getcontext()
1601 self.assertEqual(str(Decimal(0).sqrt()),
1602 str(c.sqrt(Decimal(0))))
1603
Mark Dickinson0c673122009-10-29 12:04:00 +00001604 def test_conversions_from_int(self):
1605 # Check that methods taking a second Decimal argument will
1606 # always accept an integer in place of a Decimal.
1607 self.assertEqual(Decimal(4).compare(3),
1608 Decimal(4).compare(Decimal(3)))
1609 self.assertEqual(Decimal(4).compare_signal(3),
1610 Decimal(4).compare_signal(Decimal(3)))
1611 self.assertEqual(Decimal(4).compare_total(3),
1612 Decimal(4).compare_total(Decimal(3)))
1613 self.assertEqual(Decimal(4).compare_total_mag(3),
1614 Decimal(4).compare_total_mag(Decimal(3)))
1615 self.assertEqual(Decimal(10101).logical_and(1001),
1616 Decimal(10101).logical_and(Decimal(1001)))
1617 self.assertEqual(Decimal(10101).logical_or(1001),
1618 Decimal(10101).logical_or(Decimal(1001)))
1619 self.assertEqual(Decimal(10101).logical_xor(1001),
1620 Decimal(10101).logical_xor(Decimal(1001)))
1621 self.assertEqual(Decimal(567).max(123),
1622 Decimal(567).max(Decimal(123)))
1623 self.assertEqual(Decimal(567).max_mag(123),
1624 Decimal(567).max_mag(Decimal(123)))
1625 self.assertEqual(Decimal(567).min(123),
1626 Decimal(567).min(Decimal(123)))
1627 self.assertEqual(Decimal(567).min_mag(123),
1628 Decimal(567).min_mag(Decimal(123)))
1629 self.assertEqual(Decimal(567).next_toward(123),
1630 Decimal(567).next_toward(Decimal(123)))
1631 self.assertEqual(Decimal(1234).quantize(100),
1632 Decimal(1234).quantize(Decimal(100)))
1633 self.assertEqual(Decimal(768).remainder_near(1234),
1634 Decimal(768).remainder_near(Decimal(1234)))
1635 self.assertEqual(Decimal(123).rotate(1),
1636 Decimal(123).rotate(Decimal(1)))
1637 self.assertEqual(Decimal(1234).same_quantum(1000),
1638 Decimal(1234).same_quantum(Decimal(1000)))
1639 self.assertEqual(Decimal('9.123').scaleb(-100),
1640 Decimal('9.123').scaleb(Decimal(-100)))
1641 self.assertEqual(Decimal(456).shift(-1),
1642 Decimal(456).shift(Decimal(-1)))
1643
1644 self.assertEqual(Decimal(-12).fma(Decimal(45), 67),
1645 Decimal(-12).fma(Decimal(45), Decimal(67)))
1646 self.assertEqual(Decimal(-12).fma(45, 67),
1647 Decimal(-12).fma(Decimal(45), Decimal(67)))
1648 self.assertEqual(Decimal(-12).fma(45, Decimal(67)),
1649 Decimal(-12).fma(Decimal(45), Decimal(67)))
1650
Facundo Batista6c398da2007-09-17 17:30:13 +00001651
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001652class DecimalPythonAPItests(unittest.TestCase):
1653
Raymond Hettinger2c8585b2009-02-03 03:37:03 +00001654 def test_abc(self):
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001655 self.assertTrue(issubclass(Decimal, numbers.Number))
Ezio Melotti856a3be2010-04-03 14:51:00 +00001656 self.assertFalse(issubclass(Decimal, numbers.Real))
Ezio Melottib0f5adc2010-01-24 16:58:36 +00001657 self.assertIsInstance(Decimal(0), numbers.Number)
Ezio Melotti856a3be2010-04-03 14:51:00 +00001658 self.assertNotIsInstance(Decimal(0), numbers.Real)
Raymond Hettinger2c8585b2009-02-03 03:37:03 +00001659
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001660 def test_pickle(self):
1661 d = Decimal('-3.141590000')
1662 p = pickle.dumps(d)
1663 e = pickle.loads(p)
1664 self.assertEqual(d, e)
1665
Raymond Hettinger5548be22004-07-05 18:49:38 +00001666 def test_int(self):
Raymond Hettinger605ed022004-11-24 07:28:48 +00001667 for x in range(-250, 250):
1668 s = '%0.2f' % (x / 100.0)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001669 # should work the same as for floats
1670 self.assertEqual(int(Decimal(s)), int(float(s)))
Raymond Hettinger605ed022004-11-24 07:28:48 +00001671 # should work the same as to_integral in the ROUND_DOWN mode
Raymond Hettinger5548be22004-07-05 18:49:38 +00001672 d = Decimal(s)
Raymond Hettinger605ed022004-11-24 07:28:48 +00001673 r = d.to_integral(ROUND_DOWN)
Raymond Hettinger5548be22004-07-05 18:49:38 +00001674 self.assertEqual(Decimal(int(d)), r)
1675
Mark Dickinson968f1692009-09-07 18:04:58 +00001676 self.assertRaises(ValueError, int, Decimal('-nan'))
1677 self.assertRaises(ValueError, int, Decimal('snan'))
1678 self.assertRaises(OverflowError, int, Decimal('inf'))
1679 self.assertRaises(OverflowError, int, Decimal('-inf'))
1680
1681 self.assertRaises(ValueError, long, Decimal('-nan'))
1682 self.assertRaises(ValueError, long, Decimal('snan'))
1683 self.assertRaises(OverflowError, long, Decimal('inf'))
1684 self.assertRaises(OverflowError, long, Decimal('-inf'))
1685
Raymond Hettinger5a053642008-01-24 19:05:29 +00001686 def test_trunc(self):
1687 for x in range(-250, 250):
1688 s = '%0.2f' % (x / 100.0)
1689 # should work the same as for floats
1690 self.assertEqual(int(Decimal(s)), int(float(s)))
1691 # should work the same as to_integral in the ROUND_DOWN mode
1692 d = Decimal(s)
1693 r = d.to_integral(ROUND_DOWN)
Jeffrey Yasskinca2b69f2008-02-01 06:22:46 +00001694 self.assertEqual(Decimal(math.trunc(d)), r)
Raymond Hettinger5a053642008-01-24 19:05:29 +00001695
Raymond Hettingerf4d85972009-01-03 19:02:23 +00001696 def test_from_float(self):
1697
1698 class MyDecimal(Decimal):
1699 pass
1700
1701 r = MyDecimal.from_float(0.1)
1702 self.assertEqual(type(r), MyDecimal)
1703 self.assertEqual(str(r),
1704 '0.1000000000000000055511151231257827021181583404541015625')
1705 bigint = 12345678901234567890123456789
1706 self.assertEqual(MyDecimal.from_float(bigint), MyDecimal(bigint))
Benjamin Peterson5c8da862009-06-30 22:57:08 +00001707 self.assertTrue(MyDecimal.from_float(float('nan')).is_qnan())
1708 self.assertTrue(MyDecimal.from_float(float('inf')).is_infinite())
1709 self.assertTrue(MyDecimal.from_float(float('-inf')).is_infinite())
Raymond Hettingerf4d85972009-01-03 19:02:23 +00001710 self.assertEqual(str(MyDecimal.from_float(float('nan'))),
1711 str(Decimal('NaN')))
1712 self.assertEqual(str(MyDecimal.from_float(float('inf'))),
1713 str(Decimal('Infinity')))
1714 self.assertEqual(str(MyDecimal.from_float(float('-inf'))),
1715 str(Decimal('-Infinity')))
1716 self.assertRaises(TypeError, MyDecimal.from_float, 'abc')
1717 for i in range(200):
1718 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
1719 self.assertEqual(x, float(MyDecimal.from_float(x))) # roundtrip
1720
1721 def test_create_decimal_from_float(self):
1722 context = Context(prec=5, rounding=ROUND_DOWN)
1723 self.assertEqual(
1724 context.create_decimal_from_float(math.pi),
1725 Decimal('3.1415')
1726 )
1727 context = Context(prec=5, rounding=ROUND_UP)
1728 self.assertEqual(
1729 context.create_decimal_from_float(math.pi),
1730 Decimal('3.1416')
1731 )
1732 context = Context(prec=5, traps=[Inexact])
1733 self.assertRaises(
1734 Inexact,
1735 context.create_decimal_from_float,
1736 math.pi
1737 )
1738 self.assertEqual(repr(context.create_decimal_from_float(-0.0)),
1739 "Decimal('-0')")
1740 self.assertEqual(repr(context.create_decimal_from_float(1.0)),
1741 "Decimal('1')")
1742 self.assertEqual(repr(context.create_decimal_from_float(10)),
1743 "Decimal('10')")
1744
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00001745class ContextAPItests(unittest.TestCase):
1746
1747 def test_pickle(self):
1748 c = Context()
1749 e = pickle.loads(pickle.dumps(c))
1750 for k in vars(c):
1751 v1 = vars(c)[k]
1752 v2 = vars(e)[k]
1753 self.assertEqual(v1, v2)
1754
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001755 def test_equality_with_other_types(self):
Ezio Melottiaa980582010-01-23 23:04:36 +00001756 self.assertIn(Decimal(10), ['a', 1.0, Decimal(10), (1,2), {}])
1757 self.assertNotIn(Decimal(10), ['a', 1.0, (1,2), {}])
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001758
Raymond Hettinger955d2b22004-08-08 20:17:45 +00001759 def test_copy(self):
1760 # All copies should be deep
1761 c = Context()
1762 d = c.copy()
1763 self.assertNotEqual(id(c), id(d))
1764 self.assertNotEqual(id(c.flags), id(d.flags))
1765 self.assertNotEqual(id(c.traps), id(d.traps))
1766
Mark Dickinson6d8effb2010-02-18 14:27:02 +00001767 def test_abs(self):
1768 c = Context()
1769 d = c.abs(Decimal(-1))
1770 self.assertEqual(c.abs(-1), d)
1771 self.assertRaises(TypeError, c.abs, '-1')
1772
1773 def test_add(self):
1774 c = Context()
1775 d = c.add(Decimal(1), Decimal(1))
1776 self.assertEqual(c.add(1, 1), d)
1777 self.assertEqual(c.add(Decimal(1), 1), d)
1778 self.assertEqual(c.add(1, Decimal(1)), d)
1779 self.assertRaises(TypeError, c.add, '1', 1)
1780 self.assertRaises(TypeError, c.add, 1, '1')
1781
1782 def test_compare(self):
1783 c = Context()
1784 d = c.compare(Decimal(1), Decimal(1))
1785 self.assertEqual(c.compare(1, 1), d)
1786 self.assertEqual(c.compare(Decimal(1), 1), d)
1787 self.assertEqual(c.compare(1, Decimal(1)), d)
1788 self.assertRaises(TypeError, c.compare, '1', 1)
1789 self.assertRaises(TypeError, c.compare, 1, '1')
1790
1791 def test_compare_signal(self):
1792 c = Context()
1793 d = c.compare_signal(Decimal(1), Decimal(1))
1794 self.assertEqual(c.compare_signal(1, 1), d)
1795 self.assertEqual(c.compare_signal(Decimal(1), 1), d)
1796 self.assertEqual(c.compare_signal(1, Decimal(1)), d)
1797 self.assertRaises(TypeError, c.compare_signal, '1', 1)
1798 self.assertRaises(TypeError, c.compare_signal, 1, '1')
1799
1800 def test_compare_total(self):
1801 c = Context()
1802 d = c.compare_total(Decimal(1), Decimal(1))
1803 self.assertEqual(c.compare_total(1, 1), d)
1804 self.assertEqual(c.compare_total(Decimal(1), 1), d)
1805 self.assertEqual(c.compare_total(1, Decimal(1)), d)
1806 self.assertRaises(TypeError, c.compare_total, '1', 1)
1807 self.assertRaises(TypeError, c.compare_total, 1, '1')
1808
1809 def test_compare_total_mag(self):
1810 c = Context()
1811 d = c.compare_total_mag(Decimal(1), Decimal(1))
1812 self.assertEqual(c.compare_total_mag(1, 1), d)
1813 self.assertEqual(c.compare_total_mag(Decimal(1), 1), d)
1814 self.assertEqual(c.compare_total_mag(1, Decimal(1)), d)
1815 self.assertRaises(TypeError, c.compare_total_mag, '1', 1)
1816 self.assertRaises(TypeError, c.compare_total_mag, 1, '1')
1817
1818 def test_copy_abs(self):
1819 c = Context()
1820 d = c.copy_abs(Decimal(-1))
1821 self.assertEqual(c.copy_abs(-1), d)
1822 self.assertRaises(TypeError, c.copy_abs, '-1')
1823
1824 def test_copy_decimal(self):
1825 c = Context()
1826 d = c.copy_decimal(Decimal(-1))
1827 self.assertEqual(c.copy_decimal(-1), d)
1828 self.assertRaises(TypeError, c.copy_decimal, '-1')
1829
1830 def test_copy_negate(self):
1831 c = Context()
1832 d = c.copy_negate(Decimal(-1))
1833 self.assertEqual(c.copy_negate(-1), d)
1834 self.assertRaises(TypeError, c.copy_negate, '-1')
1835
1836 def test_copy_sign(self):
1837 c = Context()
1838 d = c.copy_sign(Decimal(1), Decimal(-2))
1839 self.assertEqual(c.copy_sign(1, -2), d)
1840 self.assertEqual(c.copy_sign(Decimal(1), -2), d)
1841 self.assertEqual(c.copy_sign(1, Decimal(-2)), d)
1842 self.assertRaises(TypeError, c.copy_sign, '1', -2)
1843 self.assertRaises(TypeError, c.copy_sign, 1, '-2')
1844
1845 def test_divide(self):
1846 c = Context()
1847 d = c.divide(Decimal(1), Decimal(2))
1848 self.assertEqual(c.divide(1, 2), d)
1849 self.assertEqual(c.divide(Decimal(1), 2), d)
1850 self.assertEqual(c.divide(1, Decimal(2)), d)
1851 self.assertRaises(TypeError, c.divide, '1', 2)
1852 self.assertRaises(TypeError, c.divide, 1, '2')
1853
1854 def test_divide_int(self):
1855 c = Context()
1856 d = c.divide_int(Decimal(1), Decimal(2))
1857 self.assertEqual(c.divide_int(1, 2), d)
1858 self.assertEqual(c.divide_int(Decimal(1), 2), d)
1859 self.assertEqual(c.divide_int(1, Decimal(2)), d)
1860 self.assertRaises(TypeError, c.divide_int, '1', 2)
1861 self.assertRaises(TypeError, c.divide_int, 1, '2')
1862
1863 def test_divmod(self):
1864 c = Context()
1865 d = c.divmod(Decimal(1), Decimal(2))
1866 self.assertEqual(c.divmod(1, 2), d)
1867 self.assertEqual(c.divmod(Decimal(1), 2), d)
1868 self.assertEqual(c.divmod(1, Decimal(2)), d)
1869 self.assertRaises(TypeError, c.divmod, '1', 2)
1870 self.assertRaises(TypeError, c.divmod, 1, '2')
1871
1872 def test_exp(self):
1873 c = Context()
1874 d = c.exp(Decimal(10))
1875 self.assertEqual(c.exp(10), d)
1876 self.assertRaises(TypeError, c.exp, '10')
1877
1878 def test_fma(self):
1879 c = Context()
1880 d = c.fma(Decimal(2), Decimal(3), Decimal(4))
1881 self.assertEqual(c.fma(2, 3, 4), d)
1882 self.assertEqual(c.fma(Decimal(2), 3, 4), d)
1883 self.assertEqual(c.fma(2, Decimal(3), 4), d)
1884 self.assertEqual(c.fma(2, 3, Decimal(4)), d)
1885 self.assertEqual(c.fma(Decimal(2), Decimal(3), 4), d)
1886 self.assertRaises(TypeError, c.fma, '2', 3, 4)
1887 self.assertRaises(TypeError, c.fma, 2, '3', 4)
1888 self.assertRaises(TypeError, c.fma, 2, 3, '4')
1889
1890 def test_is_finite(self):
1891 c = Context()
1892 d = c.is_finite(Decimal(10))
1893 self.assertEqual(c.is_finite(10), d)
1894 self.assertRaises(TypeError, c.is_finite, '10')
1895
1896 def test_is_infinite(self):
1897 c = Context()
1898 d = c.is_infinite(Decimal(10))
1899 self.assertEqual(c.is_infinite(10), d)
1900 self.assertRaises(TypeError, c.is_infinite, '10')
1901
1902 def test_is_nan(self):
1903 c = Context()
1904 d = c.is_nan(Decimal(10))
1905 self.assertEqual(c.is_nan(10), d)
1906 self.assertRaises(TypeError, c.is_nan, '10')
1907
1908 def test_is_normal(self):
1909 c = Context()
1910 d = c.is_normal(Decimal(10))
1911 self.assertEqual(c.is_normal(10), d)
1912 self.assertRaises(TypeError, c.is_normal, '10')
1913
1914 def test_is_qnan(self):
1915 c = Context()
1916 d = c.is_qnan(Decimal(10))
1917 self.assertEqual(c.is_qnan(10), d)
1918 self.assertRaises(TypeError, c.is_qnan, '10')
1919
1920 def test_is_signed(self):
1921 c = Context()
1922 d = c.is_signed(Decimal(10))
1923 self.assertEqual(c.is_signed(10), d)
1924 self.assertRaises(TypeError, c.is_signed, '10')
1925
1926 def test_is_snan(self):
1927 c = Context()
1928 d = c.is_snan(Decimal(10))
1929 self.assertEqual(c.is_snan(10), d)
1930 self.assertRaises(TypeError, c.is_snan, '10')
1931
1932 def test_is_subnormal(self):
1933 c = Context()
1934 d = c.is_subnormal(Decimal(10))
1935 self.assertEqual(c.is_subnormal(10), d)
1936 self.assertRaises(TypeError, c.is_subnormal, '10')
1937
1938 def test_is_zero(self):
1939 c = Context()
1940 d = c.is_zero(Decimal(10))
1941 self.assertEqual(c.is_zero(10), d)
1942 self.assertRaises(TypeError, c.is_zero, '10')
1943
1944 def test_ln(self):
1945 c = Context()
1946 d = c.ln(Decimal(10))
1947 self.assertEqual(c.ln(10), d)
1948 self.assertRaises(TypeError, c.ln, '10')
1949
1950 def test_log10(self):
1951 c = Context()
1952 d = c.log10(Decimal(10))
1953 self.assertEqual(c.log10(10), d)
1954 self.assertRaises(TypeError, c.log10, '10')
1955
1956 def test_logb(self):
1957 c = Context()
1958 d = c.logb(Decimal(10))
1959 self.assertEqual(c.logb(10), d)
1960 self.assertRaises(TypeError, c.logb, '10')
1961
1962 def test_logical_and(self):
1963 c = Context()
1964 d = c.logical_and(Decimal(1), Decimal(1))
1965 self.assertEqual(c.logical_and(1, 1), d)
1966 self.assertEqual(c.logical_and(Decimal(1), 1), d)
1967 self.assertEqual(c.logical_and(1, Decimal(1)), d)
1968 self.assertRaises(TypeError, c.logical_and, '1', 1)
1969 self.assertRaises(TypeError, c.logical_and, 1, '1')
1970
1971 def test_logical_invert(self):
1972 c = Context()
1973 d = c.logical_invert(Decimal(1000))
1974 self.assertEqual(c.logical_invert(1000), d)
1975 self.assertRaises(TypeError, c.logical_invert, '1000')
1976
1977 def test_logical_or(self):
1978 c = Context()
1979 d = c.logical_or(Decimal(1), Decimal(1))
1980 self.assertEqual(c.logical_or(1, 1), d)
1981 self.assertEqual(c.logical_or(Decimal(1), 1), d)
1982 self.assertEqual(c.logical_or(1, Decimal(1)), d)
1983 self.assertRaises(TypeError, c.logical_or, '1', 1)
1984 self.assertRaises(TypeError, c.logical_or, 1, '1')
1985
1986 def test_logical_xor(self):
1987 c = Context()
1988 d = c.logical_xor(Decimal(1), Decimal(1))
1989 self.assertEqual(c.logical_xor(1, 1), d)
1990 self.assertEqual(c.logical_xor(Decimal(1), 1), d)
1991 self.assertEqual(c.logical_xor(1, Decimal(1)), d)
1992 self.assertRaises(TypeError, c.logical_xor, '1', 1)
1993 self.assertRaises(TypeError, c.logical_xor, 1, '1')
1994
1995 def test_max(self):
1996 c = Context()
1997 d = c.max(Decimal(1), Decimal(2))
1998 self.assertEqual(c.max(1, 2), d)
1999 self.assertEqual(c.max(Decimal(1), 2), d)
2000 self.assertEqual(c.max(1, Decimal(2)), d)
2001 self.assertRaises(TypeError, c.max, '1', 2)
2002 self.assertRaises(TypeError, c.max, 1, '2')
2003
2004 def test_max_mag(self):
2005 c = Context()
2006 d = c.max_mag(Decimal(1), Decimal(2))
2007 self.assertEqual(c.max_mag(1, 2), d)
2008 self.assertEqual(c.max_mag(Decimal(1), 2), d)
2009 self.assertEqual(c.max_mag(1, Decimal(2)), d)
2010 self.assertRaises(TypeError, c.max_mag, '1', 2)
2011 self.assertRaises(TypeError, c.max_mag, 1, '2')
2012
2013 def test_min(self):
2014 c = Context()
2015 d = c.min(Decimal(1), Decimal(2))
2016 self.assertEqual(c.min(1, 2), d)
2017 self.assertEqual(c.min(Decimal(1), 2), d)
2018 self.assertEqual(c.min(1, Decimal(2)), d)
2019 self.assertRaises(TypeError, c.min, '1', 2)
2020 self.assertRaises(TypeError, c.min, 1, '2')
2021
2022 def test_min_mag(self):
2023 c = Context()
2024 d = c.min_mag(Decimal(1), Decimal(2))
2025 self.assertEqual(c.min_mag(1, 2), d)
2026 self.assertEqual(c.min_mag(Decimal(1), 2), d)
2027 self.assertEqual(c.min_mag(1, Decimal(2)), d)
2028 self.assertRaises(TypeError, c.min_mag, '1', 2)
2029 self.assertRaises(TypeError, c.min_mag, 1, '2')
2030
2031 def test_minus(self):
2032 c = Context()
2033 d = c.minus(Decimal(10))
2034 self.assertEqual(c.minus(10), d)
2035 self.assertRaises(TypeError, c.minus, '10')
2036
2037 def test_multiply(self):
2038 c = Context()
2039 d = c.multiply(Decimal(1), Decimal(2))
2040 self.assertEqual(c.multiply(1, 2), d)
2041 self.assertEqual(c.multiply(Decimal(1), 2), d)
2042 self.assertEqual(c.multiply(1, Decimal(2)), d)
2043 self.assertRaises(TypeError, c.multiply, '1', 2)
2044 self.assertRaises(TypeError, c.multiply, 1, '2')
2045
2046 def test_next_minus(self):
2047 c = Context()
2048 d = c.next_minus(Decimal(10))
2049 self.assertEqual(c.next_minus(10), d)
2050 self.assertRaises(TypeError, c.next_minus, '10')
2051
2052 def test_next_plus(self):
2053 c = Context()
2054 d = c.next_plus(Decimal(10))
2055 self.assertEqual(c.next_plus(10), d)
2056 self.assertRaises(TypeError, c.next_plus, '10')
2057
2058 def test_next_toward(self):
2059 c = Context()
2060 d = c.next_toward(Decimal(1), Decimal(2))
2061 self.assertEqual(c.next_toward(1, 2), d)
2062 self.assertEqual(c.next_toward(Decimal(1), 2), d)
2063 self.assertEqual(c.next_toward(1, Decimal(2)), d)
2064 self.assertRaises(TypeError, c.next_toward, '1', 2)
2065 self.assertRaises(TypeError, c.next_toward, 1, '2')
2066
2067 def test_normalize(self):
2068 c = Context()
2069 d = c.normalize(Decimal(10))
2070 self.assertEqual(c.normalize(10), d)
2071 self.assertRaises(TypeError, c.normalize, '10')
2072
2073 def test_number_class(self):
2074 c = Context()
2075 self.assertEqual(c.number_class(123), c.number_class(Decimal(123)))
2076 self.assertEqual(c.number_class(0), c.number_class(Decimal(0)))
2077 self.assertEqual(c.number_class(-45), c.number_class(Decimal(-45)))
2078
2079 def test_power(self):
2080 c = Context()
2081 d = c.power(Decimal(1), Decimal(4), Decimal(2))
2082 self.assertEqual(c.power(1, 4, 2), d)
2083 self.assertEqual(c.power(Decimal(1), 4, 2), d)
2084 self.assertEqual(c.power(1, Decimal(4), 2), d)
2085 self.assertEqual(c.power(1, 4, Decimal(2)), d)
2086 self.assertEqual(c.power(Decimal(1), Decimal(4), 2), d)
2087 self.assertRaises(TypeError, c.power, '1', 4, 2)
2088 self.assertRaises(TypeError, c.power, 1, '4', 2)
2089 self.assertRaises(TypeError, c.power, 1, 4, '2')
2090
2091 def test_plus(self):
2092 c = Context()
2093 d = c.plus(Decimal(10))
2094 self.assertEqual(c.plus(10), d)
2095 self.assertRaises(TypeError, c.plus, '10')
2096
2097 def test_quantize(self):
2098 c = Context()
2099 d = c.quantize(Decimal(1), Decimal(2))
2100 self.assertEqual(c.quantize(1, 2), d)
2101 self.assertEqual(c.quantize(Decimal(1), 2), d)
2102 self.assertEqual(c.quantize(1, Decimal(2)), d)
2103 self.assertRaises(TypeError, c.quantize, '1', 2)
2104 self.assertRaises(TypeError, c.quantize, 1, '2')
2105
2106 def test_remainder(self):
2107 c = Context()
2108 d = c.remainder(Decimal(1), Decimal(2))
2109 self.assertEqual(c.remainder(1, 2), d)
2110 self.assertEqual(c.remainder(Decimal(1), 2), d)
2111 self.assertEqual(c.remainder(1, Decimal(2)), d)
2112 self.assertRaises(TypeError, c.remainder, '1', 2)
2113 self.assertRaises(TypeError, c.remainder, 1, '2')
2114
2115 def test_remainder_near(self):
2116 c = Context()
2117 d = c.remainder_near(Decimal(1), Decimal(2))
2118 self.assertEqual(c.remainder_near(1, 2), d)
2119 self.assertEqual(c.remainder_near(Decimal(1), 2), d)
2120 self.assertEqual(c.remainder_near(1, Decimal(2)), d)
2121 self.assertRaises(TypeError, c.remainder_near, '1', 2)
2122 self.assertRaises(TypeError, c.remainder_near, 1, '2')
2123
2124 def test_rotate(self):
2125 c = Context()
2126 d = c.rotate(Decimal(1), Decimal(2))
2127 self.assertEqual(c.rotate(1, 2), d)
2128 self.assertEqual(c.rotate(Decimal(1), 2), d)
2129 self.assertEqual(c.rotate(1, Decimal(2)), d)
2130 self.assertRaises(TypeError, c.rotate, '1', 2)
2131 self.assertRaises(TypeError, c.rotate, 1, '2')
2132
2133 def test_sqrt(self):
2134 c = Context()
2135 d = c.sqrt(Decimal(10))
2136 self.assertEqual(c.sqrt(10), d)
2137 self.assertRaises(TypeError, c.sqrt, '10')
2138
2139 def test_same_quantum(self):
2140 c = Context()
2141 d = c.same_quantum(Decimal(1), Decimal(2))
2142 self.assertEqual(c.same_quantum(1, 2), d)
2143 self.assertEqual(c.same_quantum(Decimal(1), 2), d)
2144 self.assertEqual(c.same_quantum(1, Decimal(2)), d)
2145 self.assertRaises(TypeError, c.same_quantum, '1', 2)
2146 self.assertRaises(TypeError, c.same_quantum, 1, '2')
2147
2148 def test_scaleb(self):
2149 c = Context()
2150 d = c.scaleb(Decimal(1), Decimal(2))
2151 self.assertEqual(c.scaleb(1, 2), d)
2152 self.assertEqual(c.scaleb(Decimal(1), 2), d)
2153 self.assertEqual(c.scaleb(1, Decimal(2)), d)
2154 self.assertRaises(TypeError, c.scaleb, '1', 2)
2155 self.assertRaises(TypeError, c.scaleb, 1, '2')
2156
2157 def test_shift(self):
2158 c = Context()
2159 d = c.shift(Decimal(1), Decimal(2))
2160 self.assertEqual(c.shift(1, 2), d)
2161 self.assertEqual(c.shift(Decimal(1), 2), d)
2162 self.assertEqual(c.shift(1, Decimal(2)), d)
2163 self.assertRaises(TypeError, c.shift, '1', 2)
2164 self.assertRaises(TypeError, c.shift, 1, '2')
2165
2166 def test_subtract(self):
2167 c = Context()
2168 d = c.subtract(Decimal(1), Decimal(2))
2169 self.assertEqual(c.subtract(1, 2), d)
2170 self.assertEqual(c.subtract(Decimal(1), 2), d)
2171 self.assertEqual(c.subtract(1, Decimal(2)), d)
2172 self.assertRaises(TypeError, c.subtract, '1', 2)
2173 self.assertRaises(TypeError, c.subtract, 1, '2')
2174
2175 def test_to_eng_string(self):
2176 c = Context()
2177 d = c.to_eng_string(Decimal(10))
2178 self.assertEqual(c.to_eng_string(10), d)
2179 self.assertRaises(TypeError, c.to_eng_string, '10')
2180
2181 def test_to_sci_string(self):
2182 c = Context()
2183 d = c.to_sci_string(Decimal(10))
2184 self.assertEqual(c.to_sci_string(10), d)
2185 self.assertRaises(TypeError, c.to_sci_string, '10')
2186
2187 def test_to_integral_exact(self):
2188 c = Context()
2189 d = c.to_integral_exact(Decimal(10))
2190 self.assertEqual(c.to_integral_exact(10), d)
2191 self.assertRaises(TypeError, c.to_integral_exact, '10')
2192
2193 def test_to_integral_value(self):
2194 c = Context()
2195 d = c.to_integral_value(Decimal(10))
2196 self.assertEqual(c.to_integral_value(10), d)
2197 self.assertRaises(TypeError, c.to_integral_value, '10')
2198
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002199class WithStatementTest(unittest.TestCase):
2200 # Can't do these as docstrings until Python 2.6
2201 # as doctest can't handle __future__ statements
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002202
2203 def test_localcontext(self):
Nick Coghlanced12182006-09-02 03:54:17 +00002204 # Use a copy of the current context in the block
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002205 orig_ctx = getcontext()
2206 with localcontext() as enter_ctx:
2207 set_ctx = getcontext()
2208 final_ctx = getcontext()
Ezio Melotti856a3be2010-04-03 14:51:00 +00002209 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
2210 self.assertIsNot(orig_ctx, set_ctx, 'did not copy the context')
2211 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002212
2213 def test_localcontextarg(self):
Nick Coghlanced12182006-09-02 03:54:17 +00002214 # Use a copy of the supplied context in the block
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002215 orig_ctx = getcontext()
2216 new_ctx = Context(prec=42)
2217 with localcontext(new_ctx) as enter_ctx:
2218 set_ctx = getcontext()
2219 final_ctx = getcontext()
Ezio Melotti856a3be2010-04-03 14:51:00 +00002220 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
2221 self.assertEqual(set_ctx.prec, new_ctx.prec, 'did not set correct context')
2222 self.assertIsNot(new_ctx, set_ctx, 'did not copy the context')
2223 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
Nick Coghlan8b6999b2006-08-31 12:00:43 +00002224
Facundo Batista353750c2007-09-13 18:13:15 +00002225class ContextFlags(unittest.TestCase):
2226 def test_flags_irrelevant(self):
2227 # check that the result (numeric result + flags raised) of an
2228 # arithmetic operation doesn't depend on the current flags
2229
2230 context = Context(prec=9, Emin = -999999999, Emax = 999999999,
2231 rounding=ROUND_HALF_EVEN, traps=[], flags=[])
2232
2233 # operations that raise various flags, in the form (function, arglist)
2234 operations = [
2235 (context._apply, [Decimal("100E-1000000009")]),
2236 (context.sqrt, [Decimal(2)]),
2237 (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]),
2238 (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]),
2239 (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]),
2240 ]
2241
2242 # try various flags individually, then a whole lot at once
2243 flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal],
2244 [Inexact, Rounded, Underflow, Clamped, Subnormal]]
2245
2246 for fn, args in operations:
2247 # find answer and flags raised using a clean context
2248 context.clear_flags()
2249 ans = fn(*args)
2250 flags = [k for k, v in context.flags.items() if v]
2251
2252 for extra_flags in flagsets:
2253 # set flags, before calling operation
2254 context.clear_flags()
2255 for flag in extra_flags:
2256 context._raise_error(flag)
2257 new_ans = fn(*args)
2258
2259 # flags that we expect to be set after the operation
2260 expected_flags = list(flags)
2261 for flag in extra_flags:
2262 if flag not in expected_flags:
2263 expected_flags.append(flag)
Facundo Batista353750c2007-09-13 18:13:15 +00002264
2265 # flags we actually got
2266 new_flags = [k for k,v in context.flags.items() if v]
Facundo Batista353750c2007-09-13 18:13:15 +00002267
2268 self.assertEqual(ans, new_ans,
2269 "operation produces different answers depending on flags set: " +
2270 "expected %s, got %s." % (ans, new_ans))
Florent Xicluna8f43cec2010-03-21 10:51:40 +00002271 self.assertItemsEqual(new_flags, expected_flags,
Facundo Batista353750c2007-09-13 18:13:15 +00002272 "operation raises different flags depending on flags set: " +
2273 "expected %s, got %s" % (expected_flags, new_flags))
2274
2275def test_main(arith=False, verbose=None, todo_tests=None, debug=None):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002276 """ Execute the tests.
2277
Raymond Hettingered20ad82004-09-04 20:09:13 +00002278 Runs all arithmetic tests if arith is True or if the "decimal" resource
2279 is enabled in regrtest.py
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002280 """
Raymond Hettingered20ad82004-09-04 20:09:13 +00002281
Neal Norwitzce4a9c92006-04-09 08:36:46 +00002282 init()
Facundo Batista353750c2007-09-13 18:13:15 +00002283 global TEST_ALL, DEBUG
Raymond Hettingered20ad82004-09-04 20:09:13 +00002284 TEST_ALL = arith or is_resource_enabled('decimal')
Facundo Batista353750c2007-09-13 18:13:15 +00002285 DEBUG = debug
Raymond Hettingered20ad82004-09-04 20:09:13 +00002286
Facundo Batista353750c2007-09-13 18:13:15 +00002287 if todo_tests is None:
2288 test_classes = [
2289 DecimalExplicitConstructionTest,
2290 DecimalImplicitConstructionTest,
2291 DecimalArithmeticOperatorsTest,
Mark Dickinson1ddf1d82008-02-29 02:16:37 +00002292 DecimalFormatTest,
Facundo Batista353750c2007-09-13 18:13:15 +00002293 DecimalUseOfContextTest,
2294 DecimalUsabilityTest,
2295 DecimalPythonAPItests,
2296 ContextAPItests,
2297 DecimalTest,
2298 WithStatementTest,
2299 ContextFlags
2300 ]
2301 else:
2302 test_classes = [DecimalTest]
2303
2304 # Dynamically build custom test definition for each file in the test
2305 # directory and add the definitions to the DecimalTest class. This
2306 # procedure insures that new files do not get skipped.
2307 for filename in os.listdir(directory):
2308 if '.decTest' not in filename or filename.startswith("."):
2309 continue
2310 head, tail = filename.split('.')
2311 if todo_tests is not None and head not in todo_tests:
2312 continue
2313 tester = lambda self, f=filename: self.eval_file(directory + f)
2314 setattr(DecimalTest, 'test_' + head, tester)
2315 del filename, head, tail, tester
2316
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002317
Tim Peters46cc7022006-03-31 04:11:16 +00002318 try:
2319 run_unittest(*test_classes)
Facundo Batista353750c2007-09-13 18:13:15 +00002320 if todo_tests is None:
2321 import decimal as DecimalModule
2322 run_doctest(DecimalModule, verbose)
Tim Peters46cc7022006-03-31 04:11:16 +00002323 finally:
2324 setcontext(ORIGINAL_CONTEXT)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002325
2326if __name__ == '__main__':
Facundo Batista353750c2007-09-13 18:13:15 +00002327 import optparse
2328 p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]")
2329 p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test')
2330 p.add_option('--skip', '-s', action='store_true', help='skip over 90% of the arithmetic tests')
2331 (opt, args) = p.parse_args()
2332
2333 if opt.skip:
2334 test_main(arith=False, verbose=True)
2335 elif args:
2336 test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002337 else:
Facundo Batista353750c2007-09-13 18:13:15 +00002338 test_main(arith=True, verbose=True)