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