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