blob: f6d58ff53d0d1d95693086068b2046ad46f9bd6f [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):
2527 pass
2528
2529 self.assertTrue(issubclass(MyDecimal, Decimal))
2530
2531 r = MyDecimal.from_float(0.1)
2532 self.assertEqual(type(r), MyDecimal)
2533 self.assertEqual(str(r),
2534 '0.1000000000000000055511151231257827021181583404541015625')
2535 bigint = 12345678901234567890123456789
2536 self.assertEqual(MyDecimal.from_float(bigint), MyDecimal(bigint))
2537 self.assertTrue(MyDecimal.from_float(float('nan')).is_qnan())
2538 self.assertTrue(MyDecimal.from_float(float('inf')).is_infinite())
2539 self.assertTrue(MyDecimal.from_float(float('-inf')).is_infinite())
2540 self.assertEqual(str(MyDecimal.from_float(float('nan'))),
2541 str(Decimal('NaN')))
2542 self.assertEqual(str(MyDecimal.from_float(float('inf'))),
2543 str(Decimal('Infinity')))
2544 self.assertEqual(str(MyDecimal.from_float(float('-inf'))),
2545 str(Decimal('-Infinity')))
2546 self.assertRaises(TypeError, MyDecimal.from_float, 'abc')
2547 for i in range(200):
2548 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
2549 self.assertEqual(x, float(MyDecimal.from_float(x))) # roundtrip
2550
2551 def test_create_decimal_from_float(self):
2552 Decimal = self.decimal.Decimal
2553 Context = self.decimal.Context
Stefan Krah1919b7e2012-03-21 18:25:23 +01002554 Inexact = self.decimal.Inexact
2555
2556 context = Context(prec=5, rounding=ROUND_DOWN)
2557 self.assertEqual(
2558 context.create_decimal_from_float(math.pi),
2559 Decimal('3.1415')
2560 )
2561 context = Context(prec=5, rounding=ROUND_UP)
2562 self.assertEqual(
2563 context.create_decimal_from_float(math.pi),
2564 Decimal('3.1416')
2565 )
2566 context = Context(prec=5, traps=[Inexact])
2567 self.assertRaises(
2568 Inexact,
2569 context.create_decimal_from_float,
2570 math.pi
2571 )
2572 self.assertEqual(repr(context.create_decimal_from_float(-0.0)),
2573 "Decimal('-0')")
2574 self.assertEqual(repr(context.create_decimal_from_float(1.0)),
2575 "Decimal('1')")
2576 self.assertEqual(repr(context.create_decimal_from_float(10)),
2577 "Decimal('10')")
2578
2579 def test_quantize(self):
2580 Decimal = self.decimal.Decimal
2581 Context = self.decimal.Context
2582 InvalidOperation = self.decimal.InvalidOperation
Stefan Krah1919b7e2012-03-21 18:25:23 +01002583
2584 c = Context(Emax=99999, Emin=-99999)
2585 self.assertEqual(
2586 Decimal('7.335').quantize(Decimal('.01')),
2587 Decimal('7.34')
2588 )
2589 self.assertEqual(
2590 Decimal('7.335').quantize(Decimal('.01'), rounding=ROUND_DOWN),
2591 Decimal('7.33')
2592 )
2593 self.assertRaises(
2594 InvalidOperation,
2595 Decimal("10e99999").quantize, Decimal('1e100000'), context=c
2596 )
2597
2598 c = Context()
2599 d = Decimal("0.871831e800")
2600 x = d.quantize(context=c, exp=Decimal("1e797"), rounding=ROUND_DOWN)
2601 self.assertEqual(x, Decimal('8.71E+799'))
2602
2603 def test_complex(self):
2604 Decimal = self.decimal.Decimal
2605
2606 x = Decimal("9.8182731e181273")
2607 self.assertEqual(x.real, x)
2608 self.assertEqual(x.imag, 0)
2609 self.assertEqual(x.conjugate(), x)
2610
2611 x = Decimal("1")
2612 self.assertEqual(complex(x), complex(float(1)))
2613
2614 self.assertRaises(AttributeError, setattr, x, 'real', 100)
2615 self.assertRaises(AttributeError, setattr, x, 'imag', 100)
2616 self.assertRaises(AttributeError, setattr, x, 'conjugate', 100)
2617 self.assertRaises(AttributeError, setattr, x, '__complex__', 100)
2618
2619 def test_named_parameters(self):
2620 D = self.decimal.Decimal
2621 Context = self.decimal.Context
2622 localcontext = self.decimal.localcontext
2623 InvalidOperation = self.decimal.InvalidOperation
2624 Overflow = self.decimal.Overflow
2625
2626 xc = Context()
2627 xc.prec = 1
2628 xc.Emax = 1
2629 xc.Emin = -1
2630
2631 with localcontext() as c:
2632 c.clear_flags()
2633
2634 self.assertEqual(D(9, xc), 9)
2635 self.assertEqual(D(9, context=xc), 9)
2636 self.assertEqual(D(context=xc, value=9), 9)
2637 self.assertEqual(D(context=xc), 0)
2638 xc.clear_flags()
2639 self.assertRaises(InvalidOperation, D, "xyz", context=xc)
2640 self.assertTrue(xc.flags[InvalidOperation])
2641 self.assertFalse(c.flags[InvalidOperation])
2642
2643 xc.clear_flags()
2644 self.assertEqual(D(2).exp(context=xc), 7)
2645 self.assertRaises(Overflow, D(8).exp, context=xc)
2646 self.assertTrue(xc.flags[Overflow])
2647 self.assertFalse(c.flags[Overflow])
2648
2649 xc.clear_flags()
2650 self.assertEqual(D(2).ln(context=xc), D('0.7'))
2651 self.assertRaises(InvalidOperation, D(-1).ln, context=xc)
2652 self.assertTrue(xc.flags[InvalidOperation])
2653 self.assertFalse(c.flags[InvalidOperation])
2654
2655 self.assertEqual(D(0).log10(context=xc), D('-inf'))
2656 self.assertEqual(D(-1).next_minus(context=xc), -2)
2657 self.assertEqual(D(-1).next_plus(context=xc), D('-0.9'))
2658 self.assertEqual(D("9.73").normalize(context=xc), D('1E+1'))
2659 self.assertEqual(D("9999").to_integral(context=xc), 9999)
2660 self.assertEqual(D("-2000").to_integral_exact(context=xc), -2000)
2661 self.assertEqual(D("123").to_integral_value(context=xc), 123)
2662 self.assertEqual(D("0.0625").sqrt(context=xc), D('0.2'))
2663
2664 self.assertEqual(D("0.0625").compare(context=xc, other=3), -1)
2665 xc.clear_flags()
2666 self.assertRaises(InvalidOperation,
2667 D("0").compare_signal, D('nan'), context=xc)
2668 self.assertTrue(xc.flags[InvalidOperation])
2669 self.assertFalse(c.flags[InvalidOperation])
2670 self.assertEqual(D("0.01").max(D('0.0101'), context=xc), D('0.0'))
2671 self.assertEqual(D("0.01").max(D('0.0101'), context=xc), D('0.0'))
2672 self.assertEqual(D("0.2").max_mag(D('-0.3'), context=xc),
2673 D('-0.3'))
2674 self.assertEqual(D("0.02").min(D('-0.03'), context=xc), D('-0.0'))
2675 self.assertEqual(D("0.02").min_mag(D('-0.03'), context=xc),
2676 D('0.0'))
2677 self.assertEqual(D("0.2").next_toward(D('-1'), context=xc), D('0.1'))
2678 xc.clear_flags()
2679 self.assertRaises(InvalidOperation,
2680 D("0.2").quantize, D('1e10'), context=xc)
2681 self.assertTrue(xc.flags[InvalidOperation])
2682 self.assertFalse(c.flags[InvalidOperation])
2683 self.assertEqual(D("9.99").remainder_near(D('1.5'), context=xc),
2684 D('-0.5'))
2685
2686 self.assertEqual(D("9.9").fma(third=D('0.9'), context=xc, other=7),
2687 D('7E+1'))
2688
2689 self.assertRaises(TypeError, D(1).is_canonical, context=xc)
2690 self.assertRaises(TypeError, D(1).is_finite, context=xc)
2691 self.assertRaises(TypeError, D(1).is_infinite, context=xc)
2692 self.assertRaises(TypeError, D(1).is_nan, context=xc)
2693 self.assertRaises(TypeError, D(1).is_qnan, context=xc)
2694 self.assertRaises(TypeError, D(1).is_snan, context=xc)
2695 self.assertRaises(TypeError, D(1).is_signed, context=xc)
2696 self.assertRaises(TypeError, D(1).is_zero, context=xc)
2697
2698 self.assertFalse(D("0.01").is_normal(context=xc))
2699 self.assertTrue(D("0.01").is_subnormal(context=xc))
2700
2701 self.assertRaises(TypeError, D(1).adjusted, context=xc)
2702 self.assertRaises(TypeError, D(1).conjugate, context=xc)
2703 self.assertRaises(TypeError, D(1).radix, context=xc)
2704
2705 self.assertEqual(D(-111).logb(context=xc), 2)
2706 self.assertEqual(D(0).logical_invert(context=xc), 1)
2707 self.assertEqual(D('0.01').number_class(context=xc), '+Subnormal')
2708 self.assertEqual(D('0.21').to_eng_string(context=xc), '0.21')
2709
2710 self.assertEqual(D('11').logical_and(D('10'), context=xc), 0)
2711 self.assertEqual(D('11').logical_or(D('10'), context=xc), 1)
2712 self.assertEqual(D('01').logical_xor(D('10'), context=xc), 1)
2713 self.assertEqual(D('23').rotate(1, context=xc), 3)
2714 self.assertEqual(D('23').rotate(1, context=xc), 3)
2715 xc.clear_flags()
2716 self.assertRaises(Overflow,
2717 D('23').scaleb, 1, context=xc)
2718 self.assertTrue(xc.flags[Overflow])
2719 self.assertFalse(c.flags[Overflow])
2720 self.assertEqual(D('23').shift(-1, context=xc), 0)
2721
2722 self.assertRaises(TypeError, D.from_float, 1.1, context=xc)
2723 self.assertRaises(TypeError, D(0).as_tuple, context=xc)
2724
Stefan Krah040e3112012-12-15 22:33:33 +01002725 self.assertEqual(D(1).canonical(), 1)
2726 self.assertRaises(TypeError, D("-1").copy_abs, context=xc)
2727 self.assertRaises(TypeError, D("-1").copy_negate, context=xc)
2728 self.assertRaises(TypeError, D(1).canonical, context="x")
2729 self.assertRaises(TypeError, D(1).canonical, xyz="x")
Stefan Krah1919b7e2012-03-21 18:25:23 +01002730
Stefan Krahb6405ef2012-03-23 14:46:48 +01002731 def test_exception_hierarchy(self):
2732
2733 decimal = self.decimal
2734 DecimalException = decimal.DecimalException
2735 InvalidOperation = decimal.InvalidOperation
2736 FloatOperation = decimal.FloatOperation
2737 DivisionByZero = decimal.DivisionByZero
2738 Overflow = decimal.Overflow
2739 Underflow = decimal.Underflow
2740 Subnormal = decimal.Subnormal
2741 Inexact = decimal.Inexact
2742 Rounded = decimal.Rounded
2743 Clamped = decimal.Clamped
2744
2745 self.assertTrue(issubclass(DecimalException, ArithmeticError))
2746
2747 self.assertTrue(issubclass(InvalidOperation, DecimalException))
2748 self.assertTrue(issubclass(FloatOperation, DecimalException))
2749 self.assertTrue(issubclass(FloatOperation, TypeError))
2750 self.assertTrue(issubclass(DivisionByZero, DecimalException))
2751 self.assertTrue(issubclass(DivisionByZero, ZeroDivisionError))
2752 self.assertTrue(issubclass(Overflow, Rounded))
2753 self.assertTrue(issubclass(Overflow, Inexact))
2754 self.assertTrue(issubclass(Overflow, DecimalException))
2755 self.assertTrue(issubclass(Underflow, Inexact))
2756 self.assertTrue(issubclass(Underflow, Rounded))
2757 self.assertTrue(issubclass(Underflow, Subnormal))
2758 self.assertTrue(issubclass(Underflow, DecimalException))
2759
2760 self.assertTrue(issubclass(Subnormal, DecimalException))
2761 self.assertTrue(issubclass(Inexact, DecimalException))
2762 self.assertTrue(issubclass(Rounded, DecimalException))
2763 self.assertTrue(issubclass(Clamped, DecimalException))
2764
2765 self.assertTrue(issubclass(decimal.ConversionSyntax, InvalidOperation))
2766 self.assertTrue(issubclass(decimal.DivisionImpossible, InvalidOperation))
2767 self.assertTrue(issubclass(decimal.DivisionUndefined, InvalidOperation))
2768 self.assertTrue(issubclass(decimal.DivisionUndefined, ZeroDivisionError))
2769 self.assertTrue(issubclass(decimal.InvalidContext, InvalidOperation))
2770
Stefan Krah1919b7e2012-03-21 18:25:23 +01002771class CPythonAPItests(PythonAPItests):
2772 decimal = C
2773class PyPythonAPItests(PythonAPItests):
2774 decimal = P
2775
2776class ContextAPItests(unittest.TestCase):
2777
Stefan Krah9a4ff432012-12-16 21:10:35 +01002778 def test_none_args(self):
2779 Context = self.decimal.Context
2780 InvalidOperation = self.decimal.InvalidOperation
2781 DivisionByZero = self.decimal.DivisionByZero
2782 Overflow = self.decimal.Overflow
Stefan Krah9a4ff432012-12-16 21:10:35 +01002783
2784 c1 = Context()
2785 c2 = Context(prec=None, rounding=None, Emax=None, Emin=None,
2786 capitals=None, clamp=None, flags=None, traps=None)
2787 for c in [c1, c2]:
2788 self.assertEqual(c.prec, 28)
2789 self.assertEqual(c.rounding, ROUND_HALF_EVEN)
2790 self.assertEqual(c.Emax, 999999)
2791 self.assertEqual(c.Emin, -999999)
2792 self.assertEqual(c.capitals, 1)
2793 self.assertEqual(c.clamp, 0)
2794 assert_signals(self, c, 'flags', [])
2795 assert_signals(self, c, 'traps', [InvalidOperation, DivisionByZero,
2796 Overflow])
2797
Stefan Krah59a4a932013-01-16 12:58:59 +01002798 @cpython_only
2799 def test_from_legacy_strings(self):
2800 import _testcapi
2801 c = self.decimal.Context()
2802
2803 for rnd in RoundingModes:
2804 c.rounding = _testcapi.unicode_legacy_string(rnd)
2805 self.assertEqual(c.rounding, rnd)
2806
2807 s = _testcapi.unicode_legacy_string('')
2808 self.assertRaises(TypeError, setattr, c, 'rounding', s)
2809
2810 s = _testcapi.unicode_legacy_string('ROUND_\x00UP')
2811 self.assertRaises(TypeError, setattr, c, 'rounding', s)
2812
Stefan Krah1919b7e2012-03-21 18:25:23 +01002813 def test_pickle(self):
2814
Serhiy Storchakabad12572014-12-15 14:03:42 +02002815 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
2816 Context = self.decimal.Context
Stefan Krah1919b7e2012-03-21 18:25:23 +01002817
Serhiy Storchakabad12572014-12-15 14:03:42 +02002818 savedecimal = sys.modules['decimal']
Stefan Krah1919b7e2012-03-21 18:25:23 +01002819
Serhiy Storchakabad12572014-12-15 14:03:42 +02002820 # Round trip
2821 sys.modules['decimal'] = self.decimal
2822 c = Context()
2823 e = pickle.loads(pickle.dumps(c, proto))
Stefan Krah1919b7e2012-03-21 18:25:23 +01002824
Serhiy Storchakabad12572014-12-15 14:03:42 +02002825 self.assertEqual(c.prec, e.prec)
2826 self.assertEqual(c.Emin, e.Emin)
2827 self.assertEqual(c.Emax, e.Emax)
2828 self.assertEqual(c.rounding, e.rounding)
2829 self.assertEqual(c.capitals, e.capitals)
2830 self.assertEqual(c.clamp, e.clamp)
2831 self.assertEqual(c.flags, e.flags)
2832 self.assertEqual(c.traps, e.traps)
Stefan Krah1919b7e2012-03-21 18:25:23 +01002833
Serhiy Storchakabad12572014-12-15 14:03:42 +02002834 # Test interchangeability
2835 combinations = [(C, P), (P, C)] if C else [(P, P)]
2836 for dumper, loader in combinations:
2837 for ri, _ in enumerate(RoundingModes):
2838 for fi, _ in enumerate(OrderedSignals[dumper]):
2839 for ti, _ in enumerate(OrderedSignals[dumper]):
Stefan Krah1919b7e2012-03-21 18:25:23 +01002840
Serhiy Storchakabad12572014-12-15 14:03:42 +02002841 prec = random.randrange(1, 100)
2842 emin = random.randrange(-100, 0)
2843 emax = random.randrange(1, 100)
2844 caps = random.randrange(2)
2845 clamp = random.randrange(2)
Stefan Krah1919b7e2012-03-21 18:25:23 +01002846
Serhiy Storchakabad12572014-12-15 14:03:42 +02002847 # One module dumps
2848 sys.modules['decimal'] = dumper
2849 c = dumper.Context(
2850 prec=prec, Emin=emin, Emax=emax,
2851 rounding=RoundingModes[ri],
2852 capitals=caps, clamp=clamp,
2853 flags=OrderedSignals[dumper][:fi],
2854 traps=OrderedSignals[dumper][:ti]
2855 )
2856 s = pickle.dumps(c, proto)
Stefan Krah1919b7e2012-03-21 18:25:23 +01002857
Serhiy Storchakabad12572014-12-15 14:03:42 +02002858 # The other module loads
2859 sys.modules['decimal'] = loader
2860 d = pickle.loads(s)
2861 self.assertIsInstance(d, loader.Context)
Stefan Krah1919b7e2012-03-21 18:25:23 +01002862
Serhiy Storchakabad12572014-12-15 14:03:42 +02002863 self.assertEqual(d.prec, prec)
2864 self.assertEqual(d.Emin, emin)
2865 self.assertEqual(d.Emax, emax)
2866 self.assertEqual(d.rounding, RoundingModes[ri])
2867 self.assertEqual(d.capitals, caps)
2868 self.assertEqual(d.clamp, clamp)
2869 assert_signals(self, d, 'flags', OrderedSignals[loader][:fi])
2870 assert_signals(self, d, 'traps', OrderedSignals[loader][:ti])
Stefan Krah1919b7e2012-03-21 18:25:23 +01002871
Serhiy Storchakabad12572014-12-15 14:03:42 +02002872 sys.modules['decimal'] = savedecimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01002873
2874 def test_equality_with_other_types(self):
2875 Decimal = self.decimal.Decimal
2876
2877 self.assertIn(Decimal(10), ['a', 1.0, Decimal(10), (1,2), {}])
2878 self.assertNotIn(Decimal(10), ['a', 1.0, (1,2), {}])
2879
2880 def test_copy(self):
2881 # All copies should be deep
2882 Decimal = self.decimal.Decimal
2883 Context = self.decimal.Context
2884
2885 c = Context()
2886 d = c.copy()
2887 self.assertNotEqual(id(c), id(d))
2888 self.assertNotEqual(id(c.flags), id(d.flags))
2889 self.assertNotEqual(id(c.traps), id(d.traps))
2890 k1 = set(c.flags.keys())
2891 k2 = set(d.flags.keys())
2892 self.assertEqual(k1, k2)
2893 self.assertEqual(c.flags, d.flags)
2894
2895 def test__clamp(self):
2896 # In Python 3.2, the private attribute `_clamp` was made
2897 # public (issue 8540), with the old `_clamp` becoming a
2898 # property wrapping `clamp`. For the duration of Python 3.2
2899 # only, the attribute should be gettable/settable via both
2900 # `clamp` and `_clamp`; in Python 3.3, `_clamp` should be
2901 # removed.
2902 Context = self.decimal.Context
2903 c = Context()
2904 self.assertRaises(AttributeError, getattr, c, '_clamp')
2905
2906 def test_abs(self):
2907 Decimal = self.decimal.Decimal
2908 Context = self.decimal.Context
2909
2910 c = Context()
2911 d = c.abs(Decimal(-1))
2912 self.assertEqual(c.abs(-1), d)
2913 self.assertRaises(TypeError, c.abs, '-1')
2914
2915 def test_add(self):
2916 Decimal = self.decimal.Decimal
2917 Context = self.decimal.Context
2918
2919 c = Context()
2920 d = c.add(Decimal(1), Decimal(1))
2921 self.assertEqual(c.add(1, 1), d)
2922 self.assertEqual(c.add(Decimal(1), 1), d)
2923 self.assertEqual(c.add(1, Decimal(1)), d)
2924 self.assertRaises(TypeError, c.add, '1', 1)
2925 self.assertRaises(TypeError, c.add, 1, '1')
2926
2927 def test_compare(self):
2928 Decimal = self.decimal.Decimal
2929 Context = self.decimal.Context
2930
2931 c = Context()
2932 d = c.compare(Decimal(1), Decimal(1))
2933 self.assertEqual(c.compare(1, 1), d)
2934 self.assertEqual(c.compare(Decimal(1), 1), d)
2935 self.assertEqual(c.compare(1, Decimal(1)), d)
2936 self.assertRaises(TypeError, c.compare, '1', 1)
2937 self.assertRaises(TypeError, c.compare, 1, '1')
2938
2939 def test_compare_signal(self):
2940 Decimal = self.decimal.Decimal
2941 Context = self.decimal.Context
2942
2943 c = Context()
2944 d = c.compare_signal(Decimal(1), Decimal(1))
2945 self.assertEqual(c.compare_signal(1, 1), d)
2946 self.assertEqual(c.compare_signal(Decimal(1), 1), d)
2947 self.assertEqual(c.compare_signal(1, Decimal(1)), d)
2948 self.assertRaises(TypeError, c.compare_signal, '1', 1)
2949 self.assertRaises(TypeError, c.compare_signal, 1, '1')
2950
2951 def test_compare_total(self):
2952 Decimal = self.decimal.Decimal
2953 Context = self.decimal.Context
2954
2955 c = Context()
2956 d = c.compare_total(Decimal(1), Decimal(1))
2957 self.assertEqual(c.compare_total(1, 1), d)
2958 self.assertEqual(c.compare_total(Decimal(1), 1), d)
2959 self.assertEqual(c.compare_total(1, Decimal(1)), d)
2960 self.assertRaises(TypeError, c.compare_total, '1', 1)
2961 self.assertRaises(TypeError, c.compare_total, 1, '1')
2962
2963 def test_compare_total_mag(self):
2964 Decimal = self.decimal.Decimal
2965 Context = self.decimal.Context
2966
2967 c = Context()
2968 d = c.compare_total_mag(Decimal(1), Decimal(1))
2969 self.assertEqual(c.compare_total_mag(1, 1), d)
2970 self.assertEqual(c.compare_total_mag(Decimal(1), 1), d)
2971 self.assertEqual(c.compare_total_mag(1, Decimal(1)), d)
2972 self.assertRaises(TypeError, c.compare_total_mag, '1', 1)
2973 self.assertRaises(TypeError, c.compare_total_mag, 1, '1')
2974
2975 def test_copy_abs(self):
2976 Decimal = self.decimal.Decimal
2977 Context = self.decimal.Context
2978
2979 c = Context()
2980 d = c.copy_abs(Decimal(-1))
2981 self.assertEqual(c.copy_abs(-1), d)
2982 self.assertRaises(TypeError, c.copy_abs, '-1')
2983
2984 def test_copy_decimal(self):
2985 Decimal = self.decimal.Decimal
2986 Context = self.decimal.Context
2987
2988 c = Context()
2989 d = c.copy_decimal(Decimal(-1))
2990 self.assertEqual(c.copy_decimal(-1), d)
2991 self.assertRaises(TypeError, c.copy_decimal, '-1')
2992
2993 def test_copy_negate(self):
2994 Decimal = self.decimal.Decimal
2995 Context = self.decimal.Context
2996
2997 c = Context()
2998 d = c.copy_negate(Decimal(-1))
2999 self.assertEqual(c.copy_negate(-1), d)
3000 self.assertRaises(TypeError, c.copy_negate, '-1')
3001
3002 def test_copy_sign(self):
3003 Decimal = self.decimal.Decimal
3004 Context = self.decimal.Context
3005
3006 c = Context()
3007 d = c.copy_sign(Decimal(1), Decimal(-2))
3008 self.assertEqual(c.copy_sign(1, -2), d)
3009 self.assertEqual(c.copy_sign(Decimal(1), -2), d)
3010 self.assertEqual(c.copy_sign(1, Decimal(-2)), d)
3011 self.assertRaises(TypeError, c.copy_sign, '1', -2)
3012 self.assertRaises(TypeError, c.copy_sign, 1, '-2')
3013
3014 def test_divide(self):
3015 Decimal = self.decimal.Decimal
3016 Context = self.decimal.Context
3017
3018 c = Context()
3019 d = c.divide(Decimal(1), Decimal(2))
3020 self.assertEqual(c.divide(1, 2), d)
3021 self.assertEqual(c.divide(Decimal(1), 2), d)
3022 self.assertEqual(c.divide(1, Decimal(2)), d)
3023 self.assertRaises(TypeError, c.divide, '1', 2)
3024 self.assertRaises(TypeError, c.divide, 1, '2')
3025
3026 def test_divide_int(self):
3027 Decimal = self.decimal.Decimal
3028 Context = self.decimal.Context
3029
3030 c = Context()
3031 d = c.divide_int(Decimal(1), Decimal(2))
3032 self.assertEqual(c.divide_int(1, 2), d)
3033 self.assertEqual(c.divide_int(Decimal(1), 2), d)
3034 self.assertEqual(c.divide_int(1, Decimal(2)), d)
3035 self.assertRaises(TypeError, c.divide_int, '1', 2)
3036 self.assertRaises(TypeError, c.divide_int, 1, '2')
3037
3038 def test_divmod(self):
3039 Decimal = self.decimal.Decimal
3040 Context = self.decimal.Context
3041
3042 c = Context()
3043 d = c.divmod(Decimal(1), Decimal(2))
3044 self.assertEqual(c.divmod(1, 2), d)
3045 self.assertEqual(c.divmod(Decimal(1), 2), d)
3046 self.assertEqual(c.divmod(1, Decimal(2)), d)
3047 self.assertRaises(TypeError, c.divmod, '1', 2)
3048 self.assertRaises(TypeError, c.divmod, 1, '2')
3049
3050 def test_exp(self):
3051 Decimal = self.decimal.Decimal
3052 Context = self.decimal.Context
3053
3054 c = Context()
3055 d = c.exp(Decimal(10))
3056 self.assertEqual(c.exp(10), d)
3057 self.assertRaises(TypeError, c.exp, '10')
3058
3059 def test_fma(self):
3060 Decimal = self.decimal.Decimal
3061 Context = self.decimal.Context
3062
3063 c = Context()
3064 d = c.fma(Decimal(2), Decimal(3), Decimal(4))
3065 self.assertEqual(c.fma(2, 3, 4), d)
3066 self.assertEqual(c.fma(Decimal(2), 3, 4), d)
3067 self.assertEqual(c.fma(2, Decimal(3), 4), d)
3068 self.assertEqual(c.fma(2, 3, Decimal(4)), d)
3069 self.assertEqual(c.fma(Decimal(2), Decimal(3), 4), d)
3070 self.assertRaises(TypeError, c.fma, '2', 3, 4)
3071 self.assertRaises(TypeError, c.fma, 2, '3', 4)
3072 self.assertRaises(TypeError, c.fma, 2, 3, '4')
3073
3074 # Issue 12079 for Context.fma ...
3075 self.assertRaises(TypeError, c.fma,
3076 Decimal('Infinity'), Decimal(0), "not a decimal")
3077 self.assertRaises(TypeError, c.fma,
3078 Decimal(1), Decimal('snan'), 1.222)
3079 # ... and for Decimal.fma.
3080 self.assertRaises(TypeError, Decimal('Infinity').fma,
3081 Decimal(0), "not a decimal")
3082 self.assertRaises(TypeError, Decimal(1).fma,
3083 Decimal('snan'), 1.222)
3084
3085 def test_is_finite(self):
3086 Decimal = self.decimal.Decimal
3087 Context = self.decimal.Context
3088
3089 c = Context()
3090 d = c.is_finite(Decimal(10))
3091 self.assertEqual(c.is_finite(10), d)
3092 self.assertRaises(TypeError, c.is_finite, '10')
3093
3094 def test_is_infinite(self):
3095 Decimal = self.decimal.Decimal
3096 Context = self.decimal.Context
3097
3098 c = Context()
3099 d = c.is_infinite(Decimal(10))
3100 self.assertEqual(c.is_infinite(10), d)
3101 self.assertRaises(TypeError, c.is_infinite, '10')
3102
3103 def test_is_nan(self):
3104 Decimal = self.decimal.Decimal
3105 Context = self.decimal.Context
3106
3107 c = Context()
3108 d = c.is_nan(Decimal(10))
3109 self.assertEqual(c.is_nan(10), d)
3110 self.assertRaises(TypeError, c.is_nan, '10')
3111
3112 def test_is_normal(self):
3113 Decimal = self.decimal.Decimal
3114 Context = self.decimal.Context
3115
3116 c = Context()
3117 d = c.is_normal(Decimal(10))
3118 self.assertEqual(c.is_normal(10), d)
3119 self.assertRaises(TypeError, c.is_normal, '10')
3120
3121 def test_is_qnan(self):
3122 Decimal = self.decimal.Decimal
3123 Context = self.decimal.Context
3124
3125 c = Context()
3126 d = c.is_qnan(Decimal(10))
3127 self.assertEqual(c.is_qnan(10), d)
3128 self.assertRaises(TypeError, c.is_qnan, '10')
3129
3130 def test_is_signed(self):
3131 Decimal = self.decimal.Decimal
3132 Context = self.decimal.Context
3133
3134 c = Context()
3135 d = c.is_signed(Decimal(10))
3136 self.assertEqual(c.is_signed(10), d)
3137 self.assertRaises(TypeError, c.is_signed, '10')
3138
3139 def test_is_snan(self):
3140 Decimal = self.decimal.Decimal
3141 Context = self.decimal.Context
3142
3143 c = Context()
3144 d = c.is_snan(Decimal(10))
3145 self.assertEqual(c.is_snan(10), d)
3146 self.assertRaises(TypeError, c.is_snan, '10')
3147
3148 def test_is_subnormal(self):
3149 Decimal = self.decimal.Decimal
3150 Context = self.decimal.Context
3151
3152 c = Context()
3153 d = c.is_subnormal(Decimal(10))
3154 self.assertEqual(c.is_subnormal(10), d)
3155 self.assertRaises(TypeError, c.is_subnormal, '10')
3156
3157 def test_is_zero(self):
3158 Decimal = self.decimal.Decimal
3159 Context = self.decimal.Context
3160
3161 c = Context()
3162 d = c.is_zero(Decimal(10))
3163 self.assertEqual(c.is_zero(10), d)
3164 self.assertRaises(TypeError, c.is_zero, '10')
3165
3166 def test_ln(self):
3167 Decimal = self.decimal.Decimal
3168 Context = self.decimal.Context
3169
3170 c = Context()
3171 d = c.ln(Decimal(10))
3172 self.assertEqual(c.ln(10), d)
3173 self.assertRaises(TypeError, c.ln, '10')
3174
3175 def test_log10(self):
3176 Decimal = self.decimal.Decimal
3177 Context = self.decimal.Context
3178
3179 c = Context()
3180 d = c.log10(Decimal(10))
3181 self.assertEqual(c.log10(10), d)
3182 self.assertRaises(TypeError, c.log10, '10')
3183
3184 def test_logb(self):
3185 Decimal = self.decimal.Decimal
3186 Context = self.decimal.Context
3187
3188 c = Context()
3189 d = c.logb(Decimal(10))
3190 self.assertEqual(c.logb(10), d)
3191 self.assertRaises(TypeError, c.logb, '10')
3192
3193 def test_logical_and(self):
3194 Decimal = self.decimal.Decimal
3195 Context = self.decimal.Context
3196
3197 c = Context()
3198 d = c.logical_and(Decimal(1), Decimal(1))
3199 self.assertEqual(c.logical_and(1, 1), d)
3200 self.assertEqual(c.logical_and(Decimal(1), 1), d)
3201 self.assertEqual(c.logical_and(1, Decimal(1)), d)
3202 self.assertRaises(TypeError, c.logical_and, '1', 1)
3203 self.assertRaises(TypeError, c.logical_and, 1, '1')
3204
3205 def test_logical_invert(self):
3206 Decimal = self.decimal.Decimal
3207 Context = self.decimal.Context
3208
3209 c = Context()
3210 d = c.logical_invert(Decimal(1000))
3211 self.assertEqual(c.logical_invert(1000), d)
3212 self.assertRaises(TypeError, c.logical_invert, '1000')
3213
3214 def test_logical_or(self):
3215 Decimal = self.decimal.Decimal
3216 Context = self.decimal.Context
3217
3218 c = Context()
3219 d = c.logical_or(Decimal(1), Decimal(1))
3220 self.assertEqual(c.logical_or(1, 1), d)
3221 self.assertEqual(c.logical_or(Decimal(1), 1), d)
3222 self.assertEqual(c.logical_or(1, Decimal(1)), d)
3223 self.assertRaises(TypeError, c.logical_or, '1', 1)
3224 self.assertRaises(TypeError, c.logical_or, 1, '1')
3225
3226 def test_logical_xor(self):
3227 Decimal = self.decimal.Decimal
3228 Context = self.decimal.Context
3229
3230 c = Context()
3231 d = c.logical_xor(Decimal(1), Decimal(1))
3232 self.assertEqual(c.logical_xor(1, 1), d)
3233 self.assertEqual(c.logical_xor(Decimal(1), 1), d)
3234 self.assertEqual(c.logical_xor(1, Decimal(1)), d)
3235 self.assertRaises(TypeError, c.logical_xor, '1', 1)
3236 self.assertRaises(TypeError, c.logical_xor, 1, '1')
3237
3238 def test_max(self):
3239 Decimal = self.decimal.Decimal
3240 Context = self.decimal.Context
3241
3242 c = Context()
3243 d = c.max(Decimal(1), Decimal(2))
3244 self.assertEqual(c.max(1, 2), d)
3245 self.assertEqual(c.max(Decimal(1), 2), d)
3246 self.assertEqual(c.max(1, Decimal(2)), d)
3247 self.assertRaises(TypeError, c.max, '1', 2)
3248 self.assertRaises(TypeError, c.max, 1, '2')
3249
3250 def test_max_mag(self):
3251 Decimal = self.decimal.Decimal
3252 Context = self.decimal.Context
3253
3254 c = Context()
3255 d = c.max_mag(Decimal(1), Decimal(2))
3256 self.assertEqual(c.max_mag(1, 2), d)
3257 self.assertEqual(c.max_mag(Decimal(1), 2), d)
3258 self.assertEqual(c.max_mag(1, Decimal(2)), d)
3259 self.assertRaises(TypeError, c.max_mag, '1', 2)
3260 self.assertRaises(TypeError, c.max_mag, 1, '2')
3261
3262 def test_min(self):
3263 Decimal = self.decimal.Decimal
3264 Context = self.decimal.Context
3265
3266 c = Context()
3267 d = c.min(Decimal(1), Decimal(2))
3268 self.assertEqual(c.min(1, 2), d)
3269 self.assertEqual(c.min(Decimal(1), 2), d)
3270 self.assertEqual(c.min(1, Decimal(2)), d)
3271 self.assertRaises(TypeError, c.min, '1', 2)
3272 self.assertRaises(TypeError, c.min, 1, '2')
3273
3274 def test_min_mag(self):
3275 Decimal = self.decimal.Decimal
3276 Context = self.decimal.Context
3277
3278 c = Context()
3279 d = c.min_mag(Decimal(1), Decimal(2))
3280 self.assertEqual(c.min_mag(1, 2), d)
3281 self.assertEqual(c.min_mag(Decimal(1), 2), d)
3282 self.assertEqual(c.min_mag(1, Decimal(2)), d)
3283 self.assertRaises(TypeError, c.min_mag, '1', 2)
3284 self.assertRaises(TypeError, c.min_mag, 1, '2')
3285
3286 def test_minus(self):
3287 Decimal = self.decimal.Decimal
3288 Context = self.decimal.Context
3289
3290 c = Context()
3291 d = c.minus(Decimal(10))
3292 self.assertEqual(c.minus(10), d)
3293 self.assertRaises(TypeError, c.minus, '10')
3294
3295 def test_multiply(self):
3296 Decimal = self.decimal.Decimal
3297 Context = self.decimal.Context
3298
3299 c = Context()
3300 d = c.multiply(Decimal(1), Decimal(2))
3301 self.assertEqual(c.multiply(1, 2), d)
3302 self.assertEqual(c.multiply(Decimal(1), 2), d)
3303 self.assertEqual(c.multiply(1, Decimal(2)), d)
3304 self.assertRaises(TypeError, c.multiply, '1', 2)
3305 self.assertRaises(TypeError, c.multiply, 1, '2')
3306
3307 def test_next_minus(self):
3308 Decimal = self.decimal.Decimal
3309 Context = self.decimal.Context
3310
3311 c = Context()
3312 d = c.next_minus(Decimal(10))
3313 self.assertEqual(c.next_minus(10), d)
3314 self.assertRaises(TypeError, c.next_minus, '10')
3315
3316 def test_next_plus(self):
3317 Decimal = self.decimal.Decimal
3318 Context = self.decimal.Context
3319
3320 c = Context()
3321 d = c.next_plus(Decimal(10))
3322 self.assertEqual(c.next_plus(10), d)
3323 self.assertRaises(TypeError, c.next_plus, '10')
3324
3325 def test_next_toward(self):
3326 Decimal = self.decimal.Decimal
3327 Context = self.decimal.Context
3328
3329 c = Context()
3330 d = c.next_toward(Decimal(1), Decimal(2))
3331 self.assertEqual(c.next_toward(1, 2), d)
3332 self.assertEqual(c.next_toward(Decimal(1), 2), d)
3333 self.assertEqual(c.next_toward(1, Decimal(2)), d)
3334 self.assertRaises(TypeError, c.next_toward, '1', 2)
3335 self.assertRaises(TypeError, c.next_toward, 1, '2')
3336
3337 def test_normalize(self):
3338 Decimal = self.decimal.Decimal
3339 Context = self.decimal.Context
3340
3341 c = Context()
3342 d = c.normalize(Decimal(10))
3343 self.assertEqual(c.normalize(10), d)
3344 self.assertRaises(TypeError, c.normalize, '10')
3345
3346 def test_number_class(self):
3347 Decimal = self.decimal.Decimal
3348 Context = self.decimal.Context
3349
3350 c = Context()
3351 self.assertEqual(c.number_class(123), c.number_class(Decimal(123)))
3352 self.assertEqual(c.number_class(0), c.number_class(Decimal(0)))
3353 self.assertEqual(c.number_class(-45), c.number_class(Decimal(-45)))
3354
3355 def test_plus(self):
3356 Decimal = self.decimal.Decimal
3357 Context = self.decimal.Context
3358
3359 c = Context()
3360 d = c.plus(Decimal(10))
3361 self.assertEqual(c.plus(10), d)
3362 self.assertRaises(TypeError, c.plus, '10')
3363
3364 def test_power(self):
3365 Decimal = self.decimal.Decimal
3366 Context = self.decimal.Context
3367
3368 c = Context()
3369 d = c.power(Decimal(1), Decimal(4))
3370 self.assertEqual(c.power(1, 4), d)
3371 self.assertEqual(c.power(Decimal(1), 4), d)
3372 self.assertEqual(c.power(1, Decimal(4)), d)
3373 self.assertEqual(c.power(Decimal(1), Decimal(4)), d)
3374 self.assertRaises(TypeError, c.power, '1', 4)
3375 self.assertRaises(TypeError, c.power, 1, '4')
3376 self.assertEqual(c.power(modulo=5, b=8, a=2), 1)
3377
3378 def test_quantize(self):
3379 Decimal = self.decimal.Decimal
3380 Context = self.decimal.Context
3381
3382 c = Context()
3383 d = c.quantize(Decimal(1), Decimal(2))
3384 self.assertEqual(c.quantize(1, 2), d)
3385 self.assertEqual(c.quantize(Decimal(1), 2), d)
3386 self.assertEqual(c.quantize(1, Decimal(2)), d)
3387 self.assertRaises(TypeError, c.quantize, '1', 2)
3388 self.assertRaises(TypeError, c.quantize, 1, '2')
3389
3390 def test_remainder(self):
3391 Decimal = self.decimal.Decimal
3392 Context = self.decimal.Context
3393
3394 c = Context()
3395 d = c.remainder(Decimal(1), Decimal(2))
3396 self.assertEqual(c.remainder(1, 2), d)
3397 self.assertEqual(c.remainder(Decimal(1), 2), d)
3398 self.assertEqual(c.remainder(1, Decimal(2)), d)
3399 self.assertRaises(TypeError, c.remainder, '1', 2)
3400 self.assertRaises(TypeError, c.remainder, 1, '2')
3401
3402 def test_remainder_near(self):
3403 Decimal = self.decimal.Decimal
3404 Context = self.decimal.Context
3405
3406 c = Context()
3407 d = c.remainder_near(Decimal(1), Decimal(2))
3408 self.assertEqual(c.remainder_near(1, 2), d)
3409 self.assertEqual(c.remainder_near(Decimal(1), 2), d)
3410 self.assertEqual(c.remainder_near(1, Decimal(2)), d)
3411 self.assertRaises(TypeError, c.remainder_near, '1', 2)
3412 self.assertRaises(TypeError, c.remainder_near, 1, '2')
3413
3414 def test_rotate(self):
3415 Decimal = self.decimal.Decimal
3416 Context = self.decimal.Context
3417
3418 c = Context()
3419 d = c.rotate(Decimal(1), Decimal(2))
3420 self.assertEqual(c.rotate(1, 2), d)
3421 self.assertEqual(c.rotate(Decimal(1), 2), d)
3422 self.assertEqual(c.rotate(1, Decimal(2)), d)
3423 self.assertRaises(TypeError, c.rotate, '1', 2)
3424 self.assertRaises(TypeError, c.rotate, 1, '2')
3425
3426 def test_sqrt(self):
3427 Decimal = self.decimal.Decimal
3428 Context = self.decimal.Context
3429
3430 c = Context()
3431 d = c.sqrt(Decimal(10))
3432 self.assertEqual(c.sqrt(10), d)
3433 self.assertRaises(TypeError, c.sqrt, '10')
3434
3435 def test_same_quantum(self):
3436 Decimal = self.decimal.Decimal
3437 Context = self.decimal.Context
3438
3439 c = Context()
3440 d = c.same_quantum(Decimal(1), Decimal(2))
3441 self.assertEqual(c.same_quantum(1, 2), d)
3442 self.assertEqual(c.same_quantum(Decimal(1), 2), d)
3443 self.assertEqual(c.same_quantum(1, Decimal(2)), d)
3444 self.assertRaises(TypeError, c.same_quantum, '1', 2)
3445 self.assertRaises(TypeError, c.same_quantum, 1, '2')
3446
3447 def test_scaleb(self):
3448 Decimal = self.decimal.Decimal
3449 Context = self.decimal.Context
3450
3451 c = Context()
3452 d = c.scaleb(Decimal(1), Decimal(2))
3453 self.assertEqual(c.scaleb(1, 2), d)
3454 self.assertEqual(c.scaleb(Decimal(1), 2), d)
3455 self.assertEqual(c.scaleb(1, Decimal(2)), d)
3456 self.assertRaises(TypeError, c.scaleb, '1', 2)
3457 self.assertRaises(TypeError, c.scaleb, 1, '2')
3458
3459 def test_shift(self):
3460 Decimal = self.decimal.Decimal
3461 Context = self.decimal.Context
3462
3463 c = Context()
3464 d = c.shift(Decimal(1), Decimal(2))
3465 self.assertEqual(c.shift(1, 2), d)
3466 self.assertEqual(c.shift(Decimal(1), 2), d)
3467 self.assertEqual(c.shift(1, Decimal(2)), d)
3468 self.assertRaises(TypeError, c.shift, '1', 2)
3469 self.assertRaises(TypeError, c.shift, 1, '2')
3470
3471 def test_subtract(self):
3472 Decimal = self.decimal.Decimal
3473 Context = self.decimal.Context
3474
3475 c = Context()
3476 d = c.subtract(Decimal(1), Decimal(2))
3477 self.assertEqual(c.subtract(1, 2), d)
3478 self.assertEqual(c.subtract(Decimal(1), 2), d)
3479 self.assertEqual(c.subtract(1, Decimal(2)), d)
3480 self.assertRaises(TypeError, c.subtract, '1', 2)
3481 self.assertRaises(TypeError, c.subtract, 1, '2')
3482
3483 def test_to_eng_string(self):
3484 Decimal = self.decimal.Decimal
3485 Context = self.decimal.Context
3486
3487 c = Context()
3488 d = c.to_eng_string(Decimal(10))
3489 self.assertEqual(c.to_eng_string(10), d)
3490 self.assertRaises(TypeError, c.to_eng_string, '10')
3491
3492 def test_to_sci_string(self):
3493 Decimal = self.decimal.Decimal
3494 Context = self.decimal.Context
3495
3496 c = Context()
3497 d = c.to_sci_string(Decimal(10))
3498 self.assertEqual(c.to_sci_string(10), d)
3499 self.assertRaises(TypeError, c.to_sci_string, '10')
3500
3501 def test_to_integral_exact(self):
3502 Decimal = self.decimal.Decimal
3503 Context = self.decimal.Context
3504
3505 c = Context()
3506 d = c.to_integral_exact(Decimal(10))
3507 self.assertEqual(c.to_integral_exact(10), d)
3508 self.assertRaises(TypeError, c.to_integral_exact, '10')
3509
3510 def test_to_integral_value(self):
3511 Decimal = self.decimal.Decimal
3512 Context = self.decimal.Context
3513
3514 c = Context()
3515 d = c.to_integral_value(Decimal(10))
3516 self.assertEqual(c.to_integral_value(10), d)
3517 self.assertRaises(TypeError, c.to_integral_value, '10')
3518 self.assertRaises(TypeError, c.to_integral_value, 10, 'x')
3519
3520class CContextAPItests(ContextAPItests):
3521 decimal = C
3522class PyContextAPItests(ContextAPItests):
3523 decimal = P
3524
3525class ContextWithStatement(unittest.TestCase):
3526 # Can't do these as docstrings until Python 2.6
3527 # as doctest can't handle __future__ statements
3528
3529 def test_localcontext(self):
3530 # Use a copy of the current context in the block
3531 getcontext = self.decimal.getcontext
3532 localcontext = self.decimal.localcontext
3533
3534 orig_ctx = getcontext()
3535 with localcontext() as enter_ctx:
3536 set_ctx = getcontext()
3537 final_ctx = getcontext()
3538 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
3539 self.assertIsNot(orig_ctx, set_ctx, 'did not copy the context')
3540 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
3541
3542 def test_localcontextarg(self):
3543 # Use a copy of the supplied context in the block
3544 Context = self.decimal.Context
3545 getcontext = self.decimal.getcontext
3546 localcontext = self.decimal.localcontext
3547
3548 localcontext = self.decimal.localcontext
3549 orig_ctx = getcontext()
3550 new_ctx = Context(prec=42)
3551 with localcontext(new_ctx) as enter_ctx:
3552 set_ctx = getcontext()
3553 final_ctx = getcontext()
3554 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
3555 self.assertEqual(set_ctx.prec, new_ctx.prec, 'did not set correct context')
3556 self.assertIsNot(new_ctx, set_ctx, 'did not copy the context')
3557 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
3558
3559 def test_nested_with_statements(self):
3560 # Use a copy of the supplied context in the block
3561 Decimal = self.decimal.Decimal
3562 Context = self.decimal.Context
3563 getcontext = self.decimal.getcontext
3564 localcontext = self.decimal.localcontext
3565 Clamped = self.decimal.Clamped
3566 Overflow = self.decimal.Overflow
3567
3568 orig_ctx = getcontext()
3569 orig_ctx.clear_flags()
3570 new_ctx = Context(Emax=384)
3571 with localcontext() as c1:
3572 self.assertEqual(c1.flags, orig_ctx.flags)
3573 self.assertEqual(c1.traps, orig_ctx.traps)
3574 c1.traps[Clamped] = True
3575 c1.Emin = -383
3576 self.assertNotEqual(orig_ctx.Emin, -383)
3577 self.assertRaises(Clamped, c1.create_decimal, '0e-999')
3578 self.assertTrue(c1.flags[Clamped])
3579 with localcontext(new_ctx) as c2:
3580 self.assertEqual(c2.flags, new_ctx.flags)
3581 self.assertEqual(c2.traps, new_ctx.traps)
3582 self.assertRaises(Overflow, c2.power, Decimal('3.4e200'), 2)
3583 self.assertFalse(c2.flags[Clamped])
3584 self.assertTrue(c2.flags[Overflow])
3585 del c2
3586 self.assertFalse(c1.flags[Overflow])
3587 del c1
3588 self.assertNotEqual(orig_ctx.Emin, -383)
3589 self.assertFalse(orig_ctx.flags[Clamped])
3590 self.assertFalse(orig_ctx.flags[Overflow])
3591 self.assertFalse(new_ctx.flags[Clamped])
3592 self.assertFalse(new_ctx.flags[Overflow])
3593
3594 def test_with_statements_gc1(self):
3595 localcontext = self.decimal.localcontext
3596
3597 with localcontext() as c1:
3598 del c1
3599 with localcontext() as c2:
3600 del c2
3601 with localcontext() as c3:
3602 del c3
3603 with localcontext() as c4:
3604 del c4
3605
3606 def test_with_statements_gc2(self):
3607 localcontext = self.decimal.localcontext
3608
3609 with localcontext() as c1:
3610 with localcontext(c1) as c2:
3611 del c1
3612 with localcontext(c2) as c3:
3613 del c2
3614 with localcontext(c3) as c4:
3615 del c3
3616 del c4
3617
3618 def test_with_statements_gc3(self):
3619 Context = self.decimal.Context
3620 localcontext = self.decimal.localcontext
3621 getcontext = self.decimal.getcontext
3622 setcontext = self.decimal.setcontext
3623
3624 with localcontext() as c1:
3625 del c1
3626 n1 = Context(prec=1)
3627 setcontext(n1)
3628 with localcontext(n1) as c2:
3629 del n1
3630 self.assertEqual(c2.prec, 1)
3631 del c2
3632 n2 = Context(prec=2)
3633 setcontext(n2)
3634 del n2
3635 self.assertEqual(getcontext().prec, 2)
3636 n3 = Context(prec=3)
3637 setcontext(n3)
3638 self.assertEqual(getcontext().prec, 3)
3639 with localcontext(n3) as c3:
3640 del n3
3641 self.assertEqual(c3.prec, 3)
3642 del c3
3643 n4 = Context(prec=4)
3644 setcontext(n4)
3645 del n4
3646 self.assertEqual(getcontext().prec, 4)
3647 with localcontext() as c4:
3648 self.assertEqual(c4.prec, 4)
3649 del c4
3650
3651class CContextWithStatement(ContextWithStatement):
3652 decimal = C
3653class PyContextWithStatement(ContextWithStatement):
3654 decimal = P
3655
3656class ContextFlags(unittest.TestCase):
3657
3658 def test_flags_irrelevant(self):
3659 # check that the result (numeric result + flags raised) of an
3660 # arithmetic operation doesn't depend on the current flags
3661 Decimal = self.decimal.Decimal
3662 Context = self.decimal.Context
3663 Inexact = self.decimal.Inexact
3664 Rounded = self.decimal.Rounded
3665 Underflow = self.decimal.Underflow
3666 Clamped = self.decimal.Clamped
3667 Subnormal = self.decimal.Subnormal
Stefan Krah1919b7e2012-03-21 18:25:23 +01003668
3669 def raise_error(context, flag):
3670 if self.decimal == C:
3671 context.flags[flag] = True
3672 if context.traps[flag]:
3673 raise flag
3674 else:
3675 context._raise_error(flag)
3676
3677 context = Context(prec=9, Emin = -425000000, Emax = 425000000,
3678 rounding=ROUND_HALF_EVEN, traps=[], flags=[])
3679
3680 # operations that raise various flags, in the form (function, arglist)
3681 operations = [
3682 (context._apply, [Decimal("100E-425000010")]),
3683 (context.sqrt, [Decimal(2)]),
3684 (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]),
3685 (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]),
3686 (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]),
3687 ]
3688
3689 # try various flags individually, then a whole lot at once
3690 flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal],
3691 [Inexact, Rounded, Underflow, Clamped, Subnormal]]
3692
3693 for fn, args in operations:
3694 # find answer and flags raised using a clean context
3695 context.clear_flags()
3696 ans = fn(*args)
3697 flags = [k for k, v in context.flags.items() if v]
3698
3699 for extra_flags in flagsets:
3700 # set flags, before calling operation
3701 context.clear_flags()
3702 for flag in extra_flags:
3703 raise_error(context, flag)
3704 new_ans = fn(*args)
3705
3706 # flags that we expect to be set after the operation
3707 expected_flags = list(flags)
3708 for flag in extra_flags:
3709 if flag not in expected_flags:
3710 expected_flags.append(flag)
3711 expected_flags.sort(key=id)
3712
3713 # flags we actually got
3714 new_flags = [k for k,v in context.flags.items() if v]
3715 new_flags.sort(key=id)
3716
3717 self.assertEqual(ans, new_ans,
3718 "operation produces different answers depending on flags set: " +
3719 "expected %s, got %s." % (ans, new_ans))
3720 self.assertEqual(new_flags, expected_flags,
3721 "operation raises different flags depending on flags set: " +
3722 "expected %s, got %s" % (expected_flags, new_flags))
3723
3724 def test_flag_comparisons(self):
3725 Context = self.decimal.Context
3726 Inexact = self.decimal.Inexact
3727 Rounded = self.decimal.Rounded
3728
3729 c = Context()
3730
3731 # Valid SignalDict
3732 self.assertNotEqual(c.flags, c.traps)
3733 self.assertNotEqual(c.traps, c.flags)
3734
3735 c.flags = c.traps
3736 self.assertEqual(c.flags, c.traps)
3737 self.assertEqual(c.traps, c.flags)
3738
3739 c.flags[Rounded] = True
3740 c.traps = c.flags
3741 self.assertEqual(c.flags, c.traps)
3742 self.assertEqual(c.traps, c.flags)
3743
3744 d = {}
3745 d.update(c.flags)
3746 self.assertEqual(d, c.flags)
3747 self.assertEqual(c.flags, d)
3748
3749 d[Inexact] = True
3750 self.assertNotEqual(d, c.flags)
3751 self.assertNotEqual(c.flags, d)
3752
3753 # Invalid SignalDict
3754 d = {Inexact:False}
3755 self.assertNotEqual(d, c.flags)
3756 self.assertNotEqual(c.flags, d)
3757
3758 d = ["xyz"]
3759 self.assertNotEqual(d, c.flags)
3760 self.assertNotEqual(c.flags, d)
3761
3762 @requires_IEEE_754
3763 def test_float_operation(self):
3764 Decimal = self.decimal.Decimal
3765 FloatOperation = self.decimal.FloatOperation
3766 localcontext = self.decimal.localcontext
3767
3768 with localcontext() as c:
3769 ##### trap is off by default
3770 self.assertFalse(c.traps[FloatOperation])
3771
3772 # implicit conversion sets the flag
3773 c.clear_flags()
3774 self.assertEqual(Decimal(7.5), 7.5)
3775 self.assertTrue(c.flags[FloatOperation])
3776
3777 c.clear_flags()
3778 self.assertEqual(c.create_decimal(7.5), 7.5)
3779 self.assertTrue(c.flags[FloatOperation])
3780
3781 # explicit conversion does not set the flag
3782 c.clear_flags()
3783 x = Decimal.from_float(7.5)
3784 self.assertFalse(c.flags[FloatOperation])
3785 # comparison sets the flag
3786 self.assertEqual(x, 7.5)
3787 self.assertTrue(c.flags[FloatOperation])
3788
3789 c.clear_flags()
3790 x = c.create_decimal_from_float(7.5)
3791 self.assertFalse(c.flags[FloatOperation])
3792 self.assertEqual(x, 7.5)
3793 self.assertTrue(c.flags[FloatOperation])
3794
3795 ##### set the trap
3796 c.traps[FloatOperation] = True
3797
3798 # implicit conversion raises
3799 c.clear_flags()
3800 self.assertRaises(FloatOperation, Decimal, 7.5)
3801 self.assertTrue(c.flags[FloatOperation])
3802
3803 c.clear_flags()
3804 self.assertRaises(FloatOperation, c.create_decimal, 7.5)
3805 self.assertTrue(c.flags[FloatOperation])
3806
3807 # explicit conversion is silent
3808 c.clear_flags()
3809 x = Decimal.from_float(7.5)
3810 self.assertFalse(c.flags[FloatOperation])
3811
3812 c.clear_flags()
3813 x = c.create_decimal_from_float(7.5)
3814 self.assertFalse(c.flags[FloatOperation])
3815
3816 def test_float_comparison(self):
3817 Decimal = self.decimal.Decimal
3818 Context = self.decimal.Context
3819 FloatOperation = self.decimal.FloatOperation
3820 localcontext = self.decimal.localcontext
3821
3822 def assert_attr(a, b, attr, context, signal=None):
3823 context.clear_flags()
3824 f = getattr(a, attr)
3825 if signal == FloatOperation:
3826 self.assertRaises(signal, f, b)
3827 else:
3828 self.assertIs(f(b), True)
3829 self.assertTrue(context.flags[FloatOperation])
3830
3831 small_d = Decimal('0.25')
3832 big_d = Decimal('3.0')
3833 small_f = 0.25
3834 big_f = 3.0
3835
3836 zero_d = Decimal('0.0')
3837 neg_zero_d = Decimal('-0.0')
3838 zero_f = 0.0
3839 neg_zero_f = -0.0
3840
3841 inf_d = Decimal('Infinity')
3842 neg_inf_d = Decimal('-Infinity')
3843 inf_f = float('inf')
3844 neg_inf_f = float('-inf')
3845
3846 def doit(c, signal=None):
3847 # Order
3848 for attr in '__lt__', '__le__':
3849 assert_attr(small_d, big_f, attr, c, signal)
3850
3851 for attr in '__gt__', '__ge__':
3852 assert_attr(big_d, small_f, attr, c, signal)
3853
3854 # Equality
3855 assert_attr(small_d, small_f, '__eq__', c, None)
3856
3857 assert_attr(neg_zero_d, neg_zero_f, '__eq__', c, None)
3858 assert_attr(neg_zero_d, zero_f, '__eq__', c, None)
3859
3860 assert_attr(zero_d, neg_zero_f, '__eq__', c, None)
3861 assert_attr(zero_d, zero_f, '__eq__', c, None)
3862
3863 assert_attr(neg_inf_d, neg_inf_f, '__eq__', c, None)
3864 assert_attr(inf_d, inf_f, '__eq__', c, None)
3865
3866 # Inequality
3867 assert_attr(small_d, big_f, '__ne__', c, None)
3868
3869 assert_attr(Decimal('0.1'), 0.1, '__ne__', c, None)
3870
3871 assert_attr(neg_inf_d, inf_f, '__ne__', c, None)
3872 assert_attr(inf_d, neg_inf_f, '__ne__', c, None)
3873
3874 assert_attr(Decimal('NaN'), float('nan'), '__ne__', c, None)
3875
3876 def test_containers(c, signal=None):
3877 c.clear_flags()
3878 s = set([100.0, Decimal('100.0')])
3879 self.assertEqual(len(s), 1)
3880 self.assertTrue(c.flags[FloatOperation])
3881
3882 c.clear_flags()
3883 if signal:
3884 self.assertRaises(signal, sorted, [1.0, Decimal('10.0')])
3885 else:
3886 s = sorted([10.0, Decimal('10.0')])
3887 self.assertTrue(c.flags[FloatOperation])
3888
3889 c.clear_flags()
3890 b = 10.0 in [Decimal('10.0'), 1.0]
3891 self.assertTrue(c.flags[FloatOperation])
3892
3893 c.clear_flags()
3894 b = 10.0 in {Decimal('10.0'):'a', 1.0:'b'}
3895 self.assertTrue(c.flags[FloatOperation])
3896
3897 nc = Context()
3898 with localcontext(nc) as c:
3899 self.assertFalse(c.traps[FloatOperation])
3900 doit(c, signal=None)
3901 test_containers(c, signal=None)
3902
3903 c.traps[FloatOperation] = True
3904 doit(c, signal=FloatOperation)
3905 test_containers(c, signal=FloatOperation)
3906
3907 def test_float_operation_default(self):
3908 Decimal = self.decimal.Decimal
3909 Context = self.decimal.Context
3910 Inexact = self.decimal.Inexact
3911 FloatOperation= self.decimal.FloatOperation
3912
3913 context = Context()
3914 self.assertFalse(context.flags[FloatOperation])
3915 self.assertFalse(context.traps[FloatOperation])
3916
3917 context.clear_traps()
3918 context.traps[Inexact] = True
3919 context.traps[FloatOperation] = True
3920 self.assertTrue(context.traps[FloatOperation])
3921 self.assertTrue(context.traps[Inexact])
3922
3923class CContextFlags(ContextFlags):
3924 decimal = C
3925class PyContextFlags(ContextFlags):
3926 decimal = P
3927
3928class SpecialContexts(unittest.TestCase):
3929 """Test the context templates."""
3930
3931 def test_context_templates(self):
3932 BasicContext = self.decimal.BasicContext
3933 ExtendedContext = self.decimal.ExtendedContext
3934 getcontext = self.decimal.getcontext
3935 setcontext = self.decimal.setcontext
3936 InvalidOperation = self.decimal.InvalidOperation
3937 DivisionByZero = self.decimal.DivisionByZero
3938 Overflow = self.decimal.Overflow
3939 Underflow = self.decimal.Underflow
3940 Clamped = self.decimal.Clamped
3941
3942 assert_signals(self, BasicContext, 'traps',
3943 [InvalidOperation, DivisionByZero, Overflow, Underflow, Clamped]
3944 )
3945
3946 savecontext = getcontext().copy()
3947 basic_context_prec = BasicContext.prec
3948 extended_context_prec = ExtendedContext.prec
3949
3950 ex = None
3951 try:
3952 BasicContext.prec = ExtendedContext.prec = 441
3953 for template in BasicContext, ExtendedContext:
3954 setcontext(template)
3955 c = getcontext()
3956 self.assertIsNot(c, template)
3957 self.assertEqual(c.prec, 441)
3958 except Exception as e:
3959 ex = e.__class__
3960 finally:
3961 BasicContext.prec = basic_context_prec
3962 ExtendedContext.prec = extended_context_prec
3963 setcontext(savecontext)
3964 if ex:
3965 raise ex
3966
3967 def test_default_context(self):
3968 DefaultContext = self.decimal.DefaultContext
3969 BasicContext = self.decimal.BasicContext
3970 ExtendedContext = self.decimal.ExtendedContext
3971 getcontext = self.decimal.getcontext
3972 setcontext = self.decimal.setcontext
3973 InvalidOperation = self.decimal.InvalidOperation
3974 DivisionByZero = self.decimal.DivisionByZero
3975 Overflow = self.decimal.Overflow
3976
3977 self.assertEqual(BasicContext.prec, 9)
3978 self.assertEqual(ExtendedContext.prec, 9)
3979
3980 assert_signals(self, DefaultContext, 'traps',
3981 [InvalidOperation, DivisionByZero, Overflow]
3982 )
3983
3984 savecontext = getcontext().copy()
3985 default_context_prec = DefaultContext.prec
3986
3987 ex = None
3988 try:
3989 c = getcontext()
3990 saveprec = c.prec
3991
3992 DefaultContext.prec = 961
3993 c = getcontext()
3994 self.assertEqual(c.prec, saveprec)
3995
3996 setcontext(DefaultContext)
3997 c = getcontext()
3998 self.assertIsNot(c, DefaultContext)
3999 self.assertEqual(c.prec, 961)
4000 except Exception as e:
4001 ex = e.__class__
4002 finally:
4003 DefaultContext.prec = default_context_prec
4004 setcontext(savecontext)
4005 if ex:
4006 raise ex
4007
4008class CSpecialContexts(SpecialContexts):
4009 decimal = C
4010class PySpecialContexts(SpecialContexts):
4011 decimal = P
4012
4013class ContextInputValidation(unittest.TestCase):
4014
4015 def test_invalid_context(self):
4016 Context = self.decimal.Context
4017 DefaultContext = self.decimal.DefaultContext
4018
4019 c = DefaultContext.copy()
4020
4021 # prec, Emax
4022 for attr in ['prec', 'Emax']:
4023 setattr(c, attr, 999999)
4024 self.assertEqual(getattr(c, attr), 999999)
4025 self.assertRaises(ValueError, setattr, c, attr, -1)
4026 self.assertRaises(TypeError, setattr, c, attr, 'xyz')
4027
4028 # Emin
4029 setattr(c, 'Emin', -999999)
4030 self.assertEqual(getattr(c, 'Emin'), -999999)
4031 self.assertRaises(ValueError, setattr, c, 'Emin', 1)
4032 self.assertRaises(TypeError, setattr, c, 'Emin', (1,2,3))
4033
Stefan Krah1919b7e2012-03-21 18:25:23 +01004034 self.assertRaises(TypeError, setattr, c, 'rounding', -1)
4035 self.assertRaises(TypeError, setattr, c, 'rounding', 9)
4036 self.assertRaises(TypeError, setattr, c, 'rounding', 1.0)
4037 self.assertRaises(TypeError, setattr, c, 'rounding', 'xyz')
4038
4039 # capitals, clamp
4040 for attr in ['capitals', 'clamp']:
4041 self.assertRaises(ValueError, setattr, c, attr, -1)
4042 self.assertRaises(ValueError, setattr, c, attr, 2)
4043 self.assertRaises(TypeError, setattr, c, attr, [1,2,3])
4044
4045 # Invalid attribute
4046 self.assertRaises(AttributeError, setattr, c, 'emax', 100)
4047
4048 # Invalid signal dict
4049 self.assertRaises(TypeError, setattr, c, 'flags', [])
4050 self.assertRaises(KeyError, setattr, c, 'flags', {})
4051 self.assertRaises(KeyError, setattr, c, 'traps',
4052 {'InvalidOperation':0})
4053
4054 # Attributes cannot be deleted
4055 for attr in ['prec', 'Emax', 'Emin', 'rounding', 'capitals', 'clamp',
4056 'flags', 'traps']:
4057 self.assertRaises(AttributeError, c.__delattr__, attr)
4058
4059 # Invalid attributes
4060 self.assertRaises(TypeError, getattr, c, 9)
4061 self.assertRaises(TypeError, setattr, c, 9)
4062
4063 # Invalid values in constructor
4064 self.assertRaises(TypeError, Context, rounding=999999)
4065 self.assertRaises(TypeError, Context, rounding='xyz')
4066 self.assertRaises(ValueError, Context, clamp=2)
4067 self.assertRaises(ValueError, Context, capitals=-1)
4068 self.assertRaises(KeyError, Context, flags=["P"])
4069 self.assertRaises(KeyError, Context, traps=["Q"])
4070
4071 # Type error in conversion
4072 self.assertRaises(TypeError, Context, flags=(0,1))
4073 self.assertRaises(TypeError, Context, traps=(1,0))
4074
4075class CContextInputValidation(ContextInputValidation):
4076 decimal = C
4077class PyContextInputValidation(ContextInputValidation):
4078 decimal = P
4079
4080class ContextSubclassing(unittest.TestCase):
4081
4082 def test_context_subclassing(self):
4083 decimal = self.decimal
4084 Decimal = decimal.Decimal
4085 Context = decimal.Context
Stefan Krah1919b7e2012-03-21 18:25:23 +01004086 Clamped = decimal.Clamped
4087 DivisionByZero = decimal.DivisionByZero
4088 Inexact = decimal.Inexact
4089 Overflow = decimal.Overflow
4090 Rounded = decimal.Rounded
4091 Subnormal = decimal.Subnormal
4092 Underflow = decimal.Underflow
4093 InvalidOperation = decimal.InvalidOperation
4094
4095 class MyContext(Context):
4096 def __init__(self, prec=None, rounding=None, Emin=None, Emax=None,
4097 capitals=None, clamp=None, flags=None,
4098 traps=None):
4099 Context.__init__(self)
4100 if prec is not None:
4101 self.prec = prec
4102 if rounding is not None:
4103 self.rounding = rounding
4104 if Emin is not None:
4105 self.Emin = Emin
4106 if Emax is not None:
4107 self.Emax = Emax
4108 if capitals is not None:
4109 self.capitals = capitals
4110 if clamp is not None:
4111 self.clamp = clamp
4112 if flags is not None:
4113 if isinstance(flags, list):
4114 flags = {v:(v in flags) for v in OrderedSignals[decimal] + flags}
4115 self.flags = flags
4116 if traps is not None:
4117 if isinstance(traps, list):
4118 traps = {v:(v in traps) for v in OrderedSignals[decimal] + traps}
4119 self.traps = traps
4120
4121 c = Context()
4122 d = MyContext()
4123 for attr in ('prec', 'rounding', 'Emin', 'Emax', 'capitals', 'clamp',
4124 'flags', 'traps'):
4125 self.assertEqual(getattr(c, attr), getattr(d, attr))
4126
4127 # prec
4128 self.assertRaises(ValueError, MyContext, **{'prec':-1})
4129 c = MyContext(prec=1)
4130 self.assertEqual(c.prec, 1)
4131 self.assertRaises(InvalidOperation, c.quantize, Decimal('9e2'), 0)
4132
4133 # rounding
4134 self.assertRaises(TypeError, MyContext, **{'rounding':'XYZ'})
4135 c = MyContext(rounding=ROUND_DOWN, prec=1)
4136 self.assertEqual(c.rounding, ROUND_DOWN)
4137 self.assertEqual(c.plus(Decimal('9.9')), 9)
4138
4139 # Emin
4140 self.assertRaises(ValueError, MyContext, **{'Emin':5})
4141 c = MyContext(Emin=-1, prec=1)
4142 self.assertEqual(c.Emin, -1)
4143 x = c.add(Decimal('1e-99'), Decimal('2.234e-2000'))
4144 self.assertEqual(x, Decimal('0.0'))
4145 for signal in (Inexact, Underflow, Subnormal, Rounded, Clamped):
4146 self.assertTrue(c.flags[signal])
4147
4148 # Emax
4149 self.assertRaises(ValueError, MyContext, **{'Emax':-1})
4150 c = MyContext(Emax=1, prec=1)
4151 self.assertEqual(c.Emax, 1)
4152 self.assertRaises(Overflow, c.add, Decimal('1e99'), Decimal('2.234e2000'))
4153 if self.decimal == C:
4154 for signal in (Inexact, Overflow, Rounded):
4155 self.assertTrue(c.flags[signal])
4156
4157 # capitals
4158 self.assertRaises(ValueError, MyContext, **{'capitals':-1})
4159 c = MyContext(capitals=0)
4160 self.assertEqual(c.capitals, 0)
4161 x = c.create_decimal('1E222')
4162 self.assertEqual(c.to_sci_string(x), '1e+222')
4163
4164 # clamp
4165 self.assertRaises(ValueError, MyContext, **{'clamp':2})
4166 c = MyContext(clamp=1, Emax=99)
4167 self.assertEqual(c.clamp, 1)
4168 x = c.plus(Decimal('1e99'))
4169 self.assertEqual(str(x), '1.000000000000000000000000000E+99')
4170
4171 # flags
4172 self.assertRaises(TypeError, MyContext, **{'flags':'XYZ'})
4173 c = MyContext(flags=[Rounded, DivisionByZero])
4174 for signal in (Rounded, DivisionByZero):
4175 self.assertTrue(c.flags[signal])
4176 c.clear_flags()
4177 for signal in OrderedSignals[decimal]:
4178 self.assertFalse(c.flags[signal])
4179
4180 # traps
4181 self.assertRaises(TypeError, MyContext, **{'traps':'XYZ'})
4182 c = MyContext(traps=[Rounded, DivisionByZero])
4183 for signal in (Rounded, DivisionByZero):
4184 self.assertTrue(c.traps[signal])
4185 c.clear_traps()
4186 for signal in OrderedSignals[decimal]:
4187 self.assertFalse(c.traps[signal])
4188
4189class CContextSubclassing(ContextSubclassing):
4190 decimal = C
4191class PyContextSubclassing(ContextSubclassing):
4192 decimal = P
4193
4194@skip_if_extra_functionality
4195class CheckAttributes(unittest.TestCase):
4196
4197 def test_module_attributes(self):
4198
4199 # Architecture dependent context limits
4200 self.assertEqual(C.MAX_PREC, P.MAX_PREC)
4201 self.assertEqual(C.MAX_EMAX, P.MAX_EMAX)
4202 self.assertEqual(C.MIN_EMIN, P.MIN_EMIN)
4203 self.assertEqual(C.MIN_ETINY, P.MIN_ETINY)
4204
4205 self.assertTrue(C.HAVE_THREADS is True or C.HAVE_THREADS is False)
4206 self.assertTrue(P.HAVE_THREADS is True or P.HAVE_THREADS is False)
4207
4208 self.assertEqual(C.__version__, P.__version__)
Stefan Krah45059eb2013-11-24 19:44:57 +01004209 self.assertEqual(C.__libmpdec_version__, P.__libmpdec_version__)
Stefan Krah1919b7e2012-03-21 18:25:23 +01004210
Stefan Krahb578f8a2014-09-10 17:58:15 +02004211 self.assertEqual(dir(C), dir(P))
Stefan Krah1919b7e2012-03-21 18:25:23 +01004212
4213 def test_context_attributes(self):
4214
4215 x = [s for s in dir(C.Context()) if '__' in s or not s.startswith('_')]
4216 y = [s for s in dir(P.Context()) if '__' in s or not s.startswith('_')]
4217 self.assertEqual(set(x) - set(y), set())
4218
4219 def test_decimal_attributes(self):
4220
4221 x = [s for s in dir(C.Decimal(9)) if '__' in s or not s.startswith('_')]
4222 y = [s for s in dir(C.Decimal(9)) if '__' in s or not s.startswith('_')]
4223 self.assertEqual(set(x) - set(y), set())
4224
4225class Coverage(unittest.TestCase):
4226
4227 def test_adjusted(self):
4228 Decimal = self.decimal.Decimal
4229
4230 self.assertEqual(Decimal('1234e9999').adjusted(), 10002)
4231 # XXX raise?
4232 self.assertEqual(Decimal('nan').adjusted(), 0)
4233 self.assertEqual(Decimal('inf').adjusted(), 0)
4234
4235 def test_canonical(self):
4236 Decimal = self.decimal.Decimal
4237 getcontext = self.decimal.getcontext
4238
4239 x = Decimal(9).canonical()
4240 self.assertEqual(x, 9)
4241
4242 c = getcontext()
4243 x = c.canonical(Decimal(9))
4244 self.assertEqual(x, 9)
4245
4246 def test_context_repr(self):
4247 c = self.decimal.DefaultContext.copy()
4248
4249 c.prec = 425000000
4250 c.Emax = 425000000
4251 c.Emin = -425000000
Stefan Krah59a4a932013-01-16 12:58:59 +01004252 c.rounding = ROUND_HALF_DOWN
Stefan Krah1919b7e2012-03-21 18:25:23 +01004253 c.capitals = 0
4254 c.clamp = 1
4255 for sig in OrderedSignals[self.decimal]:
4256 c.flags[sig] = False
4257 c.traps[sig] = False
4258
4259 s = c.__repr__()
4260 t = "Context(prec=425000000, rounding=ROUND_HALF_DOWN, " \
4261 "Emin=-425000000, Emax=425000000, capitals=0, clamp=1, " \
4262 "flags=[], traps=[])"
4263 self.assertEqual(s, t)
4264
4265 def test_implicit_context(self):
4266 Decimal = self.decimal.Decimal
4267 localcontext = self.decimal.localcontext
4268
4269 with localcontext() as c:
4270 c.prec = 1
4271 c.Emax = 1
4272 c.Emin = -1
4273
4274 # abs
4275 self.assertEqual(abs(Decimal("-10")), 10)
4276 # add
4277 self.assertEqual(Decimal("7") + 1, 8)
4278 # divide
4279 self.assertEqual(Decimal("10") / 5, 2)
4280 # divide_int
4281 self.assertEqual(Decimal("10") // 7, 1)
4282 # fma
4283 self.assertEqual(Decimal("1.2").fma(Decimal("0.01"), 1), 1)
4284 self.assertIs(Decimal("NaN").fma(7, 1).is_nan(), True)
4285 # three arg power
4286 self.assertEqual(pow(Decimal(10), 2, 7), 2)
4287 # exp
4288 self.assertEqual(Decimal("1.01").exp(), 3)
4289 # is_normal
4290 self.assertIs(Decimal("0.01").is_normal(), False)
4291 # is_subnormal
4292 self.assertIs(Decimal("0.01").is_subnormal(), True)
4293 # ln
4294 self.assertEqual(Decimal("20").ln(), 3)
4295 # log10
4296 self.assertEqual(Decimal("20").log10(), 1)
4297 # logb
4298 self.assertEqual(Decimal("580").logb(), 2)
4299 # logical_invert
4300 self.assertEqual(Decimal("10").logical_invert(), 1)
4301 # minus
4302 self.assertEqual(-Decimal("-10"), 10)
4303 # multiply
4304 self.assertEqual(Decimal("2") * 4, 8)
4305 # next_minus
4306 self.assertEqual(Decimal("10").next_minus(), 9)
4307 # next_plus
4308 self.assertEqual(Decimal("10").next_plus(), Decimal('2E+1'))
4309 # normalize
4310 self.assertEqual(Decimal("-10").normalize(), Decimal('-1E+1'))
4311 # number_class
4312 self.assertEqual(Decimal("10").number_class(), '+Normal')
4313 # plus
4314 self.assertEqual(+Decimal("-1"), -1)
4315 # remainder
4316 self.assertEqual(Decimal("10") % 7, 3)
4317 # subtract
4318 self.assertEqual(Decimal("10") - 7, 3)
4319 # to_integral_exact
4320 self.assertEqual(Decimal("1.12345").to_integral_exact(), 1)
4321
4322 # Boolean functions
4323 self.assertTrue(Decimal("1").is_canonical())
4324 self.assertTrue(Decimal("1").is_finite())
4325 self.assertTrue(Decimal("1").is_finite())
4326 self.assertTrue(Decimal("snan").is_snan())
4327 self.assertTrue(Decimal("-1").is_signed())
4328 self.assertTrue(Decimal("0").is_zero())
4329 self.assertTrue(Decimal("0").is_zero())
4330
4331 # Copy
4332 with localcontext() as c:
4333 c.prec = 10000
4334 x = 1228 ** 1523
4335 y = -Decimal(x)
4336
4337 z = y.copy_abs()
4338 self.assertEqual(z, x)
4339
4340 z = y.copy_negate()
4341 self.assertEqual(z, x)
4342
4343 z = y.copy_sign(Decimal(1))
4344 self.assertEqual(z, x)
4345
4346 def test_divmod(self):
4347 Decimal = self.decimal.Decimal
4348 localcontext = self.decimal.localcontext
4349 InvalidOperation = self.decimal.InvalidOperation
4350 DivisionByZero = self.decimal.DivisionByZero
4351
4352 with localcontext() as c:
4353 q, r = divmod(Decimal("10912837129"), 1001)
4354 self.assertEqual(q, Decimal('10901935'))
4355 self.assertEqual(r, Decimal('194'))
4356
4357 q, r = divmod(Decimal("NaN"), 7)
4358 self.assertTrue(q.is_nan() and r.is_nan())
4359
4360 c.traps[InvalidOperation] = False
4361 q, r = divmod(Decimal("NaN"), 7)
4362 self.assertTrue(q.is_nan() and r.is_nan())
4363
4364 c.traps[InvalidOperation] = False
4365 c.clear_flags()
4366 q, r = divmod(Decimal("inf"), Decimal("inf"))
4367 self.assertTrue(q.is_nan() and r.is_nan())
4368 self.assertTrue(c.flags[InvalidOperation])
4369
4370 c.clear_flags()
4371 q, r = divmod(Decimal("inf"), 101)
4372 self.assertTrue(q.is_infinite() and r.is_nan())
4373 self.assertTrue(c.flags[InvalidOperation])
4374
4375 c.clear_flags()
4376 q, r = divmod(Decimal(0), 0)
4377 self.assertTrue(q.is_nan() and r.is_nan())
4378 self.assertTrue(c.flags[InvalidOperation])
4379
4380 c.traps[DivisionByZero] = False
4381 c.clear_flags()
4382 q, r = divmod(Decimal(11), 0)
4383 self.assertTrue(q.is_infinite() and r.is_nan())
4384 self.assertTrue(c.flags[InvalidOperation] and
4385 c.flags[DivisionByZero])
4386
4387 def test_power(self):
4388 Decimal = self.decimal.Decimal
4389 localcontext = self.decimal.localcontext
4390 Overflow = self.decimal.Overflow
4391 Rounded = self.decimal.Rounded
4392
4393 with localcontext() as c:
4394 c.prec = 3
4395 c.clear_flags()
4396 self.assertEqual(Decimal("1.0") ** 100, Decimal('1.00'))
4397 self.assertTrue(c.flags[Rounded])
4398
4399 c.prec = 1
4400 c.Emax = 1
4401 c.Emin = -1
4402 c.clear_flags()
4403 c.traps[Overflow] = False
4404 self.assertEqual(Decimal(10000) ** Decimal("0.5"), Decimal('inf'))
4405 self.assertTrue(c.flags[Overflow])
4406
4407 def test_quantize(self):
4408 Decimal = self.decimal.Decimal
4409 localcontext = self.decimal.localcontext
4410 InvalidOperation = self.decimal.InvalidOperation
4411
4412 with localcontext() as c:
4413 c.prec = 1
4414 c.Emax = 1
4415 c.Emin = -1
4416 c.traps[InvalidOperation] = False
4417 x = Decimal(99).quantize(Decimal("1e1"))
4418 self.assertTrue(x.is_nan())
4419
4420 def test_radix(self):
4421 Decimal = self.decimal.Decimal
4422 getcontext = self.decimal.getcontext
4423
4424 c = getcontext()
4425 self.assertEqual(Decimal("1").radix(), 10)
4426 self.assertEqual(c.radix(), 10)
4427
4428 def test_rop(self):
4429 Decimal = self.decimal.Decimal
4430
4431 for attr in ('__radd__', '__rsub__', '__rmul__', '__rtruediv__',
4432 '__rdivmod__', '__rmod__', '__rfloordiv__', '__rpow__'):
4433 self.assertIs(getattr(Decimal("1"), attr)("xyz"), NotImplemented)
4434
4435 def test_round(self):
4436 # Python3 behavior: round() returns Decimal
4437 Decimal = self.decimal.Decimal
4438 getcontext = self.decimal.getcontext
4439
4440 c = getcontext()
4441 c.prec = 28
4442
4443 self.assertEqual(str(Decimal("9.99").__round__()), "10")
4444 self.assertEqual(str(Decimal("9.99e-5").__round__()), "0")
4445 self.assertEqual(str(Decimal("1.23456789").__round__(5)), "1.23457")
4446 self.assertEqual(str(Decimal("1.2345").__round__(10)), "1.2345000000")
4447 self.assertEqual(str(Decimal("1.2345").__round__(-10)), "0E+10")
4448
4449 self.assertRaises(TypeError, Decimal("1.23").__round__, "5")
4450 self.assertRaises(TypeError, Decimal("1.23").__round__, 5, 8)
4451
4452 def test_create_decimal(self):
4453 c = self.decimal.Context()
4454 self.assertRaises(ValueError, c.create_decimal, ["%"])
4455
4456 def test_int(self):
4457 Decimal = self.decimal.Decimal
4458 localcontext = self.decimal.localcontext
4459
4460 with localcontext() as c:
4461 c.prec = 9999
4462 x = Decimal(1221**1271) / 10**3923
4463 self.assertEqual(int(x), 1)
4464 self.assertEqual(x.to_integral(), 2)
4465
4466 def test_copy(self):
4467 Context = self.decimal.Context
4468
4469 c = Context()
4470 c.prec = 10000
4471 x = -(1172 ** 1712)
4472
4473 y = c.copy_abs(x)
4474 self.assertEqual(y, -x)
4475
4476 y = c.copy_negate(x)
4477 self.assertEqual(y, -x)
4478
4479 y = c.copy_sign(x, 1)
4480 self.assertEqual(y, -x)
4481
4482class CCoverage(Coverage):
4483 decimal = C
4484class PyCoverage(Coverage):
4485 decimal = P
4486
4487class PyFunctionality(unittest.TestCase):
4488 """Extra functionality in decimal.py"""
4489
Stefan Krah1919b7e2012-03-21 18:25:23 +01004490 def test_py_alternate_formatting(self):
4491 # triples giving a format, a Decimal, and the expected result
4492 Decimal = P.Decimal
4493 localcontext = P.localcontext
4494
4495 test_values = [
4496 # Issue 7094: Alternate formatting (specified by #)
4497 ('.0e', '1.0', '1e+0'),
4498 ('#.0e', '1.0', '1.e+0'),
4499 ('.0f', '1.0', '1'),
4500 ('#.0f', '1.0', '1.'),
4501 ('g', '1.1', '1.1'),
4502 ('#g', '1.1', '1.1'),
4503 ('.0g', '1', '1'),
4504 ('#.0g', '1', '1.'),
4505 ('.0%', '1.0', '100%'),
4506 ('#.0%', '1.0', '100.%'),
4507 ]
4508 for fmt, d, result in test_values:
4509 self.assertEqual(format(Decimal(d), fmt), result)
4510
4511class PyWhitebox(unittest.TestCase):
4512 """White box testing for decimal.py"""
4513
4514 def test_py_exact_power(self):
4515 # Rarely exercised lines in _power_exact.
4516 Decimal = P.Decimal
4517 localcontext = P.localcontext
4518
4519 with localcontext() as c:
4520 c.prec = 8
4521 x = Decimal(2**16) ** Decimal("-0.5")
4522 self.assertEqual(x, Decimal('0.00390625'))
4523
4524 x = Decimal(2**16) ** Decimal("-0.6")
4525 self.assertEqual(x, Decimal('0.0012885819'))
4526
4527 x = Decimal("256e7") ** Decimal("-0.5")
4528
4529 x = Decimal(152587890625) ** Decimal('-0.0625')
4530 self.assertEqual(x, Decimal("0.2"))
4531
4532 x = Decimal("152587890625e7") ** Decimal('-0.0625')
4533
4534 x = Decimal(5**2659) ** Decimal('-0.0625')
4535
4536 c.prec = 1
4537 x = Decimal("152587890625") ** Decimal('-0.5')
4538 c.prec = 201
4539 x = Decimal(2**578) ** Decimal("-0.5")
4540
4541 def test_py_immutability_operations(self):
Terry Jan Reedy0f847642013-03-11 18:34:00 -04004542 # Do operations and check that it didn't change internal objects.
Stefan Krah1919b7e2012-03-21 18:25:23 +01004543 Decimal = P.Decimal
4544 DefaultContext = P.DefaultContext
4545 setcontext = P.setcontext
4546
4547 c = DefaultContext.copy()
4548 c.traps = dict((s, 0) for s in OrderedSignals[P])
4549 setcontext(c)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004550
4551 d1 = Decimal('-25e55')
4552 b1 = Decimal('-25e55')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004553 d2 = Decimal('33e+33')
4554 b2 = Decimal('33e+33')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004555
4556 def checkSameDec(operation, useOther=False):
4557 if useOther:
4558 eval("d1." + operation + "(d2)")
4559 self.assertEqual(d1._sign, b1._sign)
4560 self.assertEqual(d1._int, b1._int)
4561 self.assertEqual(d1._exp, b1._exp)
4562 self.assertEqual(d2._sign, b2._sign)
4563 self.assertEqual(d2._int, b2._int)
4564 self.assertEqual(d2._exp, b2._exp)
4565 else:
4566 eval("d1." + operation + "()")
4567 self.assertEqual(d1._sign, b1._sign)
4568 self.assertEqual(d1._int, b1._int)
4569 self.assertEqual(d1._exp, b1._exp)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004570
4571 Decimal(d1)
4572 self.assertEqual(d1._sign, b1._sign)
4573 self.assertEqual(d1._int, b1._int)
4574 self.assertEqual(d1._exp, b1._exp)
4575
4576 checkSameDec("__abs__")
4577 checkSameDec("__add__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004578 checkSameDec("__divmod__", True)
Christian Heimes77c02eb2008-02-09 02:18:51 +00004579 checkSameDec("__eq__", True)
4580 checkSameDec("__ne__", True)
4581 checkSameDec("__le__", True)
4582 checkSameDec("__lt__", True)
4583 checkSameDec("__ge__", True)
4584 checkSameDec("__gt__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004585 checkSameDec("__float__")
4586 checkSameDec("__floordiv__", True)
4587 checkSameDec("__hash__")
4588 checkSameDec("__int__")
Christian Heimes969fe572008-01-25 11:23:10 +00004589 checkSameDec("__trunc__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004590 checkSameDec("__mod__", True)
4591 checkSameDec("__mul__", True)
4592 checkSameDec("__neg__")
Jack Diederich4dafcc42006-11-28 19:15:13 +00004593 checkSameDec("__bool__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004594 checkSameDec("__pos__")
4595 checkSameDec("__pow__", True)
4596 checkSameDec("__radd__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004597 checkSameDec("__rdivmod__", True)
4598 checkSameDec("__repr__")
4599 checkSameDec("__rfloordiv__", True)
4600 checkSameDec("__rmod__", True)
4601 checkSameDec("__rmul__", True)
4602 checkSameDec("__rpow__", True)
4603 checkSameDec("__rsub__", True)
4604 checkSameDec("__str__")
4605 checkSameDec("__sub__", True)
4606 checkSameDec("__truediv__", True)
4607 checkSameDec("adjusted")
4608 checkSameDec("as_tuple")
4609 checkSameDec("compare", True)
4610 checkSameDec("max", True)
4611 checkSameDec("min", True)
4612 checkSameDec("normalize")
4613 checkSameDec("quantize", True)
4614 checkSameDec("remainder_near", True)
4615 checkSameDec("same_quantum", True)
4616 checkSameDec("sqrt")
4617 checkSameDec("to_eng_string")
4618 checkSameDec("to_integral")
4619
Stefan Krah1919b7e2012-03-21 18:25:23 +01004620 def test_py_decimal_id(self):
4621 Decimal = P.Decimal
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004622
Stefan Krah1919b7e2012-03-21 18:25:23 +01004623 d = Decimal(45)
4624 e = Decimal(d)
4625 self.assertEqual(str(e), '45')
4626 self.assertNotEqual(id(d), id(e))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004627
Stefan Krah1919b7e2012-03-21 18:25:23 +01004628 def test_py_rescale(self):
4629 # Coverage
4630 Decimal = P.Decimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01004631 localcontext = P.localcontext
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004632
Stefan Krah1919b7e2012-03-21 18:25:23 +01004633 with localcontext() as c:
4634 x = Decimal("NaN")._rescale(3, ROUND_UP)
4635 self.assertTrue(x.is_nan())
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004636
Stefan Krah1919b7e2012-03-21 18:25:23 +01004637 def test_py__round(self):
4638 # Coverage
4639 Decimal = P.Decimal
Christian Heimes0348fb62008-03-26 12:55:56 +00004640
Stefan Krah1919b7e2012-03-21 18:25:23 +01004641 self.assertRaises(ValueError, Decimal("3.1234")._round, 0, ROUND_UP)
Mark Dickinsona2d1fe02009-10-29 12:23:02 +00004642
Stefan Krah1919b7e2012-03-21 18:25:23 +01004643class CFunctionality(unittest.TestCase):
4644 """Extra functionality in _decimal"""
Mark Dickinsona2d1fe02009-10-29 12:23:02 +00004645
Stefan Krah1919b7e2012-03-21 18:25:23 +01004646 @requires_extra_functionality
4647 def test_c_ieee_context(self):
4648 # issue 8786: Add support for IEEE 754 contexts to decimal module.
4649 IEEEContext = C.IEEEContext
4650 DECIMAL32 = C.DECIMAL32
4651 DECIMAL64 = C.DECIMAL64
4652 DECIMAL128 = C.DECIMAL128
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004653
Stefan Krah1919b7e2012-03-21 18:25:23 +01004654 def assert_rest(self, context):
4655 self.assertEqual(context.clamp, 1)
4656 assert_signals(self, context, 'traps', [])
4657 assert_signals(self, context, 'flags', [])
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004658
Stefan Krah1919b7e2012-03-21 18:25:23 +01004659 c = IEEEContext(DECIMAL32)
4660 self.assertEqual(c.prec, 7)
4661 self.assertEqual(c.Emax, 96)
4662 self.assertEqual(c.Emin, -95)
4663 assert_rest(self, c)
Raymond Hettinger82417ca2009-02-03 03:54:28 +00004664
Stefan Krah1919b7e2012-03-21 18:25:23 +01004665 c = IEEEContext(DECIMAL64)
4666 self.assertEqual(c.prec, 16)
4667 self.assertEqual(c.Emax, 384)
4668 self.assertEqual(c.Emin, -383)
4669 assert_rest(self, c)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004670
Stefan Krah1919b7e2012-03-21 18:25:23 +01004671 c = IEEEContext(DECIMAL128)
4672 self.assertEqual(c.prec, 34)
4673 self.assertEqual(c.Emax, 6144)
4674 self.assertEqual(c.Emin, -6143)
4675 assert_rest(self, c)
Raymond Hettinger5548be22004-07-05 18:49:38 +00004676
Stefan Krah1919b7e2012-03-21 18:25:23 +01004677 # Invalid values
4678 self.assertRaises(OverflowError, IEEEContext, 2**63)
4679 self.assertRaises(ValueError, IEEEContext, -1)
4680 self.assertRaises(ValueError, IEEEContext, 1024)
Mark Dickinson825fce32009-09-07 18:08:12 +00004681
Stefan Krah1919b7e2012-03-21 18:25:23 +01004682 @requires_extra_functionality
4683 def test_c_context(self):
4684 Context = C.Context
Christian Heimes969fe572008-01-25 11:23:10 +00004685
Stefan Krah1919b7e2012-03-21 18:25:23 +01004686 c = Context(flags=C.DecClamped, traps=C.DecRounded)
4687 self.assertEqual(c._flags, C.DecClamped)
4688 self.assertEqual(c._traps, C.DecRounded)
Raymond Hettinger771ed762009-01-03 19:20:32 +00004689
Stefan Krah1919b7e2012-03-21 18:25:23 +01004690 @requires_extra_functionality
4691 def test_constants(self):
4692 # Condition flags
4693 cond = (
4694 C.DecClamped, C.DecConversionSyntax, C.DecDivisionByZero,
4695 C.DecDivisionImpossible, C.DecDivisionUndefined,
4696 C.DecFpuError, C.DecInexact, C.DecInvalidContext,
4697 C.DecInvalidOperation, C.DecMallocError,
4698 C.DecFloatOperation, C.DecOverflow, C.DecRounded,
4699 C.DecSubnormal, C.DecUnderflow
Raymond Hettinger771ed762009-01-03 19:20:32 +00004700 )
Stefan Krah1919b7e2012-03-21 18:25:23 +01004701
4702 # IEEEContext
4703 self.assertEqual(C.DECIMAL32, 32)
4704 self.assertEqual(C.DECIMAL64, 64)
4705 self.assertEqual(C.DECIMAL128, 128)
4706 self.assertEqual(C.IEEE_CONTEXT_MAX_BITS, 512)
4707
Stefan Krah1919b7e2012-03-21 18:25:23 +01004708 # Conditions
4709 for i, v in enumerate(cond):
4710 self.assertEqual(v, 1<<i)
4711
4712 self.assertEqual(C.DecIEEEInvalidOperation,
4713 C.DecConversionSyntax|
4714 C.DecDivisionImpossible|
4715 C.DecDivisionUndefined|
4716 C.DecFpuError|
4717 C.DecInvalidContext|
4718 C.DecInvalidOperation|
4719 C.DecMallocError)
4720
4721 self.assertEqual(C.DecErrors,
4722 C.DecIEEEInvalidOperation|
4723 C.DecDivisionByZero)
4724
4725 self.assertEqual(C.DecTraps,
4726 C.DecErrors|C.DecOverflow|C.DecUnderflow)
4727
4728class CWhitebox(unittest.TestCase):
4729 """Whitebox testing for _decimal"""
4730
4731 def test_bignum(self):
4732 # Not exactly whitebox, but too slow with pydecimal.
4733
4734 Decimal = C.Decimal
4735 localcontext = C.localcontext
4736
4737 b1 = 10**35
4738 b2 = 10**36
4739 with localcontext() as c:
4740 c.prec = 1000000
4741 for i in range(5):
4742 a = random.randrange(b1, b2)
4743 b = random.randrange(1000, 1200)
4744 x = a ** b
4745 y = Decimal(a) ** Decimal(b)
4746 self.assertEqual(x, y)
4747
4748 def test_invalid_construction(self):
4749 self.assertRaises(TypeError, C.Decimal, 9, "xyz")
4750
4751 def test_c_input_restriction(self):
4752 # Too large for _decimal to be converted exactly
4753 Decimal = C.Decimal
4754 InvalidOperation = C.InvalidOperation
4755 Context = C.Context
4756 localcontext = C.localcontext
4757
4758 with localcontext(Context()):
4759 self.assertRaises(InvalidOperation, Decimal,
4760 "1e9999999999999999999")
4761
4762 def test_c_context_repr(self):
4763 # This test is _decimal-only because flags are not printed
4764 # in the same order.
4765 DefaultContext = C.DefaultContext
4766 FloatOperation = C.FloatOperation
Stefan Krah1919b7e2012-03-21 18:25:23 +01004767
4768 c = DefaultContext.copy()
4769
4770 c.prec = 425000000
4771 c.Emax = 425000000
4772 c.Emin = -425000000
4773 c.rounding = ROUND_HALF_DOWN
4774 c.capitals = 0
4775 c.clamp = 1
4776 for sig in OrderedSignals[C]:
4777 c.flags[sig] = True
4778 c.traps[sig] = True
4779 c.flags[FloatOperation] = True
4780 c.traps[FloatOperation] = True
4781
4782 s = c.__repr__()
4783 t = "Context(prec=425000000, rounding=ROUND_HALF_DOWN, " \
4784 "Emin=-425000000, Emax=425000000, capitals=0, clamp=1, " \
4785 "flags=[Clamped, InvalidOperation, DivisionByZero, Inexact, " \
4786 "FloatOperation, Overflow, Rounded, Subnormal, Underflow], " \
4787 "traps=[Clamped, InvalidOperation, DivisionByZero, Inexact, " \
4788 "FloatOperation, Overflow, Rounded, Subnormal, Underflow])"
4789 self.assertEqual(s, t)
4790
4791 def test_c_context_errors(self):
4792 Context = C.Context
4793 InvalidOperation = C.InvalidOperation
4794 Overflow = C.Overflow
4795 FloatOperation = C.FloatOperation
4796 localcontext = C.localcontext
4797 getcontext = C.getcontext
4798 setcontext = C.setcontext
4799 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
4800
4801 c = Context()
4802
4803 # SignalDict: input validation
4804 self.assertRaises(KeyError, c.flags.__setitem__, 801, 0)
4805 self.assertRaises(KeyError, c.traps.__setitem__, 801, 0)
4806 self.assertRaises(ValueError, c.flags.__delitem__, Overflow)
4807 self.assertRaises(ValueError, c.traps.__delitem__, InvalidOperation)
4808 self.assertRaises(TypeError, setattr, c, 'flags', ['x'])
4809 self.assertRaises(TypeError, setattr, c,'traps', ['y'])
4810 self.assertRaises(KeyError, setattr, c, 'flags', {0:1})
4811 self.assertRaises(KeyError, setattr, c, 'traps', {0:1})
4812
4813 # Test assignment from a signal dict with the correct length but
4814 # one invalid key.
4815 d = c.flags.copy()
4816 del d[FloatOperation]
4817 d["XYZ"] = 91283719
4818 self.assertRaises(KeyError, setattr, c, 'flags', d)
4819 self.assertRaises(KeyError, setattr, c, 'traps', d)
4820
4821 # Input corner cases
4822 int_max = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
4823 gt_max_emax = 10**18 if HAVE_CONFIG_64 else 10**9
4824
4825 # prec, Emax, Emin
4826 for attr in ['prec', 'Emax']:
4827 self.assertRaises(ValueError, setattr, c, attr, gt_max_emax)
4828 self.assertRaises(ValueError, setattr, c, 'Emin', -gt_max_emax)
4829
4830 # prec, Emax, Emin in context constructor
4831 self.assertRaises(ValueError, Context, prec=gt_max_emax)
4832 self.assertRaises(ValueError, Context, Emax=gt_max_emax)
4833 self.assertRaises(ValueError, Context, Emin=-gt_max_emax)
4834
4835 # Overflow in conversion
4836 self.assertRaises(OverflowError, Context, prec=int_max+1)
4837 self.assertRaises(OverflowError, Context, Emax=int_max+1)
4838 self.assertRaises(OverflowError, Context, Emin=-int_max-2)
Stefan Krah1919b7e2012-03-21 18:25:23 +01004839 self.assertRaises(OverflowError, Context, clamp=int_max+1)
4840 self.assertRaises(OverflowError, Context, capitals=int_max+1)
4841
4842 # OverflowError, general ValueError
4843 for attr in ('prec', 'Emin', 'Emax', 'capitals', 'clamp'):
4844 self.assertRaises(OverflowError, setattr, c, attr, int_max+1)
4845 self.assertRaises(OverflowError, setattr, c, attr, -int_max-2)
4846 if sys.platform != 'win32':
4847 self.assertRaises(ValueError, setattr, c, attr, int_max)
4848 self.assertRaises(ValueError, setattr, c, attr, -int_max-1)
4849
Stefan Krah1919b7e2012-03-21 18:25:23 +01004850 # OverflowError: _unsafe_setprec, _unsafe_setemin, _unsafe_setemax
4851 if C.MAX_PREC == 425000000:
4852 self.assertRaises(OverflowError, getattr(c, '_unsafe_setprec'),
4853 int_max+1)
4854 self.assertRaises(OverflowError, getattr(c, '_unsafe_setemax'),
4855 int_max+1)
4856 self.assertRaises(OverflowError, getattr(c, '_unsafe_setemin'),
4857 -int_max-2)
4858
4859 # ValueError: _unsafe_setprec, _unsafe_setemin, _unsafe_setemax
4860 if C.MAX_PREC == 425000000:
4861 self.assertRaises(ValueError, getattr(c, '_unsafe_setprec'), 0)
4862 self.assertRaises(ValueError, getattr(c, '_unsafe_setprec'),
4863 1070000001)
4864 self.assertRaises(ValueError, getattr(c, '_unsafe_setemax'), -1)
4865 self.assertRaises(ValueError, getattr(c, '_unsafe_setemax'),
4866 1070000001)
4867 self.assertRaises(ValueError, getattr(c, '_unsafe_setemin'),
4868 -1070000001)
4869 self.assertRaises(ValueError, getattr(c, '_unsafe_setemin'), 1)
4870
4871 # capitals, clamp
4872 for attr in ['capitals', 'clamp']:
4873 self.assertRaises(ValueError, setattr, c, attr, -1)
4874 self.assertRaises(ValueError, setattr, c, attr, 2)
4875 self.assertRaises(TypeError, setattr, c, attr, [1,2,3])
4876 if HAVE_CONFIG_64:
4877 self.assertRaises(ValueError, setattr, c, attr, 2**32)
4878 self.assertRaises(ValueError, setattr, c, attr, 2**32+1)
4879
4880 # Invalid local context
4881 self.assertRaises(TypeError, exec, 'with localcontext("xyz"): pass',
4882 locals())
Stefan Krah040e3112012-12-15 22:33:33 +01004883 self.assertRaises(TypeError, exec,
4884 'with localcontext(context=getcontext()): pass',
4885 locals())
Stefan Krah1919b7e2012-03-21 18:25:23 +01004886
4887 # setcontext
4888 saved_context = getcontext()
4889 self.assertRaises(TypeError, setcontext, "xyz")
4890 setcontext(saved_context)
4891
Stefan Krah59a4a932013-01-16 12:58:59 +01004892 def test_rounding_strings_interned(self):
4893
4894 self.assertIs(C.ROUND_UP, P.ROUND_UP)
4895 self.assertIs(C.ROUND_DOWN, P.ROUND_DOWN)
4896 self.assertIs(C.ROUND_CEILING, P.ROUND_CEILING)
4897 self.assertIs(C.ROUND_FLOOR, P.ROUND_FLOOR)
4898 self.assertIs(C.ROUND_HALF_UP, P.ROUND_HALF_UP)
4899 self.assertIs(C.ROUND_HALF_DOWN, P.ROUND_HALF_DOWN)
4900 self.assertIs(C.ROUND_HALF_EVEN, P.ROUND_HALF_EVEN)
4901 self.assertIs(C.ROUND_05UP, P.ROUND_05UP)
4902
Stefan Krah1919b7e2012-03-21 18:25:23 +01004903 @requires_extra_functionality
4904 def test_c_context_errors_extra(self):
4905 Context = C.Context
4906 InvalidOperation = C.InvalidOperation
4907 Overflow = C.Overflow
4908 localcontext = C.localcontext
4909 getcontext = C.getcontext
4910 setcontext = C.setcontext
4911 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
4912
4913 c = Context()
4914
4915 # Input corner cases
4916 int_max = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
4917
4918 # OverflowError, general ValueError
4919 self.assertRaises(OverflowError, setattr, c, '_allcr', int_max+1)
4920 self.assertRaises(OverflowError, setattr, c, '_allcr', -int_max-2)
4921 if sys.platform != 'win32':
4922 self.assertRaises(ValueError, setattr, c, '_allcr', int_max)
4923 self.assertRaises(ValueError, setattr, c, '_allcr', -int_max-1)
4924
4925 # OverflowError, general TypeError
4926 for attr in ('_flags', '_traps'):
4927 self.assertRaises(OverflowError, setattr, c, attr, int_max+1)
4928 self.assertRaises(OverflowError, setattr, c, attr, -int_max-2)
4929 if sys.platform != 'win32':
4930 self.assertRaises(TypeError, setattr, c, attr, int_max)
4931 self.assertRaises(TypeError, setattr, c, attr, -int_max-1)
4932
4933 # _allcr
4934 self.assertRaises(ValueError, setattr, c, '_allcr', -1)
4935 self.assertRaises(ValueError, setattr, c, '_allcr', 2)
4936 self.assertRaises(TypeError, setattr, c, '_allcr', [1,2,3])
4937 if HAVE_CONFIG_64:
4938 self.assertRaises(ValueError, setattr, c, '_allcr', 2**32)
4939 self.assertRaises(ValueError, setattr, c, '_allcr', 2**32+1)
4940
4941 # _flags, _traps
4942 for attr in ['_flags', '_traps']:
4943 self.assertRaises(TypeError, setattr, c, attr, 999999)
4944 self.assertRaises(TypeError, setattr, c, attr, 'x')
4945
4946 def test_c_valid_context(self):
4947 # These tests are for code coverage in _decimal.
4948 DefaultContext = C.DefaultContext
Stefan Krah1919b7e2012-03-21 18:25:23 +01004949 Clamped = C.Clamped
4950 Underflow = C.Underflow
4951 Inexact = C.Inexact
4952 Rounded = C.Rounded
4953 Subnormal = C.Subnormal
4954
4955 c = DefaultContext.copy()
4956
4957 # Exercise all getters and setters
4958 c.prec = 34
4959 c.rounding = ROUND_HALF_UP
4960 c.Emax = 3000
4961 c.Emin = -3000
4962 c.capitals = 1
4963 c.clamp = 0
4964
4965 self.assertEqual(c.prec, 34)
4966 self.assertEqual(c.rounding, ROUND_HALF_UP)
4967 self.assertEqual(c.Emin, -3000)
4968 self.assertEqual(c.Emax, 3000)
4969 self.assertEqual(c.capitals, 1)
4970 self.assertEqual(c.clamp, 0)
4971
4972 self.assertEqual(c.Etiny(), -3033)
4973 self.assertEqual(c.Etop(), 2967)
4974
4975 # Exercise all unsafe setters
4976 if C.MAX_PREC == 425000000:
4977 c._unsafe_setprec(999999999)
4978 c._unsafe_setemax(999999999)
4979 c._unsafe_setemin(-999999999)
4980 self.assertEqual(c.prec, 999999999)
4981 self.assertEqual(c.Emax, 999999999)
4982 self.assertEqual(c.Emin, -999999999)
4983
4984 @requires_extra_functionality
4985 def test_c_valid_context_extra(self):
4986 DefaultContext = C.DefaultContext
4987
4988 c = DefaultContext.copy()
4989 self.assertEqual(c._allcr, 1)
4990 c._allcr = 0
4991 self.assertEqual(c._allcr, 0)
4992
4993 def test_c_round(self):
4994 # Restricted input.
4995 Decimal = C.Decimal
4996 InvalidOperation = C.InvalidOperation
4997 localcontext = C.localcontext
4998 MAX_EMAX = C.MAX_EMAX
4999 MIN_ETINY = C.MIN_ETINY
5000 int_max = 2**63-1 if C.MAX_PREC > 425000000 else 2**31-1
5001
5002 with localcontext() as c:
5003 c.traps[InvalidOperation] = True
5004 self.assertRaises(InvalidOperation, Decimal("1.23").__round__,
5005 -int_max-1)
5006 self.assertRaises(InvalidOperation, Decimal("1.23").__round__,
5007 int_max)
5008 self.assertRaises(InvalidOperation, Decimal("1").__round__,
5009 int(MAX_EMAX+1))
5010 self.assertRaises(C.InvalidOperation, Decimal("1").__round__,
5011 -int(MIN_ETINY-1))
5012 self.assertRaises(OverflowError, Decimal("1.23").__round__,
5013 -int_max-2)
5014 self.assertRaises(OverflowError, Decimal("1.23").__round__,
5015 int_max+1)
5016
5017 def test_c_format(self):
5018 # Restricted input
5019 Decimal = C.Decimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01005020 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
5021
5022 self.assertRaises(TypeError, Decimal(1).__format__, "=10.10", [], 9)
5023 self.assertRaises(TypeError, Decimal(1).__format__, "=10.10", 9)
5024 self.assertRaises(TypeError, Decimal(1).__format__, [])
5025
Stefan Kraheb8c4512013-01-24 15:22:33 +01005026 self.assertRaises(ValueError, Decimal(1).__format__, "<>=10.10")
5027 maxsize = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
5028 self.assertRaises(ValueError, Decimal("1.23456789").__format__,
5029 "=%d.1" % maxsize)
Stefan Krah1919b7e2012-03-21 18:25:23 +01005030
5031 def test_c_integral(self):
5032 Decimal = C.Decimal
5033 Inexact = C.Inexact
Stefan Krah1919b7e2012-03-21 18:25:23 +01005034 localcontext = C.localcontext
5035
5036 x = Decimal(10)
5037 self.assertEqual(x.to_integral(), 10)
5038 self.assertRaises(TypeError, x.to_integral, '10')
5039 self.assertRaises(TypeError, x.to_integral, 10, 'x')
5040 self.assertRaises(TypeError, x.to_integral, 10)
5041
5042 self.assertEqual(x.to_integral_value(), 10)
5043 self.assertRaises(TypeError, x.to_integral_value, '10')
5044 self.assertRaises(TypeError, x.to_integral_value, 10, 'x')
5045 self.assertRaises(TypeError, x.to_integral_value, 10)
5046
5047 self.assertEqual(x.to_integral_exact(), 10)
5048 self.assertRaises(TypeError, x.to_integral_exact, '10')
5049 self.assertRaises(TypeError, x.to_integral_exact, 10, 'x')
5050 self.assertRaises(TypeError, x.to_integral_exact, 10)
5051
5052 with localcontext() as c:
5053 x = Decimal("99999999999999999999999999.9").to_integral_value(ROUND_UP)
5054 self.assertEqual(x, Decimal('100000000000000000000000000'))
5055
5056 x = Decimal("99999999999999999999999999.9").to_integral_exact(ROUND_UP)
5057 self.assertEqual(x, Decimal('100000000000000000000000000'))
5058
5059 c.traps[Inexact] = True
5060 self.assertRaises(Inexact, Decimal("999.9").to_integral_exact, ROUND_UP)
5061
5062 def test_c_funcs(self):
5063 # Invalid arguments
5064 Decimal = C.Decimal
5065 InvalidOperation = C.InvalidOperation
5066 DivisionByZero = C.DivisionByZero
Stefan Krah1919b7e2012-03-21 18:25:23 +01005067 getcontext = C.getcontext
5068 localcontext = C.localcontext
5069
5070 self.assertEqual(Decimal('9.99e10').to_eng_string(), '99.9E+9')
5071
5072 self.assertRaises(TypeError, pow, Decimal(1), 2, "3")
5073 self.assertRaises(TypeError, Decimal(9).number_class, "x", "y")
5074 self.assertRaises(TypeError, Decimal(9).same_quantum, 3, "x", "y")
5075
Raymond Hettinger771ed762009-01-03 19:20:32 +00005076 self.assertRaises(
Stefan Krah1919b7e2012-03-21 18:25:23 +01005077 TypeError,
5078 Decimal("1.23456789").quantize, Decimal('1e-100000'), []
Raymond Hettinger771ed762009-01-03 19:20:32 +00005079 )
Stefan Krah1919b7e2012-03-21 18:25:23 +01005080 self.assertRaises(
5081 TypeError,
5082 Decimal("1.23456789").quantize, Decimal('1e-100000'), getcontext()
5083 )
5084 self.assertRaises(
5085 TypeError,
5086 Decimal("1.23456789").quantize, Decimal('1e-100000'), 10
5087 )
5088 self.assertRaises(
5089 TypeError,
5090 Decimal("1.23456789").quantize, Decimal('1e-100000'), ROUND_UP, 1000
5091 )
Raymond Hettinger771ed762009-01-03 19:20:32 +00005092
Stefan Krah1919b7e2012-03-21 18:25:23 +01005093 with localcontext() as c:
5094 c.clear_traps()
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00005095
Stefan Krah1919b7e2012-03-21 18:25:23 +01005096 # Invalid arguments
5097 self.assertRaises(TypeError, c.copy_sign, Decimal(1), "x", "y")
5098 self.assertRaises(TypeError, c.canonical, 200)
5099 self.assertRaises(TypeError, c.is_canonical, 200)
5100 self.assertRaises(TypeError, c.divmod, 9, 8, "x", "y")
5101 self.assertRaises(TypeError, c.same_quantum, 9, 3, "x", "y")
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00005102
Stefan Krah1919b7e2012-03-21 18:25:23 +01005103 self.assertEqual(str(c.canonical(Decimal(200))), '200')
5104 self.assertEqual(c.radix(), 10)
Raymond Hettinger0aeac102004-07-05 22:53:03 +00005105
Stefan Krah1919b7e2012-03-21 18:25:23 +01005106 c.traps[DivisionByZero] = True
5107 self.assertRaises(DivisionByZero, Decimal(9).__divmod__, 0)
5108 self.assertRaises(DivisionByZero, c.divmod, 9, 0)
5109 self.assertTrue(c.flags[InvalidOperation])
Raymond Hettinger955d2b22004-08-08 20:17:45 +00005110
Stefan Krah1919b7e2012-03-21 18:25:23 +01005111 c.clear_flags()
5112 c.traps[InvalidOperation] = True
5113 self.assertRaises(InvalidOperation, Decimal(9).__divmod__, 0)
5114 self.assertRaises(InvalidOperation, c.divmod, 9, 0)
5115 self.assertTrue(c.flags[DivisionByZero])
Mark Dickinsonb1d8e322010-05-22 18:35:36 +00005116
Stefan Krah1919b7e2012-03-21 18:25:23 +01005117 c.traps[InvalidOperation] = True
5118 c.prec = 2
5119 self.assertRaises(InvalidOperation, pow, Decimal(1000), 1, 501)
Mark Dickinson84230a12010-02-18 14:49:50 +00005120
Stefan Krah040e3112012-12-15 22:33:33 +01005121 def test_va_args_exceptions(self):
5122 Decimal = C.Decimal
5123 Context = C.Context
5124
5125 x = Decimal("10001111111")
5126
5127 for attr in ['exp', 'is_normal', 'is_subnormal', 'ln', 'log10',
5128 'logb', 'logical_invert', 'next_minus', 'next_plus',
5129 'normalize', 'number_class', 'sqrt', 'to_eng_string']:
5130 func = getattr(x, attr)
5131 self.assertRaises(TypeError, func, context="x")
5132 self.assertRaises(TypeError, func, "x", context=None)
5133
5134 for attr in ['compare', 'compare_signal', 'logical_and',
5135 'logical_or', 'max', 'max_mag', 'min', 'min_mag',
5136 'remainder_near', 'rotate', 'scaleb', 'shift']:
5137 func = getattr(x, attr)
5138 self.assertRaises(TypeError, func, context="x")
5139 self.assertRaises(TypeError, func, "x", context=None)
5140
5141 self.assertRaises(TypeError, x.to_integral, rounding=None, context=[])
5142 self.assertRaises(TypeError, x.to_integral, rounding={}, context=[])
5143 self.assertRaises(TypeError, x.to_integral, [], [])
5144
5145 self.assertRaises(TypeError, x.to_integral_value, rounding=None, context=[])
5146 self.assertRaises(TypeError, x.to_integral_value, rounding={}, context=[])
5147 self.assertRaises(TypeError, x.to_integral_value, [], [])
5148
5149 self.assertRaises(TypeError, x.to_integral_exact, rounding=None, context=[])
5150 self.assertRaises(TypeError, x.to_integral_exact, rounding={}, context=[])
5151 self.assertRaises(TypeError, x.to_integral_exact, [], [])
5152
5153 self.assertRaises(TypeError, x.fma, 1, 2, context="x")
5154 self.assertRaises(TypeError, x.fma, 1, 2, "x", context=None)
5155
5156 self.assertRaises(TypeError, x.quantize, 1, [], context=None)
5157 self.assertRaises(TypeError, x.quantize, 1, [], rounding=None)
5158 self.assertRaises(TypeError, x.quantize, 1, [], [])
5159
5160 c = Context()
5161 self.assertRaises(TypeError, c.power, 1, 2, mod="x")
5162 self.assertRaises(TypeError, c.power, 1, "x", mod=None)
5163 self.assertRaises(TypeError, c.power, "x", 2, mod=None)
5164
Stefan Krah1919b7e2012-03-21 18:25:23 +01005165 @requires_extra_functionality
5166 def test_c_context_templates(self):
5167 self.assertEqual(
5168 C.BasicContext._traps,
5169 C.DecIEEEInvalidOperation|C.DecDivisionByZero|C.DecOverflow|
5170 C.DecUnderflow|C.DecClamped
5171 )
5172 self.assertEqual(
5173 C.DefaultContext._traps,
5174 C.DecIEEEInvalidOperation|C.DecDivisionByZero|C.DecOverflow
5175 )
Mark Dickinson84230a12010-02-18 14:49:50 +00005176
Stefan Krah1919b7e2012-03-21 18:25:23 +01005177 @requires_extra_functionality
5178 def test_c_signal_dict(self):
Mark Dickinson84230a12010-02-18 14:49:50 +00005179
Stefan Krah1919b7e2012-03-21 18:25:23 +01005180 # SignalDict coverage
5181 Context = C.Context
5182 DefaultContext = C.DefaultContext
Mark Dickinson84230a12010-02-18 14:49:50 +00005183
Stefan Krah1919b7e2012-03-21 18:25:23 +01005184 InvalidOperation = C.InvalidOperation
5185 DivisionByZero = C.DivisionByZero
5186 Overflow = C.Overflow
5187 Subnormal = C.Subnormal
5188 Underflow = C.Underflow
5189 Rounded = C.Rounded
5190 Inexact = C.Inexact
5191 Clamped = C.Clamped
Mark Dickinson84230a12010-02-18 14:49:50 +00005192
Stefan Krah1919b7e2012-03-21 18:25:23 +01005193 DecClamped = C.DecClamped
5194 DecInvalidOperation = C.DecInvalidOperation
5195 DecIEEEInvalidOperation = C.DecIEEEInvalidOperation
Mark Dickinson84230a12010-02-18 14:49:50 +00005196
Stefan Krah1919b7e2012-03-21 18:25:23 +01005197 def assertIsExclusivelySet(signal, signal_dict):
5198 for sig in signal_dict:
5199 if sig == signal:
5200 self.assertTrue(signal_dict[sig])
5201 else:
5202 self.assertFalse(signal_dict[sig])
Mark Dickinson84230a12010-02-18 14:49:50 +00005203
Stefan Krah1919b7e2012-03-21 18:25:23 +01005204 c = DefaultContext.copy()
Mark Dickinson84230a12010-02-18 14:49:50 +00005205
Stefan Krah1919b7e2012-03-21 18:25:23 +01005206 # Signal dict methods
5207 self.assertTrue(Overflow in c.traps)
5208 c.clear_traps()
5209 for k in c.traps.keys():
5210 c.traps[k] = True
5211 for v in c.traps.values():
5212 self.assertTrue(v)
5213 c.clear_traps()
5214 for k, v in c.traps.items():
5215 self.assertFalse(v)
Mark Dickinson84230a12010-02-18 14:49:50 +00005216
Stefan Krah1919b7e2012-03-21 18:25:23 +01005217 self.assertFalse(c.flags.get(Overflow))
5218 self.assertIs(c.flags.get("x"), None)
5219 self.assertEqual(c.flags.get("x", "y"), "y")
5220 self.assertRaises(TypeError, c.flags.get, "x", "y", "z")
Mark Dickinson84230a12010-02-18 14:49:50 +00005221
Stefan Krah1919b7e2012-03-21 18:25:23 +01005222 self.assertEqual(len(c.flags), len(c.traps))
5223 s = sys.getsizeof(c.flags)
5224 s = sys.getsizeof(c.traps)
5225 s = c.flags.__repr__()
Mark Dickinson84230a12010-02-18 14:49:50 +00005226
Stefan Krah1919b7e2012-03-21 18:25:23 +01005227 # Set flags/traps.
5228 c.clear_flags()
5229 c._flags = DecClamped
5230 self.assertTrue(c.flags[Clamped])
Mark Dickinson84230a12010-02-18 14:49:50 +00005231
Stefan Krah1919b7e2012-03-21 18:25:23 +01005232 c.clear_traps()
5233 c._traps = DecInvalidOperation
5234 self.assertTrue(c.traps[InvalidOperation])
Mark Dickinson84230a12010-02-18 14:49:50 +00005235
Stefan Krah1919b7e2012-03-21 18:25:23 +01005236 # Set flags/traps from dictionary.
5237 c.clear_flags()
5238 d = c.flags.copy()
5239 d[DivisionByZero] = True
5240 c.flags = d
5241 assertIsExclusivelySet(DivisionByZero, c.flags)
Mark Dickinson84230a12010-02-18 14:49:50 +00005242
Stefan Krah1919b7e2012-03-21 18:25:23 +01005243 c.clear_traps()
5244 d = c.traps.copy()
5245 d[Underflow] = True
5246 c.traps = d
5247 assertIsExclusivelySet(Underflow, c.traps)
Mark Dickinson84230a12010-02-18 14:49:50 +00005248
Stefan Krah1919b7e2012-03-21 18:25:23 +01005249 # Random constructors
5250 IntSignals = {
5251 Clamped: C.DecClamped,
5252 Rounded: C.DecRounded,
5253 Inexact: C.DecInexact,
5254 Subnormal: C.DecSubnormal,
5255 Underflow: C.DecUnderflow,
5256 Overflow: C.DecOverflow,
5257 DivisionByZero: C.DecDivisionByZero,
5258 InvalidOperation: C.DecIEEEInvalidOperation
5259 }
5260 IntCond = [
5261 C.DecDivisionImpossible, C.DecDivisionUndefined, C.DecFpuError,
5262 C.DecInvalidContext, C.DecInvalidOperation, C.DecMallocError,
5263 C.DecConversionSyntax,
5264 ]
Mark Dickinsonb455e582011-05-22 12:53:18 +01005265
Stefan Krah1919b7e2012-03-21 18:25:23 +01005266 lim = len(OrderedSignals[C])
5267 for r in range(lim):
5268 for t in range(lim):
Stefan Krah59a4a932013-01-16 12:58:59 +01005269 for round in RoundingModes:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005270 flags = random.sample(OrderedSignals[C], r)
5271 traps = random.sample(OrderedSignals[C], t)
5272 prec = random.randrange(1, 10000)
5273 emin = random.randrange(-10000, 0)
5274 emax = random.randrange(0, 10000)
5275 clamp = random.randrange(0, 2)
5276 caps = random.randrange(0, 2)
5277 cr = random.randrange(0, 2)
5278 c = Context(prec=prec, rounding=round, Emin=emin, Emax=emax,
5279 capitals=caps, clamp=clamp, flags=list(flags),
5280 traps=list(traps))
Mark Dickinson84230a12010-02-18 14:49:50 +00005281
Stefan Krah1919b7e2012-03-21 18:25:23 +01005282 self.assertEqual(c.prec, prec)
5283 self.assertEqual(c.rounding, round)
5284 self.assertEqual(c.Emin, emin)
5285 self.assertEqual(c.Emax, emax)
5286 self.assertEqual(c.capitals, caps)
5287 self.assertEqual(c.clamp, clamp)
Mark Dickinson84230a12010-02-18 14:49:50 +00005288
Stefan Krah1919b7e2012-03-21 18:25:23 +01005289 f = 0
5290 for x in flags:
5291 f |= IntSignals[x]
5292 self.assertEqual(c._flags, f)
Mark Dickinson84230a12010-02-18 14:49:50 +00005293
Stefan Krah1919b7e2012-03-21 18:25:23 +01005294 f = 0
5295 for x in traps:
5296 f |= IntSignals[x]
5297 self.assertEqual(c._traps, f)
Mark Dickinson84230a12010-02-18 14:49:50 +00005298
Stefan Krah1919b7e2012-03-21 18:25:23 +01005299 for cond in IntCond:
5300 c._flags = cond
5301 self.assertTrue(c._flags&DecIEEEInvalidOperation)
5302 assertIsExclusivelySet(InvalidOperation, c.flags)
Mark Dickinson84230a12010-02-18 14:49:50 +00005303
Stefan Krah1919b7e2012-03-21 18:25:23 +01005304 for cond in IntCond:
5305 c._traps = cond
5306 self.assertTrue(c._traps&DecIEEEInvalidOperation)
5307 assertIsExclusivelySet(InvalidOperation, c.traps)
Mark Dickinson84230a12010-02-18 14:49:50 +00005308
Stefan Krah1919b7e2012-03-21 18:25:23 +01005309 def test_invalid_override(self):
5310 Decimal = C.Decimal
Mark Dickinson84230a12010-02-18 14:49:50 +00005311
Stefan Krah1919b7e2012-03-21 18:25:23 +01005312 try:
5313 from locale import CHAR_MAX
5314 except ImportError:
Zachary Ware9fe6d862013-12-08 00:20:35 -06005315 self.skipTest('locale.CHAR_MAX not available')
Mark Dickinson84230a12010-02-18 14:49:50 +00005316
Stefan Krah1919b7e2012-03-21 18:25:23 +01005317 def make_grouping(lst):
5318 return ''.join([chr(x) for x in lst])
Mark Dickinson84230a12010-02-18 14:49:50 +00005319
Stefan Krah1919b7e2012-03-21 18:25:23 +01005320 def get_fmt(x, override=None, fmt='n'):
5321 return Decimal(x).__format__(fmt, override)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005322
Stefan Krah1919b7e2012-03-21 18:25:23 +01005323 invalid_grouping = {
5324 'decimal_point' : ',',
5325 'grouping' : make_grouping([255, 255, 0]),
5326 'thousands_sep' : ','
5327 }
5328 invalid_dot = {
5329 'decimal_point' : 'xxxxx',
5330 'grouping' : make_grouping([3, 3, 0]),
5331 'thousands_sep' : ','
5332 }
5333 invalid_sep = {
5334 'decimal_point' : '.',
5335 'grouping' : make_grouping([3, 3, 0]),
5336 'thousands_sep' : 'yyyyy'
5337 }
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005338
Stefan Krah1919b7e2012-03-21 18:25:23 +01005339 if CHAR_MAX == 127: # negative grouping in override
5340 self.assertRaises(ValueError, get_fmt, 12345,
5341 invalid_grouping, 'g')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005342
Stefan Krah1919b7e2012-03-21 18:25:23 +01005343 self.assertRaises(ValueError, get_fmt, 12345, invalid_dot, 'g')
5344 self.assertRaises(ValueError, get_fmt, 12345, invalid_sep, 'g')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005345
Stefan Krah0774e9b2012-04-05 15:21:58 +02005346 def test_exact_conversion(self):
5347 Decimal = C.Decimal
5348 localcontext = C.localcontext
5349 InvalidOperation = C.InvalidOperation
5350
5351 with localcontext() as c:
5352
5353 c.traps[InvalidOperation] = True
5354
5355 # Clamped
5356 x = "0e%d" % sys.maxsize
5357 self.assertRaises(InvalidOperation, Decimal, x)
5358
5359 x = "0e%d" % (-sys.maxsize-1)
5360 self.assertRaises(InvalidOperation, Decimal, x)
5361
5362 # Overflow
5363 x = "1e%d" % sys.maxsize
5364 self.assertRaises(InvalidOperation, Decimal, x)
5365
5366 # Underflow
5367 x = "1e%d" % (-sys.maxsize-1)
5368 self.assertRaises(InvalidOperation, Decimal, x)
5369
Stefan Krahff3eca02012-04-05 15:46:19 +02005370 def test_from_tuple(self):
5371 Decimal = C.Decimal
5372 localcontext = C.localcontext
5373 InvalidOperation = C.InvalidOperation
5374 Overflow = C.Overflow
5375 Underflow = C.Underflow
5376
5377 with localcontext() as c:
5378
5379 c.traps[InvalidOperation] = True
5380 c.traps[Overflow] = True
5381 c.traps[Underflow] = True
5382
5383 # SSIZE_MAX
5384 x = (1, (), sys.maxsize)
5385 self.assertEqual(str(c.create_decimal(x)), '-0E+999999')
5386 self.assertRaises(InvalidOperation, Decimal, x)
5387
5388 x = (1, (0, 1, 2), sys.maxsize)
5389 self.assertRaises(Overflow, c.create_decimal, x)
5390 self.assertRaises(InvalidOperation, Decimal, x)
5391
5392 # SSIZE_MIN
5393 x = (1, (), -sys.maxsize-1)
5394 self.assertEqual(str(c.create_decimal(x)), '-0E-1000026')
5395 self.assertRaises(InvalidOperation, Decimal, x)
5396
5397 x = (1, (0, 1, 2), -sys.maxsize-1)
5398 self.assertRaises(Underflow, c.create_decimal, x)
5399 self.assertRaises(InvalidOperation, Decimal, x)
5400
5401 # OverflowError
5402 x = (1, (), sys.maxsize+1)
5403 self.assertRaises(OverflowError, c.create_decimal, x)
5404 self.assertRaises(OverflowError, Decimal, x)
5405
5406 x = (1, (), -sys.maxsize-2)
5407 self.assertRaises(OverflowError, c.create_decimal, x)
5408 self.assertRaises(OverflowError, Decimal, x)
5409
5410 # Specials
5411 x = (1, (), "N")
5412 self.assertEqual(str(Decimal(x)), '-sNaN')
5413 x = (1, (0,), "N")
5414 self.assertEqual(str(Decimal(x)), '-sNaN')
5415 x = (1, (0, 1), "N")
5416 self.assertEqual(str(Decimal(x)), '-sNaN1')
5417
Stefan Krah891ca9e2013-05-29 19:14:17 +02005418 def test_sizeof(self):
5419 Decimal = C.Decimal
5420 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
5421
5422 self.assertGreater(Decimal(0).__sizeof__(), 0)
5423 if HAVE_CONFIG_64:
5424 x = Decimal(10**(19*24)).__sizeof__()
5425 y = Decimal(10**(19*25)).__sizeof__()
5426 self.assertEqual(y, x+8)
5427 else:
5428 x = Decimal(10**(9*24)).__sizeof__()
5429 y = Decimal(10**(9*25)).__sizeof__()
5430 self.assertEqual(y, x+4)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005431
Stefan Krah6b794b82014-05-01 17:42:33 +02005432@requires_docstrings
5433@unittest.skipUnless(C, "test requires C version")
Stefan Krah5de1f822014-05-01 15:53:42 +02005434class SignatureTest(unittest.TestCase):
5435 """Function signatures"""
5436
5437 def test_inspect_module(self):
5438 for attr in dir(P):
5439 if attr.startswith('_'):
5440 continue
5441 p_func = getattr(P, attr)
5442 c_func = getattr(C, attr)
5443 if (attr == 'Decimal' or attr == 'Context' or
5444 inspect.isfunction(p_func)):
5445 p_sig = inspect.signature(p_func)
5446 c_sig = inspect.signature(c_func)
5447
5448 # parameter names:
5449 c_names = list(c_sig.parameters.keys())
5450 p_names = [x for x in p_sig.parameters.keys() if not
5451 x.startswith('_')]
5452
5453 self.assertEqual(c_names, p_names,
5454 msg="parameter name mismatch in %s" % p_func)
5455
5456 c_kind = [x.kind for x in c_sig.parameters.values()]
5457 p_kind = [x[1].kind for x in p_sig.parameters.items() if not
5458 x[0].startswith('_')]
5459
5460 # parameters:
5461 if attr != 'setcontext':
5462 self.assertEqual(c_kind, p_kind,
5463 msg="parameter kind mismatch in %s" % p_func)
5464
5465 def test_inspect_types(self):
5466
5467 POS = inspect._ParameterKind.POSITIONAL_ONLY
5468 POS_KWD = inspect._ParameterKind.POSITIONAL_OR_KEYWORD
5469
5470 # Type heuristic (type annotations would help!):
5471 pdict = {C: {'other': C.Decimal(1),
5472 'third': C.Decimal(1),
5473 'x': C.Decimal(1),
5474 'y': C.Decimal(1),
5475 'z': C.Decimal(1),
5476 'a': C.Decimal(1),
5477 'b': C.Decimal(1),
5478 'c': C.Decimal(1),
5479 'exp': C.Decimal(1),
5480 'modulo': C.Decimal(1),
5481 'num': "1",
5482 'f': 1.0,
5483 'rounding': C.ROUND_HALF_UP,
5484 'context': C.getcontext()},
5485 P: {'other': P.Decimal(1),
5486 'third': P.Decimal(1),
5487 'a': P.Decimal(1),
5488 'b': P.Decimal(1),
5489 'c': P.Decimal(1),
5490 'exp': P.Decimal(1),
5491 'modulo': P.Decimal(1),
5492 'num': "1",
5493 'f': 1.0,
5494 'rounding': P.ROUND_HALF_UP,
5495 'context': P.getcontext()}}
5496
5497 def mkargs(module, sig):
5498 args = []
5499 kwargs = {}
5500 for name, param in sig.parameters.items():
5501 if name == 'self': continue
5502 if param.kind == POS:
5503 args.append(pdict[module][name])
5504 elif param.kind == POS_KWD:
5505 kwargs[name] = pdict[module][name]
5506 else:
5507 raise TestFailed("unexpected parameter kind")
5508 return args, kwargs
5509
5510 def tr(s):
5511 """The C Context docstrings use 'x' in order to prevent confusion
5512 with the article 'a' in the descriptions."""
5513 if s == 'x': return 'a'
5514 if s == 'y': return 'b'
5515 if s == 'z': return 'c'
5516 return s
5517
5518 def doit(ty):
5519 p_type = getattr(P, ty)
5520 c_type = getattr(C, ty)
5521 for attr in dir(p_type):
5522 if attr.startswith('_'):
5523 continue
5524 p_func = getattr(p_type, attr)
5525 c_func = getattr(c_type, attr)
5526 if inspect.isfunction(p_func):
5527 p_sig = inspect.signature(p_func)
5528 c_sig = inspect.signature(c_func)
5529
5530 # parameter names:
5531 p_names = list(p_sig.parameters.keys())
5532 c_names = [tr(x) for x in c_sig.parameters.keys()]
5533
5534 self.assertEqual(c_names, p_names,
5535 msg="parameter name mismatch in %s" % p_func)
5536
5537 p_kind = [x.kind for x in p_sig.parameters.values()]
5538 c_kind = [x.kind for x in c_sig.parameters.values()]
5539
5540 # 'self' parameter:
5541 self.assertIs(p_kind[0], POS_KWD)
5542 self.assertIs(c_kind[0], POS)
5543
5544 # remaining parameters:
5545 if ty == 'Decimal':
5546 self.assertEqual(c_kind[1:], p_kind[1:],
5547 msg="parameter kind mismatch in %s" % p_func)
5548 else: # Context methods are positional only in the C version.
5549 self.assertEqual(len(c_kind), len(p_kind),
5550 msg="parameter kind mismatch in %s" % p_func)
5551
5552 # Run the function:
5553 args, kwds = mkargs(C, c_sig)
5554 try:
5555 getattr(c_type(9), attr)(*args, **kwds)
5556 except Exception as err:
5557 raise TestFailed("invalid signature for %s: %s %s" % (c_func, args, kwds))
5558
5559 args, kwds = mkargs(P, p_sig)
5560 try:
5561 getattr(p_type(9), attr)(*args, **kwds)
5562 except Exception as err:
5563 raise TestFailed("invalid signature for %s: %s %s" % (p_func, args, kwds))
5564
5565 doit('Decimal')
5566 doit('Context')
5567
5568
Stefan Krah1919b7e2012-03-21 18:25:23 +01005569all_tests = [
5570 CExplicitConstructionTest, PyExplicitConstructionTest,
5571 CImplicitConstructionTest, PyImplicitConstructionTest,
5572 CFormatTest, PyFormatTest,
5573 CArithmeticOperatorsTest, PyArithmeticOperatorsTest,
5574 CThreadingTest, PyThreadingTest,
5575 CUsabilityTest, PyUsabilityTest,
5576 CPythonAPItests, PyPythonAPItests,
5577 CContextAPItests, PyContextAPItests,
5578 CContextWithStatement, PyContextWithStatement,
5579 CContextFlags, PyContextFlags,
5580 CSpecialContexts, PySpecialContexts,
5581 CContextInputValidation, PyContextInputValidation,
5582 CContextSubclassing, PyContextSubclassing,
5583 CCoverage, PyCoverage,
5584 CFunctionality, PyFunctionality,
5585 CWhitebox, PyWhitebox,
5586 CIBMTestCases, PyIBMTestCases,
5587]
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005588
Stefan Krah1919b7e2012-03-21 18:25:23 +01005589# Delete C tests if _decimal.so is not present.
5590if not C:
5591 all_tests = all_tests[1::2]
5592else:
5593 all_tests.insert(0, CheckAttributes)
Stefan Krah5de1f822014-05-01 15:53:42 +02005594 all_tests.insert(1, SignatureTest)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005595
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005596
Zachary Ware66f29282014-06-02 16:01:29 -05005597def test_main(arith=None, verbose=None, todo_tests=None, debug=None):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005598 """ Execute the tests.
5599
Raymond Hettingered20ad82004-09-04 20:09:13 +00005600 Runs all arithmetic tests if arith is True or if the "decimal" resource
5601 is enabled in regrtest.py
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005602 """
Raymond Hettingered20ad82004-09-04 20:09:13 +00005603
Stefan Krah1919b7e2012-03-21 18:25:23 +01005604 init(C)
5605 init(P)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005606 global TEST_ALL, DEBUG
Zachary Ware66f29282014-06-02 16:01:29 -05005607 TEST_ALL = arith if arith is not None else is_resource_enabled('decimal')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005608 DEBUG = debug
Raymond Hettingered20ad82004-09-04 20:09:13 +00005609
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005610 if todo_tests is None:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005611 test_classes = all_tests
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005612 else:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005613 test_classes = [CIBMTestCases, PyIBMTestCases]
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005614
5615 # Dynamically build custom test definition for each file in the test
5616 # directory and add the definitions to the DecimalTest class. This
5617 # procedure insures that new files do not get skipped.
5618 for filename in os.listdir(directory):
5619 if '.decTest' not in filename or filename.startswith("."):
5620 continue
5621 head, tail = filename.split('.')
5622 if todo_tests is not None and head not in todo_tests:
5623 continue
5624 tester = lambda self, f=filename: self.eval_file(directory + f)
Stefan Krah1919b7e2012-03-21 18:25:23 +01005625 setattr(CIBMTestCases, 'test_' + head, tester)
5626 setattr(PyIBMTestCases, 'test_' + head, tester)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005627 del filename, head, tail, tester
5628
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005629
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005630 try:
5631 run_unittest(*test_classes)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005632 if todo_tests is None:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005633 from doctest import IGNORE_EXCEPTION_DETAIL
5634 savedecimal = sys.modules['decimal']
5635 if C:
5636 sys.modules['decimal'] = C
5637 run_doctest(C, verbose, optionflags=IGNORE_EXCEPTION_DETAIL)
5638 sys.modules['decimal'] = P
5639 run_doctest(P, verbose)
5640 sys.modules['decimal'] = savedecimal
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005641 finally:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005642 if C: C.setcontext(ORIGINAL_CONTEXT[C])
5643 P.setcontext(ORIGINAL_CONTEXT[P])
5644 if not C:
5645 warnings.warn('C tests skipped: no module named _decimal.',
5646 UserWarning)
5647 if not orig_sys_decimal is sys.modules['decimal']:
5648 raise TestFailed("Internal error: unbalanced number of changes to "
5649 "sys.modules['decimal'].")
5650
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005651
5652if __name__ == '__main__':
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005653 import optparse
5654 p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]")
5655 p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test')
5656 p.add_option('--skip', '-s', action='store_true', help='skip over 90% of the arithmetic tests')
5657 (opt, args) = p.parse_args()
5658
5659 if opt.skip:
5660 test_main(arith=False, verbose=True)
5661 elif args:
5662 test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005663 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005664 test_main(arith=True, verbose=True)