blob: 3ca5927f79e9a665a1de8c561590b514e15eaba7 [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 Krah76e12172012-09-10 19:34:58 +02001995 # The '0' coefficient is implementation specific to decimal.py.
1996 # It has no meaning in the C-version and is ignored there.
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001997 d = Decimal("Infinity")
1998 self.assertEqual(d.as_tuple(), (0, (0,), 'F') )
1999
Guido van Rossum8ce8a782007-11-01 19:42:39 +00002000 #leading zeros in coefficient should be stripped
2001 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), -2) )
2002 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), -2) )
2003 d = Decimal( (1, (0, 0, 0), 37) )
2004 self.assertEqual(d.as_tuple(), (1, (0,), 37))
2005 d = Decimal( (1, (), 37) )
2006 self.assertEqual(d.as_tuple(), (1, (0,), 37))
2007
2008 #leading zeros in NaN diagnostic info should be stripped
2009 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), 'n') )
2010 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), 'n') )
2011 d = Decimal( (1, (0, 0, 0), 'N') )
2012 self.assertEqual(d.as_tuple(), (1, (), 'N') )
2013 d = Decimal( (1, (), 'n') )
2014 self.assertEqual(d.as_tuple(), (1, (), 'n') )
2015
Stefan Krah76e12172012-09-10 19:34:58 +02002016 # For infinities, decimal.py has always silently accepted any
2017 # coefficient tuple.
2018 d = Decimal( (0, (0,), 'F') )
2019 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
2020 d = Decimal( (0, (4, 5, 3, 4), 'F') )
2021 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
2022 d = Decimal( (1, (0, 2, 7, 1), 'F') )
2023 self.assertEqual(d.as_tuple(), (1, (0,), 'F'))
Guido van Rossum8ce8a782007-11-01 19:42:39 +00002024
Stefan Krah1919b7e2012-03-21 18:25:23 +01002025 def test_subclassing(self):
2026 # Different behaviours when subclassing Decimal
2027 Decimal = self.decimal.Decimal
2028
2029 class MyDecimal(Decimal):
2030 pass
2031
2032 d1 = MyDecimal(1)
2033 d2 = MyDecimal(2)
2034 d = d1 + d2
2035 self.assertIs(type(d), Decimal)
2036
2037 d = d1.max(d2)
2038 self.assertIs(type(d), Decimal)
2039
2040 d = copy.copy(d1)
2041 self.assertIs(type(d), MyDecimal)
2042 self.assertEqual(d, d1)
2043
2044 d = copy.deepcopy(d1)
2045 self.assertIs(type(d), MyDecimal)
2046 self.assertEqual(d, d1)
2047
2048 def test_implicit_context(self):
2049 Decimal = self.decimal.Decimal
2050 getcontext = self.decimal.getcontext
2051
2052 # Check results when context given implicitly. (Issue 2478)
2053 c = getcontext()
2054 self.assertEqual(str(Decimal(0).sqrt()),
2055 str(c.sqrt(Decimal(0))))
2056
2057 def test_conversions_from_int(self):
2058 # Check that methods taking a second Decimal argument will
2059 # always accept an integer in place of a Decimal.
2060 Decimal = self.decimal.Decimal
2061
2062 self.assertEqual(Decimal(4).compare(3),
2063 Decimal(4).compare(Decimal(3)))
2064 self.assertEqual(Decimal(4).compare_signal(3),
2065 Decimal(4).compare_signal(Decimal(3)))
2066 self.assertEqual(Decimal(4).compare_total(3),
2067 Decimal(4).compare_total(Decimal(3)))
2068 self.assertEqual(Decimal(4).compare_total_mag(3),
2069 Decimal(4).compare_total_mag(Decimal(3)))
2070 self.assertEqual(Decimal(10101).logical_and(1001),
2071 Decimal(10101).logical_and(Decimal(1001)))
2072 self.assertEqual(Decimal(10101).logical_or(1001),
2073 Decimal(10101).logical_or(Decimal(1001)))
2074 self.assertEqual(Decimal(10101).logical_xor(1001),
2075 Decimal(10101).logical_xor(Decimal(1001)))
2076 self.assertEqual(Decimal(567).max(123),
2077 Decimal(567).max(Decimal(123)))
2078 self.assertEqual(Decimal(567).max_mag(123),
2079 Decimal(567).max_mag(Decimal(123)))
2080 self.assertEqual(Decimal(567).min(123),
2081 Decimal(567).min(Decimal(123)))
2082 self.assertEqual(Decimal(567).min_mag(123),
2083 Decimal(567).min_mag(Decimal(123)))
2084 self.assertEqual(Decimal(567).next_toward(123),
2085 Decimal(567).next_toward(Decimal(123)))
2086 self.assertEqual(Decimal(1234).quantize(100),
2087 Decimal(1234).quantize(Decimal(100)))
2088 self.assertEqual(Decimal(768).remainder_near(1234),
2089 Decimal(768).remainder_near(Decimal(1234)))
2090 self.assertEqual(Decimal(123).rotate(1),
2091 Decimal(123).rotate(Decimal(1)))
2092 self.assertEqual(Decimal(1234).same_quantum(1000),
2093 Decimal(1234).same_quantum(Decimal(1000)))
2094 self.assertEqual(Decimal('9.123').scaleb(-100),
2095 Decimal('9.123').scaleb(Decimal(-100)))
2096 self.assertEqual(Decimal(456).shift(-1),
2097 Decimal(456).shift(Decimal(-1)))
2098
2099 self.assertEqual(Decimal(-12).fma(Decimal(45), 67),
2100 Decimal(-12).fma(Decimal(45), Decimal(67)))
2101 self.assertEqual(Decimal(-12).fma(45, 67),
2102 Decimal(-12).fma(Decimal(45), Decimal(67)))
2103 self.assertEqual(Decimal(-12).fma(45, Decimal(67)),
2104 Decimal(-12).fma(Decimal(45), Decimal(67)))
2105
2106class CUsabilityTest(UsabilityTest):
2107 decimal = C
2108class PyUsabilityTest(UsabilityTest):
2109 decimal = P
2110
2111class PythonAPItests(unittest.TestCase):
2112
2113 def test_abc(self):
2114 Decimal = self.decimal.Decimal
2115
2116 self.assertTrue(issubclass(Decimal, numbers.Number))
2117 self.assertFalse(issubclass(Decimal, numbers.Real))
2118 self.assertIsInstance(Decimal(0), numbers.Number)
2119 self.assertNotIsInstance(Decimal(0), numbers.Real)
2120
2121 def test_pickle(self):
2122 Decimal = self.decimal.Decimal
2123
2124 savedecimal = sys.modules['decimal']
2125
2126 # Round trip
2127 sys.modules['decimal'] = self.decimal
2128 d = Decimal('-3.141590000')
2129 p = pickle.dumps(d)
2130 e = pickle.loads(p)
2131 self.assertEqual(d, e)
2132
2133 if C:
2134 # Test interchangeability
2135 x = C.Decimal('-3.123e81723')
2136 y = P.Decimal('-3.123e81723')
2137
2138 sys.modules['decimal'] = C
2139 sx = pickle.dumps(x)
2140 sys.modules['decimal'] = P
2141 r = pickle.loads(sx)
2142 self.assertIsInstance(r, P.Decimal)
2143 self.assertEqual(r, y)
2144
2145 sys.modules['decimal'] = P
2146 sy = pickle.dumps(y)
2147 sys.modules['decimal'] = C
2148 r = pickle.loads(sy)
2149 self.assertIsInstance(r, C.Decimal)
2150 self.assertEqual(r, x)
2151
2152 sys.modules['decimal'] = savedecimal
2153
2154 def test_int(self):
2155 Decimal = self.decimal.Decimal
2156 ROUND_DOWN = self.decimal.ROUND_DOWN
2157
2158 for x in range(-250, 250):
2159 s = '%0.2f' % (x / 100.0)
2160 # should work the same as for floats
2161 self.assertEqual(int(Decimal(s)), int(float(s)))
2162 # should work the same as to_integral in the ROUND_DOWN mode
2163 d = Decimal(s)
2164 r = d.to_integral(ROUND_DOWN)
2165 self.assertEqual(Decimal(int(d)), r)
2166
2167 self.assertRaises(ValueError, int, Decimal('-nan'))
2168 self.assertRaises(ValueError, int, Decimal('snan'))
2169 self.assertRaises(OverflowError, int, Decimal('inf'))
2170 self.assertRaises(OverflowError, int, Decimal('-inf'))
2171
2172 def test_trunc(self):
2173 Decimal = self.decimal.Decimal
2174 ROUND_DOWN = self.decimal.ROUND_DOWN
2175
2176 for x in range(-250, 250):
2177 s = '%0.2f' % (x / 100.0)
2178 # should work the same as for floats
2179 self.assertEqual(int(Decimal(s)), int(float(s)))
2180 # should work the same as to_integral in the ROUND_DOWN mode
2181 d = Decimal(s)
2182 r = d.to_integral(ROUND_DOWN)
2183 self.assertEqual(Decimal(math.trunc(d)), r)
2184
2185 def test_from_float(self):
2186
2187 Decimal = self.decimal.Decimal
2188
2189 class MyDecimal(Decimal):
2190 pass
2191
2192 self.assertTrue(issubclass(MyDecimal, Decimal))
2193
2194 r = MyDecimal.from_float(0.1)
2195 self.assertEqual(type(r), MyDecimal)
2196 self.assertEqual(str(r),
2197 '0.1000000000000000055511151231257827021181583404541015625')
2198 bigint = 12345678901234567890123456789
2199 self.assertEqual(MyDecimal.from_float(bigint), MyDecimal(bigint))
2200 self.assertTrue(MyDecimal.from_float(float('nan')).is_qnan())
2201 self.assertTrue(MyDecimal.from_float(float('inf')).is_infinite())
2202 self.assertTrue(MyDecimal.from_float(float('-inf')).is_infinite())
2203 self.assertEqual(str(MyDecimal.from_float(float('nan'))),
2204 str(Decimal('NaN')))
2205 self.assertEqual(str(MyDecimal.from_float(float('inf'))),
2206 str(Decimal('Infinity')))
2207 self.assertEqual(str(MyDecimal.from_float(float('-inf'))),
2208 str(Decimal('-Infinity')))
2209 self.assertRaises(TypeError, MyDecimal.from_float, 'abc')
2210 for i in range(200):
2211 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
2212 self.assertEqual(x, float(MyDecimal.from_float(x))) # roundtrip
2213
2214 def test_create_decimal_from_float(self):
2215 Decimal = self.decimal.Decimal
2216 Context = self.decimal.Context
2217 ROUND_DOWN = self.decimal.ROUND_DOWN
2218 ROUND_UP = self.decimal.ROUND_UP
2219 Inexact = self.decimal.Inexact
2220
2221 context = Context(prec=5, rounding=ROUND_DOWN)
2222 self.assertEqual(
2223 context.create_decimal_from_float(math.pi),
2224 Decimal('3.1415')
2225 )
2226 context = Context(prec=5, rounding=ROUND_UP)
2227 self.assertEqual(
2228 context.create_decimal_from_float(math.pi),
2229 Decimal('3.1416')
2230 )
2231 context = Context(prec=5, traps=[Inexact])
2232 self.assertRaises(
2233 Inexact,
2234 context.create_decimal_from_float,
2235 math.pi
2236 )
2237 self.assertEqual(repr(context.create_decimal_from_float(-0.0)),
2238 "Decimal('-0')")
2239 self.assertEqual(repr(context.create_decimal_from_float(1.0)),
2240 "Decimal('1')")
2241 self.assertEqual(repr(context.create_decimal_from_float(10)),
2242 "Decimal('10')")
2243
2244 def test_quantize(self):
2245 Decimal = self.decimal.Decimal
2246 Context = self.decimal.Context
2247 InvalidOperation = self.decimal.InvalidOperation
2248 ROUND_DOWN = self.decimal.ROUND_DOWN
2249
2250 c = Context(Emax=99999, Emin=-99999)
2251 self.assertEqual(
2252 Decimal('7.335').quantize(Decimal('.01')),
2253 Decimal('7.34')
2254 )
2255 self.assertEqual(
2256 Decimal('7.335').quantize(Decimal('.01'), rounding=ROUND_DOWN),
2257 Decimal('7.33')
2258 )
2259 self.assertRaises(
2260 InvalidOperation,
2261 Decimal("10e99999").quantize, Decimal('1e100000'), context=c
2262 )
2263
2264 c = Context()
2265 d = Decimal("0.871831e800")
2266 x = d.quantize(context=c, exp=Decimal("1e797"), rounding=ROUND_DOWN)
2267 self.assertEqual(x, Decimal('8.71E+799'))
2268
2269 def test_complex(self):
2270 Decimal = self.decimal.Decimal
2271
2272 x = Decimal("9.8182731e181273")
2273 self.assertEqual(x.real, x)
2274 self.assertEqual(x.imag, 0)
2275 self.assertEqual(x.conjugate(), x)
2276
2277 x = Decimal("1")
2278 self.assertEqual(complex(x), complex(float(1)))
2279
2280 self.assertRaises(AttributeError, setattr, x, 'real', 100)
2281 self.assertRaises(AttributeError, setattr, x, 'imag', 100)
2282 self.assertRaises(AttributeError, setattr, x, 'conjugate', 100)
2283 self.assertRaises(AttributeError, setattr, x, '__complex__', 100)
2284
2285 def test_named_parameters(self):
2286 D = self.decimal.Decimal
2287 Context = self.decimal.Context
2288 localcontext = self.decimal.localcontext
2289 InvalidOperation = self.decimal.InvalidOperation
2290 Overflow = self.decimal.Overflow
2291
2292 xc = Context()
2293 xc.prec = 1
2294 xc.Emax = 1
2295 xc.Emin = -1
2296
2297 with localcontext() as c:
2298 c.clear_flags()
2299
2300 self.assertEqual(D(9, xc), 9)
2301 self.assertEqual(D(9, context=xc), 9)
2302 self.assertEqual(D(context=xc, value=9), 9)
2303 self.assertEqual(D(context=xc), 0)
2304 xc.clear_flags()
2305 self.assertRaises(InvalidOperation, D, "xyz", context=xc)
2306 self.assertTrue(xc.flags[InvalidOperation])
2307 self.assertFalse(c.flags[InvalidOperation])
2308
2309 xc.clear_flags()
2310 self.assertEqual(D(2).exp(context=xc), 7)
2311 self.assertRaises(Overflow, D(8).exp, context=xc)
2312 self.assertTrue(xc.flags[Overflow])
2313 self.assertFalse(c.flags[Overflow])
2314
2315 xc.clear_flags()
2316 self.assertEqual(D(2).ln(context=xc), D('0.7'))
2317 self.assertRaises(InvalidOperation, D(-1).ln, context=xc)
2318 self.assertTrue(xc.flags[InvalidOperation])
2319 self.assertFalse(c.flags[InvalidOperation])
2320
2321 self.assertEqual(D(0).log10(context=xc), D('-inf'))
2322 self.assertEqual(D(-1).next_minus(context=xc), -2)
2323 self.assertEqual(D(-1).next_plus(context=xc), D('-0.9'))
2324 self.assertEqual(D("9.73").normalize(context=xc), D('1E+1'))
2325 self.assertEqual(D("9999").to_integral(context=xc), 9999)
2326 self.assertEqual(D("-2000").to_integral_exact(context=xc), -2000)
2327 self.assertEqual(D("123").to_integral_value(context=xc), 123)
2328 self.assertEqual(D("0.0625").sqrt(context=xc), D('0.2'))
2329
2330 self.assertEqual(D("0.0625").compare(context=xc, other=3), -1)
2331 xc.clear_flags()
2332 self.assertRaises(InvalidOperation,
2333 D("0").compare_signal, D('nan'), context=xc)
2334 self.assertTrue(xc.flags[InvalidOperation])
2335 self.assertFalse(c.flags[InvalidOperation])
2336 self.assertEqual(D("0.01").max(D('0.0101'), context=xc), D('0.0'))
2337 self.assertEqual(D("0.01").max(D('0.0101'), context=xc), D('0.0'))
2338 self.assertEqual(D("0.2").max_mag(D('-0.3'), context=xc),
2339 D('-0.3'))
2340 self.assertEqual(D("0.02").min(D('-0.03'), context=xc), D('-0.0'))
2341 self.assertEqual(D("0.02").min_mag(D('-0.03'), context=xc),
2342 D('0.0'))
2343 self.assertEqual(D("0.2").next_toward(D('-1'), context=xc), D('0.1'))
2344 xc.clear_flags()
2345 self.assertRaises(InvalidOperation,
2346 D("0.2").quantize, D('1e10'), context=xc)
2347 self.assertTrue(xc.flags[InvalidOperation])
2348 self.assertFalse(c.flags[InvalidOperation])
2349 self.assertEqual(D("9.99").remainder_near(D('1.5'), context=xc),
2350 D('-0.5'))
2351
2352 self.assertEqual(D("9.9").fma(third=D('0.9'), context=xc, other=7),
2353 D('7E+1'))
2354
2355 self.assertRaises(TypeError, D(1).is_canonical, context=xc)
2356 self.assertRaises(TypeError, D(1).is_finite, context=xc)
2357 self.assertRaises(TypeError, D(1).is_infinite, context=xc)
2358 self.assertRaises(TypeError, D(1).is_nan, context=xc)
2359 self.assertRaises(TypeError, D(1).is_qnan, context=xc)
2360 self.assertRaises(TypeError, D(1).is_snan, context=xc)
2361 self.assertRaises(TypeError, D(1).is_signed, context=xc)
2362 self.assertRaises(TypeError, D(1).is_zero, context=xc)
2363
2364 self.assertFalse(D("0.01").is_normal(context=xc))
2365 self.assertTrue(D("0.01").is_subnormal(context=xc))
2366
2367 self.assertRaises(TypeError, D(1).adjusted, context=xc)
2368 self.assertRaises(TypeError, D(1).conjugate, context=xc)
2369 self.assertRaises(TypeError, D(1).radix, context=xc)
2370
2371 self.assertEqual(D(-111).logb(context=xc), 2)
2372 self.assertEqual(D(0).logical_invert(context=xc), 1)
2373 self.assertEqual(D('0.01').number_class(context=xc), '+Subnormal')
2374 self.assertEqual(D('0.21').to_eng_string(context=xc), '0.21')
2375
2376 self.assertEqual(D('11').logical_and(D('10'), context=xc), 0)
2377 self.assertEqual(D('11').logical_or(D('10'), context=xc), 1)
2378 self.assertEqual(D('01').logical_xor(D('10'), context=xc), 1)
2379 self.assertEqual(D('23').rotate(1, context=xc), 3)
2380 self.assertEqual(D('23').rotate(1, context=xc), 3)
2381 xc.clear_flags()
2382 self.assertRaises(Overflow,
2383 D('23').scaleb, 1, context=xc)
2384 self.assertTrue(xc.flags[Overflow])
2385 self.assertFalse(c.flags[Overflow])
2386 self.assertEqual(D('23').shift(-1, context=xc), 0)
2387
2388 self.assertRaises(TypeError, D.from_float, 1.1, context=xc)
2389 self.assertRaises(TypeError, D(0).as_tuple, context=xc)
2390
2391 if (self.decimal == C):
2392 self.assertRaises(TypeError, D(1).canonical, context=xc)
2393 self.assertEqual(D("-1").copy_abs(context=xc), 1)
2394 self.assertEqual(D("1").copy_negate(context=xc), -1)
2395 else:
2396 self.assertEqual(D(1).canonical(context=xc), 1)
2397 self.assertRaises(TypeError, D("-1").copy_abs, context=xc)
2398 self.assertRaises(TypeError, D("-1").copy_negate, context=xc)
2399
Stefan Krahb6405ef2012-03-23 14:46:48 +01002400 def test_exception_hierarchy(self):
2401
2402 decimal = self.decimal
2403 DecimalException = decimal.DecimalException
2404 InvalidOperation = decimal.InvalidOperation
2405 FloatOperation = decimal.FloatOperation
2406 DivisionByZero = decimal.DivisionByZero
2407 Overflow = decimal.Overflow
2408 Underflow = decimal.Underflow
2409 Subnormal = decimal.Subnormal
2410 Inexact = decimal.Inexact
2411 Rounded = decimal.Rounded
2412 Clamped = decimal.Clamped
2413
2414 self.assertTrue(issubclass(DecimalException, ArithmeticError))
2415
2416 self.assertTrue(issubclass(InvalidOperation, DecimalException))
2417 self.assertTrue(issubclass(FloatOperation, DecimalException))
2418 self.assertTrue(issubclass(FloatOperation, TypeError))
2419 self.assertTrue(issubclass(DivisionByZero, DecimalException))
2420 self.assertTrue(issubclass(DivisionByZero, ZeroDivisionError))
2421 self.assertTrue(issubclass(Overflow, Rounded))
2422 self.assertTrue(issubclass(Overflow, Inexact))
2423 self.assertTrue(issubclass(Overflow, DecimalException))
2424 self.assertTrue(issubclass(Underflow, Inexact))
2425 self.assertTrue(issubclass(Underflow, Rounded))
2426 self.assertTrue(issubclass(Underflow, Subnormal))
2427 self.assertTrue(issubclass(Underflow, DecimalException))
2428
2429 self.assertTrue(issubclass(Subnormal, DecimalException))
2430 self.assertTrue(issubclass(Inexact, DecimalException))
2431 self.assertTrue(issubclass(Rounded, DecimalException))
2432 self.assertTrue(issubclass(Clamped, DecimalException))
2433
2434 self.assertTrue(issubclass(decimal.ConversionSyntax, InvalidOperation))
2435 self.assertTrue(issubclass(decimal.DivisionImpossible, InvalidOperation))
2436 self.assertTrue(issubclass(decimal.DivisionUndefined, InvalidOperation))
2437 self.assertTrue(issubclass(decimal.DivisionUndefined, ZeroDivisionError))
2438 self.assertTrue(issubclass(decimal.InvalidContext, InvalidOperation))
2439
Stefan Krah1919b7e2012-03-21 18:25:23 +01002440class CPythonAPItests(PythonAPItests):
2441 decimal = C
2442class PyPythonAPItests(PythonAPItests):
2443 decimal = P
2444
2445class ContextAPItests(unittest.TestCase):
2446
2447 def test_pickle(self):
2448
2449 Context = self.decimal.Context
2450
2451 savedecimal = sys.modules['decimal']
2452
2453 # Round trip
2454 sys.modules['decimal'] = self.decimal
2455 c = Context()
2456 e = pickle.loads(pickle.dumps(c))
2457
2458 self.assertEqual(c.prec, e.prec)
2459 self.assertEqual(c.Emin, e.Emin)
2460 self.assertEqual(c.Emax, e.Emax)
2461 self.assertEqual(c.rounding, e.rounding)
2462 self.assertEqual(c.capitals, e.capitals)
2463 self.assertEqual(c.clamp, e.clamp)
2464 self.assertEqual(c.flags, e.flags)
2465 self.assertEqual(c.traps, e.traps)
2466
2467 # Test interchangeability
2468 combinations = [(C, P), (P, C)] if C else [(P, P)]
2469 for dumper, loader in combinations:
2470 for ri, _ in enumerate(RoundingModes[dumper]):
2471 for fi, _ in enumerate(OrderedSignals[dumper]):
2472 for ti, _ in enumerate(OrderedSignals[dumper]):
2473
2474 prec = random.randrange(1, 100)
2475 emin = random.randrange(-100, 0)
2476 emax = random.randrange(1, 100)
2477 caps = random.randrange(2)
2478 clamp = random.randrange(2)
2479
2480 # One module dumps
2481 sys.modules['decimal'] = dumper
2482 c = dumper.Context(
2483 prec=prec, Emin=emin, Emax=emax,
2484 rounding=RoundingModes[dumper][ri],
2485 capitals=caps, clamp=clamp,
2486 flags=OrderedSignals[dumper][:fi],
2487 traps=OrderedSignals[dumper][:ti]
2488 )
2489 s = pickle.dumps(c)
2490
2491 # The other module loads
2492 sys.modules['decimal'] = loader
2493 d = pickle.loads(s)
2494 self.assertIsInstance(d, loader.Context)
2495
2496 self.assertEqual(d.prec, prec)
2497 self.assertEqual(d.Emin, emin)
2498 self.assertEqual(d.Emax, emax)
2499 self.assertEqual(d.rounding, RoundingModes[loader][ri])
2500 self.assertEqual(d.capitals, caps)
2501 self.assertEqual(d.clamp, clamp)
2502 assert_signals(self, d, 'flags', OrderedSignals[loader][:fi])
2503 assert_signals(self, d, 'traps', OrderedSignals[loader][:ti])
2504
2505 sys.modules['decimal'] = savedecimal
2506
2507 def test_equality_with_other_types(self):
2508 Decimal = self.decimal.Decimal
2509
2510 self.assertIn(Decimal(10), ['a', 1.0, Decimal(10), (1,2), {}])
2511 self.assertNotIn(Decimal(10), ['a', 1.0, (1,2), {}])
2512
2513 def test_copy(self):
2514 # All copies should be deep
2515 Decimal = self.decimal.Decimal
2516 Context = self.decimal.Context
2517
2518 c = Context()
2519 d = c.copy()
2520 self.assertNotEqual(id(c), id(d))
2521 self.assertNotEqual(id(c.flags), id(d.flags))
2522 self.assertNotEqual(id(c.traps), id(d.traps))
2523 k1 = set(c.flags.keys())
2524 k2 = set(d.flags.keys())
2525 self.assertEqual(k1, k2)
2526 self.assertEqual(c.flags, d.flags)
2527
2528 def test__clamp(self):
2529 # In Python 3.2, the private attribute `_clamp` was made
2530 # public (issue 8540), with the old `_clamp` becoming a
2531 # property wrapping `clamp`. For the duration of Python 3.2
2532 # only, the attribute should be gettable/settable via both
2533 # `clamp` and `_clamp`; in Python 3.3, `_clamp` should be
2534 # removed.
2535 Context = self.decimal.Context
2536 c = Context()
2537 self.assertRaises(AttributeError, getattr, c, '_clamp')
2538
2539 def test_abs(self):
2540 Decimal = self.decimal.Decimal
2541 Context = self.decimal.Context
2542
2543 c = Context()
2544 d = c.abs(Decimal(-1))
2545 self.assertEqual(c.abs(-1), d)
2546 self.assertRaises(TypeError, c.abs, '-1')
2547
2548 def test_add(self):
2549 Decimal = self.decimal.Decimal
2550 Context = self.decimal.Context
2551
2552 c = Context()
2553 d = c.add(Decimal(1), Decimal(1))
2554 self.assertEqual(c.add(1, 1), d)
2555 self.assertEqual(c.add(Decimal(1), 1), d)
2556 self.assertEqual(c.add(1, Decimal(1)), d)
2557 self.assertRaises(TypeError, c.add, '1', 1)
2558 self.assertRaises(TypeError, c.add, 1, '1')
2559
2560 def test_compare(self):
2561 Decimal = self.decimal.Decimal
2562 Context = self.decimal.Context
2563
2564 c = Context()
2565 d = c.compare(Decimal(1), Decimal(1))
2566 self.assertEqual(c.compare(1, 1), d)
2567 self.assertEqual(c.compare(Decimal(1), 1), d)
2568 self.assertEqual(c.compare(1, Decimal(1)), d)
2569 self.assertRaises(TypeError, c.compare, '1', 1)
2570 self.assertRaises(TypeError, c.compare, 1, '1')
2571
2572 def test_compare_signal(self):
2573 Decimal = self.decimal.Decimal
2574 Context = self.decimal.Context
2575
2576 c = Context()
2577 d = c.compare_signal(Decimal(1), Decimal(1))
2578 self.assertEqual(c.compare_signal(1, 1), d)
2579 self.assertEqual(c.compare_signal(Decimal(1), 1), d)
2580 self.assertEqual(c.compare_signal(1, Decimal(1)), d)
2581 self.assertRaises(TypeError, c.compare_signal, '1', 1)
2582 self.assertRaises(TypeError, c.compare_signal, 1, '1')
2583
2584 def test_compare_total(self):
2585 Decimal = self.decimal.Decimal
2586 Context = self.decimal.Context
2587
2588 c = Context()
2589 d = c.compare_total(Decimal(1), Decimal(1))
2590 self.assertEqual(c.compare_total(1, 1), d)
2591 self.assertEqual(c.compare_total(Decimal(1), 1), d)
2592 self.assertEqual(c.compare_total(1, Decimal(1)), d)
2593 self.assertRaises(TypeError, c.compare_total, '1', 1)
2594 self.assertRaises(TypeError, c.compare_total, 1, '1')
2595
2596 def test_compare_total_mag(self):
2597 Decimal = self.decimal.Decimal
2598 Context = self.decimal.Context
2599
2600 c = Context()
2601 d = c.compare_total_mag(Decimal(1), Decimal(1))
2602 self.assertEqual(c.compare_total_mag(1, 1), d)
2603 self.assertEqual(c.compare_total_mag(Decimal(1), 1), d)
2604 self.assertEqual(c.compare_total_mag(1, Decimal(1)), d)
2605 self.assertRaises(TypeError, c.compare_total_mag, '1', 1)
2606 self.assertRaises(TypeError, c.compare_total_mag, 1, '1')
2607
2608 def test_copy_abs(self):
2609 Decimal = self.decimal.Decimal
2610 Context = self.decimal.Context
2611
2612 c = Context()
2613 d = c.copy_abs(Decimal(-1))
2614 self.assertEqual(c.copy_abs(-1), d)
2615 self.assertRaises(TypeError, c.copy_abs, '-1')
2616
2617 def test_copy_decimal(self):
2618 Decimal = self.decimal.Decimal
2619 Context = self.decimal.Context
2620
2621 c = Context()
2622 d = c.copy_decimal(Decimal(-1))
2623 self.assertEqual(c.copy_decimal(-1), d)
2624 self.assertRaises(TypeError, c.copy_decimal, '-1')
2625
2626 def test_copy_negate(self):
2627 Decimal = self.decimal.Decimal
2628 Context = self.decimal.Context
2629
2630 c = Context()
2631 d = c.copy_negate(Decimal(-1))
2632 self.assertEqual(c.copy_negate(-1), d)
2633 self.assertRaises(TypeError, c.copy_negate, '-1')
2634
2635 def test_copy_sign(self):
2636 Decimal = self.decimal.Decimal
2637 Context = self.decimal.Context
2638
2639 c = Context()
2640 d = c.copy_sign(Decimal(1), Decimal(-2))
2641 self.assertEqual(c.copy_sign(1, -2), d)
2642 self.assertEqual(c.copy_sign(Decimal(1), -2), d)
2643 self.assertEqual(c.copy_sign(1, Decimal(-2)), d)
2644 self.assertRaises(TypeError, c.copy_sign, '1', -2)
2645 self.assertRaises(TypeError, c.copy_sign, 1, '-2')
2646
2647 def test_divide(self):
2648 Decimal = self.decimal.Decimal
2649 Context = self.decimal.Context
2650
2651 c = Context()
2652 d = c.divide(Decimal(1), Decimal(2))
2653 self.assertEqual(c.divide(1, 2), d)
2654 self.assertEqual(c.divide(Decimal(1), 2), d)
2655 self.assertEqual(c.divide(1, Decimal(2)), d)
2656 self.assertRaises(TypeError, c.divide, '1', 2)
2657 self.assertRaises(TypeError, c.divide, 1, '2')
2658
2659 def test_divide_int(self):
2660 Decimal = self.decimal.Decimal
2661 Context = self.decimal.Context
2662
2663 c = Context()
2664 d = c.divide_int(Decimal(1), Decimal(2))
2665 self.assertEqual(c.divide_int(1, 2), d)
2666 self.assertEqual(c.divide_int(Decimal(1), 2), d)
2667 self.assertEqual(c.divide_int(1, Decimal(2)), d)
2668 self.assertRaises(TypeError, c.divide_int, '1', 2)
2669 self.assertRaises(TypeError, c.divide_int, 1, '2')
2670
2671 def test_divmod(self):
2672 Decimal = self.decimal.Decimal
2673 Context = self.decimal.Context
2674
2675 c = Context()
2676 d = c.divmod(Decimal(1), Decimal(2))
2677 self.assertEqual(c.divmod(1, 2), d)
2678 self.assertEqual(c.divmod(Decimal(1), 2), d)
2679 self.assertEqual(c.divmod(1, Decimal(2)), d)
2680 self.assertRaises(TypeError, c.divmod, '1', 2)
2681 self.assertRaises(TypeError, c.divmod, 1, '2')
2682
2683 def test_exp(self):
2684 Decimal = self.decimal.Decimal
2685 Context = self.decimal.Context
2686
2687 c = Context()
2688 d = c.exp(Decimal(10))
2689 self.assertEqual(c.exp(10), d)
2690 self.assertRaises(TypeError, c.exp, '10')
2691
2692 def test_fma(self):
2693 Decimal = self.decimal.Decimal
2694 Context = self.decimal.Context
2695
2696 c = Context()
2697 d = c.fma(Decimal(2), Decimal(3), Decimal(4))
2698 self.assertEqual(c.fma(2, 3, 4), d)
2699 self.assertEqual(c.fma(Decimal(2), 3, 4), d)
2700 self.assertEqual(c.fma(2, Decimal(3), 4), d)
2701 self.assertEqual(c.fma(2, 3, Decimal(4)), d)
2702 self.assertEqual(c.fma(Decimal(2), Decimal(3), 4), d)
2703 self.assertRaises(TypeError, c.fma, '2', 3, 4)
2704 self.assertRaises(TypeError, c.fma, 2, '3', 4)
2705 self.assertRaises(TypeError, c.fma, 2, 3, '4')
2706
2707 # Issue 12079 for Context.fma ...
2708 self.assertRaises(TypeError, c.fma,
2709 Decimal('Infinity'), Decimal(0), "not a decimal")
2710 self.assertRaises(TypeError, c.fma,
2711 Decimal(1), Decimal('snan'), 1.222)
2712 # ... and for Decimal.fma.
2713 self.assertRaises(TypeError, Decimal('Infinity').fma,
2714 Decimal(0), "not a decimal")
2715 self.assertRaises(TypeError, Decimal(1).fma,
2716 Decimal('snan'), 1.222)
2717
2718 def test_is_finite(self):
2719 Decimal = self.decimal.Decimal
2720 Context = self.decimal.Context
2721
2722 c = Context()
2723 d = c.is_finite(Decimal(10))
2724 self.assertEqual(c.is_finite(10), d)
2725 self.assertRaises(TypeError, c.is_finite, '10')
2726
2727 def test_is_infinite(self):
2728 Decimal = self.decimal.Decimal
2729 Context = self.decimal.Context
2730
2731 c = Context()
2732 d = c.is_infinite(Decimal(10))
2733 self.assertEqual(c.is_infinite(10), d)
2734 self.assertRaises(TypeError, c.is_infinite, '10')
2735
2736 def test_is_nan(self):
2737 Decimal = self.decimal.Decimal
2738 Context = self.decimal.Context
2739
2740 c = Context()
2741 d = c.is_nan(Decimal(10))
2742 self.assertEqual(c.is_nan(10), d)
2743 self.assertRaises(TypeError, c.is_nan, '10')
2744
2745 def test_is_normal(self):
2746 Decimal = self.decimal.Decimal
2747 Context = self.decimal.Context
2748
2749 c = Context()
2750 d = c.is_normal(Decimal(10))
2751 self.assertEqual(c.is_normal(10), d)
2752 self.assertRaises(TypeError, c.is_normal, '10')
2753
2754 def test_is_qnan(self):
2755 Decimal = self.decimal.Decimal
2756 Context = self.decimal.Context
2757
2758 c = Context()
2759 d = c.is_qnan(Decimal(10))
2760 self.assertEqual(c.is_qnan(10), d)
2761 self.assertRaises(TypeError, c.is_qnan, '10')
2762
2763 def test_is_signed(self):
2764 Decimal = self.decimal.Decimal
2765 Context = self.decimal.Context
2766
2767 c = Context()
2768 d = c.is_signed(Decimal(10))
2769 self.assertEqual(c.is_signed(10), d)
2770 self.assertRaises(TypeError, c.is_signed, '10')
2771
2772 def test_is_snan(self):
2773 Decimal = self.decimal.Decimal
2774 Context = self.decimal.Context
2775
2776 c = Context()
2777 d = c.is_snan(Decimal(10))
2778 self.assertEqual(c.is_snan(10), d)
2779 self.assertRaises(TypeError, c.is_snan, '10')
2780
2781 def test_is_subnormal(self):
2782 Decimal = self.decimal.Decimal
2783 Context = self.decimal.Context
2784
2785 c = Context()
2786 d = c.is_subnormal(Decimal(10))
2787 self.assertEqual(c.is_subnormal(10), d)
2788 self.assertRaises(TypeError, c.is_subnormal, '10')
2789
2790 def test_is_zero(self):
2791 Decimal = self.decimal.Decimal
2792 Context = self.decimal.Context
2793
2794 c = Context()
2795 d = c.is_zero(Decimal(10))
2796 self.assertEqual(c.is_zero(10), d)
2797 self.assertRaises(TypeError, c.is_zero, '10')
2798
2799 def test_ln(self):
2800 Decimal = self.decimal.Decimal
2801 Context = self.decimal.Context
2802
2803 c = Context()
2804 d = c.ln(Decimal(10))
2805 self.assertEqual(c.ln(10), d)
2806 self.assertRaises(TypeError, c.ln, '10')
2807
2808 def test_log10(self):
2809 Decimal = self.decimal.Decimal
2810 Context = self.decimal.Context
2811
2812 c = Context()
2813 d = c.log10(Decimal(10))
2814 self.assertEqual(c.log10(10), d)
2815 self.assertRaises(TypeError, c.log10, '10')
2816
2817 def test_logb(self):
2818 Decimal = self.decimal.Decimal
2819 Context = self.decimal.Context
2820
2821 c = Context()
2822 d = c.logb(Decimal(10))
2823 self.assertEqual(c.logb(10), d)
2824 self.assertRaises(TypeError, c.logb, '10')
2825
2826 def test_logical_and(self):
2827 Decimal = self.decimal.Decimal
2828 Context = self.decimal.Context
2829
2830 c = Context()
2831 d = c.logical_and(Decimal(1), Decimal(1))
2832 self.assertEqual(c.logical_and(1, 1), d)
2833 self.assertEqual(c.logical_and(Decimal(1), 1), d)
2834 self.assertEqual(c.logical_and(1, Decimal(1)), d)
2835 self.assertRaises(TypeError, c.logical_and, '1', 1)
2836 self.assertRaises(TypeError, c.logical_and, 1, '1')
2837
2838 def test_logical_invert(self):
2839 Decimal = self.decimal.Decimal
2840 Context = self.decimal.Context
2841
2842 c = Context()
2843 d = c.logical_invert(Decimal(1000))
2844 self.assertEqual(c.logical_invert(1000), d)
2845 self.assertRaises(TypeError, c.logical_invert, '1000')
2846
2847 def test_logical_or(self):
2848 Decimal = self.decimal.Decimal
2849 Context = self.decimal.Context
2850
2851 c = Context()
2852 d = c.logical_or(Decimal(1), Decimal(1))
2853 self.assertEqual(c.logical_or(1, 1), d)
2854 self.assertEqual(c.logical_or(Decimal(1), 1), d)
2855 self.assertEqual(c.logical_or(1, Decimal(1)), d)
2856 self.assertRaises(TypeError, c.logical_or, '1', 1)
2857 self.assertRaises(TypeError, c.logical_or, 1, '1')
2858
2859 def test_logical_xor(self):
2860 Decimal = self.decimal.Decimal
2861 Context = self.decimal.Context
2862
2863 c = Context()
2864 d = c.logical_xor(Decimal(1), Decimal(1))
2865 self.assertEqual(c.logical_xor(1, 1), d)
2866 self.assertEqual(c.logical_xor(Decimal(1), 1), d)
2867 self.assertEqual(c.logical_xor(1, Decimal(1)), d)
2868 self.assertRaises(TypeError, c.logical_xor, '1', 1)
2869 self.assertRaises(TypeError, c.logical_xor, 1, '1')
2870
2871 def test_max(self):
2872 Decimal = self.decimal.Decimal
2873 Context = self.decimal.Context
2874
2875 c = Context()
2876 d = c.max(Decimal(1), Decimal(2))
2877 self.assertEqual(c.max(1, 2), d)
2878 self.assertEqual(c.max(Decimal(1), 2), d)
2879 self.assertEqual(c.max(1, Decimal(2)), d)
2880 self.assertRaises(TypeError, c.max, '1', 2)
2881 self.assertRaises(TypeError, c.max, 1, '2')
2882
2883 def test_max_mag(self):
2884 Decimal = self.decimal.Decimal
2885 Context = self.decimal.Context
2886
2887 c = Context()
2888 d = c.max_mag(Decimal(1), Decimal(2))
2889 self.assertEqual(c.max_mag(1, 2), d)
2890 self.assertEqual(c.max_mag(Decimal(1), 2), d)
2891 self.assertEqual(c.max_mag(1, Decimal(2)), d)
2892 self.assertRaises(TypeError, c.max_mag, '1', 2)
2893 self.assertRaises(TypeError, c.max_mag, 1, '2')
2894
2895 def test_min(self):
2896 Decimal = self.decimal.Decimal
2897 Context = self.decimal.Context
2898
2899 c = Context()
2900 d = c.min(Decimal(1), Decimal(2))
2901 self.assertEqual(c.min(1, 2), d)
2902 self.assertEqual(c.min(Decimal(1), 2), d)
2903 self.assertEqual(c.min(1, Decimal(2)), d)
2904 self.assertRaises(TypeError, c.min, '1', 2)
2905 self.assertRaises(TypeError, c.min, 1, '2')
2906
2907 def test_min_mag(self):
2908 Decimal = self.decimal.Decimal
2909 Context = self.decimal.Context
2910
2911 c = Context()
2912 d = c.min_mag(Decimal(1), Decimal(2))
2913 self.assertEqual(c.min_mag(1, 2), d)
2914 self.assertEqual(c.min_mag(Decimal(1), 2), d)
2915 self.assertEqual(c.min_mag(1, Decimal(2)), d)
2916 self.assertRaises(TypeError, c.min_mag, '1', 2)
2917 self.assertRaises(TypeError, c.min_mag, 1, '2')
2918
2919 def test_minus(self):
2920 Decimal = self.decimal.Decimal
2921 Context = self.decimal.Context
2922
2923 c = Context()
2924 d = c.minus(Decimal(10))
2925 self.assertEqual(c.minus(10), d)
2926 self.assertRaises(TypeError, c.minus, '10')
2927
2928 def test_multiply(self):
2929 Decimal = self.decimal.Decimal
2930 Context = self.decimal.Context
2931
2932 c = Context()
2933 d = c.multiply(Decimal(1), Decimal(2))
2934 self.assertEqual(c.multiply(1, 2), d)
2935 self.assertEqual(c.multiply(Decimal(1), 2), d)
2936 self.assertEqual(c.multiply(1, Decimal(2)), d)
2937 self.assertRaises(TypeError, c.multiply, '1', 2)
2938 self.assertRaises(TypeError, c.multiply, 1, '2')
2939
2940 def test_next_minus(self):
2941 Decimal = self.decimal.Decimal
2942 Context = self.decimal.Context
2943
2944 c = Context()
2945 d = c.next_minus(Decimal(10))
2946 self.assertEqual(c.next_minus(10), d)
2947 self.assertRaises(TypeError, c.next_minus, '10')
2948
2949 def test_next_plus(self):
2950 Decimal = self.decimal.Decimal
2951 Context = self.decimal.Context
2952
2953 c = Context()
2954 d = c.next_plus(Decimal(10))
2955 self.assertEqual(c.next_plus(10), d)
2956 self.assertRaises(TypeError, c.next_plus, '10')
2957
2958 def test_next_toward(self):
2959 Decimal = self.decimal.Decimal
2960 Context = self.decimal.Context
2961
2962 c = Context()
2963 d = c.next_toward(Decimal(1), Decimal(2))
2964 self.assertEqual(c.next_toward(1, 2), d)
2965 self.assertEqual(c.next_toward(Decimal(1), 2), d)
2966 self.assertEqual(c.next_toward(1, Decimal(2)), d)
2967 self.assertRaises(TypeError, c.next_toward, '1', 2)
2968 self.assertRaises(TypeError, c.next_toward, 1, '2')
2969
2970 def test_normalize(self):
2971 Decimal = self.decimal.Decimal
2972 Context = self.decimal.Context
2973
2974 c = Context()
2975 d = c.normalize(Decimal(10))
2976 self.assertEqual(c.normalize(10), d)
2977 self.assertRaises(TypeError, c.normalize, '10')
2978
2979 def test_number_class(self):
2980 Decimal = self.decimal.Decimal
2981 Context = self.decimal.Context
2982
2983 c = Context()
2984 self.assertEqual(c.number_class(123), c.number_class(Decimal(123)))
2985 self.assertEqual(c.number_class(0), c.number_class(Decimal(0)))
2986 self.assertEqual(c.number_class(-45), c.number_class(Decimal(-45)))
2987
2988 def test_plus(self):
2989 Decimal = self.decimal.Decimal
2990 Context = self.decimal.Context
2991
2992 c = Context()
2993 d = c.plus(Decimal(10))
2994 self.assertEqual(c.plus(10), d)
2995 self.assertRaises(TypeError, c.plus, '10')
2996
2997 def test_power(self):
2998 Decimal = self.decimal.Decimal
2999 Context = self.decimal.Context
3000
3001 c = Context()
3002 d = c.power(Decimal(1), Decimal(4))
3003 self.assertEqual(c.power(1, 4), d)
3004 self.assertEqual(c.power(Decimal(1), 4), d)
3005 self.assertEqual(c.power(1, Decimal(4)), d)
3006 self.assertEqual(c.power(Decimal(1), Decimal(4)), d)
3007 self.assertRaises(TypeError, c.power, '1', 4)
3008 self.assertRaises(TypeError, c.power, 1, '4')
3009 self.assertEqual(c.power(modulo=5, b=8, a=2), 1)
3010
3011 def test_quantize(self):
3012 Decimal = self.decimal.Decimal
3013 Context = self.decimal.Context
3014
3015 c = Context()
3016 d = c.quantize(Decimal(1), Decimal(2))
3017 self.assertEqual(c.quantize(1, 2), d)
3018 self.assertEqual(c.quantize(Decimal(1), 2), d)
3019 self.assertEqual(c.quantize(1, Decimal(2)), d)
3020 self.assertRaises(TypeError, c.quantize, '1', 2)
3021 self.assertRaises(TypeError, c.quantize, 1, '2')
3022
3023 def test_remainder(self):
3024 Decimal = self.decimal.Decimal
3025 Context = self.decimal.Context
3026
3027 c = Context()
3028 d = c.remainder(Decimal(1), Decimal(2))
3029 self.assertEqual(c.remainder(1, 2), d)
3030 self.assertEqual(c.remainder(Decimal(1), 2), d)
3031 self.assertEqual(c.remainder(1, Decimal(2)), d)
3032 self.assertRaises(TypeError, c.remainder, '1', 2)
3033 self.assertRaises(TypeError, c.remainder, 1, '2')
3034
3035 def test_remainder_near(self):
3036 Decimal = self.decimal.Decimal
3037 Context = self.decimal.Context
3038
3039 c = Context()
3040 d = c.remainder_near(Decimal(1), Decimal(2))
3041 self.assertEqual(c.remainder_near(1, 2), d)
3042 self.assertEqual(c.remainder_near(Decimal(1), 2), d)
3043 self.assertEqual(c.remainder_near(1, Decimal(2)), d)
3044 self.assertRaises(TypeError, c.remainder_near, '1', 2)
3045 self.assertRaises(TypeError, c.remainder_near, 1, '2')
3046
3047 def test_rotate(self):
3048 Decimal = self.decimal.Decimal
3049 Context = self.decimal.Context
3050
3051 c = Context()
3052 d = c.rotate(Decimal(1), Decimal(2))
3053 self.assertEqual(c.rotate(1, 2), d)
3054 self.assertEqual(c.rotate(Decimal(1), 2), d)
3055 self.assertEqual(c.rotate(1, Decimal(2)), d)
3056 self.assertRaises(TypeError, c.rotate, '1', 2)
3057 self.assertRaises(TypeError, c.rotate, 1, '2')
3058
3059 def test_sqrt(self):
3060 Decimal = self.decimal.Decimal
3061 Context = self.decimal.Context
3062
3063 c = Context()
3064 d = c.sqrt(Decimal(10))
3065 self.assertEqual(c.sqrt(10), d)
3066 self.assertRaises(TypeError, c.sqrt, '10')
3067
3068 def test_same_quantum(self):
3069 Decimal = self.decimal.Decimal
3070 Context = self.decimal.Context
3071
3072 c = Context()
3073 d = c.same_quantum(Decimal(1), Decimal(2))
3074 self.assertEqual(c.same_quantum(1, 2), d)
3075 self.assertEqual(c.same_quantum(Decimal(1), 2), d)
3076 self.assertEqual(c.same_quantum(1, Decimal(2)), d)
3077 self.assertRaises(TypeError, c.same_quantum, '1', 2)
3078 self.assertRaises(TypeError, c.same_quantum, 1, '2')
3079
3080 def test_scaleb(self):
3081 Decimal = self.decimal.Decimal
3082 Context = self.decimal.Context
3083
3084 c = Context()
3085 d = c.scaleb(Decimal(1), Decimal(2))
3086 self.assertEqual(c.scaleb(1, 2), d)
3087 self.assertEqual(c.scaleb(Decimal(1), 2), d)
3088 self.assertEqual(c.scaleb(1, Decimal(2)), d)
3089 self.assertRaises(TypeError, c.scaleb, '1', 2)
3090 self.assertRaises(TypeError, c.scaleb, 1, '2')
3091
3092 def test_shift(self):
3093 Decimal = self.decimal.Decimal
3094 Context = self.decimal.Context
3095
3096 c = Context()
3097 d = c.shift(Decimal(1), Decimal(2))
3098 self.assertEqual(c.shift(1, 2), d)
3099 self.assertEqual(c.shift(Decimal(1), 2), d)
3100 self.assertEqual(c.shift(1, Decimal(2)), d)
3101 self.assertRaises(TypeError, c.shift, '1', 2)
3102 self.assertRaises(TypeError, c.shift, 1, '2')
3103
3104 def test_subtract(self):
3105 Decimal = self.decimal.Decimal
3106 Context = self.decimal.Context
3107
3108 c = Context()
3109 d = c.subtract(Decimal(1), Decimal(2))
3110 self.assertEqual(c.subtract(1, 2), d)
3111 self.assertEqual(c.subtract(Decimal(1), 2), d)
3112 self.assertEqual(c.subtract(1, Decimal(2)), d)
3113 self.assertRaises(TypeError, c.subtract, '1', 2)
3114 self.assertRaises(TypeError, c.subtract, 1, '2')
3115
3116 def test_to_eng_string(self):
3117 Decimal = self.decimal.Decimal
3118 Context = self.decimal.Context
3119
3120 c = Context()
3121 d = c.to_eng_string(Decimal(10))
3122 self.assertEqual(c.to_eng_string(10), d)
3123 self.assertRaises(TypeError, c.to_eng_string, '10')
3124
3125 def test_to_sci_string(self):
3126 Decimal = self.decimal.Decimal
3127 Context = self.decimal.Context
3128
3129 c = Context()
3130 d = c.to_sci_string(Decimal(10))
3131 self.assertEqual(c.to_sci_string(10), d)
3132 self.assertRaises(TypeError, c.to_sci_string, '10')
3133
3134 def test_to_integral_exact(self):
3135 Decimal = self.decimal.Decimal
3136 Context = self.decimal.Context
3137
3138 c = Context()
3139 d = c.to_integral_exact(Decimal(10))
3140 self.assertEqual(c.to_integral_exact(10), d)
3141 self.assertRaises(TypeError, c.to_integral_exact, '10')
3142
3143 def test_to_integral_value(self):
3144 Decimal = self.decimal.Decimal
3145 Context = self.decimal.Context
3146
3147 c = Context()
3148 d = c.to_integral_value(Decimal(10))
3149 self.assertEqual(c.to_integral_value(10), d)
3150 self.assertRaises(TypeError, c.to_integral_value, '10')
3151 self.assertRaises(TypeError, c.to_integral_value, 10, 'x')
3152
3153class CContextAPItests(ContextAPItests):
3154 decimal = C
3155class PyContextAPItests(ContextAPItests):
3156 decimal = P
3157
3158class ContextWithStatement(unittest.TestCase):
3159 # Can't do these as docstrings until Python 2.6
3160 # as doctest can't handle __future__ statements
3161
3162 def test_localcontext(self):
3163 # Use a copy of the current context in the block
3164 getcontext = self.decimal.getcontext
3165 localcontext = self.decimal.localcontext
3166
3167 orig_ctx = getcontext()
3168 with localcontext() as enter_ctx:
3169 set_ctx = getcontext()
3170 final_ctx = getcontext()
3171 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
3172 self.assertIsNot(orig_ctx, set_ctx, 'did not copy the context')
3173 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
3174
3175 def test_localcontextarg(self):
3176 # Use a copy of the supplied context in the block
3177 Context = self.decimal.Context
3178 getcontext = self.decimal.getcontext
3179 localcontext = self.decimal.localcontext
3180
3181 localcontext = self.decimal.localcontext
3182 orig_ctx = getcontext()
3183 new_ctx = Context(prec=42)
3184 with localcontext(new_ctx) as enter_ctx:
3185 set_ctx = getcontext()
3186 final_ctx = getcontext()
3187 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
3188 self.assertEqual(set_ctx.prec, new_ctx.prec, 'did not set correct context')
3189 self.assertIsNot(new_ctx, set_ctx, 'did not copy the context')
3190 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
3191
3192 def test_nested_with_statements(self):
3193 # Use a copy of the supplied context in the block
3194 Decimal = self.decimal.Decimal
3195 Context = self.decimal.Context
3196 getcontext = self.decimal.getcontext
3197 localcontext = self.decimal.localcontext
3198 Clamped = self.decimal.Clamped
3199 Overflow = self.decimal.Overflow
3200
3201 orig_ctx = getcontext()
3202 orig_ctx.clear_flags()
3203 new_ctx = Context(Emax=384)
3204 with localcontext() as c1:
3205 self.assertEqual(c1.flags, orig_ctx.flags)
3206 self.assertEqual(c1.traps, orig_ctx.traps)
3207 c1.traps[Clamped] = True
3208 c1.Emin = -383
3209 self.assertNotEqual(orig_ctx.Emin, -383)
3210 self.assertRaises(Clamped, c1.create_decimal, '0e-999')
3211 self.assertTrue(c1.flags[Clamped])
3212 with localcontext(new_ctx) as c2:
3213 self.assertEqual(c2.flags, new_ctx.flags)
3214 self.assertEqual(c2.traps, new_ctx.traps)
3215 self.assertRaises(Overflow, c2.power, Decimal('3.4e200'), 2)
3216 self.assertFalse(c2.flags[Clamped])
3217 self.assertTrue(c2.flags[Overflow])
3218 del c2
3219 self.assertFalse(c1.flags[Overflow])
3220 del c1
3221 self.assertNotEqual(orig_ctx.Emin, -383)
3222 self.assertFalse(orig_ctx.flags[Clamped])
3223 self.assertFalse(orig_ctx.flags[Overflow])
3224 self.assertFalse(new_ctx.flags[Clamped])
3225 self.assertFalse(new_ctx.flags[Overflow])
3226
3227 def test_with_statements_gc1(self):
3228 localcontext = self.decimal.localcontext
3229
3230 with localcontext() as c1:
3231 del c1
3232 with localcontext() as c2:
3233 del c2
3234 with localcontext() as c3:
3235 del c3
3236 with localcontext() as c4:
3237 del c4
3238
3239 def test_with_statements_gc2(self):
3240 localcontext = self.decimal.localcontext
3241
3242 with localcontext() as c1:
3243 with localcontext(c1) as c2:
3244 del c1
3245 with localcontext(c2) as c3:
3246 del c2
3247 with localcontext(c3) as c4:
3248 del c3
3249 del c4
3250
3251 def test_with_statements_gc3(self):
3252 Context = self.decimal.Context
3253 localcontext = self.decimal.localcontext
3254 getcontext = self.decimal.getcontext
3255 setcontext = self.decimal.setcontext
3256
3257 with localcontext() as c1:
3258 del c1
3259 n1 = Context(prec=1)
3260 setcontext(n1)
3261 with localcontext(n1) as c2:
3262 del n1
3263 self.assertEqual(c2.prec, 1)
3264 del c2
3265 n2 = Context(prec=2)
3266 setcontext(n2)
3267 del n2
3268 self.assertEqual(getcontext().prec, 2)
3269 n3 = Context(prec=3)
3270 setcontext(n3)
3271 self.assertEqual(getcontext().prec, 3)
3272 with localcontext(n3) as c3:
3273 del n3
3274 self.assertEqual(c3.prec, 3)
3275 del c3
3276 n4 = Context(prec=4)
3277 setcontext(n4)
3278 del n4
3279 self.assertEqual(getcontext().prec, 4)
3280 with localcontext() as c4:
3281 self.assertEqual(c4.prec, 4)
3282 del c4
3283
3284class CContextWithStatement(ContextWithStatement):
3285 decimal = C
3286class PyContextWithStatement(ContextWithStatement):
3287 decimal = P
3288
3289class ContextFlags(unittest.TestCase):
3290
3291 def test_flags_irrelevant(self):
3292 # check that the result (numeric result + flags raised) of an
3293 # arithmetic operation doesn't depend on the current flags
3294 Decimal = self.decimal.Decimal
3295 Context = self.decimal.Context
3296 Inexact = self.decimal.Inexact
3297 Rounded = self.decimal.Rounded
3298 Underflow = self.decimal.Underflow
3299 Clamped = self.decimal.Clamped
3300 Subnormal = self.decimal.Subnormal
3301 ROUND_HALF_EVEN = self.decimal.ROUND_HALF_EVEN
3302
3303 def raise_error(context, flag):
3304 if self.decimal == C:
3305 context.flags[flag] = True
3306 if context.traps[flag]:
3307 raise flag
3308 else:
3309 context._raise_error(flag)
3310
3311 context = Context(prec=9, Emin = -425000000, Emax = 425000000,
3312 rounding=ROUND_HALF_EVEN, traps=[], flags=[])
3313
3314 # operations that raise various flags, in the form (function, arglist)
3315 operations = [
3316 (context._apply, [Decimal("100E-425000010")]),
3317 (context.sqrt, [Decimal(2)]),
3318 (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]),
3319 (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]),
3320 (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]),
3321 ]
3322
3323 # try various flags individually, then a whole lot at once
3324 flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal],
3325 [Inexact, Rounded, Underflow, Clamped, Subnormal]]
3326
3327 for fn, args in operations:
3328 # find answer and flags raised using a clean context
3329 context.clear_flags()
3330 ans = fn(*args)
3331 flags = [k for k, v in context.flags.items() if v]
3332
3333 for extra_flags in flagsets:
3334 # set flags, before calling operation
3335 context.clear_flags()
3336 for flag in extra_flags:
3337 raise_error(context, flag)
3338 new_ans = fn(*args)
3339
3340 # flags that we expect to be set after the operation
3341 expected_flags = list(flags)
3342 for flag in extra_flags:
3343 if flag not in expected_flags:
3344 expected_flags.append(flag)
3345 expected_flags.sort(key=id)
3346
3347 # flags we actually got
3348 new_flags = [k for k,v in context.flags.items() if v]
3349 new_flags.sort(key=id)
3350
3351 self.assertEqual(ans, new_ans,
3352 "operation produces different answers depending on flags set: " +
3353 "expected %s, got %s." % (ans, new_ans))
3354 self.assertEqual(new_flags, expected_flags,
3355 "operation raises different flags depending on flags set: " +
3356 "expected %s, got %s" % (expected_flags, new_flags))
3357
3358 def test_flag_comparisons(self):
3359 Context = self.decimal.Context
3360 Inexact = self.decimal.Inexact
3361 Rounded = self.decimal.Rounded
3362
3363 c = Context()
3364
3365 # Valid SignalDict
3366 self.assertNotEqual(c.flags, c.traps)
3367 self.assertNotEqual(c.traps, c.flags)
3368
3369 c.flags = c.traps
3370 self.assertEqual(c.flags, c.traps)
3371 self.assertEqual(c.traps, c.flags)
3372
3373 c.flags[Rounded] = True
3374 c.traps = c.flags
3375 self.assertEqual(c.flags, c.traps)
3376 self.assertEqual(c.traps, c.flags)
3377
3378 d = {}
3379 d.update(c.flags)
3380 self.assertEqual(d, c.flags)
3381 self.assertEqual(c.flags, d)
3382
3383 d[Inexact] = True
3384 self.assertNotEqual(d, c.flags)
3385 self.assertNotEqual(c.flags, d)
3386
3387 # Invalid SignalDict
3388 d = {Inexact:False}
3389 self.assertNotEqual(d, c.flags)
3390 self.assertNotEqual(c.flags, d)
3391
3392 d = ["xyz"]
3393 self.assertNotEqual(d, c.flags)
3394 self.assertNotEqual(c.flags, d)
3395
3396 @requires_IEEE_754
3397 def test_float_operation(self):
3398 Decimal = self.decimal.Decimal
3399 FloatOperation = self.decimal.FloatOperation
3400 localcontext = self.decimal.localcontext
3401
3402 with localcontext() as c:
3403 ##### trap is off by default
3404 self.assertFalse(c.traps[FloatOperation])
3405
3406 # implicit conversion sets the flag
3407 c.clear_flags()
3408 self.assertEqual(Decimal(7.5), 7.5)
3409 self.assertTrue(c.flags[FloatOperation])
3410
3411 c.clear_flags()
3412 self.assertEqual(c.create_decimal(7.5), 7.5)
3413 self.assertTrue(c.flags[FloatOperation])
3414
3415 # explicit conversion does not set the flag
3416 c.clear_flags()
3417 x = Decimal.from_float(7.5)
3418 self.assertFalse(c.flags[FloatOperation])
3419 # comparison sets the flag
3420 self.assertEqual(x, 7.5)
3421 self.assertTrue(c.flags[FloatOperation])
3422
3423 c.clear_flags()
3424 x = c.create_decimal_from_float(7.5)
3425 self.assertFalse(c.flags[FloatOperation])
3426 self.assertEqual(x, 7.5)
3427 self.assertTrue(c.flags[FloatOperation])
3428
3429 ##### set the trap
3430 c.traps[FloatOperation] = True
3431
3432 # implicit conversion raises
3433 c.clear_flags()
3434 self.assertRaises(FloatOperation, Decimal, 7.5)
3435 self.assertTrue(c.flags[FloatOperation])
3436
3437 c.clear_flags()
3438 self.assertRaises(FloatOperation, c.create_decimal, 7.5)
3439 self.assertTrue(c.flags[FloatOperation])
3440
3441 # explicit conversion is silent
3442 c.clear_flags()
3443 x = Decimal.from_float(7.5)
3444 self.assertFalse(c.flags[FloatOperation])
3445
3446 c.clear_flags()
3447 x = c.create_decimal_from_float(7.5)
3448 self.assertFalse(c.flags[FloatOperation])
3449
3450 def test_float_comparison(self):
3451 Decimal = self.decimal.Decimal
3452 Context = self.decimal.Context
3453 FloatOperation = self.decimal.FloatOperation
3454 localcontext = self.decimal.localcontext
3455
3456 def assert_attr(a, b, attr, context, signal=None):
3457 context.clear_flags()
3458 f = getattr(a, attr)
3459 if signal == FloatOperation:
3460 self.assertRaises(signal, f, b)
3461 else:
3462 self.assertIs(f(b), True)
3463 self.assertTrue(context.flags[FloatOperation])
3464
3465 small_d = Decimal('0.25')
3466 big_d = Decimal('3.0')
3467 small_f = 0.25
3468 big_f = 3.0
3469
3470 zero_d = Decimal('0.0')
3471 neg_zero_d = Decimal('-0.0')
3472 zero_f = 0.0
3473 neg_zero_f = -0.0
3474
3475 inf_d = Decimal('Infinity')
3476 neg_inf_d = Decimal('-Infinity')
3477 inf_f = float('inf')
3478 neg_inf_f = float('-inf')
3479
3480 def doit(c, signal=None):
3481 # Order
3482 for attr in '__lt__', '__le__':
3483 assert_attr(small_d, big_f, attr, c, signal)
3484
3485 for attr in '__gt__', '__ge__':
3486 assert_attr(big_d, small_f, attr, c, signal)
3487
3488 # Equality
3489 assert_attr(small_d, small_f, '__eq__', c, None)
3490
3491 assert_attr(neg_zero_d, neg_zero_f, '__eq__', c, None)
3492 assert_attr(neg_zero_d, zero_f, '__eq__', c, None)
3493
3494 assert_attr(zero_d, neg_zero_f, '__eq__', c, None)
3495 assert_attr(zero_d, zero_f, '__eq__', c, None)
3496
3497 assert_attr(neg_inf_d, neg_inf_f, '__eq__', c, None)
3498 assert_attr(inf_d, inf_f, '__eq__', c, None)
3499
3500 # Inequality
3501 assert_attr(small_d, big_f, '__ne__', c, None)
3502
3503 assert_attr(Decimal('0.1'), 0.1, '__ne__', c, None)
3504
3505 assert_attr(neg_inf_d, inf_f, '__ne__', c, None)
3506 assert_attr(inf_d, neg_inf_f, '__ne__', c, None)
3507
3508 assert_attr(Decimal('NaN'), float('nan'), '__ne__', c, None)
3509
3510 def test_containers(c, signal=None):
3511 c.clear_flags()
3512 s = set([100.0, Decimal('100.0')])
3513 self.assertEqual(len(s), 1)
3514 self.assertTrue(c.flags[FloatOperation])
3515
3516 c.clear_flags()
3517 if signal:
3518 self.assertRaises(signal, sorted, [1.0, Decimal('10.0')])
3519 else:
3520 s = sorted([10.0, Decimal('10.0')])
3521 self.assertTrue(c.flags[FloatOperation])
3522
3523 c.clear_flags()
3524 b = 10.0 in [Decimal('10.0'), 1.0]
3525 self.assertTrue(c.flags[FloatOperation])
3526
3527 c.clear_flags()
3528 b = 10.0 in {Decimal('10.0'):'a', 1.0:'b'}
3529 self.assertTrue(c.flags[FloatOperation])
3530
3531 nc = Context()
3532 with localcontext(nc) as c:
3533 self.assertFalse(c.traps[FloatOperation])
3534 doit(c, signal=None)
3535 test_containers(c, signal=None)
3536
3537 c.traps[FloatOperation] = True
3538 doit(c, signal=FloatOperation)
3539 test_containers(c, signal=FloatOperation)
3540
3541 def test_float_operation_default(self):
3542 Decimal = self.decimal.Decimal
3543 Context = self.decimal.Context
3544 Inexact = self.decimal.Inexact
3545 FloatOperation= self.decimal.FloatOperation
3546
3547 context = Context()
3548 self.assertFalse(context.flags[FloatOperation])
3549 self.assertFalse(context.traps[FloatOperation])
3550
3551 context.clear_traps()
3552 context.traps[Inexact] = True
3553 context.traps[FloatOperation] = True
3554 self.assertTrue(context.traps[FloatOperation])
3555 self.assertTrue(context.traps[Inexact])
3556
3557class CContextFlags(ContextFlags):
3558 decimal = C
3559class PyContextFlags(ContextFlags):
3560 decimal = P
3561
3562class SpecialContexts(unittest.TestCase):
3563 """Test the context templates."""
3564
3565 def test_context_templates(self):
3566 BasicContext = self.decimal.BasicContext
3567 ExtendedContext = self.decimal.ExtendedContext
3568 getcontext = self.decimal.getcontext
3569 setcontext = self.decimal.setcontext
3570 InvalidOperation = self.decimal.InvalidOperation
3571 DivisionByZero = self.decimal.DivisionByZero
3572 Overflow = self.decimal.Overflow
3573 Underflow = self.decimal.Underflow
3574 Clamped = self.decimal.Clamped
3575
3576 assert_signals(self, BasicContext, 'traps',
3577 [InvalidOperation, DivisionByZero, Overflow, Underflow, Clamped]
3578 )
3579
3580 savecontext = getcontext().copy()
3581 basic_context_prec = BasicContext.prec
3582 extended_context_prec = ExtendedContext.prec
3583
3584 ex = None
3585 try:
3586 BasicContext.prec = ExtendedContext.prec = 441
3587 for template in BasicContext, ExtendedContext:
3588 setcontext(template)
3589 c = getcontext()
3590 self.assertIsNot(c, template)
3591 self.assertEqual(c.prec, 441)
3592 except Exception as e:
3593 ex = e.__class__
3594 finally:
3595 BasicContext.prec = basic_context_prec
3596 ExtendedContext.prec = extended_context_prec
3597 setcontext(savecontext)
3598 if ex:
3599 raise ex
3600
3601 def test_default_context(self):
3602 DefaultContext = self.decimal.DefaultContext
3603 BasicContext = self.decimal.BasicContext
3604 ExtendedContext = self.decimal.ExtendedContext
3605 getcontext = self.decimal.getcontext
3606 setcontext = self.decimal.setcontext
3607 InvalidOperation = self.decimal.InvalidOperation
3608 DivisionByZero = self.decimal.DivisionByZero
3609 Overflow = self.decimal.Overflow
3610
3611 self.assertEqual(BasicContext.prec, 9)
3612 self.assertEqual(ExtendedContext.prec, 9)
3613
3614 assert_signals(self, DefaultContext, 'traps',
3615 [InvalidOperation, DivisionByZero, Overflow]
3616 )
3617
3618 savecontext = getcontext().copy()
3619 default_context_prec = DefaultContext.prec
3620
3621 ex = None
3622 try:
3623 c = getcontext()
3624 saveprec = c.prec
3625
3626 DefaultContext.prec = 961
3627 c = getcontext()
3628 self.assertEqual(c.prec, saveprec)
3629
3630 setcontext(DefaultContext)
3631 c = getcontext()
3632 self.assertIsNot(c, DefaultContext)
3633 self.assertEqual(c.prec, 961)
3634 except Exception as e:
3635 ex = e.__class__
3636 finally:
3637 DefaultContext.prec = default_context_prec
3638 setcontext(savecontext)
3639 if ex:
3640 raise ex
3641
3642class CSpecialContexts(SpecialContexts):
3643 decimal = C
3644class PySpecialContexts(SpecialContexts):
3645 decimal = P
3646
3647class ContextInputValidation(unittest.TestCase):
3648
3649 def test_invalid_context(self):
3650 Context = self.decimal.Context
3651 DefaultContext = self.decimal.DefaultContext
3652
3653 c = DefaultContext.copy()
3654
3655 # prec, Emax
3656 for attr in ['prec', 'Emax']:
3657 setattr(c, attr, 999999)
3658 self.assertEqual(getattr(c, attr), 999999)
3659 self.assertRaises(ValueError, setattr, c, attr, -1)
3660 self.assertRaises(TypeError, setattr, c, attr, 'xyz')
3661
3662 # Emin
3663 setattr(c, 'Emin', -999999)
3664 self.assertEqual(getattr(c, 'Emin'), -999999)
3665 self.assertRaises(ValueError, setattr, c, 'Emin', 1)
3666 self.assertRaises(TypeError, setattr, c, 'Emin', (1,2,3))
3667
3668 # rounding: always raise TypeError in order to get consistent
3669 # exceptions across implementations. In decimal, rounding
3670 # modes are strings, in _decimal they are integers. The idea
3671 # is to view rounding as an abstract type and not mind the
3672 # implementation details.
3673 # Hence, a user should view the rounding modes as if they
3674 # had been defined in a language that supports abstract
3675 # data types, e.g. ocaml:
3676 #
3677 # type rounding = ROUND_DOWN | ROUND_HALF_UP | ... ;;
3678 #
3679 self.assertRaises(TypeError, setattr, c, 'rounding', -1)
3680 self.assertRaises(TypeError, setattr, c, 'rounding', 9)
3681 self.assertRaises(TypeError, setattr, c, 'rounding', 1.0)
3682 self.assertRaises(TypeError, setattr, c, 'rounding', 'xyz')
3683
3684 # capitals, clamp
3685 for attr in ['capitals', 'clamp']:
3686 self.assertRaises(ValueError, setattr, c, attr, -1)
3687 self.assertRaises(ValueError, setattr, c, attr, 2)
3688 self.assertRaises(TypeError, setattr, c, attr, [1,2,3])
3689
3690 # Invalid attribute
3691 self.assertRaises(AttributeError, setattr, c, 'emax', 100)
3692
3693 # Invalid signal dict
3694 self.assertRaises(TypeError, setattr, c, 'flags', [])
3695 self.assertRaises(KeyError, setattr, c, 'flags', {})
3696 self.assertRaises(KeyError, setattr, c, 'traps',
3697 {'InvalidOperation':0})
3698
3699 # Attributes cannot be deleted
3700 for attr in ['prec', 'Emax', 'Emin', 'rounding', 'capitals', 'clamp',
3701 'flags', 'traps']:
3702 self.assertRaises(AttributeError, c.__delattr__, attr)
3703
3704 # Invalid attributes
3705 self.assertRaises(TypeError, getattr, c, 9)
3706 self.assertRaises(TypeError, setattr, c, 9)
3707
3708 # Invalid values in constructor
3709 self.assertRaises(TypeError, Context, rounding=999999)
3710 self.assertRaises(TypeError, Context, rounding='xyz')
3711 self.assertRaises(ValueError, Context, clamp=2)
3712 self.assertRaises(ValueError, Context, capitals=-1)
3713 self.assertRaises(KeyError, Context, flags=["P"])
3714 self.assertRaises(KeyError, Context, traps=["Q"])
3715
3716 # Type error in conversion
3717 self.assertRaises(TypeError, Context, flags=(0,1))
3718 self.assertRaises(TypeError, Context, traps=(1,0))
3719
3720class CContextInputValidation(ContextInputValidation):
3721 decimal = C
3722class PyContextInputValidation(ContextInputValidation):
3723 decimal = P
3724
3725class ContextSubclassing(unittest.TestCase):
3726
3727 def test_context_subclassing(self):
3728 decimal = self.decimal
3729 Decimal = decimal.Decimal
3730 Context = decimal.Context
3731 ROUND_HALF_EVEN = decimal.ROUND_HALF_EVEN
3732 ROUND_DOWN = decimal.ROUND_DOWN
3733 Clamped = decimal.Clamped
3734 DivisionByZero = decimal.DivisionByZero
3735 Inexact = decimal.Inexact
3736 Overflow = decimal.Overflow
3737 Rounded = decimal.Rounded
3738 Subnormal = decimal.Subnormal
3739 Underflow = decimal.Underflow
3740 InvalidOperation = decimal.InvalidOperation
3741
3742 class MyContext(Context):
3743 def __init__(self, prec=None, rounding=None, Emin=None, Emax=None,
3744 capitals=None, clamp=None, flags=None,
3745 traps=None):
3746 Context.__init__(self)
3747 if prec is not None:
3748 self.prec = prec
3749 if rounding is not None:
3750 self.rounding = rounding
3751 if Emin is not None:
3752 self.Emin = Emin
3753 if Emax is not None:
3754 self.Emax = Emax
3755 if capitals is not None:
3756 self.capitals = capitals
3757 if clamp is not None:
3758 self.clamp = clamp
3759 if flags is not None:
3760 if isinstance(flags, list):
3761 flags = {v:(v in flags) for v in OrderedSignals[decimal] + flags}
3762 self.flags = flags
3763 if traps is not None:
3764 if isinstance(traps, list):
3765 traps = {v:(v in traps) for v in OrderedSignals[decimal] + traps}
3766 self.traps = traps
3767
3768 c = Context()
3769 d = MyContext()
3770 for attr in ('prec', 'rounding', 'Emin', 'Emax', 'capitals', 'clamp',
3771 'flags', 'traps'):
3772 self.assertEqual(getattr(c, attr), getattr(d, attr))
3773
3774 # prec
3775 self.assertRaises(ValueError, MyContext, **{'prec':-1})
3776 c = MyContext(prec=1)
3777 self.assertEqual(c.prec, 1)
3778 self.assertRaises(InvalidOperation, c.quantize, Decimal('9e2'), 0)
3779
3780 # rounding
3781 self.assertRaises(TypeError, MyContext, **{'rounding':'XYZ'})
3782 c = MyContext(rounding=ROUND_DOWN, prec=1)
3783 self.assertEqual(c.rounding, ROUND_DOWN)
3784 self.assertEqual(c.plus(Decimal('9.9')), 9)
3785
3786 # Emin
3787 self.assertRaises(ValueError, MyContext, **{'Emin':5})
3788 c = MyContext(Emin=-1, prec=1)
3789 self.assertEqual(c.Emin, -1)
3790 x = c.add(Decimal('1e-99'), Decimal('2.234e-2000'))
3791 self.assertEqual(x, Decimal('0.0'))
3792 for signal in (Inexact, Underflow, Subnormal, Rounded, Clamped):
3793 self.assertTrue(c.flags[signal])
3794
3795 # Emax
3796 self.assertRaises(ValueError, MyContext, **{'Emax':-1})
3797 c = MyContext(Emax=1, prec=1)
3798 self.assertEqual(c.Emax, 1)
3799 self.assertRaises(Overflow, c.add, Decimal('1e99'), Decimal('2.234e2000'))
3800 if self.decimal == C:
3801 for signal in (Inexact, Overflow, Rounded):
3802 self.assertTrue(c.flags[signal])
3803
3804 # capitals
3805 self.assertRaises(ValueError, MyContext, **{'capitals':-1})
3806 c = MyContext(capitals=0)
3807 self.assertEqual(c.capitals, 0)
3808 x = c.create_decimal('1E222')
3809 self.assertEqual(c.to_sci_string(x), '1e+222')
3810
3811 # clamp
3812 self.assertRaises(ValueError, MyContext, **{'clamp':2})
3813 c = MyContext(clamp=1, Emax=99)
3814 self.assertEqual(c.clamp, 1)
3815 x = c.plus(Decimal('1e99'))
3816 self.assertEqual(str(x), '1.000000000000000000000000000E+99')
3817
3818 # flags
3819 self.assertRaises(TypeError, MyContext, **{'flags':'XYZ'})
3820 c = MyContext(flags=[Rounded, DivisionByZero])
3821 for signal in (Rounded, DivisionByZero):
3822 self.assertTrue(c.flags[signal])
3823 c.clear_flags()
3824 for signal in OrderedSignals[decimal]:
3825 self.assertFalse(c.flags[signal])
3826
3827 # traps
3828 self.assertRaises(TypeError, MyContext, **{'traps':'XYZ'})
3829 c = MyContext(traps=[Rounded, DivisionByZero])
3830 for signal in (Rounded, DivisionByZero):
3831 self.assertTrue(c.traps[signal])
3832 c.clear_traps()
3833 for signal in OrderedSignals[decimal]:
3834 self.assertFalse(c.traps[signal])
3835
3836class CContextSubclassing(ContextSubclassing):
3837 decimal = C
3838class PyContextSubclassing(ContextSubclassing):
3839 decimal = P
3840
3841@skip_if_extra_functionality
3842class CheckAttributes(unittest.TestCase):
3843
3844 def test_module_attributes(self):
3845
3846 # Architecture dependent context limits
3847 self.assertEqual(C.MAX_PREC, P.MAX_PREC)
3848 self.assertEqual(C.MAX_EMAX, P.MAX_EMAX)
3849 self.assertEqual(C.MIN_EMIN, P.MIN_EMIN)
3850 self.assertEqual(C.MIN_ETINY, P.MIN_ETINY)
3851
3852 self.assertTrue(C.HAVE_THREADS is True or C.HAVE_THREADS is False)
3853 self.assertTrue(P.HAVE_THREADS is True or P.HAVE_THREADS is False)
3854
3855 self.assertEqual(C.__version__, P.__version__)
3856
3857 x = dir(C)
3858 y = [s for s in dir(P) if '__' in s or not s.startswith('_')]
Stefan Krahfe17b2b2012-03-25 18:59:21 +02003859 self.assertEqual(set(x) - set(y), set())
Stefan Krah1919b7e2012-03-21 18:25:23 +01003860
3861 def test_context_attributes(self):
3862
3863 x = [s for s in dir(C.Context()) if '__' in s or not s.startswith('_')]
3864 y = [s for s in dir(P.Context()) if '__' in s or not s.startswith('_')]
3865 self.assertEqual(set(x) - set(y), set())
3866
3867 def test_decimal_attributes(self):
3868
3869 x = [s for s in dir(C.Decimal(9)) if '__' in s or not s.startswith('_')]
3870 y = [s for s in dir(C.Decimal(9)) if '__' in s or not s.startswith('_')]
3871 self.assertEqual(set(x) - set(y), set())
3872
3873class Coverage(unittest.TestCase):
3874
3875 def test_adjusted(self):
3876 Decimal = self.decimal.Decimal
3877
3878 self.assertEqual(Decimal('1234e9999').adjusted(), 10002)
3879 # XXX raise?
3880 self.assertEqual(Decimal('nan').adjusted(), 0)
3881 self.assertEqual(Decimal('inf').adjusted(), 0)
3882
3883 def test_canonical(self):
3884 Decimal = self.decimal.Decimal
3885 getcontext = self.decimal.getcontext
3886
3887 x = Decimal(9).canonical()
3888 self.assertEqual(x, 9)
3889
3890 c = getcontext()
3891 x = c.canonical(Decimal(9))
3892 self.assertEqual(x, 9)
3893
3894 def test_context_repr(self):
3895 c = self.decimal.DefaultContext.copy()
3896
3897 c.prec = 425000000
3898 c.Emax = 425000000
3899 c.Emin = -425000000
3900 c.rounding = self.decimal.ROUND_HALF_DOWN
3901 c.capitals = 0
3902 c.clamp = 1
3903 for sig in OrderedSignals[self.decimal]:
3904 c.flags[sig] = False
3905 c.traps[sig] = False
3906
3907 s = c.__repr__()
3908 t = "Context(prec=425000000, rounding=ROUND_HALF_DOWN, " \
3909 "Emin=-425000000, Emax=425000000, capitals=0, clamp=1, " \
3910 "flags=[], traps=[])"
3911 self.assertEqual(s, t)
3912
3913 def test_implicit_context(self):
3914 Decimal = self.decimal.Decimal
3915 localcontext = self.decimal.localcontext
3916
3917 with localcontext() as c:
3918 c.prec = 1
3919 c.Emax = 1
3920 c.Emin = -1
3921
3922 # abs
3923 self.assertEqual(abs(Decimal("-10")), 10)
3924 # add
3925 self.assertEqual(Decimal("7") + 1, 8)
3926 # divide
3927 self.assertEqual(Decimal("10") / 5, 2)
3928 # divide_int
3929 self.assertEqual(Decimal("10") // 7, 1)
3930 # fma
3931 self.assertEqual(Decimal("1.2").fma(Decimal("0.01"), 1), 1)
3932 self.assertIs(Decimal("NaN").fma(7, 1).is_nan(), True)
3933 # three arg power
3934 self.assertEqual(pow(Decimal(10), 2, 7), 2)
3935 # exp
3936 self.assertEqual(Decimal("1.01").exp(), 3)
3937 # is_normal
3938 self.assertIs(Decimal("0.01").is_normal(), False)
3939 # is_subnormal
3940 self.assertIs(Decimal("0.01").is_subnormal(), True)
3941 # ln
3942 self.assertEqual(Decimal("20").ln(), 3)
3943 # log10
3944 self.assertEqual(Decimal("20").log10(), 1)
3945 # logb
3946 self.assertEqual(Decimal("580").logb(), 2)
3947 # logical_invert
3948 self.assertEqual(Decimal("10").logical_invert(), 1)
3949 # minus
3950 self.assertEqual(-Decimal("-10"), 10)
3951 # multiply
3952 self.assertEqual(Decimal("2") * 4, 8)
3953 # next_minus
3954 self.assertEqual(Decimal("10").next_minus(), 9)
3955 # next_plus
3956 self.assertEqual(Decimal("10").next_plus(), Decimal('2E+1'))
3957 # normalize
3958 self.assertEqual(Decimal("-10").normalize(), Decimal('-1E+1'))
3959 # number_class
3960 self.assertEqual(Decimal("10").number_class(), '+Normal')
3961 # plus
3962 self.assertEqual(+Decimal("-1"), -1)
3963 # remainder
3964 self.assertEqual(Decimal("10") % 7, 3)
3965 # subtract
3966 self.assertEqual(Decimal("10") - 7, 3)
3967 # to_integral_exact
3968 self.assertEqual(Decimal("1.12345").to_integral_exact(), 1)
3969
3970 # Boolean functions
3971 self.assertTrue(Decimal("1").is_canonical())
3972 self.assertTrue(Decimal("1").is_finite())
3973 self.assertTrue(Decimal("1").is_finite())
3974 self.assertTrue(Decimal("snan").is_snan())
3975 self.assertTrue(Decimal("-1").is_signed())
3976 self.assertTrue(Decimal("0").is_zero())
3977 self.assertTrue(Decimal("0").is_zero())
3978
3979 # Copy
3980 with localcontext() as c:
3981 c.prec = 10000
3982 x = 1228 ** 1523
3983 y = -Decimal(x)
3984
3985 z = y.copy_abs()
3986 self.assertEqual(z, x)
3987
3988 z = y.copy_negate()
3989 self.assertEqual(z, x)
3990
3991 z = y.copy_sign(Decimal(1))
3992 self.assertEqual(z, x)
3993
3994 def test_divmod(self):
3995 Decimal = self.decimal.Decimal
3996 localcontext = self.decimal.localcontext
3997 InvalidOperation = self.decimal.InvalidOperation
3998 DivisionByZero = self.decimal.DivisionByZero
3999
4000 with localcontext() as c:
4001 q, r = divmod(Decimal("10912837129"), 1001)
4002 self.assertEqual(q, Decimal('10901935'))
4003 self.assertEqual(r, Decimal('194'))
4004
4005 q, r = divmod(Decimal("NaN"), 7)
4006 self.assertTrue(q.is_nan() and r.is_nan())
4007
4008 c.traps[InvalidOperation] = False
4009 q, r = divmod(Decimal("NaN"), 7)
4010 self.assertTrue(q.is_nan() and r.is_nan())
4011
4012 c.traps[InvalidOperation] = False
4013 c.clear_flags()
4014 q, r = divmod(Decimal("inf"), Decimal("inf"))
4015 self.assertTrue(q.is_nan() and r.is_nan())
4016 self.assertTrue(c.flags[InvalidOperation])
4017
4018 c.clear_flags()
4019 q, r = divmod(Decimal("inf"), 101)
4020 self.assertTrue(q.is_infinite() and r.is_nan())
4021 self.assertTrue(c.flags[InvalidOperation])
4022
4023 c.clear_flags()
4024 q, r = divmod(Decimal(0), 0)
4025 self.assertTrue(q.is_nan() and r.is_nan())
4026 self.assertTrue(c.flags[InvalidOperation])
4027
4028 c.traps[DivisionByZero] = False
4029 c.clear_flags()
4030 q, r = divmod(Decimal(11), 0)
4031 self.assertTrue(q.is_infinite() and r.is_nan())
4032 self.assertTrue(c.flags[InvalidOperation] and
4033 c.flags[DivisionByZero])
4034
4035 def test_power(self):
4036 Decimal = self.decimal.Decimal
4037 localcontext = self.decimal.localcontext
4038 Overflow = self.decimal.Overflow
4039 Rounded = self.decimal.Rounded
4040
4041 with localcontext() as c:
4042 c.prec = 3
4043 c.clear_flags()
4044 self.assertEqual(Decimal("1.0") ** 100, Decimal('1.00'))
4045 self.assertTrue(c.flags[Rounded])
4046
4047 c.prec = 1
4048 c.Emax = 1
4049 c.Emin = -1
4050 c.clear_flags()
4051 c.traps[Overflow] = False
4052 self.assertEqual(Decimal(10000) ** Decimal("0.5"), Decimal('inf'))
4053 self.assertTrue(c.flags[Overflow])
4054
4055 def test_quantize(self):
4056 Decimal = self.decimal.Decimal
4057 localcontext = self.decimal.localcontext
4058 InvalidOperation = self.decimal.InvalidOperation
4059
4060 with localcontext() as c:
4061 c.prec = 1
4062 c.Emax = 1
4063 c.Emin = -1
4064 c.traps[InvalidOperation] = False
4065 x = Decimal(99).quantize(Decimal("1e1"))
4066 self.assertTrue(x.is_nan())
4067
4068 def test_radix(self):
4069 Decimal = self.decimal.Decimal
4070 getcontext = self.decimal.getcontext
4071
4072 c = getcontext()
4073 self.assertEqual(Decimal("1").radix(), 10)
4074 self.assertEqual(c.radix(), 10)
4075
4076 def test_rop(self):
4077 Decimal = self.decimal.Decimal
4078
4079 for attr in ('__radd__', '__rsub__', '__rmul__', '__rtruediv__',
4080 '__rdivmod__', '__rmod__', '__rfloordiv__', '__rpow__'):
4081 self.assertIs(getattr(Decimal("1"), attr)("xyz"), NotImplemented)
4082
4083 def test_round(self):
4084 # Python3 behavior: round() returns Decimal
4085 Decimal = self.decimal.Decimal
4086 getcontext = self.decimal.getcontext
4087
4088 c = getcontext()
4089 c.prec = 28
4090
4091 self.assertEqual(str(Decimal("9.99").__round__()), "10")
4092 self.assertEqual(str(Decimal("9.99e-5").__round__()), "0")
4093 self.assertEqual(str(Decimal("1.23456789").__round__(5)), "1.23457")
4094 self.assertEqual(str(Decimal("1.2345").__round__(10)), "1.2345000000")
4095 self.assertEqual(str(Decimal("1.2345").__round__(-10)), "0E+10")
4096
4097 self.assertRaises(TypeError, Decimal("1.23").__round__, "5")
4098 self.assertRaises(TypeError, Decimal("1.23").__round__, 5, 8)
4099
4100 def test_create_decimal(self):
4101 c = self.decimal.Context()
4102 self.assertRaises(ValueError, c.create_decimal, ["%"])
4103
4104 def test_int(self):
4105 Decimal = self.decimal.Decimal
4106 localcontext = self.decimal.localcontext
4107
4108 with localcontext() as c:
4109 c.prec = 9999
4110 x = Decimal(1221**1271) / 10**3923
4111 self.assertEqual(int(x), 1)
4112 self.assertEqual(x.to_integral(), 2)
4113
4114 def test_copy(self):
4115 Context = self.decimal.Context
4116
4117 c = Context()
4118 c.prec = 10000
4119 x = -(1172 ** 1712)
4120
4121 y = c.copy_abs(x)
4122 self.assertEqual(y, -x)
4123
4124 y = c.copy_negate(x)
4125 self.assertEqual(y, -x)
4126
4127 y = c.copy_sign(x, 1)
4128 self.assertEqual(y, -x)
4129
4130class CCoverage(Coverage):
4131 decimal = C
4132class PyCoverage(Coverage):
4133 decimal = P
4134
4135class PyFunctionality(unittest.TestCase):
4136 """Extra functionality in decimal.py"""
4137
4138 def test_py_quantize_watchexp(self):
4139 # watchexp functionality
4140 Decimal = P.Decimal
4141 localcontext = P.localcontext
4142
4143 with localcontext() as c:
4144 c.prec = 1
4145 c.Emax = 1
4146 c.Emin = -1
4147 x = Decimal(99999).quantize(Decimal("1e3"), watchexp=False)
4148 self.assertEqual(x, Decimal('1.00E+5'))
4149
4150 def test_py_alternate_formatting(self):
4151 # triples giving a format, a Decimal, and the expected result
4152 Decimal = P.Decimal
4153 localcontext = P.localcontext
4154
4155 test_values = [
4156 # Issue 7094: Alternate formatting (specified by #)
4157 ('.0e', '1.0', '1e+0'),
4158 ('#.0e', '1.0', '1.e+0'),
4159 ('.0f', '1.0', '1'),
4160 ('#.0f', '1.0', '1.'),
4161 ('g', '1.1', '1.1'),
4162 ('#g', '1.1', '1.1'),
4163 ('.0g', '1', '1'),
4164 ('#.0g', '1', '1.'),
4165 ('.0%', '1.0', '100%'),
4166 ('#.0%', '1.0', '100.%'),
4167 ]
4168 for fmt, d, result in test_values:
4169 self.assertEqual(format(Decimal(d), fmt), result)
4170
4171class PyWhitebox(unittest.TestCase):
4172 """White box testing for decimal.py"""
4173
4174 def test_py_exact_power(self):
4175 # Rarely exercised lines in _power_exact.
4176 Decimal = P.Decimal
4177 localcontext = P.localcontext
4178
4179 with localcontext() as c:
4180 c.prec = 8
4181 x = Decimal(2**16) ** Decimal("-0.5")
4182 self.assertEqual(x, Decimal('0.00390625'))
4183
4184 x = Decimal(2**16) ** Decimal("-0.6")
4185 self.assertEqual(x, Decimal('0.0012885819'))
4186
4187 x = Decimal("256e7") ** Decimal("-0.5")
4188
4189 x = Decimal(152587890625) ** Decimal('-0.0625')
4190 self.assertEqual(x, Decimal("0.2"))
4191
4192 x = Decimal("152587890625e7") ** Decimal('-0.0625')
4193
4194 x = Decimal(5**2659) ** Decimal('-0.0625')
4195
4196 c.prec = 1
4197 x = Decimal("152587890625") ** Decimal('-0.5')
4198 c.prec = 201
4199 x = Decimal(2**578) ** Decimal("-0.5")
4200
4201 def test_py_immutability_operations(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004202 # Do operations and check that it didn't change change internal objects.
Stefan Krah1919b7e2012-03-21 18:25:23 +01004203 Decimal = P.Decimal
4204 DefaultContext = P.DefaultContext
4205 setcontext = P.setcontext
4206
4207 c = DefaultContext.copy()
4208 c.traps = dict((s, 0) for s in OrderedSignals[P])
4209 setcontext(c)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004210
4211 d1 = Decimal('-25e55')
4212 b1 = Decimal('-25e55')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004213 d2 = Decimal('33e+33')
4214 b2 = Decimal('33e+33')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004215
4216 def checkSameDec(operation, useOther=False):
4217 if useOther:
4218 eval("d1." + operation + "(d2)")
4219 self.assertEqual(d1._sign, b1._sign)
4220 self.assertEqual(d1._int, b1._int)
4221 self.assertEqual(d1._exp, b1._exp)
4222 self.assertEqual(d2._sign, b2._sign)
4223 self.assertEqual(d2._int, b2._int)
4224 self.assertEqual(d2._exp, b2._exp)
4225 else:
4226 eval("d1." + operation + "()")
4227 self.assertEqual(d1._sign, b1._sign)
4228 self.assertEqual(d1._int, b1._int)
4229 self.assertEqual(d1._exp, b1._exp)
4230 return
4231
4232 Decimal(d1)
4233 self.assertEqual(d1._sign, b1._sign)
4234 self.assertEqual(d1._int, b1._int)
4235 self.assertEqual(d1._exp, b1._exp)
4236
4237 checkSameDec("__abs__")
4238 checkSameDec("__add__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004239 checkSameDec("__divmod__", True)
Christian Heimes77c02eb2008-02-09 02:18:51 +00004240 checkSameDec("__eq__", True)
4241 checkSameDec("__ne__", True)
4242 checkSameDec("__le__", True)
4243 checkSameDec("__lt__", True)
4244 checkSameDec("__ge__", True)
4245 checkSameDec("__gt__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004246 checkSameDec("__float__")
4247 checkSameDec("__floordiv__", True)
4248 checkSameDec("__hash__")
4249 checkSameDec("__int__")
Christian Heimes969fe572008-01-25 11:23:10 +00004250 checkSameDec("__trunc__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004251 checkSameDec("__mod__", True)
4252 checkSameDec("__mul__", True)
4253 checkSameDec("__neg__")
Jack Diederich4dafcc42006-11-28 19:15:13 +00004254 checkSameDec("__bool__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004255 checkSameDec("__pos__")
4256 checkSameDec("__pow__", True)
4257 checkSameDec("__radd__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004258 checkSameDec("__rdivmod__", True)
4259 checkSameDec("__repr__")
4260 checkSameDec("__rfloordiv__", True)
4261 checkSameDec("__rmod__", True)
4262 checkSameDec("__rmul__", True)
4263 checkSameDec("__rpow__", True)
4264 checkSameDec("__rsub__", True)
4265 checkSameDec("__str__")
4266 checkSameDec("__sub__", True)
4267 checkSameDec("__truediv__", True)
4268 checkSameDec("adjusted")
4269 checkSameDec("as_tuple")
4270 checkSameDec("compare", True)
4271 checkSameDec("max", True)
4272 checkSameDec("min", True)
4273 checkSameDec("normalize")
4274 checkSameDec("quantize", True)
4275 checkSameDec("remainder_near", True)
4276 checkSameDec("same_quantum", True)
4277 checkSameDec("sqrt")
4278 checkSameDec("to_eng_string")
4279 checkSameDec("to_integral")
4280
Stefan Krah1919b7e2012-03-21 18:25:23 +01004281 def test_py_decimal_id(self):
4282 Decimal = P.Decimal
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004283
Stefan Krah1919b7e2012-03-21 18:25:23 +01004284 d = Decimal(45)
4285 e = Decimal(d)
4286 self.assertEqual(str(e), '45')
4287 self.assertNotEqual(id(d), id(e))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004288
Stefan Krah1919b7e2012-03-21 18:25:23 +01004289 def test_py_rescale(self):
4290 # Coverage
4291 Decimal = P.Decimal
4292 ROUND_UP = P.ROUND_UP
4293 localcontext = P.localcontext
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004294
Stefan Krah1919b7e2012-03-21 18:25:23 +01004295 with localcontext() as c:
4296 x = Decimal("NaN")._rescale(3, ROUND_UP)
4297 self.assertTrue(x.is_nan())
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004298
Stefan Krah1919b7e2012-03-21 18:25:23 +01004299 def test_py__round(self):
4300 # Coverage
4301 Decimal = P.Decimal
4302 ROUND_UP = P.ROUND_UP
Christian Heimes0348fb62008-03-26 12:55:56 +00004303
Stefan Krah1919b7e2012-03-21 18:25:23 +01004304 self.assertRaises(ValueError, Decimal("3.1234")._round, 0, ROUND_UP)
Mark Dickinsona2d1fe02009-10-29 12:23:02 +00004305
Stefan Krah1919b7e2012-03-21 18:25:23 +01004306class CFunctionality(unittest.TestCase):
4307 """Extra functionality in _decimal"""
Mark Dickinsona2d1fe02009-10-29 12:23:02 +00004308
Stefan Krah1919b7e2012-03-21 18:25:23 +01004309 @requires_extra_functionality
4310 def test_c_ieee_context(self):
4311 # issue 8786: Add support for IEEE 754 contexts to decimal module.
4312 IEEEContext = C.IEEEContext
4313 DECIMAL32 = C.DECIMAL32
4314 DECIMAL64 = C.DECIMAL64
4315 DECIMAL128 = C.DECIMAL128
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004316
Stefan Krah1919b7e2012-03-21 18:25:23 +01004317 def assert_rest(self, context):
4318 self.assertEqual(context.clamp, 1)
4319 assert_signals(self, context, 'traps', [])
4320 assert_signals(self, context, 'flags', [])
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004321
Stefan Krah1919b7e2012-03-21 18:25:23 +01004322 c = IEEEContext(DECIMAL32)
4323 self.assertEqual(c.prec, 7)
4324 self.assertEqual(c.Emax, 96)
4325 self.assertEqual(c.Emin, -95)
4326 assert_rest(self, c)
Raymond Hettinger82417ca2009-02-03 03:54:28 +00004327
Stefan Krah1919b7e2012-03-21 18:25:23 +01004328 c = IEEEContext(DECIMAL64)
4329 self.assertEqual(c.prec, 16)
4330 self.assertEqual(c.Emax, 384)
4331 self.assertEqual(c.Emin, -383)
4332 assert_rest(self, c)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004333
Stefan Krah1919b7e2012-03-21 18:25:23 +01004334 c = IEEEContext(DECIMAL128)
4335 self.assertEqual(c.prec, 34)
4336 self.assertEqual(c.Emax, 6144)
4337 self.assertEqual(c.Emin, -6143)
4338 assert_rest(self, c)
Raymond Hettinger5548be22004-07-05 18:49:38 +00004339
Stefan Krah1919b7e2012-03-21 18:25:23 +01004340 # Invalid values
4341 self.assertRaises(OverflowError, IEEEContext, 2**63)
4342 self.assertRaises(ValueError, IEEEContext, -1)
4343 self.assertRaises(ValueError, IEEEContext, 1024)
Mark Dickinson825fce32009-09-07 18:08:12 +00004344
Stefan Krah1919b7e2012-03-21 18:25:23 +01004345 @requires_extra_functionality
4346 def test_c_context(self):
4347 Context = C.Context
Christian Heimes969fe572008-01-25 11:23:10 +00004348
Stefan Krah1919b7e2012-03-21 18:25:23 +01004349 c = Context(flags=C.DecClamped, traps=C.DecRounded)
4350 self.assertEqual(c._flags, C.DecClamped)
4351 self.assertEqual(c._traps, C.DecRounded)
Raymond Hettinger771ed762009-01-03 19:20:32 +00004352
Stefan Krah1919b7e2012-03-21 18:25:23 +01004353 @requires_extra_functionality
4354 def test_constants(self):
4355 # Condition flags
4356 cond = (
4357 C.DecClamped, C.DecConversionSyntax, C.DecDivisionByZero,
4358 C.DecDivisionImpossible, C.DecDivisionUndefined,
4359 C.DecFpuError, C.DecInexact, C.DecInvalidContext,
4360 C.DecInvalidOperation, C.DecMallocError,
4361 C.DecFloatOperation, C.DecOverflow, C.DecRounded,
4362 C.DecSubnormal, C.DecUnderflow
Raymond Hettinger771ed762009-01-03 19:20:32 +00004363 )
Stefan Krah1919b7e2012-03-21 18:25:23 +01004364
4365 # IEEEContext
4366 self.assertEqual(C.DECIMAL32, 32)
4367 self.assertEqual(C.DECIMAL64, 64)
4368 self.assertEqual(C.DECIMAL128, 128)
4369 self.assertEqual(C.IEEE_CONTEXT_MAX_BITS, 512)
4370
4371 # Rounding modes
4372 for i, v in enumerate(RoundingModes[C]):
4373 self.assertEqual(v, i)
4374 self.assertEqual(C.ROUND_TRUNC, 8)
4375
4376 # Conditions
4377 for i, v in enumerate(cond):
4378 self.assertEqual(v, 1<<i)
4379
4380 self.assertEqual(C.DecIEEEInvalidOperation,
4381 C.DecConversionSyntax|
4382 C.DecDivisionImpossible|
4383 C.DecDivisionUndefined|
4384 C.DecFpuError|
4385 C.DecInvalidContext|
4386 C.DecInvalidOperation|
4387 C.DecMallocError)
4388
4389 self.assertEqual(C.DecErrors,
4390 C.DecIEEEInvalidOperation|
4391 C.DecDivisionByZero)
4392
4393 self.assertEqual(C.DecTraps,
4394 C.DecErrors|C.DecOverflow|C.DecUnderflow)
4395
4396class CWhitebox(unittest.TestCase):
4397 """Whitebox testing for _decimal"""
4398
4399 def test_bignum(self):
4400 # Not exactly whitebox, but too slow with pydecimal.
4401
4402 Decimal = C.Decimal
4403 localcontext = C.localcontext
4404
4405 b1 = 10**35
4406 b2 = 10**36
4407 with localcontext() as c:
4408 c.prec = 1000000
4409 for i in range(5):
4410 a = random.randrange(b1, b2)
4411 b = random.randrange(1000, 1200)
4412 x = a ** b
4413 y = Decimal(a) ** Decimal(b)
4414 self.assertEqual(x, y)
4415
4416 def test_invalid_construction(self):
4417 self.assertRaises(TypeError, C.Decimal, 9, "xyz")
4418
4419 def test_c_input_restriction(self):
4420 # Too large for _decimal to be converted exactly
4421 Decimal = C.Decimal
4422 InvalidOperation = C.InvalidOperation
4423 Context = C.Context
4424 localcontext = C.localcontext
4425
4426 with localcontext(Context()):
4427 self.assertRaises(InvalidOperation, Decimal,
4428 "1e9999999999999999999")
4429
4430 def test_c_context_repr(self):
4431 # This test is _decimal-only because flags are not printed
4432 # in the same order.
4433 DefaultContext = C.DefaultContext
4434 FloatOperation = C.FloatOperation
4435 ROUND_HALF_DOWN = C.ROUND_HALF_DOWN
4436
4437 c = DefaultContext.copy()
4438
4439 c.prec = 425000000
4440 c.Emax = 425000000
4441 c.Emin = -425000000
4442 c.rounding = ROUND_HALF_DOWN
4443 c.capitals = 0
4444 c.clamp = 1
4445 for sig in OrderedSignals[C]:
4446 c.flags[sig] = True
4447 c.traps[sig] = True
4448 c.flags[FloatOperation] = True
4449 c.traps[FloatOperation] = True
4450
4451 s = c.__repr__()
4452 t = "Context(prec=425000000, rounding=ROUND_HALF_DOWN, " \
4453 "Emin=-425000000, Emax=425000000, capitals=0, clamp=1, " \
4454 "flags=[Clamped, InvalidOperation, DivisionByZero, Inexact, " \
4455 "FloatOperation, Overflow, Rounded, Subnormal, Underflow], " \
4456 "traps=[Clamped, InvalidOperation, DivisionByZero, Inexact, " \
4457 "FloatOperation, Overflow, Rounded, Subnormal, Underflow])"
4458 self.assertEqual(s, t)
4459
4460 def test_c_context_errors(self):
4461 Context = C.Context
4462 InvalidOperation = C.InvalidOperation
4463 Overflow = C.Overflow
4464 FloatOperation = C.FloatOperation
4465 localcontext = C.localcontext
4466 getcontext = C.getcontext
4467 setcontext = C.setcontext
4468 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
4469
4470 c = Context()
4471
4472 # SignalDict: input validation
4473 self.assertRaises(KeyError, c.flags.__setitem__, 801, 0)
4474 self.assertRaises(KeyError, c.traps.__setitem__, 801, 0)
4475 self.assertRaises(ValueError, c.flags.__delitem__, Overflow)
4476 self.assertRaises(ValueError, c.traps.__delitem__, InvalidOperation)
4477 self.assertRaises(TypeError, setattr, c, 'flags', ['x'])
4478 self.assertRaises(TypeError, setattr, c,'traps', ['y'])
4479 self.assertRaises(KeyError, setattr, c, 'flags', {0:1})
4480 self.assertRaises(KeyError, setattr, c, 'traps', {0:1})
4481
4482 # Test assignment from a signal dict with the correct length but
4483 # one invalid key.
4484 d = c.flags.copy()
4485 del d[FloatOperation]
4486 d["XYZ"] = 91283719
4487 self.assertRaises(KeyError, setattr, c, 'flags', d)
4488 self.assertRaises(KeyError, setattr, c, 'traps', d)
4489
4490 # Input corner cases
4491 int_max = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
4492 gt_max_emax = 10**18 if HAVE_CONFIG_64 else 10**9
4493
4494 # prec, Emax, Emin
4495 for attr in ['prec', 'Emax']:
4496 self.assertRaises(ValueError, setattr, c, attr, gt_max_emax)
4497 self.assertRaises(ValueError, setattr, c, 'Emin', -gt_max_emax)
4498
4499 # prec, Emax, Emin in context constructor
4500 self.assertRaises(ValueError, Context, prec=gt_max_emax)
4501 self.assertRaises(ValueError, Context, Emax=gt_max_emax)
4502 self.assertRaises(ValueError, Context, Emin=-gt_max_emax)
4503
4504 # Overflow in conversion
4505 self.assertRaises(OverflowError, Context, prec=int_max+1)
4506 self.assertRaises(OverflowError, Context, Emax=int_max+1)
4507 self.assertRaises(OverflowError, Context, Emin=-int_max-2)
4508 self.assertRaises(OverflowError, Context, rounding=int_max+1)
4509 self.assertRaises(OverflowError, Context, clamp=int_max+1)
4510 self.assertRaises(OverflowError, Context, capitals=int_max+1)
4511
4512 # OverflowError, general ValueError
4513 for attr in ('prec', 'Emin', 'Emax', 'capitals', 'clamp'):
4514 self.assertRaises(OverflowError, setattr, c, attr, int_max+1)
4515 self.assertRaises(OverflowError, setattr, c, attr, -int_max-2)
4516 if sys.platform != 'win32':
4517 self.assertRaises(ValueError, setattr, c, attr, int_max)
4518 self.assertRaises(ValueError, setattr, c, attr, -int_max-1)
4519
4520 # OverflowError, general TypeError
4521 for attr in ('rounding',):
4522 self.assertRaises(OverflowError, setattr, c, attr, int_max+1)
4523 self.assertRaises(OverflowError, setattr, c, attr, -int_max-2)
4524 if sys.platform != 'win32':
4525 self.assertRaises(TypeError, setattr, c, attr, int_max)
4526 self.assertRaises(TypeError, setattr, c, attr, -int_max-1)
4527
4528 # OverflowError: _unsafe_setprec, _unsafe_setemin, _unsafe_setemax
4529 if C.MAX_PREC == 425000000:
4530 self.assertRaises(OverflowError, getattr(c, '_unsafe_setprec'),
4531 int_max+1)
4532 self.assertRaises(OverflowError, getattr(c, '_unsafe_setemax'),
4533 int_max+1)
4534 self.assertRaises(OverflowError, getattr(c, '_unsafe_setemin'),
4535 -int_max-2)
4536
4537 # ValueError: _unsafe_setprec, _unsafe_setemin, _unsafe_setemax
4538 if C.MAX_PREC == 425000000:
4539 self.assertRaises(ValueError, getattr(c, '_unsafe_setprec'), 0)
4540 self.assertRaises(ValueError, getattr(c, '_unsafe_setprec'),
4541 1070000001)
4542 self.assertRaises(ValueError, getattr(c, '_unsafe_setemax'), -1)
4543 self.assertRaises(ValueError, getattr(c, '_unsafe_setemax'),
4544 1070000001)
4545 self.assertRaises(ValueError, getattr(c, '_unsafe_setemin'),
4546 -1070000001)
4547 self.assertRaises(ValueError, getattr(c, '_unsafe_setemin'), 1)
4548
4549 # capitals, clamp
4550 for attr in ['capitals', 'clamp']:
4551 self.assertRaises(ValueError, setattr, c, attr, -1)
4552 self.assertRaises(ValueError, setattr, c, attr, 2)
4553 self.assertRaises(TypeError, setattr, c, attr, [1,2,3])
4554 if HAVE_CONFIG_64:
4555 self.assertRaises(ValueError, setattr, c, attr, 2**32)
4556 self.assertRaises(ValueError, setattr, c, attr, 2**32+1)
4557
4558 # Invalid local context
4559 self.assertRaises(TypeError, exec, 'with localcontext("xyz"): pass',
4560 locals())
4561
4562 # setcontext
4563 saved_context = getcontext()
4564 self.assertRaises(TypeError, setcontext, "xyz")
4565 setcontext(saved_context)
4566
4567 @requires_extra_functionality
4568 def test_c_context_errors_extra(self):
4569 Context = C.Context
4570 InvalidOperation = C.InvalidOperation
4571 Overflow = C.Overflow
4572 localcontext = C.localcontext
4573 getcontext = C.getcontext
4574 setcontext = C.setcontext
4575 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
4576
4577 c = Context()
4578
4579 # Input corner cases
4580 int_max = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
4581
4582 # OverflowError, general ValueError
4583 self.assertRaises(OverflowError, setattr, c, '_allcr', int_max+1)
4584 self.assertRaises(OverflowError, setattr, c, '_allcr', -int_max-2)
4585 if sys.platform != 'win32':
4586 self.assertRaises(ValueError, setattr, c, '_allcr', int_max)
4587 self.assertRaises(ValueError, setattr, c, '_allcr', -int_max-1)
4588
4589 # OverflowError, general TypeError
4590 for attr in ('_flags', '_traps'):
4591 self.assertRaises(OverflowError, setattr, c, attr, int_max+1)
4592 self.assertRaises(OverflowError, setattr, c, attr, -int_max-2)
4593 if sys.platform != 'win32':
4594 self.assertRaises(TypeError, setattr, c, attr, int_max)
4595 self.assertRaises(TypeError, setattr, c, attr, -int_max-1)
4596
4597 # _allcr
4598 self.assertRaises(ValueError, setattr, c, '_allcr', -1)
4599 self.assertRaises(ValueError, setattr, c, '_allcr', 2)
4600 self.assertRaises(TypeError, setattr, c, '_allcr', [1,2,3])
4601 if HAVE_CONFIG_64:
4602 self.assertRaises(ValueError, setattr, c, '_allcr', 2**32)
4603 self.assertRaises(ValueError, setattr, c, '_allcr', 2**32+1)
4604
4605 # _flags, _traps
4606 for attr in ['_flags', '_traps']:
4607 self.assertRaises(TypeError, setattr, c, attr, 999999)
4608 self.assertRaises(TypeError, setattr, c, attr, 'x')
4609
4610 def test_c_valid_context(self):
4611 # These tests are for code coverage in _decimal.
4612 DefaultContext = C.DefaultContext
4613 ROUND_HALF_UP = C.ROUND_HALF_UP
4614 Clamped = C.Clamped
4615 Underflow = C.Underflow
4616 Inexact = C.Inexact
4617 Rounded = C.Rounded
4618 Subnormal = C.Subnormal
4619
4620 c = DefaultContext.copy()
4621
4622 # Exercise all getters and setters
4623 c.prec = 34
4624 c.rounding = ROUND_HALF_UP
4625 c.Emax = 3000
4626 c.Emin = -3000
4627 c.capitals = 1
4628 c.clamp = 0
4629
4630 self.assertEqual(c.prec, 34)
4631 self.assertEqual(c.rounding, ROUND_HALF_UP)
4632 self.assertEqual(c.Emin, -3000)
4633 self.assertEqual(c.Emax, 3000)
4634 self.assertEqual(c.capitals, 1)
4635 self.assertEqual(c.clamp, 0)
4636
4637 self.assertEqual(c.Etiny(), -3033)
4638 self.assertEqual(c.Etop(), 2967)
4639
4640 # Exercise all unsafe setters
4641 if C.MAX_PREC == 425000000:
4642 c._unsafe_setprec(999999999)
4643 c._unsafe_setemax(999999999)
4644 c._unsafe_setemin(-999999999)
4645 self.assertEqual(c.prec, 999999999)
4646 self.assertEqual(c.Emax, 999999999)
4647 self.assertEqual(c.Emin, -999999999)
4648
4649 @requires_extra_functionality
4650 def test_c_valid_context_extra(self):
4651 DefaultContext = C.DefaultContext
4652
4653 c = DefaultContext.copy()
4654 self.assertEqual(c._allcr, 1)
4655 c._allcr = 0
4656 self.assertEqual(c._allcr, 0)
4657
4658 def test_c_round(self):
4659 # Restricted input.
4660 Decimal = C.Decimal
4661 InvalidOperation = C.InvalidOperation
4662 localcontext = C.localcontext
4663 MAX_EMAX = C.MAX_EMAX
4664 MIN_ETINY = C.MIN_ETINY
4665 int_max = 2**63-1 if C.MAX_PREC > 425000000 else 2**31-1
4666
4667 with localcontext() as c:
4668 c.traps[InvalidOperation] = True
4669 self.assertRaises(InvalidOperation, Decimal("1.23").__round__,
4670 -int_max-1)
4671 self.assertRaises(InvalidOperation, Decimal("1.23").__round__,
4672 int_max)
4673 self.assertRaises(InvalidOperation, Decimal("1").__round__,
4674 int(MAX_EMAX+1))
4675 self.assertRaises(C.InvalidOperation, Decimal("1").__round__,
4676 -int(MIN_ETINY-1))
4677 self.assertRaises(OverflowError, Decimal("1.23").__round__,
4678 -int_max-2)
4679 self.assertRaises(OverflowError, Decimal("1.23").__round__,
4680 int_max+1)
4681
4682 def test_c_format(self):
4683 # Restricted input
4684 Decimal = C.Decimal
4685 InvalidOperation = C.InvalidOperation
4686 Rounded = C.Rounded
4687 localcontext = C.localcontext
4688 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
4689
4690 self.assertRaises(TypeError, Decimal(1).__format__, "=10.10", [], 9)
4691 self.assertRaises(TypeError, Decimal(1).__format__, "=10.10", 9)
4692 self.assertRaises(TypeError, Decimal(1).__format__, [])
4693
4694 with localcontext() as c:
4695 c.traps[InvalidOperation] = True
4696 c.traps[Rounded] = True
4697 self.assertRaises(ValueError, Decimal(1).__format__, "<>=10.10")
4698 maxsize = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
4699 self.assertRaises(InvalidOperation, Decimal("1.23456789").__format__,
4700 "=%d.1" % maxsize)
4701
4702 def test_c_integral(self):
4703 Decimal = C.Decimal
4704 Inexact = C.Inexact
4705 ROUND_UP = C.ROUND_UP
4706 localcontext = C.localcontext
4707
4708 x = Decimal(10)
4709 self.assertEqual(x.to_integral(), 10)
4710 self.assertRaises(TypeError, x.to_integral, '10')
4711 self.assertRaises(TypeError, x.to_integral, 10, 'x')
4712 self.assertRaises(TypeError, x.to_integral, 10)
4713
4714 self.assertEqual(x.to_integral_value(), 10)
4715 self.assertRaises(TypeError, x.to_integral_value, '10')
4716 self.assertRaises(TypeError, x.to_integral_value, 10, 'x')
4717 self.assertRaises(TypeError, x.to_integral_value, 10)
4718
4719 self.assertEqual(x.to_integral_exact(), 10)
4720 self.assertRaises(TypeError, x.to_integral_exact, '10')
4721 self.assertRaises(TypeError, x.to_integral_exact, 10, 'x')
4722 self.assertRaises(TypeError, x.to_integral_exact, 10)
4723
4724 with localcontext() as c:
4725 x = Decimal("99999999999999999999999999.9").to_integral_value(ROUND_UP)
4726 self.assertEqual(x, Decimal('100000000000000000000000000'))
4727
4728 x = Decimal("99999999999999999999999999.9").to_integral_exact(ROUND_UP)
4729 self.assertEqual(x, Decimal('100000000000000000000000000'))
4730
4731 c.traps[Inexact] = True
4732 self.assertRaises(Inexact, Decimal("999.9").to_integral_exact, ROUND_UP)
4733
4734 def test_c_funcs(self):
4735 # Invalid arguments
4736 Decimal = C.Decimal
4737 InvalidOperation = C.InvalidOperation
4738 DivisionByZero = C.DivisionByZero
4739 ROUND_UP = C.ROUND_UP
4740 getcontext = C.getcontext
4741 localcontext = C.localcontext
4742
4743 self.assertEqual(Decimal('9.99e10').to_eng_string(), '99.9E+9')
4744
4745 self.assertRaises(TypeError, pow, Decimal(1), 2, "3")
4746 self.assertRaises(TypeError, Decimal(9).number_class, "x", "y")
4747 self.assertRaises(TypeError, Decimal(9).same_quantum, 3, "x", "y")
4748
Raymond Hettinger771ed762009-01-03 19:20:32 +00004749 self.assertRaises(
Stefan Krah1919b7e2012-03-21 18:25:23 +01004750 TypeError,
4751 Decimal("1.23456789").quantize, Decimal('1e-100000'), []
Raymond Hettinger771ed762009-01-03 19:20:32 +00004752 )
Stefan Krah1919b7e2012-03-21 18:25:23 +01004753 self.assertRaises(
4754 TypeError,
4755 Decimal("1.23456789").quantize, Decimal('1e-100000'), getcontext()
4756 )
4757 self.assertRaises(
4758 TypeError,
4759 Decimal("1.23456789").quantize, Decimal('1e-100000'), 10
4760 )
4761 self.assertRaises(
4762 TypeError,
4763 Decimal("1.23456789").quantize, Decimal('1e-100000'), ROUND_UP, 1000
4764 )
Raymond Hettinger771ed762009-01-03 19:20:32 +00004765
Stefan Krah1919b7e2012-03-21 18:25:23 +01004766 with localcontext() as c:
4767 c.clear_traps()
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00004768
Stefan Krah1919b7e2012-03-21 18:25:23 +01004769 # Invalid arguments
4770 self.assertRaises(TypeError, c.copy_sign, Decimal(1), "x", "y")
4771 self.assertRaises(TypeError, c.canonical, 200)
4772 self.assertRaises(TypeError, c.is_canonical, 200)
4773 self.assertRaises(TypeError, c.divmod, 9, 8, "x", "y")
4774 self.assertRaises(TypeError, c.same_quantum, 9, 3, "x", "y")
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00004775
Stefan Krah1919b7e2012-03-21 18:25:23 +01004776 self.assertEqual(str(c.canonical(Decimal(200))), '200')
4777 self.assertEqual(c.radix(), 10)
Raymond Hettinger0aeac102004-07-05 22:53:03 +00004778
Stefan Krah1919b7e2012-03-21 18:25:23 +01004779 c.traps[DivisionByZero] = True
4780 self.assertRaises(DivisionByZero, Decimal(9).__divmod__, 0)
4781 self.assertRaises(DivisionByZero, c.divmod, 9, 0)
4782 self.assertTrue(c.flags[InvalidOperation])
Raymond Hettinger955d2b22004-08-08 20:17:45 +00004783
Stefan Krah1919b7e2012-03-21 18:25:23 +01004784 c.clear_flags()
4785 c.traps[InvalidOperation] = True
4786 self.assertRaises(InvalidOperation, Decimal(9).__divmod__, 0)
4787 self.assertRaises(InvalidOperation, c.divmod, 9, 0)
4788 self.assertTrue(c.flags[DivisionByZero])
Mark Dickinsonb1d8e322010-05-22 18:35:36 +00004789
Stefan Krah1919b7e2012-03-21 18:25:23 +01004790 c.traps[InvalidOperation] = True
4791 c.prec = 2
4792 self.assertRaises(InvalidOperation, pow, Decimal(1000), 1, 501)
Mark Dickinson84230a12010-02-18 14:49:50 +00004793
Stefan Krah1919b7e2012-03-21 18:25:23 +01004794 @requires_extra_functionality
4795 def test_c_context_templates(self):
4796 self.assertEqual(
4797 C.BasicContext._traps,
4798 C.DecIEEEInvalidOperation|C.DecDivisionByZero|C.DecOverflow|
4799 C.DecUnderflow|C.DecClamped
4800 )
4801 self.assertEqual(
4802 C.DefaultContext._traps,
4803 C.DecIEEEInvalidOperation|C.DecDivisionByZero|C.DecOverflow
4804 )
Mark Dickinson84230a12010-02-18 14:49:50 +00004805
Stefan Krah1919b7e2012-03-21 18:25:23 +01004806 @requires_extra_functionality
4807 def test_c_signal_dict(self):
Mark Dickinson84230a12010-02-18 14:49:50 +00004808
Stefan Krah1919b7e2012-03-21 18:25:23 +01004809 # SignalDict coverage
4810 Context = C.Context
4811 DefaultContext = C.DefaultContext
Mark Dickinson84230a12010-02-18 14:49:50 +00004812
Stefan Krah1919b7e2012-03-21 18:25:23 +01004813 InvalidOperation = C.InvalidOperation
4814 DivisionByZero = C.DivisionByZero
4815 Overflow = C.Overflow
4816 Subnormal = C.Subnormal
4817 Underflow = C.Underflow
4818 Rounded = C.Rounded
4819 Inexact = C.Inexact
4820 Clamped = C.Clamped
Mark Dickinson84230a12010-02-18 14:49:50 +00004821
Stefan Krah1919b7e2012-03-21 18:25:23 +01004822 DecClamped = C.DecClamped
4823 DecInvalidOperation = C.DecInvalidOperation
4824 DecIEEEInvalidOperation = C.DecIEEEInvalidOperation
Mark Dickinson84230a12010-02-18 14:49:50 +00004825
Stefan Krah1919b7e2012-03-21 18:25:23 +01004826 def assertIsExclusivelySet(signal, signal_dict):
4827 for sig in signal_dict:
4828 if sig == signal:
4829 self.assertTrue(signal_dict[sig])
4830 else:
4831 self.assertFalse(signal_dict[sig])
Mark Dickinson84230a12010-02-18 14:49:50 +00004832
Stefan Krah1919b7e2012-03-21 18:25:23 +01004833 c = DefaultContext.copy()
Mark Dickinson84230a12010-02-18 14:49:50 +00004834
Stefan Krah1919b7e2012-03-21 18:25:23 +01004835 # Signal dict methods
4836 self.assertTrue(Overflow in c.traps)
4837 c.clear_traps()
4838 for k in c.traps.keys():
4839 c.traps[k] = True
4840 for v in c.traps.values():
4841 self.assertTrue(v)
4842 c.clear_traps()
4843 for k, v in c.traps.items():
4844 self.assertFalse(v)
Mark Dickinson84230a12010-02-18 14:49:50 +00004845
Stefan Krah1919b7e2012-03-21 18:25:23 +01004846 self.assertFalse(c.flags.get(Overflow))
4847 self.assertIs(c.flags.get("x"), None)
4848 self.assertEqual(c.flags.get("x", "y"), "y")
4849 self.assertRaises(TypeError, c.flags.get, "x", "y", "z")
Mark Dickinson84230a12010-02-18 14:49:50 +00004850
Stefan Krah1919b7e2012-03-21 18:25:23 +01004851 self.assertEqual(len(c.flags), len(c.traps))
4852 s = sys.getsizeof(c.flags)
4853 s = sys.getsizeof(c.traps)
4854 s = c.flags.__repr__()
Mark Dickinson84230a12010-02-18 14:49:50 +00004855
Stefan Krah1919b7e2012-03-21 18:25:23 +01004856 # Set flags/traps.
4857 c.clear_flags()
4858 c._flags = DecClamped
4859 self.assertTrue(c.flags[Clamped])
Mark Dickinson84230a12010-02-18 14:49:50 +00004860
Stefan Krah1919b7e2012-03-21 18:25:23 +01004861 c.clear_traps()
4862 c._traps = DecInvalidOperation
4863 self.assertTrue(c.traps[InvalidOperation])
Mark Dickinson84230a12010-02-18 14:49:50 +00004864
Stefan Krah1919b7e2012-03-21 18:25:23 +01004865 # Set flags/traps from dictionary.
4866 c.clear_flags()
4867 d = c.flags.copy()
4868 d[DivisionByZero] = True
4869 c.flags = d
4870 assertIsExclusivelySet(DivisionByZero, c.flags)
Mark Dickinson84230a12010-02-18 14:49:50 +00004871
Stefan Krah1919b7e2012-03-21 18:25:23 +01004872 c.clear_traps()
4873 d = c.traps.copy()
4874 d[Underflow] = True
4875 c.traps = d
4876 assertIsExclusivelySet(Underflow, c.traps)
Mark Dickinson84230a12010-02-18 14:49:50 +00004877
Stefan Krah1919b7e2012-03-21 18:25:23 +01004878 # Random constructors
4879 IntSignals = {
4880 Clamped: C.DecClamped,
4881 Rounded: C.DecRounded,
4882 Inexact: C.DecInexact,
4883 Subnormal: C.DecSubnormal,
4884 Underflow: C.DecUnderflow,
4885 Overflow: C.DecOverflow,
4886 DivisionByZero: C.DecDivisionByZero,
4887 InvalidOperation: C.DecIEEEInvalidOperation
4888 }
4889 IntCond = [
4890 C.DecDivisionImpossible, C.DecDivisionUndefined, C.DecFpuError,
4891 C.DecInvalidContext, C.DecInvalidOperation, C.DecMallocError,
4892 C.DecConversionSyntax,
4893 ]
Mark Dickinsonb455e582011-05-22 12:53:18 +01004894
Stefan Krah1919b7e2012-03-21 18:25:23 +01004895 lim = len(OrderedSignals[C])
4896 for r in range(lim):
4897 for t in range(lim):
4898 for round in RoundingModes[C]:
4899 flags = random.sample(OrderedSignals[C], r)
4900 traps = random.sample(OrderedSignals[C], t)
4901 prec = random.randrange(1, 10000)
4902 emin = random.randrange(-10000, 0)
4903 emax = random.randrange(0, 10000)
4904 clamp = random.randrange(0, 2)
4905 caps = random.randrange(0, 2)
4906 cr = random.randrange(0, 2)
4907 c = Context(prec=prec, rounding=round, Emin=emin, Emax=emax,
4908 capitals=caps, clamp=clamp, flags=list(flags),
4909 traps=list(traps))
Mark Dickinson84230a12010-02-18 14:49:50 +00004910
Stefan Krah1919b7e2012-03-21 18:25:23 +01004911 self.assertEqual(c.prec, prec)
4912 self.assertEqual(c.rounding, round)
4913 self.assertEqual(c.Emin, emin)
4914 self.assertEqual(c.Emax, emax)
4915 self.assertEqual(c.capitals, caps)
4916 self.assertEqual(c.clamp, clamp)
Mark Dickinson84230a12010-02-18 14:49:50 +00004917
Stefan Krah1919b7e2012-03-21 18:25:23 +01004918 f = 0
4919 for x in flags:
4920 f |= IntSignals[x]
4921 self.assertEqual(c._flags, f)
Mark Dickinson84230a12010-02-18 14:49:50 +00004922
Stefan Krah1919b7e2012-03-21 18:25:23 +01004923 f = 0
4924 for x in traps:
4925 f |= IntSignals[x]
4926 self.assertEqual(c._traps, f)
Mark Dickinson84230a12010-02-18 14:49:50 +00004927
Stefan Krah1919b7e2012-03-21 18:25:23 +01004928 for cond in IntCond:
4929 c._flags = cond
4930 self.assertTrue(c._flags&DecIEEEInvalidOperation)
4931 assertIsExclusivelySet(InvalidOperation, c.flags)
Mark Dickinson84230a12010-02-18 14:49:50 +00004932
Stefan Krah1919b7e2012-03-21 18:25:23 +01004933 for cond in IntCond:
4934 c._traps = cond
4935 self.assertTrue(c._traps&DecIEEEInvalidOperation)
4936 assertIsExclusivelySet(InvalidOperation, c.traps)
Mark Dickinson84230a12010-02-18 14:49:50 +00004937
Stefan Krah1919b7e2012-03-21 18:25:23 +01004938 def test_invalid_override(self):
4939 Decimal = C.Decimal
Mark Dickinson84230a12010-02-18 14:49:50 +00004940
Stefan Krah1919b7e2012-03-21 18:25:23 +01004941 try:
4942 from locale import CHAR_MAX
4943 except ImportError:
4944 return
Mark Dickinson84230a12010-02-18 14:49:50 +00004945
Stefan Krah1919b7e2012-03-21 18:25:23 +01004946 def make_grouping(lst):
4947 return ''.join([chr(x) for x in lst])
Mark Dickinson84230a12010-02-18 14:49:50 +00004948
Stefan Krah1919b7e2012-03-21 18:25:23 +01004949 def get_fmt(x, override=None, fmt='n'):
4950 return Decimal(x).__format__(fmt, override)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004951
Stefan Krah1919b7e2012-03-21 18:25:23 +01004952 invalid_grouping = {
4953 'decimal_point' : ',',
4954 'grouping' : make_grouping([255, 255, 0]),
4955 'thousands_sep' : ','
4956 }
4957 invalid_dot = {
4958 'decimal_point' : 'xxxxx',
4959 'grouping' : make_grouping([3, 3, 0]),
4960 'thousands_sep' : ','
4961 }
4962 invalid_sep = {
4963 'decimal_point' : '.',
4964 'grouping' : make_grouping([3, 3, 0]),
4965 'thousands_sep' : 'yyyyy'
4966 }
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004967
Stefan Krah1919b7e2012-03-21 18:25:23 +01004968 if CHAR_MAX == 127: # negative grouping in override
4969 self.assertRaises(ValueError, get_fmt, 12345,
4970 invalid_grouping, 'g')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004971
Stefan Krah1919b7e2012-03-21 18:25:23 +01004972 self.assertRaises(ValueError, get_fmt, 12345, invalid_dot, 'g')
4973 self.assertRaises(ValueError, get_fmt, 12345, invalid_sep, 'g')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004974
Stefan Krah0774e9b2012-04-05 15:21:58 +02004975 def test_exact_conversion(self):
4976 Decimal = C.Decimal
4977 localcontext = C.localcontext
4978 InvalidOperation = C.InvalidOperation
4979
4980 with localcontext() as c:
4981
4982 c.traps[InvalidOperation] = True
4983
4984 # Clamped
4985 x = "0e%d" % sys.maxsize
4986 self.assertRaises(InvalidOperation, Decimal, x)
4987
4988 x = "0e%d" % (-sys.maxsize-1)
4989 self.assertRaises(InvalidOperation, Decimal, x)
4990
4991 # Overflow
4992 x = "1e%d" % sys.maxsize
4993 self.assertRaises(InvalidOperation, Decimal, x)
4994
4995 # Underflow
4996 x = "1e%d" % (-sys.maxsize-1)
4997 self.assertRaises(InvalidOperation, Decimal, x)
4998
Stefan Krahff3eca02012-04-05 15:46:19 +02004999 def test_from_tuple(self):
5000 Decimal = C.Decimal
5001 localcontext = C.localcontext
5002 InvalidOperation = C.InvalidOperation
5003 Overflow = C.Overflow
5004 Underflow = C.Underflow
5005
5006 with localcontext() as c:
5007
5008 c.traps[InvalidOperation] = True
5009 c.traps[Overflow] = True
5010 c.traps[Underflow] = True
5011
5012 # SSIZE_MAX
5013 x = (1, (), sys.maxsize)
5014 self.assertEqual(str(c.create_decimal(x)), '-0E+999999')
5015 self.assertRaises(InvalidOperation, Decimal, x)
5016
5017 x = (1, (0, 1, 2), sys.maxsize)
5018 self.assertRaises(Overflow, c.create_decimal, x)
5019 self.assertRaises(InvalidOperation, Decimal, x)
5020
5021 # SSIZE_MIN
5022 x = (1, (), -sys.maxsize-1)
5023 self.assertEqual(str(c.create_decimal(x)), '-0E-1000026')
5024 self.assertRaises(InvalidOperation, Decimal, x)
5025
5026 x = (1, (0, 1, 2), -sys.maxsize-1)
5027 self.assertRaises(Underflow, c.create_decimal, x)
5028 self.assertRaises(InvalidOperation, Decimal, x)
5029
5030 # OverflowError
5031 x = (1, (), sys.maxsize+1)
5032 self.assertRaises(OverflowError, c.create_decimal, x)
5033 self.assertRaises(OverflowError, Decimal, x)
5034
5035 x = (1, (), -sys.maxsize-2)
5036 self.assertRaises(OverflowError, c.create_decimal, x)
5037 self.assertRaises(OverflowError, Decimal, x)
5038
5039 # Specials
5040 x = (1, (), "N")
5041 self.assertEqual(str(Decimal(x)), '-sNaN')
5042 x = (1, (0,), "N")
5043 self.assertEqual(str(Decimal(x)), '-sNaN')
5044 x = (1, (0, 1), "N")
5045 self.assertEqual(str(Decimal(x)), '-sNaN1')
5046
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005047
Stefan Krah1919b7e2012-03-21 18:25:23 +01005048all_tests = [
5049 CExplicitConstructionTest, PyExplicitConstructionTest,
5050 CImplicitConstructionTest, PyImplicitConstructionTest,
5051 CFormatTest, PyFormatTest,
5052 CArithmeticOperatorsTest, PyArithmeticOperatorsTest,
5053 CThreadingTest, PyThreadingTest,
5054 CUsabilityTest, PyUsabilityTest,
5055 CPythonAPItests, PyPythonAPItests,
5056 CContextAPItests, PyContextAPItests,
5057 CContextWithStatement, PyContextWithStatement,
5058 CContextFlags, PyContextFlags,
5059 CSpecialContexts, PySpecialContexts,
5060 CContextInputValidation, PyContextInputValidation,
5061 CContextSubclassing, PyContextSubclassing,
5062 CCoverage, PyCoverage,
5063 CFunctionality, PyFunctionality,
5064 CWhitebox, PyWhitebox,
5065 CIBMTestCases, PyIBMTestCases,
5066]
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005067
Stefan Krah1919b7e2012-03-21 18:25:23 +01005068# Delete C tests if _decimal.so is not present.
5069if not C:
5070 all_tests = all_tests[1::2]
5071else:
5072 all_tests.insert(0, CheckAttributes)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005073
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005074
5075def test_main(arith=False, verbose=None, todo_tests=None, debug=None):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005076 """ Execute the tests.
5077
Raymond Hettingered20ad82004-09-04 20:09:13 +00005078 Runs all arithmetic tests if arith is True or if the "decimal" resource
5079 is enabled in regrtest.py
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005080 """
Raymond Hettingered20ad82004-09-04 20:09:13 +00005081
Stefan Krah1919b7e2012-03-21 18:25:23 +01005082 init(C)
5083 init(P)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005084 global TEST_ALL, DEBUG
Raymond Hettingered20ad82004-09-04 20:09:13 +00005085 TEST_ALL = arith or is_resource_enabled('decimal')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005086 DEBUG = debug
Raymond Hettingered20ad82004-09-04 20:09:13 +00005087
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005088 if todo_tests is None:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005089 test_classes = all_tests
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005090 else:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005091 test_classes = [CIBMTestCases, PyIBMTestCases]
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005092
5093 # Dynamically build custom test definition for each file in the test
5094 # directory and add the definitions to the DecimalTest class. This
5095 # procedure insures that new files do not get skipped.
5096 for filename in os.listdir(directory):
5097 if '.decTest' not in filename or filename.startswith("."):
5098 continue
5099 head, tail = filename.split('.')
5100 if todo_tests is not None and head not in todo_tests:
5101 continue
5102 tester = lambda self, f=filename: self.eval_file(directory + f)
Stefan Krah1919b7e2012-03-21 18:25:23 +01005103 setattr(CIBMTestCases, 'test_' + head, tester)
5104 setattr(PyIBMTestCases, 'test_' + head, tester)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005105 del filename, head, tail, tester
5106
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005107
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005108 try:
5109 run_unittest(*test_classes)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005110 if todo_tests is None:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005111 from doctest import IGNORE_EXCEPTION_DETAIL
5112 savedecimal = sys.modules['decimal']
5113 if C:
5114 sys.modules['decimal'] = C
5115 run_doctest(C, verbose, optionflags=IGNORE_EXCEPTION_DETAIL)
5116 sys.modules['decimal'] = P
5117 run_doctest(P, verbose)
5118 sys.modules['decimal'] = savedecimal
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005119 finally:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005120 if C: C.setcontext(ORIGINAL_CONTEXT[C])
5121 P.setcontext(ORIGINAL_CONTEXT[P])
5122 if not C:
5123 warnings.warn('C tests skipped: no module named _decimal.',
5124 UserWarning)
5125 if not orig_sys_decimal is sys.modules['decimal']:
5126 raise TestFailed("Internal error: unbalanced number of changes to "
5127 "sys.modules['decimal'].")
5128
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005129
5130if __name__ == '__main__':
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005131 import optparse
5132 p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]")
5133 p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test')
5134 p.add_option('--skip', '-s', action='store_true', help='skip over 90% of the arithmetic tests')
5135 (opt, args) = p.parse_args()
5136
5137 if opt.skip:
5138 test_main(arith=False, verbose=True)
5139 elif args:
5140 test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005141 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005142 test_main(arith=True, verbose=True)