blob: d00ed5aa40c75b116c4e0d2bbd63bfccc459314e [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
Stefan Krah1919b7e2012-03-21 18:25:23 +010019 http://speleotrove.com/decimal/dectest.zip
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000020
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
Christian Heimes400adb02008-02-01 08:12:03 +000027import math
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000028import os, sys
Mark Dickinsonac256ab2010-04-03 11:08:14 +000029import operator
Mark Dickinsonb1d8e322010-05-22 18:35:36 +000030import warnings
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000031import pickle, copy
Christian Heimes400adb02008-02-01 08:12:03 +000032import unittest
Raymond Hettinger82417ca2009-02-03 03:54:28 +000033import numbers
Stefan Krah1919b7e2012-03-21 18:25:23 +010034import locale
Eric Smith3ab08ca2010-12-04 15:17:38 +000035from test.support import (run_unittest, run_doctest, is_resource_enabled,
36 requires_IEEE_754)
Stefan Krah1919b7e2012-03-21 18:25:23 +010037from test.support import check_warnings, import_fresh_module, TestFailed
Raymond Hettinger0aeac102004-07-05 22:53:03 +000038import random
Stefan Krah1919b7e2012-03-21 18:25:23 +010039import time
40import warnings
Raymond Hettinger7e71fa52004-12-18 19:07:19 +000041try:
42 import threading
43except ImportError:
44 threading = None
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000045
Raymond Hettingerfed52962004-07-14 15:41:57 +000046
Stefan Krah1919b7e2012-03-21 18:25:23 +010047C = import_fresh_module('decimal', fresh=['_decimal'])
48P = import_fresh_module('decimal', blocked=['_decimal'])
49orig_sys_decimal = sys.modules['decimal']
50
51# fractions module must import the correct decimal module.
52cfractions = import_fresh_module('fractions', fresh=['fractions'])
53sys.modules['decimal'] = P
54pfractions = import_fresh_module('fractions', fresh=['fractions'])
55sys.modules['decimal'] = C
56fractions = {C:cfractions, P:pfractions}
57sys.modules['decimal'] = orig_sys_decimal
58
59
60# Useful Test Constant
61Signals = {
62 C: tuple(C.getcontext().flags.keys()) if C else None,
63 P: tuple(P.getcontext().flags.keys())
64}
Mark Dickinsonc69160e2010-05-04 14:35:33 +000065# Signals ordered with respect to precedence: when an operation
66# produces multiple signals, signals occurring later in the list
67# should be handled before those occurring earlier in the list.
Stefan Krah1919b7e2012-03-21 18:25:23 +010068OrderedSignals = {
69 C: [C.Clamped, C.Rounded, C.Inexact, C.Subnormal, C.Underflow,
70 C.Overflow, C.DivisionByZero, C.InvalidOperation,
71 C.FloatOperation] if C else None,
72 P: [P.Clamped, P.Rounded, P.Inexact, P.Subnormal, P.Underflow,
73 P.Overflow, P.DivisionByZero, P.InvalidOperation,
74 P.FloatOperation]
75}
76def assert_signals(cls, context, attr, expected):
77 d = getattr(context, attr)
78 cls.assertTrue(all(d[s] if s in expected else not d[s] for s in d))
79
80RoundingModes = {
81 C: (C.ROUND_UP, C.ROUND_DOWN, C.ROUND_CEILING, C.ROUND_FLOOR,
82 C.ROUND_HALF_UP, C.ROUND_HALF_DOWN, C.ROUND_HALF_EVEN,
83 C.ROUND_05UP) if C else None,
84 P: (P.ROUND_UP, P.ROUND_DOWN, P.ROUND_CEILING, P.ROUND_FLOOR,
85 P.ROUND_HALF_UP, P.ROUND_HALF_DOWN, P.ROUND_HALF_EVEN,
86 P.ROUND_05UP)
87}
Mark Dickinsonc69160e2010-05-04 14:35:33 +000088
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000089# Tests are built around these assumed context defaults.
90# test_main() restores the original context.
Stefan Krah1919b7e2012-03-21 18:25:23 +010091ORIGINAL_CONTEXT = {
92 C: C.getcontext().copy() if C else None,
93 P: P.getcontext().copy()
94}
95def init(m):
96 if not m: return
97 DefaultTestContext = m.Context(
98 prec=9, rounding=m.ROUND_HALF_EVEN, traps=dict.fromkeys(Signals[m], 0)
99 )
100 m.setcontext(DefaultTestContext)
Raymond Hettinger6ea48452004-07-03 12:26:21 +0000101
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000102TESTDATADIR = 'decimaltestdata'
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000103if __name__ == '__main__':
104 file = sys.argv[0]
105else:
106 file = __file__
107testdir = os.path.dirname(file) or os.curdir
Raymond Hettinger267b8682005-03-27 10:47:39 +0000108directory = testdir + os.sep + TESTDATADIR + os.sep
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000109
Raymond Hettinger267b8682005-03-27 10:47:39 +0000110skip_expected = not os.path.isdir(directory)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000111
112# Make sure it actually raises errors when not expected and caught in flags
113# Slower, since it runs some things several times.
114EXTENDEDERRORTEST = False
115
Stefan Krah1919b7e2012-03-21 18:25:23 +0100116# Test extra functionality in the C version (-DEXTRA_FUNCTIONALITY).
117EXTRA_FUNCTIONALITY = True if hasattr(C, 'DecClamped') else False
118requires_extra_functionality = unittest.skipUnless(
119 EXTRA_FUNCTIONALITY, "test requires build with -DEXTRA_FUNCTIONALITY")
120skip_if_extra_functionality = unittest.skipIf(
121 EXTRA_FUNCTIONALITY, "test requires regular build")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000122
123
Stefan Krah1919b7e2012-03-21 18:25:23 +0100124class IBMTestCases(unittest.TestCase):
125 """Class which tests the Decimal class against the IBM test cases."""
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000126
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000127 def setUp(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100128 self.context = self.decimal.Context()
129 self.readcontext = self.decimal.Context()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000130 self.ignore_list = ['#']
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000131
Stefan Krah1919b7e2012-03-21 18:25:23 +0100132 # List of individual .decTest test ids that correspond to tests that
133 # we're skipping for one reason or another.
134 self.skipped_test_ids = set([
135 # Skip implementation-specific scaleb tests.
136 'scbx164',
137 'scbx165',
138
139 # For some operations (currently exp, ln, log10, power), the decNumber
140 # reference implementation imposes additional restrictions on the context
141 # and operands. These restrictions are not part of the specification;
142 # however, the effect of these restrictions does show up in some of the
143 # testcases. We skip testcases that violate these restrictions, since
144 # Decimal behaves differently from decNumber for these testcases so these
145 # testcases would otherwise fail.
146 'expx901',
147 'expx902',
148 'expx903',
149 'expx905',
150 'lnx901',
151 'lnx902',
152 'lnx903',
153 'lnx905',
154 'logx901',
155 'logx902',
156 'logx903',
157 'logx905',
158 'powx1183',
159 'powx1184',
160 'powx4001',
161 'powx4002',
162 'powx4003',
163 'powx4005',
164 'powx4008',
165 'powx4010',
166 'powx4012',
167 'powx4014',
168 ])
169
170 if self.decimal == C:
171 # status has additional Subnormal, Underflow
172 self.skipped_test_ids.add('pwsx803')
173 self.skipped_test_ids.add('pwsx805')
174 # Correct rounding (skipped for decNumber, too)
175 self.skipped_test_ids.add('powx4302')
176 self.skipped_test_ids.add('powx4303')
177 self.skipped_test_ids.add('powx4342')
178 self.skipped_test_ids.add('powx4343')
179 # http://bugs.python.org/issue7049
180 self.skipped_test_ids.add('pwmx325')
181 self.skipped_test_ids.add('pwmx326')
182
183 # Map test directives to setter functions.
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000184 self.ChangeDict = {'precision' : self.change_precision,
Stefan Krah1919b7e2012-03-21 18:25:23 +0100185 'rounding' : self.change_rounding_method,
186 'maxexponent' : self.change_max_exponent,
187 'minexponent' : self.change_min_exponent,
188 'clamp' : self.change_clamp}
189
190 # Name adapter to be able to change the Decimal and Context
191 # interface without changing the test files from Cowlishaw.
192 self.NameAdapter = {'and':'logical_and',
193 'apply':'_apply',
194 'class':'number_class',
195 'comparesig':'compare_signal',
196 'comparetotal':'compare_total',
197 'comparetotmag':'compare_total_mag',
198 'copy':'copy_decimal',
199 'copyabs':'copy_abs',
200 'copynegate':'copy_negate',
201 'copysign':'copy_sign',
202 'divideint':'divide_int',
203 'invert':'logical_invert',
204 'iscanonical':'is_canonical',
205 'isfinite':'is_finite',
206 'isinfinite':'is_infinite',
207 'isnan':'is_nan',
208 'isnormal':'is_normal',
209 'isqnan':'is_qnan',
210 'issigned':'is_signed',
211 'issnan':'is_snan',
212 'issubnormal':'is_subnormal',
213 'iszero':'is_zero',
214 'maxmag':'max_mag',
215 'minmag':'min_mag',
216 'nextminus':'next_minus',
217 'nextplus':'next_plus',
218 'nexttoward':'next_toward',
219 'or':'logical_or',
220 'reduce':'normalize',
221 'remaindernear':'remainder_near',
222 'samequantum':'same_quantum',
223 'squareroot':'sqrt',
224 'toeng':'to_eng_string',
225 'tointegral':'to_integral_value',
226 'tointegralx':'to_integral_exact',
227 'tosci':'to_sci_string',
228 'xor':'logical_xor'}
229
230 # Map test-case names to roundings.
231 self.RoundingDict = {'ceiling' : self.decimal.ROUND_CEILING,
232 'down' : self.decimal.ROUND_DOWN,
233 'floor' : self.decimal.ROUND_FLOOR,
234 'half_down' : self.decimal.ROUND_HALF_DOWN,
235 'half_even' : self.decimal.ROUND_HALF_EVEN,
236 'half_up' : self.decimal.ROUND_HALF_UP,
237 'up' : self.decimal.ROUND_UP,
238 '05up' : self.decimal.ROUND_05UP}
239
240 # Map the test cases' error names to the actual errors.
241 self.ErrorNames = {'clamped' : self.decimal.Clamped,
242 'conversion_syntax' : self.decimal.InvalidOperation,
243 'division_by_zero' : self.decimal.DivisionByZero,
244 'division_impossible' : self.decimal.InvalidOperation,
245 'division_undefined' : self.decimal.InvalidOperation,
246 'inexact' : self.decimal.Inexact,
247 'invalid_context' : self.decimal.InvalidOperation,
248 'invalid_operation' : self.decimal.InvalidOperation,
249 'overflow' : self.decimal.Overflow,
250 'rounded' : self.decimal.Rounded,
251 'subnormal' : self.decimal.Subnormal,
252 'underflow' : self.decimal.Underflow}
253
254 # The following functions return True/False rather than a
255 # Decimal instance.
256 self.LogicalFunctions = ('is_canonical',
257 'is_finite',
258 'is_infinite',
259 'is_nan',
260 'is_normal',
261 'is_qnan',
262 'is_signed',
263 'is_snan',
264 'is_subnormal',
265 'is_zero',
266 'same_quantum')
267
268 def read_unlimited(self, v, context):
269 """Work around the limitations of the 32-bit _decimal version. The
270 guaranteed maximum values for prec, Emax etc. are 425000000,
271 but higher values usually work, except for rare corner cases.
272 In particular, all of the IBM tests pass with maximum values
273 of 1070000000."""
274 if self.decimal == C and self.decimal.MAX_EMAX == 425000000:
275 self.readcontext._unsafe_setprec(1070000000)
276 self.readcontext._unsafe_setemax(1070000000)
277 self.readcontext._unsafe_setemin(-1070000000)
278 return self.readcontext.create_decimal(v)
279 else:
280 return self.decimal.Decimal(v, context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000281
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000282 def eval_file(self, file):
283 global skip_expected
284 if skip_expected:
Benjamin Petersone549ead2009-03-28 21:42:05 +0000285 raise unittest.SkipTest
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000286 return
Antoine Pitrou92f60ed2010-10-14 22:11:44 +0000287 with open(file) as f:
288 for line in f:
289 line = line.replace('\r\n', '').replace('\n', '')
290 #print line
291 try:
292 t = self.eval_line(line)
Stefan Krah1919b7e2012-03-21 18:25:23 +0100293 except self.decimal.DecimalException as exception:
Ezio Melotti13925002011-03-16 11:05:33 +0200294 #Exception raised where there shouldn't have been one.
Antoine Pitrou92f60ed2010-10-14 22:11:44 +0000295 self.fail('Exception "'+exception.__class__.__name__ + '" raised on line '+line)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000296
297 return
298
299 def eval_line(self, s):
300 if s.find(' -> ') >= 0 and s[:2] != '--' and not s.startswith(' --'):
301 s = (s.split('->')[0] + '->' +
302 s.split('->')[1].split('--')[0]).strip()
303 else:
304 s = s.split('--')[0].strip()
305
306 for ignore in self.ignore_list:
307 if s.find(ignore) >= 0:
308 #print s.split()[0], 'NotImplemented--', ignore
309 return
310 if not s:
311 return
312 elif ':' in s:
313 return self.eval_directive(s)
314 else:
315 return self.eval_equation(s)
316
317 def eval_directive(self, s):
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000318 funct, value = (x.strip().lower() for x in s.split(':'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000319 if funct == 'rounding':
Stefan Krah1919b7e2012-03-21 18:25:23 +0100320 value = self.RoundingDict[value]
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000321 else:
322 try:
323 value = int(value)
324 except ValueError:
325 pass
326
Stefan Krah1919b7e2012-03-21 18:25:23 +0100327 funct = self.ChangeDict.get(funct, (lambda *args: None))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000328 funct(value)
329
330 def eval_equation(self, s):
Raymond Hettingered20ad82004-09-04 20:09:13 +0000331
332 if not TEST_ALL and random.random() < 0.90:
333 return
334
Stefan Krah1919b7e2012-03-21 18:25:23 +0100335 self.context.clear_flags()
336
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000337 try:
338 Sides = s.split('->')
339 L = Sides[0].strip().split()
340 id = L[0]
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000341 if DEBUG:
342 print("Test ", id, end=" ")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000343 funct = L[1].lower()
344 valstemp = L[2:]
345 L = Sides[1].strip().split()
346 ans = L[0]
347 exceptions = L[1:]
348 except (TypeError, AttributeError, IndexError):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100349 raise self.decimal.InvalidOperation
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000350 def FixQuotes(val):
351 val = val.replace("''", 'SingleQuote').replace('""', 'DoubleQuote')
352 val = val.replace("'", '').replace('"', '')
353 val = val.replace('SingleQuote', "'").replace('DoubleQuote', '"')
354 return val
Mark Dickinson8a546532009-10-08 16:30:38 +0000355
Stefan Krah1919b7e2012-03-21 18:25:23 +0100356 if id in self.skipped_test_ids:
Mark Dickinson8a546532009-10-08 16:30:38 +0000357 return
358
Stefan Krah1919b7e2012-03-21 18:25:23 +0100359 fname = self.NameAdapter.get(funct, funct)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000360 if fname == 'rescale':
361 return
362 funct = getattr(self.context, fname)
363 vals = []
364 conglomerate = ''
365 quote = 0
Stefan Krah1919b7e2012-03-21 18:25:23 +0100366 theirexceptions = [self.ErrorNames[x.lower()] for x in exceptions]
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000367
Stefan Krah1919b7e2012-03-21 18:25:23 +0100368 for exception in Signals[self.decimal]:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000369 self.context.traps[exception] = 1 #Catch these bugs...
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000370 for exception in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000371 self.context.traps[exception] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000372 for i, val in enumerate(valstemp):
373 if val.count("'") % 2 == 1:
374 quote = 1 - quote
375 if quote:
376 conglomerate = conglomerate + ' ' + val
377 continue
378 else:
379 val = conglomerate + val
380 conglomerate = ''
381 v = FixQuotes(val)
382 if fname in ('to_sci_string', 'to_eng_string'):
383 if EXTENDEDERRORTEST:
384 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000385 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000386 try:
387 funct(self.context.create_decimal(v))
388 except error:
389 pass
Stefan Krah1919b7e2012-03-21 18:25:23 +0100390 except Signals[self.decimal] as e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000391 self.fail("Raised %s in %s when %s disabled" % \
392 (e, s, error))
393 else:
394 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000395 self.context.traps[error] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000396 v = self.context.create_decimal(v)
397 else:
Stefan Krah1919b7e2012-03-21 18:25:23 +0100398 v = self.read_unlimited(v, self.context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000399 vals.append(v)
400
401 ans = FixQuotes(ans)
402
403 if EXTENDEDERRORTEST and fname not in ('to_sci_string', 'to_eng_string'):
404 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000405 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000406 try:
407 funct(*vals)
408 except error:
409 pass
Stefan Krah1919b7e2012-03-21 18:25:23 +0100410 except Signals[self.decimal] as e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000411 self.fail("Raised %s in %s when %s disabled" % \
412 (e, s, error))
413 else:
414 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000415 self.context.traps[error] = 0
Mark Dickinsonc69160e2010-05-04 14:35:33 +0000416
417 # as above, but add traps cumulatively, to check precedence
Stefan Krah1919b7e2012-03-21 18:25:23 +0100418 ordered_errors = [e for e in OrderedSignals[self.decimal] if e in theirexceptions]
Mark Dickinsonc69160e2010-05-04 14:35:33 +0000419 for error in ordered_errors:
420 self.context.traps[error] = 1
421 try:
422 funct(*vals)
423 except error:
424 pass
Stefan Krah1919b7e2012-03-21 18:25:23 +0100425 except Signals[self.decimal] as e:
Mark Dickinsonc69160e2010-05-04 14:35:33 +0000426 self.fail("Raised %s in %s; expected %s" %
427 (type(e), s, error))
428 else:
429 self.fail("Did not raise %s in %s" % (error, s))
430 # reset traps
431 for error in ordered_errors:
432 self.context.traps[error] = 0
433
434
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000435 if DEBUG:
436 print("--", self.context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000437 try:
438 result = str(funct(*vals))
Stefan Krah1919b7e2012-03-21 18:25:23 +0100439 if fname in self.LogicalFunctions:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000440 result = str(int(eval(result))) # 'True', 'False' -> '1', '0'
Stefan Krah1919b7e2012-03-21 18:25:23 +0100441 except Signals[self.decimal] as error:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000442 self.fail("Raised %s in %s" % (error, s))
443 except: #Catch any error long enough to state the test case.
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000444 print("ERROR:", s)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000445 raise
446
447 myexceptions = self.getexceptions()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000448
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000449 myexceptions.sort(key=repr)
450 theirexceptions.sort(key=repr)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000451
452 self.assertEqual(result, ans,
453 'Incorrect answer for ' + s + ' -- got ' + result)
Stefan Krah1919b7e2012-03-21 18:25:23 +0100454
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000455 self.assertEqual(myexceptions, theirexceptions,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000456 'Incorrect flags set in ' + s + ' -- got ' + str(myexceptions))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000457 return
458
459 def getexceptions(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100460 return [e for e in Signals[self.decimal] if self.context.flags[e]]
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000461
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000462 def change_precision(self, prec):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100463 if self.decimal == C and self.decimal.MAX_PREC == 425000000:
464 self.context._unsafe_setprec(prec)
465 else:
466 self.context.prec = prec
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000467 def change_rounding_method(self, rounding):
468 self.context.rounding = rounding
469 def change_min_exponent(self, exp):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100470 if self.decimal == C and self.decimal.MAX_PREC == 425000000:
471 self.context._unsafe_setemin(exp)
472 else:
473 self.context.Emin = exp
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000474 def change_max_exponent(self, exp):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100475 if self.decimal == C and self.decimal.MAX_PREC == 425000000:
476 self.context._unsafe_setemax(exp)
477 else:
478 self.context.Emax = exp
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000479 def change_clamp(self, clamp):
Mark Dickinsonb1d8e322010-05-22 18:35:36 +0000480 self.context.clamp = clamp
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000481
Stefan Krah1919b7e2012-03-21 18:25:23 +0100482class CIBMTestCases(IBMTestCases):
483 decimal = C
484class PyIBMTestCases(IBMTestCases):
485 decimal = P
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000486
487# The following classes test the behaviour of Decimal according to PEP 327
488
Stefan Krah1919b7e2012-03-21 18:25:23 +0100489class ExplicitConstructionTest(unittest.TestCase):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000490 '''Unit tests for Explicit Construction cases of Decimal.'''
491
492 def test_explicit_empty(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100493 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000494 self.assertEqual(Decimal(), Decimal("0"))
495
496 def test_explicit_from_None(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100497 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000498 self.assertRaises(TypeError, Decimal, None)
499
500 def test_explicit_from_int(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100501 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000502
503 #positive
504 d = Decimal(45)
505 self.assertEqual(str(d), '45')
506
507 #very large positive
508 d = Decimal(500000123)
509 self.assertEqual(str(d), '500000123')
510
511 #negative
512 d = Decimal(-45)
513 self.assertEqual(str(d), '-45')
514
515 #zero
516 d = Decimal(0)
517 self.assertEqual(str(d), '0')
518
Stefan Krah1919b7e2012-03-21 18:25:23 +0100519 # single word longs
520 for n in range(0, 32):
521 for sign in (-1, 1):
522 for x in range(-5, 5):
523 i = sign * (2**n + x)
524 d = Decimal(i)
525 self.assertEqual(str(d), str(i))
526
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000527 def test_explicit_from_string(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100528 Decimal = self.decimal.Decimal
529 InvalidOperation = self.decimal.InvalidOperation
530 localcontext = self.decimal.localcontext
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000531
532 #empty
533 self.assertEqual(str(Decimal('')), 'NaN')
534
535 #int
536 self.assertEqual(str(Decimal('45')), '45')
537
538 #float
539 self.assertEqual(str(Decimal('45.34')), '45.34')
540
541 #engineer notation
542 self.assertEqual(str(Decimal('45e2')), '4.5E+3')
543
544 #just not a number
545 self.assertEqual(str(Decimal('ugly')), 'NaN')
546
Christian Heimesa62da1d2008-01-12 19:39:10 +0000547 #leading and trailing whitespace permitted
548 self.assertEqual(str(Decimal('1.3E4 \n')), '1.3E+4')
549 self.assertEqual(str(Decimal(' -7.89')), '-7.89')
Stefan Krah1919b7e2012-03-21 18:25:23 +0100550 self.assertEqual(str(Decimal(" 3.45679 ")), '3.45679')
551
552 # unicode whitespace
553 for lead in ["", ' ', '\u00a0', '\u205f']:
554 for trail in ["", ' ', '\u00a0', '\u205f']:
555 self.assertEqual(str(Decimal(lead + '9.311E+28' + trail)),
556 '9.311E+28')
557
558 with localcontext() as c:
559 c.traps[InvalidOperation] = True
560 # Invalid string
561 self.assertRaises(InvalidOperation, Decimal, "xyz")
562 # Two arguments max
563 self.assertRaises(TypeError, Decimal, "1234", "x", "y")
564
565 # space within the numeric part
566 self.assertRaises(InvalidOperation, Decimal, "1\u00a02\u00a03")
567 self.assertRaises(InvalidOperation, Decimal, "\u00a01\u00a02\u00a0")
568
569 # unicode whitespace
570 self.assertRaises(InvalidOperation, Decimal, "\u00a0")
571 self.assertRaises(InvalidOperation, Decimal, "\u00a0\u00a0")
572
573 # embedded NUL
574 self.assertRaises(InvalidOperation, Decimal, "12\u00003")
575
Christian Heimesa62da1d2008-01-12 19:39:10 +0000576
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000577 def test_explicit_from_tuples(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100578 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000579
580 #zero
581 d = Decimal( (0, (0,), 0) )
582 self.assertEqual(str(d), '0')
583
584 #int
585 d = Decimal( (1, (4, 5), 0) )
586 self.assertEqual(str(d), '-45')
587
588 #float
589 d = Decimal( (0, (4, 5, 3, 4), -2) )
590 self.assertEqual(str(d), '45.34')
591
592 #weird
593 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
594 self.assertEqual(str(d), '-4.34913534E-17')
595
Stefan Krah1919b7e2012-03-21 18:25:23 +0100596 #inf
597 d = Decimal( (0, (), "F") )
598 self.assertEqual(str(d), 'Infinity')
599
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000600 #wrong number of items
601 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1)) )
602
603 #bad sign
604 self.assertRaises(ValueError, Decimal, (8, (4, 3, 4, 9, 1), 2) )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000605 self.assertRaises(ValueError, Decimal, (0., (4, 3, 4, 9, 1), 2) )
606 self.assertRaises(ValueError, Decimal, (Decimal(1), (4, 3, 4, 9, 1), 2))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000607
608 #bad exp
609 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 'wrong!') )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000610 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 0.) )
611 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), '1') )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000612
613 #bad coefficients
Stefan Krah1919b7e2012-03-21 18:25:23 +0100614 self.assertRaises(ValueError, Decimal, (1, "xyz", 2) )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000615 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, None, 1), 2) )
616 self.assertRaises(ValueError, Decimal, (1, (4, -3, 4, 9, 1), 2) )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000617 self.assertRaises(ValueError, Decimal, (1, (4, 10, 4, 9, 1), 2) )
Guido van Rossum0d3fb8a2007-11-26 23:23:18 +0000618 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 'a', 1), 2) )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000619
Stefan Krah1919b7e2012-03-21 18:25:23 +0100620 def test_explicit_from_list(self):
621 Decimal = self.decimal.Decimal
622
623 d = Decimal([0, [0], 0])
624 self.assertEqual(str(d), '0')
625
626 d = Decimal([1, [4, 3, 4, 9, 1, 3, 5, 3, 4], -25])
627 self.assertEqual(str(d), '-4.34913534E-17')
628
629 d = Decimal([1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25])
630 self.assertEqual(str(d), '-4.34913534E-17')
631
632 d = Decimal((1, [4, 3, 4, 9, 1, 3, 5, 3, 4], -25))
633 self.assertEqual(str(d), '-4.34913534E-17')
634
Antoine Pitrou503ab332010-03-30 18:56:19 +0000635 def test_explicit_from_bool(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100636 Decimal = self.decimal.Decimal
637
Antoine Pitrou503ab332010-03-30 18:56:19 +0000638 self.assertIs(bool(Decimal(0)), False)
639 self.assertIs(bool(Decimal(1)), True)
640 self.assertEqual(Decimal(False), Decimal(0))
641 self.assertEqual(Decimal(True), Decimal(1))
642
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000643 def test_explicit_from_Decimal(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100644 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000645
646 #positive
647 d = Decimal(45)
648 e = Decimal(d)
649 self.assertEqual(str(e), '45')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000650
651 #very large positive
652 d = Decimal(500000123)
653 e = Decimal(d)
654 self.assertEqual(str(e), '500000123')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000655
656 #negative
657 d = Decimal(-45)
658 e = Decimal(d)
659 self.assertEqual(str(e), '-45')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000660
661 #zero
662 d = Decimal(0)
663 e = Decimal(d)
664 self.assertEqual(str(e), '0')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000665
Raymond Hettinger96798592010-04-02 16:58:27 +0000666 @requires_IEEE_754
667 def test_explicit_from_float(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100668
669 Decimal = self.decimal.Decimal
670
Raymond Hettinger96798592010-04-02 16:58:27 +0000671 r = Decimal(0.1)
672 self.assertEqual(type(r), Decimal)
673 self.assertEqual(str(r),
674 '0.1000000000000000055511151231257827021181583404541015625')
675 self.assertTrue(Decimal(float('nan')).is_qnan())
676 self.assertTrue(Decimal(float('inf')).is_infinite())
677 self.assertTrue(Decimal(float('-inf')).is_infinite())
678 self.assertEqual(str(Decimal(float('nan'))),
679 str(Decimal('NaN')))
680 self.assertEqual(str(Decimal(float('inf'))),
681 str(Decimal('Infinity')))
682 self.assertEqual(str(Decimal(float('-inf'))),
683 str(Decimal('-Infinity')))
684 self.assertEqual(str(Decimal(float('-0.0'))),
685 str(Decimal('-0')))
686 for i in range(200):
687 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
688 self.assertEqual(x, float(Decimal(x))) # roundtrip
689
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000690 def test_explicit_context_create_decimal(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100691 Decimal = self.decimal.Decimal
692 InvalidOperation = self.decimal.InvalidOperation
693 Rounded = self.decimal.Rounded
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000694
Stefan Krah1919b7e2012-03-21 18:25:23 +0100695 nc = copy.copy(self.decimal.getcontext())
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000696 nc.prec = 3
697
698 # empty
Raymond Hettingerfed52962004-07-14 15:41:57 +0000699 d = Decimal()
700 self.assertEqual(str(d), '0')
701 d = nc.create_decimal()
702 self.assertEqual(str(d), '0')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000703
704 # from None
705 self.assertRaises(TypeError, nc.create_decimal, None)
706
707 # from int
708 d = nc.create_decimal(456)
Ezio Melottie9615932010-01-24 19:26:24 +0000709 self.assertIsInstance(d, Decimal)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000710 self.assertEqual(nc.create_decimal(45678),
711 nc.create_decimal('457E+2'))
712
713 # from string
714 d = Decimal('456789')
715 self.assertEqual(str(d), '456789')
716 d = nc.create_decimal('456789')
717 self.assertEqual(str(d), '4.57E+5')
Christian Heimesa62da1d2008-01-12 19:39:10 +0000718 # leading and trailing whitespace should result in a NaN;
719 # spaces are already checked in Cowlishaw's test-suite, so
720 # here we just check that a trailing newline results in a NaN
721 self.assertEqual(str(nc.create_decimal('3.14\n')), 'NaN')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000722
723 # from tuples
724 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
725 self.assertEqual(str(d), '-4.34913534E-17')
726 d = nc.create_decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
727 self.assertEqual(str(d), '-4.35E-17')
728
729 # from Decimal
730 prevdec = Decimal(500000123)
731 d = Decimal(prevdec)
732 self.assertEqual(str(d), '500000123')
733 d = nc.create_decimal(prevdec)
734 self.assertEqual(str(d), '5.00E+8')
735
Stefan Krah1919b7e2012-03-21 18:25:23 +0100736 # more integers
737 nc.prec = 28
738 nc.traps[InvalidOperation] = True
739
740 for v in [-2**63-1, -2**63, -2**31-1, -2**31, 0,
741 2**31-1, 2**31, 2**63-1, 2**63]:
742 d = nc.create_decimal(v)
743 self.assertTrue(isinstance(d, Decimal))
744 self.assertEqual(int(d), v)
745
746 nc.prec = 3
747 nc.traps[Rounded] = True
748 self.assertRaises(Rounded, nc.create_decimal, 1234)
749
750 # from string
751 nc.prec = 28
752 self.assertEqual(str(nc.create_decimal('0E-017')), '0E-17')
753 self.assertEqual(str(nc.create_decimal('45')), '45')
754 self.assertEqual(str(nc.create_decimal('-Inf')), '-Infinity')
755 self.assertEqual(str(nc.create_decimal('NaN123')), 'NaN123')
756
757 # invalid arguments
758 self.assertRaises(InvalidOperation, nc.create_decimal, "xyz")
759 self.assertRaises(ValueError, nc.create_decimal, (1, "xyz", -25))
760 self.assertRaises(TypeError, nc.create_decimal, "1234", "5678")
761
762 # too many NaN payload digits
763 nc.prec = 3
764 self.assertRaises(InvalidOperation, nc.create_decimal, 'NaN12345')
765 self.assertRaises(InvalidOperation, nc.create_decimal,
766 Decimal('NaN12345'))
767
768 nc.traps[InvalidOperation] = False
769 self.assertEqual(str(nc.create_decimal('NaN12345')), 'NaN')
770 self.assertTrue(nc.flags[InvalidOperation])
771
772 nc.flags[InvalidOperation] = False
773 self.assertEqual(str(nc.create_decimal(Decimal('NaN12345'))), 'NaN')
774 self.assertTrue(nc.flags[InvalidOperation])
775
776 def test_explicit_context_create_from_float(self):
777
778 Decimal = self.decimal.Decimal
779
780 nc = self.decimal.Context()
781 r = nc.create_decimal(0.1)
782 self.assertEqual(type(r), Decimal)
783 self.assertEqual(str(r), '0.1000000000000000055511151231')
784 self.assertTrue(nc.create_decimal(float('nan')).is_qnan())
785 self.assertTrue(nc.create_decimal(float('inf')).is_infinite())
786 self.assertTrue(nc.create_decimal(float('-inf')).is_infinite())
787 self.assertEqual(str(nc.create_decimal(float('nan'))),
788 str(nc.create_decimal('NaN')))
789 self.assertEqual(str(nc.create_decimal(float('inf'))),
790 str(nc.create_decimal('Infinity')))
791 self.assertEqual(str(nc.create_decimal(float('-inf'))),
792 str(nc.create_decimal('-Infinity')))
793 self.assertEqual(str(nc.create_decimal(float('-0.0'))),
794 str(nc.create_decimal('-0')))
795 nc.prec = 100
796 for i in range(200):
797 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
798 self.assertEqual(x, float(nc.create_decimal(x))) # roundtrip
799
Mark Dickinson345adc42009-08-02 10:14:23 +0000800 def test_unicode_digits(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100801 Decimal = self.decimal.Decimal
802
Mark Dickinson345adc42009-08-02 10:14:23 +0000803 test_values = {
804 '\uff11': '1',
805 '\u0660.\u0660\u0663\u0667\u0662e-\u0663' : '0.0000372',
806 '-nan\u0c68\u0c6a\u0c66\u0c66' : '-NaN2400',
807 }
808 for input, expected in test_values.items():
809 self.assertEqual(str(Decimal(input)), expected)
810
Stefan Krah1919b7e2012-03-21 18:25:23 +0100811class CExplicitConstructionTest(ExplicitConstructionTest):
812 decimal = C
813class PyExplicitConstructionTest(ExplicitConstructionTest):
814 decimal = P
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000815
Stefan Krah1919b7e2012-03-21 18:25:23 +0100816class ImplicitConstructionTest(unittest.TestCase):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000817 '''Unit tests for Implicit Construction cases of Decimal.'''
818
819 def test_implicit_from_None(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100820 Decimal = self.decimal.Decimal
821 self.assertRaises(TypeError, eval, 'Decimal(5) + None', locals())
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000822
823 def test_implicit_from_int(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100824 Decimal = self.decimal.Decimal
825
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000826 #normal
827 self.assertEqual(str(Decimal(5) + 45), '50')
828 #exceeding precision
829 self.assertEqual(Decimal(5) + 123456789000, Decimal(123456789000))
830
831 def test_implicit_from_string(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100832 Decimal = self.decimal.Decimal
833 self.assertRaises(TypeError, eval, 'Decimal(5) + "3"', locals())
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000834
835 def test_implicit_from_float(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100836 Decimal = self.decimal.Decimal
837 self.assertRaises(TypeError, eval, 'Decimal(5) + 2.2', locals())
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000838
839 def test_implicit_from_Decimal(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100840 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000841 self.assertEqual(Decimal(5) + Decimal(45), Decimal(50))
842
Raymond Hettinger267b8682005-03-27 10:47:39 +0000843 def test_rop(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100844 Decimal = self.decimal.Decimal
845
Raymond Hettinger267b8682005-03-27 10:47:39 +0000846 # Allow other classes to be trained to interact with Decimals
847 class E:
848 def __divmod__(self, other):
849 return 'divmod ' + str(other)
850 def __rdivmod__(self, other):
851 return str(other) + ' rdivmod'
852 def __lt__(self, other):
853 return 'lt ' + str(other)
854 def __gt__(self, other):
855 return 'gt ' + str(other)
856 def __le__(self, other):
857 return 'le ' + str(other)
858 def __ge__(self, other):
859 return 'ge ' + str(other)
860 def __eq__(self, other):
861 return 'eq ' + str(other)
862 def __ne__(self, other):
863 return 'ne ' + str(other)
864
865 self.assertEqual(divmod(E(), Decimal(10)), 'divmod 10')
866 self.assertEqual(divmod(Decimal(10), E()), '10 rdivmod')
867 self.assertEqual(eval('Decimal(10) < E()'), 'gt 10')
868 self.assertEqual(eval('Decimal(10) > E()'), 'lt 10')
869 self.assertEqual(eval('Decimal(10) <= E()'), 'ge 10')
870 self.assertEqual(eval('Decimal(10) >= E()'), 'le 10')
871 self.assertEqual(eval('Decimal(10) == E()'), 'eq 10')
872 self.assertEqual(eval('Decimal(10) != E()'), 'ne 10')
873
874 # insert operator methods and then exercise them
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000875 oplist = [
876 ('+', '__add__', '__radd__'),
877 ('-', '__sub__', '__rsub__'),
878 ('*', '__mul__', '__rmul__'),
Thomas Woutersdcc6d322006-04-21 11:30:52 +0000879 ('/', '__truediv__', '__rtruediv__'),
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000880 ('%', '__mod__', '__rmod__'),
881 ('//', '__floordiv__', '__rfloordiv__'),
882 ('**', '__pow__', '__rpow__')
883 ]
Raymond Hettinger267b8682005-03-27 10:47:39 +0000884
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000885 for sym, lop, rop in oplist:
Raymond Hettinger267b8682005-03-27 10:47:39 +0000886 setattr(E, lop, lambda self, other: 'str' + lop + str(other))
887 setattr(E, rop, lambda self, other: str(other) + rop + 'str')
888 self.assertEqual(eval('E()' + sym + 'Decimal(10)'),
889 'str' + lop + '10')
890 self.assertEqual(eval('Decimal(10)' + sym + 'E()'),
891 '10' + rop + 'str')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000892
Stefan Krah1919b7e2012-03-21 18:25:23 +0100893class CImplicitConstructionTest(ImplicitConstructionTest):
894 decimal = C
895class PyImplicitConstructionTest(ImplicitConstructionTest):
896 decimal = P
Mark Dickinson79f52032009-03-17 23:12:51 +0000897
Stefan Krah1919b7e2012-03-21 18:25:23 +0100898class FormatTest(unittest.TestCase):
Christian Heimesf16baeb2008-02-29 14:57:44 +0000899 '''Unit tests for the format function.'''
900 def test_formatting(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100901 Decimal = self.decimal.Decimal
902
Christian Heimesf16baeb2008-02-29 14:57:44 +0000903 # triples giving a format, a Decimal, and the expected result
904 test_values = [
905 ('e', '0E-15', '0e-15'),
906 ('e', '2.3E-15', '2.3e-15'),
907 ('e', '2.30E+2', '2.30e+2'), # preserve significant zeros
908 ('e', '2.30000E-15', '2.30000e-15'),
909 ('e', '1.23456789123456789e40', '1.23456789123456789e+40'),
910 ('e', '1.5', '1.5e+0'),
911 ('e', '0.15', '1.5e-1'),
912 ('e', '0.015', '1.5e-2'),
913 ('e', '0.0000000000015', '1.5e-12'),
914 ('e', '15.0', '1.50e+1'),
915 ('e', '-15', '-1.5e+1'),
916 ('e', '0', '0e+0'),
917 ('e', '0E1', '0e+1'),
918 ('e', '0.0', '0e-1'),
919 ('e', '0.00', '0e-2'),
920 ('.6e', '0E-15', '0.000000e-9'),
921 ('.6e', '0', '0.000000e+6'),
922 ('.6e', '9.999999', '9.999999e+0'),
923 ('.6e', '9.9999999', '1.000000e+1'),
924 ('.6e', '-1.23e5', '-1.230000e+5'),
925 ('.6e', '1.23456789e-3', '1.234568e-3'),
926 ('f', '0', '0'),
927 ('f', '0.0', '0.0'),
928 ('f', '0E-2', '0.00'),
929 ('f', '0.00E-8', '0.0000000000'),
930 ('f', '0E1', '0'), # loses exponent information
931 ('f', '3.2E1', '32'),
932 ('f', '3.2E2', '320'),
933 ('f', '3.20E2', '320'),
934 ('f', '3.200E2', '320.0'),
935 ('f', '3.2E-6', '0.0000032'),
936 ('.6f', '0E-15', '0.000000'), # all zeros treated equally
937 ('.6f', '0E1', '0.000000'),
938 ('.6f', '0', '0.000000'),
939 ('.0f', '0', '0'), # no decimal point
940 ('.0f', '0e-2', '0'),
941 ('.0f', '3.14159265', '3'),
942 ('.1f', '3.14159265', '3.1'),
943 ('.4f', '3.14159265', '3.1416'),
944 ('.6f', '3.14159265', '3.141593'),
945 ('.7f', '3.14159265', '3.1415926'), # round-half-even!
946 ('.8f', '3.14159265', '3.14159265'),
947 ('.9f', '3.14159265', '3.141592650'),
948
949 ('g', '0', '0'),
950 ('g', '0.0', '0.0'),
951 ('g', '0E1', '0e+1'),
952 ('G', '0E1', '0E+1'),
953 ('g', '0E-5', '0.00000'),
954 ('g', '0E-6', '0.000000'),
955 ('g', '0E-7', '0e-7'),
956 ('g', '-0E2', '-0e+2'),
957 ('.0g', '3.14159265', '3'), # 0 sig fig -> 1 sig fig
Stefan Krah1919b7e2012-03-21 18:25:23 +0100958 ('.0n', '3.14159265', '3'), # same for 'n'
Christian Heimesf16baeb2008-02-29 14:57:44 +0000959 ('.1g', '3.14159265', '3'),
960 ('.2g', '3.14159265', '3.1'),
961 ('.5g', '3.14159265', '3.1416'),
962 ('.7g', '3.14159265', '3.141593'),
963 ('.8g', '3.14159265', '3.1415926'), # round-half-even!
964 ('.9g', '3.14159265', '3.14159265'),
965 ('.10g', '3.14159265', '3.14159265'), # don't pad
966
967 ('%', '0E1', '0%'),
968 ('%', '0E0', '0%'),
969 ('%', '0E-1', '0%'),
970 ('%', '0E-2', '0%'),
971 ('%', '0E-3', '0.0%'),
972 ('%', '0E-4', '0.00%'),
973
974 ('.3%', '0', '0.000%'), # all zeros treated equally
975 ('.3%', '0E10', '0.000%'),
976 ('.3%', '0E-10', '0.000%'),
977 ('.3%', '2.34', '234.000%'),
978 ('.3%', '1.234567', '123.457%'),
979 ('.0%', '1.23', '123%'),
980
981 ('e', 'NaN', 'NaN'),
982 ('f', '-NaN123', '-NaN123'),
983 ('+g', 'NaN456', '+NaN456'),
984 ('.3e', 'Inf', 'Infinity'),
985 ('.16f', '-Inf', '-Infinity'),
986 ('.0g', '-sNaN', '-sNaN'),
987
988 ('', '1.00', '1.00'),
Mark Dickinsonad416342009-03-17 18:10:15 +0000989
Mark Dickinson79f52032009-03-17 23:12:51 +0000990 # test alignment and padding
Mark Dickinson46ab5d02009-09-08 20:22:46 +0000991 ('6', '123', ' 123'),
Mark Dickinsonad416342009-03-17 18:10:15 +0000992 ('<6', '123', '123 '),
993 ('>6', '123', ' 123'),
994 ('^6', '123', ' 123 '),
995 ('=+6', '123', '+ 123'),
Mark Dickinson79f52032009-03-17 23:12:51 +0000996 ('#<10', 'NaN', 'NaN#######'),
997 ('#<10', '-4.3', '-4.3######'),
998 ('#<+10', '0.0130', '+0.0130###'),
999 ('#< 10', '0.0130', ' 0.0130###'),
1000 ('@>10', '-Inf', '@-Infinity'),
1001 ('#>5', '-Inf', '-Infinity'),
1002 ('?^5', '123', '?123?'),
1003 ('%^6', '123', '%123%%'),
1004 (' ^6', '-45.6', '-45.6 '),
1005 ('/=10', '-45.6', '-/////45.6'),
1006 ('/=+10', '45.6', '+/////45.6'),
1007 ('/= 10', '45.6', ' /////45.6'),
1008
1009 # thousands separator
1010 (',', '1234567', '1,234,567'),
1011 (',', '123456', '123,456'),
1012 (',', '12345', '12,345'),
1013 (',', '1234', '1,234'),
1014 (',', '123', '123'),
1015 (',', '12', '12'),
1016 (',', '1', '1'),
1017 (',', '0', '0'),
1018 (',', '-1234567', '-1,234,567'),
1019 (',', '-123456', '-123,456'),
1020 ('7,', '123456', '123,456'),
Mark Dickinson46ab5d02009-09-08 20:22:46 +00001021 ('8,', '123456', ' 123,456'),
Mark Dickinson79f52032009-03-17 23:12:51 +00001022 ('08,', '123456', '0,123,456'), # special case: extra 0 needed
1023 ('+08,', '123456', '+123,456'), # but not if there's a sign
1024 (' 08,', '123456', ' 123,456'),
1025 ('08,', '-123456', '-123,456'),
1026 ('+09,', '123456', '+0,123,456'),
1027 # ... with fractional part...
1028 ('07,', '1234.56', '1,234.56'),
1029 ('08,', '1234.56', '1,234.56'),
1030 ('09,', '1234.56', '01,234.56'),
1031 ('010,', '1234.56', '001,234.56'),
1032 ('011,', '1234.56', '0,001,234.56'),
1033 ('012,', '1234.56', '0,001,234.56'),
1034 ('08,.1f', '1234.5', '01,234.5'),
1035 # no thousands separators in fraction part
1036 (',', '1.23456789', '1.23456789'),
1037 (',%', '123.456789', '12,345.6789%'),
1038 (',e', '123456', '1.23456e+5'),
1039 (',E', '123456', '1.23456E+5'),
Mark Dickinson7718d2b2009-09-07 16:21:56 +00001040
1041 # issue 6850
1042 ('a=-7.0', '0.12345', 'aaaa0.1'),
Christian Heimesf16baeb2008-02-29 14:57:44 +00001043 ]
1044 for fmt, d, result in test_values:
1045 self.assertEqual(format(Decimal(d), fmt), result)
1046
Stefan Krah1919b7e2012-03-21 18:25:23 +01001047 # bytes format argument
1048 self.assertRaises(TypeError, Decimal(1).__format__, b'-020')
1049
Mark Dickinson79f52032009-03-17 23:12:51 +00001050 def test_n_format(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001051 Decimal = self.decimal.Decimal
1052
Mark Dickinson79f52032009-03-17 23:12:51 +00001053 try:
1054 from locale import CHAR_MAX
1055 except ImportError:
1056 return
1057
Stefan Krah1919b7e2012-03-21 18:25:23 +01001058 def make_grouping(lst):
1059 return ''.join([chr(x) for x in lst]) if self.decimal == C else lst
1060
1061 def get_fmt(x, override=None, fmt='n'):
1062 if self.decimal == C:
1063 return Decimal(x).__format__(fmt, override)
1064 else:
1065 return Decimal(x).__format__(fmt, _localeconv=override)
1066
Mark Dickinson79f52032009-03-17 23:12:51 +00001067 # Set up some localeconv-like dictionaries
1068 en_US = {
1069 'decimal_point' : '.',
Stefan Krah1919b7e2012-03-21 18:25:23 +01001070 'grouping' : make_grouping([3, 3, 0]),
1071 'thousands_sep' : ','
Mark Dickinson79f52032009-03-17 23:12:51 +00001072 }
1073
1074 fr_FR = {
1075 'decimal_point' : ',',
Stefan Krah1919b7e2012-03-21 18:25:23 +01001076 'grouping' : make_grouping([CHAR_MAX]),
Mark Dickinson79f52032009-03-17 23:12:51 +00001077 'thousands_sep' : ''
1078 }
1079
1080 ru_RU = {
1081 'decimal_point' : ',',
Stefan Krah1919b7e2012-03-21 18:25:23 +01001082 'grouping': make_grouping([3, 3, 0]),
Mark Dickinson79f52032009-03-17 23:12:51 +00001083 'thousands_sep' : ' '
1084 }
1085
1086 crazy = {
1087 'decimal_point' : '&',
Stefan Krah1919b7e2012-03-21 18:25:23 +01001088 'grouping': make_grouping([1, 4, 2, CHAR_MAX]),
Mark Dickinson79f52032009-03-17 23:12:51 +00001089 'thousands_sep' : '-'
1090 }
1091
Stefan Krah1919b7e2012-03-21 18:25:23 +01001092 dotsep_wide = {
1093 'decimal_point' : b'\xc2\xbf'.decode('utf-8'),
1094 'grouping': make_grouping([3, 3, 0]),
1095 'thousands_sep' : b'\xc2\xb4'.decode('utf-8')
1096 }
Mark Dickinson79f52032009-03-17 23:12:51 +00001097
1098 self.assertEqual(get_fmt(Decimal('12.7'), en_US), '12.7')
1099 self.assertEqual(get_fmt(Decimal('12.7'), fr_FR), '12,7')
1100 self.assertEqual(get_fmt(Decimal('12.7'), ru_RU), '12,7')
1101 self.assertEqual(get_fmt(Decimal('12.7'), crazy), '1-2&7')
1102
1103 self.assertEqual(get_fmt(123456789, en_US), '123,456,789')
1104 self.assertEqual(get_fmt(123456789, fr_FR), '123456789')
1105 self.assertEqual(get_fmt(123456789, ru_RU), '123 456 789')
1106 self.assertEqual(get_fmt(1234567890123, crazy), '123456-78-9012-3')
1107
1108 self.assertEqual(get_fmt(123456789, en_US, '.6n'), '1.23457e+8')
1109 self.assertEqual(get_fmt(123456789, fr_FR, '.6n'), '1,23457e+8')
1110 self.assertEqual(get_fmt(123456789, ru_RU, '.6n'), '1,23457e+8')
1111 self.assertEqual(get_fmt(123456789, crazy, '.6n'), '1&23457e+8')
1112
Mark Dickinson7303b592009-03-18 08:25:36 +00001113 # zero padding
1114 self.assertEqual(get_fmt(1234, fr_FR, '03n'), '1234')
1115 self.assertEqual(get_fmt(1234, fr_FR, '04n'), '1234')
1116 self.assertEqual(get_fmt(1234, fr_FR, '05n'), '01234')
1117 self.assertEqual(get_fmt(1234, fr_FR, '06n'), '001234')
1118
1119 self.assertEqual(get_fmt(12345, en_US, '05n'), '12,345')
1120 self.assertEqual(get_fmt(12345, en_US, '06n'), '12,345')
1121 self.assertEqual(get_fmt(12345, en_US, '07n'), '012,345')
1122 self.assertEqual(get_fmt(12345, en_US, '08n'), '0,012,345')
1123 self.assertEqual(get_fmt(12345, en_US, '09n'), '0,012,345')
1124 self.assertEqual(get_fmt(12345, en_US, '010n'), '00,012,345')
1125
1126 self.assertEqual(get_fmt(123456, crazy, '06n'), '1-2345-6')
1127 self.assertEqual(get_fmt(123456, crazy, '07n'), '1-2345-6')
1128 self.assertEqual(get_fmt(123456, crazy, '08n'), '1-2345-6')
1129 self.assertEqual(get_fmt(123456, crazy, '09n'), '01-2345-6')
1130 self.assertEqual(get_fmt(123456, crazy, '010n'), '0-01-2345-6')
1131 self.assertEqual(get_fmt(123456, crazy, '011n'), '0-01-2345-6')
1132 self.assertEqual(get_fmt(123456, crazy, '012n'), '00-01-2345-6')
1133 self.assertEqual(get_fmt(123456, crazy, '013n'), '000-01-2345-6')
1134
Stefan Krah1919b7e2012-03-21 18:25:23 +01001135 # wide char separator and decimal point
1136 self.assertEqual(get_fmt(Decimal('-1.5'), dotsep_wide, '020n'),
1137 '-0\u00b4000\u00b4000\u00b4000\u00b4001\u00bf5')
Mark Dickinson79f52032009-03-17 23:12:51 +00001138
Stefan Krah1919b7e2012-03-21 18:25:23 +01001139 def test_wide_char_separator_decimal_point(self):
1140 # locale with wide char separator and decimal point
1141 Decimal = self.decimal.Decimal
1142
1143 try:
1144 locale.setlocale(locale.LC_ALL, 'ps_AF')
1145 except locale.Error:
1146 return
1147
1148 self.assertEqual(format(Decimal('100000000.123'), 'n'),
1149 '100\u066c000\u066c000\u066b123')
1150 locale.resetlocale()
1151
1152class CFormatTest(FormatTest):
1153 decimal = C
1154class PyFormatTest(FormatTest):
1155 decimal = P
1156
1157class ArithmeticOperatorsTest(unittest.TestCase):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001158 '''Unit tests for all arithmetic operators, binary and unary.'''
1159
1160 def test_addition(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001161 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001162
1163 d1 = Decimal('-11.1')
1164 d2 = Decimal('22.2')
1165
1166 #two Decimals
1167 self.assertEqual(d1+d2, Decimal('11.1'))
1168 self.assertEqual(d2+d1, Decimal('11.1'))
1169
1170 #with other type, left
1171 c = d1 + 5
1172 self.assertEqual(c, Decimal('-6.1'))
1173 self.assertEqual(type(c), type(d1))
1174
1175 #with other type, right
1176 c = 5 + d1
1177 self.assertEqual(c, Decimal('-6.1'))
1178 self.assertEqual(type(c), type(d1))
1179
1180 #inline with decimal
1181 d1 += d2
1182 self.assertEqual(d1, Decimal('11.1'))
1183
1184 #inline with other type
1185 d1 += 5
1186 self.assertEqual(d1, Decimal('16.1'))
1187
1188 def test_subtraction(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001189 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001190
1191 d1 = Decimal('-11.1')
1192 d2 = Decimal('22.2')
1193
1194 #two Decimals
1195 self.assertEqual(d1-d2, Decimal('-33.3'))
1196 self.assertEqual(d2-d1, Decimal('33.3'))
1197
1198 #with other type, left
1199 c = d1 - 5
1200 self.assertEqual(c, Decimal('-16.1'))
1201 self.assertEqual(type(c), type(d1))
1202
1203 #with other type, right
1204 c = 5 - d1
1205 self.assertEqual(c, Decimal('16.1'))
1206 self.assertEqual(type(c), type(d1))
1207
1208 #inline with decimal
1209 d1 -= d2
1210 self.assertEqual(d1, Decimal('-33.3'))
1211
1212 #inline with other type
1213 d1 -= 5
1214 self.assertEqual(d1, Decimal('-38.3'))
1215
1216 def test_multiplication(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001217 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001218
1219 d1 = Decimal('-5')
1220 d2 = Decimal('3')
1221
1222 #two Decimals
1223 self.assertEqual(d1*d2, Decimal('-15'))
1224 self.assertEqual(d2*d1, Decimal('-15'))
1225
1226 #with other type, left
1227 c = d1 * 5
1228 self.assertEqual(c, Decimal('-25'))
1229 self.assertEqual(type(c), type(d1))
1230
1231 #with other type, right
1232 c = 5 * d1
1233 self.assertEqual(c, Decimal('-25'))
1234 self.assertEqual(type(c), type(d1))
1235
1236 #inline with decimal
1237 d1 *= d2
1238 self.assertEqual(d1, Decimal('-15'))
1239
1240 #inline with other type
1241 d1 *= 5
1242 self.assertEqual(d1, Decimal('-75'))
1243
1244 def test_division(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001245 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001246
1247 d1 = Decimal('-5')
1248 d2 = Decimal('2')
1249
1250 #two Decimals
1251 self.assertEqual(d1/d2, Decimal('-2.5'))
1252 self.assertEqual(d2/d1, Decimal('-0.4'))
1253
1254 #with other type, left
1255 c = d1 / 4
1256 self.assertEqual(c, Decimal('-1.25'))
1257 self.assertEqual(type(c), type(d1))
1258
1259 #with other type, right
1260 c = 4 / d1
1261 self.assertEqual(c, Decimal('-0.8'))
1262 self.assertEqual(type(c), type(d1))
1263
1264 #inline with decimal
1265 d1 /= d2
1266 self.assertEqual(d1, Decimal('-2.5'))
1267
1268 #inline with other type
1269 d1 /= 4
1270 self.assertEqual(d1, Decimal('-0.625'))
1271
1272 def test_floor_division(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001273 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001274
1275 d1 = Decimal('5')
1276 d2 = Decimal('2')
1277
1278 #two Decimals
1279 self.assertEqual(d1//d2, Decimal('2'))
1280 self.assertEqual(d2//d1, Decimal('0'))
1281
1282 #with other type, left
1283 c = d1 // 4
1284 self.assertEqual(c, Decimal('1'))
1285 self.assertEqual(type(c), type(d1))
1286
1287 #with other type, right
1288 c = 7 // d1
1289 self.assertEqual(c, Decimal('1'))
1290 self.assertEqual(type(c), type(d1))
1291
1292 #inline with decimal
1293 d1 //= d2
1294 self.assertEqual(d1, Decimal('2'))
1295
1296 #inline with other type
1297 d1 //= 2
1298 self.assertEqual(d1, Decimal('1'))
1299
1300 def test_powering(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001301 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001302
1303 d1 = Decimal('5')
1304 d2 = Decimal('2')
1305
1306 #two Decimals
1307 self.assertEqual(d1**d2, Decimal('25'))
1308 self.assertEqual(d2**d1, Decimal('32'))
1309
1310 #with other type, left
1311 c = d1 ** 4
1312 self.assertEqual(c, Decimal('625'))
1313 self.assertEqual(type(c), type(d1))
1314
1315 #with other type, right
1316 c = 7 ** d1
1317 self.assertEqual(c, Decimal('16807'))
1318 self.assertEqual(type(c), type(d1))
1319
1320 #inline with decimal
1321 d1 **= d2
1322 self.assertEqual(d1, Decimal('25'))
1323
1324 #inline with other type
1325 d1 **= 4
1326 self.assertEqual(d1, Decimal('390625'))
1327
1328 def test_module(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001329 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001330
1331 d1 = Decimal('5')
1332 d2 = Decimal('2')
1333
1334 #two Decimals
1335 self.assertEqual(d1%d2, Decimal('1'))
1336 self.assertEqual(d2%d1, Decimal('2'))
1337
1338 #with other type, left
1339 c = d1 % 4
1340 self.assertEqual(c, Decimal('1'))
1341 self.assertEqual(type(c), type(d1))
1342
1343 #with other type, right
1344 c = 7 % d1
1345 self.assertEqual(c, Decimal('2'))
1346 self.assertEqual(type(c), type(d1))
1347
1348 #inline with decimal
1349 d1 %= d2
1350 self.assertEqual(d1, Decimal('1'))
1351
1352 #inline with other type
1353 d1 %= 4
1354 self.assertEqual(d1, Decimal('1'))
1355
1356 def test_floor_div_module(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001357 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001358
1359 d1 = Decimal('5')
1360 d2 = Decimal('2')
1361
1362 #two Decimals
1363 (p, q) = divmod(d1, d2)
1364 self.assertEqual(p, Decimal('2'))
1365 self.assertEqual(q, Decimal('1'))
1366 self.assertEqual(type(p), type(d1))
1367 self.assertEqual(type(q), type(d1))
1368
1369 #with other type, left
1370 (p, q) = divmod(d1, 4)
1371 self.assertEqual(p, Decimal('1'))
1372 self.assertEqual(q, Decimal('1'))
1373 self.assertEqual(type(p), type(d1))
1374 self.assertEqual(type(q), type(d1))
1375
1376 #with other type, right
1377 (p, q) = divmod(7, d1)
1378 self.assertEqual(p, Decimal('1'))
1379 self.assertEqual(q, Decimal('2'))
1380 self.assertEqual(type(p), type(d1))
1381 self.assertEqual(type(q), type(d1))
1382
1383 def test_unary_operators(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001384 Decimal = self.decimal.Decimal
1385
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001386 self.assertEqual(+Decimal(45), Decimal(+45)) # +
1387 self.assertEqual(-Decimal(45), Decimal(-45)) # -
1388 self.assertEqual(abs(Decimal(45)), abs(Decimal(-45))) # abs
1389
Christian Heimes77c02eb2008-02-09 02:18:51 +00001390 def test_nan_comparisons(self):
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001391 # comparisons involving signaling nans signal InvalidOperation
1392
1393 # order comparisons (<, <=, >, >=) involving only quiet nans
1394 # also signal InvalidOperation
1395
1396 # equality comparisons (==, !=) involving only quiet nans
1397 # don't signal, but return False or True respectively.
Stefan Krah1919b7e2012-03-21 18:25:23 +01001398 Decimal = self.decimal.Decimal
1399 InvalidOperation = self.decimal.InvalidOperation
1400 localcontext = self.decimal.localcontext
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001401
Christian Heimes77c02eb2008-02-09 02:18:51 +00001402 n = Decimal('NaN')
1403 s = Decimal('sNaN')
1404 i = Decimal('Inf')
1405 f = Decimal('2')
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001406
1407 qnan_pairs = (n, n), (n, i), (i, n), (n, f), (f, n)
1408 snan_pairs = (s, n), (n, s), (s, i), (i, s), (s, f), (f, s), (s, s)
1409 order_ops = operator.lt, operator.le, operator.gt, operator.ge
1410 equality_ops = operator.eq, operator.ne
1411
1412 # results when InvalidOperation is not trapped
1413 for x, y in qnan_pairs + snan_pairs:
1414 for op in order_ops + equality_ops:
1415 got = op(x, y)
1416 expected = True if op is operator.ne else False
1417 self.assertIs(expected, got,
1418 "expected {0!r} for operator.{1}({2!r}, {3!r}); "
1419 "got {4!r}".format(
1420 expected, op.__name__, x, y, got))
1421
1422 # repeat the above, but this time trap the InvalidOperation
1423 with localcontext() as ctx:
1424 ctx.traps[InvalidOperation] = 1
1425
1426 for x, y in qnan_pairs:
1427 for op in equality_ops:
1428 got = op(x, y)
1429 expected = True if op is operator.ne else False
1430 self.assertIs(expected, got,
1431 "expected {0!r} for "
1432 "operator.{1}({2!r}, {3!r}); "
1433 "got {4!r}".format(
1434 expected, op.__name__, x, y, got))
1435
1436 for x, y in snan_pairs:
1437 for op in equality_ops:
1438 self.assertRaises(InvalidOperation, operator.eq, x, y)
1439 self.assertRaises(InvalidOperation, operator.ne, x, y)
1440
1441 for x, y in qnan_pairs + snan_pairs:
1442 for op in order_ops:
1443 self.assertRaises(InvalidOperation, op, x, y)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001444
Mark Dickinson84230a12010-02-18 14:49:50 +00001445 def test_copy_sign(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001446 Decimal = self.decimal.Decimal
Mark Dickinson84230a12010-02-18 14:49:50 +00001447
Stefan Krah1919b7e2012-03-21 18:25:23 +01001448 d = Decimal(1).copy_sign(Decimal(-2))
Mark Dickinson84230a12010-02-18 14:49:50 +00001449 self.assertEqual(Decimal(1).copy_sign(-2), d)
1450 self.assertRaises(TypeError, Decimal(1).copy_sign, '-2')
1451
Stefan Krah1919b7e2012-03-21 18:25:23 +01001452class CArithmeticOperatorsTest(ArithmeticOperatorsTest):
1453 decimal = C
1454class PyArithmeticOperatorsTest(ArithmeticOperatorsTest):
1455 decimal = P
1456
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001457# The following are two functions used to test threading in the next class
1458
1459def thfunc1(cls):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001460 Decimal = cls.decimal.Decimal
1461 InvalidOperation = cls.decimal.InvalidOperation
1462 DivisionByZero = cls.decimal.DivisionByZero
1463 Overflow = cls.decimal.Overflow
1464 Underflow = cls.decimal.Underflow
1465 Inexact = cls.decimal.Inexact
1466 getcontext = cls.decimal.getcontext
1467 localcontext = cls.decimal.localcontext
1468
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001469 d1 = Decimal(1)
1470 d3 = Decimal(3)
Christian Heimesfe337bf2008-03-23 21:54:12 +00001471 test1 = d1/d3
Christian Heimesfe337bf2008-03-23 21:54:12 +00001472
Stefan Krah1919b7e2012-03-21 18:25:23 +01001473 cls.finish1.set()
1474 cls.synchro.wait()
1475
1476 test2 = d1/d3
1477 with localcontext() as c2:
1478 cls.assertTrue(c2.flags[Inexact])
1479 cls.assertRaises(DivisionByZero, c2.divide, d1, 0)
1480 cls.assertTrue(c2.flags[DivisionByZero])
1481 with localcontext() as c3:
1482 cls.assertTrue(c3.flags[Inexact])
1483 cls.assertTrue(c3.flags[DivisionByZero])
1484 cls.assertRaises(InvalidOperation, c3.compare, d1, Decimal('sNaN'))
1485 cls.assertTrue(c3.flags[InvalidOperation])
1486 del c3
1487 cls.assertFalse(c2.flags[InvalidOperation])
1488 del c2
1489
1490 cls.assertEqual(test1, Decimal('0.333333333333333333333333'))
1491 cls.assertEqual(test2, Decimal('0.333333333333333333333333'))
1492
1493 c1 = getcontext()
1494 cls.assertTrue(c1.flags[Inexact])
1495 for sig in Overflow, Underflow, DivisionByZero, InvalidOperation:
1496 cls.assertFalse(c1.flags[sig])
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001497 return
1498
1499def thfunc2(cls):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001500 Decimal = cls.decimal.Decimal
1501 InvalidOperation = cls.decimal.InvalidOperation
1502 DivisionByZero = cls.decimal.DivisionByZero
1503 Overflow = cls.decimal.Overflow
1504 Underflow = cls.decimal.Underflow
1505 Inexact = cls.decimal.Inexact
1506 getcontext = cls.decimal.getcontext
1507 localcontext = cls.decimal.localcontext
1508
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001509 d1 = Decimal(1)
1510 d3 = Decimal(3)
Christian Heimesfe337bf2008-03-23 21:54:12 +00001511 test1 = d1/d3
Stefan Krah1919b7e2012-03-21 18:25:23 +01001512
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001513 thiscontext = getcontext()
1514 thiscontext.prec = 18
Christian Heimesfe337bf2008-03-23 21:54:12 +00001515 test2 = d1/d3
Stefan Krah1919b7e2012-03-21 18:25:23 +01001516
1517 with localcontext() as c2:
1518 cls.assertTrue(c2.flags[Inexact])
1519 cls.assertRaises(Overflow, c2.multiply, Decimal('1e425000000'), 999)
1520 cls.assertTrue(c2.flags[Overflow])
1521 with localcontext(thiscontext) as c3:
1522 cls.assertTrue(c3.flags[Inexact])
1523 cls.assertFalse(c3.flags[Overflow])
1524 c3.traps[Underflow] = True
1525 cls.assertRaises(Underflow, c3.divide, Decimal('1e-425000000'), 999)
1526 cls.assertTrue(c3.flags[Underflow])
1527 del c3
1528 cls.assertFalse(c2.flags[Underflow])
1529 cls.assertFalse(c2.traps[Underflow])
1530 del c2
1531
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001532 cls.synchro.set()
1533 cls.finish2.set()
Christian Heimesfe337bf2008-03-23 21:54:12 +00001534
Stefan Krah1919b7e2012-03-21 18:25:23 +01001535 cls.assertEqual(test1, Decimal('0.333333333333333333333333'))
Christian Heimesfe337bf2008-03-23 21:54:12 +00001536 cls.assertEqual(test2, Decimal('0.333333333333333333'))
Stefan Krah1919b7e2012-03-21 18:25:23 +01001537
1538 cls.assertFalse(thiscontext.traps[Underflow])
1539 cls.assertTrue(thiscontext.flags[Inexact])
1540 for sig in Overflow, Underflow, DivisionByZero, InvalidOperation:
1541 cls.assertFalse(thiscontext.flags[sig])
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001542 return
1543
Stefan Krah1919b7e2012-03-21 18:25:23 +01001544class ThreadingTest(unittest.TestCase):
1545 '''Unit tests for thread local contexts in Decimal.'''
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001546
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001547 # Take care executing this test from IDLE, there's an issue in threading
1548 # that hangs IDLE and I couldn't find it
1549
1550 def test_threading(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001551 DefaultContext = self.decimal.DefaultContext
1552
1553 if self.decimal == C and not self.decimal.HAVE_THREADS:
1554 self.skipTest("compiled without threading")
1555 # Test the "threading isolation" of a Context. Also test changing
1556 # the DefaultContext, which acts as a template for the thread-local
1557 # contexts.
1558 save_prec = DefaultContext.prec
1559 save_emax = DefaultContext.Emax
1560 save_emin = DefaultContext.Emin
1561 DefaultContext.prec = 24
1562 DefaultContext.Emax = 425000000
1563 DefaultContext.Emin = -425000000
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001564
1565 self.synchro = threading.Event()
1566 self.finish1 = threading.Event()
1567 self.finish2 = threading.Event()
1568
1569 th1 = threading.Thread(target=thfunc1, args=(self,))
1570 th2 = threading.Thread(target=thfunc2, args=(self,))
1571
1572 th1.start()
1573 th2.start()
1574
1575 self.finish1.wait()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001576 self.finish2.wait()
Stefan Krah1919b7e2012-03-21 18:25:23 +01001577
1578 for sig in Signals[self.decimal]:
1579 self.assertFalse(DefaultContext.flags[sig])
1580
1581 DefaultContext.prec = save_prec
1582 DefaultContext.Emax = save_emax
1583 DefaultContext.Emin = save_emin
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001584 return
1585
Stefan Krah1919b7e2012-03-21 18:25:23 +01001586@unittest.skipUnless(threading, 'threading required')
1587class CThreadingTest(ThreadingTest):
1588 decimal = C
1589@unittest.skipUnless(threading, 'threading required')
1590class PyThreadingTest(ThreadingTest):
1591 decimal = P
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001592
Stefan Krah1919b7e2012-03-21 18:25:23 +01001593class UsabilityTest(unittest.TestCase):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001594 '''Unit tests for Usability cases of Decimal.'''
1595
1596 def test_comparison_operators(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001597
Stefan Krah1919b7e2012-03-21 18:25:23 +01001598 Decimal = self.decimal.Decimal
1599
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001600 da = Decimal('23.42')
1601 db = Decimal('23.42')
1602 dc = Decimal('45')
1603
1604 #two Decimals
Ezio Melotti6607d512010-04-03 14:59:49 +00001605 self.assertGreater(dc, da)
1606 self.assertGreaterEqual(dc, da)
1607 self.assertLess(da, dc)
1608 self.assertLessEqual(da, dc)
Guido van Rossume61fd5b2007-07-11 12:20:59 +00001609 self.assertEqual(da, db)
Ezio Melotti6607d512010-04-03 14:59:49 +00001610 self.assertNotEqual(da, dc)
1611 self.assertLessEqual(da, db)
1612 self.assertGreaterEqual(da, db)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001613
1614 #a Decimal and an int
Ezio Melotti6607d512010-04-03 14:59:49 +00001615 self.assertGreater(dc, 23)
1616 self.assertLess(23, dc)
Guido van Rossume61fd5b2007-07-11 12:20:59 +00001617 self.assertEqual(dc, 45)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001618
1619 #a Decimal and uncomparable
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001620 self.assertNotEqual(da, 'ugly')
1621 self.assertNotEqual(da, 32.7)
1622 self.assertNotEqual(da, object())
1623 self.assertNotEqual(da, object)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001624
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001625 # sortable
Guido van Rossumc1f779c2007-07-03 08:25:58 +00001626 a = list(map(Decimal, range(100)))
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001627 b = a[:]
1628 random.shuffle(a)
1629 a.sort()
1630 self.assertEqual(a, b)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001631
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001632 def test_decimal_float_comparison(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001633 Decimal = self.decimal.Decimal
1634
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001635 da = Decimal('0.25')
1636 db = Decimal('3.0')
Ezio Melotti6607d512010-04-03 14:59:49 +00001637 self.assertLess(da, 3.0)
1638 self.assertLessEqual(da, 3.0)
1639 self.assertGreater(db, 0.25)
1640 self.assertGreaterEqual(db, 0.25)
1641 self.assertNotEqual(da, 1.5)
1642 self.assertEqual(da, 0.25)
1643 self.assertGreater(3.0, da)
1644 self.assertGreaterEqual(3.0, da)
1645 self.assertLess(0.25, db)
1646 self.assertLessEqual(0.25, db)
1647 self.assertNotEqual(0.25, db)
1648 self.assertEqual(3.0, db)
1649 self.assertNotEqual(0.1, Decimal('0.1'))
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001650
Stefan Krah1919b7e2012-03-21 18:25:23 +01001651 def test_decimal_complex_comparison(self):
1652 Decimal = self.decimal.Decimal
1653
1654 da = Decimal('0.25')
1655 db = Decimal('3.0')
1656 self.assertNotEqual(da, (1.5+0j))
1657 self.assertNotEqual((1.5+0j), da)
1658 self.assertEqual(da, (0.25+0j))
1659 self.assertEqual((0.25+0j), da)
1660 self.assertEqual((3.0+0j), db)
1661 self.assertEqual(db, (3.0+0j))
1662
1663 self.assertNotEqual(db, (3.0+1j))
1664 self.assertNotEqual((3.0+1j), db)
1665
1666 self.assertIs(db.__lt__(3.0+0j), NotImplemented)
1667 self.assertIs(db.__le__(3.0+0j), NotImplemented)
1668 self.assertIs(db.__gt__(3.0+0j), NotImplemented)
1669 self.assertIs(db.__le__(3.0+0j), NotImplemented)
1670
1671 def test_decimal_fraction_comparison(self):
1672 D = self.decimal.Decimal
1673 F = fractions[self.decimal].Fraction
1674 Context = self.decimal.Context
1675 localcontext = self.decimal.localcontext
1676 InvalidOperation = self.decimal.InvalidOperation
1677
1678
1679 emax = C.MAX_EMAX if C else 999999999
1680 emin = C.MIN_EMIN if C else -999999999
1681 etiny = C.MIN_ETINY if C else -1999999997
1682 c = Context(Emax=emax, Emin=emin)
1683
1684 with localcontext(c):
1685 c.prec = emax
1686 self.assertLess(D(0), F(1,9999999999999999999999999999999999999))
1687 self.assertLess(F(-1,9999999999999999999999999999999999999), D(0))
1688 self.assertLess(F(0,1), D("1e" + str(etiny)))
1689 self.assertLess(D("-1e" + str(etiny)), F(0,1))
1690 self.assertLess(F(0,9999999999999999999999999), D("1e" + str(etiny)))
1691 self.assertLess(D("-1e" + str(etiny)), F(0,9999999999999999999999999))
1692
1693 self.assertEqual(D("0.1"), F(1,10))
1694 self.assertEqual(F(1,10), D("0.1"))
1695
1696 c.prec = 300
1697 self.assertNotEqual(D(1)/3, F(1,3))
1698 self.assertNotEqual(F(1,3), D(1)/3)
1699
1700 self.assertLessEqual(F(120984237, 9999999999), D("9e" + str(emax)))
1701 self.assertGreaterEqual(D("9e" + str(emax)), F(120984237, 9999999999))
1702
1703 self.assertGreater(D('inf'), F(99999999999,123))
1704 self.assertGreater(D('inf'), F(-99999999999,123))
1705 self.assertLess(D('-inf'), F(99999999999,123))
1706 self.assertLess(D('-inf'), F(-99999999999,123))
1707
1708 self.assertRaises(InvalidOperation, D('nan').__gt__, F(-9,123))
1709 self.assertIs(NotImplemented, F(-9,123).__lt__(D('nan')))
1710 self.assertNotEqual(D('nan'), F(-9,123))
1711 self.assertNotEqual(F(-9,123), D('nan'))
1712
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001713 def test_copy_and_deepcopy_methods(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001714 Decimal = self.decimal.Decimal
1715
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001716 d = Decimal('43.24')
1717 c = copy.copy(d)
1718 self.assertEqual(id(c), id(d))
1719 dc = copy.deepcopy(d)
1720 self.assertEqual(id(dc), id(d))
1721
1722 def test_hash_method(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001723
1724 Decimal = self.decimal.Decimal
1725 localcontext = self.decimal.localcontext
1726
Stefan Krahdc817b22010-11-17 11:16:34 +00001727 def hashit(d):
1728 a = hash(d)
1729 b = d.__hash__()
1730 self.assertEqual(a, b)
1731 return a
1732
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001733 #just that it's hashable
Stefan Krahdc817b22010-11-17 11:16:34 +00001734 hashit(Decimal(23))
1735 hashit(Decimal('Infinity'))
1736 hashit(Decimal('-Infinity'))
1737 hashit(Decimal('nan123'))
1738 hashit(Decimal('-NaN'))
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001739
1740 test_values = [Decimal(sign*(2**m + n))
1741 for m in [0, 14, 15, 16, 17, 30, 31,
Stefan Krahdc817b22010-11-17 11:16:34 +00001742 32, 33, 61, 62, 63, 64, 65, 66]
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001743 for n in range(-10, 10)
1744 for sign in [-1, 1]]
1745 test_values.extend([
Stefan Krahdc817b22010-11-17 11:16:34 +00001746 Decimal("-1"), # ==> -2
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001747 Decimal("-0"), # zeros
1748 Decimal("0.00"),
1749 Decimal("-0.000"),
1750 Decimal("0E10"),
1751 Decimal("-0E12"),
1752 Decimal("10.0"), # negative exponent
1753 Decimal("-23.00000"),
1754 Decimal("1230E100"), # positive exponent
1755 Decimal("-4.5678E50"),
1756 # a value for which hash(n) != hash(n % (2**64-1))
1757 # in Python pre-2.6
1758 Decimal(2**64 + 2**32 - 1),
1759 # selection of values which fail with the old (before
1760 # version 2.6) long.__hash__
1761 Decimal("1.634E100"),
1762 Decimal("90.697E100"),
1763 Decimal("188.83E100"),
1764 Decimal("1652.9E100"),
1765 Decimal("56531E100"),
1766 ])
1767
1768 # check that hash(d) == hash(int(d)) for integral values
1769 for value in test_values:
Stefan Krahdc817b22010-11-17 11:16:34 +00001770 self.assertEqual(hashit(value), hashit(int(value)))
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001771
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001772 #the same hash that to an int
Stefan Krahdc817b22010-11-17 11:16:34 +00001773 self.assertEqual(hashit(Decimal(23)), hashit(23))
Raymond Hettingerd325c4b2010-11-21 04:08:28 +00001774 self.assertRaises(TypeError, hash, Decimal('sNaN'))
Stefan Krahdc817b22010-11-17 11:16:34 +00001775 self.assertTrue(hashit(Decimal('Inf')))
1776 self.assertTrue(hashit(Decimal('-Inf')))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001777
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001778 # check that the hashes of a Decimal float match when they
1779 # represent exactly the same values
1780 test_strings = ['inf', '-Inf', '0.0', '-.0e1',
1781 '34.0', '2.5', '112390.625', '-0.515625']
1782 for s in test_strings:
1783 f = float(s)
1784 d = Decimal(s)
Stefan Krahdc817b22010-11-17 11:16:34 +00001785 self.assertEqual(hashit(f), hashit(d))
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001786
Stefan Krah1919b7e2012-03-21 18:25:23 +01001787 with localcontext() as c:
1788 # check that the value of the hash doesn't depend on the
1789 # current context (issue #1757)
1790 x = Decimal("123456789.1")
Christian Heimes2380ac72008-01-09 00:17:24 +00001791
Stefan Krah1919b7e2012-03-21 18:25:23 +01001792 c.prec = 6
1793 h1 = hashit(x)
1794 c.prec = 10
1795 h2 = hashit(x)
1796 c.prec = 16
1797 h3 = hashit(x)
Christian Heimes2380ac72008-01-09 00:17:24 +00001798
Stefan Krah1919b7e2012-03-21 18:25:23 +01001799 self.assertEqual(h1, h2)
1800 self.assertEqual(h1, h3)
1801
1802 c.prec = 10000
1803 x = 1100 ** 1248
1804 self.assertEqual(hashit(Decimal(x)), hashit(x))
Christian Heimes2380ac72008-01-09 00:17:24 +00001805
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001806 def test_min_and_max_methods(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001807 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001808
1809 d1 = Decimal('15.32')
1810 d2 = Decimal('28.5')
1811 l1 = 15
1812 l2 = 28
1813
1814 #between Decimals
Ezio Melotti6607d512010-04-03 14:59:49 +00001815 self.assertIs(min(d1,d2), d1)
1816 self.assertIs(min(d2,d1), d1)
1817 self.assertIs(max(d1,d2), d2)
1818 self.assertIs(max(d2,d1), d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001819
1820 #between Decimal and long
Ezio Melotti6607d512010-04-03 14:59:49 +00001821 self.assertIs(min(d1,l2), d1)
1822 self.assertIs(min(l2,d1), d1)
1823 self.assertIs(max(l1,d2), d2)
1824 self.assertIs(max(d2,l1), d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001825
1826 def test_as_nonzero(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001827 Decimal = self.decimal.Decimal
1828
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001829 #as false
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001830 self.assertFalse(Decimal(0))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001831 #as true
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001832 self.assertTrue(Decimal('0.372'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001833
1834 def test_tostring_methods(self):
1835 #Test str and repr methods.
Stefan Krah1919b7e2012-03-21 18:25:23 +01001836 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001837
1838 d = Decimal('15.32')
1839 self.assertEqual(str(d), '15.32') # str
Christian Heimes68f5fbe2008-02-14 08:27:37 +00001840 self.assertEqual(repr(d), "Decimal('15.32')") # repr
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001841
1842 def test_tonum_methods(self):
Mark Dickinson5c2db372009-12-05 20:28:34 +00001843 #Test float and int methods.
Stefan Krah1919b7e2012-03-21 18:25:23 +01001844 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001845
1846 d1 = Decimal('66')
1847 d2 = Decimal('15.32')
1848
1849 #int
1850 self.assertEqual(int(d1), 66)
1851 self.assertEqual(int(d2), 15)
1852
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001853 #float
1854 self.assertEqual(float(d1), 66)
1855 self.assertEqual(float(d2), 15.32)
1856
Mark Dickinsonb27406c2008-05-09 13:42:33 +00001857 #floor
1858 test_pairs = [
1859 ('123.00', 123),
1860 ('3.2', 3),
1861 ('3.54', 3),
1862 ('3.899', 3),
1863 ('-2.3', -3),
1864 ('-11.0', -11),
1865 ('0.0', 0),
1866 ('-0E3', 0),
Stefan Krah1919b7e2012-03-21 18:25:23 +01001867 ('89891211712379812736.1', 89891211712379812736),
Mark Dickinsonb27406c2008-05-09 13:42:33 +00001868 ]
1869 for d, i in test_pairs:
1870 self.assertEqual(math.floor(Decimal(d)), i)
1871 self.assertRaises(ValueError, math.floor, Decimal('-NaN'))
1872 self.assertRaises(ValueError, math.floor, Decimal('sNaN'))
1873 self.assertRaises(ValueError, math.floor, Decimal('NaN123'))
1874 self.assertRaises(OverflowError, math.floor, Decimal('Inf'))
1875 self.assertRaises(OverflowError, math.floor, Decimal('-Inf'))
1876
1877 #ceiling
1878 test_pairs = [
1879 ('123.00', 123),
1880 ('3.2', 4),
1881 ('3.54', 4),
1882 ('3.899', 4),
1883 ('-2.3', -2),
1884 ('-11.0', -11),
1885 ('0.0', 0),
1886 ('-0E3', 0),
Stefan Krah1919b7e2012-03-21 18:25:23 +01001887 ('89891211712379812736.1', 89891211712379812737),
Mark Dickinsonb27406c2008-05-09 13:42:33 +00001888 ]
1889 for d, i in test_pairs:
1890 self.assertEqual(math.ceil(Decimal(d)), i)
1891 self.assertRaises(ValueError, math.ceil, Decimal('-NaN'))
1892 self.assertRaises(ValueError, math.ceil, Decimal('sNaN'))
1893 self.assertRaises(ValueError, math.ceil, Decimal('NaN123'))
1894 self.assertRaises(OverflowError, math.ceil, Decimal('Inf'))
1895 self.assertRaises(OverflowError, math.ceil, Decimal('-Inf'))
1896
1897 #round, single argument
1898 test_pairs = [
1899 ('123.00', 123),
1900 ('3.2', 3),
1901 ('3.54', 4),
1902 ('3.899', 4),
1903 ('-2.3', -2),
1904 ('-11.0', -11),
1905 ('0.0', 0),
1906 ('-0E3', 0),
1907 ('-3.5', -4),
1908 ('-2.5', -2),
1909 ('-1.5', -2),
1910 ('-0.5', 0),
1911 ('0.5', 0),
1912 ('1.5', 2),
1913 ('2.5', 2),
1914 ('3.5', 4),
1915 ]
1916 for d, i in test_pairs:
1917 self.assertEqual(round(Decimal(d)), i)
1918 self.assertRaises(ValueError, round, Decimal('-NaN'))
1919 self.assertRaises(ValueError, round, Decimal('sNaN'))
1920 self.assertRaises(ValueError, round, Decimal('NaN123'))
1921 self.assertRaises(OverflowError, round, Decimal('Inf'))
1922 self.assertRaises(OverflowError, round, Decimal('-Inf'))
1923
1924 #round, two arguments; this is essentially equivalent
1925 #to quantize, which is already extensively tested
1926 test_triples = [
1927 ('123.456', -4, '0E+4'),
1928 ('123.456', -3, '0E+3'),
1929 ('123.456', -2, '1E+2'),
1930 ('123.456', -1, '1.2E+2'),
1931 ('123.456', 0, '123'),
1932 ('123.456', 1, '123.5'),
1933 ('123.456', 2, '123.46'),
1934 ('123.456', 3, '123.456'),
1935 ('123.456', 4, '123.4560'),
1936 ('123.455', 2, '123.46'),
1937 ('123.445', 2, '123.44'),
1938 ('Inf', 4, 'NaN'),
1939 ('-Inf', -23, 'NaN'),
1940 ('sNaN314', 3, 'NaN314'),
1941 ]
1942 for d, n, r in test_triples:
1943 self.assertEqual(str(round(Decimal(d), n)), r)
1944
Mark Dickinsonfc33d4c2012-08-24 18:53:10 +01001945 def test_nan_to_float(self):
1946 # Test conversions of decimal NANs to float.
1947 # See http://bugs.python.org/issue15544
1948 Decimal = self.decimal.Decimal
1949 for s in ('nan', 'nan1234', '-nan', '-nan2468'):
1950 f = float(Decimal(s))
1951 self.assertTrue(math.isnan(f))
1952 sign = math.copysign(1.0, f)
1953 self.assertEqual(sign, -1.0 if s.startswith('-') else 1.0)
1954
1955 def test_snan_to_float(self):
1956 Decimal = self.decimal.Decimal
1957 for s in ('snan', '-snan', 'snan1357', '-snan1234'):
1958 d = Decimal(s)
1959 self.assertRaises(ValueError, float, d)
1960
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001961 def test_eval_round_trip(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001962 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001963
1964 #with zero
1965 d = Decimal( (0, (0,), 0) )
1966 self.assertEqual(d, eval(repr(d)))
1967
1968 #int
1969 d = Decimal( (1, (4, 5), 0) )
1970 self.assertEqual(d, eval(repr(d)))
1971
1972 #float
1973 d = Decimal( (0, (4, 5, 3, 4), -2) )
1974 self.assertEqual(d, eval(repr(d)))
1975
1976 #weird
1977 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1978 self.assertEqual(d, eval(repr(d)))
1979
1980 def test_as_tuple(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001981 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001982
1983 #with zero
1984 d = Decimal(0)
1985 self.assertEqual(d.as_tuple(), (0, (0,), 0) )
1986
1987 #int
1988 d = Decimal(-45)
1989 self.assertEqual(d.as_tuple(), (1, (4, 5), 0) )
1990
1991 #complicated string
1992 d = Decimal("-4.34913534E-17")
1993 self.assertEqual(d.as_tuple(), (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1994
Stefan Krah1919b7e2012-03-21 18:25:23 +01001995 # XXX non-compliant infinity payload.
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001996 d = Decimal("Infinity")
1997 self.assertEqual(d.as_tuple(), (0, (0,), 'F') )
1998
Guido van Rossum8ce8a782007-11-01 19:42:39 +00001999 #leading zeros in coefficient should be stripped
2000 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), -2) )
2001 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), -2) )
2002 d = Decimal( (1, (0, 0, 0), 37) )
2003 self.assertEqual(d.as_tuple(), (1, (0,), 37))
2004 d = Decimal( (1, (), 37) )
2005 self.assertEqual(d.as_tuple(), (1, (0,), 37))
2006
2007 #leading zeros in NaN diagnostic info should be stripped
2008 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), 'n') )
2009 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), 'n') )
2010 d = Decimal( (1, (0, 0, 0), 'N') )
2011 self.assertEqual(d.as_tuple(), (1, (), 'N') )
2012 d = Decimal( (1, (), 'n') )
2013 self.assertEqual(d.as_tuple(), (1, (), 'n') )
2014
Stefan Krah1919b7e2012-03-21 18:25:23 +01002015 # XXX coefficient in infinity should raise an error
2016 if self.decimal == P:
2017 d = Decimal( (0, (4, 5, 3, 4), 'F') )
2018 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
2019 d = Decimal( (1, (0, 2, 7, 1), 'F') )
2020 self.assertEqual(d.as_tuple(), (1, (0,), 'F'))
Guido van Rossum8ce8a782007-11-01 19:42:39 +00002021
Stefan Krah1919b7e2012-03-21 18:25:23 +01002022 def test_subclassing(self):
2023 # Different behaviours when subclassing Decimal
2024 Decimal = self.decimal.Decimal
2025
2026 class MyDecimal(Decimal):
2027 pass
2028
2029 d1 = MyDecimal(1)
2030 d2 = MyDecimal(2)
2031 d = d1 + d2
2032 self.assertIs(type(d), Decimal)
2033
2034 d = d1.max(d2)
2035 self.assertIs(type(d), Decimal)
2036
2037 d = copy.copy(d1)
2038 self.assertIs(type(d), MyDecimal)
2039 self.assertEqual(d, d1)
2040
2041 d = copy.deepcopy(d1)
2042 self.assertIs(type(d), MyDecimal)
2043 self.assertEqual(d, d1)
2044
2045 def test_implicit_context(self):
2046 Decimal = self.decimal.Decimal
2047 getcontext = self.decimal.getcontext
2048
2049 # Check results when context given implicitly. (Issue 2478)
2050 c = getcontext()
2051 self.assertEqual(str(Decimal(0).sqrt()),
2052 str(c.sqrt(Decimal(0))))
2053
2054 def test_conversions_from_int(self):
2055 # Check that methods taking a second Decimal argument will
2056 # always accept an integer in place of a Decimal.
2057 Decimal = self.decimal.Decimal
2058
2059 self.assertEqual(Decimal(4).compare(3),
2060 Decimal(4).compare(Decimal(3)))
2061 self.assertEqual(Decimal(4).compare_signal(3),
2062 Decimal(4).compare_signal(Decimal(3)))
2063 self.assertEqual(Decimal(4).compare_total(3),
2064 Decimal(4).compare_total(Decimal(3)))
2065 self.assertEqual(Decimal(4).compare_total_mag(3),
2066 Decimal(4).compare_total_mag(Decimal(3)))
2067 self.assertEqual(Decimal(10101).logical_and(1001),
2068 Decimal(10101).logical_and(Decimal(1001)))
2069 self.assertEqual(Decimal(10101).logical_or(1001),
2070 Decimal(10101).logical_or(Decimal(1001)))
2071 self.assertEqual(Decimal(10101).logical_xor(1001),
2072 Decimal(10101).logical_xor(Decimal(1001)))
2073 self.assertEqual(Decimal(567).max(123),
2074 Decimal(567).max(Decimal(123)))
2075 self.assertEqual(Decimal(567).max_mag(123),
2076 Decimal(567).max_mag(Decimal(123)))
2077 self.assertEqual(Decimal(567).min(123),
2078 Decimal(567).min(Decimal(123)))
2079 self.assertEqual(Decimal(567).min_mag(123),
2080 Decimal(567).min_mag(Decimal(123)))
2081 self.assertEqual(Decimal(567).next_toward(123),
2082 Decimal(567).next_toward(Decimal(123)))
2083 self.assertEqual(Decimal(1234).quantize(100),
2084 Decimal(1234).quantize(Decimal(100)))
2085 self.assertEqual(Decimal(768).remainder_near(1234),
2086 Decimal(768).remainder_near(Decimal(1234)))
2087 self.assertEqual(Decimal(123).rotate(1),
2088 Decimal(123).rotate(Decimal(1)))
2089 self.assertEqual(Decimal(1234).same_quantum(1000),
2090 Decimal(1234).same_quantum(Decimal(1000)))
2091 self.assertEqual(Decimal('9.123').scaleb(-100),
2092 Decimal('9.123').scaleb(Decimal(-100)))
2093 self.assertEqual(Decimal(456).shift(-1),
2094 Decimal(456).shift(Decimal(-1)))
2095
2096 self.assertEqual(Decimal(-12).fma(Decimal(45), 67),
2097 Decimal(-12).fma(Decimal(45), Decimal(67)))
2098 self.assertEqual(Decimal(-12).fma(45, 67),
2099 Decimal(-12).fma(Decimal(45), Decimal(67)))
2100 self.assertEqual(Decimal(-12).fma(45, Decimal(67)),
2101 Decimal(-12).fma(Decimal(45), Decimal(67)))
2102
2103class CUsabilityTest(UsabilityTest):
2104 decimal = C
2105class PyUsabilityTest(UsabilityTest):
2106 decimal = P
2107
2108class PythonAPItests(unittest.TestCase):
2109
2110 def test_abc(self):
2111 Decimal = self.decimal.Decimal
2112
2113 self.assertTrue(issubclass(Decimal, numbers.Number))
2114 self.assertFalse(issubclass(Decimal, numbers.Real))
2115 self.assertIsInstance(Decimal(0), numbers.Number)
2116 self.assertNotIsInstance(Decimal(0), numbers.Real)
2117
2118 def test_pickle(self):
2119 Decimal = self.decimal.Decimal
2120
2121 savedecimal = sys.modules['decimal']
2122
2123 # Round trip
2124 sys.modules['decimal'] = self.decimal
2125 d = Decimal('-3.141590000')
2126 p = pickle.dumps(d)
2127 e = pickle.loads(p)
2128 self.assertEqual(d, e)
2129
2130 if C:
2131 # Test interchangeability
2132 x = C.Decimal('-3.123e81723')
2133 y = P.Decimal('-3.123e81723')
2134
2135 sys.modules['decimal'] = C
2136 sx = pickle.dumps(x)
2137 sys.modules['decimal'] = P
2138 r = pickle.loads(sx)
2139 self.assertIsInstance(r, P.Decimal)
2140 self.assertEqual(r, y)
2141
2142 sys.modules['decimal'] = P
2143 sy = pickle.dumps(y)
2144 sys.modules['decimal'] = C
2145 r = pickle.loads(sy)
2146 self.assertIsInstance(r, C.Decimal)
2147 self.assertEqual(r, x)
2148
2149 sys.modules['decimal'] = savedecimal
2150
2151 def test_int(self):
2152 Decimal = self.decimal.Decimal
2153 ROUND_DOWN = self.decimal.ROUND_DOWN
2154
2155 for x in range(-250, 250):
2156 s = '%0.2f' % (x / 100.0)
2157 # should work the same as for floats
2158 self.assertEqual(int(Decimal(s)), int(float(s)))
2159 # should work the same as to_integral in the ROUND_DOWN mode
2160 d = Decimal(s)
2161 r = d.to_integral(ROUND_DOWN)
2162 self.assertEqual(Decimal(int(d)), r)
2163
2164 self.assertRaises(ValueError, int, Decimal('-nan'))
2165 self.assertRaises(ValueError, int, Decimal('snan'))
2166 self.assertRaises(OverflowError, int, Decimal('inf'))
2167 self.assertRaises(OverflowError, int, Decimal('-inf'))
2168
2169 def test_trunc(self):
2170 Decimal = self.decimal.Decimal
2171 ROUND_DOWN = self.decimal.ROUND_DOWN
2172
2173 for x in range(-250, 250):
2174 s = '%0.2f' % (x / 100.0)
2175 # should work the same as for floats
2176 self.assertEqual(int(Decimal(s)), int(float(s)))
2177 # should work the same as to_integral in the ROUND_DOWN mode
2178 d = Decimal(s)
2179 r = d.to_integral(ROUND_DOWN)
2180 self.assertEqual(Decimal(math.trunc(d)), r)
2181
2182 def test_from_float(self):
2183
2184 Decimal = self.decimal.Decimal
2185
2186 class MyDecimal(Decimal):
2187 pass
2188
2189 self.assertTrue(issubclass(MyDecimal, Decimal))
2190
2191 r = MyDecimal.from_float(0.1)
2192 self.assertEqual(type(r), MyDecimal)
2193 self.assertEqual(str(r),
2194 '0.1000000000000000055511151231257827021181583404541015625')
2195 bigint = 12345678901234567890123456789
2196 self.assertEqual(MyDecimal.from_float(bigint), MyDecimal(bigint))
2197 self.assertTrue(MyDecimal.from_float(float('nan')).is_qnan())
2198 self.assertTrue(MyDecimal.from_float(float('inf')).is_infinite())
2199 self.assertTrue(MyDecimal.from_float(float('-inf')).is_infinite())
2200 self.assertEqual(str(MyDecimal.from_float(float('nan'))),
2201 str(Decimal('NaN')))
2202 self.assertEqual(str(MyDecimal.from_float(float('inf'))),
2203 str(Decimal('Infinity')))
2204 self.assertEqual(str(MyDecimal.from_float(float('-inf'))),
2205 str(Decimal('-Infinity')))
2206 self.assertRaises(TypeError, MyDecimal.from_float, 'abc')
2207 for i in range(200):
2208 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
2209 self.assertEqual(x, float(MyDecimal.from_float(x))) # roundtrip
2210
2211 def test_create_decimal_from_float(self):
2212 Decimal = self.decimal.Decimal
2213 Context = self.decimal.Context
2214 ROUND_DOWN = self.decimal.ROUND_DOWN
2215 ROUND_UP = self.decimal.ROUND_UP
2216 Inexact = self.decimal.Inexact
2217
2218 context = Context(prec=5, rounding=ROUND_DOWN)
2219 self.assertEqual(
2220 context.create_decimal_from_float(math.pi),
2221 Decimal('3.1415')
2222 )
2223 context = Context(prec=5, rounding=ROUND_UP)
2224 self.assertEqual(
2225 context.create_decimal_from_float(math.pi),
2226 Decimal('3.1416')
2227 )
2228 context = Context(prec=5, traps=[Inexact])
2229 self.assertRaises(
2230 Inexact,
2231 context.create_decimal_from_float,
2232 math.pi
2233 )
2234 self.assertEqual(repr(context.create_decimal_from_float(-0.0)),
2235 "Decimal('-0')")
2236 self.assertEqual(repr(context.create_decimal_from_float(1.0)),
2237 "Decimal('1')")
2238 self.assertEqual(repr(context.create_decimal_from_float(10)),
2239 "Decimal('10')")
2240
2241 def test_quantize(self):
2242 Decimal = self.decimal.Decimal
2243 Context = self.decimal.Context
2244 InvalidOperation = self.decimal.InvalidOperation
2245 ROUND_DOWN = self.decimal.ROUND_DOWN
2246
2247 c = Context(Emax=99999, Emin=-99999)
2248 self.assertEqual(
2249 Decimal('7.335').quantize(Decimal('.01')),
2250 Decimal('7.34')
2251 )
2252 self.assertEqual(
2253 Decimal('7.335').quantize(Decimal('.01'), rounding=ROUND_DOWN),
2254 Decimal('7.33')
2255 )
2256 self.assertRaises(
2257 InvalidOperation,
2258 Decimal("10e99999").quantize, Decimal('1e100000'), context=c
2259 )
2260
2261 c = Context()
2262 d = Decimal("0.871831e800")
2263 x = d.quantize(context=c, exp=Decimal("1e797"), rounding=ROUND_DOWN)
2264 self.assertEqual(x, Decimal('8.71E+799'))
2265
2266 def test_complex(self):
2267 Decimal = self.decimal.Decimal
2268
2269 x = Decimal("9.8182731e181273")
2270 self.assertEqual(x.real, x)
2271 self.assertEqual(x.imag, 0)
2272 self.assertEqual(x.conjugate(), x)
2273
2274 x = Decimal("1")
2275 self.assertEqual(complex(x), complex(float(1)))
2276
2277 self.assertRaises(AttributeError, setattr, x, 'real', 100)
2278 self.assertRaises(AttributeError, setattr, x, 'imag', 100)
2279 self.assertRaises(AttributeError, setattr, x, 'conjugate', 100)
2280 self.assertRaises(AttributeError, setattr, x, '__complex__', 100)
2281
2282 def test_named_parameters(self):
2283 D = self.decimal.Decimal
2284 Context = self.decimal.Context
2285 localcontext = self.decimal.localcontext
2286 InvalidOperation = self.decimal.InvalidOperation
2287 Overflow = self.decimal.Overflow
2288
2289 xc = Context()
2290 xc.prec = 1
2291 xc.Emax = 1
2292 xc.Emin = -1
2293
2294 with localcontext() as c:
2295 c.clear_flags()
2296
2297 self.assertEqual(D(9, xc), 9)
2298 self.assertEqual(D(9, context=xc), 9)
2299 self.assertEqual(D(context=xc, value=9), 9)
2300 self.assertEqual(D(context=xc), 0)
2301 xc.clear_flags()
2302 self.assertRaises(InvalidOperation, D, "xyz", context=xc)
2303 self.assertTrue(xc.flags[InvalidOperation])
2304 self.assertFalse(c.flags[InvalidOperation])
2305
2306 xc.clear_flags()
2307 self.assertEqual(D(2).exp(context=xc), 7)
2308 self.assertRaises(Overflow, D(8).exp, context=xc)
2309 self.assertTrue(xc.flags[Overflow])
2310 self.assertFalse(c.flags[Overflow])
2311
2312 xc.clear_flags()
2313 self.assertEqual(D(2).ln(context=xc), D('0.7'))
2314 self.assertRaises(InvalidOperation, D(-1).ln, context=xc)
2315 self.assertTrue(xc.flags[InvalidOperation])
2316 self.assertFalse(c.flags[InvalidOperation])
2317
2318 self.assertEqual(D(0).log10(context=xc), D('-inf'))
2319 self.assertEqual(D(-1).next_minus(context=xc), -2)
2320 self.assertEqual(D(-1).next_plus(context=xc), D('-0.9'))
2321 self.assertEqual(D("9.73").normalize(context=xc), D('1E+1'))
2322 self.assertEqual(D("9999").to_integral(context=xc), 9999)
2323 self.assertEqual(D("-2000").to_integral_exact(context=xc), -2000)
2324 self.assertEqual(D("123").to_integral_value(context=xc), 123)
2325 self.assertEqual(D("0.0625").sqrt(context=xc), D('0.2'))
2326
2327 self.assertEqual(D("0.0625").compare(context=xc, other=3), -1)
2328 xc.clear_flags()
2329 self.assertRaises(InvalidOperation,
2330 D("0").compare_signal, D('nan'), context=xc)
2331 self.assertTrue(xc.flags[InvalidOperation])
2332 self.assertFalse(c.flags[InvalidOperation])
2333 self.assertEqual(D("0.01").max(D('0.0101'), context=xc), D('0.0'))
2334 self.assertEqual(D("0.01").max(D('0.0101'), context=xc), D('0.0'))
2335 self.assertEqual(D("0.2").max_mag(D('-0.3'), context=xc),
2336 D('-0.3'))
2337 self.assertEqual(D("0.02").min(D('-0.03'), context=xc), D('-0.0'))
2338 self.assertEqual(D("0.02").min_mag(D('-0.03'), context=xc),
2339 D('0.0'))
2340 self.assertEqual(D("0.2").next_toward(D('-1'), context=xc), D('0.1'))
2341 xc.clear_flags()
2342 self.assertRaises(InvalidOperation,
2343 D("0.2").quantize, D('1e10'), context=xc)
2344 self.assertTrue(xc.flags[InvalidOperation])
2345 self.assertFalse(c.flags[InvalidOperation])
2346 self.assertEqual(D("9.99").remainder_near(D('1.5'), context=xc),
2347 D('-0.5'))
2348
2349 self.assertEqual(D("9.9").fma(third=D('0.9'), context=xc, other=7),
2350 D('7E+1'))
2351
2352 self.assertRaises(TypeError, D(1).is_canonical, context=xc)
2353 self.assertRaises(TypeError, D(1).is_finite, context=xc)
2354 self.assertRaises(TypeError, D(1).is_infinite, context=xc)
2355 self.assertRaises(TypeError, D(1).is_nan, context=xc)
2356 self.assertRaises(TypeError, D(1).is_qnan, context=xc)
2357 self.assertRaises(TypeError, D(1).is_snan, context=xc)
2358 self.assertRaises(TypeError, D(1).is_signed, context=xc)
2359 self.assertRaises(TypeError, D(1).is_zero, context=xc)
2360
2361 self.assertFalse(D("0.01").is_normal(context=xc))
2362 self.assertTrue(D("0.01").is_subnormal(context=xc))
2363
2364 self.assertRaises(TypeError, D(1).adjusted, context=xc)
2365 self.assertRaises(TypeError, D(1).conjugate, context=xc)
2366 self.assertRaises(TypeError, D(1).radix, context=xc)
2367
2368 self.assertEqual(D(-111).logb(context=xc), 2)
2369 self.assertEqual(D(0).logical_invert(context=xc), 1)
2370 self.assertEqual(D('0.01').number_class(context=xc), '+Subnormal')
2371 self.assertEqual(D('0.21').to_eng_string(context=xc), '0.21')
2372
2373 self.assertEqual(D('11').logical_and(D('10'), context=xc), 0)
2374 self.assertEqual(D('11').logical_or(D('10'), context=xc), 1)
2375 self.assertEqual(D('01').logical_xor(D('10'), context=xc), 1)
2376 self.assertEqual(D('23').rotate(1, context=xc), 3)
2377 self.assertEqual(D('23').rotate(1, context=xc), 3)
2378 xc.clear_flags()
2379 self.assertRaises(Overflow,
2380 D('23').scaleb, 1, context=xc)
2381 self.assertTrue(xc.flags[Overflow])
2382 self.assertFalse(c.flags[Overflow])
2383 self.assertEqual(D('23').shift(-1, context=xc), 0)
2384
2385 self.assertRaises(TypeError, D.from_float, 1.1, context=xc)
2386 self.assertRaises(TypeError, D(0).as_tuple, context=xc)
2387
2388 if (self.decimal == C):
2389 self.assertRaises(TypeError, D(1).canonical, context=xc)
2390 self.assertEqual(D("-1").copy_abs(context=xc), 1)
2391 self.assertEqual(D("1").copy_negate(context=xc), -1)
2392 else:
2393 self.assertEqual(D(1).canonical(context=xc), 1)
2394 self.assertRaises(TypeError, D("-1").copy_abs, context=xc)
2395 self.assertRaises(TypeError, D("-1").copy_negate, context=xc)
2396
Stefan Krahb6405ef2012-03-23 14:46:48 +01002397 def test_exception_hierarchy(self):
2398
2399 decimal = self.decimal
2400 DecimalException = decimal.DecimalException
2401 InvalidOperation = decimal.InvalidOperation
2402 FloatOperation = decimal.FloatOperation
2403 DivisionByZero = decimal.DivisionByZero
2404 Overflow = decimal.Overflow
2405 Underflow = decimal.Underflow
2406 Subnormal = decimal.Subnormal
2407 Inexact = decimal.Inexact
2408 Rounded = decimal.Rounded
2409 Clamped = decimal.Clamped
2410
2411 self.assertTrue(issubclass(DecimalException, ArithmeticError))
2412
2413 self.assertTrue(issubclass(InvalidOperation, DecimalException))
2414 self.assertTrue(issubclass(FloatOperation, DecimalException))
2415 self.assertTrue(issubclass(FloatOperation, TypeError))
2416 self.assertTrue(issubclass(DivisionByZero, DecimalException))
2417 self.assertTrue(issubclass(DivisionByZero, ZeroDivisionError))
2418 self.assertTrue(issubclass(Overflow, Rounded))
2419 self.assertTrue(issubclass(Overflow, Inexact))
2420 self.assertTrue(issubclass(Overflow, DecimalException))
2421 self.assertTrue(issubclass(Underflow, Inexact))
2422 self.assertTrue(issubclass(Underflow, Rounded))
2423 self.assertTrue(issubclass(Underflow, Subnormal))
2424 self.assertTrue(issubclass(Underflow, DecimalException))
2425
2426 self.assertTrue(issubclass(Subnormal, DecimalException))
2427 self.assertTrue(issubclass(Inexact, DecimalException))
2428 self.assertTrue(issubclass(Rounded, DecimalException))
2429 self.assertTrue(issubclass(Clamped, DecimalException))
2430
2431 self.assertTrue(issubclass(decimal.ConversionSyntax, InvalidOperation))
2432 self.assertTrue(issubclass(decimal.DivisionImpossible, InvalidOperation))
2433 self.assertTrue(issubclass(decimal.DivisionUndefined, InvalidOperation))
2434 self.assertTrue(issubclass(decimal.DivisionUndefined, ZeroDivisionError))
2435 self.assertTrue(issubclass(decimal.InvalidContext, InvalidOperation))
2436
Stefan Krah1919b7e2012-03-21 18:25:23 +01002437class CPythonAPItests(PythonAPItests):
2438 decimal = C
2439class PyPythonAPItests(PythonAPItests):
2440 decimal = P
2441
2442class ContextAPItests(unittest.TestCase):
2443
2444 def test_pickle(self):
2445
2446 Context = self.decimal.Context
2447
2448 savedecimal = sys.modules['decimal']
2449
2450 # Round trip
2451 sys.modules['decimal'] = self.decimal
2452 c = Context()
2453 e = pickle.loads(pickle.dumps(c))
2454
2455 self.assertEqual(c.prec, e.prec)
2456 self.assertEqual(c.Emin, e.Emin)
2457 self.assertEqual(c.Emax, e.Emax)
2458 self.assertEqual(c.rounding, e.rounding)
2459 self.assertEqual(c.capitals, e.capitals)
2460 self.assertEqual(c.clamp, e.clamp)
2461 self.assertEqual(c.flags, e.flags)
2462 self.assertEqual(c.traps, e.traps)
2463
2464 # Test interchangeability
2465 combinations = [(C, P), (P, C)] if C else [(P, P)]
2466 for dumper, loader in combinations:
2467 for ri, _ in enumerate(RoundingModes[dumper]):
2468 for fi, _ in enumerate(OrderedSignals[dumper]):
2469 for ti, _ in enumerate(OrderedSignals[dumper]):
2470
2471 prec = random.randrange(1, 100)
2472 emin = random.randrange(-100, 0)
2473 emax = random.randrange(1, 100)
2474 caps = random.randrange(2)
2475 clamp = random.randrange(2)
2476
2477 # One module dumps
2478 sys.modules['decimal'] = dumper
2479 c = dumper.Context(
2480 prec=prec, Emin=emin, Emax=emax,
2481 rounding=RoundingModes[dumper][ri],
2482 capitals=caps, clamp=clamp,
2483 flags=OrderedSignals[dumper][:fi],
2484 traps=OrderedSignals[dumper][:ti]
2485 )
2486 s = pickle.dumps(c)
2487
2488 # The other module loads
2489 sys.modules['decimal'] = loader
2490 d = pickle.loads(s)
2491 self.assertIsInstance(d, loader.Context)
2492
2493 self.assertEqual(d.prec, prec)
2494 self.assertEqual(d.Emin, emin)
2495 self.assertEqual(d.Emax, emax)
2496 self.assertEqual(d.rounding, RoundingModes[loader][ri])
2497 self.assertEqual(d.capitals, caps)
2498 self.assertEqual(d.clamp, clamp)
2499 assert_signals(self, d, 'flags', OrderedSignals[loader][:fi])
2500 assert_signals(self, d, 'traps', OrderedSignals[loader][:ti])
2501
2502 sys.modules['decimal'] = savedecimal
2503
2504 def test_equality_with_other_types(self):
2505 Decimal = self.decimal.Decimal
2506
2507 self.assertIn(Decimal(10), ['a', 1.0, Decimal(10), (1,2), {}])
2508 self.assertNotIn(Decimal(10), ['a', 1.0, (1,2), {}])
2509
2510 def test_copy(self):
2511 # All copies should be deep
2512 Decimal = self.decimal.Decimal
2513 Context = self.decimal.Context
2514
2515 c = Context()
2516 d = c.copy()
2517 self.assertNotEqual(id(c), id(d))
2518 self.assertNotEqual(id(c.flags), id(d.flags))
2519 self.assertNotEqual(id(c.traps), id(d.traps))
2520 k1 = set(c.flags.keys())
2521 k2 = set(d.flags.keys())
2522 self.assertEqual(k1, k2)
2523 self.assertEqual(c.flags, d.flags)
2524
2525 def test__clamp(self):
2526 # In Python 3.2, the private attribute `_clamp` was made
2527 # public (issue 8540), with the old `_clamp` becoming a
2528 # property wrapping `clamp`. For the duration of Python 3.2
2529 # only, the attribute should be gettable/settable via both
2530 # `clamp` and `_clamp`; in Python 3.3, `_clamp` should be
2531 # removed.
2532 Context = self.decimal.Context
2533 c = Context()
2534 self.assertRaises(AttributeError, getattr, c, '_clamp')
2535
2536 def test_abs(self):
2537 Decimal = self.decimal.Decimal
2538 Context = self.decimal.Context
2539
2540 c = Context()
2541 d = c.abs(Decimal(-1))
2542 self.assertEqual(c.abs(-1), d)
2543 self.assertRaises(TypeError, c.abs, '-1')
2544
2545 def test_add(self):
2546 Decimal = self.decimal.Decimal
2547 Context = self.decimal.Context
2548
2549 c = Context()
2550 d = c.add(Decimal(1), Decimal(1))
2551 self.assertEqual(c.add(1, 1), d)
2552 self.assertEqual(c.add(Decimal(1), 1), d)
2553 self.assertEqual(c.add(1, Decimal(1)), d)
2554 self.assertRaises(TypeError, c.add, '1', 1)
2555 self.assertRaises(TypeError, c.add, 1, '1')
2556
2557 def test_compare(self):
2558 Decimal = self.decimal.Decimal
2559 Context = self.decimal.Context
2560
2561 c = Context()
2562 d = c.compare(Decimal(1), Decimal(1))
2563 self.assertEqual(c.compare(1, 1), d)
2564 self.assertEqual(c.compare(Decimal(1), 1), d)
2565 self.assertEqual(c.compare(1, Decimal(1)), d)
2566 self.assertRaises(TypeError, c.compare, '1', 1)
2567 self.assertRaises(TypeError, c.compare, 1, '1')
2568
2569 def test_compare_signal(self):
2570 Decimal = self.decimal.Decimal
2571 Context = self.decimal.Context
2572
2573 c = Context()
2574 d = c.compare_signal(Decimal(1), Decimal(1))
2575 self.assertEqual(c.compare_signal(1, 1), d)
2576 self.assertEqual(c.compare_signal(Decimal(1), 1), d)
2577 self.assertEqual(c.compare_signal(1, Decimal(1)), d)
2578 self.assertRaises(TypeError, c.compare_signal, '1', 1)
2579 self.assertRaises(TypeError, c.compare_signal, 1, '1')
2580
2581 def test_compare_total(self):
2582 Decimal = self.decimal.Decimal
2583 Context = self.decimal.Context
2584
2585 c = Context()
2586 d = c.compare_total(Decimal(1), Decimal(1))
2587 self.assertEqual(c.compare_total(1, 1), d)
2588 self.assertEqual(c.compare_total(Decimal(1), 1), d)
2589 self.assertEqual(c.compare_total(1, Decimal(1)), d)
2590 self.assertRaises(TypeError, c.compare_total, '1', 1)
2591 self.assertRaises(TypeError, c.compare_total, 1, '1')
2592
2593 def test_compare_total_mag(self):
2594 Decimal = self.decimal.Decimal
2595 Context = self.decimal.Context
2596
2597 c = Context()
2598 d = c.compare_total_mag(Decimal(1), Decimal(1))
2599 self.assertEqual(c.compare_total_mag(1, 1), d)
2600 self.assertEqual(c.compare_total_mag(Decimal(1), 1), d)
2601 self.assertEqual(c.compare_total_mag(1, Decimal(1)), d)
2602 self.assertRaises(TypeError, c.compare_total_mag, '1', 1)
2603 self.assertRaises(TypeError, c.compare_total_mag, 1, '1')
2604
2605 def test_copy_abs(self):
2606 Decimal = self.decimal.Decimal
2607 Context = self.decimal.Context
2608
2609 c = Context()
2610 d = c.copy_abs(Decimal(-1))
2611 self.assertEqual(c.copy_abs(-1), d)
2612 self.assertRaises(TypeError, c.copy_abs, '-1')
2613
2614 def test_copy_decimal(self):
2615 Decimal = self.decimal.Decimal
2616 Context = self.decimal.Context
2617
2618 c = Context()
2619 d = c.copy_decimal(Decimal(-1))
2620 self.assertEqual(c.copy_decimal(-1), d)
2621 self.assertRaises(TypeError, c.copy_decimal, '-1')
2622
2623 def test_copy_negate(self):
2624 Decimal = self.decimal.Decimal
2625 Context = self.decimal.Context
2626
2627 c = Context()
2628 d = c.copy_negate(Decimal(-1))
2629 self.assertEqual(c.copy_negate(-1), d)
2630 self.assertRaises(TypeError, c.copy_negate, '-1')
2631
2632 def test_copy_sign(self):
2633 Decimal = self.decimal.Decimal
2634 Context = self.decimal.Context
2635
2636 c = Context()
2637 d = c.copy_sign(Decimal(1), Decimal(-2))
2638 self.assertEqual(c.copy_sign(1, -2), d)
2639 self.assertEqual(c.copy_sign(Decimal(1), -2), d)
2640 self.assertEqual(c.copy_sign(1, Decimal(-2)), d)
2641 self.assertRaises(TypeError, c.copy_sign, '1', -2)
2642 self.assertRaises(TypeError, c.copy_sign, 1, '-2')
2643
2644 def test_divide(self):
2645 Decimal = self.decimal.Decimal
2646 Context = self.decimal.Context
2647
2648 c = Context()
2649 d = c.divide(Decimal(1), Decimal(2))
2650 self.assertEqual(c.divide(1, 2), d)
2651 self.assertEqual(c.divide(Decimal(1), 2), d)
2652 self.assertEqual(c.divide(1, Decimal(2)), d)
2653 self.assertRaises(TypeError, c.divide, '1', 2)
2654 self.assertRaises(TypeError, c.divide, 1, '2')
2655
2656 def test_divide_int(self):
2657 Decimal = self.decimal.Decimal
2658 Context = self.decimal.Context
2659
2660 c = Context()
2661 d = c.divide_int(Decimal(1), Decimal(2))
2662 self.assertEqual(c.divide_int(1, 2), d)
2663 self.assertEqual(c.divide_int(Decimal(1), 2), d)
2664 self.assertEqual(c.divide_int(1, Decimal(2)), d)
2665 self.assertRaises(TypeError, c.divide_int, '1', 2)
2666 self.assertRaises(TypeError, c.divide_int, 1, '2')
2667
2668 def test_divmod(self):
2669 Decimal = self.decimal.Decimal
2670 Context = self.decimal.Context
2671
2672 c = Context()
2673 d = c.divmod(Decimal(1), Decimal(2))
2674 self.assertEqual(c.divmod(1, 2), d)
2675 self.assertEqual(c.divmod(Decimal(1), 2), d)
2676 self.assertEqual(c.divmod(1, Decimal(2)), d)
2677 self.assertRaises(TypeError, c.divmod, '1', 2)
2678 self.assertRaises(TypeError, c.divmod, 1, '2')
2679
2680 def test_exp(self):
2681 Decimal = self.decimal.Decimal
2682 Context = self.decimal.Context
2683
2684 c = Context()
2685 d = c.exp(Decimal(10))
2686 self.assertEqual(c.exp(10), d)
2687 self.assertRaises(TypeError, c.exp, '10')
2688
2689 def test_fma(self):
2690 Decimal = self.decimal.Decimal
2691 Context = self.decimal.Context
2692
2693 c = Context()
2694 d = c.fma(Decimal(2), Decimal(3), Decimal(4))
2695 self.assertEqual(c.fma(2, 3, 4), d)
2696 self.assertEqual(c.fma(Decimal(2), 3, 4), d)
2697 self.assertEqual(c.fma(2, Decimal(3), 4), d)
2698 self.assertEqual(c.fma(2, 3, Decimal(4)), d)
2699 self.assertEqual(c.fma(Decimal(2), Decimal(3), 4), d)
2700 self.assertRaises(TypeError, c.fma, '2', 3, 4)
2701 self.assertRaises(TypeError, c.fma, 2, '3', 4)
2702 self.assertRaises(TypeError, c.fma, 2, 3, '4')
2703
2704 # Issue 12079 for Context.fma ...
2705 self.assertRaises(TypeError, c.fma,
2706 Decimal('Infinity'), Decimal(0), "not a decimal")
2707 self.assertRaises(TypeError, c.fma,
2708 Decimal(1), Decimal('snan'), 1.222)
2709 # ... and for Decimal.fma.
2710 self.assertRaises(TypeError, Decimal('Infinity').fma,
2711 Decimal(0), "not a decimal")
2712 self.assertRaises(TypeError, Decimal(1).fma,
2713 Decimal('snan'), 1.222)
2714
2715 def test_is_finite(self):
2716 Decimal = self.decimal.Decimal
2717 Context = self.decimal.Context
2718
2719 c = Context()
2720 d = c.is_finite(Decimal(10))
2721 self.assertEqual(c.is_finite(10), d)
2722 self.assertRaises(TypeError, c.is_finite, '10')
2723
2724 def test_is_infinite(self):
2725 Decimal = self.decimal.Decimal
2726 Context = self.decimal.Context
2727
2728 c = Context()
2729 d = c.is_infinite(Decimal(10))
2730 self.assertEqual(c.is_infinite(10), d)
2731 self.assertRaises(TypeError, c.is_infinite, '10')
2732
2733 def test_is_nan(self):
2734 Decimal = self.decimal.Decimal
2735 Context = self.decimal.Context
2736
2737 c = Context()
2738 d = c.is_nan(Decimal(10))
2739 self.assertEqual(c.is_nan(10), d)
2740 self.assertRaises(TypeError, c.is_nan, '10')
2741
2742 def test_is_normal(self):
2743 Decimal = self.decimal.Decimal
2744 Context = self.decimal.Context
2745
2746 c = Context()
2747 d = c.is_normal(Decimal(10))
2748 self.assertEqual(c.is_normal(10), d)
2749 self.assertRaises(TypeError, c.is_normal, '10')
2750
2751 def test_is_qnan(self):
2752 Decimal = self.decimal.Decimal
2753 Context = self.decimal.Context
2754
2755 c = Context()
2756 d = c.is_qnan(Decimal(10))
2757 self.assertEqual(c.is_qnan(10), d)
2758 self.assertRaises(TypeError, c.is_qnan, '10')
2759
2760 def test_is_signed(self):
2761 Decimal = self.decimal.Decimal
2762 Context = self.decimal.Context
2763
2764 c = Context()
2765 d = c.is_signed(Decimal(10))
2766 self.assertEqual(c.is_signed(10), d)
2767 self.assertRaises(TypeError, c.is_signed, '10')
2768
2769 def test_is_snan(self):
2770 Decimal = self.decimal.Decimal
2771 Context = self.decimal.Context
2772
2773 c = Context()
2774 d = c.is_snan(Decimal(10))
2775 self.assertEqual(c.is_snan(10), d)
2776 self.assertRaises(TypeError, c.is_snan, '10')
2777
2778 def test_is_subnormal(self):
2779 Decimal = self.decimal.Decimal
2780 Context = self.decimal.Context
2781
2782 c = Context()
2783 d = c.is_subnormal(Decimal(10))
2784 self.assertEqual(c.is_subnormal(10), d)
2785 self.assertRaises(TypeError, c.is_subnormal, '10')
2786
2787 def test_is_zero(self):
2788 Decimal = self.decimal.Decimal
2789 Context = self.decimal.Context
2790
2791 c = Context()
2792 d = c.is_zero(Decimal(10))
2793 self.assertEqual(c.is_zero(10), d)
2794 self.assertRaises(TypeError, c.is_zero, '10')
2795
2796 def test_ln(self):
2797 Decimal = self.decimal.Decimal
2798 Context = self.decimal.Context
2799
2800 c = Context()
2801 d = c.ln(Decimal(10))
2802 self.assertEqual(c.ln(10), d)
2803 self.assertRaises(TypeError, c.ln, '10')
2804
2805 def test_log10(self):
2806 Decimal = self.decimal.Decimal
2807 Context = self.decimal.Context
2808
2809 c = Context()
2810 d = c.log10(Decimal(10))
2811 self.assertEqual(c.log10(10), d)
2812 self.assertRaises(TypeError, c.log10, '10')
2813
2814 def test_logb(self):
2815 Decimal = self.decimal.Decimal
2816 Context = self.decimal.Context
2817
2818 c = Context()
2819 d = c.logb(Decimal(10))
2820 self.assertEqual(c.logb(10), d)
2821 self.assertRaises(TypeError, c.logb, '10')
2822
2823 def test_logical_and(self):
2824 Decimal = self.decimal.Decimal
2825 Context = self.decimal.Context
2826
2827 c = Context()
2828 d = c.logical_and(Decimal(1), Decimal(1))
2829 self.assertEqual(c.logical_and(1, 1), d)
2830 self.assertEqual(c.logical_and(Decimal(1), 1), d)
2831 self.assertEqual(c.logical_and(1, Decimal(1)), d)
2832 self.assertRaises(TypeError, c.logical_and, '1', 1)
2833 self.assertRaises(TypeError, c.logical_and, 1, '1')
2834
2835 def test_logical_invert(self):
2836 Decimal = self.decimal.Decimal
2837 Context = self.decimal.Context
2838
2839 c = Context()
2840 d = c.logical_invert(Decimal(1000))
2841 self.assertEqual(c.logical_invert(1000), d)
2842 self.assertRaises(TypeError, c.logical_invert, '1000')
2843
2844 def test_logical_or(self):
2845 Decimal = self.decimal.Decimal
2846 Context = self.decimal.Context
2847
2848 c = Context()
2849 d = c.logical_or(Decimal(1), Decimal(1))
2850 self.assertEqual(c.logical_or(1, 1), d)
2851 self.assertEqual(c.logical_or(Decimal(1), 1), d)
2852 self.assertEqual(c.logical_or(1, Decimal(1)), d)
2853 self.assertRaises(TypeError, c.logical_or, '1', 1)
2854 self.assertRaises(TypeError, c.logical_or, 1, '1')
2855
2856 def test_logical_xor(self):
2857 Decimal = self.decimal.Decimal
2858 Context = self.decimal.Context
2859
2860 c = Context()
2861 d = c.logical_xor(Decimal(1), Decimal(1))
2862 self.assertEqual(c.logical_xor(1, 1), d)
2863 self.assertEqual(c.logical_xor(Decimal(1), 1), d)
2864 self.assertEqual(c.logical_xor(1, Decimal(1)), d)
2865 self.assertRaises(TypeError, c.logical_xor, '1', 1)
2866 self.assertRaises(TypeError, c.logical_xor, 1, '1')
2867
2868 def test_max(self):
2869 Decimal = self.decimal.Decimal
2870 Context = self.decimal.Context
2871
2872 c = Context()
2873 d = c.max(Decimal(1), Decimal(2))
2874 self.assertEqual(c.max(1, 2), d)
2875 self.assertEqual(c.max(Decimal(1), 2), d)
2876 self.assertEqual(c.max(1, Decimal(2)), d)
2877 self.assertRaises(TypeError, c.max, '1', 2)
2878 self.assertRaises(TypeError, c.max, 1, '2')
2879
2880 def test_max_mag(self):
2881 Decimal = self.decimal.Decimal
2882 Context = self.decimal.Context
2883
2884 c = Context()
2885 d = c.max_mag(Decimal(1), Decimal(2))
2886 self.assertEqual(c.max_mag(1, 2), d)
2887 self.assertEqual(c.max_mag(Decimal(1), 2), d)
2888 self.assertEqual(c.max_mag(1, Decimal(2)), d)
2889 self.assertRaises(TypeError, c.max_mag, '1', 2)
2890 self.assertRaises(TypeError, c.max_mag, 1, '2')
2891
2892 def test_min(self):
2893 Decimal = self.decimal.Decimal
2894 Context = self.decimal.Context
2895
2896 c = Context()
2897 d = c.min(Decimal(1), Decimal(2))
2898 self.assertEqual(c.min(1, 2), d)
2899 self.assertEqual(c.min(Decimal(1), 2), d)
2900 self.assertEqual(c.min(1, Decimal(2)), d)
2901 self.assertRaises(TypeError, c.min, '1', 2)
2902 self.assertRaises(TypeError, c.min, 1, '2')
2903
2904 def test_min_mag(self):
2905 Decimal = self.decimal.Decimal
2906 Context = self.decimal.Context
2907
2908 c = Context()
2909 d = c.min_mag(Decimal(1), Decimal(2))
2910 self.assertEqual(c.min_mag(1, 2), d)
2911 self.assertEqual(c.min_mag(Decimal(1), 2), d)
2912 self.assertEqual(c.min_mag(1, Decimal(2)), d)
2913 self.assertRaises(TypeError, c.min_mag, '1', 2)
2914 self.assertRaises(TypeError, c.min_mag, 1, '2')
2915
2916 def test_minus(self):
2917 Decimal = self.decimal.Decimal
2918 Context = self.decimal.Context
2919
2920 c = Context()
2921 d = c.minus(Decimal(10))
2922 self.assertEqual(c.minus(10), d)
2923 self.assertRaises(TypeError, c.minus, '10')
2924
2925 def test_multiply(self):
2926 Decimal = self.decimal.Decimal
2927 Context = self.decimal.Context
2928
2929 c = Context()
2930 d = c.multiply(Decimal(1), Decimal(2))
2931 self.assertEqual(c.multiply(1, 2), d)
2932 self.assertEqual(c.multiply(Decimal(1), 2), d)
2933 self.assertEqual(c.multiply(1, Decimal(2)), d)
2934 self.assertRaises(TypeError, c.multiply, '1', 2)
2935 self.assertRaises(TypeError, c.multiply, 1, '2')
2936
2937 def test_next_minus(self):
2938 Decimal = self.decimal.Decimal
2939 Context = self.decimal.Context
2940
2941 c = Context()
2942 d = c.next_minus(Decimal(10))
2943 self.assertEqual(c.next_minus(10), d)
2944 self.assertRaises(TypeError, c.next_minus, '10')
2945
2946 def test_next_plus(self):
2947 Decimal = self.decimal.Decimal
2948 Context = self.decimal.Context
2949
2950 c = Context()
2951 d = c.next_plus(Decimal(10))
2952 self.assertEqual(c.next_plus(10), d)
2953 self.assertRaises(TypeError, c.next_plus, '10')
2954
2955 def test_next_toward(self):
2956 Decimal = self.decimal.Decimal
2957 Context = self.decimal.Context
2958
2959 c = Context()
2960 d = c.next_toward(Decimal(1), Decimal(2))
2961 self.assertEqual(c.next_toward(1, 2), d)
2962 self.assertEqual(c.next_toward(Decimal(1), 2), d)
2963 self.assertEqual(c.next_toward(1, Decimal(2)), d)
2964 self.assertRaises(TypeError, c.next_toward, '1', 2)
2965 self.assertRaises(TypeError, c.next_toward, 1, '2')
2966
2967 def test_normalize(self):
2968 Decimal = self.decimal.Decimal
2969 Context = self.decimal.Context
2970
2971 c = Context()
2972 d = c.normalize(Decimal(10))
2973 self.assertEqual(c.normalize(10), d)
2974 self.assertRaises(TypeError, c.normalize, '10')
2975
2976 def test_number_class(self):
2977 Decimal = self.decimal.Decimal
2978 Context = self.decimal.Context
2979
2980 c = Context()
2981 self.assertEqual(c.number_class(123), c.number_class(Decimal(123)))
2982 self.assertEqual(c.number_class(0), c.number_class(Decimal(0)))
2983 self.assertEqual(c.number_class(-45), c.number_class(Decimal(-45)))
2984
2985 def test_plus(self):
2986 Decimal = self.decimal.Decimal
2987 Context = self.decimal.Context
2988
2989 c = Context()
2990 d = c.plus(Decimal(10))
2991 self.assertEqual(c.plus(10), d)
2992 self.assertRaises(TypeError, c.plus, '10')
2993
2994 def test_power(self):
2995 Decimal = self.decimal.Decimal
2996 Context = self.decimal.Context
2997
2998 c = Context()
2999 d = c.power(Decimal(1), Decimal(4))
3000 self.assertEqual(c.power(1, 4), d)
3001 self.assertEqual(c.power(Decimal(1), 4), d)
3002 self.assertEqual(c.power(1, Decimal(4)), d)
3003 self.assertEqual(c.power(Decimal(1), Decimal(4)), d)
3004 self.assertRaises(TypeError, c.power, '1', 4)
3005 self.assertRaises(TypeError, c.power, 1, '4')
3006 self.assertEqual(c.power(modulo=5, b=8, a=2), 1)
3007
3008 def test_quantize(self):
3009 Decimal = self.decimal.Decimal
3010 Context = self.decimal.Context
3011
3012 c = Context()
3013 d = c.quantize(Decimal(1), Decimal(2))
3014 self.assertEqual(c.quantize(1, 2), d)
3015 self.assertEqual(c.quantize(Decimal(1), 2), d)
3016 self.assertEqual(c.quantize(1, Decimal(2)), d)
3017 self.assertRaises(TypeError, c.quantize, '1', 2)
3018 self.assertRaises(TypeError, c.quantize, 1, '2')
3019
3020 def test_remainder(self):
3021 Decimal = self.decimal.Decimal
3022 Context = self.decimal.Context
3023
3024 c = Context()
3025 d = c.remainder(Decimal(1), Decimal(2))
3026 self.assertEqual(c.remainder(1, 2), d)
3027 self.assertEqual(c.remainder(Decimal(1), 2), d)
3028 self.assertEqual(c.remainder(1, Decimal(2)), d)
3029 self.assertRaises(TypeError, c.remainder, '1', 2)
3030 self.assertRaises(TypeError, c.remainder, 1, '2')
3031
3032 def test_remainder_near(self):
3033 Decimal = self.decimal.Decimal
3034 Context = self.decimal.Context
3035
3036 c = Context()
3037 d = c.remainder_near(Decimal(1), Decimal(2))
3038 self.assertEqual(c.remainder_near(1, 2), d)
3039 self.assertEqual(c.remainder_near(Decimal(1), 2), d)
3040 self.assertEqual(c.remainder_near(1, Decimal(2)), d)
3041 self.assertRaises(TypeError, c.remainder_near, '1', 2)
3042 self.assertRaises(TypeError, c.remainder_near, 1, '2')
3043
3044 def test_rotate(self):
3045 Decimal = self.decimal.Decimal
3046 Context = self.decimal.Context
3047
3048 c = Context()
3049 d = c.rotate(Decimal(1), Decimal(2))
3050 self.assertEqual(c.rotate(1, 2), d)
3051 self.assertEqual(c.rotate(Decimal(1), 2), d)
3052 self.assertEqual(c.rotate(1, Decimal(2)), d)
3053 self.assertRaises(TypeError, c.rotate, '1', 2)
3054 self.assertRaises(TypeError, c.rotate, 1, '2')
3055
3056 def test_sqrt(self):
3057 Decimal = self.decimal.Decimal
3058 Context = self.decimal.Context
3059
3060 c = Context()
3061 d = c.sqrt(Decimal(10))
3062 self.assertEqual(c.sqrt(10), d)
3063 self.assertRaises(TypeError, c.sqrt, '10')
3064
3065 def test_same_quantum(self):
3066 Decimal = self.decimal.Decimal
3067 Context = self.decimal.Context
3068
3069 c = Context()
3070 d = c.same_quantum(Decimal(1), Decimal(2))
3071 self.assertEqual(c.same_quantum(1, 2), d)
3072 self.assertEqual(c.same_quantum(Decimal(1), 2), d)
3073 self.assertEqual(c.same_quantum(1, Decimal(2)), d)
3074 self.assertRaises(TypeError, c.same_quantum, '1', 2)
3075 self.assertRaises(TypeError, c.same_quantum, 1, '2')
3076
3077 def test_scaleb(self):
3078 Decimal = self.decimal.Decimal
3079 Context = self.decimal.Context
3080
3081 c = Context()
3082 d = c.scaleb(Decimal(1), Decimal(2))
3083 self.assertEqual(c.scaleb(1, 2), d)
3084 self.assertEqual(c.scaleb(Decimal(1), 2), d)
3085 self.assertEqual(c.scaleb(1, Decimal(2)), d)
3086 self.assertRaises(TypeError, c.scaleb, '1', 2)
3087 self.assertRaises(TypeError, c.scaleb, 1, '2')
3088
3089 def test_shift(self):
3090 Decimal = self.decimal.Decimal
3091 Context = self.decimal.Context
3092
3093 c = Context()
3094 d = c.shift(Decimal(1), Decimal(2))
3095 self.assertEqual(c.shift(1, 2), d)
3096 self.assertEqual(c.shift(Decimal(1), 2), d)
3097 self.assertEqual(c.shift(1, Decimal(2)), d)
3098 self.assertRaises(TypeError, c.shift, '1', 2)
3099 self.assertRaises(TypeError, c.shift, 1, '2')
3100
3101 def test_subtract(self):
3102 Decimal = self.decimal.Decimal
3103 Context = self.decimal.Context
3104
3105 c = Context()
3106 d = c.subtract(Decimal(1), Decimal(2))
3107 self.assertEqual(c.subtract(1, 2), d)
3108 self.assertEqual(c.subtract(Decimal(1), 2), d)
3109 self.assertEqual(c.subtract(1, Decimal(2)), d)
3110 self.assertRaises(TypeError, c.subtract, '1', 2)
3111 self.assertRaises(TypeError, c.subtract, 1, '2')
3112
3113 def test_to_eng_string(self):
3114 Decimal = self.decimal.Decimal
3115 Context = self.decimal.Context
3116
3117 c = Context()
3118 d = c.to_eng_string(Decimal(10))
3119 self.assertEqual(c.to_eng_string(10), d)
3120 self.assertRaises(TypeError, c.to_eng_string, '10')
3121
3122 def test_to_sci_string(self):
3123 Decimal = self.decimal.Decimal
3124 Context = self.decimal.Context
3125
3126 c = Context()
3127 d = c.to_sci_string(Decimal(10))
3128 self.assertEqual(c.to_sci_string(10), d)
3129 self.assertRaises(TypeError, c.to_sci_string, '10')
3130
3131 def test_to_integral_exact(self):
3132 Decimal = self.decimal.Decimal
3133 Context = self.decimal.Context
3134
3135 c = Context()
3136 d = c.to_integral_exact(Decimal(10))
3137 self.assertEqual(c.to_integral_exact(10), d)
3138 self.assertRaises(TypeError, c.to_integral_exact, '10')
3139
3140 def test_to_integral_value(self):
3141 Decimal = self.decimal.Decimal
3142 Context = self.decimal.Context
3143
3144 c = Context()
3145 d = c.to_integral_value(Decimal(10))
3146 self.assertEqual(c.to_integral_value(10), d)
3147 self.assertRaises(TypeError, c.to_integral_value, '10')
3148 self.assertRaises(TypeError, c.to_integral_value, 10, 'x')
3149
3150class CContextAPItests(ContextAPItests):
3151 decimal = C
3152class PyContextAPItests(ContextAPItests):
3153 decimal = P
3154
3155class ContextWithStatement(unittest.TestCase):
3156 # Can't do these as docstrings until Python 2.6
3157 # as doctest can't handle __future__ statements
3158
3159 def test_localcontext(self):
3160 # Use a copy of the current context in the block
3161 getcontext = self.decimal.getcontext
3162 localcontext = self.decimal.localcontext
3163
3164 orig_ctx = getcontext()
3165 with localcontext() as enter_ctx:
3166 set_ctx = getcontext()
3167 final_ctx = getcontext()
3168 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
3169 self.assertIsNot(orig_ctx, set_ctx, 'did not copy the context')
3170 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
3171
3172 def test_localcontextarg(self):
3173 # Use a copy of the supplied context in the block
3174 Context = self.decimal.Context
3175 getcontext = self.decimal.getcontext
3176 localcontext = self.decimal.localcontext
3177
3178 localcontext = self.decimal.localcontext
3179 orig_ctx = getcontext()
3180 new_ctx = Context(prec=42)
3181 with localcontext(new_ctx) as enter_ctx:
3182 set_ctx = getcontext()
3183 final_ctx = getcontext()
3184 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
3185 self.assertEqual(set_ctx.prec, new_ctx.prec, 'did not set correct context')
3186 self.assertIsNot(new_ctx, set_ctx, 'did not copy the context')
3187 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
3188
3189 def test_nested_with_statements(self):
3190 # Use a copy of the supplied context in the block
3191 Decimal = self.decimal.Decimal
3192 Context = self.decimal.Context
3193 getcontext = self.decimal.getcontext
3194 localcontext = self.decimal.localcontext
3195 Clamped = self.decimal.Clamped
3196 Overflow = self.decimal.Overflow
3197
3198 orig_ctx = getcontext()
3199 orig_ctx.clear_flags()
3200 new_ctx = Context(Emax=384)
3201 with localcontext() as c1:
3202 self.assertEqual(c1.flags, orig_ctx.flags)
3203 self.assertEqual(c1.traps, orig_ctx.traps)
3204 c1.traps[Clamped] = True
3205 c1.Emin = -383
3206 self.assertNotEqual(orig_ctx.Emin, -383)
3207 self.assertRaises(Clamped, c1.create_decimal, '0e-999')
3208 self.assertTrue(c1.flags[Clamped])
3209 with localcontext(new_ctx) as c2:
3210 self.assertEqual(c2.flags, new_ctx.flags)
3211 self.assertEqual(c2.traps, new_ctx.traps)
3212 self.assertRaises(Overflow, c2.power, Decimal('3.4e200'), 2)
3213 self.assertFalse(c2.flags[Clamped])
3214 self.assertTrue(c2.flags[Overflow])
3215 del c2
3216 self.assertFalse(c1.flags[Overflow])
3217 del c1
3218 self.assertNotEqual(orig_ctx.Emin, -383)
3219 self.assertFalse(orig_ctx.flags[Clamped])
3220 self.assertFalse(orig_ctx.flags[Overflow])
3221 self.assertFalse(new_ctx.flags[Clamped])
3222 self.assertFalse(new_ctx.flags[Overflow])
3223
3224 def test_with_statements_gc1(self):
3225 localcontext = self.decimal.localcontext
3226
3227 with localcontext() as c1:
3228 del c1
3229 with localcontext() as c2:
3230 del c2
3231 with localcontext() as c3:
3232 del c3
3233 with localcontext() as c4:
3234 del c4
3235
3236 def test_with_statements_gc2(self):
3237 localcontext = self.decimal.localcontext
3238
3239 with localcontext() as c1:
3240 with localcontext(c1) as c2:
3241 del c1
3242 with localcontext(c2) as c3:
3243 del c2
3244 with localcontext(c3) as c4:
3245 del c3
3246 del c4
3247
3248 def test_with_statements_gc3(self):
3249 Context = self.decimal.Context
3250 localcontext = self.decimal.localcontext
3251 getcontext = self.decimal.getcontext
3252 setcontext = self.decimal.setcontext
3253
3254 with localcontext() as c1:
3255 del c1
3256 n1 = Context(prec=1)
3257 setcontext(n1)
3258 with localcontext(n1) as c2:
3259 del n1
3260 self.assertEqual(c2.prec, 1)
3261 del c2
3262 n2 = Context(prec=2)
3263 setcontext(n2)
3264 del n2
3265 self.assertEqual(getcontext().prec, 2)
3266 n3 = Context(prec=3)
3267 setcontext(n3)
3268 self.assertEqual(getcontext().prec, 3)
3269 with localcontext(n3) as c3:
3270 del n3
3271 self.assertEqual(c3.prec, 3)
3272 del c3
3273 n4 = Context(prec=4)
3274 setcontext(n4)
3275 del n4
3276 self.assertEqual(getcontext().prec, 4)
3277 with localcontext() as c4:
3278 self.assertEqual(c4.prec, 4)
3279 del c4
3280
3281class CContextWithStatement(ContextWithStatement):
3282 decimal = C
3283class PyContextWithStatement(ContextWithStatement):
3284 decimal = P
3285
3286class ContextFlags(unittest.TestCase):
3287
3288 def test_flags_irrelevant(self):
3289 # check that the result (numeric result + flags raised) of an
3290 # arithmetic operation doesn't depend on the current flags
3291 Decimal = self.decimal.Decimal
3292 Context = self.decimal.Context
3293 Inexact = self.decimal.Inexact
3294 Rounded = self.decimal.Rounded
3295 Underflow = self.decimal.Underflow
3296 Clamped = self.decimal.Clamped
3297 Subnormal = self.decimal.Subnormal
3298 ROUND_HALF_EVEN = self.decimal.ROUND_HALF_EVEN
3299
3300 def raise_error(context, flag):
3301 if self.decimal == C:
3302 context.flags[flag] = True
3303 if context.traps[flag]:
3304 raise flag
3305 else:
3306 context._raise_error(flag)
3307
3308 context = Context(prec=9, Emin = -425000000, Emax = 425000000,
3309 rounding=ROUND_HALF_EVEN, traps=[], flags=[])
3310
3311 # operations that raise various flags, in the form (function, arglist)
3312 operations = [
3313 (context._apply, [Decimal("100E-425000010")]),
3314 (context.sqrt, [Decimal(2)]),
3315 (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]),
3316 (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]),
3317 (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]),
3318 ]
3319
3320 # try various flags individually, then a whole lot at once
3321 flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal],
3322 [Inexact, Rounded, Underflow, Clamped, Subnormal]]
3323
3324 for fn, args in operations:
3325 # find answer and flags raised using a clean context
3326 context.clear_flags()
3327 ans = fn(*args)
3328 flags = [k for k, v in context.flags.items() if v]
3329
3330 for extra_flags in flagsets:
3331 # set flags, before calling operation
3332 context.clear_flags()
3333 for flag in extra_flags:
3334 raise_error(context, flag)
3335 new_ans = fn(*args)
3336
3337 # flags that we expect to be set after the operation
3338 expected_flags = list(flags)
3339 for flag in extra_flags:
3340 if flag not in expected_flags:
3341 expected_flags.append(flag)
3342 expected_flags.sort(key=id)
3343
3344 # flags we actually got
3345 new_flags = [k for k,v in context.flags.items() if v]
3346 new_flags.sort(key=id)
3347
3348 self.assertEqual(ans, new_ans,
3349 "operation produces different answers depending on flags set: " +
3350 "expected %s, got %s." % (ans, new_ans))
3351 self.assertEqual(new_flags, expected_flags,
3352 "operation raises different flags depending on flags set: " +
3353 "expected %s, got %s" % (expected_flags, new_flags))
3354
3355 def test_flag_comparisons(self):
3356 Context = self.decimal.Context
3357 Inexact = self.decimal.Inexact
3358 Rounded = self.decimal.Rounded
3359
3360 c = Context()
3361
3362 # Valid SignalDict
3363 self.assertNotEqual(c.flags, c.traps)
3364 self.assertNotEqual(c.traps, c.flags)
3365
3366 c.flags = c.traps
3367 self.assertEqual(c.flags, c.traps)
3368 self.assertEqual(c.traps, c.flags)
3369
3370 c.flags[Rounded] = True
3371 c.traps = c.flags
3372 self.assertEqual(c.flags, c.traps)
3373 self.assertEqual(c.traps, c.flags)
3374
3375 d = {}
3376 d.update(c.flags)
3377 self.assertEqual(d, c.flags)
3378 self.assertEqual(c.flags, d)
3379
3380 d[Inexact] = True
3381 self.assertNotEqual(d, c.flags)
3382 self.assertNotEqual(c.flags, d)
3383
3384 # Invalid SignalDict
3385 d = {Inexact:False}
3386 self.assertNotEqual(d, c.flags)
3387 self.assertNotEqual(c.flags, d)
3388
3389 d = ["xyz"]
3390 self.assertNotEqual(d, c.flags)
3391 self.assertNotEqual(c.flags, d)
3392
3393 @requires_IEEE_754
3394 def test_float_operation(self):
3395 Decimal = self.decimal.Decimal
3396 FloatOperation = self.decimal.FloatOperation
3397 localcontext = self.decimal.localcontext
3398
3399 with localcontext() as c:
3400 ##### trap is off by default
3401 self.assertFalse(c.traps[FloatOperation])
3402
3403 # implicit conversion sets the flag
3404 c.clear_flags()
3405 self.assertEqual(Decimal(7.5), 7.5)
3406 self.assertTrue(c.flags[FloatOperation])
3407
3408 c.clear_flags()
3409 self.assertEqual(c.create_decimal(7.5), 7.5)
3410 self.assertTrue(c.flags[FloatOperation])
3411
3412 # explicit conversion does not set the flag
3413 c.clear_flags()
3414 x = Decimal.from_float(7.5)
3415 self.assertFalse(c.flags[FloatOperation])
3416 # comparison sets the flag
3417 self.assertEqual(x, 7.5)
3418 self.assertTrue(c.flags[FloatOperation])
3419
3420 c.clear_flags()
3421 x = c.create_decimal_from_float(7.5)
3422 self.assertFalse(c.flags[FloatOperation])
3423 self.assertEqual(x, 7.5)
3424 self.assertTrue(c.flags[FloatOperation])
3425
3426 ##### set the trap
3427 c.traps[FloatOperation] = True
3428
3429 # implicit conversion raises
3430 c.clear_flags()
3431 self.assertRaises(FloatOperation, Decimal, 7.5)
3432 self.assertTrue(c.flags[FloatOperation])
3433
3434 c.clear_flags()
3435 self.assertRaises(FloatOperation, c.create_decimal, 7.5)
3436 self.assertTrue(c.flags[FloatOperation])
3437
3438 # explicit conversion is silent
3439 c.clear_flags()
3440 x = Decimal.from_float(7.5)
3441 self.assertFalse(c.flags[FloatOperation])
3442
3443 c.clear_flags()
3444 x = c.create_decimal_from_float(7.5)
3445 self.assertFalse(c.flags[FloatOperation])
3446
3447 def test_float_comparison(self):
3448 Decimal = self.decimal.Decimal
3449 Context = self.decimal.Context
3450 FloatOperation = self.decimal.FloatOperation
3451 localcontext = self.decimal.localcontext
3452
3453 def assert_attr(a, b, attr, context, signal=None):
3454 context.clear_flags()
3455 f = getattr(a, attr)
3456 if signal == FloatOperation:
3457 self.assertRaises(signal, f, b)
3458 else:
3459 self.assertIs(f(b), True)
3460 self.assertTrue(context.flags[FloatOperation])
3461
3462 small_d = Decimal('0.25')
3463 big_d = Decimal('3.0')
3464 small_f = 0.25
3465 big_f = 3.0
3466
3467 zero_d = Decimal('0.0')
3468 neg_zero_d = Decimal('-0.0')
3469 zero_f = 0.0
3470 neg_zero_f = -0.0
3471
3472 inf_d = Decimal('Infinity')
3473 neg_inf_d = Decimal('-Infinity')
3474 inf_f = float('inf')
3475 neg_inf_f = float('-inf')
3476
3477 def doit(c, signal=None):
3478 # Order
3479 for attr in '__lt__', '__le__':
3480 assert_attr(small_d, big_f, attr, c, signal)
3481
3482 for attr in '__gt__', '__ge__':
3483 assert_attr(big_d, small_f, attr, c, signal)
3484
3485 # Equality
3486 assert_attr(small_d, small_f, '__eq__', c, None)
3487
3488 assert_attr(neg_zero_d, neg_zero_f, '__eq__', c, None)
3489 assert_attr(neg_zero_d, zero_f, '__eq__', c, None)
3490
3491 assert_attr(zero_d, neg_zero_f, '__eq__', c, None)
3492 assert_attr(zero_d, zero_f, '__eq__', c, None)
3493
3494 assert_attr(neg_inf_d, neg_inf_f, '__eq__', c, None)
3495 assert_attr(inf_d, inf_f, '__eq__', c, None)
3496
3497 # Inequality
3498 assert_attr(small_d, big_f, '__ne__', c, None)
3499
3500 assert_attr(Decimal('0.1'), 0.1, '__ne__', c, None)
3501
3502 assert_attr(neg_inf_d, inf_f, '__ne__', c, None)
3503 assert_attr(inf_d, neg_inf_f, '__ne__', c, None)
3504
3505 assert_attr(Decimal('NaN'), float('nan'), '__ne__', c, None)
3506
3507 def test_containers(c, signal=None):
3508 c.clear_flags()
3509 s = set([100.0, Decimal('100.0')])
3510 self.assertEqual(len(s), 1)
3511 self.assertTrue(c.flags[FloatOperation])
3512
3513 c.clear_flags()
3514 if signal:
3515 self.assertRaises(signal, sorted, [1.0, Decimal('10.0')])
3516 else:
3517 s = sorted([10.0, Decimal('10.0')])
3518 self.assertTrue(c.flags[FloatOperation])
3519
3520 c.clear_flags()
3521 b = 10.0 in [Decimal('10.0'), 1.0]
3522 self.assertTrue(c.flags[FloatOperation])
3523
3524 c.clear_flags()
3525 b = 10.0 in {Decimal('10.0'):'a', 1.0:'b'}
3526 self.assertTrue(c.flags[FloatOperation])
3527
3528 nc = Context()
3529 with localcontext(nc) as c:
3530 self.assertFalse(c.traps[FloatOperation])
3531 doit(c, signal=None)
3532 test_containers(c, signal=None)
3533
3534 c.traps[FloatOperation] = True
3535 doit(c, signal=FloatOperation)
3536 test_containers(c, signal=FloatOperation)
3537
3538 def test_float_operation_default(self):
3539 Decimal = self.decimal.Decimal
3540 Context = self.decimal.Context
3541 Inexact = self.decimal.Inexact
3542 FloatOperation= self.decimal.FloatOperation
3543
3544 context = Context()
3545 self.assertFalse(context.flags[FloatOperation])
3546 self.assertFalse(context.traps[FloatOperation])
3547
3548 context.clear_traps()
3549 context.traps[Inexact] = True
3550 context.traps[FloatOperation] = True
3551 self.assertTrue(context.traps[FloatOperation])
3552 self.assertTrue(context.traps[Inexact])
3553
3554class CContextFlags(ContextFlags):
3555 decimal = C
3556class PyContextFlags(ContextFlags):
3557 decimal = P
3558
3559class SpecialContexts(unittest.TestCase):
3560 """Test the context templates."""
3561
3562 def test_context_templates(self):
3563 BasicContext = self.decimal.BasicContext
3564 ExtendedContext = self.decimal.ExtendedContext
3565 getcontext = self.decimal.getcontext
3566 setcontext = self.decimal.setcontext
3567 InvalidOperation = self.decimal.InvalidOperation
3568 DivisionByZero = self.decimal.DivisionByZero
3569 Overflow = self.decimal.Overflow
3570 Underflow = self.decimal.Underflow
3571 Clamped = self.decimal.Clamped
3572
3573 assert_signals(self, BasicContext, 'traps',
3574 [InvalidOperation, DivisionByZero, Overflow, Underflow, Clamped]
3575 )
3576
3577 savecontext = getcontext().copy()
3578 basic_context_prec = BasicContext.prec
3579 extended_context_prec = ExtendedContext.prec
3580
3581 ex = None
3582 try:
3583 BasicContext.prec = ExtendedContext.prec = 441
3584 for template in BasicContext, ExtendedContext:
3585 setcontext(template)
3586 c = getcontext()
3587 self.assertIsNot(c, template)
3588 self.assertEqual(c.prec, 441)
3589 except Exception as e:
3590 ex = e.__class__
3591 finally:
3592 BasicContext.prec = basic_context_prec
3593 ExtendedContext.prec = extended_context_prec
3594 setcontext(savecontext)
3595 if ex:
3596 raise ex
3597
3598 def test_default_context(self):
3599 DefaultContext = self.decimal.DefaultContext
3600 BasicContext = self.decimal.BasicContext
3601 ExtendedContext = self.decimal.ExtendedContext
3602 getcontext = self.decimal.getcontext
3603 setcontext = self.decimal.setcontext
3604 InvalidOperation = self.decimal.InvalidOperation
3605 DivisionByZero = self.decimal.DivisionByZero
3606 Overflow = self.decimal.Overflow
3607
3608 self.assertEqual(BasicContext.prec, 9)
3609 self.assertEqual(ExtendedContext.prec, 9)
3610
3611 assert_signals(self, DefaultContext, 'traps',
3612 [InvalidOperation, DivisionByZero, Overflow]
3613 )
3614
3615 savecontext = getcontext().copy()
3616 default_context_prec = DefaultContext.prec
3617
3618 ex = None
3619 try:
3620 c = getcontext()
3621 saveprec = c.prec
3622
3623 DefaultContext.prec = 961
3624 c = getcontext()
3625 self.assertEqual(c.prec, saveprec)
3626
3627 setcontext(DefaultContext)
3628 c = getcontext()
3629 self.assertIsNot(c, DefaultContext)
3630 self.assertEqual(c.prec, 961)
3631 except Exception as e:
3632 ex = e.__class__
3633 finally:
3634 DefaultContext.prec = default_context_prec
3635 setcontext(savecontext)
3636 if ex:
3637 raise ex
3638
3639class CSpecialContexts(SpecialContexts):
3640 decimal = C
3641class PySpecialContexts(SpecialContexts):
3642 decimal = P
3643
3644class ContextInputValidation(unittest.TestCase):
3645
3646 def test_invalid_context(self):
3647 Context = self.decimal.Context
3648 DefaultContext = self.decimal.DefaultContext
3649
3650 c = DefaultContext.copy()
3651
3652 # prec, Emax
3653 for attr in ['prec', 'Emax']:
3654 setattr(c, attr, 999999)
3655 self.assertEqual(getattr(c, attr), 999999)
3656 self.assertRaises(ValueError, setattr, c, attr, -1)
3657 self.assertRaises(TypeError, setattr, c, attr, 'xyz')
3658
3659 # Emin
3660 setattr(c, 'Emin', -999999)
3661 self.assertEqual(getattr(c, 'Emin'), -999999)
3662 self.assertRaises(ValueError, setattr, c, 'Emin', 1)
3663 self.assertRaises(TypeError, setattr, c, 'Emin', (1,2,3))
3664
3665 # rounding: always raise TypeError in order to get consistent
3666 # exceptions across implementations. In decimal, rounding
3667 # modes are strings, in _decimal they are integers. The idea
3668 # is to view rounding as an abstract type and not mind the
3669 # implementation details.
3670 # Hence, a user should view the rounding modes as if they
3671 # had been defined in a language that supports abstract
3672 # data types, e.g. ocaml:
3673 #
3674 # type rounding = ROUND_DOWN | ROUND_HALF_UP | ... ;;
3675 #
3676 self.assertRaises(TypeError, setattr, c, 'rounding', -1)
3677 self.assertRaises(TypeError, setattr, c, 'rounding', 9)
3678 self.assertRaises(TypeError, setattr, c, 'rounding', 1.0)
3679 self.assertRaises(TypeError, setattr, c, 'rounding', 'xyz')
3680
3681 # capitals, clamp
3682 for attr in ['capitals', 'clamp']:
3683 self.assertRaises(ValueError, setattr, c, attr, -1)
3684 self.assertRaises(ValueError, setattr, c, attr, 2)
3685 self.assertRaises(TypeError, setattr, c, attr, [1,2,3])
3686
3687 # Invalid attribute
3688 self.assertRaises(AttributeError, setattr, c, 'emax', 100)
3689
3690 # Invalid signal dict
3691 self.assertRaises(TypeError, setattr, c, 'flags', [])
3692 self.assertRaises(KeyError, setattr, c, 'flags', {})
3693 self.assertRaises(KeyError, setattr, c, 'traps',
3694 {'InvalidOperation':0})
3695
3696 # Attributes cannot be deleted
3697 for attr in ['prec', 'Emax', 'Emin', 'rounding', 'capitals', 'clamp',
3698 'flags', 'traps']:
3699 self.assertRaises(AttributeError, c.__delattr__, attr)
3700
3701 # Invalid attributes
3702 self.assertRaises(TypeError, getattr, c, 9)
3703 self.assertRaises(TypeError, setattr, c, 9)
3704
3705 # Invalid values in constructor
3706 self.assertRaises(TypeError, Context, rounding=999999)
3707 self.assertRaises(TypeError, Context, rounding='xyz')
3708 self.assertRaises(ValueError, Context, clamp=2)
3709 self.assertRaises(ValueError, Context, capitals=-1)
3710 self.assertRaises(KeyError, Context, flags=["P"])
3711 self.assertRaises(KeyError, Context, traps=["Q"])
3712
3713 # Type error in conversion
3714 self.assertRaises(TypeError, Context, flags=(0,1))
3715 self.assertRaises(TypeError, Context, traps=(1,0))
3716
3717class CContextInputValidation(ContextInputValidation):
3718 decimal = C
3719class PyContextInputValidation(ContextInputValidation):
3720 decimal = P
3721
3722class ContextSubclassing(unittest.TestCase):
3723
3724 def test_context_subclassing(self):
3725 decimal = self.decimal
3726 Decimal = decimal.Decimal
3727 Context = decimal.Context
3728 ROUND_HALF_EVEN = decimal.ROUND_HALF_EVEN
3729 ROUND_DOWN = decimal.ROUND_DOWN
3730 Clamped = decimal.Clamped
3731 DivisionByZero = decimal.DivisionByZero
3732 Inexact = decimal.Inexact
3733 Overflow = decimal.Overflow
3734 Rounded = decimal.Rounded
3735 Subnormal = decimal.Subnormal
3736 Underflow = decimal.Underflow
3737 InvalidOperation = decimal.InvalidOperation
3738
3739 class MyContext(Context):
3740 def __init__(self, prec=None, rounding=None, Emin=None, Emax=None,
3741 capitals=None, clamp=None, flags=None,
3742 traps=None):
3743 Context.__init__(self)
3744 if prec is not None:
3745 self.prec = prec
3746 if rounding is not None:
3747 self.rounding = rounding
3748 if Emin is not None:
3749 self.Emin = Emin
3750 if Emax is not None:
3751 self.Emax = Emax
3752 if capitals is not None:
3753 self.capitals = capitals
3754 if clamp is not None:
3755 self.clamp = clamp
3756 if flags is not None:
3757 if isinstance(flags, list):
3758 flags = {v:(v in flags) for v in OrderedSignals[decimal] + flags}
3759 self.flags = flags
3760 if traps is not None:
3761 if isinstance(traps, list):
3762 traps = {v:(v in traps) for v in OrderedSignals[decimal] + traps}
3763 self.traps = traps
3764
3765 c = Context()
3766 d = MyContext()
3767 for attr in ('prec', 'rounding', 'Emin', 'Emax', 'capitals', 'clamp',
3768 'flags', 'traps'):
3769 self.assertEqual(getattr(c, attr), getattr(d, attr))
3770
3771 # prec
3772 self.assertRaises(ValueError, MyContext, **{'prec':-1})
3773 c = MyContext(prec=1)
3774 self.assertEqual(c.prec, 1)
3775 self.assertRaises(InvalidOperation, c.quantize, Decimal('9e2'), 0)
3776
3777 # rounding
3778 self.assertRaises(TypeError, MyContext, **{'rounding':'XYZ'})
3779 c = MyContext(rounding=ROUND_DOWN, prec=1)
3780 self.assertEqual(c.rounding, ROUND_DOWN)
3781 self.assertEqual(c.plus(Decimal('9.9')), 9)
3782
3783 # Emin
3784 self.assertRaises(ValueError, MyContext, **{'Emin':5})
3785 c = MyContext(Emin=-1, prec=1)
3786 self.assertEqual(c.Emin, -1)
3787 x = c.add(Decimal('1e-99'), Decimal('2.234e-2000'))
3788 self.assertEqual(x, Decimal('0.0'))
3789 for signal in (Inexact, Underflow, Subnormal, Rounded, Clamped):
3790 self.assertTrue(c.flags[signal])
3791
3792 # Emax
3793 self.assertRaises(ValueError, MyContext, **{'Emax':-1})
3794 c = MyContext(Emax=1, prec=1)
3795 self.assertEqual(c.Emax, 1)
3796 self.assertRaises(Overflow, c.add, Decimal('1e99'), Decimal('2.234e2000'))
3797 if self.decimal == C:
3798 for signal in (Inexact, Overflow, Rounded):
3799 self.assertTrue(c.flags[signal])
3800
3801 # capitals
3802 self.assertRaises(ValueError, MyContext, **{'capitals':-1})
3803 c = MyContext(capitals=0)
3804 self.assertEqual(c.capitals, 0)
3805 x = c.create_decimal('1E222')
3806 self.assertEqual(c.to_sci_string(x), '1e+222')
3807
3808 # clamp
3809 self.assertRaises(ValueError, MyContext, **{'clamp':2})
3810 c = MyContext(clamp=1, Emax=99)
3811 self.assertEqual(c.clamp, 1)
3812 x = c.plus(Decimal('1e99'))
3813 self.assertEqual(str(x), '1.000000000000000000000000000E+99')
3814
3815 # flags
3816 self.assertRaises(TypeError, MyContext, **{'flags':'XYZ'})
3817 c = MyContext(flags=[Rounded, DivisionByZero])
3818 for signal in (Rounded, DivisionByZero):
3819 self.assertTrue(c.flags[signal])
3820 c.clear_flags()
3821 for signal in OrderedSignals[decimal]:
3822 self.assertFalse(c.flags[signal])
3823
3824 # traps
3825 self.assertRaises(TypeError, MyContext, **{'traps':'XYZ'})
3826 c = MyContext(traps=[Rounded, DivisionByZero])
3827 for signal in (Rounded, DivisionByZero):
3828 self.assertTrue(c.traps[signal])
3829 c.clear_traps()
3830 for signal in OrderedSignals[decimal]:
3831 self.assertFalse(c.traps[signal])
3832
3833class CContextSubclassing(ContextSubclassing):
3834 decimal = C
3835class PyContextSubclassing(ContextSubclassing):
3836 decimal = P
3837
3838@skip_if_extra_functionality
3839class CheckAttributes(unittest.TestCase):
3840
3841 def test_module_attributes(self):
3842
3843 # Architecture dependent context limits
3844 self.assertEqual(C.MAX_PREC, P.MAX_PREC)
3845 self.assertEqual(C.MAX_EMAX, P.MAX_EMAX)
3846 self.assertEqual(C.MIN_EMIN, P.MIN_EMIN)
3847 self.assertEqual(C.MIN_ETINY, P.MIN_ETINY)
3848
3849 self.assertTrue(C.HAVE_THREADS is True or C.HAVE_THREADS is False)
3850 self.assertTrue(P.HAVE_THREADS is True or P.HAVE_THREADS is False)
3851
3852 self.assertEqual(C.__version__, P.__version__)
3853
3854 x = dir(C)
3855 y = [s for s in dir(P) if '__' in s or not s.startswith('_')]
Stefan Krahfe17b2b2012-03-25 18:59:21 +02003856 self.assertEqual(set(x) - set(y), set())
Stefan Krah1919b7e2012-03-21 18:25:23 +01003857
3858 def test_context_attributes(self):
3859
3860 x = [s for s in dir(C.Context()) if '__' in s or not s.startswith('_')]
3861 y = [s for s in dir(P.Context()) if '__' in s or not s.startswith('_')]
3862 self.assertEqual(set(x) - set(y), set())
3863
3864 def test_decimal_attributes(self):
3865
3866 x = [s for s in dir(C.Decimal(9)) if '__' in s or not s.startswith('_')]
3867 y = [s for s in dir(C.Decimal(9)) if '__' in s or not s.startswith('_')]
3868 self.assertEqual(set(x) - set(y), set())
3869
3870class Coverage(unittest.TestCase):
3871
3872 def test_adjusted(self):
3873 Decimal = self.decimal.Decimal
3874
3875 self.assertEqual(Decimal('1234e9999').adjusted(), 10002)
3876 # XXX raise?
3877 self.assertEqual(Decimal('nan').adjusted(), 0)
3878 self.assertEqual(Decimal('inf').adjusted(), 0)
3879
3880 def test_canonical(self):
3881 Decimal = self.decimal.Decimal
3882 getcontext = self.decimal.getcontext
3883
3884 x = Decimal(9).canonical()
3885 self.assertEqual(x, 9)
3886
3887 c = getcontext()
3888 x = c.canonical(Decimal(9))
3889 self.assertEqual(x, 9)
3890
3891 def test_context_repr(self):
3892 c = self.decimal.DefaultContext.copy()
3893
3894 c.prec = 425000000
3895 c.Emax = 425000000
3896 c.Emin = -425000000
3897 c.rounding = self.decimal.ROUND_HALF_DOWN
3898 c.capitals = 0
3899 c.clamp = 1
3900 for sig in OrderedSignals[self.decimal]:
3901 c.flags[sig] = False
3902 c.traps[sig] = False
3903
3904 s = c.__repr__()
3905 t = "Context(prec=425000000, rounding=ROUND_HALF_DOWN, " \
3906 "Emin=-425000000, Emax=425000000, capitals=0, clamp=1, " \
3907 "flags=[], traps=[])"
3908 self.assertEqual(s, t)
3909
3910 def test_implicit_context(self):
3911 Decimal = self.decimal.Decimal
3912 localcontext = self.decimal.localcontext
3913
3914 with localcontext() as c:
3915 c.prec = 1
3916 c.Emax = 1
3917 c.Emin = -1
3918
3919 # abs
3920 self.assertEqual(abs(Decimal("-10")), 10)
3921 # add
3922 self.assertEqual(Decimal("7") + 1, 8)
3923 # divide
3924 self.assertEqual(Decimal("10") / 5, 2)
3925 # divide_int
3926 self.assertEqual(Decimal("10") // 7, 1)
3927 # fma
3928 self.assertEqual(Decimal("1.2").fma(Decimal("0.01"), 1), 1)
3929 self.assertIs(Decimal("NaN").fma(7, 1).is_nan(), True)
3930 # three arg power
3931 self.assertEqual(pow(Decimal(10), 2, 7), 2)
3932 # exp
3933 self.assertEqual(Decimal("1.01").exp(), 3)
3934 # is_normal
3935 self.assertIs(Decimal("0.01").is_normal(), False)
3936 # is_subnormal
3937 self.assertIs(Decimal("0.01").is_subnormal(), True)
3938 # ln
3939 self.assertEqual(Decimal("20").ln(), 3)
3940 # log10
3941 self.assertEqual(Decimal("20").log10(), 1)
3942 # logb
3943 self.assertEqual(Decimal("580").logb(), 2)
3944 # logical_invert
3945 self.assertEqual(Decimal("10").logical_invert(), 1)
3946 # minus
3947 self.assertEqual(-Decimal("-10"), 10)
3948 # multiply
3949 self.assertEqual(Decimal("2") * 4, 8)
3950 # next_minus
3951 self.assertEqual(Decimal("10").next_minus(), 9)
3952 # next_plus
3953 self.assertEqual(Decimal("10").next_plus(), Decimal('2E+1'))
3954 # normalize
3955 self.assertEqual(Decimal("-10").normalize(), Decimal('-1E+1'))
3956 # number_class
3957 self.assertEqual(Decimal("10").number_class(), '+Normal')
3958 # plus
3959 self.assertEqual(+Decimal("-1"), -1)
3960 # remainder
3961 self.assertEqual(Decimal("10") % 7, 3)
3962 # subtract
3963 self.assertEqual(Decimal("10") - 7, 3)
3964 # to_integral_exact
3965 self.assertEqual(Decimal("1.12345").to_integral_exact(), 1)
3966
3967 # Boolean functions
3968 self.assertTrue(Decimal("1").is_canonical())
3969 self.assertTrue(Decimal("1").is_finite())
3970 self.assertTrue(Decimal("1").is_finite())
3971 self.assertTrue(Decimal("snan").is_snan())
3972 self.assertTrue(Decimal("-1").is_signed())
3973 self.assertTrue(Decimal("0").is_zero())
3974 self.assertTrue(Decimal("0").is_zero())
3975
3976 # Copy
3977 with localcontext() as c:
3978 c.prec = 10000
3979 x = 1228 ** 1523
3980 y = -Decimal(x)
3981
3982 z = y.copy_abs()
3983 self.assertEqual(z, x)
3984
3985 z = y.copy_negate()
3986 self.assertEqual(z, x)
3987
3988 z = y.copy_sign(Decimal(1))
3989 self.assertEqual(z, x)
3990
3991 def test_divmod(self):
3992 Decimal = self.decimal.Decimal
3993 localcontext = self.decimal.localcontext
3994 InvalidOperation = self.decimal.InvalidOperation
3995 DivisionByZero = self.decimal.DivisionByZero
3996
3997 with localcontext() as c:
3998 q, r = divmod(Decimal("10912837129"), 1001)
3999 self.assertEqual(q, Decimal('10901935'))
4000 self.assertEqual(r, Decimal('194'))
4001
4002 q, r = divmod(Decimal("NaN"), 7)
4003 self.assertTrue(q.is_nan() and r.is_nan())
4004
4005 c.traps[InvalidOperation] = False
4006 q, r = divmod(Decimal("NaN"), 7)
4007 self.assertTrue(q.is_nan() and r.is_nan())
4008
4009 c.traps[InvalidOperation] = False
4010 c.clear_flags()
4011 q, r = divmod(Decimal("inf"), Decimal("inf"))
4012 self.assertTrue(q.is_nan() and r.is_nan())
4013 self.assertTrue(c.flags[InvalidOperation])
4014
4015 c.clear_flags()
4016 q, r = divmod(Decimal("inf"), 101)
4017 self.assertTrue(q.is_infinite() and r.is_nan())
4018 self.assertTrue(c.flags[InvalidOperation])
4019
4020 c.clear_flags()
4021 q, r = divmod(Decimal(0), 0)
4022 self.assertTrue(q.is_nan() and r.is_nan())
4023 self.assertTrue(c.flags[InvalidOperation])
4024
4025 c.traps[DivisionByZero] = False
4026 c.clear_flags()
4027 q, r = divmod(Decimal(11), 0)
4028 self.assertTrue(q.is_infinite() and r.is_nan())
4029 self.assertTrue(c.flags[InvalidOperation] and
4030 c.flags[DivisionByZero])
4031
4032 def test_power(self):
4033 Decimal = self.decimal.Decimal
4034 localcontext = self.decimal.localcontext
4035 Overflow = self.decimal.Overflow
4036 Rounded = self.decimal.Rounded
4037
4038 with localcontext() as c:
4039 c.prec = 3
4040 c.clear_flags()
4041 self.assertEqual(Decimal("1.0") ** 100, Decimal('1.00'))
4042 self.assertTrue(c.flags[Rounded])
4043
4044 c.prec = 1
4045 c.Emax = 1
4046 c.Emin = -1
4047 c.clear_flags()
4048 c.traps[Overflow] = False
4049 self.assertEqual(Decimal(10000) ** Decimal("0.5"), Decimal('inf'))
4050 self.assertTrue(c.flags[Overflow])
4051
4052 def test_quantize(self):
4053 Decimal = self.decimal.Decimal
4054 localcontext = self.decimal.localcontext
4055 InvalidOperation = self.decimal.InvalidOperation
4056
4057 with localcontext() as c:
4058 c.prec = 1
4059 c.Emax = 1
4060 c.Emin = -1
4061 c.traps[InvalidOperation] = False
4062 x = Decimal(99).quantize(Decimal("1e1"))
4063 self.assertTrue(x.is_nan())
4064
4065 def test_radix(self):
4066 Decimal = self.decimal.Decimal
4067 getcontext = self.decimal.getcontext
4068
4069 c = getcontext()
4070 self.assertEqual(Decimal("1").radix(), 10)
4071 self.assertEqual(c.radix(), 10)
4072
4073 def test_rop(self):
4074 Decimal = self.decimal.Decimal
4075
4076 for attr in ('__radd__', '__rsub__', '__rmul__', '__rtruediv__',
4077 '__rdivmod__', '__rmod__', '__rfloordiv__', '__rpow__'):
4078 self.assertIs(getattr(Decimal("1"), attr)("xyz"), NotImplemented)
4079
4080 def test_round(self):
4081 # Python3 behavior: round() returns Decimal
4082 Decimal = self.decimal.Decimal
4083 getcontext = self.decimal.getcontext
4084
4085 c = getcontext()
4086 c.prec = 28
4087
4088 self.assertEqual(str(Decimal("9.99").__round__()), "10")
4089 self.assertEqual(str(Decimal("9.99e-5").__round__()), "0")
4090 self.assertEqual(str(Decimal("1.23456789").__round__(5)), "1.23457")
4091 self.assertEqual(str(Decimal("1.2345").__round__(10)), "1.2345000000")
4092 self.assertEqual(str(Decimal("1.2345").__round__(-10)), "0E+10")
4093
4094 self.assertRaises(TypeError, Decimal("1.23").__round__, "5")
4095 self.assertRaises(TypeError, Decimal("1.23").__round__, 5, 8)
4096
4097 def test_create_decimal(self):
4098 c = self.decimal.Context()
4099 self.assertRaises(ValueError, c.create_decimal, ["%"])
4100
4101 def test_int(self):
4102 Decimal = self.decimal.Decimal
4103 localcontext = self.decimal.localcontext
4104
4105 with localcontext() as c:
4106 c.prec = 9999
4107 x = Decimal(1221**1271) / 10**3923
4108 self.assertEqual(int(x), 1)
4109 self.assertEqual(x.to_integral(), 2)
4110
4111 def test_copy(self):
4112 Context = self.decimal.Context
4113
4114 c = Context()
4115 c.prec = 10000
4116 x = -(1172 ** 1712)
4117
4118 y = c.copy_abs(x)
4119 self.assertEqual(y, -x)
4120
4121 y = c.copy_negate(x)
4122 self.assertEqual(y, -x)
4123
4124 y = c.copy_sign(x, 1)
4125 self.assertEqual(y, -x)
4126
4127class CCoverage(Coverage):
4128 decimal = C
4129class PyCoverage(Coverage):
4130 decimal = P
4131
4132class PyFunctionality(unittest.TestCase):
4133 """Extra functionality in decimal.py"""
4134
4135 def test_py_quantize_watchexp(self):
4136 # watchexp functionality
4137 Decimal = P.Decimal
4138 localcontext = P.localcontext
4139
4140 with localcontext() as c:
4141 c.prec = 1
4142 c.Emax = 1
4143 c.Emin = -1
4144 x = Decimal(99999).quantize(Decimal("1e3"), watchexp=False)
4145 self.assertEqual(x, Decimal('1.00E+5'))
4146
4147 def test_py_alternate_formatting(self):
4148 # triples giving a format, a Decimal, and the expected result
4149 Decimal = P.Decimal
4150 localcontext = P.localcontext
4151
4152 test_values = [
4153 # Issue 7094: Alternate formatting (specified by #)
4154 ('.0e', '1.0', '1e+0'),
4155 ('#.0e', '1.0', '1.e+0'),
4156 ('.0f', '1.0', '1'),
4157 ('#.0f', '1.0', '1.'),
4158 ('g', '1.1', '1.1'),
4159 ('#g', '1.1', '1.1'),
4160 ('.0g', '1', '1'),
4161 ('#.0g', '1', '1.'),
4162 ('.0%', '1.0', '100%'),
4163 ('#.0%', '1.0', '100.%'),
4164 ]
4165 for fmt, d, result in test_values:
4166 self.assertEqual(format(Decimal(d), fmt), result)
4167
4168class PyWhitebox(unittest.TestCase):
4169 """White box testing for decimal.py"""
4170
4171 def test_py_exact_power(self):
4172 # Rarely exercised lines in _power_exact.
4173 Decimal = P.Decimal
4174 localcontext = P.localcontext
4175
4176 with localcontext() as c:
4177 c.prec = 8
4178 x = Decimal(2**16) ** Decimal("-0.5")
4179 self.assertEqual(x, Decimal('0.00390625'))
4180
4181 x = Decimal(2**16) ** Decimal("-0.6")
4182 self.assertEqual(x, Decimal('0.0012885819'))
4183
4184 x = Decimal("256e7") ** Decimal("-0.5")
4185
4186 x = Decimal(152587890625) ** Decimal('-0.0625')
4187 self.assertEqual(x, Decimal("0.2"))
4188
4189 x = Decimal("152587890625e7") ** Decimal('-0.0625')
4190
4191 x = Decimal(5**2659) ** Decimal('-0.0625')
4192
4193 c.prec = 1
4194 x = Decimal("152587890625") ** Decimal('-0.5')
4195 c.prec = 201
4196 x = Decimal(2**578) ** Decimal("-0.5")
4197
4198 def test_py_immutability_operations(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004199 # Do operations and check that it didn't change change internal objects.
Stefan Krah1919b7e2012-03-21 18:25:23 +01004200 Decimal = P.Decimal
4201 DefaultContext = P.DefaultContext
4202 setcontext = P.setcontext
4203
4204 c = DefaultContext.copy()
4205 c.traps = dict((s, 0) for s in OrderedSignals[P])
4206 setcontext(c)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004207
4208 d1 = Decimal('-25e55')
4209 b1 = Decimal('-25e55')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004210 d2 = Decimal('33e+33')
4211 b2 = Decimal('33e+33')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004212
4213 def checkSameDec(operation, useOther=False):
4214 if useOther:
4215 eval("d1." + operation + "(d2)")
4216 self.assertEqual(d1._sign, b1._sign)
4217 self.assertEqual(d1._int, b1._int)
4218 self.assertEqual(d1._exp, b1._exp)
4219 self.assertEqual(d2._sign, b2._sign)
4220 self.assertEqual(d2._int, b2._int)
4221 self.assertEqual(d2._exp, b2._exp)
4222 else:
4223 eval("d1." + operation + "()")
4224 self.assertEqual(d1._sign, b1._sign)
4225 self.assertEqual(d1._int, b1._int)
4226 self.assertEqual(d1._exp, b1._exp)
4227 return
4228
4229 Decimal(d1)
4230 self.assertEqual(d1._sign, b1._sign)
4231 self.assertEqual(d1._int, b1._int)
4232 self.assertEqual(d1._exp, b1._exp)
4233
4234 checkSameDec("__abs__")
4235 checkSameDec("__add__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004236 checkSameDec("__divmod__", True)
Christian Heimes77c02eb2008-02-09 02:18:51 +00004237 checkSameDec("__eq__", True)
4238 checkSameDec("__ne__", True)
4239 checkSameDec("__le__", True)
4240 checkSameDec("__lt__", True)
4241 checkSameDec("__ge__", True)
4242 checkSameDec("__gt__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004243 checkSameDec("__float__")
4244 checkSameDec("__floordiv__", True)
4245 checkSameDec("__hash__")
4246 checkSameDec("__int__")
Christian Heimes969fe572008-01-25 11:23:10 +00004247 checkSameDec("__trunc__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004248 checkSameDec("__mod__", True)
4249 checkSameDec("__mul__", True)
4250 checkSameDec("__neg__")
Jack Diederich4dafcc42006-11-28 19:15:13 +00004251 checkSameDec("__bool__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004252 checkSameDec("__pos__")
4253 checkSameDec("__pow__", True)
4254 checkSameDec("__radd__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004255 checkSameDec("__rdivmod__", True)
4256 checkSameDec("__repr__")
4257 checkSameDec("__rfloordiv__", True)
4258 checkSameDec("__rmod__", True)
4259 checkSameDec("__rmul__", True)
4260 checkSameDec("__rpow__", True)
4261 checkSameDec("__rsub__", True)
4262 checkSameDec("__str__")
4263 checkSameDec("__sub__", True)
4264 checkSameDec("__truediv__", True)
4265 checkSameDec("adjusted")
4266 checkSameDec("as_tuple")
4267 checkSameDec("compare", True)
4268 checkSameDec("max", True)
4269 checkSameDec("min", True)
4270 checkSameDec("normalize")
4271 checkSameDec("quantize", True)
4272 checkSameDec("remainder_near", True)
4273 checkSameDec("same_quantum", True)
4274 checkSameDec("sqrt")
4275 checkSameDec("to_eng_string")
4276 checkSameDec("to_integral")
4277
Stefan Krah1919b7e2012-03-21 18:25:23 +01004278 def test_py_decimal_id(self):
4279 Decimal = P.Decimal
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004280
Stefan Krah1919b7e2012-03-21 18:25:23 +01004281 d = Decimal(45)
4282 e = Decimal(d)
4283 self.assertEqual(str(e), '45')
4284 self.assertNotEqual(id(d), id(e))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004285
Stefan Krah1919b7e2012-03-21 18:25:23 +01004286 def test_py_rescale(self):
4287 # Coverage
4288 Decimal = P.Decimal
4289 ROUND_UP = P.ROUND_UP
4290 localcontext = P.localcontext
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004291
Stefan Krah1919b7e2012-03-21 18:25:23 +01004292 with localcontext() as c:
4293 x = Decimal("NaN")._rescale(3, ROUND_UP)
4294 self.assertTrue(x.is_nan())
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004295
Stefan Krah1919b7e2012-03-21 18:25:23 +01004296 def test_py__round(self):
4297 # Coverage
4298 Decimal = P.Decimal
4299 ROUND_UP = P.ROUND_UP
Christian Heimes0348fb62008-03-26 12:55:56 +00004300
Stefan Krah1919b7e2012-03-21 18:25:23 +01004301 self.assertRaises(ValueError, Decimal("3.1234")._round, 0, ROUND_UP)
Mark Dickinsona2d1fe02009-10-29 12:23:02 +00004302
Stefan Krah1919b7e2012-03-21 18:25:23 +01004303class CFunctionality(unittest.TestCase):
4304 """Extra functionality in _decimal"""
Mark Dickinsona2d1fe02009-10-29 12:23:02 +00004305
Stefan Krah1919b7e2012-03-21 18:25:23 +01004306 @requires_extra_functionality
4307 def test_c_ieee_context(self):
4308 # issue 8786: Add support for IEEE 754 contexts to decimal module.
4309 IEEEContext = C.IEEEContext
4310 DECIMAL32 = C.DECIMAL32
4311 DECIMAL64 = C.DECIMAL64
4312 DECIMAL128 = C.DECIMAL128
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004313
Stefan Krah1919b7e2012-03-21 18:25:23 +01004314 def assert_rest(self, context):
4315 self.assertEqual(context.clamp, 1)
4316 assert_signals(self, context, 'traps', [])
4317 assert_signals(self, context, 'flags', [])
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004318
Stefan Krah1919b7e2012-03-21 18:25:23 +01004319 c = IEEEContext(DECIMAL32)
4320 self.assertEqual(c.prec, 7)
4321 self.assertEqual(c.Emax, 96)
4322 self.assertEqual(c.Emin, -95)
4323 assert_rest(self, c)
Raymond Hettinger82417ca2009-02-03 03:54:28 +00004324
Stefan Krah1919b7e2012-03-21 18:25:23 +01004325 c = IEEEContext(DECIMAL64)
4326 self.assertEqual(c.prec, 16)
4327 self.assertEqual(c.Emax, 384)
4328 self.assertEqual(c.Emin, -383)
4329 assert_rest(self, c)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004330
Stefan Krah1919b7e2012-03-21 18:25:23 +01004331 c = IEEEContext(DECIMAL128)
4332 self.assertEqual(c.prec, 34)
4333 self.assertEqual(c.Emax, 6144)
4334 self.assertEqual(c.Emin, -6143)
4335 assert_rest(self, c)
Raymond Hettinger5548be22004-07-05 18:49:38 +00004336
Stefan Krah1919b7e2012-03-21 18:25:23 +01004337 # Invalid values
4338 self.assertRaises(OverflowError, IEEEContext, 2**63)
4339 self.assertRaises(ValueError, IEEEContext, -1)
4340 self.assertRaises(ValueError, IEEEContext, 1024)
Mark Dickinson825fce32009-09-07 18:08:12 +00004341
Stefan Krah1919b7e2012-03-21 18:25:23 +01004342 @requires_extra_functionality
4343 def test_c_context(self):
4344 Context = C.Context
Christian Heimes969fe572008-01-25 11:23:10 +00004345
Stefan Krah1919b7e2012-03-21 18:25:23 +01004346 c = Context(flags=C.DecClamped, traps=C.DecRounded)
4347 self.assertEqual(c._flags, C.DecClamped)
4348 self.assertEqual(c._traps, C.DecRounded)
Raymond Hettinger771ed762009-01-03 19:20:32 +00004349
Stefan Krah1919b7e2012-03-21 18:25:23 +01004350 @requires_extra_functionality
4351 def test_constants(self):
4352 # Condition flags
4353 cond = (
4354 C.DecClamped, C.DecConversionSyntax, C.DecDivisionByZero,
4355 C.DecDivisionImpossible, C.DecDivisionUndefined,
4356 C.DecFpuError, C.DecInexact, C.DecInvalidContext,
4357 C.DecInvalidOperation, C.DecMallocError,
4358 C.DecFloatOperation, C.DecOverflow, C.DecRounded,
4359 C.DecSubnormal, C.DecUnderflow
Raymond Hettinger771ed762009-01-03 19:20:32 +00004360 )
Stefan Krah1919b7e2012-03-21 18:25:23 +01004361
4362 # IEEEContext
4363 self.assertEqual(C.DECIMAL32, 32)
4364 self.assertEqual(C.DECIMAL64, 64)
4365 self.assertEqual(C.DECIMAL128, 128)
4366 self.assertEqual(C.IEEE_CONTEXT_MAX_BITS, 512)
4367
4368 # Rounding modes
4369 for i, v in enumerate(RoundingModes[C]):
4370 self.assertEqual(v, i)
4371 self.assertEqual(C.ROUND_TRUNC, 8)
4372
4373 # Conditions
4374 for i, v in enumerate(cond):
4375 self.assertEqual(v, 1<<i)
4376
4377 self.assertEqual(C.DecIEEEInvalidOperation,
4378 C.DecConversionSyntax|
4379 C.DecDivisionImpossible|
4380 C.DecDivisionUndefined|
4381 C.DecFpuError|
4382 C.DecInvalidContext|
4383 C.DecInvalidOperation|
4384 C.DecMallocError)
4385
4386 self.assertEqual(C.DecErrors,
4387 C.DecIEEEInvalidOperation|
4388 C.DecDivisionByZero)
4389
4390 self.assertEqual(C.DecTraps,
4391 C.DecErrors|C.DecOverflow|C.DecUnderflow)
4392
4393class CWhitebox(unittest.TestCase):
4394 """Whitebox testing for _decimal"""
4395
4396 def test_bignum(self):
4397 # Not exactly whitebox, but too slow with pydecimal.
4398
4399 Decimal = C.Decimal
4400 localcontext = C.localcontext
4401
4402 b1 = 10**35
4403 b2 = 10**36
4404 with localcontext() as c:
4405 c.prec = 1000000
4406 for i in range(5):
4407 a = random.randrange(b1, b2)
4408 b = random.randrange(1000, 1200)
4409 x = a ** b
4410 y = Decimal(a) ** Decimal(b)
4411 self.assertEqual(x, y)
4412
4413 def test_invalid_construction(self):
4414 self.assertRaises(TypeError, C.Decimal, 9, "xyz")
4415
4416 def test_c_input_restriction(self):
4417 # Too large for _decimal to be converted exactly
4418 Decimal = C.Decimal
4419 InvalidOperation = C.InvalidOperation
4420 Context = C.Context
4421 localcontext = C.localcontext
4422
4423 with localcontext(Context()):
4424 self.assertRaises(InvalidOperation, Decimal,
4425 "1e9999999999999999999")
4426
4427 def test_c_context_repr(self):
4428 # This test is _decimal-only because flags are not printed
4429 # in the same order.
4430 DefaultContext = C.DefaultContext
4431 FloatOperation = C.FloatOperation
4432 ROUND_HALF_DOWN = C.ROUND_HALF_DOWN
4433
4434 c = DefaultContext.copy()
4435
4436 c.prec = 425000000
4437 c.Emax = 425000000
4438 c.Emin = -425000000
4439 c.rounding = ROUND_HALF_DOWN
4440 c.capitals = 0
4441 c.clamp = 1
4442 for sig in OrderedSignals[C]:
4443 c.flags[sig] = True
4444 c.traps[sig] = True
4445 c.flags[FloatOperation] = True
4446 c.traps[FloatOperation] = True
4447
4448 s = c.__repr__()
4449 t = "Context(prec=425000000, rounding=ROUND_HALF_DOWN, " \
4450 "Emin=-425000000, Emax=425000000, capitals=0, clamp=1, " \
4451 "flags=[Clamped, InvalidOperation, DivisionByZero, Inexact, " \
4452 "FloatOperation, Overflow, Rounded, Subnormal, Underflow], " \
4453 "traps=[Clamped, InvalidOperation, DivisionByZero, Inexact, " \
4454 "FloatOperation, Overflow, Rounded, Subnormal, Underflow])"
4455 self.assertEqual(s, t)
4456
4457 def test_c_context_errors(self):
4458 Context = C.Context
4459 InvalidOperation = C.InvalidOperation
4460 Overflow = C.Overflow
4461 FloatOperation = C.FloatOperation
4462 localcontext = C.localcontext
4463 getcontext = C.getcontext
4464 setcontext = C.setcontext
4465 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
4466
4467 c = Context()
4468
4469 # SignalDict: input validation
4470 self.assertRaises(KeyError, c.flags.__setitem__, 801, 0)
4471 self.assertRaises(KeyError, c.traps.__setitem__, 801, 0)
4472 self.assertRaises(ValueError, c.flags.__delitem__, Overflow)
4473 self.assertRaises(ValueError, c.traps.__delitem__, InvalidOperation)
4474 self.assertRaises(TypeError, setattr, c, 'flags', ['x'])
4475 self.assertRaises(TypeError, setattr, c,'traps', ['y'])
4476 self.assertRaises(KeyError, setattr, c, 'flags', {0:1})
4477 self.assertRaises(KeyError, setattr, c, 'traps', {0:1})
4478
4479 # Test assignment from a signal dict with the correct length but
4480 # one invalid key.
4481 d = c.flags.copy()
4482 del d[FloatOperation]
4483 d["XYZ"] = 91283719
4484 self.assertRaises(KeyError, setattr, c, 'flags', d)
4485 self.assertRaises(KeyError, setattr, c, 'traps', d)
4486
4487 # Input corner cases
4488 int_max = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
4489 gt_max_emax = 10**18 if HAVE_CONFIG_64 else 10**9
4490
4491 # prec, Emax, Emin
4492 for attr in ['prec', 'Emax']:
4493 self.assertRaises(ValueError, setattr, c, attr, gt_max_emax)
4494 self.assertRaises(ValueError, setattr, c, 'Emin', -gt_max_emax)
4495
4496 # prec, Emax, Emin in context constructor
4497 self.assertRaises(ValueError, Context, prec=gt_max_emax)
4498 self.assertRaises(ValueError, Context, Emax=gt_max_emax)
4499 self.assertRaises(ValueError, Context, Emin=-gt_max_emax)
4500
4501 # Overflow in conversion
4502 self.assertRaises(OverflowError, Context, prec=int_max+1)
4503 self.assertRaises(OverflowError, Context, Emax=int_max+1)
4504 self.assertRaises(OverflowError, Context, Emin=-int_max-2)
4505 self.assertRaises(OverflowError, Context, rounding=int_max+1)
4506 self.assertRaises(OverflowError, Context, clamp=int_max+1)
4507 self.assertRaises(OverflowError, Context, capitals=int_max+1)
4508
4509 # OverflowError, general ValueError
4510 for attr in ('prec', 'Emin', 'Emax', 'capitals', 'clamp'):
4511 self.assertRaises(OverflowError, setattr, c, attr, int_max+1)
4512 self.assertRaises(OverflowError, setattr, c, attr, -int_max-2)
4513 if sys.platform != 'win32':
4514 self.assertRaises(ValueError, setattr, c, attr, int_max)
4515 self.assertRaises(ValueError, setattr, c, attr, -int_max-1)
4516
4517 # OverflowError, general TypeError
4518 for attr in ('rounding',):
4519 self.assertRaises(OverflowError, setattr, c, attr, int_max+1)
4520 self.assertRaises(OverflowError, setattr, c, attr, -int_max-2)
4521 if sys.platform != 'win32':
4522 self.assertRaises(TypeError, setattr, c, attr, int_max)
4523 self.assertRaises(TypeError, setattr, c, attr, -int_max-1)
4524
4525 # OverflowError: _unsafe_setprec, _unsafe_setemin, _unsafe_setemax
4526 if C.MAX_PREC == 425000000:
4527 self.assertRaises(OverflowError, getattr(c, '_unsafe_setprec'),
4528 int_max+1)
4529 self.assertRaises(OverflowError, getattr(c, '_unsafe_setemax'),
4530 int_max+1)
4531 self.assertRaises(OverflowError, getattr(c, '_unsafe_setemin'),
4532 -int_max-2)
4533
4534 # ValueError: _unsafe_setprec, _unsafe_setemin, _unsafe_setemax
4535 if C.MAX_PREC == 425000000:
4536 self.assertRaises(ValueError, getattr(c, '_unsafe_setprec'), 0)
4537 self.assertRaises(ValueError, getattr(c, '_unsafe_setprec'),
4538 1070000001)
4539 self.assertRaises(ValueError, getattr(c, '_unsafe_setemax'), -1)
4540 self.assertRaises(ValueError, getattr(c, '_unsafe_setemax'),
4541 1070000001)
4542 self.assertRaises(ValueError, getattr(c, '_unsafe_setemin'),
4543 -1070000001)
4544 self.assertRaises(ValueError, getattr(c, '_unsafe_setemin'), 1)
4545
4546 # capitals, clamp
4547 for attr in ['capitals', 'clamp']:
4548 self.assertRaises(ValueError, setattr, c, attr, -1)
4549 self.assertRaises(ValueError, setattr, c, attr, 2)
4550 self.assertRaises(TypeError, setattr, c, attr, [1,2,3])
4551 if HAVE_CONFIG_64:
4552 self.assertRaises(ValueError, setattr, c, attr, 2**32)
4553 self.assertRaises(ValueError, setattr, c, attr, 2**32+1)
4554
4555 # Invalid local context
4556 self.assertRaises(TypeError, exec, 'with localcontext("xyz"): pass',
4557 locals())
4558
4559 # setcontext
4560 saved_context = getcontext()
4561 self.assertRaises(TypeError, setcontext, "xyz")
4562 setcontext(saved_context)
4563
4564 @requires_extra_functionality
4565 def test_c_context_errors_extra(self):
4566 Context = C.Context
4567 InvalidOperation = C.InvalidOperation
4568 Overflow = C.Overflow
4569 localcontext = C.localcontext
4570 getcontext = C.getcontext
4571 setcontext = C.setcontext
4572 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
4573
4574 c = Context()
4575
4576 # Input corner cases
4577 int_max = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
4578
4579 # OverflowError, general ValueError
4580 self.assertRaises(OverflowError, setattr, c, '_allcr', int_max+1)
4581 self.assertRaises(OverflowError, setattr, c, '_allcr', -int_max-2)
4582 if sys.platform != 'win32':
4583 self.assertRaises(ValueError, setattr, c, '_allcr', int_max)
4584 self.assertRaises(ValueError, setattr, c, '_allcr', -int_max-1)
4585
4586 # OverflowError, general TypeError
4587 for attr in ('_flags', '_traps'):
4588 self.assertRaises(OverflowError, setattr, c, attr, int_max+1)
4589 self.assertRaises(OverflowError, setattr, c, attr, -int_max-2)
4590 if sys.platform != 'win32':
4591 self.assertRaises(TypeError, setattr, c, attr, int_max)
4592 self.assertRaises(TypeError, setattr, c, attr, -int_max-1)
4593
4594 # _allcr
4595 self.assertRaises(ValueError, setattr, c, '_allcr', -1)
4596 self.assertRaises(ValueError, setattr, c, '_allcr', 2)
4597 self.assertRaises(TypeError, setattr, c, '_allcr', [1,2,3])
4598 if HAVE_CONFIG_64:
4599 self.assertRaises(ValueError, setattr, c, '_allcr', 2**32)
4600 self.assertRaises(ValueError, setattr, c, '_allcr', 2**32+1)
4601
4602 # _flags, _traps
4603 for attr in ['_flags', '_traps']:
4604 self.assertRaises(TypeError, setattr, c, attr, 999999)
4605 self.assertRaises(TypeError, setattr, c, attr, 'x')
4606
4607 def test_c_valid_context(self):
4608 # These tests are for code coverage in _decimal.
4609 DefaultContext = C.DefaultContext
4610 ROUND_HALF_UP = C.ROUND_HALF_UP
4611 Clamped = C.Clamped
4612 Underflow = C.Underflow
4613 Inexact = C.Inexact
4614 Rounded = C.Rounded
4615 Subnormal = C.Subnormal
4616
4617 c = DefaultContext.copy()
4618
4619 # Exercise all getters and setters
4620 c.prec = 34
4621 c.rounding = ROUND_HALF_UP
4622 c.Emax = 3000
4623 c.Emin = -3000
4624 c.capitals = 1
4625 c.clamp = 0
4626
4627 self.assertEqual(c.prec, 34)
4628 self.assertEqual(c.rounding, ROUND_HALF_UP)
4629 self.assertEqual(c.Emin, -3000)
4630 self.assertEqual(c.Emax, 3000)
4631 self.assertEqual(c.capitals, 1)
4632 self.assertEqual(c.clamp, 0)
4633
4634 self.assertEqual(c.Etiny(), -3033)
4635 self.assertEqual(c.Etop(), 2967)
4636
4637 # Exercise all unsafe setters
4638 if C.MAX_PREC == 425000000:
4639 c._unsafe_setprec(999999999)
4640 c._unsafe_setemax(999999999)
4641 c._unsafe_setemin(-999999999)
4642 self.assertEqual(c.prec, 999999999)
4643 self.assertEqual(c.Emax, 999999999)
4644 self.assertEqual(c.Emin, -999999999)
4645
4646 @requires_extra_functionality
4647 def test_c_valid_context_extra(self):
4648 DefaultContext = C.DefaultContext
4649
4650 c = DefaultContext.copy()
4651 self.assertEqual(c._allcr, 1)
4652 c._allcr = 0
4653 self.assertEqual(c._allcr, 0)
4654
4655 def test_c_round(self):
4656 # Restricted input.
4657 Decimal = C.Decimal
4658 InvalidOperation = C.InvalidOperation
4659 localcontext = C.localcontext
4660 MAX_EMAX = C.MAX_EMAX
4661 MIN_ETINY = C.MIN_ETINY
4662 int_max = 2**63-1 if C.MAX_PREC > 425000000 else 2**31-1
4663
4664 with localcontext() as c:
4665 c.traps[InvalidOperation] = True
4666 self.assertRaises(InvalidOperation, Decimal("1.23").__round__,
4667 -int_max-1)
4668 self.assertRaises(InvalidOperation, Decimal("1.23").__round__,
4669 int_max)
4670 self.assertRaises(InvalidOperation, Decimal("1").__round__,
4671 int(MAX_EMAX+1))
4672 self.assertRaises(C.InvalidOperation, Decimal("1").__round__,
4673 -int(MIN_ETINY-1))
4674 self.assertRaises(OverflowError, Decimal("1.23").__round__,
4675 -int_max-2)
4676 self.assertRaises(OverflowError, Decimal("1.23").__round__,
4677 int_max+1)
4678
4679 def test_c_format(self):
4680 # Restricted input
4681 Decimal = C.Decimal
4682 InvalidOperation = C.InvalidOperation
4683 Rounded = C.Rounded
4684 localcontext = C.localcontext
4685 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
4686
4687 self.assertRaises(TypeError, Decimal(1).__format__, "=10.10", [], 9)
4688 self.assertRaises(TypeError, Decimal(1).__format__, "=10.10", 9)
4689 self.assertRaises(TypeError, Decimal(1).__format__, [])
4690
4691 with localcontext() as c:
4692 c.traps[InvalidOperation] = True
4693 c.traps[Rounded] = True
4694 self.assertRaises(ValueError, Decimal(1).__format__, "<>=10.10")
4695 maxsize = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
4696 self.assertRaises(InvalidOperation, Decimal("1.23456789").__format__,
4697 "=%d.1" % maxsize)
4698
4699 def test_c_integral(self):
4700 Decimal = C.Decimal
4701 Inexact = C.Inexact
4702 ROUND_UP = C.ROUND_UP
4703 localcontext = C.localcontext
4704
4705 x = Decimal(10)
4706 self.assertEqual(x.to_integral(), 10)
4707 self.assertRaises(TypeError, x.to_integral, '10')
4708 self.assertRaises(TypeError, x.to_integral, 10, 'x')
4709 self.assertRaises(TypeError, x.to_integral, 10)
4710
4711 self.assertEqual(x.to_integral_value(), 10)
4712 self.assertRaises(TypeError, x.to_integral_value, '10')
4713 self.assertRaises(TypeError, x.to_integral_value, 10, 'x')
4714 self.assertRaises(TypeError, x.to_integral_value, 10)
4715
4716 self.assertEqual(x.to_integral_exact(), 10)
4717 self.assertRaises(TypeError, x.to_integral_exact, '10')
4718 self.assertRaises(TypeError, x.to_integral_exact, 10, 'x')
4719 self.assertRaises(TypeError, x.to_integral_exact, 10)
4720
4721 with localcontext() as c:
4722 x = Decimal("99999999999999999999999999.9").to_integral_value(ROUND_UP)
4723 self.assertEqual(x, Decimal('100000000000000000000000000'))
4724
4725 x = Decimal("99999999999999999999999999.9").to_integral_exact(ROUND_UP)
4726 self.assertEqual(x, Decimal('100000000000000000000000000'))
4727
4728 c.traps[Inexact] = True
4729 self.assertRaises(Inexact, Decimal("999.9").to_integral_exact, ROUND_UP)
4730
4731 def test_c_funcs(self):
4732 # Invalid arguments
4733 Decimal = C.Decimal
4734 InvalidOperation = C.InvalidOperation
4735 DivisionByZero = C.DivisionByZero
4736 ROUND_UP = C.ROUND_UP
4737 getcontext = C.getcontext
4738 localcontext = C.localcontext
4739
4740 self.assertEqual(Decimal('9.99e10').to_eng_string(), '99.9E+9')
4741
4742 self.assertRaises(TypeError, pow, Decimal(1), 2, "3")
4743 self.assertRaises(TypeError, Decimal(9).number_class, "x", "y")
4744 self.assertRaises(TypeError, Decimal(9).same_quantum, 3, "x", "y")
4745
Raymond Hettinger771ed762009-01-03 19:20:32 +00004746 self.assertRaises(
Stefan Krah1919b7e2012-03-21 18:25:23 +01004747 TypeError,
4748 Decimal("1.23456789").quantize, Decimal('1e-100000'), []
Raymond Hettinger771ed762009-01-03 19:20:32 +00004749 )
Stefan Krah1919b7e2012-03-21 18:25:23 +01004750 self.assertRaises(
4751 TypeError,
4752 Decimal("1.23456789").quantize, Decimal('1e-100000'), getcontext()
4753 )
4754 self.assertRaises(
4755 TypeError,
4756 Decimal("1.23456789").quantize, Decimal('1e-100000'), 10
4757 )
4758 self.assertRaises(
4759 TypeError,
4760 Decimal("1.23456789").quantize, Decimal('1e-100000'), ROUND_UP, 1000
4761 )
Raymond Hettinger771ed762009-01-03 19:20:32 +00004762
Stefan Krah1919b7e2012-03-21 18:25:23 +01004763 with localcontext() as c:
4764 c.clear_traps()
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00004765
Stefan Krah1919b7e2012-03-21 18:25:23 +01004766 # Invalid arguments
4767 self.assertRaises(TypeError, c.copy_sign, Decimal(1), "x", "y")
4768 self.assertRaises(TypeError, c.canonical, 200)
4769 self.assertRaises(TypeError, c.is_canonical, 200)
4770 self.assertRaises(TypeError, c.divmod, 9, 8, "x", "y")
4771 self.assertRaises(TypeError, c.same_quantum, 9, 3, "x", "y")
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00004772
Stefan Krah1919b7e2012-03-21 18:25:23 +01004773 self.assertEqual(str(c.canonical(Decimal(200))), '200')
4774 self.assertEqual(c.radix(), 10)
Raymond Hettinger0aeac102004-07-05 22:53:03 +00004775
Stefan Krah1919b7e2012-03-21 18:25:23 +01004776 c.traps[DivisionByZero] = True
4777 self.assertRaises(DivisionByZero, Decimal(9).__divmod__, 0)
4778 self.assertRaises(DivisionByZero, c.divmod, 9, 0)
4779 self.assertTrue(c.flags[InvalidOperation])
Raymond Hettinger955d2b22004-08-08 20:17:45 +00004780
Stefan Krah1919b7e2012-03-21 18:25:23 +01004781 c.clear_flags()
4782 c.traps[InvalidOperation] = True
4783 self.assertRaises(InvalidOperation, Decimal(9).__divmod__, 0)
4784 self.assertRaises(InvalidOperation, c.divmod, 9, 0)
4785 self.assertTrue(c.flags[DivisionByZero])
Mark Dickinsonb1d8e322010-05-22 18:35:36 +00004786
Stefan Krah1919b7e2012-03-21 18:25:23 +01004787 c.traps[InvalidOperation] = True
4788 c.prec = 2
4789 self.assertRaises(InvalidOperation, pow, Decimal(1000), 1, 501)
Mark Dickinson84230a12010-02-18 14:49:50 +00004790
Stefan Krah1919b7e2012-03-21 18:25:23 +01004791 @requires_extra_functionality
4792 def test_c_context_templates(self):
4793 self.assertEqual(
4794 C.BasicContext._traps,
4795 C.DecIEEEInvalidOperation|C.DecDivisionByZero|C.DecOverflow|
4796 C.DecUnderflow|C.DecClamped
4797 )
4798 self.assertEqual(
4799 C.DefaultContext._traps,
4800 C.DecIEEEInvalidOperation|C.DecDivisionByZero|C.DecOverflow
4801 )
Mark Dickinson84230a12010-02-18 14:49:50 +00004802
Stefan Krah1919b7e2012-03-21 18:25:23 +01004803 @requires_extra_functionality
4804 def test_c_signal_dict(self):
Mark Dickinson84230a12010-02-18 14:49:50 +00004805
Stefan Krah1919b7e2012-03-21 18:25:23 +01004806 # SignalDict coverage
4807 Context = C.Context
4808 DefaultContext = C.DefaultContext
Mark Dickinson84230a12010-02-18 14:49:50 +00004809
Stefan Krah1919b7e2012-03-21 18:25:23 +01004810 InvalidOperation = C.InvalidOperation
4811 DivisionByZero = C.DivisionByZero
4812 Overflow = C.Overflow
4813 Subnormal = C.Subnormal
4814 Underflow = C.Underflow
4815 Rounded = C.Rounded
4816 Inexact = C.Inexact
4817 Clamped = C.Clamped
Mark Dickinson84230a12010-02-18 14:49:50 +00004818
Stefan Krah1919b7e2012-03-21 18:25:23 +01004819 DecClamped = C.DecClamped
4820 DecInvalidOperation = C.DecInvalidOperation
4821 DecIEEEInvalidOperation = C.DecIEEEInvalidOperation
Mark Dickinson84230a12010-02-18 14:49:50 +00004822
Stefan Krah1919b7e2012-03-21 18:25:23 +01004823 def assertIsExclusivelySet(signal, signal_dict):
4824 for sig in signal_dict:
4825 if sig == signal:
4826 self.assertTrue(signal_dict[sig])
4827 else:
4828 self.assertFalse(signal_dict[sig])
Mark Dickinson84230a12010-02-18 14:49:50 +00004829
Stefan Krah1919b7e2012-03-21 18:25:23 +01004830 c = DefaultContext.copy()
Mark Dickinson84230a12010-02-18 14:49:50 +00004831
Stefan Krah1919b7e2012-03-21 18:25:23 +01004832 # Signal dict methods
4833 self.assertTrue(Overflow in c.traps)
4834 c.clear_traps()
4835 for k in c.traps.keys():
4836 c.traps[k] = True
4837 for v in c.traps.values():
4838 self.assertTrue(v)
4839 c.clear_traps()
4840 for k, v in c.traps.items():
4841 self.assertFalse(v)
Mark Dickinson84230a12010-02-18 14:49:50 +00004842
Stefan Krah1919b7e2012-03-21 18:25:23 +01004843 self.assertFalse(c.flags.get(Overflow))
4844 self.assertIs(c.flags.get("x"), None)
4845 self.assertEqual(c.flags.get("x", "y"), "y")
4846 self.assertRaises(TypeError, c.flags.get, "x", "y", "z")
Mark Dickinson84230a12010-02-18 14:49:50 +00004847
Stefan Krah1919b7e2012-03-21 18:25:23 +01004848 self.assertEqual(len(c.flags), len(c.traps))
4849 s = sys.getsizeof(c.flags)
4850 s = sys.getsizeof(c.traps)
4851 s = c.flags.__repr__()
Mark Dickinson84230a12010-02-18 14:49:50 +00004852
Stefan Krah1919b7e2012-03-21 18:25:23 +01004853 # Set flags/traps.
4854 c.clear_flags()
4855 c._flags = DecClamped
4856 self.assertTrue(c.flags[Clamped])
Mark Dickinson84230a12010-02-18 14:49:50 +00004857
Stefan Krah1919b7e2012-03-21 18:25:23 +01004858 c.clear_traps()
4859 c._traps = DecInvalidOperation
4860 self.assertTrue(c.traps[InvalidOperation])
Mark Dickinson84230a12010-02-18 14:49:50 +00004861
Stefan Krah1919b7e2012-03-21 18:25:23 +01004862 # Set flags/traps from dictionary.
4863 c.clear_flags()
4864 d = c.flags.copy()
4865 d[DivisionByZero] = True
4866 c.flags = d
4867 assertIsExclusivelySet(DivisionByZero, c.flags)
Mark Dickinson84230a12010-02-18 14:49:50 +00004868
Stefan Krah1919b7e2012-03-21 18:25:23 +01004869 c.clear_traps()
4870 d = c.traps.copy()
4871 d[Underflow] = True
4872 c.traps = d
4873 assertIsExclusivelySet(Underflow, c.traps)
Mark Dickinson84230a12010-02-18 14:49:50 +00004874
Stefan Krah1919b7e2012-03-21 18:25:23 +01004875 # Random constructors
4876 IntSignals = {
4877 Clamped: C.DecClamped,
4878 Rounded: C.DecRounded,
4879 Inexact: C.DecInexact,
4880 Subnormal: C.DecSubnormal,
4881 Underflow: C.DecUnderflow,
4882 Overflow: C.DecOverflow,
4883 DivisionByZero: C.DecDivisionByZero,
4884 InvalidOperation: C.DecIEEEInvalidOperation
4885 }
4886 IntCond = [
4887 C.DecDivisionImpossible, C.DecDivisionUndefined, C.DecFpuError,
4888 C.DecInvalidContext, C.DecInvalidOperation, C.DecMallocError,
4889 C.DecConversionSyntax,
4890 ]
Mark Dickinsonb455e582011-05-22 12:53:18 +01004891
Stefan Krah1919b7e2012-03-21 18:25:23 +01004892 lim = len(OrderedSignals[C])
4893 for r in range(lim):
4894 for t in range(lim):
4895 for round in RoundingModes[C]:
4896 flags = random.sample(OrderedSignals[C], r)
4897 traps = random.sample(OrderedSignals[C], t)
4898 prec = random.randrange(1, 10000)
4899 emin = random.randrange(-10000, 0)
4900 emax = random.randrange(0, 10000)
4901 clamp = random.randrange(0, 2)
4902 caps = random.randrange(0, 2)
4903 cr = random.randrange(0, 2)
4904 c = Context(prec=prec, rounding=round, Emin=emin, Emax=emax,
4905 capitals=caps, clamp=clamp, flags=list(flags),
4906 traps=list(traps))
Mark Dickinson84230a12010-02-18 14:49:50 +00004907
Stefan Krah1919b7e2012-03-21 18:25:23 +01004908 self.assertEqual(c.prec, prec)
4909 self.assertEqual(c.rounding, round)
4910 self.assertEqual(c.Emin, emin)
4911 self.assertEqual(c.Emax, emax)
4912 self.assertEqual(c.capitals, caps)
4913 self.assertEqual(c.clamp, clamp)
Mark Dickinson84230a12010-02-18 14:49:50 +00004914
Stefan Krah1919b7e2012-03-21 18:25:23 +01004915 f = 0
4916 for x in flags:
4917 f |= IntSignals[x]
4918 self.assertEqual(c._flags, f)
Mark Dickinson84230a12010-02-18 14:49:50 +00004919
Stefan Krah1919b7e2012-03-21 18:25:23 +01004920 f = 0
4921 for x in traps:
4922 f |= IntSignals[x]
4923 self.assertEqual(c._traps, f)
Mark Dickinson84230a12010-02-18 14:49:50 +00004924
Stefan Krah1919b7e2012-03-21 18:25:23 +01004925 for cond in IntCond:
4926 c._flags = cond
4927 self.assertTrue(c._flags&DecIEEEInvalidOperation)
4928 assertIsExclusivelySet(InvalidOperation, c.flags)
Mark Dickinson84230a12010-02-18 14:49:50 +00004929
Stefan Krah1919b7e2012-03-21 18:25:23 +01004930 for cond in IntCond:
4931 c._traps = cond
4932 self.assertTrue(c._traps&DecIEEEInvalidOperation)
4933 assertIsExclusivelySet(InvalidOperation, c.traps)
Mark Dickinson84230a12010-02-18 14:49:50 +00004934
Stefan Krah1919b7e2012-03-21 18:25:23 +01004935 def test_invalid_override(self):
4936 Decimal = C.Decimal
Mark Dickinson84230a12010-02-18 14:49:50 +00004937
Stefan Krah1919b7e2012-03-21 18:25:23 +01004938 try:
4939 from locale import CHAR_MAX
4940 except ImportError:
4941 return
Mark Dickinson84230a12010-02-18 14:49:50 +00004942
Stefan Krah1919b7e2012-03-21 18:25:23 +01004943 def make_grouping(lst):
4944 return ''.join([chr(x) for x in lst])
Mark Dickinson84230a12010-02-18 14:49:50 +00004945
Stefan Krah1919b7e2012-03-21 18:25:23 +01004946 def get_fmt(x, override=None, fmt='n'):
4947 return Decimal(x).__format__(fmt, override)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004948
Stefan Krah1919b7e2012-03-21 18:25:23 +01004949 invalid_grouping = {
4950 'decimal_point' : ',',
4951 'grouping' : make_grouping([255, 255, 0]),
4952 'thousands_sep' : ','
4953 }
4954 invalid_dot = {
4955 'decimal_point' : 'xxxxx',
4956 'grouping' : make_grouping([3, 3, 0]),
4957 'thousands_sep' : ','
4958 }
4959 invalid_sep = {
4960 'decimal_point' : '.',
4961 'grouping' : make_grouping([3, 3, 0]),
4962 'thousands_sep' : 'yyyyy'
4963 }
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004964
Stefan Krah1919b7e2012-03-21 18:25:23 +01004965 if CHAR_MAX == 127: # negative grouping in override
4966 self.assertRaises(ValueError, get_fmt, 12345,
4967 invalid_grouping, 'g')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004968
Stefan Krah1919b7e2012-03-21 18:25:23 +01004969 self.assertRaises(ValueError, get_fmt, 12345, invalid_dot, 'g')
4970 self.assertRaises(ValueError, get_fmt, 12345, invalid_sep, 'g')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004971
Stefan Krah0774e9b2012-04-05 15:21:58 +02004972 def test_exact_conversion(self):
4973 Decimal = C.Decimal
4974 localcontext = C.localcontext
4975 InvalidOperation = C.InvalidOperation
4976
4977 with localcontext() as c:
4978
4979 c.traps[InvalidOperation] = True
4980
4981 # Clamped
4982 x = "0e%d" % sys.maxsize
4983 self.assertRaises(InvalidOperation, Decimal, x)
4984
4985 x = "0e%d" % (-sys.maxsize-1)
4986 self.assertRaises(InvalidOperation, Decimal, x)
4987
4988 # Overflow
4989 x = "1e%d" % sys.maxsize
4990 self.assertRaises(InvalidOperation, Decimal, x)
4991
4992 # Underflow
4993 x = "1e%d" % (-sys.maxsize-1)
4994 self.assertRaises(InvalidOperation, Decimal, x)
4995
Stefan Krahff3eca02012-04-05 15:46:19 +02004996 def test_from_tuple(self):
4997 Decimal = C.Decimal
4998 localcontext = C.localcontext
4999 InvalidOperation = C.InvalidOperation
5000 Overflow = C.Overflow
5001 Underflow = C.Underflow
5002
5003 with localcontext() as c:
5004
5005 c.traps[InvalidOperation] = True
5006 c.traps[Overflow] = True
5007 c.traps[Underflow] = True
5008
5009 # SSIZE_MAX
5010 x = (1, (), sys.maxsize)
5011 self.assertEqual(str(c.create_decimal(x)), '-0E+999999')
5012 self.assertRaises(InvalidOperation, Decimal, x)
5013
5014 x = (1, (0, 1, 2), sys.maxsize)
5015 self.assertRaises(Overflow, c.create_decimal, x)
5016 self.assertRaises(InvalidOperation, Decimal, x)
5017
5018 # SSIZE_MIN
5019 x = (1, (), -sys.maxsize-1)
5020 self.assertEqual(str(c.create_decimal(x)), '-0E-1000026')
5021 self.assertRaises(InvalidOperation, Decimal, x)
5022
5023 x = (1, (0, 1, 2), -sys.maxsize-1)
5024 self.assertRaises(Underflow, c.create_decimal, x)
5025 self.assertRaises(InvalidOperation, Decimal, x)
5026
5027 # OverflowError
5028 x = (1, (), sys.maxsize+1)
5029 self.assertRaises(OverflowError, c.create_decimal, x)
5030 self.assertRaises(OverflowError, Decimal, x)
5031
5032 x = (1, (), -sys.maxsize-2)
5033 self.assertRaises(OverflowError, c.create_decimal, x)
5034 self.assertRaises(OverflowError, Decimal, x)
5035
5036 # Specials
5037 x = (1, (), "N")
5038 self.assertEqual(str(Decimal(x)), '-sNaN')
5039 x = (1, (0,), "N")
5040 self.assertEqual(str(Decimal(x)), '-sNaN')
5041 x = (1, (0, 1), "N")
5042 self.assertEqual(str(Decimal(x)), '-sNaN1')
5043
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005044
Stefan Krah1919b7e2012-03-21 18:25:23 +01005045all_tests = [
5046 CExplicitConstructionTest, PyExplicitConstructionTest,
5047 CImplicitConstructionTest, PyImplicitConstructionTest,
5048 CFormatTest, PyFormatTest,
5049 CArithmeticOperatorsTest, PyArithmeticOperatorsTest,
5050 CThreadingTest, PyThreadingTest,
5051 CUsabilityTest, PyUsabilityTest,
5052 CPythonAPItests, PyPythonAPItests,
5053 CContextAPItests, PyContextAPItests,
5054 CContextWithStatement, PyContextWithStatement,
5055 CContextFlags, PyContextFlags,
5056 CSpecialContexts, PySpecialContexts,
5057 CContextInputValidation, PyContextInputValidation,
5058 CContextSubclassing, PyContextSubclassing,
5059 CCoverage, PyCoverage,
5060 CFunctionality, PyFunctionality,
5061 CWhitebox, PyWhitebox,
5062 CIBMTestCases, PyIBMTestCases,
5063]
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005064
Stefan Krah1919b7e2012-03-21 18:25:23 +01005065# Delete C tests if _decimal.so is not present.
5066if not C:
5067 all_tests = all_tests[1::2]
5068else:
5069 all_tests.insert(0, CheckAttributes)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005070
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005071
5072def test_main(arith=False, verbose=None, todo_tests=None, debug=None):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005073 """ Execute the tests.
5074
Raymond Hettingered20ad82004-09-04 20:09:13 +00005075 Runs all arithmetic tests if arith is True or if the "decimal" resource
5076 is enabled in regrtest.py
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005077 """
Raymond Hettingered20ad82004-09-04 20:09:13 +00005078
Stefan Krah1919b7e2012-03-21 18:25:23 +01005079 init(C)
5080 init(P)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005081 global TEST_ALL, DEBUG
Raymond Hettingered20ad82004-09-04 20:09:13 +00005082 TEST_ALL = arith or is_resource_enabled('decimal')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005083 DEBUG = debug
Raymond Hettingered20ad82004-09-04 20:09:13 +00005084
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005085 if todo_tests is None:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005086 test_classes = all_tests
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005087 else:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005088 test_classes = [CIBMTestCases, PyIBMTestCases]
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005089
5090 # Dynamically build custom test definition for each file in the test
5091 # directory and add the definitions to the DecimalTest class. This
5092 # procedure insures that new files do not get skipped.
5093 for filename in os.listdir(directory):
5094 if '.decTest' not in filename or filename.startswith("."):
5095 continue
5096 head, tail = filename.split('.')
5097 if todo_tests is not None and head not in todo_tests:
5098 continue
5099 tester = lambda self, f=filename: self.eval_file(directory + f)
Stefan Krah1919b7e2012-03-21 18:25:23 +01005100 setattr(CIBMTestCases, 'test_' + head, tester)
5101 setattr(PyIBMTestCases, 'test_' + head, tester)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005102 del filename, head, tail, tester
5103
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005104
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005105 try:
5106 run_unittest(*test_classes)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005107 if todo_tests is None:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005108 from doctest import IGNORE_EXCEPTION_DETAIL
5109 savedecimal = sys.modules['decimal']
5110 if C:
5111 sys.modules['decimal'] = C
5112 run_doctest(C, verbose, optionflags=IGNORE_EXCEPTION_DETAIL)
5113 sys.modules['decimal'] = P
5114 run_doctest(P, verbose)
5115 sys.modules['decimal'] = savedecimal
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005116 finally:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005117 if C: C.setcontext(ORIGINAL_CONTEXT[C])
5118 P.setcontext(ORIGINAL_CONTEXT[P])
5119 if not C:
5120 warnings.warn('C tests skipped: no module named _decimal.',
5121 UserWarning)
5122 if not orig_sys_decimal is sys.modules['decimal']:
5123 raise TestFailed("Internal error: unbalanced number of changes to "
5124 "sys.modules['decimal'].")
5125
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005126
5127if __name__ == '__main__':
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005128 import optparse
5129 p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]")
5130 p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test')
5131 p.add_option('--skip', '-s', action='store_true', help='skip over 90% of the arithmetic tests')
5132 (opt, args) = p.parse_args()
5133
5134 if opt.skip:
5135 test_main(arith=False, verbose=True)
5136 elif args:
5137 test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005138 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005139 test_main(arith=True, verbose=True)