blob: 7492f5466f030c2bd4af75d9781eaa64e866af89 [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 Krah53f2e0a2015-12-28 23:02:02 +01002050 def test_as_integer_ratio(self):
2051 Decimal = self.decimal.Decimal
2052
2053 # exceptional cases
2054 self.assertRaises(OverflowError,
2055 Decimal.as_integer_ratio, Decimal('inf'))
2056 self.assertRaises(OverflowError,
2057 Decimal.as_integer_ratio, Decimal('-inf'))
2058 self.assertRaises(ValueError,
2059 Decimal.as_integer_ratio, Decimal('-nan'))
2060 self.assertRaises(ValueError,
2061 Decimal.as_integer_ratio, Decimal('snan123'))
2062
2063 for exp in range(-4, 2):
2064 for coeff in range(1000):
2065 for sign in '+', '-':
2066 d = Decimal('%s%dE%d' % (sign, coeff, exp))
2067 pq = d.as_integer_ratio()
2068 p, q = pq
2069
2070 # check return type
2071 self.assertIsInstance(pq, tuple)
2072 self.assertIsInstance(p, int)
2073 self.assertIsInstance(q, int)
2074
2075 # check normalization: q should be positive;
2076 # p should be relatively prime to q.
2077 self.assertGreater(q, 0)
2078 self.assertEqual(math.gcd(p, q), 1)
2079
2080 # check that p/q actually gives the correct value
2081 self.assertEqual(Decimal(p) / Decimal(q), d)
2082
Stefan Krah1919b7e2012-03-21 18:25:23 +01002083 def test_subclassing(self):
2084 # Different behaviours when subclassing Decimal
2085 Decimal = self.decimal.Decimal
2086
2087 class MyDecimal(Decimal):
Stefan Krah0f82b762012-11-08 11:17:29 +01002088 y = None
Stefan Krah1919b7e2012-03-21 18:25:23 +01002089
2090 d1 = MyDecimal(1)
2091 d2 = MyDecimal(2)
2092 d = d1 + d2
2093 self.assertIs(type(d), Decimal)
2094
2095 d = d1.max(d2)
2096 self.assertIs(type(d), Decimal)
2097
2098 d = copy.copy(d1)
2099 self.assertIs(type(d), MyDecimal)
2100 self.assertEqual(d, d1)
2101
2102 d = copy.deepcopy(d1)
2103 self.assertIs(type(d), MyDecimal)
2104 self.assertEqual(d, d1)
2105
Stefan Krah0f82b762012-11-08 11:17:29 +01002106 # Decimal(Decimal)
2107 d = Decimal('1.0')
2108 x = Decimal(d)
2109 self.assertIs(type(x), Decimal)
2110 self.assertEqual(x, d)
Stefan Krahf4abc7b2012-11-07 23:12:25 +01002111
Stefan Krah0f82b762012-11-08 11:17:29 +01002112 # MyDecimal(Decimal)
2113 m = MyDecimal(d)
2114 self.assertIs(type(m), MyDecimal)
2115 self.assertEqual(m, d)
2116 self.assertIs(m.y, None)
2117
2118 # Decimal(MyDecimal)
2119 x = Decimal(m)
2120 self.assertIs(type(x), Decimal)
2121 self.assertEqual(x, d)
2122
2123 # MyDecimal(MyDecimal)
2124 m.y = 9
2125 x = MyDecimal(m)
2126 self.assertIs(type(x), MyDecimal)
2127 self.assertEqual(x, d)
2128 self.assertIs(x.y, None)
Stefan Krahed16eff2012-11-07 23:47:19 +01002129
Stefan Krah1919b7e2012-03-21 18:25:23 +01002130 def test_implicit_context(self):
2131 Decimal = self.decimal.Decimal
2132 getcontext = self.decimal.getcontext
2133
2134 # Check results when context given implicitly. (Issue 2478)
2135 c = getcontext()
2136 self.assertEqual(str(Decimal(0).sqrt()),
2137 str(c.sqrt(Decimal(0))))
2138
Stefan Krah040e3112012-12-15 22:33:33 +01002139 def test_none_args(self):
2140 Decimal = self.decimal.Decimal
2141 Context = self.decimal.Context
2142 localcontext = self.decimal.localcontext
2143 InvalidOperation = self.decimal.InvalidOperation
2144 DivisionByZero = self.decimal.DivisionByZero
2145 Overflow = self.decimal.Overflow
2146 Underflow = self.decimal.Underflow
2147 Subnormal = self.decimal.Subnormal
2148 Inexact = self.decimal.Inexact
2149 Rounded = self.decimal.Rounded
2150 Clamped = self.decimal.Clamped
Stefan Krah040e3112012-12-15 22:33:33 +01002151
2152 with localcontext(Context()) as c:
2153 c.prec = 7
2154 c.Emax = 999
2155 c.Emin = -999
2156
2157 x = Decimal("111")
2158 y = Decimal("1e9999")
2159 z = Decimal("1e-9999")
2160
2161 ##### Unary functions
2162 c.clear_flags()
2163 self.assertEqual(str(x.exp(context=None)), '1.609487E+48')
2164 self.assertTrue(c.flags[Inexact])
2165 self.assertTrue(c.flags[Rounded])
2166 c.clear_flags()
2167 self.assertRaises(Overflow, y.exp, context=None)
2168 self.assertTrue(c.flags[Overflow])
2169
2170 self.assertIs(z.is_normal(context=None), False)
2171 self.assertIs(z.is_subnormal(context=None), True)
2172
2173 c.clear_flags()
2174 self.assertEqual(str(x.ln(context=None)), '4.709530')
2175 self.assertTrue(c.flags[Inexact])
2176 self.assertTrue(c.flags[Rounded])
2177 c.clear_flags()
2178 self.assertRaises(InvalidOperation, Decimal(-1).ln, context=None)
2179 self.assertTrue(c.flags[InvalidOperation])
2180
2181 c.clear_flags()
2182 self.assertEqual(str(x.log10(context=None)), '2.045323')
2183 self.assertTrue(c.flags[Inexact])
2184 self.assertTrue(c.flags[Rounded])
2185 c.clear_flags()
2186 self.assertRaises(InvalidOperation, Decimal(-1).log10, context=None)
2187 self.assertTrue(c.flags[InvalidOperation])
2188
2189 c.clear_flags()
2190 self.assertEqual(str(x.logb(context=None)), '2')
2191 self.assertRaises(DivisionByZero, Decimal(0).logb, context=None)
2192 self.assertTrue(c.flags[DivisionByZero])
2193
2194 c.clear_flags()
2195 self.assertEqual(str(x.logical_invert(context=None)), '1111000')
2196 self.assertRaises(InvalidOperation, y.logical_invert, context=None)
2197 self.assertTrue(c.flags[InvalidOperation])
2198
2199 c.clear_flags()
2200 self.assertEqual(str(y.next_minus(context=None)), '9.999999E+999')
2201 self.assertRaises(InvalidOperation, Decimal('sNaN').next_minus, context=None)
2202 self.assertTrue(c.flags[InvalidOperation])
2203
2204 c.clear_flags()
2205 self.assertEqual(str(y.next_plus(context=None)), 'Infinity')
2206 self.assertRaises(InvalidOperation, Decimal('sNaN').next_plus, context=None)
2207 self.assertTrue(c.flags[InvalidOperation])
2208
2209 c.clear_flags()
2210 self.assertEqual(str(z.normalize(context=None)), '0')
2211 self.assertRaises(Overflow, y.normalize, context=None)
2212 self.assertTrue(c.flags[Overflow])
2213
2214 self.assertEqual(str(z.number_class(context=None)), '+Subnormal')
2215
2216 c.clear_flags()
2217 self.assertEqual(str(z.sqrt(context=None)), '0E-1005')
2218 self.assertTrue(c.flags[Clamped])
2219 self.assertTrue(c.flags[Inexact])
2220 self.assertTrue(c.flags[Rounded])
2221 self.assertTrue(c.flags[Subnormal])
2222 self.assertTrue(c.flags[Underflow])
2223 c.clear_flags()
2224 self.assertRaises(Overflow, y.sqrt, context=None)
2225 self.assertTrue(c.flags[Overflow])
2226
2227 c.capitals = 0
2228 self.assertEqual(str(z.to_eng_string(context=None)), '1e-9999')
2229 c.capitals = 1
2230
2231
2232 ##### Binary functions
2233 c.clear_flags()
2234 ans = str(x.compare(Decimal('Nan891287828'), context=None))
2235 self.assertEqual(ans, 'NaN1287828')
2236 self.assertRaises(InvalidOperation, x.compare, Decimal('sNaN'), context=None)
2237 self.assertTrue(c.flags[InvalidOperation])
2238
2239 c.clear_flags()
2240 ans = str(x.compare_signal(8224, context=None))
2241 self.assertEqual(ans, '-1')
2242 self.assertRaises(InvalidOperation, x.compare_signal, Decimal('NaN'), context=None)
2243 self.assertTrue(c.flags[InvalidOperation])
2244
2245 c.clear_flags()
2246 ans = str(x.logical_and(101, context=None))
2247 self.assertEqual(ans, '101')
2248 self.assertRaises(InvalidOperation, x.logical_and, 123, context=None)
2249 self.assertTrue(c.flags[InvalidOperation])
2250
2251 c.clear_flags()
2252 ans = str(x.logical_or(101, context=None))
2253 self.assertEqual(ans, '111')
2254 self.assertRaises(InvalidOperation, x.logical_or, 123, context=None)
2255 self.assertTrue(c.flags[InvalidOperation])
2256
2257 c.clear_flags()
2258 ans = str(x.logical_xor(101, context=None))
2259 self.assertEqual(ans, '10')
2260 self.assertRaises(InvalidOperation, x.logical_xor, 123, context=None)
2261 self.assertTrue(c.flags[InvalidOperation])
2262
2263 c.clear_flags()
2264 ans = str(x.max(101, context=None))
2265 self.assertEqual(ans, '111')
2266 self.assertRaises(InvalidOperation, x.max, Decimal('sNaN'), context=None)
2267 self.assertTrue(c.flags[InvalidOperation])
2268
2269 c.clear_flags()
2270 ans = str(x.max_mag(101, context=None))
2271 self.assertEqual(ans, '111')
2272 self.assertRaises(InvalidOperation, x.max_mag, Decimal('sNaN'), context=None)
2273 self.assertTrue(c.flags[InvalidOperation])
2274
2275 c.clear_flags()
2276 ans = str(x.min(101, context=None))
2277 self.assertEqual(ans, '101')
2278 self.assertRaises(InvalidOperation, x.min, Decimal('sNaN'), context=None)
2279 self.assertTrue(c.flags[InvalidOperation])
2280
2281 c.clear_flags()
2282 ans = str(x.min_mag(101, context=None))
2283 self.assertEqual(ans, '101')
2284 self.assertRaises(InvalidOperation, x.min_mag, Decimal('sNaN'), context=None)
2285 self.assertTrue(c.flags[InvalidOperation])
2286
2287 c.clear_flags()
2288 ans = str(x.remainder_near(101, context=None))
2289 self.assertEqual(ans, '10')
2290 self.assertRaises(InvalidOperation, y.remainder_near, 101, context=None)
2291 self.assertTrue(c.flags[InvalidOperation])
2292
2293 c.clear_flags()
2294 ans = str(x.rotate(2, context=None))
2295 self.assertEqual(ans, '11100')
2296 self.assertRaises(InvalidOperation, x.rotate, 101, context=None)
2297 self.assertTrue(c.flags[InvalidOperation])
2298
2299 c.clear_flags()
2300 ans = str(x.scaleb(7, context=None))
2301 self.assertEqual(ans, '1.11E+9')
2302 self.assertRaises(InvalidOperation, x.scaleb, 10000, context=None)
2303 self.assertTrue(c.flags[InvalidOperation])
2304
2305 c.clear_flags()
2306 ans = str(x.shift(2, context=None))
2307 self.assertEqual(ans, '11100')
2308 self.assertRaises(InvalidOperation, x.shift, 10000, context=None)
2309 self.assertTrue(c.flags[InvalidOperation])
2310
2311
2312 ##### Ternary functions
2313 c.clear_flags()
2314 ans = str(x.fma(2, 3, context=None))
2315 self.assertEqual(ans, '225')
2316 self.assertRaises(Overflow, x.fma, Decimal('1e9999'), 3, context=None)
2317 self.assertTrue(c.flags[Overflow])
2318
2319
2320 ##### Special cases
2321 c.rounding = ROUND_HALF_EVEN
2322 ans = str(Decimal('1.5').to_integral(rounding=None, context=None))
2323 self.assertEqual(ans, '2')
2324 c.rounding = ROUND_DOWN
2325 ans = str(Decimal('1.5').to_integral(rounding=None, context=None))
2326 self.assertEqual(ans, '1')
2327 ans = str(Decimal('1.5').to_integral(rounding=ROUND_UP, context=None))
2328 self.assertEqual(ans, '2')
2329 c.clear_flags()
2330 self.assertRaises(InvalidOperation, Decimal('sNaN').to_integral, context=None)
2331 self.assertTrue(c.flags[InvalidOperation])
2332
2333 c.rounding = ROUND_HALF_EVEN
2334 ans = str(Decimal('1.5').to_integral_value(rounding=None, context=None))
2335 self.assertEqual(ans, '2')
2336 c.rounding = ROUND_DOWN
2337 ans = str(Decimal('1.5').to_integral_value(rounding=None, context=None))
2338 self.assertEqual(ans, '1')
2339 ans = str(Decimal('1.5').to_integral_value(rounding=ROUND_UP, context=None))
2340 self.assertEqual(ans, '2')
2341 c.clear_flags()
2342 self.assertRaises(InvalidOperation, Decimal('sNaN').to_integral_value, context=None)
2343 self.assertTrue(c.flags[InvalidOperation])
2344
2345 c.rounding = ROUND_HALF_EVEN
2346 ans = str(Decimal('1.5').to_integral_exact(rounding=None, context=None))
2347 self.assertEqual(ans, '2')
2348 c.rounding = ROUND_DOWN
2349 ans = str(Decimal('1.5').to_integral_exact(rounding=None, context=None))
2350 self.assertEqual(ans, '1')
2351 ans = str(Decimal('1.5').to_integral_exact(rounding=ROUND_UP, context=None))
2352 self.assertEqual(ans, '2')
2353 c.clear_flags()
2354 self.assertRaises(InvalidOperation, Decimal('sNaN').to_integral_exact, context=None)
2355 self.assertTrue(c.flags[InvalidOperation])
2356
2357 c.rounding = ROUND_UP
2358 ans = str(Decimal('1.50001').quantize(exp=Decimal('1e-3'), rounding=None, context=None))
2359 self.assertEqual(ans, '1.501')
2360 c.rounding = ROUND_DOWN
2361 ans = str(Decimal('1.50001').quantize(exp=Decimal('1e-3'), rounding=None, context=None))
2362 self.assertEqual(ans, '1.500')
2363 ans = str(Decimal('1.50001').quantize(exp=Decimal('1e-3'), rounding=ROUND_UP, context=None))
2364 self.assertEqual(ans, '1.501')
2365 c.clear_flags()
2366 self.assertRaises(InvalidOperation, y.quantize, Decimal('1e-10'), rounding=ROUND_UP, context=None)
2367 self.assertTrue(c.flags[InvalidOperation])
2368
2369 with localcontext(Context()) as context:
2370 context.prec = 7
2371 context.Emax = 999
2372 context.Emin = -999
2373 with localcontext(ctx=None) as c:
2374 self.assertEqual(c.prec, 7)
2375 self.assertEqual(c.Emax, 999)
2376 self.assertEqual(c.Emin, -999)
2377
Stefan Krah1919b7e2012-03-21 18:25:23 +01002378 def test_conversions_from_int(self):
2379 # Check that methods taking a second Decimal argument will
2380 # always accept an integer in place of a Decimal.
2381 Decimal = self.decimal.Decimal
2382
2383 self.assertEqual(Decimal(4).compare(3),
2384 Decimal(4).compare(Decimal(3)))
2385 self.assertEqual(Decimal(4).compare_signal(3),
2386 Decimal(4).compare_signal(Decimal(3)))
2387 self.assertEqual(Decimal(4).compare_total(3),
2388 Decimal(4).compare_total(Decimal(3)))
2389 self.assertEqual(Decimal(4).compare_total_mag(3),
2390 Decimal(4).compare_total_mag(Decimal(3)))
2391 self.assertEqual(Decimal(10101).logical_and(1001),
2392 Decimal(10101).logical_and(Decimal(1001)))
2393 self.assertEqual(Decimal(10101).logical_or(1001),
2394 Decimal(10101).logical_or(Decimal(1001)))
2395 self.assertEqual(Decimal(10101).logical_xor(1001),
2396 Decimal(10101).logical_xor(Decimal(1001)))
2397 self.assertEqual(Decimal(567).max(123),
2398 Decimal(567).max(Decimal(123)))
2399 self.assertEqual(Decimal(567).max_mag(123),
2400 Decimal(567).max_mag(Decimal(123)))
2401 self.assertEqual(Decimal(567).min(123),
2402 Decimal(567).min(Decimal(123)))
2403 self.assertEqual(Decimal(567).min_mag(123),
2404 Decimal(567).min_mag(Decimal(123)))
2405 self.assertEqual(Decimal(567).next_toward(123),
2406 Decimal(567).next_toward(Decimal(123)))
2407 self.assertEqual(Decimal(1234).quantize(100),
2408 Decimal(1234).quantize(Decimal(100)))
2409 self.assertEqual(Decimal(768).remainder_near(1234),
2410 Decimal(768).remainder_near(Decimal(1234)))
2411 self.assertEqual(Decimal(123).rotate(1),
2412 Decimal(123).rotate(Decimal(1)))
2413 self.assertEqual(Decimal(1234).same_quantum(1000),
2414 Decimal(1234).same_quantum(Decimal(1000)))
2415 self.assertEqual(Decimal('9.123').scaleb(-100),
2416 Decimal('9.123').scaleb(Decimal(-100)))
2417 self.assertEqual(Decimal(456).shift(-1),
2418 Decimal(456).shift(Decimal(-1)))
2419
2420 self.assertEqual(Decimal(-12).fma(Decimal(45), 67),
2421 Decimal(-12).fma(Decimal(45), Decimal(67)))
2422 self.assertEqual(Decimal(-12).fma(45, 67),
2423 Decimal(-12).fma(Decimal(45), Decimal(67)))
2424 self.assertEqual(Decimal(-12).fma(45, Decimal(67)),
2425 Decimal(-12).fma(Decimal(45), Decimal(67)))
2426
2427class CUsabilityTest(UsabilityTest):
2428 decimal = C
2429class PyUsabilityTest(UsabilityTest):
2430 decimal = P
2431
2432class PythonAPItests(unittest.TestCase):
2433
2434 def test_abc(self):
2435 Decimal = self.decimal.Decimal
2436
2437 self.assertTrue(issubclass(Decimal, numbers.Number))
2438 self.assertFalse(issubclass(Decimal, numbers.Real))
2439 self.assertIsInstance(Decimal(0), numbers.Number)
2440 self.assertNotIsInstance(Decimal(0), numbers.Real)
2441
2442 def test_pickle(self):
Serhiy Storchakabad12572014-12-15 14:03:42 +02002443 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
2444 Decimal = self.decimal.Decimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01002445
Serhiy Storchakabad12572014-12-15 14:03:42 +02002446 savedecimal = sys.modules['decimal']
Stefan Krah1919b7e2012-03-21 18:25:23 +01002447
Serhiy Storchakabad12572014-12-15 14:03:42 +02002448 # Round trip
2449 sys.modules['decimal'] = self.decimal
2450 d = Decimal('-3.141590000')
2451 p = pickle.dumps(d, proto)
2452 e = pickle.loads(p)
2453 self.assertEqual(d, e)
Stefan Krah1919b7e2012-03-21 18:25:23 +01002454
Serhiy Storchakabad12572014-12-15 14:03:42 +02002455 if C:
2456 # Test interchangeability
2457 x = C.Decimal('-3.123e81723')
2458 y = P.Decimal('-3.123e81723')
Stefan Krah1919b7e2012-03-21 18:25:23 +01002459
Serhiy Storchakabad12572014-12-15 14:03:42 +02002460 sys.modules['decimal'] = C
2461 sx = pickle.dumps(x, proto)
2462 sys.modules['decimal'] = P
2463 r = pickle.loads(sx)
2464 self.assertIsInstance(r, P.Decimal)
2465 self.assertEqual(r, y)
Stefan Krah1919b7e2012-03-21 18:25:23 +01002466
Serhiy Storchakabad12572014-12-15 14:03:42 +02002467 sys.modules['decimal'] = P
2468 sy = pickle.dumps(y, proto)
2469 sys.modules['decimal'] = C
2470 r = pickle.loads(sy)
2471 self.assertIsInstance(r, C.Decimal)
2472 self.assertEqual(r, x)
Stefan Krah1919b7e2012-03-21 18:25:23 +01002473
Serhiy Storchakabad12572014-12-15 14:03:42 +02002474 x = C.Decimal('-3.123e81723').as_tuple()
2475 y = P.Decimal('-3.123e81723').as_tuple()
Stefan Krahf1d4e422014-04-29 18:23:35 +02002476
Serhiy Storchakabad12572014-12-15 14:03:42 +02002477 sys.modules['decimal'] = C
2478 sx = pickle.dumps(x, proto)
2479 sys.modules['decimal'] = P
2480 r = pickle.loads(sx)
2481 self.assertIsInstance(r, P.DecimalTuple)
2482 self.assertEqual(r, y)
Stefan Krahf1d4e422014-04-29 18:23:35 +02002483
Serhiy Storchakabad12572014-12-15 14:03:42 +02002484 sys.modules['decimal'] = P
2485 sy = pickle.dumps(y, proto)
2486 sys.modules['decimal'] = C
2487 r = pickle.loads(sy)
2488 self.assertIsInstance(r, C.DecimalTuple)
2489 self.assertEqual(r, x)
Stefan Krahf1d4e422014-04-29 18:23:35 +02002490
Serhiy Storchakabad12572014-12-15 14:03:42 +02002491 sys.modules['decimal'] = savedecimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01002492
2493 def test_int(self):
2494 Decimal = self.decimal.Decimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01002495
2496 for x in range(-250, 250):
2497 s = '%0.2f' % (x / 100.0)
2498 # should work the same as for floats
2499 self.assertEqual(int(Decimal(s)), int(float(s)))
2500 # should work the same as to_integral in the ROUND_DOWN mode
2501 d = Decimal(s)
2502 r = d.to_integral(ROUND_DOWN)
2503 self.assertEqual(Decimal(int(d)), r)
2504
2505 self.assertRaises(ValueError, int, Decimal('-nan'))
2506 self.assertRaises(ValueError, int, Decimal('snan'))
2507 self.assertRaises(OverflowError, int, Decimal('inf'))
2508 self.assertRaises(OverflowError, int, Decimal('-inf'))
2509
2510 def test_trunc(self):
2511 Decimal = self.decimal.Decimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01002512
2513 for x in range(-250, 250):
2514 s = '%0.2f' % (x / 100.0)
2515 # should work the same as for floats
2516 self.assertEqual(int(Decimal(s)), int(float(s)))
2517 # should work the same as to_integral in the ROUND_DOWN mode
2518 d = Decimal(s)
2519 r = d.to_integral(ROUND_DOWN)
2520 self.assertEqual(Decimal(math.trunc(d)), r)
2521
2522 def test_from_float(self):
2523
2524 Decimal = self.decimal.Decimal
2525
2526 class MyDecimal(Decimal):
Stefan Krah6817c592016-06-20 12:10:13 +02002527 def __init__(self, _):
2528 self.x = 'y'
Stefan Krah1919b7e2012-03-21 18:25:23 +01002529
2530 self.assertTrue(issubclass(MyDecimal, Decimal))
2531
2532 r = MyDecimal.from_float(0.1)
2533 self.assertEqual(type(r), MyDecimal)
2534 self.assertEqual(str(r),
2535 '0.1000000000000000055511151231257827021181583404541015625')
Stefan Krah6817c592016-06-20 12:10:13 +02002536 self.assertEqual(r.x, 'y')
2537
Stefan Krah1919b7e2012-03-21 18:25:23 +01002538 bigint = 12345678901234567890123456789
2539 self.assertEqual(MyDecimal.from_float(bigint), MyDecimal(bigint))
2540 self.assertTrue(MyDecimal.from_float(float('nan')).is_qnan())
2541 self.assertTrue(MyDecimal.from_float(float('inf')).is_infinite())
2542 self.assertTrue(MyDecimal.from_float(float('-inf')).is_infinite())
2543 self.assertEqual(str(MyDecimal.from_float(float('nan'))),
2544 str(Decimal('NaN')))
2545 self.assertEqual(str(MyDecimal.from_float(float('inf'))),
2546 str(Decimal('Infinity')))
2547 self.assertEqual(str(MyDecimal.from_float(float('-inf'))),
2548 str(Decimal('-Infinity')))
2549 self.assertRaises(TypeError, MyDecimal.from_float, 'abc')
2550 for i in range(200):
2551 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
2552 self.assertEqual(x, float(MyDecimal.from_float(x))) # roundtrip
2553
2554 def test_create_decimal_from_float(self):
2555 Decimal = self.decimal.Decimal
2556 Context = self.decimal.Context
Stefan Krah1919b7e2012-03-21 18:25:23 +01002557 Inexact = self.decimal.Inexact
2558
2559 context = Context(prec=5, rounding=ROUND_DOWN)
2560 self.assertEqual(
2561 context.create_decimal_from_float(math.pi),
2562 Decimal('3.1415')
2563 )
2564 context = Context(prec=5, rounding=ROUND_UP)
2565 self.assertEqual(
2566 context.create_decimal_from_float(math.pi),
2567 Decimal('3.1416')
2568 )
2569 context = Context(prec=5, traps=[Inexact])
2570 self.assertRaises(
2571 Inexact,
2572 context.create_decimal_from_float,
2573 math.pi
2574 )
2575 self.assertEqual(repr(context.create_decimal_from_float(-0.0)),
2576 "Decimal('-0')")
2577 self.assertEqual(repr(context.create_decimal_from_float(1.0)),
2578 "Decimal('1')")
2579 self.assertEqual(repr(context.create_decimal_from_float(10)),
2580 "Decimal('10')")
2581
2582 def test_quantize(self):
2583 Decimal = self.decimal.Decimal
2584 Context = self.decimal.Context
2585 InvalidOperation = self.decimal.InvalidOperation
Stefan Krah1919b7e2012-03-21 18:25:23 +01002586
2587 c = Context(Emax=99999, Emin=-99999)
2588 self.assertEqual(
2589 Decimal('7.335').quantize(Decimal('.01')),
2590 Decimal('7.34')
2591 )
2592 self.assertEqual(
2593 Decimal('7.335').quantize(Decimal('.01'), rounding=ROUND_DOWN),
2594 Decimal('7.33')
2595 )
2596 self.assertRaises(
2597 InvalidOperation,
2598 Decimal("10e99999").quantize, Decimal('1e100000'), context=c
2599 )
2600
2601 c = Context()
2602 d = Decimal("0.871831e800")
2603 x = d.quantize(context=c, exp=Decimal("1e797"), rounding=ROUND_DOWN)
2604 self.assertEqual(x, Decimal('8.71E+799'))
2605
2606 def test_complex(self):
2607 Decimal = self.decimal.Decimal
2608
2609 x = Decimal("9.8182731e181273")
2610 self.assertEqual(x.real, x)
2611 self.assertEqual(x.imag, 0)
2612 self.assertEqual(x.conjugate(), x)
2613
2614 x = Decimal("1")
2615 self.assertEqual(complex(x), complex(float(1)))
2616
2617 self.assertRaises(AttributeError, setattr, x, 'real', 100)
2618 self.assertRaises(AttributeError, setattr, x, 'imag', 100)
2619 self.assertRaises(AttributeError, setattr, x, 'conjugate', 100)
2620 self.assertRaises(AttributeError, setattr, x, '__complex__', 100)
2621
2622 def test_named_parameters(self):
2623 D = self.decimal.Decimal
2624 Context = self.decimal.Context
2625 localcontext = self.decimal.localcontext
2626 InvalidOperation = self.decimal.InvalidOperation
2627 Overflow = self.decimal.Overflow
2628
2629 xc = Context()
2630 xc.prec = 1
2631 xc.Emax = 1
2632 xc.Emin = -1
2633
2634 with localcontext() as c:
2635 c.clear_flags()
2636
2637 self.assertEqual(D(9, xc), 9)
2638 self.assertEqual(D(9, context=xc), 9)
2639 self.assertEqual(D(context=xc, value=9), 9)
2640 self.assertEqual(D(context=xc), 0)
2641 xc.clear_flags()
2642 self.assertRaises(InvalidOperation, D, "xyz", context=xc)
2643 self.assertTrue(xc.flags[InvalidOperation])
2644 self.assertFalse(c.flags[InvalidOperation])
2645
2646 xc.clear_flags()
2647 self.assertEqual(D(2).exp(context=xc), 7)
2648 self.assertRaises(Overflow, D(8).exp, context=xc)
2649 self.assertTrue(xc.flags[Overflow])
2650 self.assertFalse(c.flags[Overflow])
2651
2652 xc.clear_flags()
2653 self.assertEqual(D(2).ln(context=xc), D('0.7'))
2654 self.assertRaises(InvalidOperation, D(-1).ln, context=xc)
2655 self.assertTrue(xc.flags[InvalidOperation])
2656 self.assertFalse(c.flags[InvalidOperation])
2657
2658 self.assertEqual(D(0).log10(context=xc), D('-inf'))
2659 self.assertEqual(D(-1).next_minus(context=xc), -2)
2660 self.assertEqual(D(-1).next_plus(context=xc), D('-0.9'))
2661 self.assertEqual(D("9.73").normalize(context=xc), D('1E+1'))
2662 self.assertEqual(D("9999").to_integral(context=xc), 9999)
2663 self.assertEqual(D("-2000").to_integral_exact(context=xc), -2000)
2664 self.assertEqual(D("123").to_integral_value(context=xc), 123)
2665 self.assertEqual(D("0.0625").sqrt(context=xc), D('0.2'))
2666
2667 self.assertEqual(D("0.0625").compare(context=xc, other=3), -1)
2668 xc.clear_flags()
2669 self.assertRaises(InvalidOperation,
2670 D("0").compare_signal, D('nan'), context=xc)
2671 self.assertTrue(xc.flags[InvalidOperation])
2672 self.assertFalse(c.flags[InvalidOperation])
2673 self.assertEqual(D("0.01").max(D('0.0101'), context=xc), D('0.0'))
2674 self.assertEqual(D("0.01").max(D('0.0101'), context=xc), D('0.0'))
2675 self.assertEqual(D("0.2").max_mag(D('-0.3'), context=xc),
2676 D('-0.3'))
2677 self.assertEqual(D("0.02").min(D('-0.03'), context=xc), D('-0.0'))
2678 self.assertEqual(D("0.02").min_mag(D('-0.03'), context=xc),
2679 D('0.0'))
2680 self.assertEqual(D("0.2").next_toward(D('-1'), context=xc), D('0.1'))
2681 xc.clear_flags()
2682 self.assertRaises(InvalidOperation,
2683 D("0.2").quantize, D('1e10'), context=xc)
2684 self.assertTrue(xc.flags[InvalidOperation])
2685 self.assertFalse(c.flags[InvalidOperation])
2686 self.assertEqual(D("9.99").remainder_near(D('1.5'), context=xc),
2687 D('-0.5'))
2688
2689 self.assertEqual(D("9.9").fma(third=D('0.9'), context=xc, other=7),
2690 D('7E+1'))
2691
2692 self.assertRaises(TypeError, D(1).is_canonical, context=xc)
2693 self.assertRaises(TypeError, D(1).is_finite, context=xc)
2694 self.assertRaises(TypeError, D(1).is_infinite, context=xc)
2695 self.assertRaises(TypeError, D(1).is_nan, context=xc)
2696 self.assertRaises(TypeError, D(1).is_qnan, context=xc)
2697 self.assertRaises(TypeError, D(1).is_snan, context=xc)
2698 self.assertRaises(TypeError, D(1).is_signed, context=xc)
2699 self.assertRaises(TypeError, D(1).is_zero, context=xc)
2700
2701 self.assertFalse(D("0.01").is_normal(context=xc))
2702 self.assertTrue(D("0.01").is_subnormal(context=xc))
2703
2704 self.assertRaises(TypeError, D(1).adjusted, context=xc)
2705 self.assertRaises(TypeError, D(1).conjugate, context=xc)
2706 self.assertRaises(TypeError, D(1).radix, context=xc)
2707
2708 self.assertEqual(D(-111).logb(context=xc), 2)
2709 self.assertEqual(D(0).logical_invert(context=xc), 1)
2710 self.assertEqual(D('0.01').number_class(context=xc), '+Subnormal')
2711 self.assertEqual(D('0.21').to_eng_string(context=xc), '0.21')
2712
2713 self.assertEqual(D('11').logical_and(D('10'), context=xc), 0)
2714 self.assertEqual(D('11').logical_or(D('10'), context=xc), 1)
2715 self.assertEqual(D('01').logical_xor(D('10'), context=xc), 1)
2716 self.assertEqual(D('23').rotate(1, context=xc), 3)
2717 self.assertEqual(D('23').rotate(1, context=xc), 3)
2718 xc.clear_flags()
2719 self.assertRaises(Overflow,
2720 D('23').scaleb, 1, context=xc)
2721 self.assertTrue(xc.flags[Overflow])
2722 self.assertFalse(c.flags[Overflow])
2723 self.assertEqual(D('23').shift(-1, context=xc), 0)
2724
2725 self.assertRaises(TypeError, D.from_float, 1.1, context=xc)
2726 self.assertRaises(TypeError, D(0).as_tuple, context=xc)
2727
Stefan Krah040e3112012-12-15 22:33:33 +01002728 self.assertEqual(D(1).canonical(), 1)
2729 self.assertRaises(TypeError, D("-1").copy_abs, context=xc)
2730 self.assertRaises(TypeError, D("-1").copy_negate, context=xc)
2731 self.assertRaises(TypeError, D(1).canonical, context="x")
2732 self.assertRaises(TypeError, D(1).canonical, xyz="x")
Stefan Krah1919b7e2012-03-21 18:25:23 +01002733
Stefan Krahb6405ef2012-03-23 14:46:48 +01002734 def test_exception_hierarchy(self):
2735
2736 decimal = self.decimal
2737 DecimalException = decimal.DecimalException
2738 InvalidOperation = decimal.InvalidOperation
2739 FloatOperation = decimal.FloatOperation
2740 DivisionByZero = decimal.DivisionByZero
2741 Overflow = decimal.Overflow
2742 Underflow = decimal.Underflow
2743 Subnormal = decimal.Subnormal
2744 Inexact = decimal.Inexact
2745 Rounded = decimal.Rounded
2746 Clamped = decimal.Clamped
2747
2748 self.assertTrue(issubclass(DecimalException, ArithmeticError))
2749
2750 self.assertTrue(issubclass(InvalidOperation, DecimalException))
2751 self.assertTrue(issubclass(FloatOperation, DecimalException))
2752 self.assertTrue(issubclass(FloatOperation, TypeError))
2753 self.assertTrue(issubclass(DivisionByZero, DecimalException))
2754 self.assertTrue(issubclass(DivisionByZero, ZeroDivisionError))
2755 self.assertTrue(issubclass(Overflow, Rounded))
2756 self.assertTrue(issubclass(Overflow, Inexact))
2757 self.assertTrue(issubclass(Overflow, DecimalException))
2758 self.assertTrue(issubclass(Underflow, Inexact))
2759 self.assertTrue(issubclass(Underflow, Rounded))
2760 self.assertTrue(issubclass(Underflow, Subnormal))
2761 self.assertTrue(issubclass(Underflow, DecimalException))
2762
2763 self.assertTrue(issubclass(Subnormal, DecimalException))
2764 self.assertTrue(issubclass(Inexact, DecimalException))
2765 self.assertTrue(issubclass(Rounded, DecimalException))
2766 self.assertTrue(issubclass(Clamped, DecimalException))
2767
2768 self.assertTrue(issubclass(decimal.ConversionSyntax, InvalidOperation))
2769 self.assertTrue(issubclass(decimal.DivisionImpossible, InvalidOperation))
2770 self.assertTrue(issubclass(decimal.DivisionUndefined, InvalidOperation))
2771 self.assertTrue(issubclass(decimal.DivisionUndefined, ZeroDivisionError))
2772 self.assertTrue(issubclass(decimal.InvalidContext, InvalidOperation))
2773
Stefan Krah1919b7e2012-03-21 18:25:23 +01002774class CPythonAPItests(PythonAPItests):
2775 decimal = C
2776class PyPythonAPItests(PythonAPItests):
2777 decimal = P
2778
2779class ContextAPItests(unittest.TestCase):
2780
Stefan Krah9a4ff432012-12-16 21:10:35 +01002781 def test_none_args(self):
2782 Context = self.decimal.Context
2783 InvalidOperation = self.decimal.InvalidOperation
2784 DivisionByZero = self.decimal.DivisionByZero
2785 Overflow = self.decimal.Overflow
Stefan Krah9a4ff432012-12-16 21:10:35 +01002786
2787 c1 = Context()
2788 c2 = Context(prec=None, rounding=None, Emax=None, Emin=None,
2789 capitals=None, clamp=None, flags=None, traps=None)
2790 for c in [c1, c2]:
2791 self.assertEqual(c.prec, 28)
2792 self.assertEqual(c.rounding, ROUND_HALF_EVEN)
2793 self.assertEqual(c.Emax, 999999)
2794 self.assertEqual(c.Emin, -999999)
2795 self.assertEqual(c.capitals, 1)
2796 self.assertEqual(c.clamp, 0)
2797 assert_signals(self, c, 'flags', [])
2798 assert_signals(self, c, 'traps', [InvalidOperation, DivisionByZero,
2799 Overflow])
2800
Stefan Krah59a4a932013-01-16 12:58:59 +01002801 @cpython_only
2802 def test_from_legacy_strings(self):
2803 import _testcapi
2804 c = self.decimal.Context()
2805
2806 for rnd in RoundingModes:
2807 c.rounding = _testcapi.unicode_legacy_string(rnd)
2808 self.assertEqual(c.rounding, rnd)
2809
2810 s = _testcapi.unicode_legacy_string('')
2811 self.assertRaises(TypeError, setattr, c, 'rounding', s)
2812
2813 s = _testcapi.unicode_legacy_string('ROUND_\x00UP')
2814 self.assertRaises(TypeError, setattr, c, 'rounding', s)
2815
Stefan Krah1919b7e2012-03-21 18:25:23 +01002816 def test_pickle(self):
2817
Serhiy Storchakabad12572014-12-15 14:03:42 +02002818 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
2819 Context = self.decimal.Context
Stefan Krah1919b7e2012-03-21 18:25:23 +01002820
Serhiy Storchakabad12572014-12-15 14:03:42 +02002821 savedecimal = sys.modules['decimal']
Stefan Krah1919b7e2012-03-21 18:25:23 +01002822
Serhiy Storchakabad12572014-12-15 14:03:42 +02002823 # Round trip
2824 sys.modules['decimal'] = self.decimal
2825 c = Context()
2826 e = pickle.loads(pickle.dumps(c, proto))
Stefan Krah1919b7e2012-03-21 18:25:23 +01002827
Serhiy Storchakabad12572014-12-15 14:03:42 +02002828 self.assertEqual(c.prec, e.prec)
2829 self.assertEqual(c.Emin, e.Emin)
2830 self.assertEqual(c.Emax, e.Emax)
2831 self.assertEqual(c.rounding, e.rounding)
2832 self.assertEqual(c.capitals, e.capitals)
2833 self.assertEqual(c.clamp, e.clamp)
2834 self.assertEqual(c.flags, e.flags)
2835 self.assertEqual(c.traps, e.traps)
Stefan Krah1919b7e2012-03-21 18:25:23 +01002836
Serhiy Storchakabad12572014-12-15 14:03:42 +02002837 # Test interchangeability
2838 combinations = [(C, P), (P, C)] if C else [(P, P)]
2839 for dumper, loader in combinations:
2840 for ri, _ in enumerate(RoundingModes):
2841 for fi, _ in enumerate(OrderedSignals[dumper]):
2842 for ti, _ in enumerate(OrderedSignals[dumper]):
Stefan Krah1919b7e2012-03-21 18:25:23 +01002843
Serhiy Storchakabad12572014-12-15 14:03:42 +02002844 prec = random.randrange(1, 100)
2845 emin = random.randrange(-100, 0)
2846 emax = random.randrange(1, 100)
2847 caps = random.randrange(2)
2848 clamp = random.randrange(2)
Stefan Krah1919b7e2012-03-21 18:25:23 +01002849
Serhiy Storchakabad12572014-12-15 14:03:42 +02002850 # One module dumps
2851 sys.modules['decimal'] = dumper
2852 c = dumper.Context(
2853 prec=prec, Emin=emin, Emax=emax,
2854 rounding=RoundingModes[ri],
2855 capitals=caps, clamp=clamp,
2856 flags=OrderedSignals[dumper][:fi],
2857 traps=OrderedSignals[dumper][:ti]
2858 )
2859 s = pickle.dumps(c, proto)
Stefan Krah1919b7e2012-03-21 18:25:23 +01002860
Serhiy Storchakabad12572014-12-15 14:03:42 +02002861 # The other module loads
2862 sys.modules['decimal'] = loader
2863 d = pickle.loads(s)
2864 self.assertIsInstance(d, loader.Context)
Stefan Krah1919b7e2012-03-21 18:25:23 +01002865
Serhiy Storchakabad12572014-12-15 14:03:42 +02002866 self.assertEqual(d.prec, prec)
2867 self.assertEqual(d.Emin, emin)
2868 self.assertEqual(d.Emax, emax)
2869 self.assertEqual(d.rounding, RoundingModes[ri])
2870 self.assertEqual(d.capitals, caps)
2871 self.assertEqual(d.clamp, clamp)
2872 assert_signals(self, d, 'flags', OrderedSignals[loader][:fi])
2873 assert_signals(self, d, 'traps', OrderedSignals[loader][:ti])
Stefan Krah1919b7e2012-03-21 18:25:23 +01002874
Serhiy Storchakabad12572014-12-15 14:03:42 +02002875 sys.modules['decimal'] = savedecimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01002876
2877 def test_equality_with_other_types(self):
2878 Decimal = self.decimal.Decimal
2879
2880 self.assertIn(Decimal(10), ['a', 1.0, Decimal(10), (1,2), {}])
2881 self.assertNotIn(Decimal(10), ['a', 1.0, (1,2), {}])
2882
2883 def test_copy(self):
2884 # All copies should be deep
2885 Decimal = self.decimal.Decimal
2886 Context = self.decimal.Context
2887
2888 c = Context()
2889 d = c.copy()
2890 self.assertNotEqual(id(c), id(d))
2891 self.assertNotEqual(id(c.flags), id(d.flags))
2892 self.assertNotEqual(id(c.traps), id(d.traps))
2893 k1 = set(c.flags.keys())
2894 k2 = set(d.flags.keys())
2895 self.assertEqual(k1, k2)
2896 self.assertEqual(c.flags, d.flags)
2897
2898 def test__clamp(self):
2899 # In Python 3.2, the private attribute `_clamp` was made
2900 # public (issue 8540), with the old `_clamp` becoming a
2901 # property wrapping `clamp`. For the duration of Python 3.2
2902 # only, the attribute should be gettable/settable via both
2903 # `clamp` and `_clamp`; in Python 3.3, `_clamp` should be
2904 # removed.
2905 Context = self.decimal.Context
2906 c = Context()
2907 self.assertRaises(AttributeError, getattr, c, '_clamp')
2908
2909 def test_abs(self):
2910 Decimal = self.decimal.Decimal
2911 Context = self.decimal.Context
2912
2913 c = Context()
2914 d = c.abs(Decimal(-1))
2915 self.assertEqual(c.abs(-1), d)
2916 self.assertRaises(TypeError, c.abs, '-1')
2917
2918 def test_add(self):
2919 Decimal = self.decimal.Decimal
2920 Context = self.decimal.Context
2921
2922 c = Context()
2923 d = c.add(Decimal(1), Decimal(1))
2924 self.assertEqual(c.add(1, 1), d)
2925 self.assertEqual(c.add(Decimal(1), 1), d)
2926 self.assertEqual(c.add(1, Decimal(1)), d)
2927 self.assertRaises(TypeError, c.add, '1', 1)
2928 self.assertRaises(TypeError, c.add, 1, '1')
2929
2930 def test_compare(self):
2931 Decimal = self.decimal.Decimal
2932 Context = self.decimal.Context
2933
2934 c = Context()
2935 d = c.compare(Decimal(1), Decimal(1))
2936 self.assertEqual(c.compare(1, 1), d)
2937 self.assertEqual(c.compare(Decimal(1), 1), d)
2938 self.assertEqual(c.compare(1, Decimal(1)), d)
2939 self.assertRaises(TypeError, c.compare, '1', 1)
2940 self.assertRaises(TypeError, c.compare, 1, '1')
2941
2942 def test_compare_signal(self):
2943 Decimal = self.decimal.Decimal
2944 Context = self.decimal.Context
2945
2946 c = Context()
2947 d = c.compare_signal(Decimal(1), Decimal(1))
2948 self.assertEqual(c.compare_signal(1, 1), d)
2949 self.assertEqual(c.compare_signal(Decimal(1), 1), d)
2950 self.assertEqual(c.compare_signal(1, Decimal(1)), d)
2951 self.assertRaises(TypeError, c.compare_signal, '1', 1)
2952 self.assertRaises(TypeError, c.compare_signal, 1, '1')
2953
2954 def test_compare_total(self):
2955 Decimal = self.decimal.Decimal
2956 Context = self.decimal.Context
2957
2958 c = Context()
2959 d = c.compare_total(Decimal(1), Decimal(1))
2960 self.assertEqual(c.compare_total(1, 1), d)
2961 self.assertEqual(c.compare_total(Decimal(1), 1), d)
2962 self.assertEqual(c.compare_total(1, Decimal(1)), d)
2963 self.assertRaises(TypeError, c.compare_total, '1', 1)
2964 self.assertRaises(TypeError, c.compare_total, 1, '1')
2965
2966 def test_compare_total_mag(self):
2967 Decimal = self.decimal.Decimal
2968 Context = self.decimal.Context
2969
2970 c = Context()
2971 d = c.compare_total_mag(Decimal(1), Decimal(1))
2972 self.assertEqual(c.compare_total_mag(1, 1), d)
2973 self.assertEqual(c.compare_total_mag(Decimal(1), 1), d)
2974 self.assertEqual(c.compare_total_mag(1, Decimal(1)), d)
2975 self.assertRaises(TypeError, c.compare_total_mag, '1', 1)
2976 self.assertRaises(TypeError, c.compare_total_mag, 1, '1')
2977
2978 def test_copy_abs(self):
2979 Decimal = self.decimal.Decimal
2980 Context = self.decimal.Context
2981
2982 c = Context()
2983 d = c.copy_abs(Decimal(-1))
2984 self.assertEqual(c.copy_abs(-1), d)
2985 self.assertRaises(TypeError, c.copy_abs, '-1')
2986
2987 def test_copy_decimal(self):
2988 Decimal = self.decimal.Decimal
2989 Context = self.decimal.Context
2990
2991 c = Context()
2992 d = c.copy_decimal(Decimal(-1))
2993 self.assertEqual(c.copy_decimal(-1), d)
2994 self.assertRaises(TypeError, c.copy_decimal, '-1')
2995
2996 def test_copy_negate(self):
2997 Decimal = self.decimal.Decimal
2998 Context = self.decimal.Context
2999
3000 c = Context()
3001 d = c.copy_negate(Decimal(-1))
3002 self.assertEqual(c.copy_negate(-1), d)
3003 self.assertRaises(TypeError, c.copy_negate, '-1')
3004
3005 def test_copy_sign(self):
3006 Decimal = self.decimal.Decimal
3007 Context = self.decimal.Context
3008
3009 c = Context()
3010 d = c.copy_sign(Decimal(1), Decimal(-2))
3011 self.assertEqual(c.copy_sign(1, -2), d)
3012 self.assertEqual(c.copy_sign(Decimal(1), -2), d)
3013 self.assertEqual(c.copy_sign(1, Decimal(-2)), d)
3014 self.assertRaises(TypeError, c.copy_sign, '1', -2)
3015 self.assertRaises(TypeError, c.copy_sign, 1, '-2')
3016
3017 def test_divide(self):
3018 Decimal = self.decimal.Decimal
3019 Context = self.decimal.Context
3020
3021 c = Context()
3022 d = c.divide(Decimal(1), Decimal(2))
3023 self.assertEqual(c.divide(1, 2), d)
3024 self.assertEqual(c.divide(Decimal(1), 2), d)
3025 self.assertEqual(c.divide(1, Decimal(2)), d)
3026 self.assertRaises(TypeError, c.divide, '1', 2)
3027 self.assertRaises(TypeError, c.divide, 1, '2')
3028
3029 def test_divide_int(self):
3030 Decimal = self.decimal.Decimal
3031 Context = self.decimal.Context
3032
3033 c = Context()
3034 d = c.divide_int(Decimal(1), Decimal(2))
3035 self.assertEqual(c.divide_int(1, 2), d)
3036 self.assertEqual(c.divide_int(Decimal(1), 2), d)
3037 self.assertEqual(c.divide_int(1, Decimal(2)), d)
3038 self.assertRaises(TypeError, c.divide_int, '1', 2)
3039 self.assertRaises(TypeError, c.divide_int, 1, '2')
3040
3041 def test_divmod(self):
3042 Decimal = self.decimal.Decimal
3043 Context = self.decimal.Context
3044
3045 c = Context()
3046 d = c.divmod(Decimal(1), Decimal(2))
3047 self.assertEqual(c.divmod(1, 2), d)
3048 self.assertEqual(c.divmod(Decimal(1), 2), d)
3049 self.assertEqual(c.divmod(1, Decimal(2)), d)
3050 self.assertRaises(TypeError, c.divmod, '1', 2)
3051 self.assertRaises(TypeError, c.divmod, 1, '2')
3052
3053 def test_exp(self):
3054 Decimal = self.decimal.Decimal
3055 Context = self.decimal.Context
3056
3057 c = Context()
3058 d = c.exp(Decimal(10))
3059 self.assertEqual(c.exp(10), d)
3060 self.assertRaises(TypeError, c.exp, '10')
3061
3062 def test_fma(self):
3063 Decimal = self.decimal.Decimal
3064 Context = self.decimal.Context
3065
3066 c = Context()
3067 d = c.fma(Decimal(2), Decimal(3), Decimal(4))
3068 self.assertEqual(c.fma(2, 3, 4), d)
3069 self.assertEqual(c.fma(Decimal(2), 3, 4), d)
3070 self.assertEqual(c.fma(2, Decimal(3), 4), d)
3071 self.assertEqual(c.fma(2, 3, Decimal(4)), d)
3072 self.assertEqual(c.fma(Decimal(2), Decimal(3), 4), d)
3073 self.assertRaises(TypeError, c.fma, '2', 3, 4)
3074 self.assertRaises(TypeError, c.fma, 2, '3', 4)
3075 self.assertRaises(TypeError, c.fma, 2, 3, '4')
3076
3077 # Issue 12079 for Context.fma ...
3078 self.assertRaises(TypeError, c.fma,
3079 Decimal('Infinity'), Decimal(0), "not a decimal")
3080 self.assertRaises(TypeError, c.fma,
3081 Decimal(1), Decimal('snan'), 1.222)
3082 # ... and for Decimal.fma.
3083 self.assertRaises(TypeError, Decimal('Infinity').fma,
3084 Decimal(0), "not a decimal")
3085 self.assertRaises(TypeError, Decimal(1).fma,
3086 Decimal('snan'), 1.222)
3087
3088 def test_is_finite(self):
3089 Decimal = self.decimal.Decimal
3090 Context = self.decimal.Context
3091
3092 c = Context()
3093 d = c.is_finite(Decimal(10))
3094 self.assertEqual(c.is_finite(10), d)
3095 self.assertRaises(TypeError, c.is_finite, '10')
3096
3097 def test_is_infinite(self):
3098 Decimal = self.decimal.Decimal
3099 Context = self.decimal.Context
3100
3101 c = Context()
3102 d = c.is_infinite(Decimal(10))
3103 self.assertEqual(c.is_infinite(10), d)
3104 self.assertRaises(TypeError, c.is_infinite, '10')
3105
3106 def test_is_nan(self):
3107 Decimal = self.decimal.Decimal
3108 Context = self.decimal.Context
3109
3110 c = Context()
3111 d = c.is_nan(Decimal(10))
3112 self.assertEqual(c.is_nan(10), d)
3113 self.assertRaises(TypeError, c.is_nan, '10')
3114
3115 def test_is_normal(self):
3116 Decimal = self.decimal.Decimal
3117 Context = self.decimal.Context
3118
3119 c = Context()
3120 d = c.is_normal(Decimal(10))
3121 self.assertEqual(c.is_normal(10), d)
3122 self.assertRaises(TypeError, c.is_normal, '10')
3123
3124 def test_is_qnan(self):
3125 Decimal = self.decimal.Decimal
3126 Context = self.decimal.Context
3127
3128 c = Context()
3129 d = c.is_qnan(Decimal(10))
3130 self.assertEqual(c.is_qnan(10), d)
3131 self.assertRaises(TypeError, c.is_qnan, '10')
3132
3133 def test_is_signed(self):
3134 Decimal = self.decimal.Decimal
3135 Context = self.decimal.Context
3136
3137 c = Context()
3138 d = c.is_signed(Decimal(10))
3139 self.assertEqual(c.is_signed(10), d)
3140 self.assertRaises(TypeError, c.is_signed, '10')
3141
3142 def test_is_snan(self):
3143 Decimal = self.decimal.Decimal
3144 Context = self.decimal.Context
3145
3146 c = Context()
3147 d = c.is_snan(Decimal(10))
3148 self.assertEqual(c.is_snan(10), d)
3149 self.assertRaises(TypeError, c.is_snan, '10')
3150
3151 def test_is_subnormal(self):
3152 Decimal = self.decimal.Decimal
3153 Context = self.decimal.Context
3154
3155 c = Context()
3156 d = c.is_subnormal(Decimal(10))
3157 self.assertEqual(c.is_subnormal(10), d)
3158 self.assertRaises(TypeError, c.is_subnormal, '10')
3159
3160 def test_is_zero(self):
3161 Decimal = self.decimal.Decimal
3162 Context = self.decimal.Context
3163
3164 c = Context()
3165 d = c.is_zero(Decimal(10))
3166 self.assertEqual(c.is_zero(10), d)
3167 self.assertRaises(TypeError, c.is_zero, '10')
3168
3169 def test_ln(self):
3170 Decimal = self.decimal.Decimal
3171 Context = self.decimal.Context
3172
3173 c = Context()
3174 d = c.ln(Decimal(10))
3175 self.assertEqual(c.ln(10), d)
3176 self.assertRaises(TypeError, c.ln, '10')
3177
3178 def test_log10(self):
3179 Decimal = self.decimal.Decimal
3180 Context = self.decimal.Context
3181
3182 c = Context()
3183 d = c.log10(Decimal(10))
3184 self.assertEqual(c.log10(10), d)
3185 self.assertRaises(TypeError, c.log10, '10')
3186
3187 def test_logb(self):
3188 Decimal = self.decimal.Decimal
3189 Context = self.decimal.Context
3190
3191 c = Context()
3192 d = c.logb(Decimal(10))
3193 self.assertEqual(c.logb(10), d)
3194 self.assertRaises(TypeError, c.logb, '10')
3195
3196 def test_logical_and(self):
3197 Decimal = self.decimal.Decimal
3198 Context = self.decimal.Context
3199
3200 c = Context()
3201 d = c.logical_and(Decimal(1), Decimal(1))
3202 self.assertEqual(c.logical_and(1, 1), d)
3203 self.assertEqual(c.logical_and(Decimal(1), 1), d)
3204 self.assertEqual(c.logical_and(1, Decimal(1)), d)
3205 self.assertRaises(TypeError, c.logical_and, '1', 1)
3206 self.assertRaises(TypeError, c.logical_and, 1, '1')
3207
3208 def test_logical_invert(self):
3209 Decimal = self.decimal.Decimal
3210 Context = self.decimal.Context
3211
3212 c = Context()
3213 d = c.logical_invert(Decimal(1000))
3214 self.assertEqual(c.logical_invert(1000), d)
3215 self.assertRaises(TypeError, c.logical_invert, '1000')
3216
3217 def test_logical_or(self):
3218 Decimal = self.decimal.Decimal
3219 Context = self.decimal.Context
3220
3221 c = Context()
3222 d = c.logical_or(Decimal(1), Decimal(1))
3223 self.assertEqual(c.logical_or(1, 1), d)
3224 self.assertEqual(c.logical_or(Decimal(1), 1), d)
3225 self.assertEqual(c.logical_or(1, Decimal(1)), d)
3226 self.assertRaises(TypeError, c.logical_or, '1', 1)
3227 self.assertRaises(TypeError, c.logical_or, 1, '1')
3228
3229 def test_logical_xor(self):
3230 Decimal = self.decimal.Decimal
3231 Context = self.decimal.Context
3232
3233 c = Context()
3234 d = c.logical_xor(Decimal(1), Decimal(1))
3235 self.assertEqual(c.logical_xor(1, 1), d)
3236 self.assertEqual(c.logical_xor(Decimal(1), 1), d)
3237 self.assertEqual(c.logical_xor(1, Decimal(1)), d)
3238 self.assertRaises(TypeError, c.logical_xor, '1', 1)
3239 self.assertRaises(TypeError, c.logical_xor, 1, '1')
3240
3241 def test_max(self):
3242 Decimal = self.decimal.Decimal
3243 Context = self.decimal.Context
3244
3245 c = Context()
3246 d = c.max(Decimal(1), Decimal(2))
3247 self.assertEqual(c.max(1, 2), d)
3248 self.assertEqual(c.max(Decimal(1), 2), d)
3249 self.assertEqual(c.max(1, Decimal(2)), d)
3250 self.assertRaises(TypeError, c.max, '1', 2)
3251 self.assertRaises(TypeError, c.max, 1, '2')
3252
3253 def test_max_mag(self):
3254 Decimal = self.decimal.Decimal
3255 Context = self.decimal.Context
3256
3257 c = Context()
3258 d = c.max_mag(Decimal(1), Decimal(2))
3259 self.assertEqual(c.max_mag(1, 2), d)
3260 self.assertEqual(c.max_mag(Decimal(1), 2), d)
3261 self.assertEqual(c.max_mag(1, Decimal(2)), d)
3262 self.assertRaises(TypeError, c.max_mag, '1', 2)
3263 self.assertRaises(TypeError, c.max_mag, 1, '2')
3264
3265 def test_min(self):
3266 Decimal = self.decimal.Decimal
3267 Context = self.decimal.Context
3268
3269 c = Context()
3270 d = c.min(Decimal(1), Decimal(2))
3271 self.assertEqual(c.min(1, 2), d)
3272 self.assertEqual(c.min(Decimal(1), 2), d)
3273 self.assertEqual(c.min(1, Decimal(2)), d)
3274 self.assertRaises(TypeError, c.min, '1', 2)
3275 self.assertRaises(TypeError, c.min, 1, '2')
3276
3277 def test_min_mag(self):
3278 Decimal = self.decimal.Decimal
3279 Context = self.decimal.Context
3280
3281 c = Context()
3282 d = c.min_mag(Decimal(1), Decimal(2))
3283 self.assertEqual(c.min_mag(1, 2), d)
3284 self.assertEqual(c.min_mag(Decimal(1), 2), d)
3285 self.assertEqual(c.min_mag(1, Decimal(2)), d)
3286 self.assertRaises(TypeError, c.min_mag, '1', 2)
3287 self.assertRaises(TypeError, c.min_mag, 1, '2')
3288
3289 def test_minus(self):
3290 Decimal = self.decimal.Decimal
3291 Context = self.decimal.Context
3292
3293 c = Context()
3294 d = c.minus(Decimal(10))
3295 self.assertEqual(c.minus(10), d)
3296 self.assertRaises(TypeError, c.minus, '10')
3297
3298 def test_multiply(self):
3299 Decimal = self.decimal.Decimal
3300 Context = self.decimal.Context
3301
3302 c = Context()
3303 d = c.multiply(Decimal(1), Decimal(2))
3304 self.assertEqual(c.multiply(1, 2), d)
3305 self.assertEqual(c.multiply(Decimal(1), 2), d)
3306 self.assertEqual(c.multiply(1, Decimal(2)), d)
3307 self.assertRaises(TypeError, c.multiply, '1', 2)
3308 self.assertRaises(TypeError, c.multiply, 1, '2')
3309
3310 def test_next_minus(self):
3311 Decimal = self.decimal.Decimal
3312 Context = self.decimal.Context
3313
3314 c = Context()
3315 d = c.next_minus(Decimal(10))
3316 self.assertEqual(c.next_minus(10), d)
3317 self.assertRaises(TypeError, c.next_minus, '10')
3318
3319 def test_next_plus(self):
3320 Decimal = self.decimal.Decimal
3321 Context = self.decimal.Context
3322
3323 c = Context()
3324 d = c.next_plus(Decimal(10))
3325 self.assertEqual(c.next_plus(10), d)
3326 self.assertRaises(TypeError, c.next_plus, '10')
3327
3328 def test_next_toward(self):
3329 Decimal = self.decimal.Decimal
3330 Context = self.decimal.Context
3331
3332 c = Context()
3333 d = c.next_toward(Decimal(1), Decimal(2))
3334 self.assertEqual(c.next_toward(1, 2), d)
3335 self.assertEqual(c.next_toward(Decimal(1), 2), d)
3336 self.assertEqual(c.next_toward(1, Decimal(2)), d)
3337 self.assertRaises(TypeError, c.next_toward, '1', 2)
3338 self.assertRaises(TypeError, c.next_toward, 1, '2')
3339
3340 def test_normalize(self):
3341 Decimal = self.decimal.Decimal
3342 Context = self.decimal.Context
3343
3344 c = Context()
3345 d = c.normalize(Decimal(10))
3346 self.assertEqual(c.normalize(10), d)
3347 self.assertRaises(TypeError, c.normalize, '10')
3348
3349 def test_number_class(self):
3350 Decimal = self.decimal.Decimal
3351 Context = self.decimal.Context
3352
3353 c = Context()
3354 self.assertEqual(c.number_class(123), c.number_class(Decimal(123)))
3355 self.assertEqual(c.number_class(0), c.number_class(Decimal(0)))
3356 self.assertEqual(c.number_class(-45), c.number_class(Decimal(-45)))
3357
3358 def test_plus(self):
3359 Decimal = self.decimal.Decimal
3360 Context = self.decimal.Context
3361
3362 c = Context()
3363 d = c.plus(Decimal(10))
3364 self.assertEqual(c.plus(10), d)
3365 self.assertRaises(TypeError, c.plus, '10')
3366
3367 def test_power(self):
3368 Decimal = self.decimal.Decimal
3369 Context = self.decimal.Context
3370
3371 c = Context()
3372 d = c.power(Decimal(1), Decimal(4))
3373 self.assertEqual(c.power(1, 4), d)
3374 self.assertEqual(c.power(Decimal(1), 4), d)
3375 self.assertEqual(c.power(1, Decimal(4)), d)
3376 self.assertEqual(c.power(Decimal(1), Decimal(4)), d)
3377 self.assertRaises(TypeError, c.power, '1', 4)
3378 self.assertRaises(TypeError, c.power, 1, '4')
3379 self.assertEqual(c.power(modulo=5, b=8, a=2), 1)
3380
3381 def test_quantize(self):
3382 Decimal = self.decimal.Decimal
3383 Context = self.decimal.Context
3384
3385 c = Context()
3386 d = c.quantize(Decimal(1), Decimal(2))
3387 self.assertEqual(c.quantize(1, 2), d)
3388 self.assertEqual(c.quantize(Decimal(1), 2), d)
3389 self.assertEqual(c.quantize(1, Decimal(2)), d)
3390 self.assertRaises(TypeError, c.quantize, '1', 2)
3391 self.assertRaises(TypeError, c.quantize, 1, '2')
3392
3393 def test_remainder(self):
3394 Decimal = self.decimal.Decimal
3395 Context = self.decimal.Context
3396
3397 c = Context()
3398 d = c.remainder(Decimal(1), Decimal(2))
3399 self.assertEqual(c.remainder(1, 2), d)
3400 self.assertEqual(c.remainder(Decimal(1), 2), d)
3401 self.assertEqual(c.remainder(1, Decimal(2)), d)
3402 self.assertRaises(TypeError, c.remainder, '1', 2)
3403 self.assertRaises(TypeError, c.remainder, 1, '2')
3404
3405 def test_remainder_near(self):
3406 Decimal = self.decimal.Decimal
3407 Context = self.decimal.Context
3408
3409 c = Context()
3410 d = c.remainder_near(Decimal(1), Decimal(2))
3411 self.assertEqual(c.remainder_near(1, 2), d)
3412 self.assertEqual(c.remainder_near(Decimal(1), 2), d)
3413 self.assertEqual(c.remainder_near(1, Decimal(2)), d)
3414 self.assertRaises(TypeError, c.remainder_near, '1', 2)
3415 self.assertRaises(TypeError, c.remainder_near, 1, '2')
3416
3417 def test_rotate(self):
3418 Decimal = self.decimal.Decimal
3419 Context = self.decimal.Context
3420
3421 c = Context()
3422 d = c.rotate(Decimal(1), Decimal(2))
3423 self.assertEqual(c.rotate(1, 2), d)
3424 self.assertEqual(c.rotate(Decimal(1), 2), d)
3425 self.assertEqual(c.rotate(1, Decimal(2)), d)
3426 self.assertRaises(TypeError, c.rotate, '1', 2)
3427 self.assertRaises(TypeError, c.rotate, 1, '2')
3428
3429 def test_sqrt(self):
3430 Decimal = self.decimal.Decimal
3431 Context = self.decimal.Context
3432
3433 c = Context()
3434 d = c.sqrt(Decimal(10))
3435 self.assertEqual(c.sqrt(10), d)
3436 self.assertRaises(TypeError, c.sqrt, '10')
3437
3438 def test_same_quantum(self):
3439 Decimal = self.decimal.Decimal
3440 Context = self.decimal.Context
3441
3442 c = Context()
3443 d = c.same_quantum(Decimal(1), Decimal(2))
3444 self.assertEqual(c.same_quantum(1, 2), d)
3445 self.assertEqual(c.same_quantum(Decimal(1), 2), d)
3446 self.assertEqual(c.same_quantum(1, Decimal(2)), d)
3447 self.assertRaises(TypeError, c.same_quantum, '1', 2)
3448 self.assertRaises(TypeError, c.same_quantum, 1, '2')
3449
3450 def test_scaleb(self):
3451 Decimal = self.decimal.Decimal
3452 Context = self.decimal.Context
3453
3454 c = Context()
3455 d = c.scaleb(Decimal(1), Decimal(2))
3456 self.assertEqual(c.scaleb(1, 2), d)
3457 self.assertEqual(c.scaleb(Decimal(1), 2), d)
3458 self.assertEqual(c.scaleb(1, Decimal(2)), d)
3459 self.assertRaises(TypeError, c.scaleb, '1', 2)
3460 self.assertRaises(TypeError, c.scaleb, 1, '2')
3461
3462 def test_shift(self):
3463 Decimal = self.decimal.Decimal
3464 Context = self.decimal.Context
3465
3466 c = Context()
3467 d = c.shift(Decimal(1), Decimal(2))
3468 self.assertEqual(c.shift(1, 2), d)
3469 self.assertEqual(c.shift(Decimal(1), 2), d)
3470 self.assertEqual(c.shift(1, Decimal(2)), d)
3471 self.assertRaises(TypeError, c.shift, '1', 2)
3472 self.assertRaises(TypeError, c.shift, 1, '2')
3473
3474 def test_subtract(self):
3475 Decimal = self.decimal.Decimal
3476 Context = self.decimal.Context
3477
3478 c = Context()
3479 d = c.subtract(Decimal(1), Decimal(2))
3480 self.assertEqual(c.subtract(1, 2), d)
3481 self.assertEqual(c.subtract(Decimal(1), 2), d)
3482 self.assertEqual(c.subtract(1, Decimal(2)), d)
3483 self.assertRaises(TypeError, c.subtract, '1', 2)
3484 self.assertRaises(TypeError, c.subtract, 1, '2')
3485
3486 def test_to_eng_string(self):
3487 Decimal = self.decimal.Decimal
3488 Context = self.decimal.Context
3489
3490 c = Context()
3491 d = c.to_eng_string(Decimal(10))
3492 self.assertEqual(c.to_eng_string(10), d)
3493 self.assertRaises(TypeError, c.to_eng_string, '10')
3494
3495 def test_to_sci_string(self):
3496 Decimal = self.decimal.Decimal
3497 Context = self.decimal.Context
3498
3499 c = Context()
3500 d = c.to_sci_string(Decimal(10))
3501 self.assertEqual(c.to_sci_string(10), d)
3502 self.assertRaises(TypeError, c.to_sci_string, '10')
3503
3504 def test_to_integral_exact(self):
3505 Decimal = self.decimal.Decimal
3506 Context = self.decimal.Context
3507
3508 c = Context()
3509 d = c.to_integral_exact(Decimal(10))
3510 self.assertEqual(c.to_integral_exact(10), d)
3511 self.assertRaises(TypeError, c.to_integral_exact, '10')
3512
3513 def test_to_integral_value(self):
3514 Decimal = self.decimal.Decimal
3515 Context = self.decimal.Context
3516
3517 c = Context()
3518 d = c.to_integral_value(Decimal(10))
3519 self.assertEqual(c.to_integral_value(10), d)
3520 self.assertRaises(TypeError, c.to_integral_value, '10')
3521 self.assertRaises(TypeError, c.to_integral_value, 10, 'x')
3522
3523class CContextAPItests(ContextAPItests):
3524 decimal = C
3525class PyContextAPItests(ContextAPItests):
3526 decimal = P
3527
3528class ContextWithStatement(unittest.TestCase):
3529 # Can't do these as docstrings until Python 2.6
3530 # as doctest can't handle __future__ statements
3531
3532 def test_localcontext(self):
3533 # Use a copy of the current context in the block
3534 getcontext = self.decimal.getcontext
3535 localcontext = self.decimal.localcontext
3536
3537 orig_ctx = getcontext()
3538 with localcontext() as enter_ctx:
3539 set_ctx = getcontext()
3540 final_ctx = getcontext()
3541 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
3542 self.assertIsNot(orig_ctx, set_ctx, 'did not copy the context')
3543 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
3544
3545 def test_localcontextarg(self):
3546 # Use a copy of the supplied context in the block
3547 Context = self.decimal.Context
3548 getcontext = self.decimal.getcontext
3549 localcontext = self.decimal.localcontext
3550
3551 localcontext = self.decimal.localcontext
3552 orig_ctx = getcontext()
3553 new_ctx = Context(prec=42)
3554 with localcontext(new_ctx) as enter_ctx:
3555 set_ctx = getcontext()
3556 final_ctx = getcontext()
3557 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
3558 self.assertEqual(set_ctx.prec, new_ctx.prec, 'did not set correct context')
3559 self.assertIsNot(new_ctx, set_ctx, 'did not copy the context')
3560 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
3561
3562 def test_nested_with_statements(self):
3563 # Use a copy of the supplied context in the block
3564 Decimal = self.decimal.Decimal
3565 Context = self.decimal.Context
3566 getcontext = self.decimal.getcontext
3567 localcontext = self.decimal.localcontext
3568 Clamped = self.decimal.Clamped
3569 Overflow = self.decimal.Overflow
3570
3571 orig_ctx = getcontext()
3572 orig_ctx.clear_flags()
3573 new_ctx = Context(Emax=384)
3574 with localcontext() as c1:
3575 self.assertEqual(c1.flags, orig_ctx.flags)
3576 self.assertEqual(c1.traps, orig_ctx.traps)
3577 c1.traps[Clamped] = True
3578 c1.Emin = -383
3579 self.assertNotEqual(orig_ctx.Emin, -383)
3580 self.assertRaises(Clamped, c1.create_decimal, '0e-999')
3581 self.assertTrue(c1.flags[Clamped])
3582 with localcontext(new_ctx) as c2:
3583 self.assertEqual(c2.flags, new_ctx.flags)
3584 self.assertEqual(c2.traps, new_ctx.traps)
3585 self.assertRaises(Overflow, c2.power, Decimal('3.4e200'), 2)
3586 self.assertFalse(c2.flags[Clamped])
3587 self.assertTrue(c2.flags[Overflow])
3588 del c2
3589 self.assertFalse(c1.flags[Overflow])
3590 del c1
3591 self.assertNotEqual(orig_ctx.Emin, -383)
3592 self.assertFalse(orig_ctx.flags[Clamped])
3593 self.assertFalse(orig_ctx.flags[Overflow])
3594 self.assertFalse(new_ctx.flags[Clamped])
3595 self.assertFalse(new_ctx.flags[Overflow])
3596
3597 def test_with_statements_gc1(self):
3598 localcontext = self.decimal.localcontext
3599
3600 with localcontext() as c1:
3601 del c1
3602 with localcontext() as c2:
3603 del c2
3604 with localcontext() as c3:
3605 del c3
3606 with localcontext() as c4:
3607 del c4
3608
3609 def test_with_statements_gc2(self):
3610 localcontext = self.decimal.localcontext
3611
3612 with localcontext() as c1:
3613 with localcontext(c1) as c2:
3614 del c1
3615 with localcontext(c2) as c3:
3616 del c2
3617 with localcontext(c3) as c4:
3618 del c3
3619 del c4
3620
3621 def test_with_statements_gc3(self):
3622 Context = self.decimal.Context
3623 localcontext = self.decimal.localcontext
3624 getcontext = self.decimal.getcontext
3625 setcontext = self.decimal.setcontext
3626
3627 with localcontext() as c1:
3628 del c1
3629 n1 = Context(prec=1)
3630 setcontext(n1)
3631 with localcontext(n1) as c2:
3632 del n1
3633 self.assertEqual(c2.prec, 1)
3634 del c2
3635 n2 = Context(prec=2)
3636 setcontext(n2)
3637 del n2
3638 self.assertEqual(getcontext().prec, 2)
3639 n3 = Context(prec=3)
3640 setcontext(n3)
3641 self.assertEqual(getcontext().prec, 3)
3642 with localcontext(n3) as c3:
3643 del n3
3644 self.assertEqual(c3.prec, 3)
3645 del c3
3646 n4 = Context(prec=4)
3647 setcontext(n4)
3648 del n4
3649 self.assertEqual(getcontext().prec, 4)
3650 with localcontext() as c4:
3651 self.assertEqual(c4.prec, 4)
3652 del c4
3653
3654class CContextWithStatement(ContextWithStatement):
3655 decimal = C
3656class PyContextWithStatement(ContextWithStatement):
3657 decimal = P
3658
3659class ContextFlags(unittest.TestCase):
3660
3661 def test_flags_irrelevant(self):
3662 # check that the result (numeric result + flags raised) of an
3663 # arithmetic operation doesn't depend on the current flags
3664 Decimal = self.decimal.Decimal
3665 Context = self.decimal.Context
3666 Inexact = self.decimal.Inexact
3667 Rounded = self.decimal.Rounded
3668 Underflow = self.decimal.Underflow
3669 Clamped = self.decimal.Clamped
3670 Subnormal = self.decimal.Subnormal
Stefan Krah1919b7e2012-03-21 18:25:23 +01003671
3672 def raise_error(context, flag):
3673 if self.decimal == C:
3674 context.flags[flag] = True
3675 if context.traps[flag]:
3676 raise flag
3677 else:
3678 context._raise_error(flag)
3679
3680 context = Context(prec=9, Emin = -425000000, Emax = 425000000,
3681 rounding=ROUND_HALF_EVEN, traps=[], flags=[])
3682
3683 # operations that raise various flags, in the form (function, arglist)
3684 operations = [
3685 (context._apply, [Decimal("100E-425000010")]),
3686 (context.sqrt, [Decimal(2)]),
3687 (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]),
3688 (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]),
3689 (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]),
3690 ]
3691
3692 # try various flags individually, then a whole lot at once
3693 flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal],
3694 [Inexact, Rounded, Underflow, Clamped, Subnormal]]
3695
3696 for fn, args in operations:
3697 # find answer and flags raised using a clean context
3698 context.clear_flags()
3699 ans = fn(*args)
3700 flags = [k for k, v in context.flags.items() if v]
3701
3702 for extra_flags in flagsets:
3703 # set flags, before calling operation
3704 context.clear_flags()
3705 for flag in extra_flags:
3706 raise_error(context, flag)
3707 new_ans = fn(*args)
3708
3709 # flags that we expect to be set after the operation
3710 expected_flags = list(flags)
3711 for flag in extra_flags:
3712 if flag not in expected_flags:
3713 expected_flags.append(flag)
3714 expected_flags.sort(key=id)
3715
3716 # flags we actually got
3717 new_flags = [k for k,v in context.flags.items() if v]
3718 new_flags.sort(key=id)
3719
3720 self.assertEqual(ans, new_ans,
3721 "operation produces different answers depending on flags set: " +
3722 "expected %s, got %s." % (ans, new_ans))
3723 self.assertEqual(new_flags, expected_flags,
3724 "operation raises different flags depending on flags set: " +
3725 "expected %s, got %s" % (expected_flags, new_flags))
3726
3727 def test_flag_comparisons(self):
3728 Context = self.decimal.Context
3729 Inexact = self.decimal.Inexact
3730 Rounded = self.decimal.Rounded
3731
3732 c = Context()
3733
3734 # Valid SignalDict
3735 self.assertNotEqual(c.flags, c.traps)
3736 self.assertNotEqual(c.traps, c.flags)
3737
3738 c.flags = c.traps
3739 self.assertEqual(c.flags, c.traps)
3740 self.assertEqual(c.traps, c.flags)
3741
3742 c.flags[Rounded] = True
3743 c.traps = c.flags
3744 self.assertEqual(c.flags, c.traps)
3745 self.assertEqual(c.traps, c.flags)
3746
3747 d = {}
3748 d.update(c.flags)
3749 self.assertEqual(d, c.flags)
3750 self.assertEqual(c.flags, d)
3751
3752 d[Inexact] = True
3753 self.assertNotEqual(d, c.flags)
3754 self.assertNotEqual(c.flags, d)
3755
3756 # Invalid SignalDict
3757 d = {Inexact:False}
3758 self.assertNotEqual(d, c.flags)
3759 self.assertNotEqual(c.flags, d)
3760
3761 d = ["xyz"]
3762 self.assertNotEqual(d, c.flags)
3763 self.assertNotEqual(c.flags, d)
3764
3765 @requires_IEEE_754
3766 def test_float_operation(self):
3767 Decimal = self.decimal.Decimal
3768 FloatOperation = self.decimal.FloatOperation
3769 localcontext = self.decimal.localcontext
3770
3771 with localcontext() as c:
3772 ##### trap is off by default
3773 self.assertFalse(c.traps[FloatOperation])
3774
3775 # implicit conversion sets the flag
3776 c.clear_flags()
3777 self.assertEqual(Decimal(7.5), 7.5)
3778 self.assertTrue(c.flags[FloatOperation])
3779
3780 c.clear_flags()
3781 self.assertEqual(c.create_decimal(7.5), 7.5)
3782 self.assertTrue(c.flags[FloatOperation])
3783
3784 # explicit conversion does not set the flag
3785 c.clear_flags()
3786 x = Decimal.from_float(7.5)
3787 self.assertFalse(c.flags[FloatOperation])
3788 # comparison sets the flag
3789 self.assertEqual(x, 7.5)
3790 self.assertTrue(c.flags[FloatOperation])
3791
3792 c.clear_flags()
3793 x = c.create_decimal_from_float(7.5)
3794 self.assertFalse(c.flags[FloatOperation])
3795 self.assertEqual(x, 7.5)
3796 self.assertTrue(c.flags[FloatOperation])
3797
3798 ##### set the trap
3799 c.traps[FloatOperation] = True
3800
3801 # implicit conversion raises
3802 c.clear_flags()
3803 self.assertRaises(FloatOperation, Decimal, 7.5)
3804 self.assertTrue(c.flags[FloatOperation])
3805
3806 c.clear_flags()
3807 self.assertRaises(FloatOperation, c.create_decimal, 7.5)
3808 self.assertTrue(c.flags[FloatOperation])
3809
3810 # explicit conversion is silent
3811 c.clear_flags()
3812 x = Decimal.from_float(7.5)
3813 self.assertFalse(c.flags[FloatOperation])
3814
3815 c.clear_flags()
3816 x = c.create_decimal_from_float(7.5)
3817 self.assertFalse(c.flags[FloatOperation])
3818
3819 def test_float_comparison(self):
3820 Decimal = self.decimal.Decimal
3821 Context = self.decimal.Context
3822 FloatOperation = self.decimal.FloatOperation
3823 localcontext = self.decimal.localcontext
3824
3825 def assert_attr(a, b, attr, context, signal=None):
3826 context.clear_flags()
3827 f = getattr(a, attr)
3828 if signal == FloatOperation:
3829 self.assertRaises(signal, f, b)
3830 else:
3831 self.assertIs(f(b), True)
3832 self.assertTrue(context.flags[FloatOperation])
3833
3834 small_d = Decimal('0.25')
3835 big_d = Decimal('3.0')
3836 small_f = 0.25
3837 big_f = 3.0
3838
3839 zero_d = Decimal('0.0')
3840 neg_zero_d = Decimal('-0.0')
3841 zero_f = 0.0
3842 neg_zero_f = -0.0
3843
3844 inf_d = Decimal('Infinity')
3845 neg_inf_d = Decimal('-Infinity')
3846 inf_f = float('inf')
3847 neg_inf_f = float('-inf')
3848
3849 def doit(c, signal=None):
3850 # Order
3851 for attr in '__lt__', '__le__':
3852 assert_attr(small_d, big_f, attr, c, signal)
3853
3854 for attr in '__gt__', '__ge__':
3855 assert_attr(big_d, small_f, attr, c, signal)
3856
3857 # Equality
3858 assert_attr(small_d, small_f, '__eq__', c, None)
3859
3860 assert_attr(neg_zero_d, neg_zero_f, '__eq__', c, None)
3861 assert_attr(neg_zero_d, zero_f, '__eq__', c, None)
3862
3863 assert_attr(zero_d, neg_zero_f, '__eq__', c, None)
3864 assert_attr(zero_d, zero_f, '__eq__', c, None)
3865
3866 assert_attr(neg_inf_d, neg_inf_f, '__eq__', c, None)
3867 assert_attr(inf_d, inf_f, '__eq__', c, None)
3868
3869 # Inequality
3870 assert_attr(small_d, big_f, '__ne__', c, None)
3871
3872 assert_attr(Decimal('0.1'), 0.1, '__ne__', c, None)
3873
3874 assert_attr(neg_inf_d, inf_f, '__ne__', c, None)
3875 assert_attr(inf_d, neg_inf_f, '__ne__', c, None)
3876
3877 assert_attr(Decimal('NaN'), float('nan'), '__ne__', c, None)
3878
3879 def test_containers(c, signal=None):
3880 c.clear_flags()
3881 s = set([100.0, Decimal('100.0')])
3882 self.assertEqual(len(s), 1)
3883 self.assertTrue(c.flags[FloatOperation])
3884
3885 c.clear_flags()
3886 if signal:
3887 self.assertRaises(signal, sorted, [1.0, Decimal('10.0')])
3888 else:
3889 s = sorted([10.0, Decimal('10.0')])
3890 self.assertTrue(c.flags[FloatOperation])
3891
3892 c.clear_flags()
3893 b = 10.0 in [Decimal('10.0'), 1.0]
3894 self.assertTrue(c.flags[FloatOperation])
3895
3896 c.clear_flags()
3897 b = 10.0 in {Decimal('10.0'):'a', 1.0:'b'}
3898 self.assertTrue(c.flags[FloatOperation])
3899
3900 nc = Context()
3901 with localcontext(nc) as c:
3902 self.assertFalse(c.traps[FloatOperation])
3903 doit(c, signal=None)
3904 test_containers(c, signal=None)
3905
3906 c.traps[FloatOperation] = True
3907 doit(c, signal=FloatOperation)
3908 test_containers(c, signal=FloatOperation)
3909
3910 def test_float_operation_default(self):
3911 Decimal = self.decimal.Decimal
3912 Context = self.decimal.Context
3913 Inexact = self.decimal.Inexact
3914 FloatOperation= self.decimal.FloatOperation
3915
3916 context = Context()
3917 self.assertFalse(context.flags[FloatOperation])
3918 self.assertFalse(context.traps[FloatOperation])
3919
3920 context.clear_traps()
3921 context.traps[Inexact] = True
3922 context.traps[FloatOperation] = True
3923 self.assertTrue(context.traps[FloatOperation])
3924 self.assertTrue(context.traps[Inexact])
3925
3926class CContextFlags(ContextFlags):
3927 decimal = C
3928class PyContextFlags(ContextFlags):
3929 decimal = P
3930
3931class SpecialContexts(unittest.TestCase):
3932 """Test the context templates."""
3933
3934 def test_context_templates(self):
3935 BasicContext = self.decimal.BasicContext
3936 ExtendedContext = self.decimal.ExtendedContext
3937 getcontext = self.decimal.getcontext
3938 setcontext = self.decimal.setcontext
3939 InvalidOperation = self.decimal.InvalidOperation
3940 DivisionByZero = self.decimal.DivisionByZero
3941 Overflow = self.decimal.Overflow
3942 Underflow = self.decimal.Underflow
3943 Clamped = self.decimal.Clamped
3944
3945 assert_signals(self, BasicContext, 'traps',
3946 [InvalidOperation, DivisionByZero, Overflow, Underflow, Clamped]
3947 )
3948
3949 savecontext = getcontext().copy()
3950 basic_context_prec = BasicContext.prec
3951 extended_context_prec = ExtendedContext.prec
3952
3953 ex = None
3954 try:
3955 BasicContext.prec = ExtendedContext.prec = 441
3956 for template in BasicContext, ExtendedContext:
3957 setcontext(template)
3958 c = getcontext()
3959 self.assertIsNot(c, template)
3960 self.assertEqual(c.prec, 441)
3961 except Exception as e:
3962 ex = e.__class__
3963 finally:
3964 BasicContext.prec = basic_context_prec
3965 ExtendedContext.prec = extended_context_prec
3966 setcontext(savecontext)
3967 if ex:
3968 raise ex
3969
3970 def test_default_context(self):
3971 DefaultContext = self.decimal.DefaultContext
3972 BasicContext = self.decimal.BasicContext
3973 ExtendedContext = self.decimal.ExtendedContext
3974 getcontext = self.decimal.getcontext
3975 setcontext = self.decimal.setcontext
3976 InvalidOperation = self.decimal.InvalidOperation
3977 DivisionByZero = self.decimal.DivisionByZero
3978 Overflow = self.decimal.Overflow
3979
3980 self.assertEqual(BasicContext.prec, 9)
3981 self.assertEqual(ExtendedContext.prec, 9)
3982
3983 assert_signals(self, DefaultContext, 'traps',
3984 [InvalidOperation, DivisionByZero, Overflow]
3985 )
3986
3987 savecontext = getcontext().copy()
3988 default_context_prec = DefaultContext.prec
3989
3990 ex = None
3991 try:
3992 c = getcontext()
3993 saveprec = c.prec
3994
3995 DefaultContext.prec = 961
3996 c = getcontext()
3997 self.assertEqual(c.prec, saveprec)
3998
3999 setcontext(DefaultContext)
4000 c = getcontext()
4001 self.assertIsNot(c, DefaultContext)
4002 self.assertEqual(c.prec, 961)
4003 except Exception as e:
4004 ex = e.__class__
4005 finally:
4006 DefaultContext.prec = default_context_prec
4007 setcontext(savecontext)
4008 if ex:
4009 raise ex
4010
4011class CSpecialContexts(SpecialContexts):
4012 decimal = C
4013class PySpecialContexts(SpecialContexts):
4014 decimal = P
4015
4016class ContextInputValidation(unittest.TestCase):
4017
4018 def test_invalid_context(self):
4019 Context = self.decimal.Context
4020 DefaultContext = self.decimal.DefaultContext
4021
4022 c = DefaultContext.copy()
4023
4024 # prec, Emax
4025 for attr in ['prec', 'Emax']:
4026 setattr(c, attr, 999999)
4027 self.assertEqual(getattr(c, attr), 999999)
4028 self.assertRaises(ValueError, setattr, c, attr, -1)
4029 self.assertRaises(TypeError, setattr, c, attr, 'xyz')
4030
4031 # Emin
4032 setattr(c, 'Emin', -999999)
4033 self.assertEqual(getattr(c, 'Emin'), -999999)
4034 self.assertRaises(ValueError, setattr, c, 'Emin', 1)
4035 self.assertRaises(TypeError, setattr, c, 'Emin', (1,2,3))
4036
Stefan Krah1919b7e2012-03-21 18:25:23 +01004037 self.assertRaises(TypeError, setattr, c, 'rounding', -1)
4038 self.assertRaises(TypeError, setattr, c, 'rounding', 9)
4039 self.assertRaises(TypeError, setattr, c, 'rounding', 1.0)
4040 self.assertRaises(TypeError, setattr, c, 'rounding', 'xyz')
4041
4042 # capitals, clamp
4043 for attr in ['capitals', 'clamp']:
4044 self.assertRaises(ValueError, setattr, c, attr, -1)
4045 self.assertRaises(ValueError, setattr, c, attr, 2)
4046 self.assertRaises(TypeError, setattr, c, attr, [1,2,3])
4047
4048 # Invalid attribute
4049 self.assertRaises(AttributeError, setattr, c, 'emax', 100)
4050
4051 # Invalid signal dict
4052 self.assertRaises(TypeError, setattr, c, 'flags', [])
4053 self.assertRaises(KeyError, setattr, c, 'flags', {})
4054 self.assertRaises(KeyError, setattr, c, 'traps',
4055 {'InvalidOperation':0})
4056
4057 # Attributes cannot be deleted
4058 for attr in ['prec', 'Emax', 'Emin', 'rounding', 'capitals', 'clamp',
4059 'flags', 'traps']:
4060 self.assertRaises(AttributeError, c.__delattr__, attr)
4061
4062 # Invalid attributes
4063 self.assertRaises(TypeError, getattr, c, 9)
4064 self.assertRaises(TypeError, setattr, c, 9)
4065
4066 # Invalid values in constructor
4067 self.assertRaises(TypeError, Context, rounding=999999)
4068 self.assertRaises(TypeError, Context, rounding='xyz')
4069 self.assertRaises(ValueError, Context, clamp=2)
4070 self.assertRaises(ValueError, Context, capitals=-1)
4071 self.assertRaises(KeyError, Context, flags=["P"])
4072 self.assertRaises(KeyError, Context, traps=["Q"])
4073
4074 # Type error in conversion
4075 self.assertRaises(TypeError, Context, flags=(0,1))
4076 self.assertRaises(TypeError, Context, traps=(1,0))
4077
4078class CContextInputValidation(ContextInputValidation):
4079 decimal = C
4080class PyContextInputValidation(ContextInputValidation):
4081 decimal = P
4082
4083class ContextSubclassing(unittest.TestCase):
4084
4085 def test_context_subclassing(self):
4086 decimal = self.decimal
4087 Decimal = decimal.Decimal
4088 Context = decimal.Context
Stefan Krah1919b7e2012-03-21 18:25:23 +01004089 Clamped = decimal.Clamped
4090 DivisionByZero = decimal.DivisionByZero
4091 Inexact = decimal.Inexact
4092 Overflow = decimal.Overflow
4093 Rounded = decimal.Rounded
4094 Subnormal = decimal.Subnormal
4095 Underflow = decimal.Underflow
4096 InvalidOperation = decimal.InvalidOperation
4097
4098 class MyContext(Context):
4099 def __init__(self, prec=None, rounding=None, Emin=None, Emax=None,
4100 capitals=None, clamp=None, flags=None,
4101 traps=None):
4102 Context.__init__(self)
4103 if prec is not None:
4104 self.prec = prec
4105 if rounding is not None:
4106 self.rounding = rounding
4107 if Emin is not None:
4108 self.Emin = Emin
4109 if Emax is not None:
4110 self.Emax = Emax
4111 if capitals is not None:
4112 self.capitals = capitals
4113 if clamp is not None:
4114 self.clamp = clamp
4115 if flags is not None:
4116 if isinstance(flags, list):
4117 flags = {v:(v in flags) for v in OrderedSignals[decimal] + flags}
4118 self.flags = flags
4119 if traps is not None:
4120 if isinstance(traps, list):
4121 traps = {v:(v in traps) for v in OrderedSignals[decimal] + traps}
4122 self.traps = traps
4123
4124 c = Context()
4125 d = MyContext()
4126 for attr in ('prec', 'rounding', 'Emin', 'Emax', 'capitals', 'clamp',
4127 'flags', 'traps'):
4128 self.assertEqual(getattr(c, attr), getattr(d, attr))
4129
4130 # prec
4131 self.assertRaises(ValueError, MyContext, **{'prec':-1})
4132 c = MyContext(prec=1)
4133 self.assertEqual(c.prec, 1)
4134 self.assertRaises(InvalidOperation, c.quantize, Decimal('9e2'), 0)
4135
4136 # rounding
4137 self.assertRaises(TypeError, MyContext, **{'rounding':'XYZ'})
4138 c = MyContext(rounding=ROUND_DOWN, prec=1)
4139 self.assertEqual(c.rounding, ROUND_DOWN)
4140 self.assertEqual(c.plus(Decimal('9.9')), 9)
4141
4142 # Emin
4143 self.assertRaises(ValueError, MyContext, **{'Emin':5})
4144 c = MyContext(Emin=-1, prec=1)
4145 self.assertEqual(c.Emin, -1)
4146 x = c.add(Decimal('1e-99'), Decimal('2.234e-2000'))
4147 self.assertEqual(x, Decimal('0.0'))
4148 for signal in (Inexact, Underflow, Subnormal, Rounded, Clamped):
4149 self.assertTrue(c.flags[signal])
4150
4151 # Emax
4152 self.assertRaises(ValueError, MyContext, **{'Emax':-1})
4153 c = MyContext(Emax=1, prec=1)
4154 self.assertEqual(c.Emax, 1)
4155 self.assertRaises(Overflow, c.add, Decimal('1e99'), Decimal('2.234e2000'))
4156 if self.decimal == C:
4157 for signal in (Inexact, Overflow, Rounded):
4158 self.assertTrue(c.flags[signal])
4159
4160 # capitals
4161 self.assertRaises(ValueError, MyContext, **{'capitals':-1})
4162 c = MyContext(capitals=0)
4163 self.assertEqual(c.capitals, 0)
4164 x = c.create_decimal('1E222')
4165 self.assertEqual(c.to_sci_string(x), '1e+222')
4166
4167 # clamp
4168 self.assertRaises(ValueError, MyContext, **{'clamp':2})
4169 c = MyContext(clamp=1, Emax=99)
4170 self.assertEqual(c.clamp, 1)
4171 x = c.plus(Decimal('1e99'))
4172 self.assertEqual(str(x), '1.000000000000000000000000000E+99')
4173
4174 # flags
4175 self.assertRaises(TypeError, MyContext, **{'flags':'XYZ'})
4176 c = MyContext(flags=[Rounded, DivisionByZero])
4177 for signal in (Rounded, DivisionByZero):
4178 self.assertTrue(c.flags[signal])
4179 c.clear_flags()
4180 for signal in OrderedSignals[decimal]:
4181 self.assertFalse(c.flags[signal])
4182
4183 # traps
4184 self.assertRaises(TypeError, MyContext, **{'traps':'XYZ'})
4185 c = MyContext(traps=[Rounded, DivisionByZero])
4186 for signal in (Rounded, DivisionByZero):
4187 self.assertTrue(c.traps[signal])
4188 c.clear_traps()
4189 for signal in OrderedSignals[decimal]:
4190 self.assertFalse(c.traps[signal])
4191
4192class CContextSubclassing(ContextSubclassing):
4193 decimal = C
4194class PyContextSubclassing(ContextSubclassing):
4195 decimal = P
4196
4197@skip_if_extra_functionality
4198class CheckAttributes(unittest.TestCase):
4199
4200 def test_module_attributes(self):
4201
4202 # Architecture dependent context limits
4203 self.assertEqual(C.MAX_PREC, P.MAX_PREC)
4204 self.assertEqual(C.MAX_EMAX, P.MAX_EMAX)
4205 self.assertEqual(C.MIN_EMIN, P.MIN_EMIN)
4206 self.assertEqual(C.MIN_ETINY, P.MIN_ETINY)
4207
4208 self.assertTrue(C.HAVE_THREADS is True or C.HAVE_THREADS is False)
4209 self.assertTrue(P.HAVE_THREADS is True or P.HAVE_THREADS is False)
4210
4211 self.assertEqual(C.__version__, P.__version__)
4212
Stefan Krahb578f8a2014-09-10 17:58:15 +02004213 self.assertEqual(dir(C), dir(P))
Stefan Krah1919b7e2012-03-21 18:25:23 +01004214
4215 def test_context_attributes(self):
4216
4217 x = [s for s in dir(C.Context()) if '__' in s or not s.startswith('_')]
4218 y = [s for s in dir(P.Context()) if '__' in s or not s.startswith('_')]
4219 self.assertEqual(set(x) - set(y), set())
4220
4221 def test_decimal_attributes(self):
4222
4223 x = [s for s in dir(C.Decimal(9)) if '__' in s or not s.startswith('_')]
4224 y = [s for s in dir(C.Decimal(9)) if '__' in s or not s.startswith('_')]
4225 self.assertEqual(set(x) - set(y), set())
4226
4227class Coverage(unittest.TestCase):
4228
4229 def test_adjusted(self):
4230 Decimal = self.decimal.Decimal
4231
4232 self.assertEqual(Decimal('1234e9999').adjusted(), 10002)
4233 # XXX raise?
4234 self.assertEqual(Decimal('nan').adjusted(), 0)
4235 self.assertEqual(Decimal('inf').adjusted(), 0)
4236
4237 def test_canonical(self):
4238 Decimal = self.decimal.Decimal
4239 getcontext = self.decimal.getcontext
4240
4241 x = Decimal(9).canonical()
4242 self.assertEqual(x, 9)
4243
4244 c = getcontext()
4245 x = c.canonical(Decimal(9))
4246 self.assertEqual(x, 9)
4247
4248 def test_context_repr(self):
4249 c = self.decimal.DefaultContext.copy()
4250
4251 c.prec = 425000000
4252 c.Emax = 425000000
4253 c.Emin = -425000000
Stefan Krah59a4a932013-01-16 12:58:59 +01004254 c.rounding = ROUND_HALF_DOWN
Stefan Krah1919b7e2012-03-21 18:25:23 +01004255 c.capitals = 0
4256 c.clamp = 1
4257 for sig in OrderedSignals[self.decimal]:
4258 c.flags[sig] = False
4259 c.traps[sig] = False
4260
4261 s = c.__repr__()
4262 t = "Context(prec=425000000, rounding=ROUND_HALF_DOWN, " \
4263 "Emin=-425000000, Emax=425000000, capitals=0, clamp=1, " \
4264 "flags=[], traps=[])"
4265 self.assertEqual(s, t)
4266
4267 def test_implicit_context(self):
4268 Decimal = self.decimal.Decimal
4269 localcontext = self.decimal.localcontext
4270
4271 with localcontext() as c:
4272 c.prec = 1
4273 c.Emax = 1
4274 c.Emin = -1
4275
4276 # abs
4277 self.assertEqual(abs(Decimal("-10")), 10)
4278 # add
4279 self.assertEqual(Decimal("7") + 1, 8)
4280 # divide
4281 self.assertEqual(Decimal("10") / 5, 2)
4282 # divide_int
4283 self.assertEqual(Decimal("10") // 7, 1)
4284 # fma
4285 self.assertEqual(Decimal("1.2").fma(Decimal("0.01"), 1), 1)
4286 self.assertIs(Decimal("NaN").fma(7, 1).is_nan(), True)
4287 # three arg power
4288 self.assertEqual(pow(Decimal(10), 2, 7), 2)
4289 # exp
4290 self.assertEqual(Decimal("1.01").exp(), 3)
4291 # is_normal
4292 self.assertIs(Decimal("0.01").is_normal(), False)
4293 # is_subnormal
4294 self.assertIs(Decimal("0.01").is_subnormal(), True)
4295 # ln
4296 self.assertEqual(Decimal("20").ln(), 3)
4297 # log10
4298 self.assertEqual(Decimal("20").log10(), 1)
4299 # logb
4300 self.assertEqual(Decimal("580").logb(), 2)
4301 # logical_invert
4302 self.assertEqual(Decimal("10").logical_invert(), 1)
4303 # minus
4304 self.assertEqual(-Decimal("-10"), 10)
4305 # multiply
4306 self.assertEqual(Decimal("2") * 4, 8)
4307 # next_minus
4308 self.assertEqual(Decimal("10").next_minus(), 9)
4309 # next_plus
4310 self.assertEqual(Decimal("10").next_plus(), Decimal('2E+1'))
4311 # normalize
4312 self.assertEqual(Decimal("-10").normalize(), Decimal('-1E+1'))
4313 # number_class
4314 self.assertEqual(Decimal("10").number_class(), '+Normal')
4315 # plus
4316 self.assertEqual(+Decimal("-1"), -1)
4317 # remainder
4318 self.assertEqual(Decimal("10") % 7, 3)
4319 # subtract
4320 self.assertEqual(Decimal("10") - 7, 3)
4321 # to_integral_exact
4322 self.assertEqual(Decimal("1.12345").to_integral_exact(), 1)
4323
4324 # Boolean functions
4325 self.assertTrue(Decimal("1").is_canonical())
4326 self.assertTrue(Decimal("1").is_finite())
4327 self.assertTrue(Decimal("1").is_finite())
4328 self.assertTrue(Decimal("snan").is_snan())
4329 self.assertTrue(Decimal("-1").is_signed())
4330 self.assertTrue(Decimal("0").is_zero())
4331 self.assertTrue(Decimal("0").is_zero())
4332
4333 # Copy
4334 with localcontext() as c:
4335 c.prec = 10000
4336 x = 1228 ** 1523
4337 y = -Decimal(x)
4338
4339 z = y.copy_abs()
4340 self.assertEqual(z, x)
4341
4342 z = y.copy_negate()
4343 self.assertEqual(z, x)
4344
4345 z = y.copy_sign(Decimal(1))
4346 self.assertEqual(z, x)
4347
4348 def test_divmod(self):
4349 Decimal = self.decimal.Decimal
4350 localcontext = self.decimal.localcontext
4351 InvalidOperation = self.decimal.InvalidOperation
4352 DivisionByZero = self.decimal.DivisionByZero
4353
4354 with localcontext() as c:
4355 q, r = divmod(Decimal("10912837129"), 1001)
4356 self.assertEqual(q, Decimal('10901935'))
4357 self.assertEqual(r, Decimal('194'))
4358
4359 q, r = divmod(Decimal("NaN"), 7)
4360 self.assertTrue(q.is_nan() and r.is_nan())
4361
4362 c.traps[InvalidOperation] = False
4363 q, r = divmod(Decimal("NaN"), 7)
4364 self.assertTrue(q.is_nan() and r.is_nan())
4365
4366 c.traps[InvalidOperation] = False
4367 c.clear_flags()
4368 q, r = divmod(Decimal("inf"), Decimal("inf"))
4369 self.assertTrue(q.is_nan() and r.is_nan())
4370 self.assertTrue(c.flags[InvalidOperation])
4371
4372 c.clear_flags()
4373 q, r = divmod(Decimal("inf"), 101)
4374 self.assertTrue(q.is_infinite() and r.is_nan())
4375 self.assertTrue(c.flags[InvalidOperation])
4376
4377 c.clear_flags()
4378 q, r = divmod(Decimal(0), 0)
4379 self.assertTrue(q.is_nan() and r.is_nan())
4380 self.assertTrue(c.flags[InvalidOperation])
4381
4382 c.traps[DivisionByZero] = False
4383 c.clear_flags()
4384 q, r = divmod(Decimal(11), 0)
4385 self.assertTrue(q.is_infinite() and r.is_nan())
4386 self.assertTrue(c.flags[InvalidOperation] and
4387 c.flags[DivisionByZero])
4388
4389 def test_power(self):
4390 Decimal = self.decimal.Decimal
4391 localcontext = self.decimal.localcontext
4392 Overflow = self.decimal.Overflow
4393 Rounded = self.decimal.Rounded
4394
4395 with localcontext() as c:
4396 c.prec = 3
4397 c.clear_flags()
4398 self.assertEqual(Decimal("1.0") ** 100, Decimal('1.00'))
4399 self.assertTrue(c.flags[Rounded])
4400
4401 c.prec = 1
4402 c.Emax = 1
4403 c.Emin = -1
4404 c.clear_flags()
4405 c.traps[Overflow] = False
4406 self.assertEqual(Decimal(10000) ** Decimal("0.5"), Decimal('inf'))
4407 self.assertTrue(c.flags[Overflow])
4408
4409 def test_quantize(self):
4410 Decimal = self.decimal.Decimal
4411 localcontext = self.decimal.localcontext
4412 InvalidOperation = self.decimal.InvalidOperation
4413
4414 with localcontext() as c:
4415 c.prec = 1
4416 c.Emax = 1
4417 c.Emin = -1
4418 c.traps[InvalidOperation] = False
4419 x = Decimal(99).quantize(Decimal("1e1"))
4420 self.assertTrue(x.is_nan())
4421
4422 def test_radix(self):
4423 Decimal = self.decimal.Decimal
4424 getcontext = self.decimal.getcontext
4425
4426 c = getcontext()
4427 self.assertEqual(Decimal("1").radix(), 10)
4428 self.assertEqual(c.radix(), 10)
4429
4430 def test_rop(self):
4431 Decimal = self.decimal.Decimal
4432
4433 for attr in ('__radd__', '__rsub__', '__rmul__', '__rtruediv__',
4434 '__rdivmod__', '__rmod__', '__rfloordiv__', '__rpow__'):
4435 self.assertIs(getattr(Decimal("1"), attr)("xyz"), NotImplemented)
4436
4437 def test_round(self):
4438 # Python3 behavior: round() returns Decimal
4439 Decimal = self.decimal.Decimal
4440 getcontext = self.decimal.getcontext
4441
4442 c = getcontext()
4443 c.prec = 28
4444
4445 self.assertEqual(str(Decimal("9.99").__round__()), "10")
4446 self.assertEqual(str(Decimal("9.99e-5").__round__()), "0")
4447 self.assertEqual(str(Decimal("1.23456789").__round__(5)), "1.23457")
4448 self.assertEqual(str(Decimal("1.2345").__round__(10)), "1.2345000000")
4449 self.assertEqual(str(Decimal("1.2345").__round__(-10)), "0E+10")
4450
4451 self.assertRaises(TypeError, Decimal("1.23").__round__, "5")
4452 self.assertRaises(TypeError, Decimal("1.23").__round__, 5, 8)
4453
4454 def test_create_decimal(self):
4455 c = self.decimal.Context()
4456 self.assertRaises(ValueError, c.create_decimal, ["%"])
4457
4458 def test_int(self):
4459 Decimal = self.decimal.Decimal
4460 localcontext = self.decimal.localcontext
4461
4462 with localcontext() as c:
4463 c.prec = 9999
4464 x = Decimal(1221**1271) / 10**3923
4465 self.assertEqual(int(x), 1)
4466 self.assertEqual(x.to_integral(), 2)
4467
4468 def test_copy(self):
4469 Context = self.decimal.Context
4470
4471 c = Context()
4472 c.prec = 10000
4473 x = -(1172 ** 1712)
4474
4475 y = c.copy_abs(x)
4476 self.assertEqual(y, -x)
4477
4478 y = c.copy_negate(x)
4479 self.assertEqual(y, -x)
4480
4481 y = c.copy_sign(x, 1)
4482 self.assertEqual(y, -x)
4483
4484class CCoverage(Coverage):
4485 decimal = C
4486class PyCoverage(Coverage):
4487 decimal = P
4488
4489class PyFunctionality(unittest.TestCase):
4490 """Extra functionality in decimal.py"""
4491
Stefan Krah1919b7e2012-03-21 18:25:23 +01004492 def test_py_alternate_formatting(self):
4493 # triples giving a format, a Decimal, and the expected result
4494 Decimal = P.Decimal
4495 localcontext = P.localcontext
4496
4497 test_values = [
4498 # Issue 7094: Alternate formatting (specified by #)
4499 ('.0e', '1.0', '1e+0'),
4500 ('#.0e', '1.0', '1.e+0'),
4501 ('.0f', '1.0', '1'),
4502 ('#.0f', '1.0', '1.'),
4503 ('g', '1.1', '1.1'),
4504 ('#g', '1.1', '1.1'),
4505 ('.0g', '1', '1'),
4506 ('#.0g', '1', '1.'),
4507 ('.0%', '1.0', '100%'),
4508 ('#.0%', '1.0', '100.%'),
4509 ]
4510 for fmt, d, result in test_values:
4511 self.assertEqual(format(Decimal(d), fmt), result)
4512
4513class PyWhitebox(unittest.TestCase):
4514 """White box testing for decimal.py"""
4515
4516 def test_py_exact_power(self):
4517 # Rarely exercised lines in _power_exact.
4518 Decimal = P.Decimal
4519 localcontext = P.localcontext
4520
4521 with localcontext() as c:
4522 c.prec = 8
4523 x = Decimal(2**16) ** Decimal("-0.5")
4524 self.assertEqual(x, Decimal('0.00390625'))
4525
4526 x = Decimal(2**16) ** Decimal("-0.6")
4527 self.assertEqual(x, Decimal('0.0012885819'))
4528
4529 x = Decimal("256e7") ** Decimal("-0.5")
4530
4531 x = Decimal(152587890625) ** Decimal('-0.0625')
4532 self.assertEqual(x, Decimal("0.2"))
4533
4534 x = Decimal("152587890625e7") ** Decimal('-0.0625')
4535
4536 x = Decimal(5**2659) ** Decimal('-0.0625')
4537
4538 c.prec = 1
4539 x = Decimal("152587890625") ** Decimal('-0.5')
4540 c.prec = 201
4541 x = Decimal(2**578) ** Decimal("-0.5")
4542
4543 def test_py_immutability_operations(self):
Terry Jan Reedy0f847642013-03-11 18:34:00 -04004544 # Do operations and check that it didn't change internal objects.
Stefan Krah1919b7e2012-03-21 18:25:23 +01004545 Decimal = P.Decimal
4546 DefaultContext = P.DefaultContext
4547 setcontext = P.setcontext
4548
4549 c = DefaultContext.copy()
4550 c.traps = dict((s, 0) for s in OrderedSignals[P])
4551 setcontext(c)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004552
4553 d1 = Decimal('-25e55')
4554 b1 = Decimal('-25e55')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004555 d2 = Decimal('33e+33')
4556 b2 = Decimal('33e+33')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004557
4558 def checkSameDec(operation, useOther=False):
4559 if useOther:
4560 eval("d1." + operation + "(d2)")
4561 self.assertEqual(d1._sign, b1._sign)
4562 self.assertEqual(d1._int, b1._int)
4563 self.assertEqual(d1._exp, b1._exp)
4564 self.assertEqual(d2._sign, b2._sign)
4565 self.assertEqual(d2._int, b2._int)
4566 self.assertEqual(d2._exp, b2._exp)
4567 else:
4568 eval("d1." + operation + "()")
4569 self.assertEqual(d1._sign, b1._sign)
4570 self.assertEqual(d1._int, b1._int)
4571 self.assertEqual(d1._exp, b1._exp)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004572
4573 Decimal(d1)
4574 self.assertEqual(d1._sign, b1._sign)
4575 self.assertEqual(d1._int, b1._int)
4576 self.assertEqual(d1._exp, b1._exp)
4577
4578 checkSameDec("__abs__")
4579 checkSameDec("__add__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004580 checkSameDec("__divmod__", True)
Christian Heimes77c02eb2008-02-09 02:18:51 +00004581 checkSameDec("__eq__", True)
4582 checkSameDec("__ne__", True)
4583 checkSameDec("__le__", True)
4584 checkSameDec("__lt__", True)
4585 checkSameDec("__ge__", True)
4586 checkSameDec("__gt__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004587 checkSameDec("__float__")
4588 checkSameDec("__floordiv__", True)
4589 checkSameDec("__hash__")
4590 checkSameDec("__int__")
Christian Heimes969fe572008-01-25 11:23:10 +00004591 checkSameDec("__trunc__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004592 checkSameDec("__mod__", True)
4593 checkSameDec("__mul__", True)
4594 checkSameDec("__neg__")
Jack Diederich4dafcc42006-11-28 19:15:13 +00004595 checkSameDec("__bool__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004596 checkSameDec("__pos__")
4597 checkSameDec("__pow__", True)
4598 checkSameDec("__radd__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004599 checkSameDec("__rdivmod__", True)
4600 checkSameDec("__repr__")
4601 checkSameDec("__rfloordiv__", True)
4602 checkSameDec("__rmod__", True)
4603 checkSameDec("__rmul__", True)
4604 checkSameDec("__rpow__", True)
4605 checkSameDec("__rsub__", True)
4606 checkSameDec("__str__")
4607 checkSameDec("__sub__", True)
4608 checkSameDec("__truediv__", True)
4609 checkSameDec("adjusted")
4610 checkSameDec("as_tuple")
4611 checkSameDec("compare", True)
4612 checkSameDec("max", True)
4613 checkSameDec("min", True)
4614 checkSameDec("normalize")
4615 checkSameDec("quantize", True)
4616 checkSameDec("remainder_near", True)
4617 checkSameDec("same_quantum", True)
4618 checkSameDec("sqrt")
4619 checkSameDec("to_eng_string")
4620 checkSameDec("to_integral")
4621
Stefan Krah1919b7e2012-03-21 18:25:23 +01004622 def test_py_decimal_id(self):
4623 Decimal = P.Decimal
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004624
Stefan Krah1919b7e2012-03-21 18:25:23 +01004625 d = Decimal(45)
4626 e = Decimal(d)
4627 self.assertEqual(str(e), '45')
4628 self.assertNotEqual(id(d), id(e))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004629
Stefan Krah1919b7e2012-03-21 18:25:23 +01004630 def test_py_rescale(self):
4631 # Coverage
4632 Decimal = P.Decimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01004633 localcontext = P.localcontext
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004634
Stefan Krah1919b7e2012-03-21 18:25:23 +01004635 with localcontext() as c:
4636 x = Decimal("NaN")._rescale(3, ROUND_UP)
4637 self.assertTrue(x.is_nan())
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004638
Stefan Krah1919b7e2012-03-21 18:25:23 +01004639 def test_py__round(self):
4640 # Coverage
4641 Decimal = P.Decimal
Christian Heimes0348fb62008-03-26 12:55:56 +00004642
Stefan Krah1919b7e2012-03-21 18:25:23 +01004643 self.assertRaises(ValueError, Decimal("3.1234")._round, 0, ROUND_UP)
Mark Dickinsona2d1fe02009-10-29 12:23:02 +00004644
Stefan Krah1919b7e2012-03-21 18:25:23 +01004645class CFunctionality(unittest.TestCase):
4646 """Extra functionality in _decimal"""
Mark Dickinsona2d1fe02009-10-29 12:23:02 +00004647
Stefan Krah1919b7e2012-03-21 18:25:23 +01004648 @requires_extra_functionality
4649 def test_c_ieee_context(self):
4650 # issue 8786: Add support for IEEE 754 contexts to decimal module.
4651 IEEEContext = C.IEEEContext
4652 DECIMAL32 = C.DECIMAL32
4653 DECIMAL64 = C.DECIMAL64
4654 DECIMAL128 = C.DECIMAL128
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004655
Stefan Krah1919b7e2012-03-21 18:25:23 +01004656 def assert_rest(self, context):
4657 self.assertEqual(context.clamp, 1)
4658 assert_signals(self, context, 'traps', [])
4659 assert_signals(self, context, 'flags', [])
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004660
Stefan Krah1919b7e2012-03-21 18:25:23 +01004661 c = IEEEContext(DECIMAL32)
4662 self.assertEqual(c.prec, 7)
4663 self.assertEqual(c.Emax, 96)
4664 self.assertEqual(c.Emin, -95)
4665 assert_rest(self, c)
Raymond Hettinger82417ca2009-02-03 03:54:28 +00004666
Stefan Krah1919b7e2012-03-21 18:25:23 +01004667 c = IEEEContext(DECIMAL64)
4668 self.assertEqual(c.prec, 16)
4669 self.assertEqual(c.Emax, 384)
4670 self.assertEqual(c.Emin, -383)
4671 assert_rest(self, c)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004672
Stefan Krah1919b7e2012-03-21 18:25:23 +01004673 c = IEEEContext(DECIMAL128)
4674 self.assertEqual(c.prec, 34)
4675 self.assertEqual(c.Emax, 6144)
4676 self.assertEqual(c.Emin, -6143)
4677 assert_rest(self, c)
Raymond Hettinger5548be22004-07-05 18:49:38 +00004678
Stefan Krah1919b7e2012-03-21 18:25:23 +01004679 # Invalid values
4680 self.assertRaises(OverflowError, IEEEContext, 2**63)
4681 self.assertRaises(ValueError, IEEEContext, -1)
4682 self.assertRaises(ValueError, IEEEContext, 1024)
Mark Dickinson825fce32009-09-07 18:08:12 +00004683
Stefan Krah1919b7e2012-03-21 18:25:23 +01004684 @requires_extra_functionality
4685 def test_c_context(self):
4686 Context = C.Context
Christian Heimes969fe572008-01-25 11:23:10 +00004687
Stefan Krah1919b7e2012-03-21 18:25:23 +01004688 c = Context(flags=C.DecClamped, traps=C.DecRounded)
4689 self.assertEqual(c._flags, C.DecClamped)
4690 self.assertEqual(c._traps, C.DecRounded)
Raymond Hettinger771ed762009-01-03 19:20:32 +00004691
Stefan Krah1919b7e2012-03-21 18:25:23 +01004692 @requires_extra_functionality
4693 def test_constants(self):
4694 # Condition flags
4695 cond = (
4696 C.DecClamped, C.DecConversionSyntax, C.DecDivisionByZero,
4697 C.DecDivisionImpossible, C.DecDivisionUndefined,
4698 C.DecFpuError, C.DecInexact, C.DecInvalidContext,
4699 C.DecInvalidOperation, C.DecMallocError,
4700 C.DecFloatOperation, C.DecOverflow, C.DecRounded,
4701 C.DecSubnormal, C.DecUnderflow
Raymond Hettinger771ed762009-01-03 19:20:32 +00004702 )
Stefan Krah1919b7e2012-03-21 18:25:23 +01004703
4704 # IEEEContext
4705 self.assertEqual(C.DECIMAL32, 32)
4706 self.assertEqual(C.DECIMAL64, 64)
4707 self.assertEqual(C.DECIMAL128, 128)
4708 self.assertEqual(C.IEEE_CONTEXT_MAX_BITS, 512)
4709
Stefan Krah1919b7e2012-03-21 18:25:23 +01004710 # Conditions
4711 for i, v in enumerate(cond):
4712 self.assertEqual(v, 1<<i)
4713
4714 self.assertEqual(C.DecIEEEInvalidOperation,
4715 C.DecConversionSyntax|
4716 C.DecDivisionImpossible|
4717 C.DecDivisionUndefined|
4718 C.DecFpuError|
4719 C.DecInvalidContext|
4720 C.DecInvalidOperation|
4721 C.DecMallocError)
4722
4723 self.assertEqual(C.DecErrors,
4724 C.DecIEEEInvalidOperation|
4725 C.DecDivisionByZero)
4726
4727 self.assertEqual(C.DecTraps,
4728 C.DecErrors|C.DecOverflow|C.DecUnderflow)
4729
4730class CWhitebox(unittest.TestCase):
4731 """Whitebox testing for _decimal"""
4732
4733 def test_bignum(self):
4734 # Not exactly whitebox, but too slow with pydecimal.
4735
4736 Decimal = C.Decimal
4737 localcontext = C.localcontext
4738
4739 b1 = 10**35
4740 b2 = 10**36
4741 with localcontext() as c:
4742 c.prec = 1000000
4743 for i in range(5):
4744 a = random.randrange(b1, b2)
4745 b = random.randrange(1000, 1200)
4746 x = a ** b
4747 y = Decimal(a) ** Decimal(b)
4748 self.assertEqual(x, y)
4749
4750 def test_invalid_construction(self):
4751 self.assertRaises(TypeError, C.Decimal, 9, "xyz")
4752
4753 def test_c_input_restriction(self):
4754 # Too large for _decimal to be converted exactly
4755 Decimal = C.Decimal
4756 InvalidOperation = C.InvalidOperation
4757 Context = C.Context
4758 localcontext = C.localcontext
4759
4760 with localcontext(Context()):
4761 self.assertRaises(InvalidOperation, Decimal,
4762 "1e9999999999999999999")
4763
4764 def test_c_context_repr(self):
4765 # This test is _decimal-only because flags are not printed
4766 # in the same order.
4767 DefaultContext = C.DefaultContext
4768 FloatOperation = C.FloatOperation
Stefan Krah1919b7e2012-03-21 18:25:23 +01004769
4770 c = DefaultContext.copy()
4771
4772 c.prec = 425000000
4773 c.Emax = 425000000
4774 c.Emin = -425000000
4775 c.rounding = ROUND_HALF_DOWN
4776 c.capitals = 0
4777 c.clamp = 1
4778 for sig in OrderedSignals[C]:
4779 c.flags[sig] = True
4780 c.traps[sig] = True
4781 c.flags[FloatOperation] = True
4782 c.traps[FloatOperation] = True
4783
4784 s = c.__repr__()
4785 t = "Context(prec=425000000, rounding=ROUND_HALF_DOWN, " \
4786 "Emin=-425000000, Emax=425000000, capitals=0, clamp=1, " \
4787 "flags=[Clamped, InvalidOperation, DivisionByZero, Inexact, " \
4788 "FloatOperation, Overflow, Rounded, Subnormal, Underflow], " \
4789 "traps=[Clamped, InvalidOperation, DivisionByZero, Inexact, " \
4790 "FloatOperation, Overflow, Rounded, Subnormal, Underflow])"
4791 self.assertEqual(s, t)
4792
4793 def test_c_context_errors(self):
4794 Context = C.Context
4795 InvalidOperation = C.InvalidOperation
4796 Overflow = C.Overflow
4797 FloatOperation = C.FloatOperation
4798 localcontext = C.localcontext
4799 getcontext = C.getcontext
4800 setcontext = C.setcontext
4801 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
4802
4803 c = Context()
4804
4805 # SignalDict: input validation
4806 self.assertRaises(KeyError, c.flags.__setitem__, 801, 0)
4807 self.assertRaises(KeyError, c.traps.__setitem__, 801, 0)
4808 self.assertRaises(ValueError, c.flags.__delitem__, Overflow)
4809 self.assertRaises(ValueError, c.traps.__delitem__, InvalidOperation)
4810 self.assertRaises(TypeError, setattr, c, 'flags', ['x'])
4811 self.assertRaises(TypeError, setattr, c,'traps', ['y'])
4812 self.assertRaises(KeyError, setattr, c, 'flags', {0:1})
4813 self.assertRaises(KeyError, setattr, c, 'traps', {0:1})
4814
4815 # Test assignment from a signal dict with the correct length but
4816 # one invalid key.
4817 d = c.flags.copy()
4818 del d[FloatOperation]
4819 d["XYZ"] = 91283719
4820 self.assertRaises(KeyError, setattr, c, 'flags', d)
4821 self.assertRaises(KeyError, setattr, c, 'traps', d)
4822
4823 # Input corner cases
4824 int_max = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
4825 gt_max_emax = 10**18 if HAVE_CONFIG_64 else 10**9
4826
4827 # prec, Emax, Emin
4828 for attr in ['prec', 'Emax']:
4829 self.assertRaises(ValueError, setattr, c, attr, gt_max_emax)
4830 self.assertRaises(ValueError, setattr, c, 'Emin', -gt_max_emax)
4831
4832 # prec, Emax, Emin in context constructor
4833 self.assertRaises(ValueError, Context, prec=gt_max_emax)
4834 self.assertRaises(ValueError, Context, Emax=gt_max_emax)
4835 self.assertRaises(ValueError, Context, Emin=-gt_max_emax)
4836
4837 # Overflow in conversion
4838 self.assertRaises(OverflowError, Context, prec=int_max+1)
4839 self.assertRaises(OverflowError, Context, Emax=int_max+1)
4840 self.assertRaises(OverflowError, Context, Emin=-int_max-2)
Stefan Krah1919b7e2012-03-21 18:25:23 +01004841 self.assertRaises(OverflowError, Context, clamp=int_max+1)
4842 self.assertRaises(OverflowError, Context, capitals=int_max+1)
4843
4844 # OverflowError, general ValueError
4845 for attr in ('prec', 'Emin', 'Emax', 'capitals', 'clamp'):
4846 self.assertRaises(OverflowError, setattr, c, attr, int_max+1)
4847 self.assertRaises(OverflowError, setattr, c, attr, -int_max-2)
4848 if sys.platform != 'win32':
4849 self.assertRaises(ValueError, setattr, c, attr, int_max)
4850 self.assertRaises(ValueError, setattr, c, attr, -int_max-1)
4851
Stefan Krah1919b7e2012-03-21 18:25:23 +01004852 # OverflowError: _unsafe_setprec, _unsafe_setemin, _unsafe_setemax
4853 if C.MAX_PREC == 425000000:
4854 self.assertRaises(OverflowError, getattr(c, '_unsafe_setprec'),
4855 int_max+1)
4856 self.assertRaises(OverflowError, getattr(c, '_unsafe_setemax'),
4857 int_max+1)
4858 self.assertRaises(OverflowError, getattr(c, '_unsafe_setemin'),
4859 -int_max-2)
4860
4861 # ValueError: _unsafe_setprec, _unsafe_setemin, _unsafe_setemax
4862 if C.MAX_PREC == 425000000:
4863 self.assertRaises(ValueError, getattr(c, '_unsafe_setprec'), 0)
4864 self.assertRaises(ValueError, getattr(c, '_unsafe_setprec'),
4865 1070000001)
4866 self.assertRaises(ValueError, getattr(c, '_unsafe_setemax'), -1)
4867 self.assertRaises(ValueError, getattr(c, '_unsafe_setemax'),
4868 1070000001)
4869 self.assertRaises(ValueError, getattr(c, '_unsafe_setemin'),
4870 -1070000001)
4871 self.assertRaises(ValueError, getattr(c, '_unsafe_setemin'), 1)
4872
4873 # capitals, clamp
4874 for attr in ['capitals', 'clamp']:
4875 self.assertRaises(ValueError, setattr, c, attr, -1)
4876 self.assertRaises(ValueError, setattr, c, attr, 2)
4877 self.assertRaises(TypeError, setattr, c, attr, [1,2,3])
4878 if HAVE_CONFIG_64:
4879 self.assertRaises(ValueError, setattr, c, attr, 2**32)
4880 self.assertRaises(ValueError, setattr, c, attr, 2**32+1)
4881
4882 # Invalid local context
4883 self.assertRaises(TypeError, exec, 'with localcontext("xyz"): pass',
4884 locals())
Stefan Krah040e3112012-12-15 22:33:33 +01004885 self.assertRaises(TypeError, exec,
4886 'with localcontext(context=getcontext()): pass',
4887 locals())
Stefan Krah1919b7e2012-03-21 18:25:23 +01004888
4889 # setcontext
4890 saved_context = getcontext()
4891 self.assertRaises(TypeError, setcontext, "xyz")
4892 setcontext(saved_context)
4893
Stefan Krah59a4a932013-01-16 12:58:59 +01004894 def test_rounding_strings_interned(self):
4895
4896 self.assertIs(C.ROUND_UP, P.ROUND_UP)
4897 self.assertIs(C.ROUND_DOWN, P.ROUND_DOWN)
4898 self.assertIs(C.ROUND_CEILING, P.ROUND_CEILING)
4899 self.assertIs(C.ROUND_FLOOR, P.ROUND_FLOOR)
4900 self.assertIs(C.ROUND_HALF_UP, P.ROUND_HALF_UP)
4901 self.assertIs(C.ROUND_HALF_DOWN, P.ROUND_HALF_DOWN)
4902 self.assertIs(C.ROUND_HALF_EVEN, P.ROUND_HALF_EVEN)
4903 self.assertIs(C.ROUND_05UP, P.ROUND_05UP)
4904
Stefan Krah1919b7e2012-03-21 18:25:23 +01004905 @requires_extra_functionality
4906 def test_c_context_errors_extra(self):
4907 Context = C.Context
4908 InvalidOperation = C.InvalidOperation
4909 Overflow = C.Overflow
4910 localcontext = C.localcontext
4911 getcontext = C.getcontext
4912 setcontext = C.setcontext
4913 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
4914
4915 c = Context()
4916
4917 # Input corner cases
4918 int_max = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
4919
4920 # OverflowError, general ValueError
4921 self.assertRaises(OverflowError, setattr, c, '_allcr', int_max+1)
4922 self.assertRaises(OverflowError, setattr, c, '_allcr', -int_max-2)
4923 if sys.platform != 'win32':
4924 self.assertRaises(ValueError, setattr, c, '_allcr', int_max)
4925 self.assertRaises(ValueError, setattr, c, '_allcr', -int_max-1)
4926
4927 # OverflowError, general TypeError
4928 for attr in ('_flags', '_traps'):
4929 self.assertRaises(OverflowError, setattr, c, attr, int_max+1)
4930 self.assertRaises(OverflowError, setattr, c, attr, -int_max-2)
4931 if sys.platform != 'win32':
4932 self.assertRaises(TypeError, setattr, c, attr, int_max)
4933 self.assertRaises(TypeError, setattr, c, attr, -int_max-1)
4934
4935 # _allcr
4936 self.assertRaises(ValueError, setattr, c, '_allcr', -1)
4937 self.assertRaises(ValueError, setattr, c, '_allcr', 2)
4938 self.assertRaises(TypeError, setattr, c, '_allcr', [1,2,3])
4939 if HAVE_CONFIG_64:
4940 self.assertRaises(ValueError, setattr, c, '_allcr', 2**32)
4941 self.assertRaises(ValueError, setattr, c, '_allcr', 2**32+1)
4942
4943 # _flags, _traps
4944 for attr in ['_flags', '_traps']:
4945 self.assertRaises(TypeError, setattr, c, attr, 999999)
4946 self.assertRaises(TypeError, setattr, c, attr, 'x')
4947
4948 def test_c_valid_context(self):
4949 # These tests are for code coverage in _decimal.
4950 DefaultContext = C.DefaultContext
Stefan Krah1919b7e2012-03-21 18:25:23 +01004951 Clamped = C.Clamped
4952 Underflow = C.Underflow
4953 Inexact = C.Inexact
4954 Rounded = C.Rounded
4955 Subnormal = C.Subnormal
4956
4957 c = DefaultContext.copy()
4958
4959 # Exercise all getters and setters
4960 c.prec = 34
4961 c.rounding = ROUND_HALF_UP
4962 c.Emax = 3000
4963 c.Emin = -3000
4964 c.capitals = 1
4965 c.clamp = 0
4966
4967 self.assertEqual(c.prec, 34)
4968 self.assertEqual(c.rounding, ROUND_HALF_UP)
4969 self.assertEqual(c.Emin, -3000)
4970 self.assertEqual(c.Emax, 3000)
4971 self.assertEqual(c.capitals, 1)
4972 self.assertEqual(c.clamp, 0)
4973
4974 self.assertEqual(c.Etiny(), -3033)
4975 self.assertEqual(c.Etop(), 2967)
4976
4977 # Exercise all unsafe setters
4978 if C.MAX_PREC == 425000000:
4979 c._unsafe_setprec(999999999)
4980 c._unsafe_setemax(999999999)
4981 c._unsafe_setemin(-999999999)
4982 self.assertEqual(c.prec, 999999999)
4983 self.assertEqual(c.Emax, 999999999)
4984 self.assertEqual(c.Emin, -999999999)
4985
4986 @requires_extra_functionality
4987 def test_c_valid_context_extra(self):
4988 DefaultContext = C.DefaultContext
4989
4990 c = DefaultContext.copy()
4991 self.assertEqual(c._allcr, 1)
4992 c._allcr = 0
4993 self.assertEqual(c._allcr, 0)
4994
4995 def test_c_round(self):
4996 # Restricted input.
4997 Decimal = C.Decimal
4998 InvalidOperation = C.InvalidOperation
4999 localcontext = C.localcontext
5000 MAX_EMAX = C.MAX_EMAX
5001 MIN_ETINY = C.MIN_ETINY
5002 int_max = 2**63-1 if C.MAX_PREC > 425000000 else 2**31-1
5003
5004 with localcontext() as c:
5005 c.traps[InvalidOperation] = True
5006 self.assertRaises(InvalidOperation, Decimal("1.23").__round__,
5007 -int_max-1)
5008 self.assertRaises(InvalidOperation, Decimal("1.23").__round__,
5009 int_max)
5010 self.assertRaises(InvalidOperation, Decimal("1").__round__,
5011 int(MAX_EMAX+1))
5012 self.assertRaises(C.InvalidOperation, Decimal("1").__round__,
5013 -int(MIN_ETINY-1))
5014 self.assertRaises(OverflowError, Decimal("1.23").__round__,
5015 -int_max-2)
5016 self.assertRaises(OverflowError, Decimal("1.23").__round__,
5017 int_max+1)
5018
5019 def test_c_format(self):
5020 # Restricted input
5021 Decimal = C.Decimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01005022 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
5023
5024 self.assertRaises(TypeError, Decimal(1).__format__, "=10.10", [], 9)
5025 self.assertRaises(TypeError, Decimal(1).__format__, "=10.10", 9)
5026 self.assertRaises(TypeError, Decimal(1).__format__, [])
5027
Stefan Kraheb8c4512013-01-24 15:22:33 +01005028 self.assertRaises(ValueError, Decimal(1).__format__, "<>=10.10")
5029 maxsize = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
5030 self.assertRaises(ValueError, Decimal("1.23456789").__format__,
5031 "=%d.1" % maxsize)
Stefan Krah1919b7e2012-03-21 18:25:23 +01005032
5033 def test_c_integral(self):
5034 Decimal = C.Decimal
5035 Inexact = C.Inexact
Stefan Krah1919b7e2012-03-21 18:25:23 +01005036 localcontext = C.localcontext
5037
5038 x = Decimal(10)
5039 self.assertEqual(x.to_integral(), 10)
5040 self.assertRaises(TypeError, x.to_integral, '10')
5041 self.assertRaises(TypeError, x.to_integral, 10, 'x')
5042 self.assertRaises(TypeError, x.to_integral, 10)
5043
5044 self.assertEqual(x.to_integral_value(), 10)
5045 self.assertRaises(TypeError, x.to_integral_value, '10')
5046 self.assertRaises(TypeError, x.to_integral_value, 10, 'x')
5047 self.assertRaises(TypeError, x.to_integral_value, 10)
5048
5049 self.assertEqual(x.to_integral_exact(), 10)
5050 self.assertRaises(TypeError, x.to_integral_exact, '10')
5051 self.assertRaises(TypeError, x.to_integral_exact, 10, 'x')
5052 self.assertRaises(TypeError, x.to_integral_exact, 10)
5053
5054 with localcontext() as c:
5055 x = Decimal("99999999999999999999999999.9").to_integral_value(ROUND_UP)
5056 self.assertEqual(x, Decimal('100000000000000000000000000'))
5057
5058 x = Decimal("99999999999999999999999999.9").to_integral_exact(ROUND_UP)
5059 self.assertEqual(x, Decimal('100000000000000000000000000'))
5060
5061 c.traps[Inexact] = True
5062 self.assertRaises(Inexact, Decimal("999.9").to_integral_exact, ROUND_UP)
5063
5064 def test_c_funcs(self):
5065 # Invalid arguments
5066 Decimal = C.Decimal
5067 InvalidOperation = C.InvalidOperation
5068 DivisionByZero = C.DivisionByZero
Stefan Krah1919b7e2012-03-21 18:25:23 +01005069 getcontext = C.getcontext
5070 localcontext = C.localcontext
5071
5072 self.assertEqual(Decimal('9.99e10').to_eng_string(), '99.9E+9')
5073
5074 self.assertRaises(TypeError, pow, Decimal(1), 2, "3")
5075 self.assertRaises(TypeError, Decimal(9).number_class, "x", "y")
5076 self.assertRaises(TypeError, Decimal(9).same_quantum, 3, "x", "y")
5077
Raymond Hettinger771ed762009-01-03 19:20:32 +00005078 self.assertRaises(
Stefan Krah1919b7e2012-03-21 18:25:23 +01005079 TypeError,
5080 Decimal("1.23456789").quantize, Decimal('1e-100000'), []
Raymond Hettinger771ed762009-01-03 19:20:32 +00005081 )
Stefan Krah1919b7e2012-03-21 18:25:23 +01005082 self.assertRaises(
5083 TypeError,
5084 Decimal("1.23456789").quantize, Decimal('1e-100000'), getcontext()
5085 )
5086 self.assertRaises(
5087 TypeError,
5088 Decimal("1.23456789").quantize, Decimal('1e-100000'), 10
5089 )
5090 self.assertRaises(
5091 TypeError,
5092 Decimal("1.23456789").quantize, Decimal('1e-100000'), ROUND_UP, 1000
5093 )
Raymond Hettinger771ed762009-01-03 19:20:32 +00005094
Stefan Krah1919b7e2012-03-21 18:25:23 +01005095 with localcontext() as c:
5096 c.clear_traps()
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00005097
Stefan Krah1919b7e2012-03-21 18:25:23 +01005098 # Invalid arguments
5099 self.assertRaises(TypeError, c.copy_sign, Decimal(1), "x", "y")
5100 self.assertRaises(TypeError, c.canonical, 200)
5101 self.assertRaises(TypeError, c.is_canonical, 200)
5102 self.assertRaises(TypeError, c.divmod, 9, 8, "x", "y")
5103 self.assertRaises(TypeError, c.same_quantum, 9, 3, "x", "y")
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00005104
Stefan Krah1919b7e2012-03-21 18:25:23 +01005105 self.assertEqual(str(c.canonical(Decimal(200))), '200')
5106 self.assertEqual(c.radix(), 10)
Raymond Hettinger0aeac102004-07-05 22:53:03 +00005107
Stefan Krah1919b7e2012-03-21 18:25:23 +01005108 c.traps[DivisionByZero] = True
5109 self.assertRaises(DivisionByZero, Decimal(9).__divmod__, 0)
5110 self.assertRaises(DivisionByZero, c.divmod, 9, 0)
5111 self.assertTrue(c.flags[InvalidOperation])
Raymond Hettinger955d2b22004-08-08 20:17:45 +00005112
Stefan Krah1919b7e2012-03-21 18:25:23 +01005113 c.clear_flags()
5114 c.traps[InvalidOperation] = True
5115 self.assertRaises(InvalidOperation, Decimal(9).__divmod__, 0)
5116 self.assertRaises(InvalidOperation, c.divmod, 9, 0)
5117 self.assertTrue(c.flags[DivisionByZero])
Mark Dickinsonb1d8e322010-05-22 18:35:36 +00005118
Stefan Krah1919b7e2012-03-21 18:25:23 +01005119 c.traps[InvalidOperation] = True
5120 c.prec = 2
5121 self.assertRaises(InvalidOperation, pow, Decimal(1000), 1, 501)
Mark Dickinson84230a12010-02-18 14:49:50 +00005122
Stefan Krah040e3112012-12-15 22:33:33 +01005123 def test_va_args_exceptions(self):
5124 Decimal = C.Decimal
5125 Context = C.Context
5126
5127 x = Decimal("10001111111")
5128
5129 for attr in ['exp', 'is_normal', 'is_subnormal', 'ln', 'log10',
5130 'logb', 'logical_invert', 'next_minus', 'next_plus',
5131 'normalize', 'number_class', 'sqrt', 'to_eng_string']:
5132 func = getattr(x, attr)
5133 self.assertRaises(TypeError, func, context="x")
5134 self.assertRaises(TypeError, func, "x", context=None)
5135
5136 for attr in ['compare', 'compare_signal', 'logical_and',
5137 'logical_or', 'max', 'max_mag', 'min', 'min_mag',
5138 'remainder_near', 'rotate', 'scaleb', 'shift']:
5139 func = getattr(x, attr)
5140 self.assertRaises(TypeError, func, context="x")
5141 self.assertRaises(TypeError, func, "x", context=None)
5142
5143 self.assertRaises(TypeError, x.to_integral, rounding=None, context=[])
5144 self.assertRaises(TypeError, x.to_integral, rounding={}, context=[])
5145 self.assertRaises(TypeError, x.to_integral, [], [])
5146
5147 self.assertRaises(TypeError, x.to_integral_value, rounding=None, context=[])
5148 self.assertRaises(TypeError, x.to_integral_value, rounding={}, context=[])
5149 self.assertRaises(TypeError, x.to_integral_value, [], [])
5150
5151 self.assertRaises(TypeError, x.to_integral_exact, rounding=None, context=[])
5152 self.assertRaises(TypeError, x.to_integral_exact, rounding={}, context=[])
5153 self.assertRaises(TypeError, x.to_integral_exact, [], [])
5154
5155 self.assertRaises(TypeError, x.fma, 1, 2, context="x")
5156 self.assertRaises(TypeError, x.fma, 1, 2, "x", context=None)
5157
5158 self.assertRaises(TypeError, x.quantize, 1, [], context=None)
5159 self.assertRaises(TypeError, x.quantize, 1, [], rounding=None)
5160 self.assertRaises(TypeError, x.quantize, 1, [], [])
5161
5162 c = Context()
5163 self.assertRaises(TypeError, c.power, 1, 2, mod="x")
5164 self.assertRaises(TypeError, c.power, 1, "x", mod=None)
5165 self.assertRaises(TypeError, c.power, "x", 2, mod=None)
5166
Stefan Krah1919b7e2012-03-21 18:25:23 +01005167 @requires_extra_functionality
5168 def test_c_context_templates(self):
5169 self.assertEqual(
5170 C.BasicContext._traps,
5171 C.DecIEEEInvalidOperation|C.DecDivisionByZero|C.DecOverflow|
5172 C.DecUnderflow|C.DecClamped
5173 )
5174 self.assertEqual(
5175 C.DefaultContext._traps,
5176 C.DecIEEEInvalidOperation|C.DecDivisionByZero|C.DecOverflow
5177 )
Mark Dickinson84230a12010-02-18 14:49:50 +00005178
Stefan Krah1919b7e2012-03-21 18:25:23 +01005179 @requires_extra_functionality
5180 def test_c_signal_dict(self):
Mark Dickinson84230a12010-02-18 14:49:50 +00005181
Stefan Krah1919b7e2012-03-21 18:25:23 +01005182 # SignalDict coverage
5183 Context = C.Context
5184 DefaultContext = C.DefaultContext
Mark Dickinson84230a12010-02-18 14:49:50 +00005185
Stefan Krah1919b7e2012-03-21 18:25:23 +01005186 InvalidOperation = C.InvalidOperation
5187 DivisionByZero = C.DivisionByZero
5188 Overflow = C.Overflow
5189 Subnormal = C.Subnormal
5190 Underflow = C.Underflow
5191 Rounded = C.Rounded
5192 Inexact = C.Inexact
5193 Clamped = C.Clamped
Mark Dickinson84230a12010-02-18 14:49:50 +00005194
Stefan Krah1919b7e2012-03-21 18:25:23 +01005195 DecClamped = C.DecClamped
5196 DecInvalidOperation = C.DecInvalidOperation
5197 DecIEEEInvalidOperation = C.DecIEEEInvalidOperation
Mark Dickinson84230a12010-02-18 14:49:50 +00005198
Stefan Krah1919b7e2012-03-21 18:25:23 +01005199 def assertIsExclusivelySet(signal, signal_dict):
5200 for sig in signal_dict:
5201 if sig == signal:
5202 self.assertTrue(signal_dict[sig])
5203 else:
5204 self.assertFalse(signal_dict[sig])
Mark Dickinson84230a12010-02-18 14:49:50 +00005205
Stefan Krah1919b7e2012-03-21 18:25:23 +01005206 c = DefaultContext.copy()
Mark Dickinson84230a12010-02-18 14:49:50 +00005207
Stefan Krah1919b7e2012-03-21 18:25:23 +01005208 # Signal dict methods
5209 self.assertTrue(Overflow in c.traps)
5210 c.clear_traps()
5211 for k in c.traps.keys():
5212 c.traps[k] = True
5213 for v in c.traps.values():
5214 self.assertTrue(v)
5215 c.clear_traps()
5216 for k, v in c.traps.items():
5217 self.assertFalse(v)
Mark Dickinson84230a12010-02-18 14:49:50 +00005218
Stefan Krah1919b7e2012-03-21 18:25:23 +01005219 self.assertFalse(c.flags.get(Overflow))
5220 self.assertIs(c.flags.get("x"), None)
5221 self.assertEqual(c.flags.get("x", "y"), "y")
5222 self.assertRaises(TypeError, c.flags.get, "x", "y", "z")
Mark Dickinson84230a12010-02-18 14:49:50 +00005223
Stefan Krah1919b7e2012-03-21 18:25:23 +01005224 self.assertEqual(len(c.flags), len(c.traps))
5225 s = sys.getsizeof(c.flags)
5226 s = sys.getsizeof(c.traps)
5227 s = c.flags.__repr__()
Mark Dickinson84230a12010-02-18 14:49:50 +00005228
Stefan Krah1919b7e2012-03-21 18:25:23 +01005229 # Set flags/traps.
5230 c.clear_flags()
5231 c._flags = DecClamped
5232 self.assertTrue(c.flags[Clamped])
Mark Dickinson84230a12010-02-18 14:49:50 +00005233
Stefan Krah1919b7e2012-03-21 18:25:23 +01005234 c.clear_traps()
5235 c._traps = DecInvalidOperation
5236 self.assertTrue(c.traps[InvalidOperation])
Mark Dickinson84230a12010-02-18 14:49:50 +00005237
Stefan Krah1919b7e2012-03-21 18:25:23 +01005238 # Set flags/traps from dictionary.
5239 c.clear_flags()
5240 d = c.flags.copy()
5241 d[DivisionByZero] = True
5242 c.flags = d
5243 assertIsExclusivelySet(DivisionByZero, c.flags)
Mark Dickinson84230a12010-02-18 14:49:50 +00005244
Stefan Krah1919b7e2012-03-21 18:25:23 +01005245 c.clear_traps()
5246 d = c.traps.copy()
5247 d[Underflow] = True
5248 c.traps = d
5249 assertIsExclusivelySet(Underflow, c.traps)
Mark Dickinson84230a12010-02-18 14:49:50 +00005250
Stefan Krah1919b7e2012-03-21 18:25:23 +01005251 # Random constructors
5252 IntSignals = {
5253 Clamped: C.DecClamped,
5254 Rounded: C.DecRounded,
5255 Inexact: C.DecInexact,
5256 Subnormal: C.DecSubnormal,
5257 Underflow: C.DecUnderflow,
5258 Overflow: C.DecOverflow,
5259 DivisionByZero: C.DecDivisionByZero,
5260 InvalidOperation: C.DecIEEEInvalidOperation
5261 }
5262 IntCond = [
5263 C.DecDivisionImpossible, C.DecDivisionUndefined, C.DecFpuError,
5264 C.DecInvalidContext, C.DecInvalidOperation, C.DecMallocError,
5265 C.DecConversionSyntax,
5266 ]
Mark Dickinsonb455e582011-05-22 12:53:18 +01005267
Stefan Krah1919b7e2012-03-21 18:25:23 +01005268 lim = len(OrderedSignals[C])
5269 for r in range(lim):
5270 for t in range(lim):
Stefan Krah59a4a932013-01-16 12:58:59 +01005271 for round in RoundingModes:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005272 flags = random.sample(OrderedSignals[C], r)
5273 traps = random.sample(OrderedSignals[C], t)
5274 prec = random.randrange(1, 10000)
5275 emin = random.randrange(-10000, 0)
5276 emax = random.randrange(0, 10000)
5277 clamp = random.randrange(0, 2)
5278 caps = random.randrange(0, 2)
5279 cr = random.randrange(0, 2)
5280 c = Context(prec=prec, rounding=round, Emin=emin, Emax=emax,
5281 capitals=caps, clamp=clamp, flags=list(flags),
5282 traps=list(traps))
Mark Dickinson84230a12010-02-18 14:49:50 +00005283
Stefan Krah1919b7e2012-03-21 18:25:23 +01005284 self.assertEqual(c.prec, prec)
5285 self.assertEqual(c.rounding, round)
5286 self.assertEqual(c.Emin, emin)
5287 self.assertEqual(c.Emax, emax)
5288 self.assertEqual(c.capitals, caps)
5289 self.assertEqual(c.clamp, clamp)
Mark Dickinson84230a12010-02-18 14:49:50 +00005290
Stefan Krah1919b7e2012-03-21 18:25:23 +01005291 f = 0
5292 for x in flags:
5293 f |= IntSignals[x]
5294 self.assertEqual(c._flags, f)
Mark Dickinson84230a12010-02-18 14:49:50 +00005295
Stefan Krah1919b7e2012-03-21 18:25:23 +01005296 f = 0
5297 for x in traps:
5298 f |= IntSignals[x]
5299 self.assertEqual(c._traps, f)
Mark Dickinson84230a12010-02-18 14:49:50 +00005300
Stefan Krah1919b7e2012-03-21 18:25:23 +01005301 for cond in IntCond:
5302 c._flags = cond
5303 self.assertTrue(c._flags&DecIEEEInvalidOperation)
5304 assertIsExclusivelySet(InvalidOperation, c.flags)
Mark Dickinson84230a12010-02-18 14:49:50 +00005305
Stefan Krah1919b7e2012-03-21 18:25:23 +01005306 for cond in IntCond:
5307 c._traps = cond
5308 self.assertTrue(c._traps&DecIEEEInvalidOperation)
5309 assertIsExclusivelySet(InvalidOperation, c.traps)
Mark Dickinson84230a12010-02-18 14:49:50 +00005310
Stefan Krah1919b7e2012-03-21 18:25:23 +01005311 def test_invalid_override(self):
5312 Decimal = C.Decimal
Mark Dickinson84230a12010-02-18 14:49:50 +00005313
Stefan Krah1919b7e2012-03-21 18:25:23 +01005314 try:
5315 from locale import CHAR_MAX
5316 except ImportError:
Zachary Ware9fe6d862013-12-08 00:20:35 -06005317 self.skipTest('locale.CHAR_MAX not available')
Mark Dickinson84230a12010-02-18 14:49:50 +00005318
Stefan Krah1919b7e2012-03-21 18:25:23 +01005319 def make_grouping(lst):
5320 return ''.join([chr(x) for x in lst])
Mark Dickinson84230a12010-02-18 14:49:50 +00005321
Stefan Krah1919b7e2012-03-21 18:25:23 +01005322 def get_fmt(x, override=None, fmt='n'):
5323 return Decimal(x).__format__(fmt, override)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005324
Stefan Krah1919b7e2012-03-21 18:25:23 +01005325 invalid_grouping = {
5326 'decimal_point' : ',',
5327 'grouping' : make_grouping([255, 255, 0]),
5328 'thousands_sep' : ','
5329 }
5330 invalid_dot = {
5331 'decimal_point' : 'xxxxx',
5332 'grouping' : make_grouping([3, 3, 0]),
5333 'thousands_sep' : ','
5334 }
5335 invalid_sep = {
5336 'decimal_point' : '.',
5337 'grouping' : make_grouping([3, 3, 0]),
5338 'thousands_sep' : 'yyyyy'
5339 }
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005340
Stefan Krah1919b7e2012-03-21 18:25:23 +01005341 if CHAR_MAX == 127: # negative grouping in override
5342 self.assertRaises(ValueError, get_fmt, 12345,
5343 invalid_grouping, 'g')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005344
Stefan Krah1919b7e2012-03-21 18:25:23 +01005345 self.assertRaises(ValueError, get_fmt, 12345, invalid_dot, 'g')
5346 self.assertRaises(ValueError, get_fmt, 12345, invalid_sep, 'g')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005347
Stefan Krah0774e9b2012-04-05 15:21:58 +02005348 def test_exact_conversion(self):
5349 Decimal = C.Decimal
5350 localcontext = C.localcontext
5351 InvalidOperation = C.InvalidOperation
5352
5353 with localcontext() as c:
5354
5355 c.traps[InvalidOperation] = True
5356
5357 # Clamped
5358 x = "0e%d" % sys.maxsize
5359 self.assertRaises(InvalidOperation, Decimal, x)
5360
5361 x = "0e%d" % (-sys.maxsize-1)
5362 self.assertRaises(InvalidOperation, Decimal, x)
5363
5364 # Overflow
5365 x = "1e%d" % sys.maxsize
5366 self.assertRaises(InvalidOperation, Decimal, x)
5367
5368 # Underflow
5369 x = "1e%d" % (-sys.maxsize-1)
5370 self.assertRaises(InvalidOperation, Decimal, x)
5371
Stefan Krahff3eca02012-04-05 15:46:19 +02005372 def test_from_tuple(self):
5373 Decimal = C.Decimal
5374 localcontext = C.localcontext
5375 InvalidOperation = C.InvalidOperation
5376 Overflow = C.Overflow
5377 Underflow = C.Underflow
5378
5379 with localcontext() as c:
5380
5381 c.traps[InvalidOperation] = True
5382 c.traps[Overflow] = True
5383 c.traps[Underflow] = True
5384
5385 # SSIZE_MAX
5386 x = (1, (), sys.maxsize)
5387 self.assertEqual(str(c.create_decimal(x)), '-0E+999999')
5388 self.assertRaises(InvalidOperation, Decimal, x)
5389
5390 x = (1, (0, 1, 2), sys.maxsize)
5391 self.assertRaises(Overflow, c.create_decimal, x)
5392 self.assertRaises(InvalidOperation, Decimal, x)
5393
5394 # SSIZE_MIN
5395 x = (1, (), -sys.maxsize-1)
5396 self.assertEqual(str(c.create_decimal(x)), '-0E-1000026')
5397 self.assertRaises(InvalidOperation, Decimal, x)
5398
5399 x = (1, (0, 1, 2), -sys.maxsize-1)
5400 self.assertRaises(Underflow, c.create_decimal, x)
5401 self.assertRaises(InvalidOperation, Decimal, x)
5402
5403 # OverflowError
5404 x = (1, (), sys.maxsize+1)
5405 self.assertRaises(OverflowError, c.create_decimal, x)
5406 self.assertRaises(OverflowError, Decimal, x)
5407
5408 x = (1, (), -sys.maxsize-2)
5409 self.assertRaises(OverflowError, c.create_decimal, x)
5410 self.assertRaises(OverflowError, Decimal, x)
5411
5412 # Specials
5413 x = (1, (), "N")
5414 self.assertEqual(str(Decimal(x)), '-sNaN')
5415 x = (1, (0,), "N")
5416 self.assertEqual(str(Decimal(x)), '-sNaN')
5417 x = (1, (0, 1), "N")
5418 self.assertEqual(str(Decimal(x)), '-sNaN1')
5419
Stefan Krah891ca9e2013-05-29 19:14:17 +02005420 def test_sizeof(self):
5421 Decimal = C.Decimal
5422 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
5423
5424 self.assertGreater(Decimal(0).__sizeof__(), 0)
5425 if HAVE_CONFIG_64:
5426 x = Decimal(10**(19*24)).__sizeof__()
5427 y = Decimal(10**(19*25)).__sizeof__()
5428 self.assertEqual(y, x+8)
5429 else:
5430 x = Decimal(10**(9*24)).__sizeof__()
5431 y = Decimal(10**(9*25)).__sizeof__()
5432 self.assertEqual(y, x+4)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005433
Stefan Krah8c126f12016-07-17 14:01:42 +02005434 def test_internal_use_of_overridden_methods(self):
5435 Decimal = C.Decimal
5436
5437 # Unsound subtyping
5438 class X(float):
5439 def as_integer_ratio(self):
5440 return 1
5441 def __abs__(self):
5442 return self
5443
5444 class Y(float):
5445 def __abs__(self):
5446 return [1]*200
5447
5448 class I(int):
5449 def bit_length(self):
5450 return [1]*200
5451
5452 class Z(float):
5453 def as_integer_ratio(self):
5454 return (I(1), I(1))
5455 def __abs__(self):
5456 return self
5457
5458 for cls in X, Y, Z:
5459 self.assertEqual(Decimal.from_float(cls(101.1)),
5460 Decimal.from_float(101.1))
5461
Stefan Krah6b794b82014-05-01 17:42:33 +02005462@requires_docstrings
5463@unittest.skipUnless(C, "test requires C version")
Stefan Krah5de1f822014-05-01 15:53:42 +02005464class SignatureTest(unittest.TestCase):
5465 """Function signatures"""
5466
5467 def test_inspect_module(self):
5468 for attr in dir(P):
5469 if attr.startswith('_'):
5470 continue
5471 p_func = getattr(P, attr)
5472 c_func = getattr(C, attr)
5473 if (attr == 'Decimal' or attr == 'Context' or
5474 inspect.isfunction(p_func)):
5475 p_sig = inspect.signature(p_func)
5476 c_sig = inspect.signature(c_func)
5477
5478 # parameter names:
5479 c_names = list(c_sig.parameters.keys())
5480 p_names = [x for x in p_sig.parameters.keys() if not
5481 x.startswith('_')]
5482
5483 self.assertEqual(c_names, p_names,
5484 msg="parameter name mismatch in %s" % p_func)
5485
5486 c_kind = [x.kind for x in c_sig.parameters.values()]
5487 p_kind = [x[1].kind for x in p_sig.parameters.items() if not
5488 x[0].startswith('_')]
5489
5490 # parameters:
5491 if attr != 'setcontext':
5492 self.assertEqual(c_kind, p_kind,
5493 msg="parameter kind mismatch in %s" % p_func)
5494
5495 def test_inspect_types(self):
5496
5497 POS = inspect._ParameterKind.POSITIONAL_ONLY
5498 POS_KWD = inspect._ParameterKind.POSITIONAL_OR_KEYWORD
5499
5500 # Type heuristic (type annotations would help!):
5501 pdict = {C: {'other': C.Decimal(1),
5502 'third': C.Decimal(1),
5503 'x': C.Decimal(1),
5504 'y': C.Decimal(1),
5505 'z': C.Decimal(1),
5506 'a': C.Decimal(1),
5507 'b': C.Decimal(1),
5508 'c': C.Decimal(1),
5509 'exp': C.Decimal(1),
5510 'modulo': C.Decimal(1),
5511 'num': "1",
5512 'f': 1.0,
5513 'rounding': C.ROUND_HALF_UP,
5514 'context': C.getcontext()},
5515 P: {'other': P.Decimal(1),
5516 'third': P.Decimal(1),
5517 'a': P.Decimal(1),
5518 'b': P.Decimal(1),
5519 'c': P.Decimal(1),
5520 'exp': P.Decimal(1),
5521 'modulo': P.Decimal(1),
5522 'num': "1",
5523 'f': 1.0,
5524 'rounding': P.ROUND_HALF_UP,
5525 'context': P.getcontext()}}
5526
5527 def mkargs(module, sig):
5528 args = []
5529 kwargs = {}
5530 for name, param in sig.parameters.items():
5531 if name == 'self': continue
5532 if param.kind == POS:
5533 args.append(pdict[module][name])
5534 elif param.kind == POS_KWD:
5535 kwargs[name] = pdict[module][name]
5536 else:
5537 raise TestFailed("unexpected parameter kind")
5538 return args, kwargs
5539
5540 def tr(s):
5541 """The C Context docstrings use 'x' in order to prevent confusion
5542 with the article 'a' in the descriptions."""
5543 if s == 'x': return 'a'
5544 if s == 'y': return 'b'
5545 if s == 'z': return 'c'
5546 return s
5547
5548 def doit(ty):
5549 p_type = getattr(P, ty)
5550 c_type = getattr(C, ty)
5551 for attr in dir(p_type):
5552 if attr.startswith('_'):
5553 continue
5554 p_func = getattr(p_type, attr)
5555 c_func = getattr(c_type, attr)
5556 if inspect.isfunction(p_func):
5557 p_sig = inspect.signature(p_func)
5558 c_sig = inspect.signature(c_func)
5559
5560 # parameter names:
5561 p_names = list(p_sig.parameters.keys())
5562 c_names = [tr(x) for x in c_sig.parameters.keys()]
5563
5564 self.assertEqual(c_names, p_names,
5565 msg="parameter name mismatch in %s" % p_func)
5566
5567 p_kind = [x.kind for x in p_sig.parameters.values()]
5568 c_kind = [x.kind for x in c_sig.parameters.values()]
5569
5570 # 'self' parameter:
5571 self.assertIs(p_kind[0], POS_KWD)
5572 self.assertIs(c_kind[0], POS)
5573
5574 # remaining parameters:
5575 if ty == 'Decimal':
5576 self.assertEqual(c_kind[1:], p_kind[1:],
5577 msg="parameter kind mismatch in %s" % p_func)
5578 else: # Context methods are positional only in the C version.
5579 self.assertEqual(len(c_kind), len(p_kind),
5580 msg="parameter kind mismatch in %s" % p_func)
5581
5582 # Run the function:
5583 args, kwds = mkargs(C, c_sig)
5584 try:
5585 getattr(c_type(9), attr)(*args, **kwds)
5586 except Exception as err:
5587 raise TestFailed("invalid signature for %s: %s %s" % (c_func, args, kwds))
5588
5589 args, kwds = mkargs(P, p_sig)
5590 try:
5591 getattr(p_type(9), attr)(*args, **kwds)
5592 except Exception as err:
5593 raise TestFailed("invalid signature for %s: %s %s" % (p_func, args, kwds))
5594
5595 doit('Decimal')
5596 doit('Context')
5597
5598
Stefan Krah1919b7e2012-03-21 18:25:23 +01005599all_tests = [
5600 CExplicitConstructionTest, PyExplicitConstructionTest,
5601 CImplicitConstructionTest, PyImplicitConstructionTest,
5602 CFormatTest, PyFormatTest,
5603 CArithmeticOperatorsTest, PyArithmeticOperatorsTest,
5604 CThreadingTest, PyThreadingTest,
5605 CUsabilityTest, PyUsabilityTest,
5606 CPythonAPItests, PyPythonAPItests,
5607 CContextAPItests, PyContextAPItests,
5608 CContextWithStatement, PyContextWithStatement,
5609 CContextFlags, PyContextFlags,
5610 CSpecialContexts, PySpecialContexts,
5611 CContextInputValidation, PyContextInputValidation,
5612 CContextSubclassing, PyContextSubclassing,
5613 CCoverage, PyCoverage,
5614 CFunctionality, PyFunctionality,
5615 CWhitebox, PyWhitebox,
5616 CIBMTestCases, PyIBMTestCases,
5617]
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005618
Stefan Krah1919b7e2012-03-21 18:25:23 +01005619# Delete C tests if _decimal.so is not present.
5620if not C:
5621 all_tests = all_tests[1::2]
5622else:
5623 all_tests.insert(0, CheckAttributes)
Stefan Krah5de1f822014-05-01 15:53:42 +02005624 all_tests.insert(1, SignatureTest)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005625
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005626
Zachary Ware66f29282014-06-02 16:01:29 -05005627def test_main(arith=None, verbose=None, todo_tests=None, debug=None):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005628 """ Execute the tests.
5629
Raymond Hettingered20ad82004-09-04 20:09:13 +00005630 Runs all arithmetic tests if arith is True or if the "decimal" resource
5631 is enabled in regrtest.py
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005632 """
Raymond Hettingered20ad82004-09-04 20:09:13 +00005633
Stefan Krah1919b7e2012-03-21 18:25:23 +01005634 init(C)
5635 init(P)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005636 global TEST_ALL, DEBUG
Zachary Ware66f29282014-06-02 16:01:29 -05005637 TEST_ALL = arith if arith is not None else is_resource_enabled('decimal')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005638 DEBUG = debug
Raymond Hettingered20ad82004-09-04 20:09:13 +00005639
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005640 if todo_tests is None:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005641 test_classes = all_tests
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005642 else:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005643 test_classes = [CIBMTestCases, PyIBMTestCases]
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005644
5645 # Dynamically build custom test definition for each file in the test
5646 # directory and add the definitions to the DecimalTest class. This
5647 # procedure insures that new files do not get skipped.
5648 for filename in os.listdir(directory):
5649 if '.decTest' not in filename or filename.startswith("."):
5650 continue
5651 head, tail = filename.split('.')
5652 if todo_tests is not None and head not in todo_tests:
5653 continue
5654 tester = lambda self, f=filename: self.eval_file(directory + f)
Stefan Krah1919b7e2012-03-21 18:25:23 +01005655 setattr(CIBMTestCases, 'test_' + head, tester)
5656 setattr(PyIBMTestCases, 'test_' + head, tester)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005657 del filename, head, tail, tester
5658
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005659
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005660 try:
5661 run_unittest(*test_classes)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005662 if todo_tests is None:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005663 from doctest import IGNORE_EXCEPTION_DETAIL
5664 savedecimal = sys.modules['decimal']
5665 if C:
5666 sys.modules['decimal'] = C
5667 run_doctest(C, verbose, optionflags=IGNORE_EXCEPTION_DETAIL)
5668 sys.modules['decimal'] = P
5669 run_doctest(P, verbose)
5670 sys.modules['decimal'] = savedecimal
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005671 finally:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005672 if C: C.setcontext(ORIGINAL_CONTEXT[C])
5673 P.setcontext(ORIGINAL_CONTEXT[P])
5674 if not C:
5675 warnings.warn('C tests skipped: no module named _decimal.',
5676 UserWarning)
5677 if not orig_sys_decimal is sys.modules['decimal']:
5678 raise TestFailed("Internal error: unbalanced number of changes to "
5679 "sys.modules['decimal'].")
5680
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005681
5682if __name__ == '__main__':
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005683 import optparse
5684 p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]")
5685 p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test')
5686 p.add_option('--skip', '-s', action='store_true', help='skip over 90% of the arithmetic tests')
5687 (opt, args) = p.parse_args()
5688
5689 if opt.skip:
5690 test_main(arith=False, verbose=True)
5691 elif args:
5692 test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005693 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005694 test_main(arith=True, verbose=True)