blob: 0166c699f8e42bf5d780676b51071779a2b8cc29 [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,
Stefan Krah6b794b82014-05-01 17:42:33 +020036 requires_IEEE_754, requires_docstrings)
Stefan Krah6fb204a2012-09-28 16:18:54 +020037from test.support import (check_warnings, import_fresh_module, TestFailed,
Stefan Krah6e467042012-11-10 23:09:04 +010038 run_with_locale, cpython_only)
Raymond Hettinger0aeac102004-07-05 22:53:03 +000039import random
Stefan Krah1919b7e2012-03-21 18:25:23 +010040import time
41import warnings
Stefan Krah5de1f822014-05-01 15:53:42 +020042import inspect
Raymond Hettinger7e71fa52004-12-18 19:07:19 +000043try:
44 import threading
45except ImportError:
46 threading = None
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000047
Raymond Hettingerfed52962004-07-14 15:41:57 +000048
Stefan Krah1919b7e2012-03-21 18:25:23 +010049C = import_fresh_module('decimal', fresh=['_decimal'])
50P = import_fresh_module('decimal', blocked=['_decimal'])
51orig_sys_decimal = sys.modules['decimal']
52
53# fractions module must import the correct decimal module.
54cfractions = import_fresh_module('fractions', fresh=['fractions'])
55sys.modules['decimal'] = P
56pfractions = import_fresh_module('fractions', fresh=['fractions'])
57sys.modules['decimal'] = C
58fractions = {C:cfractions, P:pfractions}
59sys.modules['decimal'] = orig_sys_decimal
60
61
62# Useful Test Constant
63Signals = {
64 C: tuple(C.getcontext().flags.keys()) if C else None,
65 P: tuple(P.getcontext().flags.keys())
66}
Mark Dickinsonc69160e2010-05-04 14:35:33 +000067# Signals ordered with respect to precedence: when an operation
68# produces multiple signals, signals occurring later in the list
69# should be handled before those occurring earlier in the list.
Stefan Krah1919b7e2012-03-21 18:25:23 +010070OrderedSignals = {
71 C: [C.Clamped, C.Rounded, C.Inexact, C.Subnormal, C.Underflow,
72 C.Overflow, C.DivisionByZero, C.InvalidOperation,
73 C.FloatOperation] if C else None,
74 P: [P.Clamped, P.Rounded, P.Inexact, P.Subnormal, P.Underflow,
75 P.Overflow, P.DivisionByZero, P.InvalidOperation,
76 P.FloatOperation]
77}
78def assert_signals(cls, context, attr, expected):
79 d = getattr(context, attr)
80 cls.assertTrue(all(d[s] if s in expected else not d[s] for s in d))
81
Stefan Krah59a4a932013-01-16 12:58:59 +010082ROUND_UP = P.ROUND_UP
83ROUND_DOWN = P.ROUND_DOWN
84ROUND_CEILING = P.ROUND_CEILING
85ROUND_FLOOR = P.ROUND_FLOOR
86ROUND_HALF_UP = P.ROUND_HALF_UP
87ROUND_HALF_DOWN = P.ROUND_HALF_DOWN
88ROUND_HALF_EVEN = P.ROUND_HALF_EVEN
89ROUND_05UP = P.ROUND_05UP
90
91RoundingModes = [
92 ROUND_UP, ROUND_DOWN, ROUND_CEILING, ROUND_FLOOR,
93 ROUND_HALF_UP, ROUND_HALF_DOWN, ROUND_HALF_EVEN,
94 ROUND_05UP
95]
Mark Dickinsonc69160e2010-05-04 14:35:33 +000096
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000097# Tests are built around these assumed context defaults.
98# test_main() restores the original context.
Stefan Krah1919b7e2012-03-21 18:25:23 +010099ORIGINAL_CONTEXT = {
100 C: C.getcontext().copy() if C else None,
101 P: P.getcontext().copy()
102}
103def init(m):
104 if not m: return
105 DefaultTestContext = m.Context(
Stefan Krah59a4a932013-01-16 12:58:59 +0100106 prec=9, rounding=ROUND_HALF_EVEN, traps=dict.fromkeys(Signals[m], 0)
Stefan Krah1919b7e2012-03-21 18:25:23 +0100107 )
108 m.setcontext(DefaultTestContext)
Raymond Hettinger6ea48452004-07-03 12:26:21 +0000109
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000110TESTDATADIR = 'decimaltestdata'
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000111if __name__ == '__main__':
112 file = sys.argv[0]
113else:
114 file = __file__
115testdir = os.path.dirname(file) or os.curdir
Raymond Hettinger267b8682005-03-27 10:47:39 +0000116directory = testdir + os.sep + TESTDATADIR + os.sep
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000117
Raymond Hettinger267b8682005-03-27 10:47:39 +0000118skip_expected = not os.path.isdir(directory)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000119
120# Make sure it actually raises errors when not expected and caught in flags
121# Slower, since it runs some things several times.
122EXTENDEDERRORTEST = False
123
Stefan Krah1919b7e2012-03-21 18:25:23 +0100124# Test extra functionality in the C version (-DEXTRA_FUNCTIONALITY).
125EXTRA_FUNCTIONALITY = True if hasattr(C, 'DecClamped') else False
126requires_extra_functionality = unittest.skipUnless(
127 EXTRA_FUNCTIONALITY, "test requires build with -DEXTRA_FUNCTIONALITY")
128skip_if_extra_functionality = unittest.skipIf(
129 EXTRA_FUNCTIONALITY, "test requires regular build")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000130
131
Stefan Krah1919b7e2012-03-21 18:25:23 +0100132class IBMTestCases(unittest.TestCase):
133 """Class which tests the Decimal class against the IBM test cases."""
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000134
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000135 def setUp(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100136 self.context = self.decimal.Context()
137 self.readcontext = self.decimal.Context()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000138 self.ignore_list = ['#']
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000139
Stefan Krah1919b7e2012-03-21 18:25:23 +0100140 # List of individual .decTest test ids that correspond to tests that
141 # we're skipping for one reason or another.
142 self.skipped_test_ids = set([
143 # Skip implementation-specific scaleb tests.
144 'scbx164',
145 'scbx165',
146
147 # For some operations (currently exp, ln, log10, power), the decNumber
148 # reference implementation imposes additional restrictions on the context
149 # and operands. These restrictions are not part of the specification;
150 # however, the effect of these restrictions does show up in some of the
151 # testcases. We skip testcases that violate these restrictions, since
152 # Decimal behaves differently from decNumber for these testcases so these
153 # testcases would otherwise fail.
154 'expx901',
155 'expx902',
156 'expx903',
157 'expx905',
158 'lnx901',
159 'lnx902',
160 'lnx903',
161 'lnx905',
162 'logx901',
163 'logx902',
164 'logx903',
165 'logx905',
166 'powx1183',
167 'powx1184',
168 'powx4001',
169 'powx4002',
170 'powx4003',
171 'powx4005',
172 'powx4008',
173 'powx4010',
174 'powx4012',
175 'powx4014',
176 ])
177
178 if self.decimal == C:
179 # status has additional Subnormal, Underflow
180 self.skipped_test_ids.add('pwsx803')
181 self.skipped_test_ids.add('pwsx805')
182 # Correct rounding (skipped for decNumber, too)
183 self.skipped_test_ids.add('powx4302')
184 self.skipped_test_ids.add('powx4303')
185 self.skipped_test_ids.add('powx4342')
186 self.skipped_test_ids.add('powx4343')
187 # http://bugs.python.org/issue7049
188 self.skipped_test_ids.add('pwmx325')
189 self.skipped_test_ids.add('pwmx326')
190
191 # Map test directives to setter functions.
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000192 self.ChangeDict = {'precision' : self.change_precision,
Stefan Krah1919b7e2012-03-21 18:25:23 +0100193 'rounding' : self.change_rounding_method,
194 'maxexponent' : self.change_max_exponent,
195 'minexponent' : self.change_min_exponent,
196 'clamp' : self.change_clamp}
197
198 # Name adapter to be able to change the Decimal and Context
199 # interface without changing the test files from Cowlishaw.
200 self.NameAdapter = {'and':'logical_and',
201 'apply':'_apply',
202 'class':'number_class',
203 'comparesig':'compare_signal',
204 'comparetotal':'compare_total',
205 'comparetotmag':'compare_total_mag',
206 'copy':'copy_decimal',
207 'copyabs':'copy_abs',
208 'copynegate':'copy_negate',
209 'copysign':'copy_sign',
210 'divideint':'divide_int',
211 'invert':'logical_invert',
212 'iscanonical':'is_canonical',
213 'isfinite':'is_finite',
214 'isinfinite':'is_infinite',
215 'isnan':'is_nan',
216 'isnormal':'is_normal',
217 'isqnan':'is_qnan',
218 'issigned':'is_signed',
219 'issnan':'is_snan',
220 'issubnormal':'is_subnormal',
221 'iszero':'is_zero',
222 'maxmag':'max_mag',
223 'minmag':'min_mag',
224 'nextminus':'next_minus',
225 'nextplus':'next_plus',
226 'nexttoward':'next_toward',
227 'or':'logical_or',
228 'reduce':'normalize',
229 'remaindernear':'remainder_near',
230 'samequantum':'same_quantum',
231 'squareroot':'sqrt',
232 'toeng':'to_eng_string',
233 'tointegral':'to_integral_value',
234 'tointegralx':'to_integral_exact',
235 'tosci':'to_sci_string',
236 'xor':'logical_xor'}
237
238 # Map test-case names to roundings.
Stefan Krah59a4a932013-01-16 12:58:59 +0100239 self.RoundingDict = {'ceiling' : ROUND_CEILING,
240 'down' : ROUND_DOWN,
241 'floor' : ROUND_FLOOR,
242 'half_down' : ROUND_HALF_DOWN,
243 'half_even' : ROUND_HALF_EVEN,
244 'half_up' : ROUND_HALF_UP,
245 'up' : ROUND_UP,
246 '05up' : ROUND_05UP}
Stefan Krah1919b7e2012-03-21 18:25:23 +0100247
248 # Map the test cases' error names to the actual errors.
249 self.ErrorNames = {'clamped' : self.decimal.Clamped,
250 'conversion_syntax' : self.decimal.InvalidOperation,
251 'division_by_zero' : self.decimal.DivisionByZero,
252 'division_impossible' : self.decimal.InvalidOperation,
253 'division_undefined' : self.decimal.InvalidOperation,
254 'inexact' : self.decimal.Inexact,
255 'invalid_context' : self.decimal.InvalidOperation,
256 'invalid_operation' : self.decimal.InvalidOperation,
257 'overflow' : self.decimal.Overflow,
258 'rounded' : self.decimal.Rounded,
259 'subnormal' : self.decimal.Subnormal,
260 'underflow' : self.decimal.Underflow}
261
262 # The following functions return True/False rather than a
263 # Decimal instance.
264 self.LogicalFunctions = ('is_canonical',
265 'is_finite',
266 'is_infinite',
267 'is_nan',
268 'is_normal',
269 'is_qnan',
270 'is_signed',
271 'is_snan',
272 'is_subnormal',
273 'is_zero',
274 'same_quantum')
275
276 def read_unlimited(self, v, context):
277 """Work around the limitations of the 32-bit _decimal version. The
278 guaranteed maximum values for prec, Emax etc. are 425000000,
279 but higher values usually work, except for rare corner cases.
280 In particular, all of the IBM tests pass with maximum values
281 of 1070000000."""
282 if self.decimal == C and self.decimal.MAX_EMAX == 425000000:
283 self.readcontext._unsafe_setprec(1070000000)
284 self.readcontext._unsafe_setemax(1070000000)
285 self.readcontext._unsafe_setemin(-1070000000)
286 return self.readcontext.create_decimal(v)
287 else:
288 return self.decimal.Decimal(v, context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000289
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000290 def eval_file(self, file):
291 global skip_expected
292 if skip_expected:
Benjamin Petersone549ead2009-03-28 21:42:05 +0000293 raise unittest.SkipTest
Antoine Pitrou92f60ed2010-10-14 22:11:44 +0000294 with open(file) as f:
295 for line in f:
296 line = line.replace('\r\n', '').replace('\n', '')
297 #print line
298 try:
299 t = self.eval_line(line)
Stefan Krah1919b7e2012-03-21 18:25:23 +0100300 except self.decimal.DecimalException as exception:
Ezio Melotti13925002011-03-16 11:05:33 +0200301 #Exception raised where there shouldn't have been one.
Antoine Pitrou92f60ed2010-10-14 22:11:44 +0000302 self.fail('Exception "'+exception.__class__.__name__ + '" raised on line '+line)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000303
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000304
305 def eval_line(self, s):
306 if s.find(' -> ') >= 0 and s[:2] != '--' and not s.startswith(' --'):
307 s = (s.split('->')[0] + '->' +
308 s.split('->')[1].split('--')[0]).strip()
309 else:
310 s = s.split('--')[0].strip()
311
312 for ignore in self.ignore_list:
313 if s.find(ignore) >= 0:
314 #print s.split()[0], 'NotImplemented--', ignore
315 return
316 if not s:
317 return
318 elif ':' in s:
319 return self.eval_directive(s)
320 else:
321 return self.eval_equation(s)
322
323 def eval_directive(self, s):
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000324 funct, value = (x.strip().lower() for x in s.split(':'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000325 if funct == 'rounding':
Stefan Krah1919b7e2012-03-21 18:25:23 +0100326 value = self.RoundingDict[value]
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000327 else:
328 try:
329 value = int(value)
330 except ValueError:
331 pass
332
Stefan Krah1919b7e2012-03-21 18:25:23 +0100333 funct = self.ChangeDict.get(funct, (lambda *args: None))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000334 funct(value)
335
336 def eval_equation(self, s):
Raymond Hettingered20ad82004-09-04 20:09:13 +0000337
338 if not TEST_ALL and random.random() < 0.90:
339 return
340
Stefan Krah1919b7e2012-03-21 18:25:23 +0100341 self.context.clear_flags()
342
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000343 try:
344 Sides = s.split('->')
345 L = Sides[0].strip().split()
346 id = L[0]
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000347 if DEBUG:
348 print("Test ", id, end=" ")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000349 funct = L[1].lower()
350 valstemp = L[2:]
351 L = Sides[1].strip().split()
352 ans = L[0]
353 exceptions = L[1:]
354 except (TypeError, AttributeError, IndexError):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100355 raise self.decimal.InvalidOperation
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000356 def FixQuotes(val):
357 val = val.replace("''", 'SingleQuote').replace('""', 'DoubleQuote')
358 val = val.replace("'", '').replace('"', '')
359 val = val.replace('SingleQuote', "'").replace('DoubleQuote', '"')
360 return val
Mark Dickinson8a546532009-10-08 16:30:38 +0000361
Stefan Krah1919b7e2012-03-21 18:25:23 +0100362 if id in self.skipped_test_ids:
Mark Dickinson8a546532009-10-08 16:30:38 +0000363 return
364
Stefan Krah1919b7e2012-03-21 18:25:23 +0100365 fname = self.NameAdapter.get(funct, funct)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000366 if fname == 'rescale':
367 return
368 funct = getattr(self.context, fname)
369 vals = []
370 conglomerate = ''
371 quote = 0
Stefan Krah1919b7e2012-03-21 18:25:23 +0100372 theirexceptions = [self.ErrorNames[x.lower()] for x in exceptions]
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000373
Stefan Krah1919b7e2012-03-21 18:25:23 +0100374 for exception in Signals[self.decimal]:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000375 self.context.traps[exception] = 1 #Catch these bugs...
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000376 for exception in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000377 self.context.traps[exception] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000378 for i, val in enumerate(valstemp):
379 if val.count("'") % 2 == 1:
380 quote = 1 - quote
381 if quote:
382 conglomerate = conglomerate + ' ' + val
383 continue
384 else:
385 val = conglomerate + val
386 conglomerate = ''
387 v = FixQuotes(val)
388 if fname in ('to_sci_string', 'to_eng_string'):
389 if EXTENDEDERRORTEST:
390 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000391 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000392 try:
393 funct(self.context.create_decimal(v))
394 except error:
395 pass
Stefan Krah1919b7e2012-03-21 18:25:23 +0100396 except Signals[self.decimal] as e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000397 self.fail("Raised %s in %s when %s disabled" % \
398 (e, s, error))
399 else:
400 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000401 self.context.traps[error] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000402 v = self.context.create_decimal(v)
403 else:
Stefan Krah1919b7e2012-03-21 18:25:23 +0100404 v = self.read_unlimited(v, self.context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000405 vals.append(v)
406
407 ans = FixQuotes(ans)
408
409 if EXTENDEDERRORTEST and fname not in ('to_sci_string', 'to_eng_string'):
410 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000411 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000412 try:
413 funct(*vals)
414 except error:
415 pass
Stefan Krah1919b7e2012-03-21 18:25:23 +0100416 except Signals[self.decimal] as e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000417 self.fail("Raised %s in %s when %s disabled" % \
418 (e, s, error))
419 else:
420 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000421 self.context.traps[error] = 0
Mark Dickinsonc69160e2010-05-04 14:35:33 +0000422
423 # as above, but add traps cumulatively, to check precedence
Stefan Krah1919b7e2012-03-21 18:25:23 +0100424 ordered_errors = [e for e in OrderedSignals[self.decimal] if e in theirexceptions]
Mark Dickinsonc69160e2010-05-04 14:35:33 +0000425 for error in ordered_errors:
426 self.context.traps[error] = 1
427 try:
428 funct(*vals)
429 except error:
430 pass
Stefan Krah1919b7e2012-03-21 18:25:23 +0100431 except Signals[self.decimal] as e:
Mark Dickinsonc69160e2010-05-04 14:35:33 +0000432 self.fail("Raised %s in %s; expected %s" %
433 (type(e), s, error))
434 else:
435 self.fail("Did not raise %s in %s" % (error, s))
436 # reset traps
437 for error in ordered_errors:
438 self.context.traps[error] = 0
439
440
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000441 if DEBUG:
442 print("--", self.context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000443 try:
444 result = str(funct(*vals))
Stefan Krah1919b7e2012-03-21 18:25:23 +0100445 if fname in self.LogicalFunctions:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000446 result = str(int(eval(result))) # 'True', 'False' -> '1', '0'
Stefan Krah1919b7e2012-03-21 18:25:23 +0100447 except Signals[self.decimal] as error:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000448 self.fail("Raised %s in %s" % (error, s))
449 except: #Catch any error long enough to state the test case.
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000450 print("ERROR:", s)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000451 raise
452
453 myexceptions = self.getexceptions()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000454
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000455 myexceptions.sort(key=repr)
456 theirexceptions.sort(key=repr)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000457
458 self.assertEqual(result, ans,
459 'Incorrect answer for ' + s + ' -- got ' + result)
Stefan Krah1919b7e2012-03-21 18:25:23 +0100460
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000461 self.assertEqual(myexceptions, theirexceptions,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000462 'Incorrect flags set in ' + s + ' -- got ' + str(myexceptions))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000463
464 def getexceptions(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100465 return [e for e in Signals[self.decimal] if self.context.flags[e]]
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000466
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000467 def change_precision(self, prec):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100468 if self.decimal == C and self.decimal.MAX_PREC == 425000000:
469 self.context._unsafe_setprec(prec)
470 else:
471 self.context.prec = prec
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000472 def change_rounding_method(self, rounding):
473 self.context.rounding = rounding
474 def change_min_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_setemin(exp)
477 else:
478 self.context.Emin = exp
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000479 def change_max_exponent(self, exp):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100480 if self.decimal == C and self.decimal.MAX_PREC == 425000000:
481 self.context._unsafe_setemax(exp)
482 else:
483 self.context.Emax = exp
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000484 def change_clamp(self, clamp):
Mark Dickinsonb1d8e322010-05-22 18:35:36 +0000485 self.context.clamp = clamp
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000486
Stefan Krah1919b7e2012-03-21 18:25:23 +0100487class CIBMTestCases(IBMTestCases):
488 decimal = C
489class PyIBMTestCases(IBMTestCases):
490 decimal = P
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000491
492# The following classes test the behaviour of Decimal according to PEP 327
493
Stefan Krah1919b7e2012-03-21 18:25:23 +0100494class ExplicitConstructionTest(unittest.TestCase):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000495 '''Unit tests for Explicit Construction cases of Decimal.'''
496
497 def test_explicit_empty(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100498 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000499 self.assertEqual(Decimal(), Decimal("0"))
500
501 def test_explicit_from_None(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100502 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000503 self.assertRaises(TypeError, Decimal, None)
504
505 def test_explicit_from_int(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100506 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000507
508 #positive
509 d = Decimal(45)
510 self.assertEqual(str(d), '45')
511
512 #very large positive
513 d = Decimal(500000123)
514 self.assertEqual(str(d), '500000123')
515
516 #negative
517 d = Decimal(-45)
518 self.assertEqual(str(d), '-45')
519
520 #zero
521 d = Decimal(0)
522 self.assertEqual(str(d), '0')
523
Stefan Krah1919b7e2012-03-21 18:25:23 +0100524 # single word longs
525 for n in range(0, 32):
526 for sign in (-1, 1):
527 for x in range(-5, 5):
528 i = sign * (2**n + x)
529 d = Decimal(i)
530 self.assertEqual(str(d), str(i))
531
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000532 def test_explicit_from_string(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100533 Decimal = self.decimal.Decimal
534 InvalidOperation = self.decimal.InvalidOperation
535 localcontext = self.decimal.localcontext
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000536
537 #empty
538 self.assertEqual(str(Decimal('')), 'NaN')
539
540 #int
541 self.assertEqual(str(Decimal('45')), '45')
542
543 #float
544 self.assertEqual(str(Decimal('45.34')), '45.34')
545
546 #engineer notation
547 self.assertEqual(str(Decimal('45e2')), '4.5E+3')
548
549 #just not a number
550 self.assertEqual(str(Decimal('ugly')), 'NaN')
551
Christian Heimesa62da1d2008-01-12 19:39:10 +0000552 #leading and trailing whitespace permitted
553 self.assertEqual(str(Decimal('1.3E4 \n')), '1.3E+4')
554 self.assertEqual(str(Decimal(' -7.89')), '-7.89')
Stefan Krah1919b7e2012-03-21 18:25:23 +0100555 self.assertEqual(str(Decimal(" 3.45679 ")), '3.45679')
556
557 # unicode whitespace
558 for lead in ["", ' ', '\u00a0', '\u205f']:
559 for trail in ["", ' ', '\u00a0', '\u205f']:
560 self.assertEqual(str(Decimal(lead + '9.311E+28' + trail)),
561 '9.311E+28')
562
563 with localcontext() as c:
564 c.traps[InvalidOperation] = True
565 # Invalid string
566 self.assertRaises(InvalidOperation, Decimal, "xyz")
567 # Two arguments max
568 self.assertRaises(TypeError, Decimal, "1234", "x", "y")
569
570 # space within the numeric part
571 self.assertRaises(InvalidOperation, Decimal, "1\u00a02\u00a03")
572 self.assertRaises(InvalidOperation, Decimal, "\u00a01\u00a02\u00a0")
573
574 # unicode whitespace
575 self.assertRaises(InvalidOperation, Decimal, "\u00a0")
576 self.assertRaises(InvalidOperation, Decimal, "\u00a0\u00a0")
577
578 # embedded NUL
579 self.assertRaises(InvalidOperation, Decimal, "12\u00003")
580
Stefan Krah6e467042012-11-10 23:09:04 +0100581 @cpython_only
582 def test_from_legacy_strings(self):
583 import _testcapi
584 Decimal = self.decimal.Decimal
585 context = self.decimal.Context()
586
587 s = _testcapi.unicode_legacy_string('9.999999')
588 self.assertEqual(str(Decimal(s)), '9.999999')
589 self.assertEqual(str(context.create_decimal(s)), '9.999999')
Christian Heimesa62da1d2008-01-12 19:39:10 +0000590
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000591 def test_explicit_from_tuples(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100592 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000593
594 #zero
595 d = Decimal( (0, (0,), 0) )
596 self.assertEqual(str(d), '0')
597
598 #int
599 d = Decimal( (1, (4, 5), 0) )
600 self.assertEqual(str(d), '-45')
601
602 #float
603 d = Decimal( (0, (4, 5, 3, 4), -2) )
604 self.assertEqual(str(d), '45.34')
605
606 #weird
607 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
608 self.assertEqual(str(d), '-4.34913534E-17')
609
Stefan Krah1919b7e2012-03-21 18:25:23 +0100610 #inf
611 d = Decimal( (0, (), "F") )
612 self.assertEqual(str(d), 'Infinity')
613
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000614 #wrong number of items
615 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1)) )
616
617 #bad sign
618 self.assertRaises(ValueError, Decimal, (8, (4, 3, 4, 9, 1), 2) )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000619 self.assertRaises(ValueError, Decimal, (0., (4, 3, 4, 9, 1), 2) )
620 self.assertRaises(ValueError, Decimal, (Decimal(1), (4, 3, 4, 9, 1), 2))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000621
622 #bad exp
623 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 'wrong!') )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000624 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 0.) )
625 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), '1') )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000626
627 #bad coefficients
Stefan Krah1919b7e2012-03-21 18:25:23 +0100628 self.assertRaises(ValueError, Decimal, (1, "xyz", 2) )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000629 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, None, 1), 2) )
630 self.assertRaises(ValueError, Decimal, (1, (4, -3, 4, 9, 1), 2) )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000631 self.assertRaises(ValueError, Decimal, (1, (4, 10, 4, 9, 1), 2) )
Guido van Rossum0d3fb8a2007-11-26 23:23:18 +0000632 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 'a', 1), 2) )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000633
Stefan Krah1919b7e2012-03-21 18:25:23 +0100634 def test_explicit_from_list(self):
635 Decimal = self.decimal.Decimal
636
637 d = Decimal([0, [0], 0])
638 self.assertEqual(str(d), '0')
639
640 d = Decimal([1, [4, 3, 4, 9, 1, 3, 5, 3, 4], -25])
641 self.assertEqual(str(d), '-4.34913534E-17')
642
643 d = Decimal([1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25])
644 self.assertEqual(str(d), '-4.34913534E-17')
645
646 d = Decimal((1, [4, 3, 4, 9, 1, 3, 5, 3, 4], -25))
647 self.assertEqual(str(d), '-4.34913534E-17')
648
Antoine Pitrou503ab332010-03-30 18:56:19 +0000649 def test_explicit_from_bool(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100650 Decimal = self.decimal.Decimal
651
Antoine Pitrou503ab332010-03-30 18:56:19 +0000652 self.assertIs(bool(Decimal(0)), False)
653 self.assertIs(bool(Decimal(1)), True)
654 self.assertEqual(Decimal(False), Decimal(0))
655 self.assertEqual(Decimal(True), Decimal(1))
656
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000657 def test_explicit_from_Decimal(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100658 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000659
660 #positive
661 d = Decimal(45)
662 e = Decimal(d)
663 self.assertEqual(str(e), '45')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000664
665 #very large positive
666 d = Decimal(500000123)
667 e = Decimal(d)
668 self.assertEqual(str(e), '500000123')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000669
670 #negative
671 d = Decimal(-45)
672 e = Decimal(d)
673 self.assertEqual(str(e), '-45')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000674
675 #zero
676 d = Decimal(0)
677 e = Decimal(d)
678 self.assertEqual(str(e), '0')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000679
Raymond Hettinger96798592010-04-02 16:58:27 +0000680 @requires_IEEE_754
681 def test_explicit_from_float(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100682
683 Decimal = self.decimal.Decimal
684
Raymond Hettinger96798592010-04-02 16:58:27 +0000685 r = Decimal(0.1)
686 self.assertEqual(type(r), Decimal)
687 self.assertEqual(str(r),
688 '0.1000000000000000055511151231257827021181583404541015625')
689 self.assertTrue(Decimal(float('nan')).is_qnan())
690 self.assertTrue(Decimal(float('inf')).is_infinite())
691 self.assertTrue(Decimal(float('-inf')).is_infinite())
692 self.assertEqual(str(Decimal(float('nan'))),
693 str(Decimal('NaN')))
694 self.assertEqual(str(Decimal(float('inf'))),
695 str(Decimal('Infinity')))
696 self.assertEqual(str(Decimal(float('-inf'))),
697 str(Decimal('-Infinity')))
698 self.assertEqual(str(Decimal(float('-0.0'))),
699 str(Decimal('-0')))
700 for i in range(200):
701 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
702 self.assertEqual(x, float(Decimal(x))) # roundtrip
703
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000704 def test_explicit_context_create_decimal(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100705 Decimal = self.decimal.Decimal
706 InvalidOperation = self.decimal.InvalidOperation
707 Rounded = self.decimal.Rounded
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000708
Stefan Krah1919b7e2012-03-21 18:25:23 +0100709 nc = copy.copy(self.decimal.getcontext())
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000710 nc.prec = 3
711
712 # empty
Raymond Hettingerfed52962004-07-14 15:41:57 +0000713 d = Decimal()
714 self.assertEqual(str(d), '0')
715 d = nc.create_decimal()
716 self.assertEqual(str(d), '0')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000717
718 # from None
719 self.assertRaises(TypeError, nc.create_decimal, None)
720
721 # from int
722 d = nc.create_decimal(456)
Ezio Melottie9615932010-01-24 19:26:24 +0000723 self.assertIsInstance(d, Decimal)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000724 self.assertEqual(nc.create_decimal(45678),
725 nc.create_decimal('457E+2'))
726
727 # from string
728 d = Decimal('456789')
729 self.assertEqual(str(d), '456789')
730 d = nc.create_decimal('456789')
731 self.assertEqual(str(d), '4.57E+5')
Christian Heimesa62da1d2008-01-12 19:39:10 +0000732 # leading and trailing whitespace should result in a NaN;
733 # spaces are already checked in Cowlishaw's test-suite, so
734 # here we just check that a trailing newline results in a NaN
735 self.assertEqual(str(nc.create_decimal('3.14\n')), 'NaN')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000736
737 # from tuples
738 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
739 self.assertEqual(str(d), '-4.34913534E-17')
740 d = nc.create_decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
741 self.assertEqual(str(d), '-4.35E-17')
742
743 # from Decimal
744 prevdec = Decimal(500000123)
745 d = Decimal(prevdec)
746 self.assertEqual(str(d), '500000123')
747 d = nc.create_decimal(prevdec)
748 self.assertEqual(str(d), '5.00E+8')
749
Stefan Krah1919b7e2012-03-21 18:25:23 +0100750 # more integers
751 nc.prec = 28
752 nc.traps[InvalidOperation] = True
753
754 for v in [-2**63-1, -2**63, -2**31-1, -2**31, 0,
755 2**31-1, 2**31, 2**63-1, 2**63]:
756 d = nc.create_decimal(v)
757 self.assertTrue(isinstance(d, Decimal))
758 self.assertEqual(int(d), v)
759
760 nc.prec = 3
761 nc.traps[Rounded] = True
762 self.assertRaises(Rounded, nc.create_decimal, 1234)
763
764 # from string
765 nc.prec = 28
766 self.assertEqual(str(nc.create_decimal('0E-017')), '0E-17')
767 self.assertEqual(str(nc.create_decimal('45')), '45')
768 self.assertEqual(str(nc.create_decimal('-Inf')), '-Infinity')
769 self.assertEqual(str(nc.create_decimal('NaN123')), 'NaN123')
770
771 # invalid arguments
772 self.assertRaises(InvalidOperation, nc.create_decimal, "xyz")
773 self.assertRaises(ValueError, nc.create_decimal, (1, "xyz", -25))
774 self.assertRaises(TypeError, nc.create_decimal, "1234", "5678")
775
776 # too many NaN payload digits
777 nc.prec = 3
778 self.assertRaises(InvalidOperation, nc.create_decimal, 'NaN12345')
779 self.assertRaises(InvalidOperation, nc.create_decimal,
780 Decimal('NaN12345'))
781
782 nc.traps[InvalidOperation] = False
783 self.assertEqual(str(nc.create_decimal('NaN12345')), 'NaN')
784 self.assertTrue(nc.flags[InvalidOperation])
785
786 nc.flags[InvalidOperation] = False
787 self.assertEqual(str(nc.create_decimal(Decimal('NaN12345'))), 'NaN')
788 self.assertTrue(nc.flags[InvalidOperation])
789
790 def test_explicit_context_create_from_float(self):
791
792 Decimal = self.decimal.Decimal
793
794 nc = self.decimal.Context()
795 r = nc.create_decimal(0.1)
796 self.assertEqual(type(r), Decimal)
797 self.assertEqual(str(r), '0.1000000000000000055511151231')
798 self.assertTrue(nc.create_decimal(float('nan')).is_qnan())
799 self.assertTrue(nc.create_decimal(float('inf')).is_infinite())
800 self.assertTrue(nc.create_decimal(float('-inf')).is_infinite())
801 self.assertEqual(str(nc.create_decimal(float('nan'))),
802 str(nc.create_decimal('NaN')))
803 self.assertEqual(str(nc.create_decimal(float('inf'))),
804 str(nc.create_decimal('Infinity')))
805 self.assertEqual(str(nc.create_decimal(float('-inf'))),
806 str(nc.create_decimal('-Infinity')))
807 self.assertEqual(str(nc.create_decimal(float('-0.0'))),
808 str(nc.create_decimal('-0')))
809 nc.prec = 100
810 for i in range(200):
811 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
812 self.assertEqual(x, float(nc.create_decimal(x))) # roundtrip
813
Mark Dickinson345adc42009-08-02 10:14:23 +0000814 def test_unicode_digits(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100815 Decimal = self.decimal.Decimal
816
Mark Dickinson345adc42009-08-02 10:14:23 +0000817 test_values = {
818 '\uff11': '1',
819 '\u0660.\u0660\u0663\u0667\u0662e-\u0663' : '0.0000372',
820 '-nan\u0c68\u0c6a\u0c66\u0c66' : '-NaN2400',
821 }
822 for input, expected in test_values.items():
823 self.assertEqual(str(Decimal(input)), expected)
824
Stefan Krah1919b7e2012-03-21 18:25:23 +0100825class CExplicitConstructionTest(ExplicitConstructionTest):
826 decimal = C
827class PyExplicitConstructionTest(ExplicitConstructionTest):
828 decimal = P
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000829
Stefan Krah1919b7e2012-03-21 18:25:23 +0100830class ImplicitConstructionTest(unittest.TestCase):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000831 '''Unit tests for Implicit Construction cases of Decimal.'''
832
833 def test_implicit_from_None(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100834 Decimal = self.decimal.Decimal
835 self.assertRaises(TypeError, eval, 'Decimal(5) + None', locals())
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000836
837 def test_implicit_from_int(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100838 Decimal = self.decimal.Decimal
839
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000840 #normal
841 self.assertEqual(str(Decimal(5) + 45), '50')
842 #exceeding precision
843 self.assertEqual(Decimal(5) + 123456789000, Decimal(123456789000))
844
845 def test_implicit_from_string(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100846 Decimal = self.decimal.Decimal
847 self.assertRaises(TypeError, eval, 'Decimal(5) + "3"', locals())
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000848
849 def test_implicit_from_float(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100850 Decimal = self.decimal.Decimal
851 self.assertRaises(TypeError, eval, 'Decimal(5) + 2.2', locals())
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000852
853 def test_implicit_from_Decimal(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100854 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000855 self.assertEqual(Decimal(5) + Decimal(45), Decimal(50))
856
Raymond Hettinger267b8682005-03-27 10:47:39 +0000857 def test_rop(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100858 Decimal = self.decimal.Decimal
859
Raymond Hettinger267b8682005-03-27 10:47:39 +0000860 # Allow other classes to be trained to interact with Decimals
861 class E:
862 def __divmod__(self, other):
863 return 'divmod ' + str(other)
864 def __rdivmod__(self, other):
865 return str(other) + ' rdivmod'
866 def __lt__(self, other):
867 return 'lt ' + str(other)
868 def __gt__(self, other):
869 return 'gt ' + str(other)
870 def __le__(self, other):
871 return 'le ' + str(other)
872 def __ge__(self, other):
873 return 'ge ' + str(other)
874 def __eq__(self, other):
875 return 'eq ' + str(other)
876 def __ne__(self, other):
877 return 'ne ' + str(other)
878
879 self.assertEqual(divmod(E(), Decimal(10)), 'divmod 10')
880 self.assertEqual(divmod(Decimal(10), E()), '10 rdivmod')
881 self.assertEqual(eval('Decimal(10) < E()'), 'gt 10')
882 self.assertEqual(eval('Decimal(10) > E()'), 'lt 10')
883 self.assertEqual(eval('Decimal(10) <= E()'), 'ge 10')
884 self.assertEqual(eval('Decimal(10) >= E()'), 'le 10')
885 self.assertEqual(eval('Decimal(10) == E()'), 'eq 10')
886 self.assertEqual(eval('Decimal(10) != E()'), 'ne 10')
887
888 # insert operator methods and then exercise them
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000889 oplist = [
890 ('+', '__add__', '__radd__'),
891 ('-', '__sub__', '__rsub__'),
892 ('*', '__mul__', '__rmul__'),
Thomas Woutersdcc6d322006-04-21 11:30:52 +0000893 ('/', '__truediv__', '__rtruediv__'),
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000894 ('%', '__mod__', '__rmod__'),
895 ('//', '__floordiv__', '__rfloordiv__'),
896 ('**', '__pow__', '__rpow__')
897 ]
Raymond Hettinger267b8682005-03-27 10:47:39 +0000898
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000899 for sym, lop, rop in oplist:
Raymond Hettinger267b8682005-03-27 10:47:39 +0000900 setattr(E, lop, lambda self, other: 'str' + lop + str(other))
901 setattr(E, rop, lambda self, other: str(other) + rop + 'str')
902 self.assertEqual(eval('E()' + sym + 'Decimal(10)'),
903 'str' + lop + '10')
904 self.assertEqual(eval('Decimal(10)' + sym + 'E()'),
905 '10' + rop + 'str')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000906
Stefan Krah1919b7e2012-03-21 18:25:23 +0100907class CImplicitConstructionTest(ImplicitConstructionTest):
908 decimal = C
909class PyImplicitConstructionTest(ImplicitConstructionTest):
910 decimal = P
Mark Dickinson79f52032009-03-17 23:12:51 +0000911
Stefan Krah1919b7e2012-03-21 18:25:23 +0100912class FormatTest(unittest.TestCase):
Christian Heimesf16baeb2008-02-29 14:57:44 +0000913 '''Unit tests for the format function.'''
914 def test_formatting(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100915 Decimal = self.decimal.Decimal
916
Christian Heimesf16baeb2008-02-29 14:57:44 +0000917 # triples giving a format, a Decimal, and the expected result
918 test_values = [
919 ('e', '0E-15', '0e-15'),
920 ('e', '2.3E-15', '2.3e-15'),
921 ('e', '2.30E+2', '2.30e+2'), # preserve significant zeros
922 ('e', '2.30000E-15', '2.30000e-15'),
923 ('e', '1.23456789123456789e40', '1.23456789123456789e+40'),
924 ('e', '1.5', '1.5e+0'),
925 ('e', '0.15', '1.5e-1'),
926 ('e', '0.015', '1.5e-2'),
927 ('e', '0.0000000000015', '1.5e-12'),
928 ('e', '15.0', '1.50e+1'),
929 ('e', '-15', '-1.5e+1'),
930 ('e', '0', '0e+0'),
931 ('e', '0E1', '0e+1'),
932 ('e', '0.0', '0e-1'),
933 ('e', '0.00', '0e-2'),
934 ('.6e', '0E-15', '0.000000e-9'),
935 ('.6e', '0', '0.000000e+6'),
936 ('.6e', '9.999999', '9.999999e+0'),
937 ('.6e', '9.9999999', '1.000000e+1'),
938 ('.6e', '-1.23e5', '-1.230000e+5'),
939 ('.6e', '1.23456789e-3', '1.234568e-3'),
940 ('f', '0', '0'),
941 ('f', '0.0', '0.0'),
942 ('f', '0E-2', '0.00'),
943 ('f', '0.00E-8', '0.0000000000'),
944 ('f', '0E1', '0'), # loses exponent information
945 ('f', '3.2E1', '32'),
946 ('f', '3.2E2', '320'),
947 ('f', '3.20E2', '320'),
948 ('f', '3.200E2', '320.0'),
949 ('f', '3.2E-6', '0.0000032'),
950 ('.6f', '0E-15', '0.000000'), # all zeros treated equally
951 ('.6f', '0E1', '0.000000'),
952 ('.6f', '0', '0.000000'),
953 ('.0f', '0', '0'), # no decimal point
954 ('.0f', '0e-2', '0'),
955 ('.0f', '3.14159265', '3'),
956 ('.1f', '3.14159265', '3.1'),
957 ('.4f', '3.14159265', '3.1416'),
958 ('.6f', '3.14159265', '3.141593'),
959 ('.7f', '3.14159265', '3.1415926'), # round-half-even!
960 ('.8f', '3.14159265', '3.14159265'),
961 ('.9f', '3.14159265', '3.141592650'),
962
963 ('g', '0', '0'),
964 ('g', '0.0', '0.0'),
965 ('g', '0E1', '0e+1'),
966 ('G', '0E1', '0E+1'),
967 ('g', '0E-5', '0.00000'),
968 ('g', '0E-6', '0.000000'),
969 ('g', '0E-7', '0e-7'),
970 ('g', '-0E2', '-0e+2'),
971 ('.0g', '3.14159265', '3'), # 0 sig fig -> 1 sig fig
Stefan Krah1919b7e2012-03-21 18:25:23 +0100972 ('.0n', '3.14159265', '3'), # same for 'n'
Christian Heimesf16baeb2008-02-29 14:57:44 +0000973 ('.1g', '3.14159265', '3'),
974 ('.2g', '3.14159265', '3.1'),
975 ('.5g', '3.14159265', '3.1416'),
976 ('.7g', '3.14159265', '3.141593'),
977 ('.8g', '3.14159265', '3.1415926'), # round-half-even!
978 ('.9g', '3.14159265', '3.14159265'),
979 ('.10g', '3.14159265', '3.14159265'), # don't pad
980
981 ('%', '0E1', '0%'),
982 ('%', '0E0', '0%'),
983 ('%', '0E-1', '0%'),
984 ('%', '0E-2', '0%'),
985 ('%', '0E-3', '0.0%'),
986 ('%', '0E-4', '0.00%'),
987
988 ('.3%', '0', '0.000%'), # all zeros treated equally
989 ('.3%', '0E10', '0.000%'),
990 ('.3%', '0E-10', '0.000%'),
991 ('.3%', '2.34', '234.000%'),
992 ('.3%', '1.234567', '123.457%'),
993 ('.0%', '1.23', '123%'),
994
995 ('e', 'NaN', 'NaN'),
996 ('f', '-NaN123', '-NaN123'),
997 ('+g', 'NaN456', '+NaN456'),
998 ('.3e', 'Inf', 'Infinity'),
999 ('.16f', '-Inf', '-Infinity'),
1000 ('.0g', '-sNaN', '-sNaN'),
1001
1002 ('', '1.00', '1.00'),
Mark Dickinsonad416342009-03-17 18:10:15 +00001003
Mark Dickinson79f52032009-03-17 23:12:51 +00001004 # test alignment and padding
Mark Dickinson46ab5d02009-09-08 20:22:46 +00001005 ('6', '123', ' 123'),
Mark Dickinsonad416342009-03-17 18:10:15 +00001006 ('<6', '123', '123 '),
1007 ('>6', '123', ' 123'),
1008 ('^6', '123', ' 123 '),
1009 ('=+6', '123', '+ 123'),
Mark Dickinson79f52032009-03-17 23:12:51 +00001010 ('#<10', 'NaN', 'NaN#######'),
1011 ('#<10', '-4.3', '-4.3######'),
1012 ('#<+10', '0.0130', '+0.0130###'),
1013 ('#< 10', '0.0130', ' 0.0130###'),
1014 ('@>10', '-Inf', '@-Infinity'),
1015 ('#>5', '-Inf', '-Infinity'),
1016 ('?^5', '123', '?123?'),
1017 ('%^6', '123', '%123%%'),
1018 (' ^6', '-45.6', '-45.6 '),
1019 ('/=10', '-45.6', '-/////45.6'),
1020 ('/=+10', '45.6', '+/////45.6'),
1021 ('/= 10', '45.6', ' /////45.6'),
Stefan Krah6edda142013-05-29 15:45:38 +02001022 ('\x00=10', '-inf', '-\x00Infinity'),
1023 ('\x00^16', '-inf', '\x00\x00\x00-Infinity\x00\x00\x00\x00'),
1024 ('\x00>10', '1.2345', '\x00\x00\x00\x001.2345'),
1025 ('\x00<10', '1.2345', '1.2345\x00\x00\x00\x00'),
Mark Dickinson79f52032009-03-17 23:12:51 +00001026
1027 # thousands separator
1028 (',', '1234567', '1,234,567'),
1029 (',', '123456', '123,456'),
1030 (',', '12345', '12,345'),
1031 (',', '1234', '1,234'),
1032 (',', '123', '123'),
1033 (',', '12', '12'),
1034 (',', '1', '1'),
1035 (',', '0', '0'),
1036 (',', '-1234567', '-1,234,567'),
1037 (',', '-123456', '-123,456'),
1038 ('7,', '123456', '123,456'),
Mark Dickinson46ab5d02009-09-08 20:22:46 +00001039 ('8,', '123456', ' 123,456'),
Mark Dickinson79f52032009-03-17 23:12:51 +00001040 ('08,', '123456', '0,123,456'), # special case: extra 0 needed
1041 ('+08,', '123456', '+123,456'), # but not if there's a sign
1042 (' 08,', '123456', ' 123,456'),
1043 ('08,', '-123456', '-123,456'),
1044 ('+09,', '123456', '+0,123,456'),
1045 # ... with fractional part...
1046 ('07,', '1234.56', '1,234.56'),
1047 ('08,', '1234.56', '1,234.56'),
1048 ('09,', '1234.56', '01,234.56'),
1049 ('010,', '1234.56', '001,234.56'),
1050 ('011,', '1234.56', '0,001,234.56'),
1051 ('012,', '1234.56', '0,001,234.56'),
1052 ('08,.1f', '1234.5', '01,234.5'),
1053 # no thousands separators in fraction part
1054 (',', '1.23456789', '1.23456789'),
1055 (',%', '123.456789', '12,345.6789%'),
1056 (',e', '123456', '1.23456e+5'),
1057 (',E', '123456', '1.23456E+5'),
Mark Dickinson7718d2b2009-09-07 16:21:56 +00001058
1059 # issue 6850
1060 ('a=-7.0', '0.12345', 'aaaa0.1'),
Stefan Krah298131a2014-08-26 20:46:49 +02001061
1062 # issue 22090
1063 ('<^+15.20%', 'inf', '<<+Infinity%<<<'),
1064 ('\x07>,%', 'sNaN1234567', 'sNaN1234567%'),
1065 ('=10.10%', 'NaN123', ' NaN123%'),
Christian Heimesf16baeb2008-02-29 14:57:44 +00001066 ]
1067 for fmt, d, result in test_values:
1068 self.assertEqual(format(Decimal(d), fmt), result)
1069
Stefan Krah1919b7e2012-03-21 18:25:23 +01001070 # bytes format argument
1071 self.assertRaises(TypeError, Decimal(1).__format__, b'-020')
1072
Mark Dickinson79f52032009-03-17 23:12:51 +00001073 def test_n_format(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001074 Decimal = self.decimal.Decimal
1075
Mark Dickinson79f52032009-03-17 23:12:51 +00001076 try:
1077 from locale import CHAR_MAX
1078 except ImportError:
Zachary Ware9fe6d862013-12-08 00:20:35 -06001079 self.skipTest('locale.CHAR_MAX not available')
Mark Dickinson79f52032009-03-17 23:12:51 +00001080
Stefan Krah1919b7e2012-03-21 18:25:23 +01001081 def make_grouping(lst):
1082 return ''.join([chr(x) for x in lst]) if self.decimal == C else lst
1083
1084 def get_fmt(x, override=None, fmt='n'):
1085 if self.decimal == C:
1086 return Decimal(x).__format__(fmt, override)
1087 else:
1088 return Decimal(x).__format__(fmt, _localeconv=override)
1089
Mark Dickinson79f52032009-03-17 23:12:51 +00001090 # Set up some localeconv-like dictionaries
1091 en_US = {
1092 'decimal_point' : '.',
Stefan Krah1919b7e2012-03-21 18:25:23 +01001093 'grouping' : make_grouping([3, 3, 0]),
1094 'thousands_sep' : ','
Mark Dickinson79f52032009-03-17 23:12:51 +00001095 }
1096
1097 fr_FR = {
1098 'decimal_point' : ',',
Stefan Krah1919b7e2012-03-21 18:25:23 +01001099 'grouping' : make_grouping([CHAR_MAX]),
Mark Dickinson79f52032009-03-17 23:12:51 +00001100 'thousands_sep' : ''
1101 }
1102
1103 ru_RU = {
1104 'decimal_point' : ',',
Stefan Krah1919b7e2012-03-21 18:25:23 +01001105 'grouping': make_grouping([3, 3, 0]),
Mark Dickinson79f52032009-03-17 23:12:51 +00001106 'thousands_sep' : ' '
1107 }
1108
1109 crazy = {
1110 'decimal_point' : '&',
Stefan Krah1919b7e2012-03-21 18:25:23 +01001111 'grouping': make_grouping([1, 4, 2, CHAR_MAX]),
Mark Dickinson79f52032009-03-17 23:12:51 +00001112 'thousands_sep' : '-'
1113 }
1114
Stefan Krah1919b7e2012-03-21 18:25:23 +01001115 dotsep_wide = {
1116 'decimal_point' : b'\xc2\xbf'.decode('utf-8'),
1117 'grouping': make_grouping([3, 3, 0]),
1118 'thousands_sep' : b'\xc2\xb4'.decode('utf-8')
1119 }
Mark Dickinson79f52032009-03-17 23:12:51 +00001120
1121 self.assertEqual(get_fmt(Decimal('12.7'), en_US), '12.7')
1122 self.assertEqual(get_fmt(Decimal('12.7'), fr_FR), '12,7')
1123 self.assertEqual(get_fmt(Decimal('12.7'), ru_RU), '12,7')
1124 self.assertEqual(get_fmt(Decimal('12.7'), crazy), '1-2&7')
1125
1126 self.assertEqual(get_fmt(123456789, en_US), '123,456,789')
1127 self.assertEqual(get_fmt(123456789, fr_FR), '123456789')
1128 self.assertEqual(get_fmt(123456789, ru_RU), '123 456 789')
1129 self.assertEqual(get_fmt(1234567890123, crazy), '123456-78-9012-3')
1130
1131 self.assertEqual(get_fmt(123456789, en_US, '.6n'), '1.23457e+8')
1132 self.assertEqual(get_fmt(123456789, fr_FR, '.6n'), '1,23457e+8')
1133 self.assertEqual(get_fmt(123456789, ru_RU, '.6n'), '1,23457e+8')
1134 self.assertEqual(get_fmt(123456789, crazy, '.6n'), '1&23457e+8')
1135
Mark Dickinson7303b592009-03-18 08:25:36 +00001136 # zero padding
1137 self.assertEqual(get_fmt(1234, fr_FR, '03n'), '1234')
1138 self.assertEqual(get_fmt(1234, fr_FR, '04n'), '1234')
1139 self.assertEqual(get_fmt(1234, fr_FR, '05n'), '01234')
1140 self.assertEqual(get_fmt(1234, fr_FR, '06n'), '001234')
1141
1142 self.assertEqual(get_fmt(12345, en_US, '05n'), '12,345')
1143 self.assertEqual(get_fmt(12345, en_US, '06n'), '12,345')
1144 self.assertEqual(get_fmt(12345, en_US, '07n'), '012,345')
1145 self.assertEqual(get_fmt(12345, en_US, '08n'), '0,012,345')
1146 self.assertEqual(get_fmt(12345, en_US, '09n'), '0,012,345')
1147 self.assertEqual(get_fmt(12345, en_US, '010n'), '00,012,345')
1148
1149 self.assertEqual(get_fmt(123456, crazy, '06n'), '1-2345-6')
1150 self.assertEqual(get_fmt(123456, crazy, '07n'), '1-2345-6')
1151 self.assertEqual(get_fmt(123456, crazy, '08n'), '1-2345-6')
1152 self.assertEqual(get_fmt(123456, crazy, '09n'), '01-2345-6')
1153 self.assertEqual(get_fmt(123456, crazy, '010n'), '0-01-2345-6')
1154 self.assertEqual(get_fmt(123456, crazy, '011n'), '0-01-2345-6')
1155 self.assertEqual(get_fmt(123456, crazy, '012n'), '00-01-2345-6')
1156 self.assertEqual(get_fmt(123456, crazy, '013n'), '000-01-2345-6')
1157
Stefan Krah1919b7e2012-03-21 18:25:23 +01001158 # wide char separator and decimal point
1159 self.assertEqual(get_fmt(Decimal('-1.5'), dotsep_wide, '020n'),
1160 '-0\u00b4000\u00b4000\u00b4000\u00b4001\u00bf5')
Mark Dickinson79f52032009-03-17 23:12:51 +00001161
Stefan Krah6fb204a2012-09-28 16:18:54 +02001162 @run_with_locale('LC_ALL', 'ps_AF')
Stefan Krah1919b7e2012-03-21 18:25:23 +01001163 def test_wide_char_separator_decimal_point(self):
1164 # locale with wide char separator and decimal point
Stefan Krah8a491a82012-09-28 17:17:11 +02001165 import locale
Stefan Krah1919b7e2012-03-21 18:25:23 +01001166 Decimal = self.decimal.Decimal
1167
Stefan Krah8a491a82012-09-28 17:17:11 +02001168 decimal_point = locale.localeconv()['decimal_point']
1169 thousands_sep = locale.localeconv()['thousands_sep']
Zachary Ware9fe6d862013-12-08 00:20:35 -06001170 if decimal_point != '\u066b':
1171 self.skipTest('inappropriate decimal point separator'
Zachary Ware0f533ac2013-12-12 10:32:16 -06001172 '({!a} not {!a})'.format(decimal_point, '\u066b'))
Zachary Ware9fe6d862013-12-08 00:20:35 -06001173 if thousands_sep != '\u066c':
1174 self.skipTest('inappropriate thousands separator'
Zachary Ware0f533ac2013-12-12 10:32:16 -06001175 '({!a} not {!a})'.format(thousands_sep, '\u066c'))
Stefan Krah8a491a82012-09-28 17:17:11 +02001176
Stefan Krah1919b7e2012-03-21 18:25:23 +01001177 self.assertEqual(format(Decimal('100000000.123'), 'n'),
1178 '100\u066c000\u066c000\u066b123')
Stefan Krah1919b7e2012-03-21 18:25:23 +01001179
1180class CFormatTest(FormatTest):
1181 decimal = C
1182class PyFormatTest(FormatTest):
1183 decimal = P
1184
1185class ArithmeticOperatorsTest(unittest.TestCase):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001186 '''Unit tests for all arithmetic operators, binary and unary.'''
1187
1188 def test_addition(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('11.1'))
1196 self.assertEqual(d2+d1, Decimal('11.1'))
1197
1198 #with other type, left
1199 c = d1 + 5
1200 self.assertEqual(c, Decimal('-6.1'))
1201 self.assertEqual(type(c), type(d1))
1202
1203 #with other type, right
1204 c = 5 + d1
1205 self.assertEqual(c, Decimal('-6.1'))
1206 self.assertEqual(type(c), type(d1))
1207
1208 #inline with decimal
1209 d1 += d2
1210 self.assertEqual(d1, Decimal('11.1'))
1211
1212 #inline with other type
1213 d1 += 5
1214 self.assertEqual(d1, Decimal('16.1'))
1215
1216 def test_subtraction(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001217 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001218
1219 d1 = Decimal('-11.1')
1220 d2 = Decimal('22.2')
1221
1222 #two Decimals
1223 self.assertEqual(d1-d2, Decimal('-33.3'))
1224 self.assertEqual(d2-d1, Decimal('33.3'))
1225
1226 #with other type, left
1227 c = d1 - 5
1228 self.assertEqual(c, Decimal('-16.1'))
1229 self.assertEqual(type(c), type(d1))
1230
1231 #with other type, right
1232 c = 5 - d1
1233 self.assertEqual(c, Decimal('16.1'))
1234 self.assertEqual(type(c), type(d1))
1235
1236 #inline with decimal
1237 d1 -= d2
1238 self.assertEqual(d1, Decimal('-33.3'))
1239
1240 #inline with other type
1241 d1 -= 5
1242 self.assertEqual(d1, Decimal('-38.3'))
1243
1244 def test_multiplication(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('3')
1249
1250 #two Decimals
1251 self.assertEqual(d1*d2, Decimal('-15'))
1252 self.assertEqual(d2*d1, Decimal('-15'))
1253
1254 #with other type, left
1255 c = d1 * 5
1256 self.assertEqual(c, Decimal('-25'))
1257 self.assertEqual(type(c), type(d1))
1258
1259 #with other type, right
1260 c = 5 * d1
1261 self.assertEqual(c, Decimal('-25'))
1262 self.assertEqual(type(c), type(d1))
1263
1264 #inline with decimal
1265 d1 *= d2
1266 self.assertEqual(d1, Decimal('-15'))
1267
1268 #inline with other type
1269 d1 *= 5
1270 self.assertEqual(d1, Decimal('-75'))
1271
1272 def test_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.5'))
1280 self.assertEqual(d2/d1, Decimal('-0.4'))
1281
1282 #with other type, left
1283 c = d1 / 4
1284 self.assertEqual(c, Decimal('-1.25'))
1285 self.assertEqual(type(c), type(d1))
1286
1287 #with other type, right
1288 c = 4 / d1
1289 self.assertEqual(c, Decimal('-0.8'))
1290 self.assertEqual(type(c), type(d1))
1291
1292 #inline with decimal
1293 d1 /= d2
1294 self.assertEqual(d1, Decimal('-2.5'))
1295
1296 #inline with other type
1297 d1 /= 4
1298 self.assertEqual(d1, Decimal('-0.625'))
1299
1300 def test_floor_division(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('2'))
1308 self.assertEqual(d2//d1, Decimal('0'))
1309
1310 #with other type, left
1311 c = d1 // 4
1312 self.assertEqual(c, Decimal('1'))
1313 self.assertEqual(type(c), type(d1))
1314
1315 #with other type, right
1316 c = 7 // d1
1317 self.assertEqual(c, Decimal('1'))
1318 self.assertEqual(type(c), type(d1))
1319
1320 #inline with decimal
1321 d1 //= d2
1322 self.assertEqual(d1, Decimal('2'))
1323
1324 #inline with other type
1325 d1 //= 2
1326 self.assertEqual(d1, Decimal('1'))
1327
1328 def test_powering(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('25'))
1336 self.assertEqual(d2**d1, Decimal('32'))
1337
1338 #with other type, left
1339 c = d1 ** 4
1340 self.assertEqual(c, Decimal('625'))
1341 self.assertEqual(type(c), type(d1))
1342
1343 #with other type, right
1344 c = 7 ** d1
1345 self.assertEqual(c, Decimal('16807'))
1346 self.assertEqual(type(c), type(d1))
1347
1348 #inline with decimal
1349 d1 **= d2
1350 self.assertEqual(d1, Decimal('25'))
1351
1352 #inline with other type
1353 d1 **= 4
1354 self.assertEqual(d1, Decimal('390625'))
1355
1356 def test_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 self.assertEqual(d1%d2, Decimal('1'))
1364 self.assertEqual(d2%d1, Decimal('2'))
1365
1366 #with other type, left
1367 c = d1 % 4
1368 self.assertEqual(c, Decimal('1'))
1369 self.assertEqual(type(c), type(d1))
1370
1371 #with other type, right
1372 c = 7 % d1
1373 self.assertEqual(c, Decimal('2'))
1374 self.assertEqual(type(c), type(d1))
1375
1376 #inline with decimal
1377 d1 %= d2
1378 self.assertEqual(d1, Decimal('1'))
1379
1380 #inline with other type
1381 d1 %= 4
1382 self.assertEqual(d1, Decimal('1'))
1383
1384 def test_floor_div_module(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001385 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001386
1387 d1 = Decimal('5')
1388 d2 = Decimal('2')
1389
1390 #two Decimals
1391 (p, q) = divmod(d1, d2)
1392 self.assertEqual(p, Decimal('2'))
1393 self.assertEqual(q, Decimal('1'))
1394 self.assertEqual(type(p), type(d1))
1395 self.assertEqual(type(q), type(d1))
1396
1397 #with other type, left
1398 (p, q) = divmod(d1, 4)
1399 self.assertEqual(p, Decimal('1'))
1400 self.assertEqual(q, Decimal('1'))
1401 self.assertEqual(type(p), type(d1))
1402 self.assertEqual(type(q), type(d1))
1403
1404 #with other type, right
1405 (p, q) = divmod(7, d1)
1406 self.assertEqual(p, Decimal('1'))
1407 self.assertEqual(q, Decimal('2'))
1408 self.assertEqual(type(p), type(d1))
1409 self.assertEqual(type(q), type(d1))
1410
1411 def test_unary_operators(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001412 Decimal = self.decimal.Decimal
1413
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001414 self.assertEqual(+Decimal(45), Decimal(+45)) # +
1415 self.assertEqual(-Decimal(45), Decimal(-45)) # -
1416 self.assertEqual(abs(Decimal(45)), abs(Decimal(-45))) # abs
1417
Christian Heimes77c02eb2008-02-09 02:18:51 +00001418 def test_nan_comparisons(self):
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001419 # comparisons involving signaling nans signal InvalidOperation
1420
1421 # order comparisons (<, <=, >, >=) involving only quiet nans
1422 # also signal InvalidOperation
1423
1424 # equality comparisons (==, !=) involving only quiet nans
1425 # don't signal, but return False or True respectively.
Stefan Krah1919b7e2012-03-21 18:25:23 +01001426 Decimal = self.decimal.Decimal
1427 InvalidOperation = self.decimal.InvalidOperation
1428 localcontext = self.decimal.localcontext
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001429
Christian Heimes77c02eb2008-02-09 02:18:51 +00001430 n = Decimal('NaN')
1431 s = Decimal('sNaN')
1432 i = Decimal('Inf')
1433 f = Decimal('2')
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001434
1435 qnan_pairs = (n, n), (n, i), (i, n), (n, f), (f, n)
1436 snan_pairs = (s, n), (n, s), (s, i), (i, s), (s, f), (f, s), (s, s)
1437 order_ops = operator.lt, operator.le, operator.gt, operator.ge
1438 equality_ops = operator.eq, operator.ne
1439
1440 # results when InvalidOperation is not trapped
1441 for x, y in qnan_pairs + snan_pairs:
1442 for op in order_ops + equality_ops:
1443 got = op(x, y)
1444 expected = True if op is operator.ne else False
1445 self.assertIs(expected, got,
1446 "expected {0!r} for operator.{1}({2!r}, {3!r}); "
1447 "got {4!r}".format(
1448 expected, op.__name__, x, y, got))
1449
1450 # repeat the above, but this time trap the InvalidOperation
1451 with localcontext() as ctx:
1452 ctx.traps[InvalidOperation] = 1
1453
1454 for x, y in qnan_pairs:
1455 for op in equality_ops:
1456 got = op(x, y)
1457 expected = True if op is operator.ne else False
1458 self.assertIs(expected, got,
1459 "expected {0!r} for "
1460 "operator.{1}({2!r}, {3!r}); "
1461 "got {4!r}".format(
1462 expected, op.__name__, x, y, got))
1463
1464 for x, y in snan_pairs:
1465 for op in equality_ops:
1466 self.assertRaises(InvalidOperation, operator.eq, x, y)
1467 self.assertRaises(InvalidOperation, operator.ne, x, y)
1468
1469 for x, y in qnan_pairs + snan_pairs:
1470 for op in order_ops:
1471 self.assertRaises(InvalidOperation, op, x, y)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001472
Mark Dickinson84230a12010-02-18 14:49:50 +00001473 def test_copy_sign(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001474 Decimal = self.decimal.Decimal
Mark Dickinson84230a12010-02-18 14:49:50 +00001475
Stefan Krah1919b7e2012-03-21 18:25:23 +01001476 d = Decimal(1).copy_sign(Decimal(-2))
Mark Dickinson84230a12010-02-18 14:49:50 +00001477 self.assertEqual(Decimal(1).copy_sign(-2), d)
1478 self.assertRaises(TypeError, Decimal(1).copy_sign, '-2')
1479
Stefan Krah1919b7e2012-03-21 18:25:23 +01001480class CArithmeticOperatorsTest(ArithmeticOperatorsTest):
1481 decimal = C
1482class PyArithmeticOperatorsTest(ArithmeticOperatorsTest):
1483 decimal = P
1484
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001485# The following are two functions used to test threading in the next class
1486
1487def thfunc1(cls):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001488 Decimal = cls.decimal.Decimal
1489 InvalidOperation = cls.decimal.InvalidOperation
1490 DivisionByZero = cls.decimal.DivisionByZero
1491 Overflow = cls.decimal.Overflow
1492 Underflow = cls.decimal.Underflow
1493 Inexact = cls.decimal.Inexact
1494 getcontext = cls.decimal.getcontext
1495 localcontext = cls.decimal.localcontext
1496
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001497 d1 = Decimal(1)
1498 d3 = Decimal(3)
Christian Heimesfe337bf2008-03-23 21:54:12 +00001499 test1 = d1/d3
Christian Heimesfe337bf2008-03-23 21:54:12 +00001500
Stefan Krah1919b7e2012-03-21 18:25:23 +01001501 cls.finish1.set()
1502 cls.synchro.wait()
1503
1504 test2 = d1/d3
1505 with localcontext() as c2:
1506 cls.assertTrue(c2.flags[Inexact])
1507 cls.assertRaises(DivisionByZero, c2.divide, d1, 0)
1508 cls.assertTrue(c2.flags[DivisionByZero])
1509 with localcontext() as c3:
1510 cls.assertTrue(c3.flags[Inexact])
1511 cls.assertTrue(c3.flags[DivisionByZero])
1512 cls.assertRaises(InvalidOperation, c3.compare, d1, Decimal('sNaN'))
1513 cls.assertTrue(c3.flags[InvalidOperation])
1514 del c3
1515 cls.assertFalse(c2.flags[InvalidOperation])
1516 del c2
1517
1518 cls.assertEqual(test1, Decimal('0.333333333333333333333333'))
1519 cls.assertEqual(test2, Decimal('0.333333333333333333333333'))
1520
1521 c1 = getcontext()
1522 cls.assertTrue(c1.flags[Inexact])
1523 for sig in Overflow, Underflow, DivisionByZero, InvalidOperation:
1524 cls.assertFalse(c1.flags[sig])
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001525
1526def thfunc2(cls):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001527 Decimal = cls.decimal.Decimal
1528 InvalidOperation = cls.decimal.InvalidOperation
1529 DivisionByZero = cls.decimal.DivisionByZero
1530 Overflow = cls.decimal.Overflow
1531 Underflow = cls.decimal.Underflow
1532 Inexact = cls.decimal.Inexact
1533 getcontext = cls.decimal.getcontext
1534 localcontext = cls.decimal.localcontext
1535
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001536 d1 = Decimal(1)
1537 d3 = Decimal(3)
Christian Heimesfe337bf2008-03-23 21:54:12 +00001538 test1 = d1/d3
Stefan Krah1919b7e2012-03-21 18:25:23 +01001539
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001540 thiscontext = getcontext()
1541 thiscontext.prec = 18
Christian Heimesfe337bf2008-03-23 21:54:12 +00001542 test2 = d1/d3
Stefan Krah1919b7e2012-03-21 18:25:23 +01001543
1544 with localcontext() as c2:
1545 cls.assertTrue(c2.flags[Inexact])
1546 cls.assertRaises(Overflow, c2.multiply, Decimal('1e425000000'), 999)
1547 cls.assertTrue(c2.flags[Overflow])
1548 with localcontext(thiscontext) as c3:
1549 cls.assertTrue(c3.flags[Inexact])
1550 cls.assertFalse(c3.flags[Overflow])
1551 c3.traps[Underflow] = True
1552 cls.assertRaises(Underflow, c3.divide, Decimal('1e-425000000'), 999)
1553 cls.assertTrue(c3.flags[Underflow])
1554 del c3
1555 cls.assertFalse(c2.flags[Underflow])
1556 cls.assertFalse(c2.traps[Underflow])
1557 del c2
1558
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001559 cls.synchro.set()
1560 cls.finish2.set()
Christian Heimesfe337bf2008-03-23 21:54:12 +00001561
Stefan Krah1919b7e2012-03-21 18:25:23 +01001562 cls.assertEqual(test1, Decimal('0.333333333333333333333333'))
Christian Heimesfe337bf2008-03-23 21:54:12 +00001563 cls.assertEqual(test2, Decimal('0.333333333333333333'))
Stefan Krah1919b7e2012-03-21 18:25:23 +01001564
1565 cls.assertFalse(thiscontext.traps[Underflow])
1566 cls.assertTrue(thiscontext.flags[Inexact])
1567 for sig in Overflow, Underflow, DivisionByZero, InvalidOperation:
1568 cls.assertFalse(thiscontext.flags[sig])
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001569
Stefan Krah1919b7e2012-03-21 18:25:23 +01001570class ThreadingTest(unittest.TestCase):
1571 '''Unit tests for thread local contexts in Decimal.'''
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001572
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001573 # Take care executing this test from IDLE, there's an issue in threading
1574 # that hangs IDLE and I couldn't find it
1575
1576 def test_threading(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001577 DefaultContext = self.decimal.DefaultContext
1578
1579 if self.decimal == C and not self.decimal.HAVE_THREADS:
1580 self.skipTest("compiled without threading")
1581 # Test the "threading isolation" of a Context. Also test changing
1582 # the DefaultContext, which acts as a template for the thread-local
1583 # contexts.
1584 save_prec = DefaultContext.prec
1585 save_emax = DefaultContext.Emax
1586 save_emin = DefaultContext.Emin
1587 DefaultContext.prec = 24
1588 DefaultContext.Emax = 425000000
1589 DefaultContext.Emin = -425000000
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001590
1591 self.synchro = threading.Event()
1592 self.finish1 = threading.Event()
1593 self.finish2 = threading.Event()
1594
1595 th1 = threading.Thread(target=thfunc1, args=(self,))
1596 th2 = threading.Thread(target=thfunc2, args=(self,))
1597
1598 th1.start()
1599 th2.start()
1600
1601 self.finish1.wait()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001602 self.finish2.wait()
Stefan Krah1919b7e2012-03-21 18:25:23 +01001603
1604 for sig in Signals[self.decimal]:
1605 self.assertFalse(DefaultContext.flags[sig])
1606
1607 DefaultContext.prec = save_prec
1608 DefaultContext.Emax = save_emax
1609 DefaultContext.Emin = save_emin
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001610
Stefan Krah1919b7e2012-03-21 18:25:23 +01001611@unittest.skipUnless(threading, 'threading required')
1612class CThreadingTest(ThreadingTest):
1613 decimal = C
1614@unittest.skipUnless(threading, 'threading required')
1615class PyThreadingTest(ThreadingTest):
1616 decimal = P
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001617
Stefan Krah1919b7e2012-03-21 18:25:23 +01001618class UsabilityTest(unittest.TestCase):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001619 '''Unit tests for Usability cases of Decimal.'''
1620
1621 def test_comparison_operators(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001622
Stefan Krah1919b7e2012-03-21 18:25:23 +01001623 Decimal = self.decimal.Decimal
1624
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001625 da = Decimal('23.42')
1626 db = Decimal('23.42')
1627 dc = Decimal('45')
1628
1629 #two Decimals
Ezio Melotti6607d512010-04-03 14:59:49 +00001630 self.assertGreater(dc, da)
1631 self.assertGreaterEqual(dc, da)
1632 self.assertLess(da, dc)
1633 self.assertLessEqual(da, dc)
Guido van Rossume61fd5b2007-07-11 12:20:59 +00001634 self.assertEqual(da, db)
Ezio Melotti6607d512010-04-03 14:59:49 +00001635 self.assertNotEqual(da, dc)
1636 self.assertLessEqual(da, db)
1637 self.assertGreaterEqual(da, db)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001638
1639 #a Decimal and an int
Ezio Melotti6607d512010-04-03 14:59:49 +00001640 self.assertGreater(dc, 23)
1641 self.assertLess(23, dc)
Guido van Rossume61fd5b2007-07-11 12:20:59 +00001642 self.assertEqual(dc, 45)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001643
1644 #a Decimal and uncomparable
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001645 self.assertNotEqual(da, 'ugly')
1646 self.assertNotEqual(da, 32.7)
1647 self.assertNotEqual(da, object())
1648 self.assertNotEqual(da, object)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001649
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001650 # sortable
Guido van Rossumc1f779c2007-07-03 08:25:58 +00001651 a = list(map(Decimal, range(100)))
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001652 b = a[:]
1653 random.shuffle(a)
1654 a.sort()
1655 self.assertEqual(a, b)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001656
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001657 def test_decimal_float_comparison(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001658 Decimal = self.decimal.Decimal
1659
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001660 da = Decimal('0.25')
1661 db = Decimal('3.0')
Ezio Melotti6607d512010-04-03 14:59:49 +00001662 self.assertLess(da, 3.0)
1663 self.assertLessEqual(da, 3.0)
1664 self.assertGreater(db, 0.25)
1665 self.assertGreaterEqual(db, 0.25)
1666 self.assertNotEqual(da, 1.5)
1667 self.assertEqual(da, 0.25)
1668 self.assertGreater(3.0, da)
1669 self.assertGreaterEqual(3.0, da)
1670 self.assertLess(0.25, db)
1671 self.assertLessEqual(0.25, db)
1672 self.assertNotEqual(0.25, db)
1673 self.assertEqual(3.0, db)
1674 self.assertNotEqual(0.1, Decimal('0.1'))
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001675
Stefan Krah1919b7e2012-03-21 18:25:23 +01001676 def test_decimal_complex_comparison(self):
1677 Decimal = self.decimal.Decimal
1678
1679 da = Decimal('0.25')
1680 db = Decimal('3.0')
1681 self.assertNotEqual(da, (1.5+0j))
1682 self.assertNotEqual((1.5+0j), da)
1683 self.assertEqual(da, (0.25+0j))
1684 self.assertEqual((0.25+0j), da)
1685 self.assertEqual((3.0+0j), db)
1686 self.assertEqual(db, (3.0+0j))
1687
1688 self.assertNotEqual(db, (3.0+1j))
1689 self.assertNotEqual((3.0+1j), db)
1690
1691 self.assertIs(db.__lt__(3.0+0j), NotImplemented)
1692 self.assertIs(db.__le__(3.0+0j), NotImplemented)
1693 self.assertIs(db.__gt__(3.0+0j), NotImplemented)
1694 self.assertIs(db.__le__(3.0+0j), NotImplemented)
1695
1696 def test_decimal_fraction_comparison(self):
1697 D = self.decimal.Decimal
1698 F = fractions[self.decimal].Fraction
1699 Context = self.decimal.Context
1700 localcontext = self.decimal.localcontext
1701 InvalidOperation = self.decimal.InvalidOperation
1702
1703
1704 emax = C.MAX_EMAX if C else 999999999
1705 emin = C.MIN_EMIN if C else -999999999
1706 etiny = C.MIN_ETINY if C else -1999999997
1707 c = Context(Emax=emax, Emin=emin)
1708
1709 with localcontext(c):
1710 c.prec = emax
1711 self.assertLess(D(0), F(1,9999999999999999999999999999999999999))
1712 self.assertLess(F(-1,9999999999999999999999999999999999999), D(0))
1713 self.assertLess(F(0,1), D("1e" + str(etiny)))
1714 self.assertLess(D("-1e" + str(etiny)), F(0,1))
1715 self.assertLess(F(0,9999999999999999999999999), D("1e" + str(etiny)))
1716 self.assertLess(D("-1e" + str(etiny)), F(0,9999999999999999999999999))
1717
1718 self.assertEqual(D("0.1"), F(1,10))
1719 self.assertEqual(F(1,10), D("0.1"))
1720
1721 c.prec = 300
1722 self.assertNotEqual(D(1)/3, F(1,3))
1723 self.assertNotEqual(F(1,3), D(1)/3)
1724
1725 self.assertLessEqual(F(120984237, 9999999999), D("9e" + str(emax)))
1726 self.assertGreaterEqual(D("9e" + str(emax)), F(120984237, 9999999999))
1727
1728 self.assertGreater(D('inf'), F(99999999999,123))
1729 self.assertGreater(D('inf'), F(-99999999999,123))
1730 self.assertLess(D('-inf'), F(99999999999,123))
1731 self.assertLess(D('-inf'), F(-99999999999,123))
1732
1733 self.assertRaises(InvalidOperation, D('nan').__gt__, F(-9,123))
1734 self.assertIs(NotImplemented, F(-9,123).__lt__(D('nan')))
1735 self.assertNotEqual(D('nan'), F(-9,123))
1736 self.assertNotEqual(F(-9,123), D('nan'))
1737
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001738 def test_copy_and_deepcopy_methods(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001739 Decimal = self.decimal.Decimal
1740
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001741 d = Decimal('43.24')
1742 c = copy.copy(d)
1743 self.assertEqual(id(c), id(d))
1744 dc = copy.deepcopy(d)
1745 self.assertEqual(id(dc), id(d))
1746
1747 def test_hash_method(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001748
1749 Decimal = self.decimal.Decimal
1750 localcontext = self.decimal.localcontext
1751
Stefan Krahdc817b22010-11-17 11:16:34 +00001752 def hashit(d):
1753 a = hash(d)
1754 b = d.__hash__()
1755 self.assertEqual(a, b)
1756 return a
1757
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001758 #just that it's hashable
Stefan Krahdc817b22010-11-17 11:16:34 +00001759 hashit(Decimal(23))
1760 hashit(Decimal('Infinity'))
1761 hashit(Decimal('-Infinity'))
1762 hashit(Decimal('nan123'))
1763 hashit(Decimal('-NaN'))
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001764
1765 test_values = [Decimal(sign*(2**m + n))
1766 for m in [0, 14, 15, 16, 17, 30, 31,
Stefan Krahdc817b22010-11-17 11:16:34 +00001767 32, 33, 61, 62, 63, 64, 65, 66]
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001768 for n in range(-10, 10)
1769 for sign in [-1, 1]]
1770 test_values.extend([
Stefan Krahdc817b22010-11-17 11:16:34 +00001771 Decimal("-1"), # ==> -2
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001772 Decimal("-0"), # zeros
1773 Decimal("0.00"),
1774 Decimal("-0.000"),
1775 Decimal("0E10"),
1776 Decimal("-0E12"),
1777 Decimal("10.0"), # negative exponent
1778 Decimal("-23.00000"),
1779 Decimal("1230E100"), # positive exponent
1780 Decimal("-4.5678E50"),
1781 # a value for which hash(n) != hash(n % (2**64-1))
1782 # in Python pre-2.6
1783 Decimal(2**64 + 2**32 - 1),
1784 # selection of values which fail with the old (before
1785 # version 2.6) long.__hash__
1786 Decimal("1.634E100"),
1787 Decimal("90.697E100"),
1788 Decimal("188.83E100"),
1789 Decimal("1652.9E100"),
1790 Decimal("56531E100"),
1791 ])
1792
1793 # check that hash(d) == hash(int(d)) for integral values
1794 for value in test_values:
Stefan Krahdc817b22010-11-17 11:16:34 +00001795 self.assertEqual(hashit(value), hashit(int(value)))
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001796
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001797 #the same hash that to an int
Stefan Krahdc817b22010-11-17 11:16:34 +00001798 self.assertEqual(hashit(Decimal(23)), hashit(23))
Raymond Hettingerd325c4b2010-11-21 04:08:28 +00001799 self.assertRaises(TypeError, hash, Decimal('sNaN'))
Stefan Krahdc817b22010-11-17 11:16:34 +00001800 self.assertTrue(hashit(Decimal('Inf')))
1801 self.assertTrue(hashit(Decimal('-Inf')))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001802
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001803 # check that the hashes of a Decimal float match when they
1804 # represent exactly the same values
1805 test_strings = ['inf', '-Inf', '0.0', '-.0e1',
1806 '34.0', '2.5', '112390.625', '-0.515625']
1807 for s in test_strings:
1808 f = float(s)
1809 d = Decimal(s)
Stefan Krahdc817b22010-11-17 11:16:34 +00001810 self.assertEqual(hashit(f), hashit(d))
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001811
Stefan Krah1919b7e2012-03-21 18:25:23 +01001812 with localcontext() as c:
1813 # check that the value of the hash doesn't depend on the
1814 # current context (issue #1757)
1815 x = Decimal("123456789.1")
Christian Heimes2380ac72008-01-09 00:17:24 +00001816
Stefan Krah1919b7e2012-03-21 18:25:23 +01001817 c.prec = 6
1818 h1 = hashit(x)
1819 c.prec = 10
1820 h2 = hashit(x)
1821 c.prec = 16
1822 h3 = hashit(x)
Christian Heimes2380ac72008-01-09 00:17:24 +00001823
Stefan Krah1919b7e2012-03-21 18:25:23 +01001824 self.assertEqual(h1, h2)
1825 self.assertEqual(h1, h3)
1826
1827 c.prec = 10000
1828 x = 1100 ** 1248
1829 self.assertEqual(hashit(Decimal(x)), hashit(x))
Christian Heimes2380ac72008-01-09 00:17:24 +00001830
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001831 def test_min_and_max_methods(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001832 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001833
1834 d1 = Decimal('15.32')
1835 d2 = Decimal('28.5')
1836 l1 = 15
1837 l2 = 28
1838
1839 #between Decimals
Ezio Melotti6607d512010-04-03 14:59:49 +00001840 self.assertIs(min(d1,d2), d1)
1841 self.assertIs(min(d2,d1), d1)
1842 self.assertIs(max(d1,d2), d2)
1843 self.assertIs(max(d2,d1), d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001844
Serhiy Storchaka95949422013-08-27 19:40:23 +03001845 #between Decimal and int
Ezio Melotti6607d512010-04-03 14:59:49 +00001846 self.assertIs(min(d1,l2), d1)
1847 self.assertIs(min(l2,d1), d1)
1848 self.assertIs(max(l1,d2), d2)
1849 self.assertIs(max(d2,l1), d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001850
1851 def test_as_nonzero(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001852 Decimal = self.decimal.Decimal
1853
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001854 #as false
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001855 self.assertFalse(Decimal(0))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001856 #as true
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001857 self.assertTrue(Decimal('0.372'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001858
1859 def test_tostring_methods(self):
1860 #Test str and repr methods.
Stefan Krah1919b7e2012-03-21 18:25:23 +01001861 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001862
1863 d = Decimal('15.32')
1864 self.assertEqual(str(d), '15.32') # str
Christian Heimes68f5fbe2008-02-14 08:27:37 +00001865 self.assertEqual(repr(d), "Decimal('15.32')") # repr
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001866
1867 def test_tonum_methods(self):
Mark Dickinson5c2db372009-12-05 20:28:34 +00001868 #Test float and int methods.
Stefan Krah1919b7e2012-03-21 18:25:23 +01001869 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001870
1871 d1 = Decimal('66')
1872 d2 = Decimal('15.32')
1873
1874 #int
1875 self.assertEqual(int(d1), 66)
1876 self.assertEqual(int(d2), 15)
1877
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001878 #float
1879 self.assertEqual(float(d1), 66)
1880 self.assertEqual(float(d2), 15.32)
1881
Mark Dickinsonb27406c2008-05-09 13:42:33 +00001882 #floor
1883 test_pairs = [
1884 ('123.00', 123),
1885 ('3.2', 3),
1886 ('3.54', 3),
1887 ('3.899', 3),
1888 ('-2.3', -3),
1889 ('-11.0', -11),
1890 ('0.0', 0),
1891 ('-0E3', 0),
Stefan Krah1919b7e2012-03-21 18:25:23 +01001892 ('89891211712379812736.1', 89891211712379812736),
Mark Dickinsonb27406c2008-05-09 13:42:33 +00001893 ]
1894 for d, i in test_pairs:
1895 self.assertEqual(math.floor(Decimal(d)), i)
1896 self.assertRaises(ValueError, math.floor, Decimal('-NaN'))
1897 self.assertRaises(ValueError, math.floor, Decimal('sNaN'))
1898 self.assertRaises(ValueError, math.floor, Decimal('NaN123'))
1899 self.assertRaises(OverflowError, math.floor, Decimal('Inf'))
1900 self.assertRaises(OverflowError, math.floor, Decimal('-Inf'))
1901
1902 #ceiling
1903 test_pairs = [
1904 ('123.00', 123),
1905 ('3.2', 4),
1906 ('3.54', 4),
1907 ('3.899', 4),
1908 ('-2.3', -2),
1909 ('-11.0', -11),
1910 ('0.0', 0),
1911 ('-0E3', 0),
Stefan Krah1919b7e2012-03-21 18:25:23 +01001912 ('89891211712379812736.1', 89891211712379812737),
Mark Dickinsonb27406c2008-05-09 13:42:33 +00001913 ]
1914 for d, i in test_pairs:
1915 self.assertEqual(math.ceil(Decimal(d)), i)
1916 self.assertRaises(ValueError, math.ceil, Decimal('-NaN'))
1917 self.assertRaises(ValueError, math.ceil, Decimal('sNaN'))
1918 self.assertRaises(ValueError, math.ceil, Decimal('NaN123'))
1919 self.assertRaises(OverflowError, math.ceil, Decimal('Inf'))
1920 self.assertRaises(OverflowError, math.ceil, Decimal('-Inf'))
1921
1922 #round, single argument
1923 test_pairs = [
1924 ('123.00', 123),
1925 ('3.2', 3),
1926 ('3.54', 4),
1927 ('3.899', 4),
1928 ('-2.3', -2),
1929 ('-11.0', -11),
1930 ('0.0', 0),
1931 ('-0E3', 0),
1932 ('-3.5', -4),
1933 ('-2.5', -2),
1934 ('-1.5', -2),
1935 ('-0.5', 0),
1936 ('0.5', 0),
1937 ('1.5', 2),
1938 ('2.5', 2),
1939 ('3.5', 4),
1940 ]
1941 for d, i in test_pairs:
1942 self.assertEqual(round(Decimal(d)), i)
1943 self.assertRaises(ValueError, round, Decimal('-NaN'))
1944 self.assertRaises(ValueError, round, Decimal('sNaN'))
1945 self.assertRaises(ValueError, round, Decimal('NaN123'))
1946 self.assertRaises(OverflowError, round, Decimal('Inf'))
1947 self.assertRaises(OverflowError, round, Decimal('-Inf'))
1948
1949 #round, two arguments; this is essentially equivalent
1950 #to quantize, which is already extensively tested
1951 test_triples = [
1952 ('123.456', -4, '0E+4'),
1953 ('123.456', -3, '0E+3'),
1954 ('123.456', -2, '1E+2'),
1955 ('123.456', -1, '1.2E+2'),
1956 ('123.456', 0, '123'),
1957 ('123.456', 1, '123.5'),
1958 ('123.456', 2, '123.46'),
1959 ('123.456', 3, '123.456'),
1960 ('123.456', 4, '123.4560'),
1961 ('123.455', 2, '123.46'),
1962 ('123.445', 2, '123.44'),
1963 ('Inf', 4, 'NaN'),
1964 ('-Inf', -23, 'NaN'),
1965 ('sNaN314', 3, 'NaN314'),
1966 ]
1967 for d, n, r in test_triples:
1968 self.assertEqual(str(round(Decimal(d), n)), r)
1969
Mark Dickinsonfc33d4c2012-08-24 18:53:10 +01001970 def test_nan_to_float(self):
1971 # Test conversions of decimal NANs to float.
1972 # See http://bugs.python.org/issue15544
1973 Decimal = self.decimal.Decimal
1974 for s in ('nan', 'nan1234', '-nan', '-nan2468'):
1975 f = float(Decimal(s))
1976 self.assertTrue(math.isnan(f))
1977 sign = math.copysign(1.0, f)
1978 self.assertEqual(sign, -1.0 if s.startswith('-') else 1.0)
1979
1980 def test_snan_to_float(self):
1981 Decimal = self.decimal.Decimal
1982 for s in ('snan', '-snan', 'snan1357', '-snan1234'):
1983 d = Decimal(s)
1984 self.assertRaises(ValueError, float, d)
1985
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001986 def test_eval_round_trip(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001987 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001988
1989 #with zero
1990 d = Decimal( (0, (0,), 0) )
1991 self.assertEqual(d, eval(repr(d)))
1992
1993 #int
1994 d = Decimal( (1, (4, 5), 0) )
1995 self.assertEqual(d, eval(repr(d)))
1996
1997 #float
1998 d = Decimal( (0, (4, 5, 3, 4), -2) )
1999 self.assertEqual(d, eval(repr(d)))
2000
2001 #weird
2002 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
2003 self.assertEqual(d, eval(repr(d)))
2004
2005 def test_as_tuple(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01002006 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002007
2008 #with zero
2009 d = Decimal(0)
2010 self.assertEqual(d.as_tuple(), (0, (0,), 0) )
2011
2012 #int
2013 d = Decimal(-45)
2014 self.assertEqual(d.as_tuple(), (1, (4, 5), 0) )
2015
2016 #complicated string
2017 d = Decimal("-4.34913534E-17")
2018 self.assertEqual(d.as_tuple(), (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
2019
Stefan Krah76e12172012-09-10 19:34:58 +02002020 # The '0' coefficient is implementation specific to decimal.py.
2021 # It has no meaning in the C-version and is ignored there.
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002022 d = Decimal("Infinity")
2023 self.assertEqual(d.as_tuple(), (0, (0,), 'F') )
2024
Guido van Rossum8ce8a782007-11-01 19:42:39 +00002025 #leading zeros in coefficient should be stripped
2026 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), -2) )
2027 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), -2) )
2028 d = Decimal( (1, (0, 0, 0), 37) )
2029 self.assertEqual(d.as_tuple(), (1, (0,), 37))
2030 d = Decimal( (1, (), 37) )
2031 self.assertEqual(d.as_tuple(), (1, (0,), 37))
2032
2033 #leading zeros in NaN diagnostic info should be stripped
2034 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), 'n') )
2035 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), 'n') )
2036 d = Decimal( (1, (0, 0, 0), 'N') )
2037 self.assertEqual(d.as_tuple(), (1, (), 'N') )
2038 d = Decimal( (1, (), 'n') )
2039 self.assertEqual(d.as_tuple(), (1, (), 'n') )
2040
Stefan Krah76e12172012-09-10 19:34:58 +02002041 # For infinities, decimal.py has always silently accepted any
2042 # coefficient tuple.
2043 d = Decimal( (0, (0,), 'F') )
2044 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
2045 d = Decimal( (0, (4, 5, 3, 4), 'F') )
2046 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
2047 d = Decimal( (1, (0, 2, 7, 1), 'F') )
2048 self.assertEqual(d.as_tuple(), (1, (0,), 'F'))
Guido van Rossum8ce8a782007-11-01 19:42:39 +00002049
Stefan Krah1919b7e2012-03-21 18:25:23 +01002050 def test_subclassing(self):
2051 # Different behaviours when subclassing Decimal
2052 Decimal = self.decimal.Decimal
2053
2054 class MyDecimal(Decimal):
Stefan Krah0f82b762012-11-08 11:17:29 +01002055 y = None
Stefan Krah1919b7e2012-03-21 18:25:23 +01002056
2057 d1 = MyDecimal(1)
2058 d2 = MyDecimal(2)
2059 d = d1 + d2
2060 self.assertIs(type(d), Decimal)
2061
2062 d = d1.max(d2)
2063 self.assertIs(type(d), Decimal)
2064
2065 d = copy.copy(d1)
2066 self.assertIs(type(d), MyDecimal)
2067 self.assertEqual(d, d1)
2068
2069 d = copy.deepcopy(d1)
2070 self.assertIs(type(d), MyDecimal)
2071 self.assertEqual(d, d1)
2072
Stefan Krah0f82b762012-11-08 11:17:29 +01002073 # Decimal(Decimal)
2074 d = Decimal('1.0')
2075 x = Decimal(d)
2076 self.assertIs(type(x), Decimal)
2077 self.assertEqual(x, d)
Stefan Krahf4abc7b2012-11-07 23:12:25 +01002078
Stefan Krah0f82b762012-11-08 11:17:29 +01002079 # MyDecimal(Decimal)
2080 m = MyDecimal(d)
2081 self.assertIs(type(m), MyDecimal)
2082 self.assertEqual(m, d)
2083 self.assertIs(m.y, None)
2084
2085 # Decimal(MyDecimal)
2086 x = Decimal(m)
2087 self.assertIs(type(x), Decimal)
2088 self.assertEqual(x, d)
2089
2090 # MyDecimal(MyDecimal)
2091 m.y = 9
2092 x = MyDecimal(m)
2093 self.assertIs(type(x), MyDecimal)
2094 self.assertEqual(x, d)
2095 self.assertIs(x.y, None)
Stefan Krahed16eff2012-11-07 23:47:19 +01002096
Stefan Krah1919b7e2012-03-21 18:25:23 +01002097 def test_implicit_context(self):
2098 Decimal = self.decimal.Decimal
2099 getcontext = self.decimal.getcontext
2100
2101 # Check results when context given implicitly. (Issue 2478)
2102 c = getcontext()
2103 self.assertEqual(str(Decimal(0).sqrt()),
2104 str(c.sqrt(Decimal(0))))
2105
Stefan Krah040e3112012-12-15 22:33:33 +01002106 def test_none_args(self):
2107 Decimal = self.decimal.Decimal
2108 Context = self.decimal.Context
2109 localcontext = self.decimal.localcontext
2110 InvalidOperation = self.decimal.InvalidOperation
2111 DivisionByZero = self.decimal.DivisionByZero
2112 Overflow = self.decimal.Overflow
2113 Underflow = self.decimal.Underflow
2114 Subnormal = self.decimal.Subnormal
2115 Inexact = self.decimal.Inexact
2116 Rounded = self.decimal.Rounded
2117 Clamped = self.decimal.Clamped
Stefan Krah040e3112012-12-15 22:33:33 +01002118
2119 with localcontext(Context()) as c:
2120 c.prec = 7
2121 c.Emax = 999
2122 c.Emin = -999
2123
2124 x = Decimal("111")
2125 y = Decimal("1e9999")
2126 z = Decimal("1e-9999")
2127
2128 ##### Unary functions
2129 c.clear_flags()
2130 self.assertEqual(str(x.exp(context=None)), '1.609487E+48')
2131 self.assertTrue(c.flags[Inexact])
2132 self.assertTrue(c.flags[Rounded])
2133 c.clear_flags()
2134 self.assertRaises(Overflow, y.exp, context=None)
2135 self.assertTrue(c.flags[Overflow])
2136
2137 self.assertIs(z.is_normal(context=None), False)
2138 self.assertIs(z.is_subnormal(context=None), True)
2139
2140 c.clear_flags()
2141 self.assertEqual(str(x.ln(context=None)), '4.709530')
2142 self.assertTrue(c.flags[Inexact])
2143 self.assertTrue(c.flags[Rounded])
2144 c.clear_flags()
2145 self.assertRaises(InvalidOperation, Decimal(-1).ln, context=None)
2146 self.assertTrue(c.flags[InvalidOperation])
2147
2148 c.clear_flags()
2149 self.assertEqual(str(x.log10(context=None)), '2.045323')
2150 self.assertTrue(c.flags[Inexact])
2151 self.assertTrue(c.flags[Rounded])
2152 c.clear_flags()
2153 self.assertRaises(InvalidOperation, Decimal(-1).log10, context=None)
2154 self.assertTrue(c.flags[InvalidOperation])
2155
2156 c.clear_flags()
2157 self.assertEqual(str(x.logb(context=None)), '2')
2158 self.assertRaises(DivisionByZero, Decimal(0).logb, context=None)
2159 self.assertTrue(c.flags[DivisionByZero])
2160
2161 c.clear_flags()
2162 self.assertEqual(str(x.logical_invert(context=None)), '1111000')
2163 self.assertRaises(InvalidOperation, y.logical_invert, context=None)
2164 self.assertTrue(c.flags[InvalidOperation])
2165
2166 c.clear_flags()
2167 self.assertEqual(str(y.next_minus(context=None)), '9.999999E+999')
2168 self.assertRaises(InvalidOperation, Decimal('sNaN').next_minus, context=None)
2169 self.assertTrue(c.flags[InvalidOperation])
2170
2171 c.clear_flags()
2172 self.assertEqual(str(y.next_plus(context=None)), 'Infinity')
2173 self.assertRaises(InvalidOperation, Decimal('sNaN').next_plus, context=None)
2174 self.assertTrue(c.flags[InvalidOperation])
2175
2176 c.clear_flags()
2177 self.assertEqual(str(z.normalize(context=None)), '0')
2178 self.assertRaises(Overflow, y.normalize, context=None)
2179 self.assertTrue(c.flags[Overflow])
2180
2181 self.assertEqual(str(z.number_class(context=None)), '+Subnormal')
2182
2183 c.clear_flags()
2184 self.assertEqual(str(z.sqrt(context=None)), '0E-1005')
2185 self.assertTrue(c.flags[Clamped])
2186 self.assertTrue(c.flags[Inexact])
2187 self.assertTrue(c.flags[Rounded])
2188 self.assertTrue(c.flags[Subnormal])
2189 self.assertTrue(c.flags[Underflow])
2190 c.clear_flags()
2191 self.assertRaises(Overflow, y.sqrt, context=None)
2192 self.assertTrue(c.flags[Overflow])
2193
2194 c.capitals = 0
2195 self.assertEqual(str(z.to_eng_string(context=None)), '1e-9999')
2196 c.capitals = 1
2197
2198
2199 ##### Binary functions
2200 c.clear_flags()
2201 ans = str(x.compare(Decimal('Nan891287828'), context=None))
2202 self.assertEqual(ans, 'NaN1287828')
2203 self.assertRaises(InvalidOperation, x.compare, Decimal('sNaN'), context=None)
2204 self.assertTrue(c.flags[InvalidOperation])
2205
2206 c.clear_flags()
2207 ans = str(x.compare_signal(8224, context=None))
2208 self.assertEqual(ans, '-1')
2209 self.assertRaises(InvalidOperation, x.compare_signal, Decimal('NaN'), context=None)
2210 self.assertTrue(c.flags[InvalidOperation])
2211
2212 c.clear_flags()
2213 ans = str(x.logical_and(101, context=None))
2214 self.assertEqual(ans, '101')
2215 self.assertRaises(InvalidOperation, x.logical_and, 123, context=None)
2216 self.assertTrue(c.flags[InvalidOperation])
2217
2218 c.clear_flags()
2219 ans = str(x.logical_or(101, context=None))
2220 self.assertEqual(ans, '111')
2221 self.assertRaises(InvalidOperation, x.logical_or, 123, context=None)
2222 self.assertTrue(c.flags[InvalidOperation])
2223
2224 c.clear_flags()
2225 ans = str(x.logical_xor(101, context=None))
2226 self.assertEqual(ans, '10')
2227 self.assertRaises(InvalidOperation, x.logical_xor, 123, context=None)
2228 self.assertTrue(c.flags[InvalidOperation])
2229
2230 c.clear_flags()
2231 ans = str(x.max(101, context=None))
2232 self.assertEqual(ans, '111')
2233 self.assertRaises(InvalidOperation, x.max, Decimal('sNaN'), context=None)
2234 self.assertTrue(c.flags[InvalidOperation])
2235
2236 c.clear_flags()
2237 ans = str(x.max_mag(101, context=None))
2238 self.assertEqual(ans, '111')
2239 self.assertRaises(InvalidOperation, x.max_mag, Decimal('sNaN'), context=None)
2240 self.assertTrue(c.flags[InvalidOperation])
2241
2242 c.clear_flags()
2243 ans = str(x.min(101, context=None))
2244 self.assertEqual(ans, '101')
2245 self.assertRaises(InvalidOperation, x.min, Decimal('sNaN'), context=None)
2246 self.assertTrue(c.flags[InvalidOperation])
2247
2248 c.clear_flags()
2249 ans = str(x.min_mag(101, context=None))
2250 self.assertEqual(ans, '101')
2251 self.assertRaises(InvalidOperation, x.min_mag, Decimal('sNaN'), context=None)
2252 self.assertTrue(c.flags[InvalidOperation])
2253
2254 c.clear_flags()
2255 ans = str(x.remainder_near(101, context=None))
2256 self.assertEqual(ans, '10')
2257 self.assertRaises(InvalidOperation, y.remainder_near, 101, context=None)
2258 self.assertTrue(c.flags[InvalidOperation])
2259
2260 c.clear_flags()
2261 ans = str(x.rotate(2, context=None))
2262 self.assertEqual(ans, '11100')
2263 self.assertRaises(InvalidOperation, x.rotate, 101, context=None)
2264 self.assertTrue(c.flags[InvalidOperation])
2265
2266 c.clear_flags()
2267 ans = str(x.scaleb(7, context=None))
2268 self.assertEqual(ans, '1.11E+9')
2269 self.assertRaises(InvalidOperation, x.scaleb, 10000, context=None)
2270 self.assertTrue(c.flags[InvalidOperation])
2271
2272 c.clear_flags()
2273 ans = str(x.shift(2, context=None))
2274 self.assertEqual(ans, '11100')
2275 self.assertRaises(InvalidOperation, x.shift, 10000, context=None)
2276 self.assertTrue(c.flags[InvalidOperation])
2277
2278
2279 ##### Ternary functions
2280 c.clear_flags()
2281 ans = str(x.fma(2, 3, context=None))
2282 self.assertEqual(ans, '225')
2283 self.assertRaises(Overflow, x.fma, Decimal('1e9999'), 3, context=None)
2284 self.assertTrue(c.flags[Overflow])
2285
2286
2287 ##### Special cases
2288 c.rounding = ROUND_HALF_EVEN
2289 ans = str(Decimal('1.5').to_integral(rounding=None, context=None))
2290 self.assertEqual(ans, '2')
2291 c.rounding = ROUND_DOWN
2292 ans = str(Decimal('1.5').to_integral(rounding=None, context=None))
2293 self.assertEqual(ans, '1')
2294 ans = str(Decimal('1.5').to_integral(rounding=ROUND_UP, context=None))
2295 self.assertEqual(ans, '2')
2296 c.clear_flags()
2297 self.assertRaises(InvalidOperation, Decimal('sNaN').to_integral, context=None)
2298 self.assertTrue(c.flags[InvalidOperation])
2299
2300 c.rounding = ROUND_HALF_EVEN
2301 ans = str(Decimal('1.5').to_integral_value(rounding=None, context=None))
2302 self.assertEqual(ans, '2')
2303 c.rounding = ROUND_DOWN
2304 ans = str(Decimal('1.5').to_integral_value(rounding=None, context=None))
2305 self.assertEqual(ans, '1')
2306 ans = str(Decimal('1.5').to_integral_value(rounding=ROUND_UP, context=None))
2307 self.assertEqual(ans, '2')
2308 c.clear_flags()
2309 self.assertRaises(InvalidOperation, Decimal('sNaN').to_integral_value, context=None)
2310 self.assertTrue(c.flags[InvalidOperation])
2311
2312 c.rounding = ROUND_HALF_EVEN
2313 ans = str(Decimal('1.5').to_integral_exact(rounding=None, context=None))
2314 self.assertEqual(ans, '2')
2315 c.rounding = ROUND_DOWN
2316 ans = str(Decimal('1.5').to_integral_exact(rounding=None, context=None))
2317 self.assertEqual(ans, '1')
2318 ans = str(Decimal('1.5').to_integral_exact(rounding=ROUND_UP, context=None))
2319 self.assertEqual(ans, '2')
2320 c.clear_flags()
2321 self.assertRaises(InvalidOperation, Decimal('sNaN').to_integral_exact, context=None)
2322 self.assertTrue(c.flags[InvalidOperation])
2323
2324 c.rounding = ROUND_UP
2325 ans = str(Decimal('1.50001').quantize(exp=Decimal('1e-3'), rounding=None, context=None))
2326 self.assertEqual(ans, '1.501')
2327 c.rounding = ROUND_DOWN
2328 ans = str(Decimal('1.50001').quantize(exp=Decimal('1e-3'), rounding=None, context=None))
2329 self.assertEqual(ans, '1.500')
2330 ans = str(Decimal('1.50001').quantize(exp=Decimal('1e-3'), rounding=ROUND_UP, context=None))
2331 self.assertEqual(ans, '1.501')
2332 c.clear_flags()
2333 self.assertRaises(InvalidOperation, y.quantize, Decimal('1e-10'), rounding=ROUND_UP, context=None)
2334 self.assertTrue(c.flags[InvalidOperation])
2335
2336 with localcontext(Context()) as context:
2337 context.prec = 7
2338 context.Emax = 999
2339 context.Emin = -999
2340 with localcontext(ctx=None) as c:
2341 self.assertEqual(c.prec, 7)
2342 self.assertEqual(c.Emax, 999)
2343 self.assertEqual(c.Emin, -999)
2344
Stefan Krah1919b7e2012-03-21 18:25:23 +01002345 def test_conversions_from_int(self):
2346 # Check that methods taking a second Decimal argument will
2347 # always accept an integer in place of a Decimal.
2348 Decimal = self.decimal.Decimal
2349
2350 self.assertEqual(Decimal(4).compare(3),
2351 Decimal(4).compare(Decimal(3)))
2352 self.assertEqual(Decimal(4).compare_signal(3),
2353 Decimal(4).compare_signal(Decimal(3)))
2354 self.assertEqual(Decimal(4).compare_total(3),
2355 Decimal(4).compare_total(Decimal(3)))
2356 self.assertEqual(Decimal(4).compare_total_mag(3),
2357 Decimal(4).compare_total_mag(Decimal(3)))
2358 self.assertEqual(Decimal(10101).logical_and(1001),
2359 Decimal(10101).logical_and(Decimal(1001)))
2360 self.assertEqual(Decimal(10101).logical_or(1001),
2361 Decimal(10101).logical_or(Decimal(1001)))
2362 self.assertEqual(Decimal(10101).logical_xor(1001),
2363 Decimal(10101).logical_xor(Decimal(1001)))
2364 self.assertEqual(Decimal(567).max(123),
2365 Decimal(567).max(Decimal(123)))
2366 self.assertEqual(Decimal(567).max_mag(123),
2367 Decimal(567).max_mag(Decimal(123)))
2368 self.assertEqual(Decimal(567).min(123),
2369 Decimal(567).min(Decimal(123)))
2370 self.assertEqual(Decimal(567).min_mag(123),
2371 Decimal(567).min_mag(Decimal(123)))
2372 self.assertEqual(Decimal(567).next_toward(123),
2373 Decimal(567).next_toward(Decimal(123)))
2374 self.assertEqual(Decimal(1234).quantize(100),
2375 Decimal(1234).quantize(Decimal(100)))
2376 self.assertEqual(Decimal(768).remainder_near(1234),
2377 Decimal(768).remainder_near(Decimal(1234)))
2378 self.assertEqual(Decimal(123).rotate(1),
2379 Decimal(123).rotate(Decimal(1)))
2380 self.assertEqual(Decimal(1234).same_quantum(1000),
2381 Decimal(1234).same_quantum(Decimal(1000)))
2382 self.assertEqual(Decimal('9.123').scaleb(-100),
2383 Decimal('9.123').scaleb(Decimal(-100)))
2384 self.assertEqual(Decimal(456).shift(-1),
2385 Decimal(456).shift(Decimal(-1)))
2386
2387 self.assertEqual(Decimal(-12).fma(Decimal(45), 67),
2388 Decimal(-12).fma(Decimal(45), Decimal(67)))
2389 self.assertEqual(Decimal(-12).fma(45, 67),
2390 Decimal(-12).fma(Decimal(45), Decimal(67)))
2391 self.assertEqual(Decimal(-12).fma(45, Decimal(67)),
2392 Decimal(-12).fma(Decimal(45), Decimal(67)))
2393
2394class CUsabilityTest(UsabilityTest):
2395 decimal = C
2396class PyUsabilityTest(UsabilityTest):
2397 decimal = P
2398
2399class PythonAPItests(unittest.TestCase):
2400
2401 def test_abc(self):
2402 Decimal = self.decimal.Decimal
2403
2404 self.assertTrue(issubclass(Decimal, numbers.Number))
2405 self.assertFalse(issubclass(Decimal, numbers.Real))
2406 self.assertIsInstance(Decimal(0), numbers.Number)
2407 self.assertNotIsInstance(Decimal(0), numbers.Real)
2408
2409 def test_pickle(self):
2410 Decimal = self.decimal.Decimal
2411
2412 savedecimal = sys.modules['decimal']
2413
2414 # Round trip
2415 sys.modules['decimal'] = self.decimal
2416 d = Decimal('-3.141590000')
2417 p = pickle.dumps(d)
2418 e = pickle.loads(p)
2419 self.assertEqual(d, e)
2420
2421 if C:
2422 # Test interchangeability
2423 x = C.Decimal('-3.123e81723')
2424 y = P.Decimal('-3.123e81723')
2425
2426 sys.modules['decimal'] = C
2427 sx = pickle.dumps(x)
2428 sys.modules['decimal'] = P
2429 r = pickle.loads(sx)
2430 self.assertIsInstance(r, P.Decimal)
2431 self.assertEqual(r, y)
2432
2433 sys.modules['decimal'] = P
2434 sy = pickle.dumps(y)
2435 sys.modules['decimal'] = C
2436 r = pickle.loads(sy)
2437 self.assertIsInstance(r, C.Decimal)
2438 self.assertEqual(r, x)
2439
Stefan Krahf1d4e422014-04-29 18:23:35 +02002440 x = C.Decimal('-3.123e81723').as_tuple()
2441 y = P.Decimal('-3.123e81723').as_tuple()
2442
2443 sys.modules['decimal'] = C
2444 sx = pickle.dumps(x)
2445 sys.modules['decimal'] = P
2446 r = pickle.loads(sx)
2447 self.assertIsInstance(r, P.DecimalTuple)
2448 self.assertEqual(r, y)
2449
2450 sys.modules['decimal'] = P
2451 sy = pickle.dumps(y)
2452 sys.modules['decimal'] = C
2453 r = pickle.loads(sy)
2454 self.assertIsInstance(r, C.DecimalTuple)
2455 self.assertEqual(r, x)
2456
Stefan Krah1919b7e2012-03-21 18:25:23 +01002457 sys.modules['decimal'] = savedecimal
2458
2459 def test_int(self):
2460 Decimal = self.decimal.Decimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01002461
2462 for x in range(-250, 250):
2463 s = '%0.2f' % (x / 100.0)
2464 # should work the same as for floats
2465 self.assertEqual(int(Decimal(s)), int(float(s)))
2466 # should work the same as to_integral in the ROUND_DOWN mode
2467 d = Decimal(s)
2468 r = d.to_integral(ROUND_DOWN)
2469 self.assertEqual(Decimal(int(d)), r)
2470
2471 self.assertRaises(ValueError, int, Decimal('-nan'))
2472 self.assertRaises(ValueError, int, Decimal('snan'))
2473 self.assertRaises(OverflowError, int, Decimal('inf'))
2474 self.assertRaises(OverflowError, int, Decimal('-inf'))
2475
2476 def test_trunc(self):
2477 Decimal = self.decimal.Decimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01002478
2479 for x in range(-250, 250):
2480 s = '%0.2f' % (x / 100.0)
2481 # should work the same as for floats
2482 self.assertEqual(int(Decimal(s)), int(float(s)))
2483 # should work the same as to_integral in the ROUND_DOWN mode
2484 d = Decimal(s)
2485 r = d.to_integral(ROUND_DOWN)
2486 self.assertEqual(Decimal(math.trunc(d)), r)
2487
2488 def test_from_float(self):
2489
2490 Decimal = self.decimal.Decimal
2491
2492 class MyDecimal(Decimal):
2493 pass
2494
2495 self.assertTrue(issubclass(MyDecimal, Decimal))
2496
2497 r = MyDecimal.from_float(0.1)
2498 self.assertEqual(type(r), MyDecimal)
2499 self.assertEqual(str(r),
2500 '0.1000000000000000055511151231257827021181583404541015625')
2501 bigint = 12345678901234567890123456789
2502 self.assertEqual(MyDecimal.from_float(bigint), MyDecimal(bigint))
2503 self.assertTrue(MyDecimal.from_float(float('nan')).is_qnan())
2504 self.assertTrue(MyDecimal.from_float(float('inf')).is_infinite())
2505 self.assertTrue(MyDecimal.from_float(float('-inf')).is_infinite())
2506 self.assertEqual(str(MyDecimal.from_float(float('nan'))),
2507 str(Decimal('NaN')))
2508 self.assertEqual(str(MyDecimal.from_float(float('inf'))),
2509 str(Decimal('Infinity')))
2510 self.assertEqual(str(MyDecimal.from_float(float('-inf'))),
2511 str(Decimal('-Infinity')))
2512 self.assertRaises(TypeError, MyDecimal.from_float, 'abc')
2513 for i in range(200):
2514 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
2515 self.assertEqual(x, float(MyDecimal.from_float(x))) # roundtrip
2516
2517 def test_create_decimal_from_float(self):
2518 Decimal = self.decimal.Decimal
2519 Context = self.decimal.Context
Stefan Krah1919b7e2012-03-21 18:25:23 +01002520 Inexact = self.decimal.Inexact
2521
2522 context = Context(prec=5, rounding=ROUND_DOWN)
2523 self.assertEqual(
2524 context.create_decimal_from_float(math.pi),
2525 Decimal('3.1415')
2526 )
2527 context = Context(prec=5, rounding=ROUND_UP)
2528 self.assertEqual(
2529 context.create_decimal_from_float(math.pi),
2530 Decimal('3.1416')
2531 )
2532 context = Context(prec=5, traps=[Inexact])
2533 self.assertRaises(
2534 Inexact,
2535 context.create_decimal_from_float,
2536 math.pi
2537 )
2538 self.assertEqual(repr(context.create_decimal_from_float(-0.0)),
2539 "Decimal('-0')")
2540 self.assertEqual(repr(context.create_decimal_from_float(1.0)),
2541 "Decimal('1')")
2542 self.assertEqual(repr(context.create_decimal_from_float(10)),
2543 "Decimal('10')")
2544
2545 def test_quantize(self):
2546 Decimal = self.decimal.Decimal
2547 Context = self.decimal.Context
2548 InvalidOperation = self.decimal.InvalidOperation
Stefan Krah1919b7e2012-03-21 18:25:23 +01002549
2550 c = Context(Emax=99999, Emin=-99999)
2551 self.assertEqual(
2552 Decimal('7.335').quantize(Decimal('.01')),
2553 Decimal('7.34')
2554 )
2555 self.assertEqual(
2556 Decimal('7.335').quantize(Decimal('.01'), rounding=ROUND_DOWN),
2557 Decimal('7.33')
2558 )
2559 self.assertRaises(
2560 InvalidOperation,
2561 Decimal("10e99999").quantize, Decimal('1e100000'), context=c
2562 )
2563
2564 c = Context()
2565 d = Decimal("0.871831e800")
2566 x = d.quantize(context=c, exp=Decimal("1e797"), rounding=ROUND_DOWN)
2567 self.assertEqual(x, Decimal('8.71E+799'))
2568
2569 def test_complex(self):
2570 Decimal = self.decimal.Decimal
2571
2572 x = Decimal("9.8182731e181273")
2573 self.assertEqual(x.real, x)
2574 self.assertEqual(x.imag, 0)
2575 self.assertEqual(x.conjugate(), x)
2576
2577 x = Decimal("1")
2578 self.assertEqual(complex(x), complex(float(1)))
2579
2580 self.assertRaises(AttributeError, setattr, x, 'real', 100)
2581 self.assertRaises(AttributeError, setattr, x, 'imag', 100)
2582 self.assertRaises(AttributeError, setattr, x, 'conjugate', 100)
2583 self.assertRaises(AttributeError, setattr, x, '__complex__', 100)
2584
2585 def test_named_parameters(self):
2586 D = self.decimal.Decimal
2587 Context = self.decimal.Context
2588 localcontext = self.decimal.localcontext
2589 InvalidOperation = self.decimal.InvalidOperation
2590 Overflow = self.decimal.Overflow
2591
2592 xc = Context()
2593 xc.prec = 1
2594 xc.Emax = 1
2595 xc.Emin = -1
2596
2597 with localcontext() as c:
2598 c.clear_flags()
2599
2600 self.assertEqual(D(9, xc), 9)
2601 self.assertEqual(D(9, context=xc), 9)
2602 self.assertEqual(D(context=xc, value=9), 9)
2603 self.assertEqual(D(context=xc), 0)
2604 xc.clear_flags()
2605 self.assertRaises(InvalidOperation, D, "xyz", context=xc)
2606 self.assertTrue(xc.flags[InvalidOperation])
2607 self.assertFalse(c.flags[InvalidOperation])
2608
2609 xc.clear_flags()
2610 self.assertEqual(D(2).exp(context=xc), 7)
2611 self.assertRaises(Overflow, D(8).exp, context=xc)
2612 self.assertTrue(xc.flags[Overflow])
2613 self.assertFalse(c.flags[Overflow])
2614
2615 xc.clear_flags()
2616 self.assertEqual(D(2).ln(context=xc), D('0.7'))
2617 self.assertRaises(InvalidOperation, D(-1).ln, context=xc)
2618 self.assertTrue(xc.flags[InvalidOperation])
2619 self.assertFalse(c.flags[InvalidOperation])
2620
2621 self.assertEqual(D(0).log10(context=xc), D('-inf'))
2622 self.assertEqual(D(-1).next_minus(context=xc), -2)
2623 self.assertEqual(D(-1).next_plus(context=xc), D('-0.9'))
2624 self.assertEqual(D("9.73").normalize(context=xc), D('1E+1'))
2625 self.assertEqual(D("9999").to_integral(context=xc), 9999)
2626 self.assertEqual(D("-2000").to_integral_exact(context=xc), -2000)
2627 self.assertEqual(D("123").to_integral_value(context=xc), 123)
2628 self.assertEqual(D("0.0625").sqrt(context=xc), D('0.2'))
2629
2630 self.assertEqual(D("0.0625").compare(context=xc, other=3), -1)
2631 xc.clear_flags()
2632 self.assertRaises(InvalidOperation,
2633 D("0").compare_signal, D('nan'), context=xc)
2634 self.assertTrue(xc.flags[InvalidOperation])
2635 self.assertFalse(c.flags[InvalidOperation])
2636 self.assertEqual(D("0.01").max(D('0.0101'), context=xc), D('0.0'))
2637 self.assertEqual(D("0.01").max(D('0.0101'), context=xc), D('0.0'))
2638 self.assertEqual(D("0.2").max_mag(D('-0.3'), context=xc),
2639 D('-0.3'))
2640 self.assertEqual(D("0.02").min(D('-0.03'), context=xc), D('-0.0'))
2641 self.assertEqual(D("0.02").min_mag(D('-0.03'), context=xc),
2642 D('0.0'))
2643 self.assertEqual(D("0.2").next_toward(D('-1'), context=xc), D('0.1'))
2644 xc.clear_flags()
2645 self.assertRaises(InvalidOperation,
2646 D("0.2").quantize, D('1e10'), context=xc)
2647 self.assertTrue(xc.flags[InvalidOperation])
2648 self.assertFalse(c.flags[InvalidOperation])
2649 self.assertEqual(D("9.99").remainder_near(D('1.5'), context=xc),
2650 D('-0.5'))
2651
2652 self.assertEqual(D("9.9").fma(third=D('0.9'), context=xc, other=7),
2653 D('7E+1'))
2654
2655 self.assertRaises(TypeError, D(1).is_canonical, context=xc)
2656 self.assertRaises(TypeError, D(1).is_finite, context=xc)
2657 self.assertRaises(TypeError, D(1).is_infinite, context=xc)
2658 self.assertRaises(TypeError, D(1).is_nan, context=xc)
2659 self.assertRaises(TypeError, D(1).is_qnan, context=xc)
2660 self.assertRaises(TypeError, D(1).is_snan, context=xc)
2661 self.assertRaises(TypeError, D(1).is_signed, context=xc)
2662 self.assertRaises(TypeError, D(1).is_zero, context=xc)
2663
2664 self.assertFalse(D("0.01").is_normal(context=xc))
2665 self.assertTrue(D("0.01").is_subnormal(context=xc))
2666
2667 self.assertRaises(TypeError, D(1).adjusted, context=xc)
2668 self.assertRaises(TypeError, D(1).conjugate, context=xc)
2669 self.assertRaises(TypeError, D(1).radix, context=xc)
2670
2671 self.assertEqual(D(-111).logb(context=xc), 2)
2672 self.assertEqual(D(0).logical_invert(context=xc), 1)
2673 self.assertEqual(D('0.01').number_class(context=xc), '+Subnormal')
2674 self.assertEqual(D('0.21').to_eng_string(context=xc), '0.21')
2675
2676 self.assertEqual(D('11').logical_and(D('10'), context=xc), 0)
2677 self.assertEqual(D('11').logical_or(D('10'), context=xc), 1)
2678 self.assertEqual(D('01').logical_xor(D('10'), context=xc), 1)
2679 self.assertEqual(D('23').rotate(1, context=xc), 3)
2680 self.assertEqual(D('23').rotate(1, context=xc), 3)
2681 xc.clear_flags()
2682 self.assertRaises(Overflow,
2683 D('23').scaleb, 1, context=xc)
2684 self.assertTrue(xc.flags[Overflow])
2685 self.assertFalse(c.flags[Overflow])
2686 self.assertEqual(D('23').shift(-1, context=xc), 0)
2687
2688 self.assertRaises(TypeError, D.from_float, 1.1, context=xc)
2689 self.assertRaises(TypeError, D(0).as_tuple, context=xc)
2690
Stefan Krah040e3112012-12-15 22:33:33 +01002691 self.assertEqual(D(1).canonical(), 1)
2692 self.assertRaises(TypeError, D("-1").copy_abs, context=xc)
2693 self.assertRaises(TypeError, D("-1").copy_negate, context=xc)
2694 self.assertRaises(TypeError, D(1).canonical, context="x")
2695 self.assertRaises(TypeError, D(1).canonical, xyz="x")
Stefan Krah1919b7e2012-03-21 18:25:23 +01002696
Stefan Krahb6405ef2012-03-23 14:46:48 +01002697 def test_exception_hierarchy(self):
2698
2699 decimal = self.decimal
2700 DecimalException = decimal.DecimalException
2701 InvalidOperation = decimal.InvalidOperation
2702 FloatOperation = decimal.FloatOperation
2703 DivisionByZero = decimal.DivisionByZero
2704 Overflow = decimal.Overflow
2705 Underflow = decimal.Underflow
2706 Subnormal = decimal.Subnormal
2707 Inexact = decimal.Inexact
2708 Rounded = decimal.Rounded
2709 Clamped = decimal.Clamped
2710
2711 self.assertTrue(issubclass(DecimalException, ArithmeticError))
2712
2713 self.assertTrue(issubclass(InvalidOperation, DecimalException))
2714 self.assertTrue(issubclass(FloatOperation, DecimalException))
2715 self.assertTrue(issubclass(FloatOperation, TypeError))
2716 self.assertTrue(issubclass(DivisionByZero, DecimalException))
2717 self.assertTrue(issubclass(DivisionByZero, ZeroDivisionError))
2718 self.assertTrue(issubclass(Overflow, Rounded))
2719 self.assertTrue(issubclass(Overflow, Inexact))
2720 self.assertTrue(issubclass(Overflow, DecimalException))
2721 self.assertTrue(issubclass(Underflow, Inexact))
2722 self.assertTrue(issubclass(Underflow, Rounded))
2723 self.assertTrue(issubclass(Underflow, Subnormal))
2724 self.assertTrue(issubclass(Underflow, DecimalException))
2725
2726 self.assertTrue(issubclass(Subnormal, DecimalException))
2727 self.assertTrue(issubclass(Inexact, DecimalException))
2728 self.assertTrue(issubclass(Rounded, DecimalException))
2729 self.assertTrue(issubclass(Clamped, DecimalException))
2730
2731 self.assertTrue(issubclass(decimal.ConversionSyntax, InvalidOperation))
2732 self.assertTrue(issubclass(decimal.DivisionImpossible, InvalidOperation))
2733 self.assertTrue(issubclass(decimal.DivisionUndefined, InvalidOperation))
2734 self.assertTrue(issubclass(decimal.DivisionUndefined, ZeroDivisionError))
2735 self.assertTrue(issubclass(decimal.InvalidContext, InvalidOperation))
2736
Stefan Krah1919b7e2012-03-21 18:25:23 +01002737class CPythonAPItests(PythonAPItests):
2738 decimal = C
2739class PyPythonAPItests(PythonAPItests):
2740 decimal = P
2741
2742class ContextAPItests(unittest.TestCase):
2743
Stefan Krah9a4ff432012-12-16 21:10:35 +01002744 def test_none_args(self):
2745 Context = self.decimal.Context
2746 InvalidOperation = self.decimal.InvalidOperation
2747 DivisionByZero = self.decimal.DivisionByZero
2748 Overflow = self.decimal.Overflow
Stefan Krah9a4ff432012-12-16 21:10:35 +01002749
2750 c1 = Context()
2751 c2 = Context(prec=None, rounding=None, Emax=None, Emin=None,
2752 capitals=None, clamp=None, flags=None, traps=None)
2753 for c in [c1, c2]:
2754 self.assertEqual(c.prec, 28)
2755 self.assertEqual(c.rounding, ROUND_HALF_EVEN)
2756 self.assertEqual(c.Emax, 999999)
2757 self.assertEqual(c.Emin, -999999)
2758 self.assertEqual(c.capitals, 1)
2759 self.assertEqual(c.clamp, 0)
2760 assert_signals(self, c, 'flags', [])
2761 assert_signals(self, c, 'traps', [InvalidOperation, DivisionByZero,
2762 Overflow])
2763
Stefan Krah59a4a932013-01-16 12:58:59 +01002764 @cpython_only
2765 def test_from_legacy_strings(self):
2766 import _testcapi
2767 c = self.decimal.Context()
2768
2769 for rnd in RoundingModes:
2770 c.rounding = _testcapi.unicode_legacy_string(rnd)
2771 self.assertEqual(c.rounding, rnd)
2772
2773 s = _testcapi.unicode_legacy_string('')
2774 self.assertRaises(TypeError, setattr, c, 'rounding', s)
2775
2776 s = _testcapi.unicode_legacy_string('ROUND_\x00UP')
2777 self.assertRaises(TypeError, setattr, c, 'rounding', s)
2778
Stefan Krah1919b7e2012-03-21 18:25:23 +01002779 def test_pickle(self):
2780
2781 Context = self.decimal.Context
2782
2783 savedecimal = sys.modules['decimal']
2784
2785 # Round trip
2786 sys.modules['decimal'] = self.decimal
2787 c = Context()
2788 e = pickle.loads(pickle.dumps(c))
2789
2790 self.assertEqual(c.prec, e.prec)
2791 self.assertEqual(c.Emin, e.Emin)
2792 self.assertEqual(c.Emax, e.Emax)
2793 self.assertEqual(c.rounding, e.rounding)
2794 self.assertEqual(c.capitals, e.capitals)
2795 self.assertEqual(c.clamp, e.clamp)
2796 self.assertEqual(c.flags, e.flags)
2797 self.assertEqual(c.traps, e.traps)
2798
2799 # Test interchangeability
2800 combinations = [(C, P), (P, C)] if C else [(P, P)]
2801 for dumper, loader in combinations:
Stefan Krah59a4a932013-01-16 12:58:59 +01002802 for ri, _ in enumerate(RoundingModes):
Stefan Krah1919b7e2012-03-21 18:25:23 +01002803 for fi, _ in enumerate(OrderedSignals[dumper]):
2804 for ti, _ in enumerate(OrderedSignals[dumper]):
2805
2806 prec = random.randrange(1, 100)
2807 emin = random.randrange(-100, 0)
2808 emax = random.randrange(1, 100)
2809 caps = random.randrange(2)
2810 clamp = random.randrange(2)
2811
2812 # One module dumps
2813 sys.modules['decimal'] = dumper
2814 c = dumper.Context(
2815 prec=prec, Emin=emin, Emax=emax,
Stefan Krah59a4a932013-01-16 12:58:59 +01002816 rounding=RoundingModes[ri],
Stefan Krah1919b7e2012-03-21 18:25:23 +01002817 capitals=caps, clamp=clamp,
2818 flags=OrderedSignals[dumper][:fi],
2819 traps=OrderedSignals[dumper][:ti]
2820 )
2821 s = pickle.dumps(c)
2822
2823 # The other module loads
2824 sys.modules['decimal'] = loader
2825 d = pickle.loads(s)
2826 self.assertIsInstance(d, loader.Context)
2827
2828 self.assertEqual(d.prec, prec)
2829 self.assertEqual(d.Emin, emin)
2830 self.assertEqual(d.Emax, emax)
Stefan Krah59a4a932013-01-16 12:58:59 +01002831 self.assertEqual(d.rounding, RoundingModes[ri])
Stefan Krah1919b7e2012-03-21 18:25:23 +01002832 self.assertEqual(d.capitals, caps)
2833 self.assertEqual(d.clamp, clamp)
2834 assert_signals(self, d, 'flags', OrderedSignals[loader][:fi])
2835 assert_signals(self, d, 'traps', OrderedSignals[loader][:ti])
2836
2837 sys.modules['decimal'] = savedecimal
2838
2839 def test_equality_with_other_types(self):
2840 Decimal = self.decimal.Decimal
2841
2842 self.assertIn(Decimal(10), ['a', 1.0, Decimal(10), (1,2), {}])
2843 self.assertNotIn(Decimal(10), ['a', 1.0, (1,2), {}])
2844
2845 def test_copy(self):
2846 # All copies should be deep
2847 Decimal = self.decimal.Decimal
2848 Context = self.decimal.Context
2849
2850 c = Context()
2851 d = c.copy()
2852 self.assertNotEqual(id(c), id(d))
2853 self.assertNotEqual(id(c.flags), id(d.flags))
2854 self.assertNotEqual(id(c.traps), id(d.traps))
2855 k1 = set(c.flags.keys())
2856 k2 = set(d.flags.keys())
2857 self.assertEqual(k1, k2)
2858 self.assertEqual(c.flags, d.flags)
2859
2860 def test__clamp(self):
2861 # In Python 3.2, the private attribute `_clamp` was made
2862 # public (issue 8540), with the old `_clamp` becoming a
2863 # property wrapping `clamp`. For the duration of Python 3.2
2864 # only, the attribute should be gettable/settable via both
2865 # `clamp` and `_clamp`; in Python 3.3, `_clamp` should be
2866 # removed.
2867 Context = self.decimal.Context
2868 c = Context()
2869 self.assertRaises(AttributeError, getattr, c, '_clamp')
2870
2871 def test_abs(self):
2872 Decimal = self.decimal.Decimal
2873 Context = self.decimal.Context
2874
2875 c = Context()
2876 d = c.abs(Decimal(-1))
2877 self.assertEqual(c.abs(-1), d)
2878 self.assertRaises(TypeError, c.abs, '-1')
2879
2880 def test_add(self):
2881 Decimal = self.decimal.Decimal
2882 Context = self.decimal.Context
2883
2884 c = Context()
2885 d = c.add(Decimal(1), Decimal(1))
2886 self.assertEqual(c.add(1, 1), d)
2887 self.assertEqual(c.add(Decimal(1), 1), d)
2888 self.assertEqual(c.add(1, Decimal(1)), d)
2889 self.assertRaises(TypeError, c.add, '1', 1)
2890 self.assertRaises(TypeError, c.add, 1, '1')
2891
2892 def test_compare(self):
2893 Decimal = self.decimal.Decimal
2894 Context = self.decimal.Context
2895
2896 c = Context()
2897 d = c.compare(Decimal(1), Decimal(1))
2898 self.assertEqual(c.compare(1, 1), d)
2899 self.assertEqual(c.compare(Decimal(1), 1), d)
2900 self.assertEqual(c.compare(1, Decimal(1)), d)
2901 self.assertRaises(TypeError, c.compare, '1', 1)
2902 self.assertRaises(TypeError, c.compare, 1, '1')
2903
2904 def test_compare_signal(self):
2905 Decimal = self.decimal.Decimal
2906 Context = self.decimal.Context
2907
2908 c = Context()
2909 d = c.compare_signal(Decimal(1), Decimal(1))
2910 self.assertEqual(c.compare_signal(1, 1), d)
2911 self.assertEqual(c.compare_signal(Decimal(1), 1), d)
2912 self.assertEqual(c.compare_signal(1, Decimal(1)), d)
2913 self.assertRaises(TypeError, c.compare_signal, '1', 1)
2914 self.assertRaises(TypeError, c.compare_signal, 1, '1')
2915
2916 def test_compare_total(self):
2917 Decimal = self.decimal.Decimal
2918 Context = self.decimal.Context
2919
2920 c = Context()
2921 d = c.compare_total(Decimal(1), Decimal(1))
2922 self.assertEqual(c.compare_total(1, 1), d)
2923 self.assertEqual(c.compare_total(Decimal(1), 1), d)
2924 self.assertEqual(c.compare_total(1, Decimal(1)), d)
2925 self.assertRaises(TypeError, c.compare_total, '1', 1)
2926 self.assertRaises(TypeError, c.compare_total, 1, '1')
2927
2928 def test_compare_total_mag(self):
2929 Decimal = self.decimal.Decimal
2930 Context = self.decimal.Context
2931
2932 c = Context()
2933 d = c.compare_total_mag(Decimal(1), Decimal(1))
2934 self.assertEqual(c.compare_total_mag(1, 1), d)
2935 self.assertEqual(c.compare_total_mag(Decimal(1), 1), d)
2936 self.assertEqual(c.compare_total_mag(1, Decimal(1)), d)
2937 self.assertRaises(TypeError, c.compare_total_mag, '1', 1)
2938 self.assertRaises(TypeError, c.compare_total_mag, 1, '1')
2939
2940 def test_copy_abs(self):
2941 Decimal = self.decimal.Decimal
2942 Context = self.decimal.Context
2943
2944 c = Context()
2945 d = c.copy_abs(Decimal(-1))
2946 self.assertEqual(c.copy_abs(-1), d)
2947 self.assertRaises(TypeError, c.copy_abs, '-1')
2948
2949 def test_copy_decimal(self):
2950 Decimal = self.decimal.Decimal
2951 Context = self.decimal.Context
2952
2953 c = Context()
2954 d = c.copy_decimal(Decimal(-1))
2955 self.assertEqual(c.copy_decimal(-1), d)
2956 self.assertRaises(TypeError, c.copy_decimal, '-1')
2957
2958 def test_copy_negate(self):
2959 Decimal = self.decimal.Decimal
2960 Context = self.decimal.Context
2961
2962 c = Context()
2963 d = c.copy_negate(Decimal(-1))
2964 self.assertEqual(c.copy_negate(-1), d)
2965 self.assertRaises(TypeError, c.copy_negate, '-1')
2966
2967 def test_copy_sign(self):
2968 Decimal = self.decimal.Decimal
2969 Context = self.decimal.Context
2970
2971 c = Context()
2972 d = c.copy_sign(Decimal(1), Decimal(-2))
2973 self.assertEqual(c.copy_sign(1, -2), d)
2974 self.assertEqual(c.copy_sign(Decimal(1), -2), d)
2975 self.assertEqual(c.copy_sign(1, Decimal(-2)), d)
2976 self.assertRaises(TypeError, c.copy_sign, '1', -2)
2977 self.assertRaises(TypeError, c.copy_sign, 1, '-2')
2978
2979 def test_divide(self):
2980 Decimal = self.decimal.Decimal
2981 Context = self.decimal.Context
2982
2983 c = Context()
2984 d = c.divide(Decimal(1), Decimal(2))
2985 self.assertEqual(c.divide(1, 2), d)
2986 self.assertEqual(c.divide(Decimal(1), 2), d)
2987 self.assertEqual(c.divide(1, Decimal(2)), d)
2988 self.assertRaises(TypeError, c.divide, '1', 2)
2989 self.assertRaises(TypeError, c.divide, 1, '2')
2990
2991 def test_divide_int(self):
2992 Decimal = self.decimal.Decimal
2993 Context = self.decimal.Context
2994
2995 c = Context()
2996 d = c.divide_int(Decimal(1), Decimal(2))
2997 self.assertEqual(c.divide_int(1, 2), d)
2998 self.assertEqual(c.divide_int(Decimal(1), 2), d)
2999 self.assertEqual(c.divide_int(1, Decimal(2)), d)
3000 self.assertRaises(TypeError, c.divide_int, '1', 2)
3001 self.assertRaises(TypeError, c.divide_int, 1, '2')
3002
3003 def test_divmod(self):
3004 Decimal = self.decimal.Decimal
3005 Context = self.decimal.Context
3006
3007 c = Context()
3008 d = c.divmod(Decimal(1), Decimal(2))
3009 self.assertEqual(c.divmod(1, 2), d)
3010 self.assertEqual(c.divmod(Decimal(1), 2), d)
3011 self.assertEqual(c.divmod(1, Decimal(2)), d)
3012 self.assertRaises(TypeError, c.divmod, '1', 2)
3013 self.assertRaises(TypeError, c.divmod, 1, '2')
3014
3015 def test_exp(self):
3016 Decimal = self.decimal.Decimal
3017 Context = self.decimal.Context
3018
3019 c = Context()
3020 d = c.exp(Decimal(10))
3021 self.assertEqual(c.exp(10), d)
3022 self.assertRaises(TypeError, c.exp, '10')
3023
3024 def test_fma(self):
3025 Decimal = self.decimal.Decimal
3026 Context = self.decimal.Context
3027
3028 c = Context()
3029 d = c.fma(Decimal(2), Decimal(3), Decimal(4))
3030 self.assertEqual(c.fma(2, 3, 4), d)
3031 self.assertEqual(c.fma(Decimal(2), 3, 4), d)
3032 self.assertEqual(c.fma(2, Decimal(3), 4), d)
3033 self.assertEqual(c.fma(2, 3, Decimal(4)), d)
3034 self.assertEqual(c.fma(Decimal(2), Decimal(3), 4), d)
3035 self.assertRaises(TypeError, c.fma, '2', 3, 4)
3036 self.assertRaises(TypeError, c.fma, 2, '3', 4)
3037 self.assertRaises(TypeError, c.fma, 2, 3, '4')
3038
3039 # Issue 12079 for Context.fma ...
3040 self.assertRaises(TypeError, c.fma,
3041 Decimal('Infinity'), Decimal(0), "not a decimal")
3042 self.assertRaises(TypeError, c.fma,
3043 Decimal(1), Decimal('snan'), 1.222)
3044 # ... and for Decimal.fma.
3045 self.assertRaises(TypeError, Decimal('Infinity').fma,
3046 Decimal(0), "not a decimal")
3047 self.assertRaises(TypeError, Decimal(1).fma,
3048 Decimal('snan'), 1.222)
3049
3050 def test_is_finite(self):
3051 Decimal = self.decimal.Decimal
3052 Context = self.decimal.Context
3053
3054 c = Context()
3055 d = c.is_finite(Decimal(10))
3056 self.assertEqual(c.is_finite(10), d)
3057 self.assertRaises(TypeError, c.is_finite, '10')
3058
3059 def test_is_infinite(self):
3060 Decimal = self.decimal.Decimal
3061 Context = self.decimal.Context
3062
3063 c = Context()
3064 d = c.is_infinite(Decimal(10))
3065 self.assertEqual(c.is_infinite(10), d)
3066 self.assertRaises(TypeError, c.is_infinite, '10')
3067
3068 def test_is_nan(self):
3069 Decimal = self.decimal.Decimal
3070 Context = self.decimal.Context
3071
3072 c = Context()
3073 d = c.is_nan(Decimal(10))
3074 self.assertEqual(c.is_nan(10), d)
3075 self.assertRaises(TypeError, c.is_nan, '10')
3076
3077 def test_is_normal(self):
3078 Decimal = self.decimal.Decimal
3079 Context = self.decimal.Context
3080
3081 c = Context()
3082 d = c.is_normal(Decimal(10))
3083 self.assertEqual(c.is_normal(10), d)
3084 self.assertRaises(TypeError, c.is_normal, '10')
3085
3086 def test_is_qnan(self):
3087 Decimal = self.decimal.Decimal
3088 Context = self.decimal.Context
3089
3090 c = Context()
3091 d = c.is_qnan(Decimal(10))
3092 self.assertEqual(c.is_qnan(10), d)
3093 self.assertRaises(TypeError, c.is_qnan, '10')
3094
3095 def test_is_signed(self):
3096 Decimal = self.decimal.Decimal
3097 Context = self.decimal.Context
3098
3099 c = Context()
3100 d = c.is_signed(Decimal(10))
3101 self.assertEqual(c.is_signed(10), d)
3102 self.assertRaises(TypeError, c.is_signed, '10')
3103
3104 def test_is_snan(self):
3105 Decimal = self.decimal.Decimal
3106 Context = self.decimal.Context
3107
3108 c = Context()
3109 d = c.is_snan(Decimal(10))
3110 self.assertEqual(c.is_snan(10), d)
3111 self.assertRaises(TypeError, c.is_snan, '10')
3112
3113 def test_is_subnormal(self):
3114 Decimal = self.decimal.Decimal
3115 Context = self.decimal.Context
3116
3117 c = Context()
3118 d = c.is_subnormal(Decimal(10))
3119 self.assertEqual(c.is_subnormal(10), d)
3120 self.assertRaises(TypeError, c.is_subnormal, '10')
3121
3122 def test_is_zero(self):
3123 Decimal = self.decimal.Decimal
3124 Context = self.decimal.Context
3125
3126 c = Context()
3127 d = c.is_zero(Decimal(10))
3128 self.assertEqual(c.is_zero(10), d)
3129 self.assertRaises(TypeError, c.is_zero, '10')
3130
3131 def test_ln(self):
3132 Decimal = self.decimal.Decimal
3133 Context = self.decimal.Context
3134
3135 c = Context()
3136 d = c.ln(Decimal(10))
3137 self.assertEqual(c.ln(10), d)
3138 self.assertRaises(TypeError, c.ln, '10')
3139
3140 def test_log10(self):
3141 Decimal = self.decimal.Decimal
3142 Context = self.decimal.Context
3143
3144 c = Context()
3145 d = c.log10(Decimal(10))
3146 self.assertEqual(c.log10(10), d)
3147 self.assertRaises(TypeError, c.log10, '10')
3148
3149 def test_logb(self):
3150 Decimal = self.decimal.Decimal
3151 Context = self.decimal.Context
3152
3153 c = Context()
3154 d = c.logb(Decimal(10))
3155 self.assertEqual(c.logb(10), d)
3156 self.assertRaises(TypeError, c.logb, '10')
3157
3158 def test_logical_and(self):
3159 Decimal = self.decimal.Decimal
3160 Context = self.decimal.Context
3161
3162 c = Context()
3163 d = c.logical_and(Decimal(1), Decimal(1))
3164 self.assertEqual(c.logical_and(1, 1), d)
3165 self.assertEqual(c.logical_and(Decimal(1), 1), d)
3166 self.assertEqual(c.logical_and(1, Decimal(1)), d)
3167 self.assertRaises(TypeError, c.logical_and, '1', 1)
3168 self.assertRaises(TypeError, c.logical_and, 1, '1')
3169
3170 def test_logical_invert(self):
3171 Decimal = self.decimal.Decimal
3172 Context = self.decimal.Context
3173
3174 c = Context()
3175 d = c.logical_invert(Decimal(1000))
3176 self.assertEqual(c.logical_invert(1000), d)
3177 self.assertRaises(TypeError, c.logical_invert, '1000')
3178
3179 def test_logical_or(self):
3180 Decimal = self.decimal.Decimal
3181 Context = self.decimal.Context
3182
3183 c = Context()
3184 d = c.logical_or(Decimal(1), Decimal(1))
3185 self.assertEqual(c.logical_or(1, 1), d)
3186 self.assertEqual(c.logical_or(Decimal(1), 1), d)
3187 self.assertEqual(c.logical_or(1, Decimal(1)), d)
3188 self.assertRaises(TypeError, c.logical_or, '1', 1)
3189 self.assertRaises(TypeError, c.logical_or, 1, '1')
3190
3191 def test_logical_xor(self):
3192 Decimal = self.decimal.Decimal
3193 Context = self.decimal.Context
3194
3195 c = Context()
3196 d = c.logical_xor(Decimal(1), Decimal(1))
3197 self.assertEqual(c.logical_xor(1, 1), d)
3198 self.assertEqual(c.logical_xor(Decimal(1), 1), d)
3199 self.assertEqual(c.logical_xor(1, Decimal(1)), d)
3200 self.assertRaises(TypeError, c.logical_xor, '1', 1)
3201 self.assertRaises(TypeError, c.logical_xor, 1, '1')
3202
3203 def test_max(self):
3204 Decimal = self.decimal.Decimal
3205 Context = self.decimal.Context
3206
3207 c = Context()
3208 d = c.max(Decimal(1), Decimal(2))
3209 self.assertEqual(c.max(1, 2), d)
3210 self.assertEqual(c.max(Decimal(1), 2), d)
3211 self.assertEqual(c.max(1, Decimal(2)), d)
3212 self.assertRaises(TypeError, c.max, '1', 2)
3213 self.assertRaises(TypeError, c.max, 1, '2')
3214
3215 def test_max_mag(self):
3216 Decimal = self.decimal.Decimal
3217 Context = self.decimal.Context
3218
3219 c = Context()
3220 d = c.max_mag(Decimal(1), Decimal(2))
3221 self.assertEqual(c.max_mag(1, 2), d)
3222 self.assertEqual(c.max_mag(Decimal(1), 2), d)
3223 self.assertEqual(c.max_mag(1, Decimal(2)), d)
3224 self.assertRaises(TypeError, c.max_mag, '1', 2)
3225 self.assertRaises(TypeError, c.max_mag, 1, '2')
3226
3227 def test_min(self):
3228 Decimal = self.decimal.Decimal
3229 Context = self.decimal.Context
3230
3231 c = Context()
3232 d = c.min(Decimal(1), Decimal(2))
3233 self.assertEqual(c.min(1, 2), d)
3234 self.assertEqual(c.min(Decimal(1), 2), d)
3235 self.assertEqual(c.min(1, Decimal(2)), d)
3236 self.assertRaises(TypeError, c.min, '1', 2)
3237 self.assertRaises(TypeError, c.min, 1, '2')
3238
3239 def test_min_mag(self):
3240 Decimal = self.decimal.Decimal
3241 Context = self.decimal.Context
3242
3243 c = Context()
3244 d = c.min_mag(Decimal(1), Decimal(2))
3245 self.assertEqual(c.min_mag(1, 2), d)
3246 self.assertEqual(c.min_mag(Decimal(1), 2), d)
3247 self.assertEqual(c.min_mag(1, Decimal(2)), d)
3248 self.assertRaises(TypeError, c.min_mag, '1', 2)
3249 self.assertRaises(TypeError, c.min_mag, 1, '2')
3250
3251 def test_minus(self):
3252 Decimal = self.decimal.Decimal
3253 Context = self.decimal.Context
3254
3255 c = Context()
3256 d = c.minus(Decimal(10))
3257 self.assertEqual(c.minus(10), d)
3258 self.assertRaises(TypeError, c.minus, '10')
3259
3260 def test_multiply(self):
3261 Decimal = self.decimal.Decimal
3262 Context = self.decimal.Context
3263
3264 c = Context()
3265 d = c.multiply(Decimal(1), Decimal(2))
3266 self.assertEqual(c.multiply(1, 2), d)
3267 self.assertEqual(c.multiply(Decimal(1), 2), d)
3268 self.assertEqual(c.multiply(1, Decimal(2)), d)
3269 self.assertRaises(TypeError, c.multiply, '1', 2)
3270 self.assertRaises(TypeError, c.multiply, 1, '2')
3271
3272 def test_next_minus(self):
3273 Decimal = self.decimal.Decimal
3274 Context = self.decimal.Context
3275
3276 c = Context()
3277 d = c.next_minus(Decimal(10))
3278 self.assertEqual(c.next_minus(10), d)
3279 self.assertRaises(TypeError, c.next_minus, '10')
3280
3281 def test_next_plus(self):
3282 Decimal = self.decimal.Decimal
3283 Context = self.decimal.Context
3284
3285 c = Context()
3286 d = c.next_plus(Decimal(10))
3287 self.assertEqual(c.next_plus(10), d)
3288 self.assertRaises(TypeError, c.next_plus, '10')
3289
3290 def test_next_toward(self):
3291 Decimal = self.decimal.Decimal
3292 Context = self.decimal.Context
3293
3294 c = Context()
3295 d = c.next_toward(Decimal(1), Decimal(2))
3296 self.assertEqual(c.next_toward(1, 2), d)
3297 self.assertEqual(c.next_toward(Decimal(1), 2), d)
3298 self.assertEqual(c.next_toward(1, Decimal(2)), d)
3299 self.assertRaises(TypeError, c.next_toward, '1', 2)
3300 self.assertRaises(TypeError, c.next_toward, 1, '2')
3301
3302 def test_normalize(self):
3303 Decimal = self.decimal.Decimal
3304 Context = self.decimal.Context
3305
3306 c = Context()
3307 d = c.normalize(Decimal(10))
3308 self.assertEqual(c.normalize(10), d)
3309 self.assertRaises(TypeError, c.normalize, '10')
3310
3311 def test_number_class(self):
3312 Decimal = self.decimal.Decimal
3313 Context = self.decimal.Context
3314
3315 c = Context()
3316 self.assertEqual(c.number_class(123), c.number_class(Decimal(123)))
3317 self.assertEqual(c.number_class(0), c.number_class(Decimal(0)))
3318 self.assertEqual(c.number_class(-45), c.number_class(Decimal(-45)))
3319
3320 def test_plus(self):
3321 Decimal = self.decimal.Decimal
3322 Context = self.decimal.Context
3323
3324 c = Context()
3325 d = c.plus(Decimal(10))
3326 self.assertEqual(c.plus(10), d)
3327 self.assertRaises(TypeError, c.plus, '10')
3328
3329 def test_power(self):
3330 Decimal = self.decimal.Decimal
3331 Context = self.decimal.Context
3332
3333 c = Context()
3334 d = c.power(Decimal(1), Decimal(4))
3335 self.assertEqual(c.power(1, 4), d)
3336 self.assertEqual(c.power(Decimal(1), 4), d)
3337 self.assertEqual(c.power(1, Decimal(4)), d)
3338 self.assertEqual(c.power(Decimal(1), Decimal(4)), d)
3339 self.assertRaises(TypeError, c.power, '1', 4)
3340 self.assertRaises(TypeError, c.power, 1, '4')
3341 self.assertEqual(c.power(modulo=5, b=8, a=2), 1)
3342
3343 def test_quantize(self):
3344 Decimal = self.decimal.Decimal
3345 Context = self.decimal.Context
3346
3347 c = Context()
3348 d = c.quantize(Decimal(1), Decimal(2))
3349 self.assertEqual(c.quantize(1, 2), d)
3350 self.assertEqual(c.quantize(Decimal(1), 2), d)
3351 self.assertEqual(c.quantize(1, Decimal(2)), d)
3352 self.assertRaises(TypeError, c.quantize, '1', 2)
3353 self.assertRaises(TypeError, c.quantize, 1, '2')
3354
3355 def test_remainder(self):
3356 Decimal = self.decimal.Decimal
3357 Context = self.decimal.Context
3358
3359 c = Context()
3360 d = c.remainder(Decimal(1), Decimal(2))
3361 self.assertEqual(c.remainder(1, 2), d)
3362 self.assertEqual(c.remainder(Decimal(1), 2), d)
3363 self.assertEqual(c.remainder(1, Decimal(2)), d)
3364 self.assertRaises(TypeError, c.remainder, '1', 2)
3365 self.assertRaises(TypeError, c.remainder, 1, '2')
3366
3367 def test_remainder_near(self):
3368 Decimal = self.decimal.Decimal
3369 Context = self.decimal.Context
3370
3371 c = Context()
3372 d = c.remainder_near(Decimal(1), Decimal(2))
3373 self.assertEqual(c.remainder_near(1, 2), d)
3374 self.assertEqual(c.remainder_near(Decimal(1), 2), d)
3375 self.assertEqual(c.remainder_near(1, Decimal(2)), d)
3376 self.assertRaises(TypeError, c.remainder_near, '1', 2)
3377 self.assertRaises(TypeError, c.remainder_near, 1, '2')
3378
3379 def test_rotate(self):
3380 Decimal = self.decimal.Decimal
3381 Context = self.decimal.Context
3382
3383 c = Context()
3384 d = c.rotate(Decimal(1), Decimal(2))
3385 self.assertEqual(c.rotate(1, 2), d)
3386 self.assertEqual(c.rotate(Decimal(1), 2), d)
3387 self.assertEqual(c.rotate(1, Decimal(2)), d)
3388 self.assertRaises(TypeError, c.rotate, '1', 2)
3389 self.assertRaises(TypeError, c.rotate, 1, '2')
3390
3391 def test_sqrt(self):
3392 Decimal = self.decimal.Decimal
3393 Context = self.decimal.Context
3394
3395 c = Context()
3396 d = c.sqrt(Decimal(10))
3397 self.assertEqual(c.sqrt(10), d)
3398 self.assertRaises(TypeError, c.sqrt, '10')
3399
3400 def test_same_quantum(self):
3401 Decimal = self.decimal.Decimal
3402 Context = self.decimal.Context
3403
3404 c = Context()
3405 d = c.same_quantum(Decimal(1), Decimal(2))
3406 self.assertEqual(c.same_quantum(1, 2), d)
3407 self.assertEqual(c.same_quantum(Decimal(1), 2), d)
3408 self.assertEqual(c.same_quantum(1, Decimal(2)), d)
3409 self.assertRaises(TypeError, c.same_quantum, '1', 2)
3410 self.assertRaises(TypeError, c.same_quantum, 1, '2')
3411
3412 def test_scaleb(self):
3413 Decimal = self.decimal.Decimal
3414 Context = self.decimal.Context
3415
3416 c = Context()
3417 d = c.scaleb(Decimal(1), Decimal(2))
3418 self.assertEqual(c.scaleb(1, 2), d)
3419 self.assertEqual(c.scaleb(Decimal(1), 2), d)
3420 self.assertEqual(c.scaleb(1, Decimal(2)), d)
3421 self.assertRaises(TypeError, c.scaleb, '1', 2)
3422 self.assertRaises(TypeError, c.scaleb, 1, '2')
3423
3424 def test_shift(self):
3425 Decimal = self.decimal.Decimal
3426 Context = self.decimal.Context
3427
3428 c = Context()
3429 d = c.shift(Decimal(1), Decimal(2))
3430 self.assertEqual(c.shift(1, 2), d)
3431 self.assertEqual(c.shift(Decimal(1), 2), d)
3432 self.assertEqual(c.shift(1, Decimal(2)), d)
3433 self.assertRaises(TypeError, c.shift, '1', 2)
3434 self.assertRaises(TypeError, c.shift, 1, '2')
3435
3436 def test_subtract(self):
3437 Decimal = self.decimal.Decimal
3438 Context = self.decimal.Context
3439
3440 c = Context()
3441 d = c.subtract(Decimal(1), Decimal(2))
3442 self.assertEqual(c.subtract(1, 2), d)
3443 self.assertEqual(c.subtract(Decimal(1), 2), d)
3444 self.assertEqual(c.subtract(1, Decimal(2)), d)
3445 self.assertRaises(TypeError, c.subtract, '1', 2)
3446 self.assertRaises(TypeError, c.subtract, 1, '2')
3447
3448 def test_to_eng_string(self):
3449 Decimal = self.decimal.Decimal
3450 Context = self.decimal.Context
3451
3452 c = Context()
3453 d = c.to_eng_string(Decimal(10))
3454 self.assertEqual(c.to_eng_string(10), d)
3455 self.assertRaises(TypeError, c.to_eng_string, '10')
3456
3457 def test_to_sci_string(self):
3458 Decimal = self.decimal.Decimal
3459 Context = self.decimal.Context
3460
3461 c = Context()
3462 d = c.to_sci_string(Decimal(10))
3463 self.assertEqual(c.to_sci_string(10), d)
3464 self.assertRaises(TypeError, c.to_sci_string, '10')
3465
3466 def test_to_integral_exact(self):
3467 Decimal = self.decimal.Decimal
3468 Context = self.decimal.Context
3469
3470 c = Context()
3471 d = c.to_integral_exact(Decimal(10))
3472 self.assertEqual(c.to_integral_exact(10), d)
3473 self.assertRaises(TypeError, c.to_integral_exact, '10')
3474
3475 def test_to_integral_value(self):
3476 Decimal = self.decimal.Decimal
3477 Context = self.decimal.Context
3478
3479 c = Context()
3480 d = c.to_integral_value(Decimal(10))
3481 self.assertEqual(c.to_integral_value(10), d)
3482 self.assertRaises(TypeError, c.to_integral_value, '10')
3483 self.assertRaises(TypeError, c.to_integral_value, 10, 'x')
3484
3485class CContextAPItests(ContextAPItests):
3486 decimal = C
3487class PyContextAPItests(ContextAPItests):
3488 decimal = P
3489
3490class ContextWithStatement(unittest.TestCase):
3491 # Can't do these as docstrings until Python 2.6
3492 # as doctest can't handle __future__ statements
3493
3494 def test_localcontext(self):
3495 # Use a copy of the current context in the block
3496 getcontext = self.decimal.getcontext
3497 localcontext = self.decimal.localcontext
3498
3499 orig_ctx = getcontext()
3500 with localcontext() as enter_ctx:
3501 set_ctx = getcontext()
3502 final_ctx = getcontext()
3503 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
3504 self.assertIsNot(orig_ctx, set_ctx, 'did not copy the context')
3505 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
3506
3507 def test_localcontextarg(self):
3508 # Use a copy of the supplied context in the block
3509 Context = self.decimal.Context
3510 getcontext = self.decimal.getcontext
3511 localcontext = self.decimal.localcontext
3512
3513 localcontext = self.decimal.localcontext
3514 orig_ctx = getcontext()
3515 new_ctx = Context(prec=42)
3516 with localcontext(new_ctx) as enter_ctx:
3517 set_ctx = getcontext()
3518 final_ctx = getcontext()
3519 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
3520 self.assertEqual(set_ctx.prec, new_ctx.prec, 'did not set correct context')
3521 self.assertIsNot(new_ctx, set_ctx, 'did not copy the context')
3522 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
3523
3524 def test_nested_with_statements(self):
3525 # Use a copy of the supplied context in the block
3526 Decimal = self.decimal.Decimal
3527 Context = self.decimal.Context
3528 getcontext = self.decimal.getcontext
3529 localcontext = self.decimal.localcontext
3530 Clamped = self.decimal.Clamped
3531 Overflow = self.decimal.Overflow
3532
3533 orig_ctx = getcontext()
3534 orig_ctx.clear_flags()
3535 new_ctx = Context(Emax=384)
3536 with localcontext() as c1:
3537 self.assertEqual(c1.flags, orig_ctx.flags)
3538 self.assertEqual(c1.traps, orig_ctx.traps)
3539 c1.traps[Clamped] = True
3540 c1.Emin = -383
3541 self.assertNotEqual(orig_ctx.Emin, -383)
3542 self.assertRaises(Clamped, c1.create_decimal, '0e-999')
3543 self.assertTrue(c1.flags[Clamped])
3544 with localcontext(new_ctx) as c2:
3545 self.assertEqual(c2.flags, new_ctx.flags)
3546 self.assertEqual(c2.traps, new_ctx.traps)
3547 self.assertRaises(Overflow, c2.power, Decimal('3.4e200'), 2)
3548 self.assertFalse(c2.flags[Clamped])
3549 self.assertTrue(c2.flags[Overflow])
3550 del c2
3551 self.assertFalse(c1.flags[Overflow])
3552 del c1
3553 self.assertNotEqual(orig_ctx.Emin, -383)
3554 self.assertFalse(orig_ctx.flags[Clamped])
3555 self.assertFalse(orig_ctx.flags[Overflow])
3556 self.assertFalse(new_ctx.flags[Clamped])
3557 self.assertFalse(new_ctx.flags[Overflow])
3558
3559 def test_with_statements_gc1(self):
3560 localcontext = self.decimal.localcontext
3561
3562 with localcontext() as c1:
3563 del c1
3564 with localcontext() as c2:
3565 del c2
3566 with localcontext() as c3:
3567 del c3
3568 with localcontext() as c4:
3569 del c4
3570
3571 def test_with_statements_gc2(self):
3572 localcontext = self.decimal.localcontext
3573
3574 with localcontext() as c1:
3575 with localcontext(c1) as c2:
3576 del c1
3577 with localcontext(c2) as c3:
3578 del c2
3579 with localcontext(c3) as c4:
3580 del c3
3581 del c4
3582
3583 def test_with_statements_gc3(self):
3584 Context = self.decimal.Context
3585 localcontext = self.decimal.localcontext
3586 getcontext = self.decimal.getcontext
3587 setcontext = self.decimal.setcontext
3588
3589 with localcontext() as c1:
3590 del c1
3591 n1 = Context(prec=1)
3592 setcontext(n1)
3593 with localcontext(n1) as c2:
3594 del n1
3595 self.assertEqual(c2.prec, 1)
3596 del c2
3597 n2 = Context(prec=2)
3598 setcontext(n2)
3599 del n2
3600 self.assertEqual(getcontext().prec, 2)
3601 n3 = Context(prec=3)
3602 setcontext(n3)
3603 self.assertEqual(getcontext().prec, 3)
3604 with localcontext(n3) as c3:
3605 del n3
3606 self.assertEqual(c3.prec, 3)
3607 del c3
3608 n4 = Context(prec=4)
3609 setcontext(n4)
3610 del n4
3611 self.assertEqual(getcontext().prec, 4)
3612 with localcontext() as c4:
3613 self.assertEqual(c4.prec, 4)
3614 del c4
3615
3616class CContextWithStatement(ContextWithStatement):
3617 decimal = C
3618class PyContextWithStatement(ContextWithStatement):
3619 decimal = P
3620
3621class ContextFlags(unittest.TestCase):
3622
3623 def test_flags_irrelevant(self):
3624 # check that the result (numeric result + flags raised) of an
3625 # arithmetic operation doesn't depend on the current flags
3626 Decimal = self.decimal.Decimal
3627 Context = self.decimal.Context
3628 Inexact = self.decimal.Inexact
3629 Rounded = self.decimal.Rounded
3630 Underflow = self.decimal.Underflow
3631 Clamped = self.decimal.Clamped
3632 Subnormal = self.decimal.Subnormal
Stefan Krah1919b7e2012-03-21 18:25:23 +01003633
3634 def raise_error(context, flag):
3635 if self.decimal == C:
3636 context.flags[flag] = True
3637 if context.traps[flag]:
3638 raise flag
3639 else:
3640 context._raise_error(flag)
3641
3642 context = Context(prec=9, Emin = -425000000, Emax = 425000000,
3643 rounding=ROUND_HALF_EVEN, traps=[], flags=[])
3644
3645 # operations that raise various flags, in the form (function, arglist)
3646 operations = [
3647 (context._apply, [Decimal("100E-425000010")]),
3648 (context.sqrt, [Decimal(2)]),
3649 (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]),
3650 (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]),
3651 (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]),
3652 ]
3653
3654 # try various flags individually, then a whole lot at once
3655 flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal],
3656 [Inexact, Rounded, Underflow, Clamped, Subnormal]]
3657
3658 for fn, args in operations:
3659 # find answer and flags raised using a clean context
3660 context.clear_flags()
3661 ans = fn(*args)
3662 flags = [k for k, v in context.flags.items() if v]
3663
3664 for extra_flags in flagsets:
3665 # set flags, before calling operation
3666 context.clear_flags()
3667 for flag in extra_flags:
3668 raise_error(context, flag)
3669 new_ans = fn(*args)
3670
3671 # flags that we expect to be set after the operation
3672 expected_flags = list(flags)
3673 for flag in extra_flags:
3674 if flag not in expected_flags:
3675 expected_flags.append(flag)
3676 expected_flags.sort(key=id)
3677
3678 # flags we actually got
3679 new_flags = [k for k,v in context.flags.items() if v]
3680 new_flags.sort(key=id)
3681
3682 self.assertEqual(ans, new_ans,
3683 "operation produces different answers depending on flags set: " +
3684 "expected %s, got %s." % (ans, new_ans))
3685 self.assertEqual(new_flags, expected_flags,
3686 "operation raises different flags depending on flags set: " +
3687 "expected %s, got %s" % (expected_flags, new_flags))
3688
3689 def test_flag_comparisons(self):
3690 Context = self.decimal.Context
3691 Inexact = self.decimal.Inexact
3692 Rounded = self.decimal.Rounded
3693
3694 c = Context()
3695
3696 # Valid SignalDict
3697 self.assertNotEqual(c.flags, c.traps)
3698 self.assertNotEqual(c.traps, c.flags)
3699
3700 c.flags = c.traps
3701 self.assertEqual(c.flags, c.traps)
3702 self.assertEqual(c.traps, c.flags)
3703
3704 c.flags[Rounded] = True
3705 c.traps = c.flags
3706 self.assertEqual(c.flags, c.traps)
3707 self.assertEqual(c.traps, c.flags)
3708
3709 d = {}
3710 d.update(c.flags)
3711 self.assertEqual(d, c.flags)
3712 self.assertEqual(c.flags, d)
3713
3714 d[Inexact] = True
3715 self.assertNotEqual(d, c.flags)
3716 self.assertNotEqual(c.flags, d)
3717
3718 # Invalid SignalDict
3719 d = {Inexact:False}
3720 self.assertNotEqual(d, c.flags)
3721 self.assertNotEqual(c.flags, d)
3722
3723 d = ["xyz"]
3724 self.assertNotEqual(d, c.flags)
3725 self.assertNotEqual(c.flags, d)
3726
3727 @requires_IEEE_754
3728 def test_float_operation(self):
3729 Decimal = self.decimal.Decimal
3730 FloatOperation = self.decimal.FloatOperation
3731 localcontext = self.decimal.localcontext
3732
3733 with localcontext() as c:
3734 ##### trap is off by default
3735 self.assertFalse(c.traps[FloatOperation])
3736
3737 # implicit conversion sets the flag
3738 c.clear_flags()
3739 self.assertEqual(Decimal(7.5), 7.5)
3740 self.assertTrue(c.flags[FloatOperation])
3741
3742 c.clear_flags()
3743 self.assertEqual(c.create_decimal(7.5), 7.5)
3744 self.assertTrue(c.flags[FloatOperation])
3745
3746 # explicit conversion does not set the flag
3747 c.clear_flags()
3748 x = Decimal.from_float(7.5)
3749 self.assertFalse(c.flags[FloatOperation])
3750 # comparison sets the flag
3751 self.assertEqual(x, 7.5)
3752 self.assertTrue(c.flags[FloatOperation])
3753
3754 c.clear_flags()
3755 x = c.create_decimal_from_float(7.5)
3756 self.assertFalse(c.flags[FloatOperation])
3757 self.assertEqual(x, 7.5)
3758 self.assertTrue(c.flags[FloatOperation])
3759
3760 ##### set the trap
3761 c.traps[FloatOperation] = True
3762
3763 # implicit conversion raises
3764 c.clear_flags()
3765 self.assertRaises(FloatOperation, Decimal, 7.5)
3766 self.assertTrue(c.flags[FloatOperation])
3767
3768 c.clear_flags()
3769 self.assertRaises(FloatOperation, c.create_decimal, 7.5)
3770 self.assertTrue(c.flags[FloatOperation])
3771
3772 # explicit conversion is silent
3773 c.clear_flags()
3774 x = Decimal.from_float(7.5)
3775 self.assertFalse(c.flags[FloatOperation])
3776
3777 c.clear_flags()
3778 x = c.create_decimal_from_float(7.5)
3779 self.assertFalse(c.flags[FloatOperation])
3780
3781 def test_float_comparison(self):
3782 Decimal = self.decimal.Decimal
3783 Context = self.decimal.Context
3784 FloatOperation = self.decimal.FloatOperation
3785 localcontext = self.decimal.localcontext
3786
3787 def assert_attr(a, b, attr, context, signal=None):
3788 context.clear_flags()
3789 f = getattr(a, attr)
3790 if signal == FloatOperation:
3791 self.assertRaises(signal, f, b)
3792 else:
3793 self.assertIs(f(b), True)
3794 self.assertTrue(context.flags[FloatOperation])
3795
3796 small_d = Decimal('0.25')
3797 big_d = Decimal('3.0')
3798 small_f = 0.25
3799 big_f = 3.0
3800
3801 zero_d = Decimal('0.0')
3802 neg_zero_d = Decimal('-0.0')
3803 zero_f = 0.0
3804 neg_zero_f = -0.0
3805
3806 inf_d = Decimal('Infinity')
3807 neg_inf_d = Decimal('-Infinity')
3808 inf_f = float('inf')
3809 neg_inf_f = float('-inf')
3810
3811 def doit(c, signal=None):
3812 # Order
3813 for attr in '__lt__', '__le__':
3814 assert_attr(small_d, big_f, attr, c, signal)
3815
3816 for attr in '__gt__', '__ge__':
3817 assert_attr(big_d, small_f, attr, c, signal)
3818
3819 # Equality
3820 assert_attr(small_d, small_f, '__eq__', c, None)
3821
3822 assert_attr(neg_zero_d, neg_zero_f, '__eq__', c, None)
3823 assert_attr(neg_zero_d, zero_f, '__eq__', c, None)
3824
3825 assert_attr(zero_d, neg_zero_f, '__eq__', c, None)
3826 assert_attr(zero_d, zero_f, '__eq__', c, None)
3827
3828 assert_attr(neg_inf_d, neg_inf_f, '__eq__', c, None)
3829 assert_attr(inf_d, inf_f, '__eq__', c, None)
3830
3831 # Inequality
3832 assert_attr(small_d, big_f, '__ne__', c, None)
3833
3834 assert_attr(Decimal('0.1'), 0.1, '__ne__', c, None)
3835
3836 assert_attr(neg_inf_d, inf_f, '__ne__', c, None)
3837 assert_attr(inf_d, neg_inf_f, '__ne__', c, None)
3838
3839 assert_attr(Decimal('NaN'), float('nan'), '__ne__', c, None)
3840
3841 def test_containers(c, signal=None):
3842 c.clear_flags()
3843 s = set([100.0, Decimal('100.0')])
3844 self.assertEqual(len(s), 1)
3845 self.assertTrue(c.flags[FloatOperation])
3846
3847 c.clear_flags()
3848 if signal:
3849 self.assertRaises(signal, sorted, [1.0, Decimal('10.0')])
3850 else:
3851 s = sorted([10.0, Decimal('10.0')])
3852 self.assertTrue(c.flags[FloatOperation])
3853
3854 c.clear_flags()
3855 b = 10.0 in [Decimal('10.0'), 1.0]
3856 self.assertTrue(c.flags[FloatOperation])
3857
3858 c.clear_flags()
3859 b = 10.0 in {Decimal('10.0'):'a', 1.0:'b'}
3860 self.assertTrue(c.flags[FloatOperation])
3861
3862 nc = Context()
3863 with localcontext(nc) as c:
3864 self.assertFalse(c.traps[FloatOperation])
3865 doit(c, signal=None)
3866 test_containers(c, signal=None)
3867
3868 c.traps[FloatOperation] = True
3869 doit(c, signal=FloatOperation)
3870 test_containers(c, signal=FloatOperation)
3871
3872 def test_float_operation_default(self):
3873 Decimal = self.decimal.Decimal
3874 Context = self.decimal.Context
3875 Inexact = self.decimal.Inexact
3876 FloatOperation= self.decimal.FloatOperation
3877
3878 context = Context()
3879 self.assertFalse(context.flags[FloatOperation])
3880 self.assertFalse(context.traps[FloatOperation])
3881
3882 context.clear_traps()
3883 context.traps[Inexact] = True
3884 context.traps[FloatOperation] = True
3885 self.assertTrue(context.traps[FloatOperation])
3886 self.assertTrue(context.traps[Inexact])
3887
3888class CContextFlags(ContextFlags):
3889 decimal = C
3890class PyContextFlags(ContextFlags):
3891 decimal = P
3892
3893class SpecialContexts(unittest.TestCase):
3894 """Test the context templates."""
3895
3896 def test_context_templates(self):
3897 BasicContext = self.decimal.BasicContext
3898 ExtendedContext = self.decimal.ExtendedContext
3899 getcontext = self.decimal.getcontext
3900 setcontext = self.decimal.setcontext
3901 InvalidOperation = self.decimal.InvalidOperation
3902 DivisionByZero = self.decimal.DivisionByZero
3903 Overflow = self.decimal.Overflow
3904 Underflow = self.decimal.Underflow
3905 Clamped = self.decimal.Clamped
3906
3907 assert_signals(self, BasicContext, 'traps',
3908 [InvalidOperation, DivisionByZero, Overflow, Underflow, Clamped]
3909 )
3910
3911 savecontext = getcontext().copy()
3912 basic_context_prec = BasicContext.prec
3913 extended_context_prec = ExtendedContext.prec
3914
3915 ex = None
3916 try:
3917 BasicContext.prec = ExtendedContext.prec = 441
3918 for template in BasicContext, ExtendedContext:
3919 setcontext(template)
3920 c = getcontext()
3921 self.assertIsNot(c, template)
3922 self.assertEqual(c.prec, 441)
3923 except Exception as e:
3924 ex = e.__class__
3925 finally:
3926 BasicContext.prec = basic_context_prec
3927 ExtendedContext.prec = extended_context_prec
3928 setcontext(savecontext)
3929 if ex:
3930 raise ex
3931
3932 def test_default_context(self):
3933 DefaultContext = self.decimal.DefaultContext
3934 BasicContext = self.decimal.BasicContext
3935 ExtendedContext = self.decimal.ExtendedContext
3936 getcontext = self.decimal.getcontext
3937 setcontext = self.decimal.setcontext
3938 InvalidOperation = self.decimal.InvalidOperation
3939 DivisionByZero = self.decimal.DivisionByZero
3940 Overflow = self.decimal.Overflow
3941
3942 self.assertEqual(BasicContext.prec, 9)
3943 self.assertEqual(ExtendedContext.prec, 9)
3944
3945 assert_signals(self, DefaultContext, 'traps',
3946 [InvalidOperation, DivisionByZero, Overflow]
3947 )
3948
3949 savecontext = getcontext().copy()
3950 default_context_prec = DefaultContext.prec
3951
3952 ex = None
3953 try:
3954 c = getcontext()
3955 saveprec = c.prec
3956
3957 DefaultContext.prec = 961
3958 c = getcontext()
3959 self.assertEqual(c.prec, saveprec)
3960
3961 setcontext(DefaultContext)
3962 c = getcontext()
3963 self.assertIsNot(c, DefaultContext)
3964 self.assertEqual(c.prec, 961)
3965 except Exception as e:
3966 ex = e.__class__
3967 finally:
3968 DefaultContext.prec = default_context_prec
3969 setcontext(savecontext)
3970 if ex:
3971 raise ex
3972
3973class CSpecialContexts(SpecialContexts):
3974 decimal = C
3975class PySpecialContexts(SpecialContexts):
3976 decimal = P
3977
3978class ContextInputValidation(unittest.TestCase):
3979
3980 def test_invalid_context(self):
3981 Context = self.decimal.Context
3982 DefaultContext = self.decimal.DefaultContext
3983
3984 c = DefaultContext.copy()
3985
3986 # prec, Emax
3987 for attr in ['prec', 'Emax']:
3988 setattr(c, attr, 999999)
3989 self.assertEqual(getattr(c, attr), 999999)
3990 self.assertRaises(ValueError, setattr, c, attr, -1)
3991 self.assertRaises(TypeError, setattr, c, attr, 'xyz')
3992
3993 # Emin
3994 setattr(c, 'Emin', -999999)
3995 self.assertEqual(getattr(c, 'Emin'), -999999)
3996 self.assertRaises(ValueError, setattr, c, 'Emin', 1)
3997 self.assertRaises(TypeError, setattr, c, 'Emin', (1,2,3))
3998
Stefan Krah1919b7e2012-03-21 18:25:23 +01003999 self.assertRaises(TypeError, setattr, c, 'rounding', -1)
4000 self.assertRaises(TypeError, setattr, c, 'rounding', 9)
4001 self.assertRaises(TypeError, setattr, c, 'rounding', 1.0)
4002 self.assertRaises(TypeError, setattr, c, 'rounding', 'xyz')
4003
4004 # capitals, clamp
4005 for attr in ['capitals', 'clamp']:
4006 self.assertRaises(ValueError, setattr, c, attr, -1)
4007 self.assertRaises(ValueError, setattr, c, attr, 2)
4008 self.assertRaises(TypeError, setattr, c, attr, [1,2,3])
4009
4010 # Invalid attribute
4011 self.assertRaises(AttributeError, setattr, c, 'emax', 100)
4012
4013 # Invalid signal dict
4014 self.assertRaises(TypeError, setattr, c, 'flags', [])
4015 self.assertRaises(KeyError, setattr, c, 'flags', {})
4016 self.assertRaises(KeyError, setattr, c, 'traps',
4017 {'InvalidOperation':0})
4018
4019 # Attributes cannot be deleted
4020 for attr in ['prec', 'Emax', 'Emin', 'rounding', 'capitals', 'clamp',
4021 'flags', 'traps']:
4022 self.assertRaises(AttributeError, c.__delattr__, attr)
4023
4024 # Invalid attributes
4025 self.assertRaises(TypeError, getattr, c, 9)
4026 self.assertRaises(TypeError, setattr, c, 9)
4027
4028 # Invalid values in constructor
4029 self.assertRaises(TypeError, Context, rounding=999999)
4030 self.assertRaises(TypeError, Context, rounding='xyz')
4031 self.assertRaises(ValueError, Context, clamp=2)
4032 self.assertRaises(ValueError, Context, capitals=-1)
4033 self.assertRaises(KeyError, Context, flags=["P"])
4034 self.assertRaises(KeyError, Context, traps=["Q"])
4035
4036 # Type error in conversion
4037 self.assertRaises(TypeError, Context, flags=(0,1))
4038 self.assertRaises(TypeError, Context, traps=(1,0))
4039
4040class CContextInputValidation(ContextInputValidation):
4041 decimal = C
4042class PyContextInputValidation(ContextInputValidation):
4043 decimal = P
4044
4045class ContextSubclassing(unittest.TestCase):
4046
4047 def test_context_subclassing(self):
4048 decimal = self.decimal
4049 Decimal = decimal.Decimal
4050 Context = decimal.Context
Stefan Krah1919b7e2012-03-21 18:25:23 +01004051 Clamped = decimal.Clamped
4052 DivisionByZero = decimal.DivisionByZero
4053 Inexact = decimal.Inexact
4054 Overflow = decimal.Overflow
4055 Rounded = decimal.Rounded
4056 Subnormal = decimal.Subnormal
4057 Underflow = decimal.Underflow
4058 InvalidOperation = decimal.InvalidOperation
4059
4060 class MyContext(Context):
4061 def __init__(self, prec=None, rounding=None, Emin=None, Emax=None,
4062 capitals=None, clamp=None, flags=None,
4063 traps=None):
4064 Context.__init__(self)
4065 if prec is not None:
4066 self.prec = prec
4067 if rounding is not None:
4068 self.rounding = rounding
4069 if Emin is not None:
4070 self.Emin = Emin
4071 if Emax is not None:
4072 self.Emax = Emax
4073 if capitals is not None:
4074 self.capitals = capitals
4075 if clamp is not None:
4076 self.clamp = clamp
4077 if flags is not None:
4078 if isinstance(flags, list):
4079 flags = {v:(v in flags) for v in OrderedSignals[decimal] + flags}
4080 self.flags = flags
4081 if traps is not None:
4082 if isinstance(traps, list):
4083 traps = {v:(v in traps) for v in OrderedSignals[decimal] + traps}
4084 self.traps = traps
4085
4086 c = Context()
4087 d = MyContext()
4088 for attr in ('prec', 'rounding', 'Emin', 'Emax', 'capitals', 'clamp',
4089 'flags', 'traps'):
4090 self.assertEqual(getattr(c, attr), getattr(d, attr))
4091
4092 # prec
4093 self.assertRaises(ValueError, MyContext, **{'prec':-1})
4094 c = MyContext(prec=1)
4095 self.assertEqual(c.prec, 1)
4096 self.assertRaises(InvalidOperation, c.quantize, Decimal('9e2'), 0)
4097
4098 # rounding
4099 self.assertRaises(TypeError, MyContext, **{'rounding':'XYZ'})
4100 c = MyContext(rounding=ROUND_DOWN, prec=1)
4101 self.assertEqual(c.rounding, ROUND_DOWN)
4102 self.assertEqual(c.plus(Decimal('9.9')), 9)
4103
4104 # Emin
4105 self.assertRaises(ValueError, MyContext, **{'Emin':5})
4106 c = MyContext(Emin=-1, prec=1)
4107 self.assertEqual(c.Emin, -1)
4108 x = c.add(Decimal('1e-99'), Decimal('2.234e-2000'))
4109 self.assertEqual(x, Decimal('0.0'))
4110 for signal in (Inexact, Underflow, Subnormal, Rounded, Clamped):
4111 self.assertTrue(c.flags[signal])
4112
4113 # Emax
4114 self.assertRaises(ValueError, MyContext, **{'Emax':-1})
4115 c = MyContext(Emax=1, prec=1)
4116 self.assertEqual(c.Emax, 1)
4117 self.assertRaises(Overflow, c.add, Decimal('1e99'), Decimal('2.234e2000'))
4118 if self.decimal == C:
4119 for signal in (Inexact, Overflow, Rounded):
4120 self.assertTrue(c.flags[signal])
4121
4122 # capitals
4123 self.assertRaises(ValueError, MyContext, **{'capitals':-1})
4124 c = MyContext(capitals=0)
4125 self.assertEqual(c.capitals, 0)
4126 x = c.create_decimal('1E222')
4127 self.assertEqual(c.to_sci_string(x), '1e+222')
4128
4129 # clamp
4130 self.assertRaises(ValueError, MyContext, **{'clamp':2})
4131 c = MyContext(clamp=1, Emax=99)
4132 self.assertEqual(c.clamp, 1)
4133 x = c.plus(Decimal('1e99'))
4134 self.assertEqual(str(x), '1.000000000000000000000000000E+99')
4135
4136 # flags
4137 self.assertRaises(TypeError, MyContext, **{'flags':'XYZ'})
4138 c = MyContext(flags=[Rounded, DivisionByZero])
4139 for signal in (Rounded, DivisionByZero):
4140 self.assertTrue(c.flags[signal])
4141 c.clear_flags()
4142 for signal in OrderedSignals[decimal]:
4143 self.assertFalse(c.flags[signal])
4144
4145 # traps
4146 self.assertRaises(TypeError, MyContext, **{'traps':'XYZ'})
4147 c = MyContext(traps=[Rounded, DivisionByZero])
4148 for signal in (Rounded, DivisionByZero):
4149 self.assertTrue(c.traps[signal])
4150 c.clear_traps()
4151 for signal in OrderedSignals[decimal]:
4152 self.assertFalse(c.traps[signal])
4153
4154class CContextSubclassing(ContextSubclassing):
4155 decimal = C
4156class PyContextSubclassing(ContextSubclassing):
4157 decimal = P
4158
4159@skip_if_extra_functionality
4160class CheckAttributes(unittest.TestCase):
4161
4162 def test_module_attributes(self):
4163
4164 # Architecture dependent context limits
4165 self.assertEqual(C.MAX_PREC, P.MAX_PREC)
4166 self.assertEqual(C.MAX_EMAX, P.MAX_EMAX)
4167 self.assertEqual(C.MIN_EMIN, P.MIN_EMIN)
4168 self.assertEqual(C.MIN_ETINY, P.MIN_ETINY)
4169
4170 self.assertTrue(C.HAVE_THREADS is True or C.HAVE_THREADS is False)
4171 self.assertTrue(P.HAVE_THREADS is True or P.HAVE_THREADS is False)
4172
4173 self.assertEqual(C.__version__, P.__version__)
Stefan Krah45059eb2013-11-24 19:44:57 +01004174 self.assertEqual(C.__libmpdec_version__, P.__libmpdec_version__)
Stefan Krah1919b7e2012-03-21 18:25:23 +01004175
Stefan Krahb578f8a2014-09-10 17:58:15 +02004176 self.assertEqual(dir(C), dir(P))
Stefan Krah1919b7e2012-03-21 18:25:23 +01004177
4178 def test_context_attributes(self):
4179
4180 x = [s for s in dir(C.Context()) if '__' in s or not s.startswith('_')]
4181 y = [s for s in dir(P.Context()) if '__' in s or not s.startswith('_')]
4182 self.assertEqual(set(x) - set(y), set())
4183
4184 def test_decimal_attributes(self):
4185
4186 x = [s for s in dir(C.Decimal(9)) if '__' in s or not s.startswith('_')]
4187 y = [s for s in dir(C.Decimal(9)) if '__' in s or not s.startswith('_')]
4188 self.assertEqual(set(x) - set(y), set())
4189
4190class Coverage(unittest.TestCase):
4191
4192 def test_adjusted(self):
4193 Decimal = self.decimal.Decimal
4194
4195 self.assertEqual(Decimal('1234e9999').adjusted(), 10002)
4196 # XXX raise?
4197 self.assertEqual(Decimal('nan').adjusted(), 0)
4198 self.assertEqual(Decimal('inf').adjusted(), 0)
4199
4200 def test_canonical(self):
4201 Decimal = self.decimal.Decimal
4202 getcontext = self.decimal.getcontext
4203
4204 x = Decimal(9).canonical()
4205 self.assertEqual(x, 9)
4206
4207 c = getcontext()
4208 x = c.canonical(Decimal(9))
4209 self.assertEqual(x, 9)
4210
4211 def test_context_repr(self):
4212 c = self.decimal.DefaultContext.copy()
4213
4214 c.prec = 425000000
4215 c.Emax = 425000000
4216 c.Emin = -425000000
Stefan Krah59a4a932013-01-16 12:58:59 +01004217 c.rounding = ROUND_HALF_DOWN
Stefan Krah1919b7e2012-03-21 18:25:23 +01004218 c.capitals = 0
4219 c.clamp = 1
4220 for sig in OrderedSignals[self.decimal]:
4221 c.flags[sig] = False
4222 c.traps[sig] = False
4223
4224 s = c.__repr__()
4225 t = "Context(prec=425000000, rounding=ROUND_HALF_DOWN, " \
4226 "Emin=-425000000, Emax=425000000, capitals=0, clamp=1, " \
4227 "flags=[], traps=[])"
4228 self.assertEqual(s, t)
4229
4230 def test_implicit_context(self):
4231 Decimal = self.decimal.Decimal
4232 localcontext = self.decimal.localcontext
4233
4234 with localcontext() as c:
4235 c.prec = 1
4236 c.Emax = 1
4237 c.Emin = -1
4238
4239 # abs
4240 self.assertEqual(abs(Decimal("-10")), 10)
4241 # add
4242 self.assertEqual(Decimal("7") + 1, 8)
4243 # divide
4244 self.assertEqual(Decimal("10") / 5, 2)
4245 # divide_int
4246 self.assertEqual(Decimal("10") // 7, 1)
4247 # fma
4248 self.assertEqual(Decimal("1.2").fma(Decimal("0.01"), 1), 1)
4249 self.assertIs(Decimal("NaN").fma(7, 1).is_nan(), True)
4250 # three arg power
4251 self.assertEqual(pow(Decimal(10), 2, 7), 2)
4252 # exp
4253 self.assertEqual(Decimal("1.01").exp(), 3)
4254 # is_normal
4255 self.assertIs(Decimal("0.01").is_normal(), False)
4256 # is_subnormal
4257 self.assertIs(Decimal("0.01").is_subnormal(), True)
4258 # ln
4259 self.assertEqual(Decimal("20").ln(), 3)
4260 # log10
4261 self.assertEqual(Decimal("20").log10(), 1)
4262 # logb
4263 self.assertEqual(Decimal("580").logb(), 2)
4264 # logical_invert
4265 self.assertEqual(Decimal("10").logical_invert(), 1)
4266 # minus
4267 self.assertEqual(-Decimal("-10"), 10)
4268 # multiply
4269 self.assertEqual(Decimal("2") * 4, 8)
4270 # next_minus
4271 self.assertEqual(Decimal("10").next_minus(), 9)
4272 # next_plus
4273 self.assertEqual(Decimal("10").next_plus(), Decimal('2E+1'))
4274 # normalize
4275 self.assertEqual(Decimal("-10").normalize(), Decimal('-1E+1'))
4276 # number_class
4277 self.assertEqual(Decimal("10").number_class(), '+Normal')
4278 # plus
4279 self.assertEqual(+Decimal("-1"), -1)
4280 # remainder
4281 self.assertEqual(Decimal("10") % 7, 3)
4282 # subtract
4283 self.assertEqual(Decimal("10") - 7, 3)
4284 # to_integral_exact
4285 self.assertEqual(Decimal("1.12345").to_integral_exact(), 1)
4286
4287 # Boolean functions
4288 self.assertTrue(Decimal("1").is_canonical())
4289 self.assertTrue(Decimal("1").is_finite())
4290 self.assertTrue(Decimal("1").is_finite())
4291 self.assertTrue(Decimal("snan").is_snan())
4292 self.assertTrue(Decimal("-1").is_signed())
4293 self.assertTrue(Decimal("0").is_zero())
4294 self.assertTrue(Decimal("0").is_zero())
4295
4296 # Copy
4297 with localcontext() as c:
4298 c.prec = 10000
4299 x = 1228 ** 1523
4300 y = -Decimal(x)
4301
4302 z = y.copy_abs()
4303 self.assertEqual(z, x)
4304
4305 z = y.copy_negate()
4306 self.assertEqual(z, x)
4307
4308 z = y.copy_sign(Decimal(1))
4309 self.assertEqual(z, x)
4310
4311 def test_divmod(self):
4312 Decimal = self.decimal.Decimal
4313 localcontext = self.decimal.localcontext
4314 InvalidOperation = self.decimal.InvalidOperation
4315 DivisionByZero = self.decimal.DivisionByZero
4316
4317 with localcontext() as c:
4318 q, r = divmod(Decimal("10912837129"), 1001)
4319 self.assertEqual(q, Decimal('10901935'))
4320 self.assertEqual(r, Decimal('194'))
4321
4322 q, r = divmod(Decimal("NaN"), 7)
4323 self.assertTrue(q.is_nan() and r.is_nan())
4324
4325 c.traps[InvalidOperation] = False
4326 q, r = divmod(Decimal("NaN"), 7)
4327 self.assertTrue(q.is_nan() and r.is_nan())
4328
4329 c.traps[InvalidOperation] = False
4330 c.clear_flags()
4331 q, r = divmod(Decimal("inf"), Decimal("inf"))
4332 self.assertTrue(q.is_nan() and r.is_nan())
4333 self.assertTrue(c.flags[InvalidOperation])
4334
4335 c.clear_flags()
4336 q, r = divmod(Decimal("inf"), 101)
4337 self.assertTrue(q.is_infinite() and r.is_nan())
4338 self.assertTrue(c.flags[InvalidOperation])
4339
4340 c.clear_flags()
4341 q, r = divmod(Decimal(0), 0)
4342 self.assertTrue(q.is_nan() and r.is_nan())
4343 self.assertTrue(c.flags[InvalidOperation])
4344
4345 c.traps[DivisionByZero] = False
4346 c.clear_flags()
4347 q, r = divmod(Decimal(11), 0)
4348 self.assertTrue(q.is_infinite() and r.is_nan())
4349 self.assertTrue(c.flags[InvalidOperation] and
4350 c.flags[DivisionByZero])
4351
4352 def test_power(self):
4353 Decimal = self.decimal.Decimal
4354 localcontext = self.decimal.localcontext
4355 Overflow = self.decimal.Overflow
4356 Rounded = self.decimal.Rounded
4357
4358 with localcontext() as c:
4359 c.prec = 3
4360 c.clear_flags()
4361 self.assertEqual(Decimal("1.0") ** 100, Decimal('1.00'))
4362 self.assertTrue(c.flags[Rounded])
4363
4364 c.prec = 1
4365 c.Emax = 1
4366 c.Emin = -1
4367 c.clear_flags()
4368 c.traps[Overflow] = False
4369 self.assertEqual(Decimal(10000) ** Decimal("0.5"), Decimal('inf'))
4370 self.assertTrue(c.flags[Overflow])
4371
4372 def test_quantize(self):
4373 Decimal = self.decimal.Decimal
4374 localcontext = self.decimal.localcontext
4375 InvalidOperation = self.decimal.InvalidOperation
4376
4377 with localcontext() as c:
4378 c.prec = 1
4379 c.Emax = 1
4380 c.Emin = -1
4381 c.traps[InvalidOperation] = False
4382 x = Decimal(99).quantize(Decimal("1e1"))
4383 self.assertTrue(x.is_nan())
4384
4385 def test_radix(self):
4386 Decimal = self.decimal.Decimal
4387 getcontext = self.decimal.getcontext
4388
4389 c = getcontext()
4390 self.assertEqual(Decimal("1").radix(), 10)
4391 self.assertEqual(c.radix(), 10)
4392
4393 def test_rop(self):
4394 Decimal = self.decimal.Decimal
4395
4396 for attr in ('__radd__', '__rsub__', '__rmul__', '__rtruediv__',
4397 '__rdivmod__', '__rmod__', '__rfloordiv__', '__rpow__'):
4398 self.assertIs(getattr(Decimal("1"), attr)("xyz"), NotImplemented)
4399
4400 def test_round(self):
4401 # Python3 behavior: round() returns Decimal
4402 Decimal = self.decimal.Decimal
4403 getcontext = self.decimal.getcontext
4404
4405 c = getcontext()
4406 c.prec = 28
4407
4408 self.assertEqual(str(Decimal("9.99").__round__()), "10")
4409 self.assertEqual(str(Decimal("9.99e-5").__round__()), "0")
4410 self.assertEqual(str(Decimal("1.23456789").__round__(5)), "1.23457")
4411 self.assertEqual(str(Decimal("1.2345").__round__(10)), "1.2345000000")
4412 self.assertEqual(str(Decimal("1.2345").__round__(-10)), "0E+10")
4413
4414 self.assertRaises(TypeError, Decimal("1.23").__round__, "5")
4415 self.assertRaises(TypeError, Decimal("1.23").__round__, 5, 8)
4416
4417 def test_create_decimal(self):
4418 c = self.decimal.Context()
4419 self.assertRaises(ValueError, c.create_decimal, ["%"])
4420
4421 def test_int(self):
4422 Decimal = self.decimal.Decimal
4423 localcontext = self.decimal.localcontext
4424
4425 with localcontext() as c:
4426 c.prec = 9999
4427 x = Decimal(1221**1271) / 10**3923
4428 self.assertEqual(int(x), 1)
4429 self.assertEqual(x.to_integral(), 2)
4430
4431 def test_copy(self):
4432 Context = self.decimal.Context
4433
4434 c = Context()
4435 c.prec = 10000
4436 x = -(1172 ** 1712)
4437
4438 y = c.copy_abs(x)
4439 self.assertEqual(y, -x)
4440
4441 y = c.copy_negate(x)
4442 self.assertEqual(y, -x)
4443
4444 y = c.copy_sign(x, 1)
4445 self.assertEqual(y, -x)
4446
4447class CCoverage(Coverage):
4448 decimal = C
4449class PyCoverage(Coverage):
4450 decimal = P
4451
4452class PyFunctionality(unittest.TestCase):
4453 """Extra functionality in decimal.py"""
4454
Stefan Krah1919b7e2012-03-21 18:25:23 +01004455 def test_py_alternate_formatting(self):
4456 # triples giving a format, a Decimal, and the expected result
4457 Decimal = P.Decimal
4458 localcontext = P.localcontext
4459
4460 test_values = [
4461 # Issue 7094: Alternate formatting (specified by #)
4462 ('.0e', '1.0', '1e+0'),
4463 ('#.0e', '1.0', '1.e+0'),
4464 ('.0f', '1.0', '1'),
4465 ('#.0f', '1.0', '1.'),
4466 ('g', '1.1', '1.1'),
4467 ('#g', '1.1', '1.1'),
4468 ('.0g', '1', '1'),
4469 ('#.0g', '1', '1.'),
4470 ('.0%', '1.0', '100%'),
4471 ('#.0%', '1.0', '100.%'),
4472 ]
4473 for fmt, d, result in test_values:
4474 self.assertEqual(format(Decimal(d), fmt), result)
4475
4476class PyWhitebox(unittest.TestCase):
4477 """White box testing for decimal.py"""
4478
4479 def test_py_exact_power(self):
4480 # Rarely exercised lines in _power_exact.
4481 Decimal = P.Decimal
4482 localcontext = P.localcontext
4483
4484 with localcontext() as c:
4485 c.prec = 8
4486 x = Decimal(2**16) ** Decimal("-0.5")
4487 self.assertEqual(x, Decimal('0.00390625'))
4488
4489 x = Decimal(2**16) ** Decimal("-0.6")
4490 self.assertEqual(x, Decimal('0.0012885819'))
4491
4492 x = Decimal("256e7") ** Decimal("-0.5")
4493
4494 x = Decimal(152587890625) ** Decimal('-0.0625')
4495 self.assertEqual(x, Decimal("0.2"))
4496
4497 x = Decimal("152587890625e7") ** Decimal('-0.0625')
4498
4499 x = Decimal(5**2659) ** Decimal('-0.0625')
4500
4501 c.prec = 1
4502 x = Decimal("152587890625") ** Decimal('-0.5')
4503 c.prec = 201
4504 x = Decimal(2**578) ** Decimal("-0.5")
4505
4506 def test_py_immutability_operations(self):
Terry Jan Reedy0f847642013-03-11 18:34:00 -04004507 # Do operations and check that it didn't change internal objects.
Stefan Krah1919b7e2012-03-21 18:25:23 +01004508 Decimal = P.Decimal
4509 DefaultContext = P.DefaultContext
4510 setcontext = P.setcontext
4511
4512 c = DefaultContext.copy()
4513 c.traps = dict((s, 0) for s in OrderedSignals[P])
4514 setcontext(c)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004515
4516 d1 = Decimal('-25e55')
4517 b1 = Decimal('-25e55')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004518 d2 = Decimal('33e+33')
4519 b2 = Decimal('33e+33')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004520
4521 def checkSameDec(operation, useOther=False):
4522 if useOther:
4523 eval("d1." + operation + "(d2)")
4524 self.assertEqual(d1._sign, b1._sign)
4525 self.assertEqual(d1._int, b1._int)
4526 self.assertEqual(d1._exp, b1._exp)
4527 self.assertEqual(d2._sign, b2._sign)
4528 self.assertEqual(d2._int, b2._int)
4529 self.assertEqual(d2._exp, b2._exp)
4530 else:
4531 eval("d1." + operation + "()")
4532 self.assertEqual(d1._sign, b1._sign)
4533 self.assertEqual(d1._int, b1._int)
4534 self.assertEqual(d1._exp, b1._exp)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004535
4536 Decimal(d1)
4537 self.assertEqual(d1._sign, b1._sign)
4538 self.assertEqual(d1._int, b1._int)
4539 self.assertEqual(d1._exp, b1._exp)
4540
4541 checkSameDec("__abs__")
4542 checkSameDec("__add__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004543 checkSameDec("__divmod__", True)
Christian Heimes77c02eb2008-02-09 02:18:51 +00004544 checkSameDec("__eq__", True)
4545 checkSameDec("__ne__", True)
4546 checkSameDec("__le__", True)
4547 checkSameDec("__lt__", True)
4548 checkSameDec("__ge__", True)
4549 checkSameDec("__gt__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004550 checkSameDec("__float__")
4551 checkSameDec("__floordiv__", True)
4552 checkSameDec("__hash__")
4553 checkSameDec("__int__")
Christian Heimes969fe572008-01-25 11:23:10 +00004554 checkSameDec("__trunc__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004555 checkSameDec("__mod__", True)
4556 checkSameDec("__mul__", True)
4557 checkSameDec("__neg__")
Jack Diederich4dafcc42006-11-28 19:15:13 +00004558 checkSameDec("__bool__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004559 checkSameDec("__pos__")
4560 checkSameDec("__pow__", True)
4561 checkSameDec("__radd__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004562 checkSameDec("__rdivmod__", True)
4563 checkSameDec("__repr__")
4564 checkSameDec("__rfloordiv__", True)
4565 checkSameDec("__rmod__", True)
4566 checkSameDec("__rmul__", True)
4567 checkSameDec("__rpow__", True)
4568 checkSameDec("__rsub__", True)
4569 checkSameDec("__str__")
4570 checkSameDec("__sub__", True)
4571 checkSameDec("__truediv__", True)
4572 checkSameDec("adjusted")
4573 checkSameDec("as_tuple")
4574 checkSameDec("compare", True)
4575 checkSameDec("max", True)
4576 checkSameDec("min", True)
4577 checkSameDec("normalize")
4578 checkSameDec("quantize", True)
4579 checkSameDec("remainder_near", True)
4580 checkSameDec("same_quantum", True)
4581 checkSameDec("sqrt")
4582 checkSameDec("to_eng_string")
4583 checkSameDec("to_integral")
4584
Stefan Krah1919b7e2012-03-21 18:25:23 +01004585 def test_py_decimal_id(self):
4586 Decimal = P.Decimal
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004587
Stefan Krah1919b7e2012-03-21 18:25:23 +01004588 d = Decimal(45)
4589 e = Decimal(d)
4590 self.assertEqual(str(e), '45')
4591 self.assertNotEqual(id(d), id(e))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004592
Stefan Krah1919b7e2012-03-21 18:25:23 +01004593 def test_py_rescale(self):
4594 # Coverage
4595 Decimal = P.Decimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01004596 localcontext = P.localcontext
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004597
Stefan Krah1919b7e2012-03-21 18:25:23 +01004598 with localcontext() as c:
4599 x = Decimal("NaN")._rescale(3, ROUND_UP)
4600 self.assertTrue(x.is_nan())
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004601
Stefan Krah1919b7e2012-03-21 18:25:23 +01004602 def test_py__round(self):
4603 # Coverage
4604 Decimal = P.Decimal
Christian Heimes0348fb62008-03-26 12:55:56 +00004605
Stefan Krah1919b7e2012-03-21 18:25:23 +01004606 self.assertRaises(ValueError, Decimal("3.1234")._round, 0, ROUND_UP)
Mark Dickinsona2d1fe02009-10-29 12:23:02 +00004607
Stefan Krah1919b7e2012-03-21 18:25:23 +01004608class CFunctionality(unittest.TestCase):
4609 """Extra functionality in _decimal"""
Mark Dickinsona2d1fe02009-10-29 12:23:02 +00004610
Stefan Krah1919b7e2012-03-21 18:25:23 +01004611 @requires_extra_functionality
4612 def test_c_ieee_context(self):
4613 # issue 8786: Add support for IEEE 754 contexts to decimal module.
4614 IEEEContext = C.IEEEContext
4615 DECIMAL32 = C.DECIMAL32
4616 DECIMAL64 = C.DECIMAL64
4617 DECIMAL128 = C.DECIMAL128
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004618
Stefan Krah1919b7e2012-03-21 18:25:23 +01004619 def assert_rest(self, context):
4620 self.assertEqual(context.clamp, 1)
4621 assert_signals(self, context, 'traps', [])
4622 assert_signals(self, context, 'flags', [])
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004623
Stefan Krah1919b7e2012-03-21 18:25:23 +01004624 c = IEEEContext(DECIMAL32)
4625 self.assertEqual(c.prec, 7)
4626 self.assertEqual(c.Emax, 96)
4627 self.assertEqual(c.Emin, -95)
4628 assert_rest(self, c)
Raymond Hettinger82417ca2009-02-03 03:54:28 +00004629
Stefan Krah1919b7e2012-03-21 18:25:23 +01004630 c = IEEEContext(DECIMAL64)
4631 self.assertEqual(c.prec, 16)
4632 self.assertEqual(c.Emax, 384)
4633 self.assertEqual(c.Emin, -383)
4634 assert_rest(self, c)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004635
Stefan Krah1919b7e2012-03-21 18:25:23 +01004636 c = IEEEContext(DECIMAL128)
4637 self.assertEqual(c.prec, 34)
4638 self.assertEqual(c.Emax, 6144)
4639 self.assertEqual(c.Emin, -6143)
4640 assert_rest(self, c)
Raymond Hettinger5548be22004-07-05 18:49:38 +00004641
Stefan Krah1919b7e2012-03-21 18:25:23 +01004642 # Invalid values
4643 self.assertRaises(OverflowError, IEEEContext, 2**63)
4644 self.assertRaises(ValueError, IEEEContext, -1)
4645 self.assertRaises(ValueError, IEEEContext, 1024)
Mark Dickinson825fce32009-09-07 18:08:12 +00004646
Stefan Krah1919b7e2012-03-21 18:25:23 +01004647 @requires_extra_functionality
4648 def test_c_context(self):
4649 Context = C.Context
Christian Heimes969fe572008-01-25 11:23:10 +00004650
Stefan Krah1919b7e2012-03-21 18:25:23 +01004651 c = Context(flags=C.DecClamped, traps=C.DecRounded)
4652 self.assertEqual(c._flags, C.DecClamped)
4653 self.assertEqual(c._traps, C.DecRounded)
Raymond Hettinger771ed762009-01-03 19:20:32 +00004654
Stefan Krah1919b7e2012-03-21 18:25:23 +01004655 @requires_extra_functionality
4656 def test_constants(self):
4657 # Condition flags
4658 cond = (
4659 C.DecClamped, C.DecConversionSyntax, C.DecDivisionByZero,
4660 C.DecDivisionImpossible, C.DecDivisionUndefined,
4661 C.DecFpuError, C.DecInexact, C.DecInvalidContext,
4662 C.DecInvalidOperation, C.DecMallocError,
4663 C.DecFloatOperation, C.DecOverflow, C.DecRounded,
4664 C.DecSubnormal, C.DecUnderflow
Raymond Hettinger771ed762009-01-03 19:20:32 +00004665 )
Stefan Krah1919b7e2012-03-21 18:25:23 +01004666
4667 # IEEEContext
4668 self.assertEqual(C.DECIMAL32, 32)
4669 self.assertEqual(C.DECIMAL64, 64)
4670 self.assertEqual(C.DECIMAL128, 128)
4671 self.assertEqual(C.IEEE_CONTEXT_MAX_BITS, 512)
4672
Stefan Krah1919b7e2012-03-21 18:25:23 +01004673 # Conditions
4674 for i, v in enumerate(cond):
4675 self.assertEqual(v, 1<<i)
4676
4677 self.assertEqual(C.DecIEEEInvalidOperation,
4678 C.DecConversionSyntax|
4679 C.DecDivisionImpossible|
4680 C.DecDivisionUndefined|
4681 C.DecFpuError|
4682 C.DecInvalidContext|
4683 C.DecInvalidOperation|
4684 C.DecMallocError)
4685
4686 self.assertEqual(C.DecErrors,
4687 C.DecIEEEInvalidOperation|
4688 C.DecDivisionByZero)
4689
4690 self.assertEqual(C.DecTraps,
4691 C.DecErrors|C.DecOverflow|C.DecUnderflow)
4692
4693class CWhitebox(unittest.TestCase):
4694 """Whitebox testing for _decimal"""
4695
4696 def test_bignum(self):
4697 # Not exactly whitebox, but too slow with pydecimal.
4698
4699 Decimal = C.Decimal
4700 localcontext = C.localcontext
4701
4702 b1 = 10**35
4703 b2 = 10**36
4704 with localcontext() as c:
4705 c.prec = 1000000
4706 for i in range(5):
4707 a = random.randrange(b1, b2)
4708 b = random.randrange(1000, 1200)
4709 x = a ** b
4710 y = Decimal(a) ** Decimal(b)
4711 self.assertEqual(x, y)
4712
4713 def test_invalid_construction(self):
4714 self.assertRaises(TypeError, C.Decimal, 9, "xyz")
4715
4716 def test_c_input_restriction(self):
4717 # Too large for _decimal to be converted exactly
4718 Decimal = C.Decimal
4719 InvalidOperation = C.InvalidOperation
4720 Context = C.Context
4721 localcontext = C.localcontext
4722
4723 with localcontext(Context()):
4724 self.assertRaises(InvalidOperation, Decimal,
4725 "1e9999999999999999999")
4726
4727 def test_c_context_repr(self):
4728 # This test is _decimal-only because flags are not printed
4729 # in the same order.
4730 DefaultContext = C.DefaultContext
4731 FloatOperation = C.FloatOperation
Stefan Krah1919b7e2012-03-21 18:25:23 +01004732
4733 c = DefaultContext.copy()
4734
4735 c.prec = 425000000
4736 c.Emax = 425000000
4737 c.Emin = -425000000
4738 c.rounding = ROUND_HALF_DOWN
4739 c.capitals = 0
4740 c.clamp = 1
4741 for sig in OrderedSignals[C]:
4742 c.flags[sig] = True
4743 c.traps[sig] = True
4744 c.flags[FloatOperation] = True
4745 c.traps[FloatOperation] = True
4746
4747 s = c.__repr__()
4748 t = "Context(prec=425000000, rounding=ROUND_HALF_DOWN, " \
4749 "Emin=-425000000, Emax=425000000, capitals=0, clamp=1, " \
4750 "flags=[Clamped, InvalidOperation, DivisionByZero, Inexact, " \
4751 "FloatOperation, Overflow, Rounded, Subnormal, Underflow], " \
4752 "traps=[Clamped, InvalidOperation, DivisionByZero, Inexact, " \
4753 "FloatOperation, Overflow, Rounded, Subnormal, Underflow])"
4754 self.assertEqual(s, t)
4755
4756 def test_c_context_errors(self):
4757 Context = C.Context
4758 InvalidOperation = C.InvalidOperation
4759 Overflow = C.Overflow
4760 FloatOperation = C.FloatOperation
4761 localcontext = C.localcontext
4762 getcontext = C.getcontext
4763 setcontext = C.setcontext
4764 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
4765
4766 c = Context()
4767
4768 # SignalDict: input validation
4769 self.assertRaises(KeyError, c.flags.__setitem__, 801, 0)
4770 self.assertRaises(KeyError, c.traps.__setitem__, 801, 0)
4771 self.assertRaises(ValueError, c.flags.__delitem__, Overflow)
4772 self.assertRaises(ValueError, c.traps.__delitem__, InvalidOperation)
4773 self.assertRaises(TypeError, setattr, c, 'flags', ['x'])
4774 self.assertRaises(TypeError, setattr, c,'traps', ['y'])
4775 self.assertRaises(KeyError, setattr, c, 'flags', {0:1})
4776 self.assertRaises(KeyError, setattr, c, 'traps', {0:1})
4777
4778 # Test assignment from a signal dict with the correct length but
4779 # one invalid key.
4780 d = c.flags.copy()
4781 del d[FloatOperation]
4782 d["XYZ"] = 91283719
4783 self.assertRaises(KeyError, setattr, c, 'flags', d)
4784 self.assertRaises(KeyError, setattr, c, 'traps', d)
4785
4786 # Input corner cases
4787 int_max = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
4788 gt_max_emax = 10**18 if HAVE_CONFIG_64 else 10**9
4789
4790 # prec, Emax, Emin
4791 for attr in ['prec', 'Emax']:
4792 self.assertRaises(ValueError, setattr, c, attr, gt_max_emax)
4793 self.assertRaises(ValueError, setattr, c, 'Emin', -gt_max_emax)
4794
4795 # prec, Emax, Emin in context constructor
4796 self.assertRaises(ValueError, Context, prec=gt_max_emax)
4797 self.assertRaises(ValueError, Context, Emax=gt_max_emax)
4798 self.assertRaises(ValueError, Context, Emin=-gt_max_emax)
4799
4800 # Overflow in conversion
4801 self.assertRaises(OverflowError, Context, prec=int_max+1)
4802 self.assertRaises(OverflowError, Context, Emax=int_max+1)
4803 self.assertRaises(OverflowError, Context, Emin=-int_max-2)
Stefan Krah1919b7e2012-03-21 18:25:23 +01004804 self.assertRaises(OverflowError, Context, clamp=int_max+1)
4805 self.assertRaises(OverflowError, Context, capitals=int_max+1)
4806
4807 # OverflowError, general ValueError
4808 for attr in ('prec', 'Emin', 'Emax', 'capitals', 'clamp'):
4809 self.assertRaises(OverflowError, setattr, c, attr, int_max+1)
4810 self.assertRaises(OverflowError, setattr, c, attr, -int_max-2)
4811 if sys.platform != 'win32':
4812 self.assertRaises(ValueError, setattr, c, attr, int_max)
4813 self.assertRaises(ValueError, setattr, c, attr, -int_max-1)
4814
Stefan Krah1919b7e2012-03-21 18:25:23 +01004815 # OverflowError: _unsafe_setprec, _unsafe_setemin, _unsafe_setemax
4816 if C.MAX_PREC == 425000000:
4817 self.assertRaises(OverflowError, getattr(c, '_unsafe_setprec'),
4818 int_max+1)
4819 self.assertRaises(OverflowError, getattr(c, '_unsafe_setemax'),
4820 int_max+1)
4821 self.assertRaises(OverflowError, getattr(c, '_unsafe_setemin'),
4822 -int_max-2)
4823
4824 # ValueError: _unsafe_setprec, _unsafe_setemin, _unsafe_setemax
4825 if C.MAX_PREC == 425000000:
4826 self.assertRaises(ValueError, getattr(c, '_unsafe_setprec'), 0)
4827 self.assertRaises(ValueError, getattr(c, '_unsafe_setprec'),
4828 1070000001)
4829 self.assertRaises(ValueError, getattr(c, '_unsafe_setemax'), -1)
4830 self.assertRaises(ValueError, getattr(c, '_unsafe_setemax'),
4831 1070000001)
4832 self.assertRaises(ValueError, getattr(c, '_unsafe_setemin'),
4833 -1070000001)
4834 self.assertRaises(ValueError, getattr(c, '_unsafe_setemin'), 1)
4835
4836 # capitals, clamp
4837 for attr in ['capitals', 'clamp']:
4838 self.assertRaises(ValueError, setattr, c, attr, -1)
4839 self.assertRaises(ValueError, setattr, c, attr, 2)
4840 self.assertRaises(TypeError, setattr, c, attr, [1,2,3])
4841 if HAVE_CONFIG_64:
4842 self.assertRaises(ValueError, setattr, c, attr, 2**32)
4843 self.assertRaises(ValueError, setattr, c, attr, 2**32+1)
4844
4845 # Invalid local context
4846 self.assertRaises(TypeError, exec, 'with localcontext("xyz"): pass',
4847 locals())
Stefan Krah040e3112012-12-15 22:33:33 +01004848 self.assertRaises(TypeError, exec,
4849 'with localcontext(context=getcontext()): pass',
4850 locals())
Stefan Krah1919b7e2012-03-21 18:25:23 +01004851
4852 # setcontext
4853 saved_context = getcontext()
4854 self.assertRaises(TypeError, setcontext, "xyz")
4855 setcontext(saved_context)
4856
Stefan Krah59a4a932013-01-16 12:58:59 +01004857 def test_rounding_strings_interned(self):
4858
4859 self.assertIs(C.ROUND_UP, P.ROUND_UP)
4860 self.assertIs(C.ROUND_DOWN, P.ROUND_DOWN)
4861 self.assertIs(C.ROUND_CEILING, P.ROUND_CEILING)
4862 self.assertIs(C.ROUND_FLOOR, P.ROUND_FLOOR)
4863 self.assertIs(C.ROUND_HALF_UP, P.ROUND_HALF_UP)
4864 self.assertIs(C.ROUND_HALF_DOWN, P.ROUND_HALF_DOWN)
4865 self.assertIs(C.ROUND_HALF_EVEN, P.ROUND_HALF_EVEN)
4866 self.assertIs(C.ROUND_05UP, P.ROUND_05UP)
4867
Stefan Krah1919b7e2012-03-21 18:25:23 +01004868 @requires_extra_functionality
4869 def test_c_context_errors_extra(self):
4870 Context = C.Context
4871 InvalidOperation = C.InvalidOperation
4872 Overflow = C.Overflow
4873 localcontext = C.localcontext
4874 getcontext = C.getcontext
4875 setcontext = C.setcontext
4876 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
4877
4878 c = Context()
4879
4880 # Input corner cases
4881 int_max = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
4882
4883 # OverflowError, general ValueError
4884 self.assertRaises(OverflowError, setattr, c, '_allcr', int_max+1)
4885 self.assertRaises(OverflowError, setattr, c, '_allcr', -int_max-2)
4886 if sys.platform != 'win32':
4887 self.assertRaises(ValueError, setattr, c, '_allcr', int_max)
4888 self.assertRaises(ValueError, setattr, c, '_allcr', -int_max-1)
4889
4890 # OverflowError, general TypeError
4891 for attr in ('_flags', '_traps'):
4892 self.assertRaises(OverflowError, setattr, c, attr, int_max+1)
4893 self.assertRaises(OverflowError, setattr, c, attr, -int_max-2)
4894 if sys.platform != 'win32':
4895 self.assertRaises(TypeError, setattr, c, attr, int_max)
4896 self.assertRaises(TypeError, setattr, c, attr, -int_max-1)
4897
4898 # _allcr
4899 self.assertRaises(ValueError, setattr, c, '_allcr', -1)
4900 self.assertRaises(ValueError, setattr, c, '_allcr', 2)
4901 self.assertRaises(TypeError, setattr, c, '_allcr', [1,2,3])
4902 if HAVE_CONFIG_64:
4903 self.assertRaises(ValueError, setattr, c, '_allcr', 2**32)
4904 self.assertRaises(ValueError, setattr, c, '_allcr', 2**32+1)
4905
4906 # _flags, _traps
4907 for attr in ['_flags', '_traps']:
4908 self.assertRaises(TypeError, setattr, c, attr, 999999)
4909 self.assertRaises(TypeError, setattr, c, attr, 'x')
4910
4911 def test_c_valid_context(self):
4912 # These tests are for code coverage in _decimal.
4913 DefaultContext = C.DefaultContext
Stefan Krah1919b7e2012-03-21 18:25:23 +01004914 Clamped = C.Clamped
4915 Underflow = C.Underflow
4916 Inexact = C.Inexact
4917 Rounded = C.Rounded
4918 Subnormal = C.Subnormal
4919
4920 c = DefaultContext.copy()
4921
4922 # Exercise all getters and setters
4923 c.prec = 34
4924 c.rounding = ROUND_HALF_UP
4925 c.Emax = 3000
4926 c.Emin = -3000
4927 c.capitals = 1
4928 c.clamp = 0
4929
4930 self.assertEqual(c.prec, 34)
4931 self.assertEqual(c.rounding, ROUND_HALF_UP)
4932 self.assertEqual(c.Emin, -3000)
4933 self.assertEqual(c.Emax, 3000)
4934 self.assertEqual(c.capitals, 1)
4935 self.assertEqual(c.clamp, 0)
4936
4937 self.assertEqual(c.Etiny(), -3033)
4938 self.assertEqual(c.Etop(), 2967)
4939
4940 # Exercise all unsafe setters
4941 if C.MAX_PREC == 425000000:
4942 c._unsafe_setprec(999999999)
4943 c._unsafe_setemax(999999999)
4944 c._unsafe_setemin(-999999999)
4945 self.assertEqual(c.prec, 999999999)
4946 self.assertEqual(c.Emax, 999999999)
4947 self.assertEqual(c.Emin, -999999999)
4948
4949 @requires_extra_functionality
4950 def test_c_valid_context_extra(self):
4951 DefaultContext = C.DefaultContext
4952
4953 c = DefaultContext.copy()
4954 self.assertEqual(c._allcr, 1)
4955 c._allcr = 0
4956 self.assertEqual(c._allcr, 0)
4957
4958 def test_c_round(self):
4959 # Restricted input.
4960 Decimal = C.Decimal
4961 InvalidOperation = C.InvalidOperation
4962 localcontext = C.localcontext
4963 MAX_EMAX = C.MAX_EMAX
4964 MIN_ETINY = C.MIN_ETINY
4965 int_max = 2**63-1 if C.MAX_PREC > 425000000 else 2**31-1
4966
4967 with localcontext() as c:
4968 c.traps[InvalidOperation] = True
4969 self.assertRaises(InvalidOperation, Decimal("1.23").__round__,
4970 -int_max-1)
4971 self.assertRaises(InvalidOperation, Decimal("1.23").__round__,
4972 int_max)
4973 self.assertRaises(InvalidOperation, Decimal("1").__round__,
4974 int(MAX_EMAX+1))
4975 self.assertRaises(C.InvalidOperation, Decimal("1").__round__,
4976 -int(MIN_ETINY-1))
4977 self.assertRaises(OverflowError, Decimal("1.23").__round__,
4978 -int_max-2)
4979 self.assertRaises(OverflowError, Decimal("1.23").__round__,
4980 int_max+1)
4981
4982 def test_c_format(self):
4983 # Restricted input
4984 Decimal = C.Decimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01004985 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
4986
4987 self.assertRaises(TypeError, Decimal(1).__format__, "=10.10", [], 9)
4988 self.assertRaises(TypeError, Decimal(1).__format__, "=10.10", 9)
4989 self.assertRaises(TypeError, Decimal(1).__format__, [])
4990
Stefan Kraheb8c4512013-01-24 15:22:33 +01004991 self.assertRaises(ValueError, Decimal(1).__format__, "<>=10.10")
4992 maxsize = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
4993 self.assertRaises(ValueError, Decimal("1.23456789").__format__,
4994 "=%d.1" % maxsize)
Stefan Krah1919b7e2012-03-21 18:25:23 +01004995
4996 def test_c_integral(self):
4997 Decimal = C.Decimal
4998 Inexact = C.Inexact
Stefan Krah1919b7e2012-03-21 18:25:23 +01004999 localcontext = C.localcontext
5000
5001 x = Decimal(10)
5002 self.assertEqual(x.to_integral(), 10)
5003 self.assertRaises(TypeError, x.to_integral, '10')
5004 self.assertRaises(TypeError, x.to_integral, 10, 'x')
5005 self.assertRaises(TypeError, x.to_integral, 10)
5006
5007 self.assertEqual(x.to_integral_value(), 10)
5008 self.assertRaises(TypeError, x.to_integral_value, '10')
5009 self.assertRaises(TypeError, x.to_integral_value, 10, 'x')
5010 self.assertRaises(TypeError, x.to_integral_value, 10)
5011
5012 self.assertEqual(x.to_integral_exact(), 10)
5013 self.assertRaises(TypeError, x.to_integral_exact, '10')
5014 self.assertRaises(TypeError, x.to_integral_exact, 10, 'x')
5015 self.assertRaises(TypeError, x.to_integral_exact, 10)
5016
5017 with localcontext() as c:
5018 x = Decimal("99999999999999999999999999.9").to_integral_value(ROUND_UP)
5019 self.assertEqual(x, Decimal('100000000000000000000000000'))
5020
5021 x = Decimal("99999999999999999999999999.9").to_integral_exact(ROUND_UP)
5022 self.assertEqual(x, Decimal('100000000000000000000000000'))
5023
5024 c.traps[Inexact] = True
5025 self.assertRaises(Inexact, Decimal("999.9").to_integral_exact, ROUND_UP)
5026
5027 def test_c_funcs(self):
5028 # Invalid arguments
5029 Decimal = C.Decimal
5030 InvalidOperation = C.InvalidOperation
5031 DivisionByZero = C.DivisionByZero
Stefan Krah1919b7e2012-03-21 18:25:23 +01005032 getcontext = C.getcontext
5033 localcontext = C.localcontext
5034
5035 self.assertEqual(Decimal('9.99e10').to_eng_string(), '99.9E+9')
5036
5037 self.assertRaises(TypeError, pow, Decimal(1), 2, "3")
5038 self.assertRaises(TypeError, Decimal(9).number_class, "x", "y")
5039 self.assertRaises(TypeError, Decimal(9).same_quantum, 3, "x", "y")
5040
Raymond Hettinger771ed762009-01-03 19:20:32 +00005041 self.assertRaises(
Stefan Krah1919b7e2012-03-21 18:25:23 +01005042 TypeError,
5043 Decimal("1.23456789").quantize, Decimal('1e-100000'), []
Raymond Hettinger771ed762009-01-03 19:20:32 +00005044 )
Stefan Krah1919b7e2012-03-21 18:25:23 +01005045 self.assertRaises(
5046 TypeError,
5047 Decimal("1.23456789").quantize, Decimal('1e-100000'), getcontext()
5048 )
5049 self.assertRaises(
5050 TypeError,
5051 Decimal("1.23456789").quantize, Decimal('1e-100000'), 10
5052 )
5053 self.assertRaises(
5054 TypeError,
5055 Decimal("1.23456789").quantize, Decimal('1e-100000'), ROUND_UP, 1000
5056 )
Raymond Hettinger771ed762009-01-03 19:20:32 +00005057
Stefan Krah1919b7e2012-03-21 18:25:23 +01005058 with localcontext() as c:
5059 c.clear_traps()
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00005060
Stefan Krah1919b7e2012-03-21 18:25:23 +01005061 # Invalid arguments
5062 self.assertRaises(TypeError, c.copy_sign, Decimal(1), "x", "y")
5063 self.assertRaises(TypeError, c.canonical, 200)
5064 self.assertRaises(TypeError, c.is_canonical, 200)
5065 self.assertRaises(TypeError, c.divmod, 9, 8, "x", "y")
5066 self.assertRaises(TypeError, c.same_quantum, 9, 3, "x", "y")
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00005067
Stefan Krah1919b7e2012-03-21 18:25:23 +01005068 self.assertEqual(str(c.canonical(Decimal(200))), '200')
5069 self.assertEqual(c.radix(), 10)
Raymond Hettinger0aeac102004-07-05 22:53:03 +00005070
Stefan Krah1919b7e2012-03-21 18:25:23 +01005071 c.traps[DivisionByZero] = True
5072 self.assertRaises(DivisionByZero, Decimal(9).__divmod__, 0)
5073 self.assertRaises(DivisionByZero, c.divmod, 9, 0)
5074 self.assertTrue(c.flags[InvalidOperation])
Raymond Hettinger955d2b22004-08-08 20:17:45 +00005075
Stefan Krah1919b7e2012-03-21 18:25:23 +01005076 c.clear_flags()
5077 c.traps[InvalidOperation] = True
5078 self.assertRaises(InvalidOperation, Decimal(9).__divmod__, 0)
5079 self.assertRaises(InvalidOperation, c.divmod, 9, 0)
5080 self.assertTrue(c.flags[DivisionByZero])
Mark Dickinsonb1d8e322010-05-22 18:35:36 +00005081
Stefan Krah1919b7e2012-03-21 18:25:23 +01005082 c.traps[InvalidOperation] = True
5083 c.prec = 2
5084 self.assertRaises(InvalidOperation, pow, Decimal(1000), 1, 501)
Mark Dickinson84230a12010-02-18 14:49:50 +00005085
Stefan Krah040e3112012-12-15 22:33:33 +01005086 def test_va_args_exceptions(self):
5087 Decimal = C.Decimal
5088 Context = C.Context
5089
5090 x = Decimal("10001111111")
5091
5092 for attr in ['exp', 'is_normal', 'is_subnormal', 'ln', 'log10',
5093 'logb', 'logical_invert', 'next_minus', 'next_plus',
5094 'normalize', 'number_class', 'sqrt', 'to_eng_string']:
5095 func = getattr(x, attr)
5096 self.assertRaises(TypeError, func, context="x")
5097 self.assertRaises(TypeError, func, "x", context=None)
5098
5099 for attr in ['compare', 'compare_signal', 'logical_and',
5100 'logical_or', 'max', 'max_mag', 'min', 'min_mag',
5101 'remainder_near', 'rotate', 'scaleb', 'shift']:
5102 func = getattr(x, attr)
5103 self.assertRaises(TypeError, func, context="x")
5104 self.assertRaises(TypeError, func, "x", context=None)
5105
5106 self.assertRaises(TypeError, x.to_integral, rounding=None, context=[])
5107 self.assertRaises(TypeError, x.to_integral, rounding={}, context=[])
5108 self.assertRaises(TypeError, x.to_integral, [], [])
5109
5110 self.assertRaises(TypeError, x.to_integral_value, rounding=None, context=[])
5111 self.assertRaises(TypeError, x.to_integral_value, rounding={}, context=[])
5112 self.assertRaises(TypeError, x.to_integral_value, [], [])
5113
5114 self.assertRaises(TypeError, x.to_integral_exact, rounding=None, context=[])
5115 self.assertRaises(TypeError, x.to_integral_exact, rounding={}, context=[])
5116 self.assertRaises(TypeError, x.to_integral_exact, [], [])
5117
5118 self.assertRaises(TypeError, x.fma, 1, 2, context="x")
5119 self.assertRaises(TypeError, x.fma, 1, 2, "x", context=None)
5120
5121 self.assertRaises(TypeError, x.quantize, 1, [], context=None)
5122 self.assertRaises(TypeError, x.quantize, 1, [], rounding=None)
5123 self.assertRaises(TypeError, x.quantize, 1, [], [])
5124
5125 c = Context()
5126 self.assertRaises(TypeError, c.power, 1, 2, mod="x")
5127 self.assertRaises(TypeError, c.power, 1, "x", mod=None)
5128 self.assertRaises(TypeError, c.power, "x", 2, mod=None)
5129
Stefan Krah1919b7e2012-03-21 18:25:23 +01005130 @requires_extra_functionality
5131 def test_c_context_templates(self):
5132 self.assertEqual(
5133 C.BasicContext._traps,
5134 C.DecIEEEInvalidOperation|C.DecDivisionByZero|C.DecOverflow|
5135 C.DecUnderflow|C.DecClamped
5136 )
5137 self.assertEqual(
5138 C.DefaultContext._traps,
5139 C.DecIEEEInvalidOperation|C.DecDivisionByZero|C.DecOverflow
5140 )
Mark Dickinson84230a12010-02-18 14:49:50 +00005141
Stefan Krah1919b7e2012-03-21 18:25:23 +01005142 @requires_extra_functionality
5143 def test_c_signal_dict(self):
Mark Dickinson84230a12010-02-18 14:49:50 +00005144
Stefan Krah1919b7e2012-03-21 18:25:23 +01005145 # SignalDict coverage
5146 Context = C.Context
5147 DefaultContext = C.DefaultContext
Mark Dickinson84230a12010-02-18 14:49:50 +00005148
Stefan Krah1919b7e2012-03-21 18:25:23 +01005149 InvalidOperation = C.InvalidOperation
5150 DivisionByZero = C.DivisionByZero
5151 Overflow = C.Overflow
5152 Subnormal = C.Subnormal
5153 Underflow = C.Underflow
5154 Rounded = C.Rounded
5155 Inexact = C.Inexact
5156 Clamped = C.Clamped
Mark Dickinson84230a12010-02-18 14:49:50 +00005157
Stefan Krah1919b7e2012-03-21 18:25:23 +01005158 DecClamped = C.DecClamped
5159 DecInvalidOperation = C.DecInvalidOperation
5160 DecIEEEInvalidOperation = C.DecIEEEInvalidOperation
Mark Dickinson84230a12010-02-18 14:49:50 +00005161
Stefan Krah1919b7e2012-03-21 18:25:23 +01005162 def assertIsExclusivelySet(signal, signal_dict):
5163 for sig in signal_dict:
5164 if sig == signal:
5165 self.assertTrue(signal_dict[sig])
5166 else:
5167 self.assertFalse(signal_dict[sig])
Mark Dickinson84230a12010-02-18 14:49:50 +00005168
Stefan Krah1919b7e2012-03-21 18:25:23 +01005169 c = DefaultContext.copy()
Mark Dickinson84230a12010-02-18 14:49:50 +00005170
Stefan Krah1919b7e2012-03-21 18:25:23 +01005171 # Signal dict methods
5172 self.assertTrue(Overflow in c.traps)
5173 c.clear_traps()
5174 for k in c.traps.keys():
5175 c.traps[k] = True
5176 for v in c.traps.values():
5177 self.assertTrue(v)
5178 c.clear_traps()
5179 for k, v in c.traps.items():
5180 self.assertFalse(v)
Mark Dickinson84230a12010-02-18 14:49:50 +00005181
Stefan Krah1919b7e2012-03-21 18:25:23 +01005182 self.assertFalse(c.flags.get(Overflow))
5183 self.assertIs(c.flags.get("x"), None)
5184 self.assertEqual(c.flags.get("x", "y"), "y")
5185 self.assertRaises(TypeError, c.flags.get, "x", "y", "z")
Mark Dickinson84230a12010-02-18 14:49:50 +00005186
Stefan Krah1919b7e2012-03-21 18:25:23 +01005187 self.assertEqual(len(c.flags), len(c.traps))
5188 s = sys.getsizeof(c.flags)
5189 s = sys.getsizeof(c.traps)
5190 s = c.flags.__repr__()
Mark Dickinson84230a12010-02-18 14:49:50 +00005191
Stefan Krah1919b7e2012-03-21 18:25:23 +01005192 # Set flags/traps.
5193 c.clear_flags()
5194 c._flags = DecClamped
5195 self.assertTrue(c.flags[Clamped])
Mark Dickinson84230a12010-02-18 14:49:50 +00005196
Stefan Krah1919b7e2012-03-21 18:25:23 +01005197 c.clear_traps()
5198 c._traps = DecInvalidOperation
5199 self.assertTrue(c.traps[InvalidOperation])
Mark Dickinson84230a12010-02-18 14:49:50 +00005200
Stefan Krah1919b7e2012-03-21 18:25:23 +01005201 # Set flags/traps from dictionary.
5202 c.clear_flags()
5203 d = c.flags.copy()
5204 d[DivisionByZero] = True
5205 c.flags = d
5206 assertIsExclusivelySet(DivisionByZero, c.flags)
Mark Dickinson84230a12010-02-18 14:49:50 +00005207
Stefan Krah1919b7e2012-03-21 18:25:23 +01005208 c.clear_traps()
5209 d = c.traps.copy()
5210 d[Underflow] = True
5211 c.traps = d
5212 assertIsExclusivelySet(Underflow, c.traps)
Mark Dickinson84230a12010-02-18 14:49:50 +00005213
Stefan Krah1919b7e2012-03-21 18:25:23 +01005214 # Random constructors
5215 IntSignals = {
5216 Clamped: C.DecClamped,
5217 Rounded: C.DecRounded,
5218 Inexact: C.DecInexact,
5219 Subnormal: C.DecSubnormal,
5220 Underflow: C.DecUnderflow,
5221 Overflow: C.DecOverflow,
5222 DivisionByZero: C.DecDivisionByZero,
5223 InvalidOperation: C.DecIEEEInvalidOperation
5224 }
5225 IntCond = [
5226 C.DecDivisionImpossible, C.DecDivisionUndefined, C.DecFpuError,
5227 C.DecInvalidContext, C.DecInvalidOperation, C.DecMallocError,
5228 C.DecConversionSyntax,
5229 ]
Mark Dickinsonb455e582011-05-22 12:53:18 +01005230
Stefan Krah1919b7e2012-03-21 18:25:23 +01005231 lim = len(OrderedSignals[C])
5232 for r in range(lim):
5233 for t in range(lim):
Stefan Krah59a4a932013-01-16 12:58:59 +01005234 for round in RoundingModes:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005235 flags = random.sample(OrderedSignals[C], r)
5236 traps = random.sample(OrderedSignals[C], t)
5237 prec = random.randrange(1, 10000)
5238 emin = random.randrange(-10000, 0)
5239 emax = random.randrange(0, 10000)
5240 clamp = random.randrange(0, 2)
5241 caps = random.randrange(0, 2)
5242 cr = random.randrange(0, 2)
5243 c = Context(prec=prec, rounding=round, Emin=emin, Emax=emax,
5244 capitals=caps, clamp=clamp, flags=list(flags),
5245 traps=list(traps))
Mark Dickinson84230a12010-02-18 14:49:50 +00005246
Stefan Krah1919b7e2012-03-21 18:25:23 +01005247 self.assertEqual(c.prec, prec)
5248 self.assertEqual(c.rounding, round)
5249 self.assertEqual(c.Emin, emin)
5250 self.assertEqual(c.Emax, emax)
5251 self.assertEqual(c.capitals, caps)
5252 self.assertEqual(c.clamp, clamp)
Mark Dickinson84230a12010-02-18 14:49:50 +00005253
Stefan Krah1919b7e2012-03-21 18:25:23 +01005254 f = 0
5255 for x in flags:
5256 f |= IntSignals[x]
5257 self.assertEqual(c._flags, f)
Mark Dickinson84230a12010-02-18 14:49:50 +00005258
Stefan Krah1919b7e2012-03-21 18:25:23 +01005259 f = 0
5260 for x in traps:
5261 f |= IntSignals[x]
5262 self.assertEqual(c._traps, f)
Mark Dickinson84230a12010-02-18 14:49:50 +00005263
Stefan Krah1919b7e2012-03-21 18:25:23 +01005264 for cond in IntCond:
5265 c._flags = cond
5266 self.assertTrue(c._flags&DecIEEEInvalidOperation)
5267 assertIsExclusivelySet(InvalidOperation, c.flags)
Mark Dickinson84230a12010-02-18 14:49:50 +00005268
Stefan Krah1919b7e2012-03-21 18:25:23 +01005269 for cond in IntCond:
5270 c._traps = cond
5271 self.assertTrue(c._traps&DecIEEEInvalidOperation)
5272 assertIsExclusivelySet(InvalidOperation, c.traps)
Mark Dickinson84230a12010-02-18 14:49:50 +00005273
Stefan Krah1919b7e2012-03-21 18:25:23 +01005274 def test_invalid_override(self):
5275 Decimal = C.Decimal
Mark Dickinson84230a12010-02-18 14:49:50 +00005276
Stefan Krah1919b7e2012-03-21 18:25:23 +01005277 try:
5278 from locale import CHAR_MAX
5279 except ImportError:
Zachary Ware9fe6d862013-12-08 00:20:35 -06005280 self.skipTest('locale.CHAR_MAX not available')
Mark Dickinson84230a12010-02-18 14:49:50 +00005281
Stefan Krah1919b7e2012-03-21 18:25:23 +01005282 def make_grouping(lst):
5283 return ''.join([chr(x) for x in lst])
Mark Dickinson84230a12010-02-18 14:49:50 +00005284
Stefan Krah1919b7e2012-03-21 18:25:23 +01005285 def get_fmt(x, override=None, fmt='n'):
5286 return Decimal(x).__format__(fmt, override)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005287
Stefan Krah1919b7e2012-03-21 18:25:23 +01005288 invalid_grouping = {
5289 'decimal_point' : ',',
5290 'grouping' : make_grouping([255, 255, 0]),
5291 'thousands_sep' : ','
5292 }
5293 invalid_dot = {
5294 'decimal_point' : 'xxxxx',
5295 'grouping' : make_grouping([3, 3, 0]),
5296 'thousands_sep' : ','
5297 }
5298 invalid_sep = {
5299 'decimal_point' : '.',
5300 'grouping' : make_grouping([3, 3, 0]),
5301 'thousands_sep' : 'yyyyy'
5302 }
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005303
Stefan Krah1919b7e2012-03-21 18:25:23 +01005304 if CHAR_MAX == 127: # negative grouping in override
5305 self.assertRaises(ValueError, get_fmt, 12345,
5306 invalid_grouping, 'g')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005307
Stefan Krah1919b7e2012-03-21 18:25:23 +01005308 self.assertRaises(ValueError, get_fmt, 12345, invalid_dot, 'g')
5309 self.assertRaises(ValueError, get_fmt, 12345, invalid_sep, 'g')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005310
Stefan Krah0774e9b2012-04-05 15:21:58 +02005311 def test_exact_conversion(self):
5312 Decimal = C.Decimal
5313 localcontext = C.localcontext
5314 InvalidOperation = C.InvalidOperation
5315
5316 with localcontext() as c:
5317
5318 c.traps[InvalidOperation] = True
5319
5320 # Clamped
5321 x = "0e%d" % sys.maxsize
5322 self.assertRaises(InvalidOperation, Decimal, x)
5323
5324 x = "0e%d" % (-sys.maxsize-1)
5325 self.assertRaises(InvalidOperation, Decimal, x)
5326
5327 # Overflow
5328 x = "1e%d" % sys.maxsize
5329 self.assertRaises(InvalidOperation, Decimal, x)
5330
5331 # Underflow
5332 x = "1e%d" % (-sys.maxsize-1)
5333 self.assertRaises(InvalidOperation, Decimal, x)
5334
Stefan Krahff3eca02012-04-05 15:46:19 +02005335 def test_from_tuple(self):
5336 Decimal = C.Decimal
5337 localcontext = C.localcontext
5338 InvalidOperation = C.InvalidOperation
5339 Overflow = C.Overflow
5340 Underflow = C.Underflow
5341
5342 with localcontext() as c:
5343
5344 c.traps[InvalidOperation] = True
5345 c.traps[Overflow] = True
5346 c.traps[Underflow] = True
5347
5348 # SSIZE_MAX
5349 x = (1, (), sys.maxsize)
5350 self.assertEqual(str(c.create_decimal(x)), '-0E+999999')
5351 self.assertRaises(InvalidOperation, Decimal, x)
5352
5353 x = (1, (0, 1, 2), sys.maxsize)
5354 self.assertRaises(Overflow, c.create_decimal, x)
5355 self.assertRaises(InvalidOperation, Decimal, x)
5356
5357 # SSIZE_MIN
5358 x = (1, (), -sys.maxsize-1)
5359 self.assertEqual(str(c.create_decimal(x)), '-0E-1000026')
5360 self.assertRaises(InvalidOperation, Decimal, x)
5361
5362 x = (1, (0, 1, 2), -sys.maxsize-1)
5363 self.assertRaises(Underflow, c.create_decimal, x)
5364 self.assertRaises(InvalidOperation, Decimal, x)
5365
5366 # OverflowError
5367 x = (1, (), sys.maxsize+1)
5368 self.assertRaises(OverflowError, c.create_decimal, x)
5369 self.assertRaises(OverflowError, Decimal, x)
5370
5371 x = (1, (), -sys.maxsize-2)
5372 self.assertRaises(OverflowError, c.create_decimal, x)
5373 self.assertRaises(OverflowError, Decimal, x)
5374
5375 # Specials
5376 x = (1, (), "N")
5377 self.assertEqual(str(Decimal(x)), '-sNaN')
5378 x = (1, (0,), "N")
5379 self.assertEqual(str(Decimal(x)), '-sNaN')
5380 x = (1, (0, 1), "N")
5381 self.assertEqual(str(Decimal(x)), '-sNaN1')
5382
Stefan Krah891ca9e2013-05-29 19:14:17 +02005383 def test_sizeof(self):
5384 Decimal = C.Decimal
5385 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
5386
5387 self.assertGreater(Decimal(0).__sizeof__(), 0)
5388 if HAVE_CONFIG_64:
5389 x = Decimal(10**(19*24)).__sizeof__()
5390 y = Decimal(10**(19*25)).__sizeof__()
5391 self.assertEqual(y, x+8)
5392 else:
5393 x = Decimal(10**(9*24)).__sizeof__()
5394 y = Decimal(10**(9*25)).__sizeof__()
5395 self.assertEqual(y, x+4)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005396
Stefan Krah6b794b82014-05-01 17:42:33 +02005397@requires_docstrings
5398@unittest.skipUnless(C, "test requires C version")
Stefan Krah5de1f822014-05-01 15:53:42 +02005399class SignatureTest(unittest.TestCase):
5400 """Function signatures"""
5401
5402 def test_inspect_module(self):
5403 for attr in dir(P):
5404 if attr.startswith('_'):
5405 continue
5406 p_func = getattr(P, attr)
5407 c_func = getattr(C, attr)
5408 if (attr == 'Decimal' or attr == 'Context' or
5409 inspect.isfunction(p_func)):
5410 p_sig = inspect.signature(p_func)
5411 c_sig = inspect.signature(c_func)
5412
5413 # parameter names:
5414 c_names = list(c_sig.parameters.keys())
5415 p_names = [x for x in p_sig.parameters.keys() if not
5416 x.startswith('_')]
5417
5418 self.assertEqual(c_names, p_names,
5419 msg="parameter name mismatch in %s" % p_func)
5420
5421 c_kind = [x.kind for x in c_sig.parameters.values()]
5422 p_kind = [x[1].kind for x in p_sig.parameters.items() if not
5423 x[0].startswith('_')]
5424
5425 # parameters:
5426 if attr != 'setcontext':
5427 self.assertEqual(c_kind, p_kind,
5428 msg="parameter kind mismatch in %s" % p_func)
5429
5430 def test_inspect_types(self):
5431
5432 POS = inspect._ParameterKind.POSITIONAL_ONLY
5433 POS_KWD = inspect._ParameterKind.POSITIONAL_OR_KEYWORD
5434
5435 # Type heuristic (type annotations would help!):
5436 pdict = {C: {'other': C.Decimal(1),
5437 'third': C.Decimal(1),
5438 'x': C.Decimal(1),
5439 'y': C.Decimal(1),
5440 'z': C.Decimal(1),
5441 'a': C.Decimal(1),
5442 'b': C.Decimal(1),
5443 'c': C.Decimal(1),
5444 'exp': C.Decimal(1),
5445 'modulo': C.Decimal(1),
5446 'num': "1",
5447 'f': 1.0,
5448 'rounding': C.ROUND_HALF_UP,
5449 'context': C.getcontext()},
5450 P: {'other': P.Decimal(1),
5451 'third': P.Decimal(1),
5452 'a': P.Decimal(1),
5453 'b': P.Decimal(1),
5454 'c': P.Decimal(1),
5455 'exp': P.Decimal(1),
5456 'modulo': P.Decimal(1),
5457 'num': "1",
5458 'f': 1.0,
5459 'rounding': P.ROUND_HALF_UP,
5460 'context': P.getcontext()}}
5461
5462 def mkargs(module, sig):
5463 args = []
5464 kwargs = {}
5465 for name, param in sig.parameters.items():
5466 if name == 'self': continue
5467 if param.kind == POS:
5468 args.append(pdict[module][name])
5469 elif param.kind == POS_KWD:
5470 kwargs[name] = pdict[module][name]
5471 else:
5472 raise TestFailed("unexpected parameter kind")
5473 return args, kwargs
5474
5475 def tr(s):
5476 """The C Context docstrings use 'x' in order to prevent confusion
5477 with the article 'a' in the descriptions."""
5478 if s == 'x': return 'a'
5479 if s == 'y': return 'b'
5480 if s == 'z': return 'c'
5481 return s
5482
5483 def doit(ty):
5484 p_type = getattr(P, ty)
5485 c_type = getattr(C, ty)
5486 for attr in dir(p_type):
5487 if attr.startswith('_'):
5488 continue
5489 p_func = getattr(p_type, attr)
5490 c_func = getattr(c_type, attr)
5491 if inspect.isfunction(p_func):
5492 p_sig = inspect.signature(p_func)
5493 c_sig = inspect.signature(c_func)
5494
5495 # parameter names:
5496 p_names = list(p_sig.parameters.keys())
5497 c_names = [tr(x) for x in c_sig.parameters.keys()]
5498
5499 self.assertEqual(c_names, p_names,
5500 msg="parameter name mismatch in %s" % p_func)
5501
5502 p_kind = [x.kind for x in p_sig.parameters.values()]
5503 c_kind = [x.kind for x in c_sig.parameters.values()]
5504
5505 # 'self' parameter:
5506 self.assertIs(p_kind[0], POS_KWD)
5507 self.assertIs(c_kind[0], POS)
5508
5509 # remaining parameters:
5510 if ty == 'Decimal':
5511 self.assertEqual(c_kind[1:], p_kind[1:],
5512 msg="parameter kind mismatch in %s" % p_func)
5513 else: # Context methods are positional only in the C version.
5514 self.assertEqual(len(c_kind), len(p_kind),
5515 msg="parameter kind mismatch in %s" % p_func)
5516
5517 # Run the function:
5518 args, kwds = mkargs(C, c_sig)
5519 try:
5520 getattr(c_type(9), attr)(*args, **kwds)
5521 except Exception as err:
5522 raise TestFailed("invalid signature for %s: %s %s" % (c_func, args, kwds))
5523
5524 args, kwds = mkargs(P, p_sig)
5525 try:
5526 getattr(p_type(9), attr)(*args, **kwds)
5527 except Exception as err:
5528 raise TestFailed("invalid signature for %s: %s %s" % (p_func, args, kwds))
5529
5530 doit('Decimal')
5531 doit('Context')
5532
5533
Stefan Krah1919b7e2012-03-21 18:25:23 +01005534all_tests = [
5535 CExplicitConstructionTest, PyExplicitConstructionTest,
5536 CImplicitConstructionTest, PyImplicitConstructionTest,
5537 CFormatTest, PyFormatTest,
5538 CArithmeticOperatorsTest, PyArithmeticOperatorsTest,
5539 CThreadingTest, PyThreadingTest,
5540 CUsabilityTest, PyUsabilityTest,
5541 CPythonAPItests, PyPythonAPItests,
5542 CContextAPItests, PyContextAPItests,
5543 CContextWithStatement, PyContextWithStatement,
5544 CContextFlags, PyContextFlags,
5545 CSpecialContexts, PySpecialContexts,
5546 CContextInputValidation, PyContextInputValidation,
5547 CContextSubclassing, PyContextSubclassing,
5548 CCoverage, PyCoverage,
5549 CFunctionality, PyFunctionality,
5550 CWhitebox, PyWhitebox,
5551 CIBMTestCases, PyIBMTestCases,
5552]
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005553
Stefan Krah1919b7e2012-03-21 18:25:23 +01005554# Delete C tests if _decimal.so is not present.
5555if not C:
5556 all_tests = all_tests[1::2]
5557else:
5558 all_tests.insert(0, CheckAttributes)
Stefan Krah5de1f822014-05-01 15:53:42 +02005559 all_tests.insert(1, SignatureTest)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005560
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005561
Zachary Ware66f29282014-06-02 16:01:29 -05005562def test_main(arith=None, verbose=None, todo_tests=None, debug=None):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005563 """ Execute the tests.
5564
Raymond Hettingered20ad82004-09-04 20:09:13 +00005565 Runs all arithmetic tests if arith is True or if the "decimal" resource
5566 is enabled in regrtest.py
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005567 """
Raymond Hettingered20ad82004-09-04 20:09:13 +00005568
Stefan Krah1919b7e2012-03-21 18:25:23 +01005569 init(C)
5570 init(P)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005571 global TEST_ALL, DEBUG
Zachary Ware66f29282014-06-02 16:01:29 -05005572 TEST_ALL = arith if arith is not None else is_resource_enabled('decimal')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005573 DEBUG = debug
Raymond Hettingered20ad82004-09-04 20:09:13 +00005574
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005575 if todo_tests is None:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005576 test_classes = all_tests
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005577 else:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005578 test_classes = [CIBMTestCases, PyIBMTestCases]
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005579
5580 # Dynamically build custom test definition for each file in the test
5581 # directory and add the definitions to the DecimalTest class. This
5582 # procedure insures that new files do not get skipped.
5583 for filename in os.listdir(directory):
5584 if '.decTest' not in filename or filename.startswith("."):
5585 continue
5586 head, tail = filename.split('.')
5587 if todo_tests is not None and head not in todo_tests:
5588 continue
5589 tester = lambda self, f=filename: self.eval_file(directory + f)
Stefan Krah1919b7e2012-03-21 18:25:23 +01005590 setattr(CIBMTestCases, 'test_' + head, tester)
5591 setattr(PyIBMTestCases, 'test_' + head, tester)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005592 del filename, head, tail, tester
5593
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005594
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005595 try:
5596 run_unittest(*test_classes)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005597 if todo_tests is None:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005598 from doctest import IGNORE_EXCEPTION_DETAIL
5599 savedecimal = sys.modules['decimal']
5600 if C:
5601 sys.modules['decimal'] = C
5602 run_doctest(C, verbose, optionflags=IGNORE_EXCEPTION_DETAIL)
5603 sys.modules['decimal'] = P
5604 run_doctest(P, verbose)
5605 sys.modules['decimal'] = savedecimal
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005606 finally:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005607 if C: C.setcontext(ORIGINAL_CONTEXT[C])
5608 P.setcontext(ORIGINAL_CONTEXT[P])
5609 if not C:
5610 warnings.warn('C tests skipped: no module named _decimal.',
5611 UserWarning)
5612 if not orig_sys_decimal is sys.modules['decimal']:
5613 raise TestFailed("Internal error: unbalanced number of changes to "
5614 "sys.modules['decimal'].")
5615
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005616
5617if __name__ == '__main__':
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005618 import optparse
5619 p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]")
5620 p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test')
5621 p.add_option('--skip', '-s', action='store_true', help='skip over 90% of the arithmetic tests')
5622 (opt, args) = p.parse_args()
5623
5624 if opt.skip:
5625 test_main(arith=False, verbose=True)
5626 elif args:
5627 test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005628 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005629 test_main(arith=True, verbose=True)