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