blob: 617a37eec8223aadfcaeefa617bdd02f00a62872 [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
Brett Cannona721aba2016-09-09 14:57:09 -0700557 # underscores
558 self.assertEqual(str(Decimal('1_3.3e4_0')), '1.33E+41')
559 self.assertEqual(str(Decimal('1_0_0_0')), '1000')
560
Stefan Krah1919b7e2012-03-21 18:25:23 +0100561 # unicode whitespace
562 for lead in ["", ' ', '\u00a0', '\u205f']:
563 for trail in ["", ' ', '\u00a0', '\u205f']:
564 self.assertEqual(str(Decimal(lead + '9.311E+28' + trail)),
565 '9.311E+28')
566
567 with localcontext() as c:
568 c.traps[InvalidOperation] = True
569 # Invalid string
570 self.assertRaises(InvalidOperation, Decimal, "xyz")
571 # Two arguments max
572 self.assertRaises(TypeError, Decimal, "1234", "x", "y")
573
574 # space within the numeric part
575 self.assertRaises(InvalidOperation, Decimal, "1\u00a02\u00a03")
576 self.assertRaises(InvalidOperation, Decimal, "\u00a01\u00a02\u00a0")
577
578 # unicode whitespace
579 self.assertRaises(InvalidOperation, Decimal, "\u00a0")
580 self.assertRaises(InvalidOperation, Decimal, "\u00a0\u00a0")
581
582 # embedded NUL
583 self.assertRaises(InvalidOperation, Decimal, "12\u00003")
584
Brett Cannona721aba2016-09-09 14:57:09 -0700585 # underscores don't prevent errors
586 self.assertRaises(InvalidOperation, Decimal, "1_2_\u00003")
587
Stefan Krah6e467042012-11-10 23:09:04 +0100588 @cpython_only
589 def test_from_legacy_strings(self):
590 import _testcapi
591 Decimal = self.decimal.Decimal
592 context = self.decimal.Context()
593
594 s = _testcapi.unicode_legacy_string('9.999999')
595 self.assertEqual(str(Decimal(s)), '9.999999')
596 self.assertEqual(str(context.create_decimal(s)), '9.999999')
Christian Heimesa62da1d2008-01-12 19:39:10 +0000597
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000598 def test_explicit_from_tuples(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100599 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000600
601 #zero
602 d = Decimal( (0, (0,), 0) )
603 self.assertEqual(str(d), '0')
604
605 #int
606 d = Decimal( (1, (4, 5), 0) )
607 self.assertEqual(str(d), '-45')
608
609 #float
610 d = Decimal( (0, (4, 5, 3, 4), -2) )
611 self.assertEqual(str(d), '45.34')
612
613 #weird
614 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
615 self.assertEqual(str(d), '-4.34913534E-17')
616
Stefan Krah1919b7e2012-03-21 18:25:23 +0100617 #inf
618 d = Decimal( (0, (), "F") )
619 self.assertEqual(str(d), 'Infinity')
620
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000621 #wrong number of items
622 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1)) )
623
624 #bad sign
625 self.assertRaises(ValueError, Decimal, (8, (4, 3, 4, 9, 1), 2) )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000626 self.assertRaises(ValueError, Decimal, (0., (4, 3, 4, 9, 1), 2) )
627 self.assertRaises(ValueError, Decimal, (Decimal(1), (4, 3, 4, 9, 1), 2))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000628
629 #bad exp
630 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 'wrong!') )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000631 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 0.) )
632 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), '1') )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000633
634 #bad coefficients
Stefan Krah1919b7e2012-03-21 18:25:23 +0100635 self.assertRaises(ValueError, Decimal, (1, "xyz", 2) )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000636 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, None, 1), 2) )
637 self.assertRaises(ValueError, Decimal, (1, (4, -3, 4, 9, 1), 2) )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000638 self.assertRaises(ValueError, Decimal, (1, (4, 10, 4, 9, 1), 2) )
Guido van Rossum0d3fb8a2007-11-26 23:23:18 +0000639 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 'a', 1), 2) )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000640
Stefan Krah1919b7e2012-03-21 18:25:23 +0100641 def test_explicit_from_list(self):
642 Decimal = self.decimal.Decimal
643
644 d = Decimal([0, [0], 0])
645 self.assertEqual(str(d), '0')
646
647 d = Decimal([1, [4, 3, 4, 9, 1, 3, 5, 3, 4], -25])
648 self.assertEqual(str(d), '-4.34913534E-17')
649
650 d = Decimal([1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25])
651 self.assertEqual(str(d), '-4.34913534E-17')
652
653 d = Decimal((1, [4, 3, 4, 9, 1, 3, 5, 3, 4], -25))
654 self.assertEqual(str(d), '-4.34913534E-17')
655
Antoine Pitrou503ab332010-03-30 18:56:19 +0000656 def test_explicit_from_bool(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100657 Decimal = self.decimal.Decimal
658
Antoine Pitrou503ab332010-03-30 18:56:19 +0000659 self.assertIs(bool(Decimal(0)), False)
660 self.assertIs(bool(Decimal(1)), True)
661 self.assertEqual(Decimal(False), Decimal(0))
662 self.assertEqual(Decimal(True), Decimal(1))
663
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000664 def test_explicit_from_Decimal(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100665 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000666
667 #positive
668 d = Decimal(45)
669 e = Decimal(d)
670 self.assertEqual(str(e), '45')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000671
672 #very large positive
673 d = Decimal(500000123)
674 e = Decimal(d)
675 self.assertEqual(str(e), '500000123')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000676
677 #negative
678 d = Decimal(-45)
679 e = Decimal(d)
680 self.assertEqual(str(e), '-45')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000681
682 #zero
683 d = Decimal(0)
684 e = Decimal(d)
685 self.assertEqual(str(e), '0')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000686
Raymond Hettinger96798592010-04-02 16:58:27 +0000687 @requires_IEEE_754
688 def test_explicit_from_float(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100689
690 Decimal = self.decimal.Decimal
691
Raymond Hettinger96798592010-04-02 16:58:27 +0000692 r = Decimal(0.1)
693 self.assertEqual(type(r), Decimal)
694 self.assertEqual(str(r),
695 '0.1000000000000000055511151231257827021181583404541015625')
696 self.assertTrue(Decimal(float('nan')).is_qnan())
697 self.assertTrue(Decimal(float('inf')).is_infinite())
698 self.assertTrue(Decimal(float('-inf')).is_infinite())
699 self.assertEqual(str(Decimal(float('nan'))),
700 str(Decimal('NaN')))
701 self.assertEqual(str(Decimal(float('inf'))),
702 str(Decimal('Infinity')))
703 self.assertEqual(str(Decimal(float('-inf'))),
704 str(Decimal('-Infinity')))
705 self.assertEqual(str(Decimal(float('-0.0'))),
706 str(Decimal('-0')))
707 for i in range(200):
708 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
709 self.assertEqual(x, float(Decimal(x))) # roundtrip
710
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000711 def test_explicit_context_create_decimal(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100712 Decimal = self.decimal.Decimal
713 InvalidOperation = self.decimal.InvalidOperation
714 Rounded = self.decimal.Rounded
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000715
Stefan Krah1919b7e2012-03-21 18:25:23 +0100716 nc = copy.copy(self.decimal.getcontext())
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000717 nc.prec = 3
718
719 # empty
Raymond Hettingerfed52962004-07-14 15:41:57 +0000720 d = Decimal()
721 self.assertEqual(str(d), '0')
722 d = nc.create_decimal()
723 self.assertEqual(str(d), '0')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000724
725 # from None
726 self.assertRaises(TypeError, nc.create_decimal, None)
727
728 # from int
729 d = nc.create_decimal(456)
Ezio Melottie9615932010-01-24 19:26:24 +0000730 self.assertIsInstance(d, Decimal)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000731 self.assertEqual(nc.create_decimal(45678),
732 nc.create_decimal('457E+2'))
733
734 # from string
735 d = Decimal('456789')
736 self.assertEqual(str(d), '456789')
737 d = nc.create_decimal('456789')
738 self.assertEqual(str(d), '4.57E+5')
Christian Heimesa62da1d2008-01-12 19:39:10 +0000739 # leading and trailing whitespace should result in a NaN;
740 # spaces are already checked in Cowlishaw's test-suite, so
741 # here we just check that a trailing newline results in a NaN
742 self.assertEqual(str(nc.create_decimal('3.14\n')), 'NaN')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000743
744 # from tuples
745 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
746 self.assertEqual(str(d), '-4.34913534E-17')
747 d = nc.create_decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
748 self.assertEqual(str(d), '-4.35E-17')
749
750 # from Decimal
751 prevdec = Decimal(500000123)
752 d = Decimal(prevdec)
753 self.assertEqual(str(d), '500000123')
754 d = nc.create_decimal(prevdec)
755 self.assertEqual(str(d), '5.00E+8')
756
Stefan Krah1919b7e2012-03-21 18:25:23 +0100757 # more integers
758 nc.prec = 28
759 nc.traps[InvalidOperation] = True
760
761 for v in [-2**63-1, -2**63, -2**31-1, -2**31, 0,
762 2**31-1, 2**31, 2**63-1, 2**63]:
763 d = nc.create_decimal(v)
764 self.assertTrue(isinstance(d, Decimal))
765 self.assertEqual(int(d), v)
766
767 nc.prec = 3
768 nc.traps[Rounded] = True
769 self.assertRaises(Rounded, nc.create_decimal, 1234)
770
771 # from string
772 nc.prec = 28
773 self.assertEqual(str(nc.create_decimal('0E-017')), '0E-17')
774 self.assertEqual(str(nc.create_decimal('45')), '45')
775 self.assertEqual(str(nc.create_decimal('-Inf')), '-Infinity')
776 self.assertEqual(str(nc.create_decimal('NaN123')), 'NaN123')
777
778 # invalid arguments
779 self.assertRaises(InvalidOperation, nc.create_decimal, "xyz")
780 self.assertRaises(ValueError, nc.create_decimal, (1, "xyz", -25))
781 self.assertRaises(TypeError, nc.create_decimal, "1234", "5678")
Brett Cannona721aba2016-09-09 14:57:09 -0700782 # no whitespace and underscore stripping is done with this method
783 self.assertRaises(InvalidOperation, nc.create_decimal, " 1234")
784 self.assertRaises(InvalidOperation, nc.create_decimal, "12_34")
Stefan Krah1919b7e2012-03-21 18:25:23 +0100785
786 # too many NaN payload digits
787 nc.prec = 3
788 self.assertRaises(InvalidOperation, nc.create_decimal, 'NaN12345')
789 self.assertRaises(InvalidOperation, nc.create_decimal,
790 Decimal('NaN12345'))
791
792 nc.traps[InvalidOperation] = False
793 self.assertEqual(str(nc.create_decimal('NaN12345')), 'NaN')
794 self.assertTrue(nc.flags[InvalidOperation])
795
796 nc.flags[InvalidOperation] = False
797 self.assertEqual(str(nc.create_decimal(Decimal('NaN12345'))), 'NaN')
798 self.assertTrue(nc.flags[InvalidOperation])
799
800 def test_explicit_context_create_from_float(self):
801
802 Decimal = self.decimal.Decimal
803
804 nc = self.decimal.Context()
805 r = nc.create_decimal(0.1)
806 self.assertEqual(type(r), Decimal)
807 self.assertEqual(str(r), '0.1000000000000000055511151231')
808 self.assertTrue(nc.create_decimal(float('nan')).is_qnan())
809 self.assertTrue(nc.create_decimal(float('inf')).is_infinite())
810 self.assertTrue(nc.create_decimal(float('-inf')).is_infinite())
811 self.assertEqual(str(nc.create_decimal(float('nan'))),
812 str(nc.create_decimal('NaN')))
813 self.assertEqual(str(nc.create_decimal(float('inf'))),
814 str(nc.create_decimal('Infinity')))
815 self.assertEqual(str(nc.create_decimal(float('-inf'))),
816 str(nc.create_decimal('-Infinity')))
817 self.assertEqual(str(nc.create_decimal(float('-0.0'))),
818 str(nc.create_decimal('-0')))
819 nc.prec = 100
820 for i in range(200):
821 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
822 self.assertEqual(x, float(nc.create_decimal(x))) # roundtrip
823
Mark Dickinson345adc42009-08-02 10:14:23 +0000824 def test_unicode_digits(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100825 Decimal = self.decimal.Decimal
826
Mark Dickinson345adc42009-08-02 10:14:23 +0000827 test_values = {
828 '\uff11': '1',
829 '\u0660.\u0660\u0663\u0667\u0662e-\u0663' : '0.0000372',
830 '-nan\u0c68\u0c6a\u0c66\u0c66' : '-NaN2400',
831 }
832 for input, expected in test_values.items():
833 self.assertEqual(str(Decimal(input)), expected)
834
Stefan Krah1919b7e2012-03-21 18:25:23 +0100835class CExplicitConstructionTest(ExplicitConstructionTest):
836 decimal = C
837class PyExplicitConstructionTest(ExplicitConstructionTest):
838 decimal = P
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000839
Stefan Krah1919b7e2012-03-21 18:25:23 +0100840class ImplicitConstructionTest(unittest.TestCase):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000841 '''Unit tests for Implicit Construction cases of Decimal.'''
842
843 def test_implicit_from_None(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100844 Decimal = self.decimal.Decimal
845 self.assertRaises(TypeError, eval, 'Decimal(5) + None', locals())
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000846
847 def test_implicit_from_int(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100848 Decimal = self.decimal.Decimal
849
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000850 #normal
851 self.assertEqual(str(Decimal(5) + 45), '50')
852 #exceeding precision
853 self.assertEqual(Decimal(5) + 123456789000, Decimal(123456789000))
854
855 def test_implicit_from_string(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100856 Decimal = self.decimal.Decimal
857 self.assertRaises(TypeError, eval, 'Decimal(5) + "3"', locals())
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000858
859 def test_implicit_from_float(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100860 Decimal = self.decimal.Decimal
861 self.assertRaises(TypeError, eval, 'Decimal(5) + 2.2', locals())
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000862
863 def test_implicit_from_Decimal(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100864 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000865 self.assertEqual(Decimal(5) + Decimal(45), Decimal(50))
866
Raymond Hettinger267b8682005-03-27 10:47:39 +0000867 def test_rop(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100868 Decimal = self.decimal.Decimal
869
Raymond Hettinger267b8682005-03-27 10:47:39 +0000870 # Allow other classes to be trained to interact with Decimals
871 class E:
872 def __divmod__(self, other):
873 return 'divmod ' + str(other)
874 def __rdivmod__(self, other):
875 return str(other) + ' rdivmod'
876 def __lt__(self, other):
877 return 'lt ' + str(other)
878 def __gt__(self, other):
879 return 'gt ' + str(other)
880 def __le__(self, other):
881 return 'le ' + str(other)
882 def __ge__(self, other):
883 return 'ge ' + str(other)
884 def __eq__(self, other):
885 return 'eq ' + str(other)
886 def __ne__(self, other):
887 return 'ne ' + str(other)
888
889 self.assertEqual(divmod(E(), Decimal(10)), 'divmod 10')
890 self.assertEqual(divmod(Decimal(10), E()), '10 rdivmod')
891 self.assertEqual(eval('Decimal(10) < E()'), 'gt 10')
892 self.assertEqual(eval('Decimal(10) > E()'), 'lt 10')
893 self.assertEqual(eval('Decimal(10) <= E()'), 'ge 10')
894 self.assertEqual(eval('Decimal(10) >= E()'), 'le 10')
895 self.assertEqual(eval('Decimal(10) == E()'), 'eq 10')
896 self.assertEqual(eval('Decimal(10) != E()'), 'ne 10')
897
898 # insert operator methods and then exercise them
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000899 oplist = [
900 ('+', '__add__', '__radd__'),
901 ('-', '__sub__', '__rsub__'),
902 ('*', '__mul__', '__rmul__'),
Thomas Woutersdcc6d322006-04-21 11:30:52 +0000903 ('/', '__truediv__', '__rtruediv__'),
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000904 ('%', '__mod__', '__rmod__'),
905 ('//', '__floordiv__', '__rfloordiv__'),
906 ('**', '__pow__', '__rpow__')
907 ]
Raymond Hettinger267b8682005-03-27 10:47:39 +0000908
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000909 for sym, lop, rop in oplist:
Raymond Hettinger267b8682005-03-27 10:47:39 +0000910 setattr(E, lop, lambda self, other: 'str' + lop + str(other))
911 setattr(E, rop, lambda self, other: str(other) + rop + 'str')
912 self.assertEqual(eval('E()' + sym + 'Decimal(10)'),
913 'str' + lop + '10')
914 self.assertEqual(eval('Decimal(10)' + sym + 'E()'),
915 '10' + rop + 'str')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000916
Stefan Krah1919b7e2012-03-21 18:25:23 +0100917class CImplicitConstructionTest(ImplicitConstructionTest):
918 decimal = C
919class PyImplicitConstructionTest(ImplicitConstructionTest):
920 decimal = P
Mark Dickinson79f52032009-03-17 23:12:51 +0000921
Stefan Krah1919b7e2012-03-21 18:25:23 +0100922class FormatTest(unittest.TestCase):
Christian Heimesf16baeb2008-02-29 14:57:44 +0000923 '''Unit tests for the format function.'''
924 def test_formatting(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100925 Decimal = self.decimal.Decimal
926
Christian Heimesf16baeb2008-02-29 14:57:44 +0000927 # triples giving a format, a Decimal, and the expected result
928 test_values = [
929 ('e', '0E-15', '0e-15'),
930 ('e', '2.3E-15', '2.3e-15'),
931 ('e', '2.30E+2', '2.30e+2'), # preserve significant zeros
932 ('e', '2.30000E-15', '2.30000e-15'),
933 ('e', '1.23456789123456789e40', '1.23456789123456789e+40'),
934 ('e', '1.5', '1.5e+0'),
935 ('e', '0.15', '1.5e-1'),
936 ('e', '0.015', '1.5e-2'),
937 ('e', '0.0000000000015', '1.5e-12'),
938 ('e', '15.0', '1.50e+1'),
939 ('e', '-15', '-1.5e+1'),
940 ('e', '0', '0e+0'),
941 ('e', '0E1', '0e+1'),
942 ('e', '0.0', '0e-1'),
943 ('e', '0.00', '0e-2'),
944 ('.6e', '0E-15', '0.000000e-9'),
945 ('.6e', '0', '0.000000e+6'),
946 ('.6e', '9.999999', '9.999999e+0'),
947 ('.6e', '9.9999999', '1.000000e+1'),
948 ('.6e', '-1.23e5', '-1.230000e+5'),
949 ('.6e', '1.23456789e-3', '1.234568e-3'),
950 ('f', '0', '0'),
951 ('f', '0.0', '0.0'),
952 ('f', '0E-2', '0.00'),
953 ('f', '0.00E-8', '0.0000000000'),
954 ('f', '0E1', '0'), # loses exponent information
955 ('f', '3.2E1', '32'),
956 ('f', '3.2E2', '320'),
957 ('f', '3.20E2', '320'),
958 ('f', '3.200E2', '320.0'),
959 ('f', '3.2E-6', '0.0000032'),
960 ('.6f', '0E-15', '0.000000'), # all zeros treated equally
961 ('.6f', '0E1', '0.000000'),
962 ('.6f', '0', '0.000000'),
963 ('.0f', '0', '0'), # no decimal point
964 ('.0f', '0e-2', '0'),
965 ('.0f', '3.14159265', '3'),
966 ('.1f', '3.14159265', '3.1'),
967 ('.4f', '3.14159265', '3.1416'),
968 ('.6f', '3.14159265', '3.141593'),
969 ('.7f', '3.14159265', '3.1415926'), # round-half-even!
970 ('.8f', '3.14159265', '3.14159265'),
971 ('.9f', '3.14159265', '3.141592650'),
972
973 ('g', '0', '0'),
974 ('g', '0.0', '0.0'),
975 ('g', '0E1', '0e+1'),
976 ('G', '0E1', '0E+1'),
977 ('g', '0E-5', '0.00000'),
978 ('g', '0E-6', '0.000000'),
979 ('g', '0E-7', '0e-7'),
980 ('g', '-0E2', '-0e+2'),
981 ('.0g', '3.14159265', '3'), # 0 sig fig -> 1 sig fig
Stefan Krah1919b7e2012-03-21 18:25:23 +0100982 ('.0n', '3.14159265', '3'), # same for 'n'
Christian Heimesf16baeb2008-02-29 14:57:44 +0000983 ('.1g', '3.14159265', '3'),
984 ('.2g', '3.14159265', '3.1'),
985 ('.5g', '3.14159265', '3.1416'),
986 ('.7g', '3.14159265', '3.141593'),
987 ('.8g', '3.14159265', '3.1415926'), # round-half-even!
988 ('.9g', '3.14159265', '3.14159265'),
989 ('.10g', '3.14159265', '3.14159265'), # don't pad
990
991 ('%', '0E1', '0%'),
992 ('%', '0E0', '0%'),
993 ('%', '0E-1', '0%'),
994 ('%', '0E-2', '0%'),
995 ('%', '0E-3', '0.0%'),
996 ('%', '0E-4', '0.00%'),
997
998 ('.3%', '0', '0.000%'), # all zeros treated equally
999 ('.3%', '0E10', '0.000%'),
1000 ('.3%', '0E-10', '0.000%'),
1001 ('.3%', '2.34', '234.000%'),
1002 ('.3%', '1.234567', '123.457%'),
1003 ('.0%', '1.23', '123%'),
1004
1005 ('e', 'NaN', 'NaN'),
1006 ('f', '-NaN123', '-NaN123'),
1007 ('+g', 'NaN456', '+NaN456'),
1008 ('.3e', 'Inf', 'Infinity'),
1009 ('.16f', '-Inf', '-Infinity'),
1010 ('.0g', '-sNaN', '-sNaN'),
1011
1012 ('', '1.00', '1.00'),
Mark Dickinsonad416342009-03-17 18:10:15 +00001013
Mark Dickinson79f52032009-03-17 23:12:51 +00001014 # test alignment and padding
Mark Dickinson46ab5d02009-09-08 20:22:46 +00001015 ('6', '123', ' 123'),
Mark Dickinsonad416342009-03-17 18:10:15 +00001016 ('<6', '123', '123 '),
1017 ('>6', '123', ' 123'),
1018 ('^6', '123', ' 123 '),
1019 ('=+6', '123', '+ 123'),
Mark Dickinson79f52032009-03-17 23:12:51 +00001020 ('#<10', 'NaN', 'NaN#######'),
1021 ('#<10', '-4.3', '-4.3######'),
1022 ('#<+10', '0.0130', '+0.0130###'),
1023 ('#< 10', '0.0130', ' 0.0130###'),
1024 ('@>10', '-Inf', '@-Infinity'),
1025 ('#>5', '-Inf', '-Infinity'),
1026 ('?^5', '123', '?123?'),
1027 ('%^6', '123', '%123%%'),
1028 (' ^6', '-45.6', '-45.6 '),
1029 ('/=10', '-45.6', '-/////45.6'),
1030 ('/=+10', '45.6', '+/////45.6'),
1031 ('/= 10', '45.6', ' /////45.6'),
Stefan Krah6edda142013-05-29 15:45:38 +02001032 ('\x00=10', '-inf', '-\x00Infinity'),
1033 ('\x00^16', '-inf', '\x00\x00\x00-Infinity\x00\x00\x00\x00'),
1034 ('\x00>10', '1.2345', '\x00\x00\x00\x001.2345'),
1035 ('\x00<10', '1.2345', '1.2345\x00\x00\x00\x00'),
Mark Dickinson79f52032009-03-17 23:12:51 +00001036
1037 # thousands separator
1038 (',', '1234567', '1,234,567'),
1039 (',', '123456', '123,456'),
1040 (',', '12345', '12,345'),
1041 (',', '1234', '1,234'),
1042 (',', '123', '123'),
1043 (',', '12', '12'),
1044 (',', '1', '1'),
1045 (',', '0', '0'),
1046 (',', '-1234567', '-1,234,567'),
1047 (',', '-123456', '-123,456'),
1048 ('7,', '123456', '123,456'),
Mark Dickinson46ab5d02009-09-08 20:22:46 +00001049 ('8,', '123456', ' 123,456'),
Mark Dickinson79f52032009-03-17 23:12:51 +00001050 ('08,', '123456', '0,123,456'), # special case: extra 0 needed
1051 ('+08,', '123456', '+123,456'), # but not if there's a sign
1052 (' 08,', '123456', ' 123,456'),
1053 ('08,', '-123456', '-123,456'),
1054 ('+09,', '123456', '+0,123,456'),
1055 # ... with fractional part...
1056 ('07,', '1234.56', '1,234.56'),
1057 ('08,', '1234.56', '1,234.56'),
1058 ('09,', '1234.56', '01,234.56'),
1059 ('010,', '1234.56', '001,234.56'),
1060 ('011,', '1234.56', '0,001,234.56'),
1061 ('012,', '1234.56', '0,001,234.56'),
1062 ('08,.1f', '1234.5', '01,234.5'),
1063 # no thousands separators in fraction part
1064 (',', '1.23456789', '1.23456789'),
1065 (',%', '123.456789', '12,345.6789%'),
1066 (',e', '123456', '1.23456e+5'),
1067 (',E', '123456', '1.23456E+5'),
Mark Dickinson7718d2b2009-09-07 16:21:56 +00001068
1069 # issue 6850
1070 ('a=-7.0', '0.12345', 'aaaa0.1'),
Stefan Krah298131a2014-08-26 20:46:49 +02001071
1072 # issue 22090
1073 ('<^+15.20%', 'inf', '<<+Infinity%<<<'),
1074 ('\x07>,%', 'sNaN1234567', 'sNaN1234567%'),
1075 ('=10.10%', 'NaN123', ' NaN123%'),
Christian Heimesf16baeb2008-02-29 14:57:44 +00001076 ]
1077 for fmt, d, result in test_values:
1078 self.assertEqual(format(Decimal(d), fmt), result)
1079
Stefan Krah1919b7e2012-03-21 18:25:23 +01001080 # bytes format argument
1081 self.assertRaises(TypeError, Decimal(1).__format__, b'-020')
1082
Mark Dickinson79f52032009-03-17 23:12:51 +00001083 def test_n_format(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001084 Decimal = self.decimal.Decimal
1085
Mark Dickinson79f52032009-03-17 23:12:51 +00001086 try:
1087 from locale import CHAR_MAX
1088 except ImportError:
Zachary Ware9fe6d862013-12-08 00:20:35 -06001089 self.skipTest('locale.CHAR_MAX not available')
Mark Dickinson79f52032009-03-17 23:12:51 +00001090
Stefan Krah1919b7e2012-03-21 18:25:23 +01001091 def make_grouping(lst):
1092 return ''.join([chr(x) for x in lst]) if self.decimal == C else lst
1093
1094 def get_fmt(x, override=None, fmt='n'):
1095 if self.decimal == C:
1096 return Decimal(x).__format__(fmt, override)
1097 else:
1098 return Decimal(x).__format__(fmt, _localeconv=override)
1099
Mark Dickinson79f52032009-03-17 23:12:51 +00001100 # Set up some localeconv-like dictionaries
1101 en_US = {
1102 'decimal_point' : '.',
Stefan Krah1919b7e2012-03-21 18:25:23 +01001103 'grouping' : make_grouping([3, 3, 0]),
1104 'thousands_sep' : ','
Mark Dickinson79f52032009-03-17 23:12:51 +00001105 }
1106
1107 fr_FR = {
1108 'decimal_point' : ',',
Stefan Krah1919b7e2012-03-21 18:25:23 +01001109 'grouping' : make_grouping([CHAR_MAX]),
Mark Dickinson79f52032009-03-17 23:12:51 +00001110 'thousands_sep' : ''
1111 }
1112
1113 ru_RU = {
1114 'decimal_point' : ',',
Stefan Krah1919b7e2012-03-21 18:25:23 +01001115 'grouping': make_grouping([3, 3, 0]),
Mark Dickinson79f52032009-03-17 23:12:51 +00001116 'thousands_sep' : ' '
1117 }
1118
1119 crazy = {
1120 'decimal_point' : '&',
Stefan Krah1919b7e2012-03-21 18:25:23 +01001121 'grouping': make_grouping([1, 4, 2, CHAR_MAX]),
Mark Dickinson79f52032009-03-17 23:12:51 +00001122 'thousands_sep' : '-'
1123 }
1124
Stefan Krah1919b7e2012-03-21 18:25:23 +01001125 dotsep_wide = {
1126 'decimal_point' : b'\xc2\xbf'.decode('utf-8'),
1127 'grouping': make_grouping([3, 3, 0]),
1128 'thousands_sep' : b'\xc2\xb4'.decode('utf-8')
1129 }
Mark Dickinson79f52032009-03-17 23:12:51 +00001130
1131 self.assertEqual(get_fmt(Decimal('12.7'), en_US), '12.7')
1132 self.assertEqual(get_fmt(Decimal('12.7'), fr_FR), '12,7')
1133 self.assertEqual(get_fmt(Decimal('12.7'), ru_RU), '12,7')
1134 self.assertEqual(get_fmt(Decimal('12.7'), crazy), '1-2&7')
1135
1136 self.assertEqual(get_fmt(123456789, en_US), '123,456,789')
1137 self.assertEqual(get_fmt(123456789, fr_FR), '123456789')
1138 self.assertEqual(get_fmt(123456789, ru_RU), '123 456 789')
1139 self.assertEqual(get_fmt(1234567890123, crazy), '123456-78-9012-3')
1140
1141 self.assertEqual(get_fmt(123456789, en_US, '.6n'), '1.23457e+8')
1142 self.assertEqual(get_fmt(123456789, fr_FR, '.6n'), '1,23457e+8')
1143 self.assertEqual(get_fmt(123456789, ru_RU, '.6n'), '1,23457e+8')
1144 self.assertEqual(get_fmt(123456789, crazy, '.6n'), '1&23457e+8')
1145
Mark Dickinson7303b592009-03-18 08:25:36 +00001146 # zero padding
1147 self.assertEqual(get_fmt(1234, fr_FR, '03n'), '1234')
1148 self.assertEqual(get_fmt(1234, fr_FR, '04n'), '1234')
1149 self.assertEqual(get_fmt(1234, fr_FR, '05n'), '01234')
1150 self.assertEqual(get_fmt(1234, fr_FR, '06n'), '001234')
1151
1152 self.assertEqual(get_fmt(12345, en_US, '05n'), '12,345')
1153 self.assertEqual(get_fmt(12345, en_US, '06n'), '12,345')
1154 self.assertEqual(get_fmt(12345, en_US, '07n'), '012,345')
1155 self.assertEqual(get_fmt(12345, en_US, '08n'), '0,012,345')
1156 self.assertEqual(get_fmt(12345, en_US, '09n'), '0,012,345')
1157 self.assertEqual(get_fmt(12345, en_US, '010n'), '00,012,345')
1158
1159 self.assertEqual(get_fmt(123456, crazy, '06n'), '1-2345-6')
1160 self.assertEqual(get_fmt(123456, crazy, '07n'), '1-2345-6')
1161 self.assertEqual(get_fmt(123456, crazy, '08n'), '1-2345-6')
1162 self.assertEqual(get_fmt(123456, crazy, '09n'), '01-2345-6')
1163 self.assertEqual(get_fmt(123456, crazy, '010n'), '0-01-2345-6')
1164 self.assertEqual(get_fmt(123456, crazy, '011n'), '0-01-2345-6')
1165 self.assertEqual(get_fmt(123456, crazy, '012n'), '00-01-2345-6')
1166 self.assertEqual(get_fmt(123456, crazy, '013n'), '000-01-2345-6')
1167
Stefan Krah1919b7e2012-03-21 18:25:23 +01001168 # wide char separator and decimal point
1169 self.assertEqual(get_fmt(Decimal('-1.5'), dotsep_wide, '020n'),
1170 '-0\u00b4000\u00b4000\u00b4000\u00b4001\u00bf5')
Mark Dickinson79f52032009-03-17 23:12:51 +00001171
Stefan Krah6fb204a2012-09-28 16:18:54 +02001172 @run_with_locale('LC_ALL', 'ps_AF')
Stefan Krah1919b7e2012-03-21 18:25:23 +01001173 def test_wide_char_separator_decimal_point(self):
1174 # locale with wide char separator and decimal point
Stefan Krah8a491a82012-09-28 17:17:11 +02001175 import locale
Stefan Krah1919b7e2012-03-21 18:25:23 +01001176 Decimal = self.decimal.Decimal
1177
Stefan Krah8a491a82012-09-28 17:17:11 +02001178 decimal_point = locale.localeconv()['decimal_point']
1179 thousands_sep = locale.localeconv()['thousands_sep']
Zachary Ware9fe6d862013-12-08 00:20:35 -06001180 if decimal_point != '\u066b':
1181 self.skipTest('inappropriate decimal point separator'
Zachary Ware0f533ac2013-12-12 10:32:16 -06001182 '({!a} not {!a})'.format(decimal_point, '\u066b'))
Zachary Ware9fe6d862013-12-08 00:20:35 -06001183 if thousands_sep != '\u066c':
1184 self.skipTest('inappropriate thousands separator'
Zachary Ware0f533ac2013-12-12 10:32:16 -06001185 '({!a} not {!a})'.format(thousands_sep, '\u066c'))
Stefan Krah8a491a82012-09-28 17:17:11 +02001186
Stefan Krah1919b7e2012-03-21 18:25:23 +01001187 self.assertEqual(format(Decimal('100000000.123'), 'n'),
1188 '100\u066c000\u066c000\u066b123')
Stefan Krah1919b7e2012-03-21 18:25:23 +01001189
1190class CFormatTest(FormatTest):
1191 decimal = C
1192class PyFormatTest(FormatTest):
1193 decimal = P
1194
1195class ArithmeticOperatorsTest(unittest.TestCase):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001196 '''Unit tests for all arithmetic operators, binary and unary.'''
1197
1198 def test_addition(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001199 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001200
1201 d1 = Decimal('-11.1')
1202 d2 = Decimal('22.2')
1203
1204 #two Decimals
1205 self.assertEqual(d1+d2, Decimal('11.1'))
1206 self.assertEqual(d2+d1, Decimal('11.1'))
1207
1208 #with other type, left
1209 c = d1 + 5
1210 self.assertEqual(c, Decimal('-6.1'))
1211 self.assertEqual(type(c), type(d1))
1212
1213 #with other type, right
1214 c = 5 + d1
1215 self.assertEqual(c, Decimal('-6.1'))
1216 self.assertEqual(type(c), type(d1))
1217
1218 #inline with decimal
1219 d1 += d2
1220 self.assertEqual(d1, Decimal('11.1'))
1221
1222 #inline with other type
1223 d1 += 5
1224 self.assertEqual(d1, Decimal('16.1'))
1225
1226 def test_subtraction(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001227 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001228
1229 d1 = Decimal('-11.1')
1230 d2 = Decimal('22.2')
1231
1232 #two Decimals
1233 self.assertEqual(d1-d2, Decimal('-33.3'))
1234 self.assertEqual(d2-d1, Decimal('33.3'))
1235
1236 #with other type, left
1237 c = d1 - 5
1238 self.assertEqual(c, Decimal('-16.1'))
1239 self.assertEqual(type(c), type(d1))
1240
1241 #with other type, right
1242 c = 5 - d1
1243 self.assertEqual(c, Decimal('16.1'))
1244 self.assertEqual(type(c), type(d1))
1245
1246 #inline with decimal
1247 d1 -= d2
1248 self.assertEqual(d1, Decimal('-33.3'))
1249
1250 #inline with other type
1251 d1 -= 5
1252 self.assertEqual(d1, Decimal('-38.3'))
1253
1254 def test_multiplication(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001255 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001256
1257 d1 = Decimal('-5')
1258 d2 = Decimal('3')
1259
1260 #two Decimals
1261 self.assertEqual(d1*d2, Decimal('-15'))
1262 self.assertEqual(d2*d1, Decimal('-15'))
1263
1264 #with other type, left
1265 c = d1 * 5
1266 self.assertEqual(c, Decimal('-25'))
1267 self.assertEqual(type(c), type(d1))
1268
1269 #with other type, right
1270 c = 5 * d1
1271 self.assertEqual(c, Decimal('-25'))
1272 self.assertEqual(type(c), type(d1))
1273
1274 #inline with decimal
1275 d1 *= d2
1276 self.assertEqual(d1, Decimal('-15'))
1277
1278 #inline with other type
1279 d1 *= 5
1280 self.assertEqual(d1, Decimal('-75'))
1281
1282 def test_division(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001283 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001284
1285 d1 = Decimal('-5')
1286 d2 = Decimal('2')
1287
1288 #two Decimals
1289 self.assertEqual(d1/d2, Decimal('-2.5'))
1290 self.assertEqual(d2/d1, Decimal('-0.4'))
1291
1292 #with other type, left
1293 c = d1 / 4
1294 self.assertEqual(c, Decimal('-1.25'))
1295 self.assertEqual(type(c), type(d1))
1296
1297 #with other type, right
1298 c = 4 / d1
1299 self.assertEqual(c, Decimal('-0.8'))
1300 self.assertEqual(type(c), type(d1))
1301
1302 #inline with decimal
1303 d1 /= d2
1304 self.assertEqual(d1, Decimal('-2.5'))
1305
1306 #inline with other type
1307 d1 /= 4
1308 self.assertEqual(d1, Decimal('-0.625'))
1309
1310 def test_floor_division(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001311 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001312
1313 d1 = Decimal('5')
1314 d2 = Decimal('2')
1315
1316 #two Decimals
1317 self.assertEqual(d1//d2, Decimal('2'))
1318 self.assertEqual(d2//d1, Decimal('0'))
1319
1320 #with other type, left
1321 c = d1 // 4
1322 self.assertEqual(c, Decimal('1'))
1323 self.assertEqual(type(c), type(d1))
1324
1325 #with other type, right
1326 c = 7 // d1
1327 self.assertEqual(c, Decimal('1'))
1328 self.assertEqual(type(c), type(d1))
1329
1330 #inline with decimal
1331 d1 //= d2
1332 self.assertEqual(d1, Decimal('2'))
1333
1334 #inline with other type
1335 d1 //= 2
1336 self.assertEqual(d1, Decimal('1'))
1337
1338 def test_powering(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001339 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001340
1341 d1 = Decimal('5')
1342 d2 = Decimal('2')
1343
1344 #two Decimals
1345 self.assertEqual(d1**d2, Decimal('25'))
1346 self.assertEqual(d2**d1, Decimal('32'))
1347
1348 #with other type, left
1349 c = d1 ** 4
1350 self.assertEqual(c, Decimal('625'))
1351 self.assertEqual(type(c), type(d1))
1352
1353 #with other type, right
1354 c = 7 ** d1
1355 self.assertEqual(c, Decimal('16807'))
1356 self.assertEqual(type(c), type(d1))
1357
1358 #inline with decimal
1359 d1 **= d2
1360 self.assertEqual(d1, Decimal('25'))
1361
1362 #inline with other type
1363 d1 **= 4
1364 self.assertEqual(d1, Decimal('390625'))
1365
1366 def test_module(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001367 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001368
1369 d1 = Decimal('5')
1370 d2 = Decimal('2')
1371
1372 #two Decimals
1373 self.assertEqual(d1%d2, Decimal('1'))
1374 self.assertEqual(d2%d1, Decimal('2'))
1375
1376 #with other type, left
1377 c = d1 % 4
1378 self.assertEqual(c, Decimal('1'))
1379 self.assertEqual(type(c), type(d1))
1380
1381 #with other type, right
1382 c = 7 % d1
1383 self.assertEqual(c, Decimal('2'))
1384 self.assertEqual(type(c), type(d1))
1385
1386 #inline with decimal
1387 d1 %= d2
1388 self.assertEqual(d1, Decimal('1'))
1389
1390 #inline with other type
1391 d1 %= 4
1392 self.assertEqual(d1, Decimal('1'))
1393
1394 def test_floor_div_module(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001395 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001396
1397 d1 = Decimal('5')
1398 d2 = Decimal('2')
1399
1400 #two Decimals
1401 (p, q) = divmod(d1, d2)
1402 self.assertEqual(p, Decimal('2'))
1403 self.assertEqual(q, Decimal('1'))
1404 self.assertEqual(type(p), type(d1))
1405 self.assertEqual(type(q), type(d1))
1406
1407 #with other type, left
1408 (p, q) = divmod(d1, 4)
1409 self.assertEqual(p, Decimal('1'))
1410 self.assertEqual(q, Decimal('1'))
1411 self.assertEqual(type(p), type(d1))
1412 self.assertEqual(type(q), type(d1))
1413
1414 #with other type, right
1415 (p, q) = divmod(7, d1)
1416 self.assertEqual(p, Decimal('1'))
1417 self.assertEqual(q, Decimal('2'))
1418 self.assertEqual(type(p), type(d1))
1419 self.assertEqual(type(q), type(d1))
1420
1421 def test_unary_operators(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001422 Decimal = self.decimal.Decimal
1423
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001424 self.assertEqual(+Decimal(45), Decimal(+45)) # +
1425 self.assertEqual(-Decimal(45), Decimal(-45)) # -
1426 self.assertEqual(abs(Decimal(45)), abs(Decimal(-45))) # abs
1427
Christian Heimes77c02eb2008-02-09 02:18:51 +00001428 def test_nan_comparisons(self):
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001429 # comparisons involving signaling nans signal InvalidOperation
1430
1431 # order comparisons (<, <=, >, >=) involving only quiet nans
1432 # also signal InvalidOperation
1433
1434 # equality comparisons (==, !=) involving only quiet nans
1435 # don't signal, but return False or True respectively.
Stefan Krah1919b7e2012-03-21 18:25:23 +01001436 Decimal = self.decimal.Decimal
1437 InvalidOperation = self.decimal.InvalidOperation
1438 localcontext = self.decimal.localcontext
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001439
Christian Heimes77c02eb2008-02-09 02:18:51 +00001440 n = Decimal('NaN')
1441 s = Decimal('sNaN')
1442 i = Decimal('Inf')
1443 f = Decimal('2')
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001444
1445 qnan_pairs = (n, n), (n, i), (i, n), (n, f), (f, n)
1446 snan_pairs = (s, n), (n, s), (s, i), (i, s), (s, f), (f, s), (s, s)
1447 order_ops = operator.lt, operator.le, operator.gt, operator.ge
1448 equality_ops = operator.eq, operator.ne
1449
1450 # results when InvalidOperation is not trapped
1451 for x, y in qnan_pairs + snan_pairs:
1452 for op in order_ops + equality_ops:
1453 got = op(x, y)
1454 expected = True if op is operator.ne else False
1455 self.assertIs(expected, got,
1456 "expected {0!r} for operator.{1}({2!r}, {3!r}); "
1457 "got {4!r}".format(
1458 expected, op.__name__, x, y, got))
1459
1460 # repeat the above, but this time trap the InvalidOperation
1461 with localcontext() as ctx:
1462 ctx.traps[InvalidOperation] = 1
1463
1464 for x, y in qnan_pairs:
1465 for op in equality_ops:
1466 got = op(x, y)
1467 expected = True if op is operator.ne else False
1468 self.assertIs(expected, got,
1469 "expected {0!r} for "
1470 "operator.{1}({2!r}, {3!r}); "
1471 "got {4!r}".format(
1472 expected, op.__name__, x, y, got))
1473
1474 for x, y in snan_pairs:
1475 for op in equality_ops:
1476 self.assertRaises(InvalidOperation, operator.eq, x, y)
1477 self.assertRaises(InvalidOperation, operator.ne, x, y)
1478
1479 for x, y in qnan_pairs + snan_pairs:
1480 for op in order_ops:
1481 self.assertRaises(InvalidOperation, op, x, y)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001482
Mark Dickinson84230a12010-02-18 14:49:50 +00001483 def test_copy_sign(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001484 Decimal = self.decimal.Decimal
Mark Dickinson84230a12010-02-18 14:49:50 +00001485
Stefan Krah1919b7e2012-03-21 18:25:23 +01001486 d = Decimal(1).copy_sign(Decimal(-2))
Mark Dickinson84230a12010-02-18 14:49:50 +00001487 self.assertEqual(Decimal(1).copy_sign(-2), d)
1488 self.assertRaises(TypeError, Decimal(1).copy_sign, '-2')
1489
Stefan Krah1919b7e2012-03-21 18:25:23 +01001490class CArithmeticOperatorsTest(ArithmeticOperatorsTest):
1491 decimal = C
1492class PyArithmeticOperatorsTest(ArithmeticOperatorsTest):
1493 decimal = P
1494
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001495# The following are two functions used to test threading in the next class
1496
1497def thfunc1(cls):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001498 Decimal = cls.decimal.Decimal
1499 InvalidOperation = cls.decimal.InvalidOperation
1500 DivisionByZero = cls.decimal.DivisionByZero
1501 Overflow = cls.decimal.Overflow
1502 Underflow = cls.decimal.Underflow
1503 Inexact = cls.decimal.Inexact
1504 getcontext = cls.decimal.getcontext
1505 localcontext = cls.decimal.localcontext
1506
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001507 d1 = Decimal(1)
1508 d3 = Decimal(3)
Christian Heimesfe337bf2008-03-23 21:54:12 +00001509 test1 = d1/d3
Christian Heimesfe337bf2008-03-23 21:54:12 +00001510
Stefan Krah1919b7e2012-03-21 18:25:23 +01001511 cls.finish1.set()
1512 cls.synchro.wait()
1513
1514 test2 = d1/d3
1515 with localcontext() as c2:
1516 cls.assertTrue(c2.flags[Inexact])
1517 cls.assertRaises(DivisionByZero, c2.divide, d1, 0)
1518 cls.assertTrue(c2.flags[DivisionByZero])
1519 with localcontext() as c3:
1520 cls.assertTrue(c3.flags[Inexact])
1521 cls.assertTrue(c3.flags[DivisionByZero])
1522 cls.assertRaises(InvalidOperation, c3.compare, d1, Decimal('sNaN'))
1523 cls.assertTrue(c3.flags[InvalidOperation])
1524 del c3
1525 cls.assertFalse(c2.flags[InvalidOperation])
1526 del c2
1527
1528 cls.assertEqual(test1, Decimal('0.333333333333333333333333'))
1529 cls.assertEqual(test2, Decimal('0.333333333333333333333333'))
1530
1531 c1 = getcontext()
1532 cls.assertTrue(c1.flags[Inexact])
1533 for sig in Overflow, Underflow, DivisionByZero, InvalidOperation:
1534 cls.assertFalse(c1.flags[sig])
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001535
1536def thfunc2(cls):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001537 Decimal = cls.decimal.Decimal
1538 InvalidOperation = cls.decimal.InvalidOperation
1539 DivisionByZero = cls.decimal.DivisionByZero
1540 Overflow = cls.decimal.Overflow
1541 Underflow = cls.decimal.Underflow
1542 Inexact = cls.decimal.Inexact
1543 getcontext = cls.decimal.getcontext
1544 localcontext = cls.decimal.localcontext
1545
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001546 d1 = Decimal(1)
1547 d3 = Decimal(3)
Christian Heimesfe337bf2008-03-23 21:54:12 +00001548 test1 = d1/d3
Stefan Krah1919b7e2012-03-21 18:25:23 +01001549
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001550 thiscontext = getcontext()
1551 thiscontext.prec = 18
Christian Heimesfe337bf2008-03-23 21:54:12 +00001552 test2 = d1/d3
Stefan Krah1919b7e2012-03-21 18:25:23 +01001553
1554 with localcontext() as c2:
1555 cls.assertTrue(c2.flags[Inexact])
1556 cls.assertRaises(Overflow, c2.multiply, Decimal('1e425000000'), 999)
1557 cls.assertTrue(c2.flags[Overflow])
1558 with localcontext(thiscontext) as c3:
1559 cls.assertTrue(c3.flags[Inexact])
1560 cls.assertFalse(c3.flags[Overflow])
1561 c3.traps[Underflow] = True
1562 cls.assertRaises(Underflow, c3.divide, Decimal('1e-425000000'), 999)
1563 cls.assertTrue(c3.flags[Underflow])
1564 del c3
1565 cls.assertFalse(c2.flags[Underflow])
1566 cls.assertFalse(c2.traps[Underflow])
1567 del c2
1568
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001569 cls.synchro.set()
1570 cls.finish2.set()
Christian Heimesfe337bf2008-03-23 21:54:12 +00001571
Stefan Krah1919b7e2012-03-21 18:25:23 +01001572 cls.assertEqual(test1, Decimal('0.333333333333333333333333'))
Christian Heimesfe337bf2008-03-23 21:54:12 +00001573 cls.assertEqual(test2, Decimal('0.333333333333333333'))
Stefan Krah1919b7e2012-03-21 18:25:23 +01001574
1575 cls.assertFalse(thiscontext.traps[Underflow])
1576 cls.assertTrue(thiscontext.flags[Inexact])
1577 for sig in Overflow, Underflow, DivisionByZero, InvalidOperation:
1578 cls.assertFalse(thiscontext.flags[sig])
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001579
Stefan Krah1919b7e2012-03-21 18:25:23 +01001580class ThreadingTest(unittest.TestCase):
1581 '''Unit tests for thread local contexts in Decimal.'''
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001582
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001583 # Take care executing this test from IDLE, there's an issue in threading
1584 # that hangs IDLE and I couldn't find it
1585
1586 def test_threading(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001587 DefaultContext = self.decimal.DefaultContext
1588
1589 if self.decimal == C and not self.decimal.HAVE_THREADS:
1590 self.skipTest("compiled without threading")
1591 # Test the "threading isolation" of a Context. Also test changing
1592 # the DefaultContext, which acts as a template for the thread-local
1593 # contexts.
1594 save_prec = DefaultContext.prec
1595 save_emax = DefaultContext.Emax
1596 save_emin = DefaultContext.Emin
1597 DefaultContext.prec = 24
1598 DefaultContext.Emax = 425000000
1599 DefaultContext.Emin = -425000000
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001600
1601 self.synchro = threading.Event()
1602 self.finish1 = threading.Event()
1603 self.finish2 = threading.Event()
1604
1605 th1 = threading.Thread(target=thfunc1, args=(self,))
1606 th2 = threading.Thread(target=thfunc2, args=(self,))
1607
1608 th1.start()
1609 th2.start()
1610
1611 self.finish1.wait()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001612 self.finish2.wait()
Stefan Krah1919b7e2012-03-21 18:25:23 +01001613
1614 for sig in Signals[self.decimal]:
1615 self.assertFalse(DefaultContext.flags[sig])
1616
1617 DefaultContext.prec = save_prec
1618 DefaultContext.Emax = save_emax
1619 DefaultContext.Emin = save_emin
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001620
Stefan Krah1919b7e2012-03-21 18:25:23 +01001621@unittest.skipUnless(threading, 'threading required')
1622class CThreadingTest(ThreadingTest):
1623 decimal = C
1624@unittest.skipUnless(threading, 'threading required')
1625class PyThreadingTest(ThreadingTest):
1626 decimal = P
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001627
Stefan Krah1919b7e2012-03-21 18:25:23 +01001628class UsabilityTest(unittest.TestCase):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001629 '''Unit tests for Usability cases of Decimal.'''
1630
1631 def test_comparison_operators(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001632
Stefan Krah1919b7e2012-03-21 18:25:23 +01001633 Decimal = self.decimal.Decimal
1634
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001635 da = Decimal('23.42')
1636 db = Decimal('23.42')
1637 dc = Decimal('45')
1638
1639 #two Decimals
Ezio Melotti6607d512010-04-03 14:59:49 +00001640 self.assertGreater(dc, da)
1641 self.assertGreaterEqual(dc, da)
1642 self.assertLess(da, dc)
1643 self.assertLessEqual(da, dc)
Guido van Rossume61fd5b2007-07-11 12:20:59 +00001644 self.assertEqual(da, db)
Ezio Melotti6607d512010-04-03 14:59:49 +00001645 self.assertNotEqual(da, dc)
1646 self.assertLessEqual(da, db)
1647 self.assertGreaterEqual(da, db)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001648
1649 #a Decimal and an int
Ezio Melotti6607d512010-04-03 14:59:49 +00001650 self.assertGreater(dc, 23)
1651 self.assertLess(23, dc)
Guido van Rossume61fd5b2007-07-11 12:20:59 +00001652 self.assertEqual(dc, 45)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001653
1654 #a Decimal and uncomparable
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001655 self.assertNotEqual(da, 'ugly')
1656 self.assertNotEqual(da, 32.7)
1657 self.assertNotEqual(da, object())
1658 self.assertNotEqual(da, object)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001659
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001660 # sortable
Guido van Rossumc1f779c2007-07-03 08:25:58 +00001661 a = list(map(Decimal, range(100)))
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001662 b = a[:]
1663 random.shuffle(a)
1664 a.sort()
1665 self.assertEqual(a, b)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001666
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001667 def test_decimal_float_comparison(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001668 Decimal = self.decimal.Decimal
1669
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001670 da = Decimal('0.25')
1671 db = Decimal('3.0')
Ezio Melotti6607d512010-04-03 14:59:49 +00001672 self.assertLess(da, 3.0)
1673 self.assertLessEqual(da, 3.0)
1674 self.assertGreater(db, 0.25)
1675 self.assertGreaterEqual(db, 0.25)
1676 self.assertNotEqual(da, 1.5)
1677 self.assertEqual(da, 0.25)
1678 self.assertGreater(3.0, da)
1679 self.assertGreaterEqual(3.0, da)
1680 self.assertLess(0.25, db)
1681 self.assertLessEqual(0.25, db)
1682 self.assertNotEqual(0.25, db)
1683 self.assertEqual(3.0, db)
1684 self.assertNotEqual(0.1, Decimal('0.1'))
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001685
Stefan Krah1919b7e2012-03-21 18:25:23 +01001686 def test_decimal_complex_comparison(self):
1687 Decimal = self.decimal.Decimal
1688
1689 da = Decimal('0.25')
1690 db = Decimal('3.0')
1691 self.assertNotEqual(da, (1.5+0j))
1692 self.assertNotEqual((1.5+0j), da)
1693 self.assertEqual(da, (0.25+0j))
1694 self.assertEqual((0.25+0j), da)
1695 self.assertEqual((3.0+0j), db)
1696 self.assertEqual(db, (3.0+0j))
1697
1698 self.assertNotEqual(db, (3.0+1j))
1699 self.assertNotEqual((3.0+1j), db)
1700
1701 self.assertIs(db.__lt__(3.0+0j), NotImplemented)
1702 self.assertIs(db.__le__(3.0+0j), NotImplemented)
1703 self.assertIs(db.__gt__(3.0+0j), NotImplemented)
1704 self.assertIs(db.__le__(3.0+0j), NotImplemented)
1705
1706 def test_decimal_fraction_comparison(self):
1707 D = self.decimal.Decimal
1708 F = fractions[self.decimal].Fraction
1709 Context = self.decimal.Context
1710 localcontext = self.decimal.localcontext
1711 InvalidOperation = self.decimal.InvalidOperation
1712
1713
1714 emax = C.MAX_EMAX if C else 999999999
1715 emin = C.MIN_EMIN if C else -999999999
1716 etiny = C.MIN_ETINY if C else -1999999997
1717 c = Context(Emax=emax, Emin=emin)
1718
1719 with localcontext(c):
1720 c.prec = emax
1721 self.assertLess(D(0), F(1,9999999999999999999999999999999999999))
1722 self.assertLess(F(-1,9999999999999999999999999999999999999), D(0))
1723 self.assertLess(F(0,1), D("1e" + str(etiny)))
1724 self.assertLess(D("-1e" + str(etiny)), F(0,1))
1725 self.assertLess(F(0,9999999999999999999999999), D("1e" + str(etiny)))
1726 self.assertLess(D("-1e" + str(etiny)), F(0,9999999999999999999999999))
1727
1728 self.assertEqual(D("0.1"), F(1,10))
1729 self.assertEqual(F(1,10), D("0.1"))
1730
1731 c.prec = 300
1732 self.assertNotEqual(D(1)/3, F(1,3))
1733 self.assertNotEqual(F(1,3), D(1)/3)
1734
1735 self.assertLessEqual(F(120984237, 9999999999), D("9e" + str(emax)))
1736 self.assertGreaterEqual(D("9e" + str(emax)), F(120984237, 9999999999))
1737
1738 self.assertGreater(D('inf'), F(99999999999,123))
1739 self.assertGreater(D('inf'), F(-99999999999,123))
1740 self.assertLess(D('-inf'), F(99999999999,123))
1741 self.assertLess(D('-inf'), F(-99999999999,123))
1742
1743 self.assertRaises(InvalidOperation, D('nan').__gt__, F(-9,123))
1744 self.assertIs(NotImplemented, F(-9,123).__lt__(D('nan')))
1745 self.assertNotEqual(D('nan'), F(-9,123))
1746 self.assertNotEqual(F(-9,123), D('nan'))
1747
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001748 def test_copy_and_deepcopy_methods(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001749 Decimal = self.decimal.Decimal
1750
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001751 d = Decimal('43.24')
1752 c = copy.copy(d)
1753 self.assertEqual(id(c), id(d))
1754 dc = copy.deepcopy(d)
1755 self.assertEqual(id(dc), id(d))
1756
1757 def test_hash_method(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001758
1759 Decimal = self.decimal.Decimal
1760 localcontext = self.decimal.localcontext
1761
Stefan Krahdc817b22010-11-17 11:16:34 +00001762 def hashit(d):
1763 a = hash(d)
1764 b = d.__hash__()
1765 self.assertEqual(a, b)
1766 return a
1767
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001768 #just that it's hashable
Stefan Krahdc817b22010-11-17 11:16:34 +00001769 hashit(Decimal(23))
1770 hashit(Decimal('Infinity'))
1771 hashit(Decimal('-Infinity'))
1772 hashit(Decimal('nan123'))
1773 hashit(Decimal('-NaN'))
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001774
1775 test_values = [Decimal(sign*(2**m + n))
1776 for m in [0, 14, 15, 16, 17, 30, 31,
Stefan Krahdc817b22010-11-17 11:16:34 +00001777 32, 33, 61, 62, 63, 64, 65, 66]
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001778 for n in range(-10, 10)
1779 for sign in [-1, 1]]
1780 test_values.extend([
Stefan Krahdc817b22010-11-17 11:16:34 +00001781 Decimal("-1"), # ==> -2
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001782 Decimal("-0"), # zeros
1783 Decimal("0.00"),
1784 Decimal("-0.000"),
1785 Decimal("0E10"),
1786 Decimal("-0E12"),
1787 Decimal("10.0"), # negative exponent
1788 Decimal("-23.00000"),
1789 Decimal("1230E100"), # positive exponent
1790 Decimal("-4.5678E50"),
1791 # a value for which hash(n) != hash(n % (2**64-1))
1792 # in Python pre-2.6
1793 Decimal(2**64 + 2**32 - 1),
1794 # selection of values which fail with the old (before
1795 # version 2.6) long.__hash__
1796 Decimal("1.634E100"),
1797 Decimal("90.697E100"),
1798 Decimal("188.83E100"),
1799 Decimal("1652.9E100"),
1800 Decimal("56531E100"),
1801 ])
1802
1803 # check that hash(d) == hash(int(d)) for integral values
1804 for value in test_values:
Stefan Krahdc817b22010-11-17 11:16:34 +00001805 self.assertEqual(hashit(value), hashit(int(value)))
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001806
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001807 #the same hash that to an int
Stefan Krahdc817b22010-11-17 11:16:34 +00001808 self.assertEqual(hashit(Decimal(23)), hashit(23))
Raymond Hettingerd325c4b2010-11-21 04:08:28 +00001809 self.assertRaises(TypeError, hash, Decimal('sNaN'))
Stefan Krahdc817b22010-11-17 11:16:34 +00001810 self.assertTrue(hashit(Decimal('Inf')))
1811 self.assertTrue(hashit(Decimal('-Inf')))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001812
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001813 # check that the hashes of a Decimal float match when they
1814 # represent exactly the same values
1815 test_strings = ['inf', '-Inf', '0.0', '-.0e1',
1816 '34.0', '2.5', '112390.625', '-0.515625']
1817 for s in test_strings:
1818 f = float(s)
1819 d = Decimal(s)
Stefan Krahdc817b22010-11-17 11:16:34 +00001820 self.assertEqual(hashit(f), hashit(d))
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001821
Stefan Krah1919b7e2012-03-21 18:25:23 +01001822 with localcontext() as c:
1823 # check that the value of the hash doesn't depend on the
1824 # current context (issue #1757)
1825 x = Decimal("123456789.1")
Christian Heimes2380ac72008-01-09 00:17:24 +00001826
Stefan Krah1919b7e2012-03-21 18:25:23 +01001827 c.prec = 6
1828 h1 = hashit(x)
1829 c.prec = 10
1830 h2 = hashit(x)
1831 c.prec = 16
1832 h3 = hashit(x)
Christian Heimes2380ac72008-01-09 00:17:24 +00001833
Stefan Krah1919b7e2012-03-21 18:25:23 +01001834 self.assertEqual(h1, h2)
1835 self.assertEqual(h1, h3)
1836
1837 c.prec = 10000
1838 x = 1100 ** 1248
1839 self.assertEqual(hashit(Decimal(x)), hashit(x))
Christian Heimes2380ac72008-01-09 00:17:24 +00001840
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001841 def test_min_and_max_methods(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001842 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001843
1844 d1 = Decimal('15.32')
1845 d2 = Decimal('28.5')
1846 l1 = 15
1847 l2 = 28
1848
1849 #between Decimals
Ezio Melotti6607d512010-04-03 14:59:49 +00001850 self.assertIs(min(d1,d2), d1)
1851 self.assertIs(min(d2,d1), d1)
1852 self.assertIs(max(d1,d2), d2)
1853 self.assertIs(max(d2,d1), d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001854
Serhiy Storchaka95949422013-08-27 19:40:23 +03001855 #between Decimal and int
Ezio Melotti6607d512010-04-03 14:59:49 +00001856 self.assertIs(min(d1,l2), d1)
1857 self.assertIs(min(l2,d1), d1)
1858 self.assertIs(max(l1,d2), d2)
1859 self.assertIs(max(d2,l1), d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001860
1861 def test_as_nonzero(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001862 Decimal = self.decimal.Decimal
1863
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001864 #as false
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001865 self.assertFalse(Decimal(0))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001866 #as true
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001867 self.assertTrue(Decimal('0.372'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001868
1869 def test_tostring_methods(self):
1870 #Test str and repr methods.
Stefan Krah1919b7e2012-03-21 18:25:23 +01001871 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001872
1873 d = Decimal('15.32')
1874 self.assertEqual(str(d), '15.32') # str
Christian Heimes68f5fbe2008-02-14 08:27:37 +00001875 self.assertEqual(repr(d), "Decimal('15.32')") # repr
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001876
1877 def test_tonum_methods(self):
Mark Dickinson5c2db372009-12-05 20:28:34 +00001878 #Test float and int methods.
Stefan Krah1919b7e2012-03-21 18:25:23 +01001879 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001880
1881 d1 = Decimal('66')
1882 d2 = Decimal('15.32')
1883
1884 #int
1885 self.assertEqual(int(d1), 66)
1886 self.assertEqual(int(d2), 15)
1887
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001888 #float
1889 self.assertEqual(float(d1), 66)
1890 self.assertEqual(float(d2), 15.32)
1891
Mark Dickinsonb27406c2008-05-09 13:42:33 +00001892 #floor
1893 test_pairs = [
1894 ('123.00', 123),
1895 ('3.2', 3),
1896 ('3.54', 3),
1897 ('3.899', 3),
1898 ('-2.3', -3),
1899 ('-11.0', -11),
1900 ('0.0', 0),
1901 ('-0E3', 0),
Stefan Krah1919b7e2012-03-21 18:25:23 +01001902 ('89891211712379812736.1', 89891211712379812736),
Mark Dickinsonb27406c2008-05-09 13:42:33 +00001903 ]
1904 for d, i in test_pairs:
1905 self.assertEqual(math.floor(Decimal(d)), i)
1906 self.assertRaises(ValueError, math.floor, Decimal('-NaN'))
1907 self.assertRaises(ValueError, math.floor, Decimal('sNaN'))
1908 self.assertRaises(ValueError, math.floor, Decimal('NaN123'))
1909 self.assertRaises(OverflowError, math.floor, Decimal('Inf'))
1910 self.assertRaises(OverflowError, math.floor, Decimal('-Inf'))
1911
1912 #ceiling
1913 test_pairs = [
1914 ('123.00', 123),
1915 ('3.2', 4),
1916 ('3.54', 4),
1917 ('3.899', 4),
1918 ('-2.3', -2),
1919 ('-11.0', -11),
1920 ('0.0', 0),
1921 ('-0E3', 0),
Stefan Krah1919b7e2012-03-21 18:25:23 +01001922 ('89891211712379812736.1', 89891211712379812737),
Mark Dickinsonb27406c2008-05-09 13:42:33 +00001923 ]
1924 for d, i in test_pairs:
1925 self.assertEqual(math.ceil(Decimal(d)), i)
1926 self.assertRaises(ValueError, math.ceil, Decimal('-NaN'))
1927 self.assertRaises(ValueError, math.ceil, Decimal('sNaN'))
1928 self.assertRaises(ValueError, math.ceil, Decimal('NaN123'))
1929 self.assertRaises(OverflowError, math.ceil, Decimal('Inf'))
1930 self.assertRaises(OverflowError, math.ceil, Decimal('-Inf'))
1931
1932 #round, single argument
1933 test_pairs = [
1934 ('123.00', 123),
1935 ('3.2', 3),
1936 ('3.54', 4),
1937 ('3.899', 4),
1938 ('-2.3', -2),
1939 ('-11.0', -11),
1940 ('0.0', 0),
1941 ('-0E3', 0),
1942 ('-3.5', -4),
1943 ('-2.5', -2),
1944 ('-1.5', -2),
1945 ('-0.5', 0),
1946 ('0.5', 0),
1947 ('1.5', 2),
1948 ('2.5', 2),
1949 ('3.5', 4),
1950 ]
1951 for d, i in test_pairs:
1952 self.assertEqual(round(Decimal(d)), i)
1953 self.assertRaises(ValueError, round, Decimal('-NaN'))
1954 self.assertRaises(ValueError, round, Decimal('sNaN'))
1955 self.assertRaises(ValueError, round, Decimal('NaN123'))
1956 self.assertRaises(OverflowError, round, Decimal('Inf'))
1957 self.assertRaises(OverflowError, round, Decimal('-Inf'))
1958
1959 #round, two arguments; this is essentially equivalent
1960 #to quantize, which is already extensively tested
1961 test_triples = [
1962 ('123.456', -4, '0E+4'),
1963 ('123.456', -3, '0E+3'),
1964 ('123.456', -2, '1E+2'),
1965 ('123.456', -1, '1.2E+2'),
1966 ('123.456', 0, '123'),
1967 ('123.456', 1, '123.5'),
1968 ('123.456', 2, '123.46'),
1969 ('123.456', 3, '123.456'),
1970 ('123.456', 4, '123.4560'),
1971 ('123.455', 2, '123.46'),
1972 ('123.445', 2, '123.44'),
1973 ('Inf', 4, 'NaN'),
1974 ('-Inf', -23, 'NaN'),
1975 ('sNaN314', 3, 'NaN314'),
1976 ]
1977 for d, n, r in test_triples:
1978 self.assertEqual(str(round(Decimal(d), n)), r)
1979
Mark Dickinsonfc33d4c2012-08-24 18:53:10 +01001980 def test_nan_to_float(self):
1981 # Test conversions of decimal NANs to float.
1982 # See http://bugs.python.org/issue15544
1983 Decimal = self.decimal.Decimal
1984 for s in ('nan', 'nan1234', '-nan', '-nan2468'):
1985 f = float(Decimal(s))
1986 self.assertTrue(math.isnan(f))
1987 sign = math.copysign(1.0, f)
1988 self.assertEqual(sign, -1.0 if s.startswith('-') else 1.0)
1989
1990 def test_snan_to_float(self):
1991 Decimal = self.decimal.Decimal
1992 for s in ('snan', '-snan', 'snan1357', '-snan1234'):
1993 d = Decimal(s)
1994 self.assertRaises(ValueError, float, d)
1995
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001996 def test_eval_round_trip(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001997 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001998
1999 #with zero
2000 d = Decimal( (0, (0,), 0) )
2001 self.assertEqual(d, eval(repr(d)))
2002
2003 #int
2004 d = Decimal( (1, (4, 5), 0) )
2005 self.assertEqual(d, eval(repr(d)))
2006
2007 #float
2008 d = Decimal( (0, (4, 5, 3, 4), -2) )
2009 self.assertEqual(d, eval(repr(d)))
2010
2011 #weird
2012 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
2013 self.assertEqual(d, eval(repr(d)))
2014
2015 def test_as_tuple(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01002016 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002017
2018 #with zero
2019 d = Decimal(0)
2020 self.assertEqual(d.as_tuple(), (0, (0,), 0) )
2021
2022 #int
2023 d = Decimal(-45)
2024 self.assertEqual(d.as_tuple(), (1, (4, 5), 0) )
2025
2026 #complicated string
2027 d = Decimal("-4.34913534E-17")
2028 self.assertEqual(d.as_tuple(), (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
2029
Stefan Krah76e12172012-09-10 19:34:58 +02002030 # The '0' coefficient is implementation specific to decimal.py.
2031 # It has no meaning in the C-version and is ignored there.
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002032 d = Decimal("Infinity")
2033 self.assertEqual(d.as_tuple(), (0, (0,), 'F') )
2034
Guido van Rossum8ce8a782007-11-01 19:42:39 +00002035 #leading zeros in coefficient should be stripped
2036 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), -2) )
2037 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), -2) )
2038 d = Decimal( (1, (0, 0, 0), 37) )
2039 self.assertEqual(d.as_tuple(), (1, (0,), 37))
2040 d = Decimal( (1, (), 37) )
2041 self.assertEqual(d.as_tuple(), (1, (0,), 37))
2042
2043 #leading zeros in NaN diagnostic info should be stripped
2044 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), 'n') )
2045 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), 'n') )
2046 d = Decimal( (1, (0, 0, 0), 'N') )
2047 self.assertEqual(d.as_tuple(), (1, (), 'N') )
2048 d = Decimal( (1, (), 'n') )
2049 self.assertEqual(d.as_tuple(), (1, (), 'n') )
2050
Stefan Krah76e12172012-09-10 19:34:58 +02002051 # For infinities, decimal.py has always silently accepted any
2052 # coefficient tuple.
2053 d = Decimal( (0, (0,), 'F') )
2054 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
2055 d = Decimal( (0, (4, 5, 3, 4), 'F') )
2056 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
2057 d = Decimal( (1, (0, 2, 7, 1), 'F') )
2058 self.assertEqual(d.as_tuple(), (1, (0,), 'F'))
Guido van Rossum8ce8a782007-11-01 19:42:39 +00002059
Stefan Krah53f2e0a2015-12-28 23:02:02 +01002060 def test_as_integer_ratio(self):
2061 Decimal = self.decimal.Decimal
2062
2063 # exceptional cases
2064 self.assertRaises(OverflowError,
2065 Decimal.as_integer_ratio, Decimal('inf'))
2066 self.assertRaises(OverflowError,
2067 Decimal.as_integer_ratio, Decimal('-inf'))
2068 self.assertRaises(ValueError,
2069 Decimal.as_integer_ratio, Decimal('-nan'))
2070 self.assertRaises(ValueError,
2071 Decimal.as_integer_ratio, Decimal('snan123'))
2072
2073 for exp in range(-4, 2):
2074 for coeff in range(1000):
2075 for sign in '+', '-':
2076 d = Decimal('%s%dE%d' % (sign, coeff, exp))
2077 pq = d.as_integer_ratio()
2078 p, q = pq
2079
2080 # check return type
2081 self.assertIsInstance(pq, tuple)
2082 self.assertIsInstance(p, int)
2083 self.assertIsInstance(q, int)
2084
2085 # check normalization: q should be positive;
2086 # p should be relatively prime to q.
2087 self.assertGreater(q, 0)
2088 self.assertEqual(math.gcd(p, q), 1)
2089
2090 # check that p/q actually gives the correct value
2091 self.assertEqual(Decimal(p) / Decimal(q), d)
2092
Stefan Krah1919b7e2012-03-21 18:25:23 +01002093 def test_subclassing(self):
2094 # Different behaviours when subclassing Decimal
2095 Decimal = self.decimal.Decimal
2096
2097 class MyDecimal(Decimal):
Stefan Krah0f82b762012-11-08 11:17:29 +01002098 y = None
Stefan Krah1919b7e2012-03-21 18:25:23 +01002099
2100 d1 = MyDecimal(1)
2101 d2 = MyDecimal(2)
2102 d = d1 + d2
2103 self.assertIs(type(d), Decimal)
2104
2105 d = d1.max(d2)
2106 self.assertIs(type(d), Decimal)
2107
2108 d = copy.copy(d1)
2109 self.assertIs(type(d), MyDecimal)
2110 self.assertEqual(d, d1)
2111
2112 d = copy.deepcopy(d1)
2113 self.assertIs(type(d), MyDecimal)
2114 self.assertEqual(d, d1)
2115
Stefan Krah0f82b762012-11-08 11:17:29 +01002116 # Decimal(Decimal)
2117 d = Decimal('1.0')
2118 x = Decimal(d)
2119 self.assertIs(type(x), Decimal)
2120 self.assertEqual(x, d)
Stefan Krahf4abc7b2012-11-07 23:12:25 +01002121
Stefan Krah0f82b762012-11-08 11:17:29 +01002122 # MyDecimal(Decimal)
2123 m = MyDecimal(d)
2124 self.assertIs(type(m), MyDecimal)
2125 self.assertEqual(m, d)
2126 self.assertIs(m.y, None)
2127
2128 # Decimal(MyDecimal)
2129 x = Decimal(m)
2130 self.assertIs(type(x), Decimal)
2131 self.assertEqual(x, d)
2132
2133 # MyDecimal(MyDecimal)
2134 m.y = 9
2135 x = MyDecimal(m)
2136 self.assertIs(type(x), MyDecimal)
2137 self.assertEqual(x, d)
2138 self.assertIs(x.y, None)
Stefan Krahed16eff2012-11-07 23:47:19 +01002139
Stefan Krah1919b7e2012-03-21 18:25:23 +01002140 def test_implicit_context(self):
2141 Decimal = self.decimal.Decimal
2142 getcontext = self.decimal.getcontext
2143
2144 # Check results when context given implicitly. (Issue 2478)
2145 c = getcontext()
2146 self.assertEqual(str(Decimal(0).sqrt()),
2147 str(c.sqrt(Decimal(0))))
2148
Stefan Krah040e3112012-12-15 22:33:33 +01002149 def test_none_args(self):
2150 Decimal = self.decimal.Decimal
2151 Context = self.decimal.Context
2152 localcontext = self.decimal.localcontext
2153 InvalidOperation = self.decimal.InvalidOperation
2154 DivisionByZero = self.decimal.DivisionByZero
2155 Overflow = self.decimal.Overflow
2156 Underflow = self.decimal.Underflow
2157 Subnormal = self.decimal.Subnormal
2158 Inexact = self.decimal.Inexact
2159 Rounded = self.decimal.Rounded
2160 Clamped = self.decimal.Clamped
Stefan Krah040e3112012-12-15 22:33:33 +01002161
2162 with localcontext(Context()) as c:
2163 c.prec = 7
2164 c.Emax = 999
2165 c.Emin = -999
2166
2167 x = Decimal("111")
2168 y = Decimal("1e9999")
2169 z = Decimal("1e-9999")
2170
2171 ##### Unary functions
2172 c.clear_flags()
2173 self.assertEqual(str(x.exp(context=None)), '1.609487E+48')
2174 self.assertTrue(c.flags[Inexact])
2175 self.assertTrue(c.flags[Rounded])
2176 c.clear_flags()
2177 self.assertRaises(Overflow, y.exp, context=None)
2178 self.assertTrue(c.flags[Overflow])
2179
2180 self.assertIs(z.is_normal(context=None), False)
2181 self.assertIs(z.is_subnormal(context=None), True)
2182
2183 c.clear_flags()
2184 self.assertEqual(str(x.ln(context=None)), '4.709530')
2185 self.assertTrue(c.flags[Inexact])
2186 self.assertTrue(c.flags[Rounded])
2187 c.clear_flags()
2188 self.assertRaises(InvalidOperation, Decimal(-1).ln, context=None)
2189 self.assertTrue(c.flags[InvalidOperation])
2190
2191 c.clear_flags()
2192 self.assertEqual(str(x.log10(context=None)), '2.045323')
2193 self.assertTrue(c.flags[Inexact])
2194 self.assertTrue(c.flags[Rounded])
2195 c.clear_flags()
2196 self.assertRaises(InvalidOperation, Decimal(-1).log10, context=None)
2197 self.assertTrue(c.flags[InvalidOperation])
2198
2199 c.clear_flags()
2200 self.assertEqual(str(x.logb(context=None)), '2')
2201 self.assertRaises(DivisionByZero, Decimal(0).logb, context=None)
2202 self.assertTrue(c.flags[DivisionByZero])
2203
2204 c.clear_flags()
2205 self.assertEqual(str(x.logical_invert(context=None)), '1111000')
2206 self.assertRaises(InvalidOperation, y.logical_invert, context=None)
2207 self.assertTrue(c.flags[InvalidOperation])
2208
2209 c.clear_flags()
2210 self.assertEqual(str(y.next_minus(context=None)), '9.999999E+999')
2211 self.assertRaises(InvalidOperation, Decimal('sNaN').next_minus, context=None)
2212 self.assertTrue(c.flags[InvalidOperation])
2213
2214 c.clear_flags()
2215 self.assertEqual(str(y.next_plus(context=None)), 'Infinity')
2216 self.assertRaises(InvalidOperation, Decimal('sNaN').next_plus, context=None)
2217 self.assertTrue(c.flags[InvalidOperation])
2218
2219 c.clear_flags()
2220 self.assertEqual(str(z.normalize(context=None)), '0')
2221 self.assertRaises(Overflow, y.normalize, context=None)
2222 self.assertTrue(c.flags[Overflow])
2223
2224 self.assertEqual(str(z.number_class(context=None)), '+Subnormal')
2225
2226 c.clear_flags()
2227 self.assertEqual(str(z.sqrt(context=None)), '0E-1005')
2228 self.assertTrue(c.flags[Clamped])
2229 self.assertTrue(c.flags[Inexact])
2230 self.assertTrue(c.flags[Rounded])
2231 self.assertTrue(c.flags[Subnormal])
2232 self.assertTrue(c.flags[Underflow])
2233 c.clear_flags()
2234 self.assertRaises(Overflow, y.sqrt, context=None)
2235 self.assertTrue(c.flags[Overflow])
2236
2237 c.capitals = 0
2238 self.assertEqual(str(z.to_eng_string(context=None)), '1e-9999')
2239 c.capitals = 1
2240
2241
2242 ##### Binary functions
2243 c.clear_flags()
2244 ans = str(x.compare(Decimal('Nan891287828'), context=None))
2245 self.assertEqual(ans, 'NaN1287828')
2246 self.assertRaises(InvalidOperation, x.compare, Decimal('sNaN'), context=None)
2247 self.assertTrue(c.flags[InvalidOperation])
2248
2249 c.clear_flags()
2250 ans = str(x.compare_signal(8224, context=None))
2251 self.assertEqual(ans, '-1')
2252 self.assertRaises(InvalidOperation, x.compare_signal, Decimal('NaN'), context=None)
2253 self.assertTrue(c.flags[InvalidOperation])
2254
2255 c.clear_flags()
2256 ans = str(x.logical_and(101, context=None))
2257 self.assertEqual(ans, '101')
2258 self.assertRaises(InvalidOperation, x.logical_and, 123, context=None)
2259 self.assertTrue(c.flags[InvalidOperation])
2260
2261 c.clear_flags()
2262 ans = str(x.logical_or(101, context=None))
2263 self.assertEqual(ans, '111')
2264 self.assertRaises(InvalidOperation, x.logical_or, 123, context=None)
2265 self.assertTrue(c.flags[InvalidOperation])
2266
2267 c.clear_flags()
2268 ans = str(x.logical_xor(101, context=None))
2269 self.assertEqual(ans, '10')
2270 self.assertRaises(InvalidOperation, x.logical_xor, 123, context=None)
2271 self.assertTrue(c.flags[InvalidOperation])
2272
2273 c.clear_flags()
2274 ans = str(x.max(101, context=None))
2275 self.assertEqual(ans, '111')
2276 self.assertRaises(InvalidOperation, x.max, Decimal('sNaN'), context=None)
2277 self.assertTrue(c.flags[InvalidOperation])
2278
2279 c.clear_flags()
2280 ans = str(x.max_mag(101, context=None))
2281 self.assertEqual(ans, '111')
2282 self.assertRaises(InvalidOperation, x.max_mag, Decimal('sNaN'), context=None)
2283 self.assertTrue(c.flags[InvalidOperation])
2284
2285 c.clear_flags()
2286 ans = str(x.min(101, context=None))
2287 self.assertEqual(ans, '101')
2288 self.assertRaises(InvalidOperation, x.min, Decimal('sNaN'), context=None)
2289 self.assertTrue(c.flags[InvalidOperation])
2290
2291 c.clear_flags()
2292 ans = str(x.min_mag(101, context=None))
2293 self.assertEqual(ans, '101')
2294 self.assertRaises(InvalidOperation, x.min_mag, Decimal('sNaN'), context=None)
2295 self.assertTrue(c.flags[InvalidOperation])
2296
2297 c.clear_flags()
2298 ans = str(x.remainder_near(101, context=None))
2299 self.assertEqual(ans, '10')
2300 self.assertRaises(InvalidOperation, y.remainder_near, 101, context=None)
2301 self.assertTrue(c.flags[InvalidOperation])
2302
2303 c.clear_flags()
2304 ans = str(x.rotate(2, context=None))
2305 self.assertEqual(ans, '11100')
2306 self.assertRaises(InvalidOperation, x.rotate, 101, context=None)
2307 self.assertTrue(c.flags[InvalidOperation])
2308
2309 c.clear_flags()
2310 ans = str(x.scaleb(7, context=None))
2311 self.assertEqual(ans, '1.11E+9')
2312 self.assertRaises(InvalidOperation, x.scaleb, 10000, context=None)
2313 self.assertTrue(c.flags[InvalidOperation])
2314
2315 c.clear_flags()
2316 ans = str(x.shift(2, context=None))
2317 self.assertEqual(ans, '11100')
2318 self.assertRaises(InvalidOperation, x.shift, 10000, context=None)
2319 self.assertTrue(c.flags[InvalidOperation])
2320
2321
2322 ##### Ternary functions
2323 c.clear_flags()
2324 ans = str(x.fma(2, 3, context=None))
2325 self.assertEqual(ans, '225')
2326 self.assertRaises(Overflow, x.fma, Decimal('1e9999'), 3, context=None)
2327 self.assertTrue(c.flags[Overflow])
2328
2329
2330 ##### Special cases
2331 c.rounding = ROUND_HALF_EVEN
2332 ans = str(Decimal('1.5').to_integral(rounding=None, context=None))
2333 self.assertEqual(ans, '2')
2334 c.rounding = ROUND_DOWN
2335 ans = str(Decimal('1.5').to_integral(rounding=None, context=None))
2336 self.assertEqual(ans, '1')
2337 ans = str(Decimal('1.5').to_integral(rounding=ROUND_UP, context=None))
2338 self.assertEqual(ans, '2')
2339 c.clear_flags()
2340 self.assertRaises(InvalidOperation, Decimal('sNaN').to_integral, context=None)
2341 self.assertTrue(c.flags[InvalidOperation])
2342
2343 c.rounding = ROUND_HALF_EVEN
2344 ans = str(Decimal('1.5').to_integral_value(rounding=None, context=None))
2345 self.assertEqual(ans, '2')
2346 c.rounding = ROUND_DOWN
2347 ans = str(Decimal('1.5').to_integral_value(rounding=None, context=None))
2348 self.assertEqual(ans, '1')
2349 ans = str(Decimal('1.5').to_integral_value(rounding=ROUND_UP, context=None))
2350 self.assertEqual(ans, '2')
2351 c.clear_flags()
2352 self.assertRaises(InvalidOperation, Decimal('sNaN').to_integral_value, context=None)
2353 self.assertTrue(c.flags[InvalidOperation])
2354
2355 c.rounding = ROUND_HALF_EVEN
2356 ans = str(Decimal('1.5').to_integral_exact(rounding=None, context=None))
2357 self.assertEqual(ans, '2')
2358 c.rounding = ROUND_DOWN
2359 ans = str(Decimal('1.5').to_integral_exact(rounding=None, context=None))
2360 self.assertEqual(ans, '1')
2361 ans = str(Decimal('1.5').to_integral_exact(rounding=ROUND_UP, context=None))
2362 self.assertEqual(ans, '2')
2363 c.clear_flags()
2364 self.assertRaises(InvalidOperation, Decimal('sNaN').to_integral_exact, context=None)
2365 self.assertTrue(c.flags[InvalidOperation])
2366
2367 c.rounding = ROUND_UP
2368 ans = str(Decimal('1.50001').quantize(exp=Decimal('1e-3'), rounding=None, context=None))
2369 self.assertEqual(ans, '1.501')
2370 c.rounding = ROUND_DOWN
2371 ans = str(Decimal('1.50001').quantize(exp=Decimal('1e-3'), rounding=None, context=None))
2372 self.assertEqual(ans, '1.500')
2373 ans = str(Decimal('1.50001').quantize(exp=Decimal('1e-3'), rounding=ROUND_UP, context=None))
2374 self.assertEqual(ans, '1.501')
2375 c.clear_flags()
2376 self.assertRaises(InvalidOperation, y.quantize, Decimal('1e-10'), rounding=ROUND_UP, context=None)
2377 self.assertTrue(c.flags[InvalidOperation])
2378
2379 with localcontext(Context()) as context:
2380 context.prec = 7
2381 context.Emax = 999
2382 context.Emin = -999
2383 with localcontext(ctx=None) as c:
2384 self.assertEqual(c.prec, 7)
2385 self.assertEqual(c.Emax, 999)
2386 self.assertEqual(c.Emin, -999)
2387
Stefan Krah1919b7e2012-03-21 18:25:23 +01002388 def test_conversions_from_int(self):
2389 # Check that methods taking a second Decimal argument will
2390 # always accept an integer in place of a Decimal.
2391 Decimal = self.decimal.Decimal
2392
2393 self.assertEqual(Decimal(4).compare(3),
2394 Decimal(4).compare(Decimal(3)))
2395 self.assertEqual(Decimal(4).compare_signal(3),
2396 Decimal(4).compare_signal(Decimal(3)))
2397 self.assertEqual(Decimal(4).compare_total(3),
2398 Decimal(4).compare_total(Decimal(3)))
2399 self.assertEqual(Decimal(4).compare_total_mag(3),
2400 Decimal(4).compare_total_mag(Decimal(3)))
2401 self.assertEqual(Decimal(10101).logical_and(1001),
2402 Decimal(10101).logical_and(Decimal(1001)))
2403 self.assertEqual(Decimal(10101).logical_or(1001),
2404 Decimal(10101).logical_or(Decimal(1001)))
2405 self.assertEqual(Decimal(10101).logical_xor(1001),
2406 Decimal(10101).logical_xor(Decimal(1001)))
2407 self.assertEqual(Decimal(567).max(123),
2408 Decimal(567).max(Decimal(123)))
2409 self.assertEqual(Decimal(567).max_mag(123),
2410 Decimal(567).max_mag(Decimal(123)))
2411 self.assertEqual(Decimal(567).min(123),
2412 Decimal(567).min(Decimal(123)))
2413 self.assertEqual(Decimal(567).min_mag(123),
2414 Decimal(567).min_mag(Decimal(123)))
2415 self.assertEqual(Decimal(567).next_toward(123),
2416 Decimal(567).next_toward(Decimal(123)))
2417 self.assertEqual(Decimal(1234).quantize(100),
2418 Decimal(1234).quantize(Decimal(100)))
2419 self.assertEqual(Decimal(768).remainder_near(1234),
2420 Decimal(768).remainder_near(Decimal(1234)))
2421 self.assertEqual(Decimal(123).rotate(1),
2422 Decimal(123).rotate(Decimal(1)))
2423 self.assertEqual(Decimal(1234).same_quantum(1000),
2424 Decimal(1234).same_quantum(Decimal(1000)))
2425 self.assertEqual(Decimal('9.123').scaleb(-100),
2426 Decimal('9.123').scaleb(Decimal(-100)))
2427 self.assertEqual(Decimal(456).shift(-1),
2428 Decimal(456).shift(Decimal(-1)))
2429
2430 self.assertEqual(Decimal(-12).fma(Decimal(45), 67),
2431 Decimal(-12).fma(Decimal(45), Decimal(67)))
2432 self.assertEqual(Decimal(-12).fma(45, 67),
2433 Decimal(-12).fma(Decimal(45), Decimal(67)))
2434 self.assertEqual(Decimal(-12).fma(45, Decimal(67)),
2435 Decimal(-12).fma(Decimal(45), Decimal(67)))
2436
2437class CUsabilityTest(UsabilityTest):
2438 decimal = C
2439class PyUsabilityTest(UsabilityTest):
2440 decimal = P
2441
2442class PythonAPItests(unittest.TestCase):
2443
2444 def test_abc(self):
2445 Decimal = self.decimal.Decimal
2446
2447 self.assertTrue(issubclass(Decimal, numbers.Number))
2448 self.assertFalse(issubclass(Decimal, numbers.Real))
2449 self.assertIsInstance(Decimal(0), numbers.Number)
2450 self.assertNotIsInstance(Decimal(0), numbers.Real)
2451
2452 def test_pickle(self):
Serhiy Storchakabad12572014-12-15 14:03:42 +02002453 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
2454 Decimal = self.decimal.Decimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01002455
Serhiy Storchakabad12572014-12-15 14:03:42 +02002456 savedecimal = sys.modules['decimal']
Stefan Krah1919b7e2012-03-21 18:25:23 +01002457
Serhiy Storchakabad12572014-12-15 14:03:42 +02002458 # Round trip
2459 sys.modules['decimal'] = self.decimal
2460 d = Decimal('-3.141590000')
2461 p = pickle.dumps(d, proto)
2462 e = pickle.loads(p)
2463 self.assertEqual(d, e)
Stefan Krah1919b7e2012-03-21 18:25:23 +01002464
Serhiy Storchakabad12572014-12-15 14:03:42 +02002465 if C:
2466 # Test interchangeability
2467 x = C.Decimal('-3.123e81723')
2468 y = P.Decimal('-3.123e81723')
Stefan Krah1919b7e2012-03-21 18:25:23 +01002469
Serhiy Storchakabad12572014-12-15 14:03:42 +02002470 sys.modules['decimal'] = C
2471 sx = pickle.dumps(x, proto)
2472 sys.modules['decimal'] = P
2473 r = pickle.loads(sx)
2474 self.assertIsInstance(r, P.Decimal)
2475 self.assertEqual(r, y)
Stefan Krah1919b7e2012-03-21 18:25:23 +01002476
Serhiy Storchakabad12572014-12-15 14:03:42 +02002477 sys.modules['decimal'] = P
2478 sy = pickle.dumps(y, proto)
2479 sys.modules['decimal'] = C
2480 r = pickle.loads(sy)
2481 self.assertIsInstance(r, C.Decimal)
2482 self.assertEqual(r, x)
Stefan Krah1919b7e2012-03-21 18:25:23 +01002483
Serhiy Storchakabad12572014-12-15 14:03:42 +02002484 x = C.Decimal('-3.123e81723').as_tuple()
2485 y = P.Decimal('-3.123e81723').as_tuple()
Stefan Krahf1d4e422014-04-29 18:23:35 +02002486
Serhiy Storchakabad12572014-12-15 14:03:42 +02002487 sys.modules['decimal'] = C
2488 sx = pickle.dumps(x, proto)
2489 sys.modules['decimal'] = P
2490 r = pickle.loads(sx)
2491 self.assertIsInstance(r, P.DecimalTuple)
2492 self.assertEqual(r, y)
Stefan Krahf1d4e422014-04-29 18:23:35 +02002493
Serhiy Storchakabad12572014-12-15 14:03:42 +02002494 sys.modules['decimal'] = P
2495 sy = pickle.dumps(y, proto)
2496 sys.modules['decimal'] = C
2497 r = pickle.loads(sy)
2498 self.assertIsInstance(r, C.DecimalTuple)
2499 self.assertEqual(r, x)
Stefan Krahf1d4e422014-04-29 18:23:35 +02002500
Serhiy Storchakabad12572014-12-15 14:03:42 +02002501 sys.modules['decimal'] = savedecimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01002502
2503 def test_int(self):
2504 Decimal = self.decimal.Decimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01002505
2506 for x in range(-250, 250):
2507 s = '%0.2f' % (x / 100.0)
2508 # should work the same as for floats
2509 self.assertEqual(int(Decimal(s)), int(float(s)))
2510 # should work the same as to_integral in the ROUND_DOWN mode
2511 d = Decimal(s)
2512 r = d.to_integral(ROUND_DOWN)
2513 self.assertEqual(Decimal(int(d)), r)
2514
2515 self.assertRaises(ValueError, int, Decimal('-nan'))
2516 self.assertRaises(ValueError, int, Decimal('snan'))
2517 self.assertRaises(OverflowError, int, Decimal('inf'))
2518 self.assertRaises(OverflowError, int, Decimal('-inf'))
2519
2520 def test_trunc(self):
2521 Decimal = self.decimal.Decimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01002522
2523 for x in range(-250, 250):
2524 s = '%0.2f' % (x / 100.0)
2525 # should work the same as for floats
2526 self.assertEqual(int(Decimal(s)), int(float(s)))
2527 # should work the same as to_integral in the ROUND_DOWN mode
2528 d = Decimal(s)
2529 r = d.to_integral(ROUND_DOWN)
2530 self.assertEqual(Decimal(math.trunc(d)), r)
2531
2532 def test_from_float(self):
2533
2534 Decimal = self.decimal.Decimal
2535
2536 class MyDecimal(Decimal):
Stefan Krah6817c592016-06-20 12:10:13 +02002537 def __init__(self, _):
2538 self.x = 'y'
Stefan Krah1919b7e2012-03-21 18:25:23 +01002539
2540 self.assertTrue(issubclass(MyDecimal, Decimal))
2541
2542 r = MyDecimal.from_float(0.1)
2543 self.assertEqual(type(r), MyDecimal)
2544 self.assertEqual(str(r),
2545 '0.1000000000000000055511151231257827021181583404541015625')
Stefan Krah6817c592016-06-20 12:10:13 +02002546 self.assertEqual(r.x, 'y')
2547
Stefan Krah1919b7e2012-03-21 18:25:23 +01002548 bigint = 12345678901234567890123456789
2549 self.assertEqual(MyDecimal.from_float(bigint), MyDecimal(bigint))
2550 self.assertTrue(MyDecimal.from_float(float('nan')).is_qnan())
2551 self.assertTrue(MyDecimal.from_float(float('inf')).is_infinite())
2552 self.assertTrue(MyDecimal.from_float(float('-inf')).is_infinite())
2553 self.assertEqual(str(MyDecimal.from_float(float('nan'))),
2554 str(Decimal('NaN')))
2555 self.assertEqual(str(MyDecimal.from_float(float('inf'))),
2556 str(Decimal('Infinity')))
2557 self.assertEqual(str(MyDecimal.from_float(float('-inf'))),
2558 str(Decimal('-Infinity')))
2559 self.assertRaises(TypeError, MyDecimal.from_float, 'abc')
2560 for i in range(200):
2561 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
2562 self.assertEqual(x, float(MyDecimal.from_float(x))) # roundtrip
2563
2564 def test_create_decimal_from_float(self):
2565 Decimal = self.decimal.Decimal
2566 Context = self.decimal.Context
Stefan Krah1919b7e2012-03-21 18:25:23 +01002567 Inexact = self.decimal.Inexact
2568
2569 context = Context(prec=5, rounding=ROUND_DOWN)
2570 self.assertEqual(
2571 context.create_decimal_from_float(math.pi),
2572 Decimal('3.1415')
2573 )
2574 context = Context(prec=5, rounding=ROUND_UP)
2575 self.assertEqual(
2576 context.create_decimal_from_float(math.pi),
2577 Decimal('3.1416')
2578 )
2579 context = Context(prec=5, traps=[Inexact])
2580 self.assertRaises(
2581 Inexact,
2582 context.create_decimal_from_float,
2583 math.pi
2584 )
2585 self.assertEqual(repr(context.create_decimal_from_float(-0.0)),
2586 "Decimal('-0')")
2587 self.assertEqual(repr(context.create_decimal_from_float(1.0)),
2588 "Decimal('1')")
2589 self.assertEqual(repr(context.create_decimal_from_float(10)),
2590 "Decimal('10')")
2591
2592 def test_quantize(self):
2593 Decimal = self.decimal.Decimal
2594 Context = self.decimal.Context
2595 InvalidOperation = self.decimal.InvalidOperation
Stefan Krah1919b7e2012-03-21 18:25:23 +01002596
2597 c = Context(Emax=99999, Emin=-99999)
2598 self.assertEqual(
2599 Decimal('7.335').quantize(Decimal('.01')),
2600 Decimal('7.34')
2601 )
2602 self.assertEqual(
2603 Decimal('7.335').quantize(Decimal('.01'), rounding=ROUND_DOWN),
2604 Decimal('7.33')
2605 )
2606 self.assertRaises(
2607 InvalidOperation,
2608 Decimal("10e99999").quantize, Decimal('1e100000'), context=c
2609 )
2610
2611 c = Context()
2612 d = Decimal("0.871831e800")
2613 x = d.quantize(context=c, exp=Decimal("1e797"), rounding=ROUND_DOWN)
2614 self.assertEqual(x, Decimal('8.71E+799'))
2615
2616 def test_complex(self):
2617 Decimal = self.decimal.Decimal
2618
2619 x = Decimal("9.8182731e181273")
2620 self.assertEqual(x.real, x)
2621 self.assertEqual(x.imag, 0)
2622 self.assertEqual(x.conjugate(), x)
2623
2624 x = Decimal("1")
2625 self.assertEqual(complex(x), complex(float(1)))
2626
2627 self.assertRaises(AttributeError, setattr, x, 'real', 100)
2628 self.assertRaises(AttributeError, setattr, x, 'imag', 100)
2629 self.assertRaises(AttributeError, setattr, x, 'conjugate', 100)
2630 self.assertRaises(AttributeError, setattr, x, '__complex__', 100)
2631
2632 def test_named_parameters(self):
2633 D = self.decimal.Decimal
2634 Context = self.decimal.Context
2635 localcontext = self.decimal.localcontext
2636 InvalidOperation = self.decimal.InvalidOperation
2637 Overflow = self.decimal.Overflow
2638
2639 xc = Context()
2640 xc.prec = 1
2641 xc.Emax = 1
2642 xc.Emin = -1
2643
2644 with localcontext() as c:
2645 c.clear_flags()
2646
2647 self.assertEqual(D(9, xc), 9)
2648 self.assertEqual(D(9, context=xc), 9)
2649 self.assertEqual(D(context=xc, value=9), 9)
2650 self.assertEqual(D(context=xc), 0)
2651 xc.clear_flags()
2652 self.assertRaises(InvalidOperation, D, "xyz", context=xc)
2653 self.assertTrue(xc.flags[InvalidOperation])
2654 self.assertFalse(c.flags[InvalidOperation])
2655
2656 xc.clear_flags()
2657 self.assertEqual(D(2).exp(context=xc), 7)
2658 self.assertRaises(Overflow, D(8).exp, context=xc)
2659 self.assertTrue(xc.flags[Overflow])
2660 self.assertFalse(c.flags[Overflow])
2661
2662 xc.clear_flags()
2663 self.assertEqual(D(2).ln(context=xc), D('0.7'))
2664 self.assertRaises(InvalidOperation, D(-1).ln, context=xc)
2665 self.assertTrue(xc.flags[InvalidOperation])
2666 self.assertFalse(c.flags[InvalidOperation])
2667
2668 self.assertEqual(D(0).log10(context=xc), D('-inf'))
2669 self.assertEqual(D(-1).next_minus(context=xc), -2)
2670 self.assertEqual(D(-1).next_plus(context=xc), D('-0.9'))
2671 self.assertEqual(D("9.73").normalize(context=xc), D('1E+1'))
2672 self.assertEqual(D("9999").to_integral(context=xc), 9999)
2673 self.assertEqual(D("-2000").to_integral_exact(context=xc), -2000)
2674 self.assertEqual(D("123").to_integral_value(context=xc), 123)
2675 self.assertEqual(D("0.0625").sqrt(context=xc), D('0.2'))
2676
2677 self.assertEqual(D("0.0625").compare(context=xc, other=3), -1)
2678 xc.clear_flags()
2679 self.assertRaises(InvalidOperation,
2680 D("0").compare_signal, D('nan'), context=xc)
2681 self.assertTrue(xc.flags[InvalidOperation])
2682 self.assertFalse(c.flags[InvalidOperation])
2683 self.assertEqual(D("0.01").max(D('0.0101'), context=xc), D('0.0'))
2684 self.assertEqual(D("0.01").max(D('0.0101'), context=xc), D('0.0'))
2685 self.assertEqual(D("0.2").max_mag(D('-0.3'), context=xc),
2686 D('-0.3'))
2687 self.assertEqual(D("0.02").min(D('-0.03'), context=xc), D('-0.0'))
2688 self.assertEqual(D("0.02").min_mag(D('-0.03'), context=xc),
2689 D('0.0'))
2690 self.assertEqual(D("0.2").next_toward(D('-1'), context=xc), D('0.1'))
2691 xc.clear_flags()
2692 self.assertRaises(InvalidOperation,
2693 D("0.2").quantize, D('1e10'), context=xc)
2694 self.assertTrue(xc.flags[InvalidOperation])
2695 self.assertFalse(c.flags[InvalidOperation])
2696 self.assertEqual(D("9.99").remainder_near(D('1.5'), context=xc),
2697 D('-0.5'))
2698
2699 self.assertEqual(D("9.9").fma(third=D('0.9'), context=xc, other=7),
2700 D('7E+1'))
2701
2702 self.assertRaises(TypeError, D(1).is_canonical, context=xc)
2703 self.assertRaises(TypeError, D(1).is_finite, context=xc)
2704 self.assertRaises(TypeError, D(1).is_infinite, context=xc)
2705 self.assertRaises(TypeError, D(1).is_nan, context=xc)
2706 self.assertRaises(TypeError, D(1).is_qnan, context=xc)
2707 self.assertRaises(TypeError, D(1).is_snan, context=xc)
2708 self.assertRaises(TypeError, D(1).is_signed, context=xc)
2709 self.assertRaises(TypeError, D(1).is_zero, context=xc)
2710
2711 self.assertFalse(D("0.01").is_normal(context=xc))
2712 self.assertTrue(D("0.01").is_subnormal(context=xc))
2713
2714 self.assertRaises(TypeError, D(1).adjusted, context=xc)
2715 self.assertRaises(TypeError, D(1).conjugate, context=xc)
2716 self.assertRaises(TypeError, D(1).radix, context=xc)
2717
2718 self.assertEqual(D(-111).logb(context=xc), 2)
2719 self.assertEqual(D(0).logical_invert(context=xc), 1)
2720 self.assertEqual(D('0.01').number_class(context=xc), '+Subnormal')
2721 self.assertEqual(D('0.21').to_eng_string(context=xc), '0.21')
2722
2723 self.assertEqual(D('11').logical_and(D('10'), context=xc), 0)
2724 self.assertEqual(D('11').logical_or(D('10'), context=xc), 1)
2725 self.assertEqual(D('01').logical_xor(D('10'), context=xc), 1)
2726 self.assertEqual(D('23').rotate(1, context=xc), 3)
2727 self.assertEqual(D('23').rotate(1, context=xc), 3)
2728 xc.clear_flags()
2729 self.assertRaises(Overflow,
2730 D('23').scaleb, 1, context=xc)
2731 self.assertTrue(xc.flags[Overflow])
2732 self.assertFalse(c.flags[Overflow])
2733 self.assertEqual(D('23').shift(-1, context=xc), 0)
2734
2735 self.assertRaises(TypeError, D.from_float, 1.1, context=xc)
2736 self.assertRaises(TypeError, D(0).as_tuple, context=xc)
2737
Stefan Krah040e3112012-12-15 22:33:33 +01002738 self.assertEqual(D(1).canonical(), 1)
2739 self.assertRaises(TypeError, D("-1").copy_abs, context=xc)
2740 self.assertRaises(TypeError, D("-1").copy_negate, context=xc)
2741 self.assertRaises(TypeError, D(1).canonical, context="x")
2742 self.assertRaises(TypeError, D(1).canonical, xyz="x")
Stefan Krah1919b7e2012-03-21 18:25:23 +01002743
Stefan Krahb6405ef2012-03-23 14:46:48 +01002744 def test_exception_hierarchy(self):
2745
2746 decimal = self.decimal
2747 DecimalException = decimal.DecimalException
2748 InvalidOperation = decimal.InvalidOperation
2749 FloatOperation = decimal.FloatOperation
2750 DivisionByZero = decimal.DivisionByZero
2751 Overflow = decimal.Overflow
2752 Underflow = decimal.Underflow
2753 Subnormal = decimal.Subnormal
2754 Inexact = decimal.Inexact
2755 Rounded = decimal.Rounded
2756 Clamped = decimal.Clamped
2757
2758 self.assertTrue(issubclass(DecimalException, ArithmeticError))
2759
2760 self.assertTrue(issubclass(InvalidOperation, DecimalException))
2761 self.assertTrue(issubclass(FloatOperation, DecimalException))
2762 self.assertTrue(issubclass(FloatOperation, TypeError))
2763 self.assertTrue(issubclass(DivisionByZero, DecimalException))
2764 self.assertTrue(issubclass(DivisionByZero, ZeroDivisionError))
2765 self.assertTrue(issubclass(Overflow, Rounded))
2766 self.assertTrue(issubclass(Overflow, Inexact))
2767 self.assertTrue(issubclass(Overflow, DecimalException))
2768 self.assertTrue(issubclass(Underflow, Inexact))
2769 self.assertTrue(issubclass(Underflow, Rounded))
2770 self.assertTrue(issubclass(Underflow, Subnormal))
2771 self.assertTrue(issubclass(Underflow, DecimalException))
2772
2773 self.assertTrue(issubclass(Subnormal, DecimalException))
2774 self.assertTrue(issubclass(Inexact, DecimalException))
2775 self.assertTrue(issubclass(Rounded, DecimalException))
2776 self.assertTrue(issubclass(Clamped, DecimalException))
2777
2778 self.assertTrue(issubclass(decimal.ConversionSyntax, InvalidOperation))
2779 self.assertTrue(issubclass(decimal.DivisionImpossible, InvalidOperation))
2780 self.assertTrue(issubclass(decimal.DivisionUndefined, InvalidOperation))
2781 self.assertTrue(issubclass(decimal.DivisionUndefined, ZeroDivisionError))
2782 self.assertTrue(issubclass(decimal.InvalidContext, InvalidOperation))
2783
Stefan Krah1919b7e2012-03-21 18:25:23 +01002784class CPythonAPItests(PythonAPItests):
2785 decimal = C
2786class PyPythonAPItests(PythonAPItests):
2787 decimal = P
2788
2789class ContextAPItests(unittest.TestCase):
2790
Stefan Krah9a4ff432012-12-16 21:10:35 +01002791 def test_none_args(self):
2792 Context = self.decimal.Context
2793 InvalidOperation = self.decimal.InvalidOperation
2794 DivisionByZero = self.decimal.DivisionByZero
2795 Overflow = self.decimal.Overflow
Stefan Krah9a4ff432012-12-16 21:10:35 +01002796
2797 c1 = Context()
2798 c2 = Context(prec=None, rounding=None, Emax=None, Emin=None,
2799 capitals=None, clamp=None, flags=None, traps=None)
2800 for c in [c1, c2]:
2801 self.assertEqual(c.prec, 28)
2802 self.assertEqual(c.rounding, ROUND_HALF_EVEN)
2803 self.assertEqual(c.Emax, 999999)
2804 self.assertEqual(c.Emin, -999999)
2805 self.assertEqual(c.capitals, 1)
2806 self.assertEqual(c.clamp, 0)
2807 assert_signals(self, c, 'flags', [])
2808 assert_signals(self, c, 'traps', [InvalidOperation, DivisionByZero,
2809 Overflow])
2810
Stefan Krah59a4a932013-01-16 12:58:59 +01002811 @cpython_only
2812 def test_from_legacy_strings(self):
2813 import _testcapi
2814 c = self.decimal.Context()
2815
2816 for rnd in RoundingModes:
2817 c.rounding = _testcapi.unicode_legacy_string(rnd)
2818 self.assertEqual(c.rounding, rnd)
2819
2820 s = _testcapi.unicode_legacy_string('')
2821 self.assertRaises(TypeError, setattr, c, 'rounding', s)
2822
2823 s = _testcapi.unicode_legacy_string('ROUND_\x00UP')
2824 self.assertRaises(TypeError, setattr, c, 'rounding', s)
2825
Stefan Krah1919b7e2012-03-21 18:25:23 +01002826 def test_pickle(self):
2827
Serhiy Storchakabad12572014-12-15 14:03:42 +02002828 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
2829 Context = self.decimal.Context
Stefan Krah1919b7e2012-03-21 18:25:23 +01002830
Serhiy Storchakabad12572014-12-15 14:03:42 +02002831 savedecimal = sys.modules['decimal']
Stefan Krah1919b7e2012-03-21 18:25:23 +01002832
Serhiy Storchakabad12572014-12-15 14:03:42 +02002833 # Round trip
2834 sys.modules['decimal'] = self.decimal
2835 c = Context()
2836 e = pickle.loads(pickle.dumps(c, proto))
Stefan Krah1919b7e2012-03-21 18:25:23 +01002837
Serhiy Storchakabad12572014-12-15 14:03:42 +02002838 self.assertEqual(c.prec, e.prec)
2839 self.assertEqual(c.Emin, e.Emin)
2840 self.assertEqual(c.Emax, e.Emax)
2841 self.assertEqual(c.rounding, e.rounding)
2842 self.assertEqual(c.capitals, e.capitals)
2843 self.assertEqual(c.clamp, e.clamp)
2844 self.assertEqual(c.flags, e.flags)
2845 self.assertEqual(c.traps, e.traps)
Stefan Krah1919b7e2012-03-21 18:25:23 +01002846
Serhiy Storchakabad12572014-12-15 14:03:42 +02002847 # Test interchangeability
2848 combinations = [(C, P), (P, C)] if C else [(P, P)]
2849 for dumper, loader in combinations:
2850 for ri, _ in enumerate(RoundingModes):
2851 for fi, _ in enumerate(OrderedSignals[dumper]):
2852 for ti, _ in enumerate(OrderedSignals[dumper]):
Stefan Krah1919b7e2012-03-21 18:25:23 +01002853
Serhiy Storchakabad12572014-12-15 14:03:42 +02002854 prec = random.randrange(1, 100)
2855 emin = random.randrange(-100, 0)
2856 emax = random.randrange(1, 100)
2857 caps = random.randrange(2)
2858 clamp = random.randrange(2)
Stefan Krah1919b7e2012-03-21 18:25:23 +01002859
Serhiy Storchakabad12572014-12-15 14:03:42 +02002860 # One module dumps
2861 sys.modules['decimal'] = dumper
2862 c = dumper.Context(
2863 prec=prec, Emin=emin, Emax=emax,
2864 rounding=RoundingModes[ri],
2865 capitals=caps, clamp=clamp,
2866 flags=OrderedSignals[dumper][:fi],
2867 traps=OrderedSignals[dumper][:ti]
2868 )
2869 s = pickle.dumps(c, proto)
Stefan Krah1919b7e2012-03-21 18:25:23 +01002870
Serhiy Storchakabad12572014-12-15 14:03:42 +02002871 # The other module loads
2872 sys.modules['decimal'] = loader
2873 d = pickle.loads(s)
2874 self.assertIsInstance(d, loader.Context)
Stefan Krah1919b7e2012-03-21 18:25:23 +01002875
Serhiy Storchakabad12572014-12-15 14:03:42 +02002876 self.assertEqual(d.prec, prec)
2877 self.assertEqual(d.Emin, emin)
2878 self.assertEqual(d.Emax, emax)
2879 self.assertEqual(d.rounding, RoundingModes[ri])
2880 self.assertEqual(d.capitals, caps)
2881 self.assertEqual(d.clamp, clamp)
2882 assert_signals(self, d, 'flags', OrderedSignals[loader][:fi])
2883 assert_signals(self, d, 'traps', OrderedSignals[loader][:ti])
Stefan Krah1919b7e2012-03-21 18:25:23 +01002884
Serhiy Storchakabad12572014-12-15 14:03:42 +02002885 sys.modules['decimal'] = savedecimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01002886
2887 def test_equality_with_other_types(self):
2888 Decimal = self.decimal.Decimal
2889
2890 self.assertIn(Decimal(10), ['a', 1.0, Decimal(10), (1,2), {}])
2891 self.assertNotIn(Decimal(10), ['a', 1.0, (1,2), {}])
2892
2893 def test_copy(self):
2894 # All copies should be deep
2895 Decimal = self.decimal.Decimal
2896 Context = self.decimal.Context
2897
2898 c = Context()
2899 d = c.copy()
2900 self.assertNotEqual(id(c), id(d))
2901 self.assertNotEqual(id(c.flags), id(d.flags))
2902 self.assertNotEqual(id(c.traps), id(d.traps))
2903 k1 = set(c.flags.keys())
2904 k2 = set(d.flags.keys())
2905 self.assertEqual(k1, k2)
2906 self.assertEqual(c.flags, d.flags)
2907
2908 def test__clamp(self):
2909 # In Python 3.2, the private attribute `_clamp` was made
2910 # public (issue 8540), with the old `_clamp` becoming a
2911 # property wrapping `clamp`. For the duration of Python 3.2
2912 # only, the attribute should be gettable/settable via both
2913 # `clamp` and `_clamp`; in Python 3.3, `_clamp` should be
2914 # removed.
2915 Context = self.decimal.Context
2916 c = Context()
2917 self.assertRaises(AttributeError, getattr, c, '_clamp')
2918
2919 def test_abs(self):
2920 Decimal = self.decimal.Decimal
2921 Context = self.decimal.Context
2922
2923 c = Context()
2924 d = c.abs(Decimal(-1))
2925 self.assertEqual(c.abs(-1), d)
2926 self.assertRaises(TypeError, c.abs, '-1')
2927
2928 def test_add(self):
2929 Decimal = self.decimal.Decimal
2930 Context = self.decimal.Context
2931
2932 c = Context()
2933 d = c.add(Decimal(1), Decimal(1))
2934 self.assertEqual(c.add(1, 1), d)
2935 self.assertEqual(c.add(Decimal(1), 1), d)
2936 self.assertEqual(c.add(1, Decimal(1)), d)
2937 self.assertRaises(TypeError, c.add, '1', 1)
2938 self.assertRaises(TypeError, c.add, 1, '1')
2939
2940 def test_compare(self):
2941 Decimal = self.decimal.Decimal
2942 Context = self.decimal.Context
2943
2944 c = Context()
2945 d = c.compare(Decimal(1), Decimal(1))
2946 self.assertEqual(c.compare(1, 1), d)
2947 self.assertEqual(c.compare(Decimal(1), 1), d)
2948 self.assertEqual(c.compare(1, Decimal(1)), d)
2949 self.assertRaises(TypeError, c.compare, '1', 1)
2950 self.assertRaises(TypeError, c.compare, 1, '1')
2951
2952 def test_compare_signal(self):
2953 Decimal = self.decimal.Decimal
2954 Context = self.decimal.Context
2955
2956 c = Context()
2957 d = c.compare_signal(Decimal(1), Decimal(1))
2958 self.assertEqual(c.compare_signal(1, 1), d)
2959 self.assertEqual(c.compare_signal(Decimal(1), 1), d)
2960 self.assertEqual(c.compare_signal(1, Decimal(1)), d)
2961 self.assertRaises(TypeError, c.compare_signal, '1', 1)
2962 self.assertRaises(TypeError, c.compare_signal, 1, '1')
2963
2964 def test_compare_total(self):
2965 Decimal = self.decimal.Decimal
2966 Context = self.decimal.Context
2967
2968 c = Context()
2969 d = c.compare_total(Decimal(1), Decimal(1))
2970 self.assertEqual(c.compare_total(1, 1), d)
2971 self.assertEqual(c.compare_total(Decimal(1), 1), d)
2972 self.assertEqual(c.compare_total(1, Decimal(1)), d)
2973 self.assertRaises(TypeError, c.compare_total, '1', 1)
2974 self.assertRaises(TypeError, c.compare_total, 1, '1')
2975
2976 def test_compare_total_mag(self):
2977 Decimal = self.decimal.Decimal
2978 Context = self.decimal.Context
2979
2980 c = Context()
2981 d = c.compare_total_mag(Decimal(1), Decimal(1))
2982 self.assertEqual(c.compare_total_mag(1, 1), d)
2983 self.assertEqual(c.compare_total_mag(Decimal(1), 1), d)
2984 self.assertEqual(c.compare_total_mag(1, Decimal(1)), d)
2985 self.assertRaises(TypeError, c.compare_total_mag, '1', 1)
2986 self.assertRaises(TypeError, c.compare_total_mag, 1, '1')
2987
2988 def test_copy_abs(self):
2989 Decimal = self.decimal.Decimal
2990 Context = self.decimal.Context
2991
2992 c = Context()
2993 d = c.copy_abs(Decimal(-1))
2994 self.assertEqual(c.copy_abs(-1), d)
2995 self.assertRaises(TypeError, c.copy_abs, '-1')
2996
2997 def test_copy_decimal(self):
2998 Decimal = self.decimal.Decimal
2999 Context = self.decimal.Context
3000
3001 c = Context()
3002 d = c.copy_decimal(Decimal(-1))
3003 self.assertEqual(c.copy_decimal(-1), d)
3004 self.assertRaises(TypeError, c.copy_decimal, '-1')
3005
3006 def test_copy_negate(self):
3007 Decimal = self.decimal.Decimal
3008 Context = self.decimal.Context
3009
3010 c = Context()
3011 d = c.copy_negate(Decimal(-1))
3012 self.assertEqual(c.copy_negate(-1), d)
3013 self.assertRaises(TypeError, c.copy_negate, '-1')
3014
3015 def test_copy_sign(self):
3016 Decimal = self.decimal.Decimal
3017 Context = self.decimal.Context
3018
3019 c = Context()
3020 d = c.copy_sign(Decimal(1), Decimal(-2))
3021 self.assertEqual(c.copy_sign(1, -2), d)
3022 self.assertEqual(c.copy_sign(Decimal(1), -2), d)
3023 self.assertEqual(c.copy_sign(1, Decimal(-2)), d)
3024 self.assertRaises(TypeError, c.copy_sign, '1', -2)
3025 self.assertRaises(TypeError, c.copy_sign, 1, '-2')
3026
3027 def test_divide(self):
3028 Decimal = self.decimal.Decimal
3029 Context = self.decimal.Context
3030
3031 c = Context()
3032 d = c.divide(Decimal(1), Decimal(2))
3033 self.assertEqual(c.divide(1, 2), d)
3034 self.assertEqual(c.divide(Decimal(1), 2), d)
3035 self.assertEqual(c.divide(1, Decimal(2)), d)
3036 self.assertRaises(TypeError, c.divide, '1', 2)
3037 self.assertRaises(TypeError, c.divide, 1, '2')
3038
3039 def test_divide_int(self):
3040 Decimal = self.decimal.Decimal
3041 Context = self.decimal.Context
3042
3043 c = Context()
3044 d = c.divide_int(Decimal(1), Decimal(2))
3045 self.assertEqual(c.divide_int(1, 2), d)
3046 self.assertEqual(c.divide_int(Decimal(1), 2), d)
3047 self.assertEqual(c.divide_int(1, Decimal(2)), d)
3048 self.assertRaises(TypeError, c.divide_int, '1', 2)
3049 self.assertRaises(TypeError, c.divide_int, 1, '2')
3050
3051 def test_divmod(self):
3052 Decimal = self.decimal.Decimal
3053 Context = self.decimal.Context
3054
3055 c = Context()
3056 d = c.divmod(Decimal(1), Decimal(2))
3057 self.assertEqual(c.divmod(1, 2), d)
3058 self.assertEqual(c.divmod(Decimal(1), 2), d)
3059 self.assertEqual(c.divmod(1, Decimal(2)), d)
3060 self.assertRaises(TypeError, c.divmod, '1', 2)
3061 self.assertRaises(TypeError, c.divmod, 1, '2')
3062
3063 def test_exp(self):
3064 Decimal = self.decimal.Decimal
3065 Context = self.decimal.Context
3066
3067 c = Context()
3068 d = c.exp(Decimal(10))
3069 self.assertEqual(c.exp(10), d)
3070 self.assertRaises(TypeError, c.exp, '10')
3071
3072 def test_fma(self):
3073 Decimal = self.decimal.Decimal
3074 Context = self.decimal.Context
3075
3076 c = Context()
3077 d = c.fma(Decimal(2), Decimal(3), Decimal(4))
3078 self.assertEqual(c.fma(2, 3, 4), d)
3079 self.assertEqual(c.fma(Decimal(2), 3, 4), d)
3080 self.assertEqual(c.fma(2, Decimal(3), 4), d)
3081 self.assertEqual(c.fma(2, 3, Decimal(4)), d)
3082 self.assertEqual(c.fma(Decimal(2), Decimal(3), 4), d)
3083 self.assertRaises(TypeError, c.fma, '2', 3, 4)
3084 self.assertRaises(TypeError, c.fma, 2, '3', 4)
3085 self.assertRaises(TypeError, c.fma, 2, 3, '4')
3086
3087 # Issue 12079 for Context.fma ...
3088 self.assertRaises(TypeError, c.fma,
3089 Decimal('Infinity'), Decimal(0), "not a decimal")
3090 self.assertRaises(TypeError, c.fma,
3091 Decimal(1), Decimal('snan'), 1.222)
3092 # ... and for Decimal.fma.
3093 self.assertRaises(TypeError, Decimal('Infinity').fma,
3094 Decimal(0), "not a decimal")
3095 self.assertRaises(TypeError, Decimal(1).fma,
3096 Decimal('snan'), 1.222)
3097
3098 def test_is_finite(self):
3099 Decimal = self.decimal.Decimal
3100 Context = self.decimal.Context
3101
3102 c = Context()
3103 d = c.is_finite(Decimal(10))
3104 self.assertEqual(c.is_finite(10), d)
3105 self.assertRaises(TypeError, c.is_finite, '10')
3106
3107 def test_is_infinite(self):
3108 Decimal = self.decimal.Decimal
3109 Context = self.decimal.Context
3110
3111 c = Context()
3112 d = c.is_infinite(Decimal(10))
3113 self.assertEqual(c.is_infinite(10), d)
3114 self.assertRaises(TypeError, c.is_infinite, '10')
3115
3116 def test_is_nan(self):
3117 Decimal = self.decimal.Decimal
3118 Context = self.decimal.Context
3119
3120 c = Context()
3121 d = c.is_nan(Decimal(10))
3122 self.assertEqual(c.is_nan(10), d)
3123 self.assertRaises(TypeError, c.is_nan, '10')
3124
3125 def test_is_normal(self):
3126 Decimal = self.decimal.Decimal
3127 Context = self.decimal.Context
3128
3129 c = Context()
3130 d = c.is_normal(Decimal(10))
3131 self.assertEqual(c.is_normal(10), d)
3132 self.assertRaises(TypeError, c.is_normal, '10')
3133
3134 def test_is_qnan(self):
3135 Decimal = self.decimal.Decimal
3136 Context = self.decimal.Context
3137
3138 c = Context()
3139 d = c.is_qnan(Decimal(10))
3140 self.assertEqual(c.is_qnan(10), d)
3141 self.assertRaises(TypeError, c.is_qnan, '10')
3142
3143 def test_is_signed(self):
3144 Decimal = self.decimal.Decimal
3145 Context = self.decimal.Context
3146
3147 c = Context()
3148 d = c.is_signed(Decimal(10))
3149 self.assertEqual(c.is_signed(10), d)
3150 self.assertRaises(TypeError, c.is_signed, '10')
3151
3152 def test_is_snan(self):
3153 Decimal = self.decimal.Decimal
3154 Context = self.decimal.Context
3155
3156 c = Context()
3157 d = c.is_snan(Decimal(10))
3158 self.assertEqual(c.is_snan(10), d)
3159 self.assertRaises(TypeError, c.is_snan, '10')
3160
3161 def test_is_subnormal(self):
3162 Decimal = self.decimal.Decimal
3163 Context = self.decimal.Context
3164
3165 c = Context()
3166 d = c.is_subnormal(Decimal(10))
3167 self.assertEqual(c.is_subnormal(10), d)
3168 self.assertRaises(TypeError, c.is_subnormal, '10')
3169
3170 def test_is_zero(self):
3171 Decimal = self.decimal.Decimal
3172 Context = self.decimal.Context
3173
3174 c = Context()
3175 d = c.is_zero(Decimal(10))
3176 self.assertEqual(c.is_zero(10), d)
3177 self.assertRaises(TypeError, c.is_zero, '10')
3178
3179 def test_ln(self):
3180 Decimal = self.decimal.Decimal
3181 Context = self.decimal.Context
3182
3183 c = Context()
3184 d = c.ln(Decimal(10))
3185 self.assertEqual(c.ln(10), d)
3186 self.assertRaises(TypeError, c.ln, '10')
3187
3188 def test_log10(self):
3189 Decimal = self.decimal.Decimal
3190 Context = self.decimal.Context
3191
3192 c = Context()
3193 d = c.log10(Decimal(10))
3194 self.assertEqual(c.log10(10), d)
3195 self.assertRaises(TypeError, c.log10, '10')
3196
3197 def test_logb(self):
3198 Decimal = self.decimal.Decimal
3199 Context = self.decimal.Context
3200
3201 c = Context()
3202 d = c.logb(Decimal(10))
3203 self.assertEqual(c.logb(10), d)
3204 self.assertRaises(TypeError, c.logb, '10')
3205
3206 def test_logical_and(self):
3207 Decimal = self.decimal.Decimal
3208 Context = self.decimal.Context
3209
3210 c = Context()
3211 d = c.logical_and(Decimal(1), Decimal(1))
3212 self.assertEqual(c.logical_and(1, 1), d)
3213 self.assertEqual(c.logical_and(Decimal(1), 1), d)
3214 self.assertEqual(c.logical_and(1, Decimal(1)), d)
3215 self.assertRaises(TypeError, c.logical_and, '1', 1)
3216 self.assertRaises(TypeError, c.logical_and, 1, '1')
3217
3218 def test_logical_invert(self):
3219 Decimal = self.decimal.Decimal
3220 Context = self.decimal.Context
3221
3222 c = Context()
3223 d = c.logical_invert(Decimal(1000))
3224 self.assertEqual(c.logical_invert(1000), d)
3225 self.assertRaises(TypeError, c.logical_invert, '1000')
3226
3227 def test_logical_or(self):
3228 Decimal = self.decimal.Decimal
3229 Context = self.decimal.Context
3230
3231 c = Context()
3232 d = c.logical_or(Decimal(1), Decimal(1))
3233 self.assertEqual(c.logical_or(1, 1), d)
3234 self.assertEqual(c.logical_or(Decimal(1), 1), d)
3235 self.assertEqual(c.logical_or(1, Decimal(1)), d)
3236 self.assertRaises(TypeError, c.logical_or, '1', 1)
3237 self.assertRaises(TypeError, c.logical_or, 1, '1')
3238
3239 def test_logical_xor(self):
3240 Decimal = self.decimal.Decimal
3241 Context = self.decimal.Context
3242
3243 c = Context()
3244 d = c.logical_xor(Decimal(1), Decimal(1))
3245 self.assertEqual(c.logical_xor(1, 1), d)
3246 self.assertEqual(c.logical_xor(Decimal(1), 1), d)
3247 self.assertEqual(c.logical_xor(1, Decimal(1)), d)
3248 self.assertRaises(TypeError, c.logical_xor, '1', 1)
3249 self.assertRaises(TypeError, c.logical_xor, 1, '1')
3250
3251 def test_max(self):
3252 Decimal = self.decimal.Decimal
3253 Context = self.decimal.Context
3254
3255 c = Context()
3256 d = c.max(Decimal(1), Decimal(2))
3257 self.assertEqual(c.max(1, 2), d)
3258 self.assertEqual(c.max(Decimal(1), 2), d)
3259 self.assertEqual(c.max(1, Decimal(2)), d)
3260 self.assertRaises(TypeError, c.max, '1', 2)
3261 self.assertRaises(TypeError, c.max, 1, '2')
3262
3263 def test_max_mag(self):
3264 Decimal = self.decimal.Decimal
3265 Context = self.decimal.Context
3266
3267 c = Context()
3268 d = c.max_mag(Decimal(1), Decimal(2))
3269 self.assertEqual(c.max_mag(1, 2), d)
3270 self.assertEqual(c.max_mag(Decimal(1), 2), d)
3271 self.assertEqual(c.max_mag(1, Decimal(2)), d)
3272 self.assertRaises(TypeError, c.max_mag, '1', 2)
3273 self.assertRaises(TypeError, c.max_mag, 1, '2')
3274
3275 def test_min(self):
3276 Decimal = self.decimal.Decimal
3277 Context = self.decimal.Context
3278
3279 c = Context()
3280 d = c.min(Decimal(1), Decimal(2))
3281 self.assertEqual(c.min(1, 2), d)
3282 self.assertEqual(c.min(Decimal(1), 2), d)
3283 self.assertEqual(c.min(1, Decimal(2)), d)
3284 self.assertRaises(TypeError, c.min, '1', 2)
3285 self.assertRaises(TypeError, c.min, 1, '2')
3286
3287 def test_min_mag(self):
3288 Decimal = self.decimal.Decimal
3289 Context = self.decimal.Context
3290
3291 c = Context()
3292 d = c.min_mag(Decimal(1), Decimal(2))
3293 self.assertEqual(c.min_mag(1, 2), d)
3294 self.assertEqual(c.min_mag(Decimal(1), 2), d)
3295 self.assertEqual(c.min_mag(1, Decimal(2)), d)
3296 self.assertRaises(TypeError, c.min_mag, '1', 2)
3297 self.assertRaises(TypeError, c.min_mag, 1, '2')
3298
3299 def test_minus(self):
3300 Decimal = self.decimal.Decimal
3301 Context = self.decimal.Context
3302
3303 c = Context()
3304 d = c.minus(Decimal(10))
3305 self.assertEqual(c.minus(10), d)
3306 self.assertRaises(TypeError, c.minus, '10')
3307
3308 def test_multiply(self):
3309 Decimal = self.decimal.Decimal
3310 Context = self.decimal.Context
3311
3312 c = Context()
3313 d = c.multiply(Decimal(1), Decimal(2))
3314 self.assertEqual(c.multiply(1, 2), d)
3315 self.assertEqual(c.multiply(Decimal(1), 2), d)
3316 self.assertEqual(c.multiply(1, Decimal(2)), d)
3317 self.assertRaises(TypeError, c.multiply, '1', 2)
3318 self.assertRaises(TypeError, c.multiply, 1, '2')
3319
3320 def test_next_minus(self):
3321 Decimal = self.decimal.Decimal
3322 Context = self.decimal.Context
3323
3324 c = Context()
3325 d = c.next_minus(Decimal(10))
3326 self.assertEqual(c.next_minus(10), d)
3327 self.assertRaises(TypeError, c.next_minus, '10')
3328
3329 def test_next_plus(self):
3330 Decimal = self.decimal.Decimal
3331 Context = self.decimal.Context
3332
3333 c = Context()
3334 d = c.next_plus(Decimal(10))
3335 self.assertEqual(c.next_plus(10), d)
3336 self.assertRaises(TypeError, c.next_plus, '10')
3337
3338 def test_next_toward(self):
3339 Decimal = self.decimal.Decimal
3340 Context = self.decimal.Context
3341
3342 c = Context()
3343 d = c.next_toward(Decimal(1), Decimal(2))
3344 self.assertEqual(c.next_toward(1, 2), d)
3345 self.assertEqual(c.next_toward(Decimal(1), 2), d)
3346 self.assertEqual(c.next_toward(1, Decimal(2)), d)
3347 self.assertRaises(TypeError, c.next_toward, '1', 2)
3348 self.assertRaises(TypeError, c.next_toward, 1, '2')
3349
3350 def test_normalize(self):
3351 Decimal = self.decimal.Decimal
3352 Context = self.decimal.Context
3353
3354 c = Context()
3355 d = c.normalize(Decimal(10))
3356 self.assertEqual(c.normalize(10), d)
3357 self.assertRaises(TypeError, c.normalize, '10')
3358
3359 def test_number_class(self):
3360 Decimal = self.decimal.Decimal
3361 Context = self.decimal.Context
3362
3363 c = Context()
3364 self.assertEqual(c.number_class(123), c.number_class(Decimal(123)))
3365 self.assertEqual(c.number_class(0), c.number_class(Decimal(0)))
3366 self.assertEqual(c.number_class(-45), c.number_class(Decimal(-45)))
3367
3368 def test_plus(self):
3369 Decimal = self.decimal.Decimal
3370 Context = self.decimal.Context
3371
3372 c = Context()
3373 d = c.plus(Decimal(10))
3374 self.assertEqual(c.plus(10), d)
3375 self.assertRaises(TypeError, c.plus, '10')
3376
3377 def test_power(self):
3378 Decimal = self.decimal.Decimal
3379 Context = self.decimal.Context
3380
3381 c = Context()
3382 d = c.power(Decimal(1), Decimal(4))
3383 self.assertEqual(c.power(1, 4), d)
3384 self.assertEqual(c.power(Decimal(1), 4), d)
3385 self.assertEqual(c.power(1, Decimal(4)), d)
3386 self.assertEqual(c.power(Decimal(1), Decimal(4)), d)
3387 self.assertRaises(TypeError, c.power, '1', 4)
3388 self.assertRaises(TypeError, c.power, 1, '4')
3389 self.assertEqual(c.power(modulo=5, b=8, a=2), 1)
3390
3391 def test_quantize(self):
3392 Decimal = self.decimal.Decimal
3393 Context = self.decimal.Context
3394
3395 c = Context()
3396 d = c.quantize(Decimal(1), Decimal(2))
3397 self.assertEqual(c.quantize(1, 2), d)
3398 self.assertEqual(c.quantize(Decimal(1), 2), d)
3399 self.assertEqual(c.quantize(1, Decimal(2)), d)
3400 self.assertRaises(TypeError, c.quantize, '1', 2)
3401 self.assertRaises(TypeError, c.quantize, 1, '2')
3402
3403 def test_remainder(self):
3404 Decimal = self.decimal.Decimal
3405 Context = self.decimal.Context
3406
3407 c = Context()
3408 d = c.remainder(Decimal(1), Decimal(2))
3409 self.assertEqual(c.remainder(1, 2), d)
3410 self.assertEqual(c.remainder(Decimal(1), 2), d)
3411 self.assertEqual(c.remainder(1, Decimal(2)), d)
3412 self.assertRaises(TypeError, c.remainder, '1', 2)
3413 self.assertRaises(TypeError, c.remainder, 1, '2')
3414
3415 def test_remainder_near(self):
3416 Decimal = self.decimal.Decimal
3417 Context = self.decimal.Context
3418
3419 c = Context()
3420 d = c.remainder_near(Decimal(1), Decimal(2))
3421 self.assertEqual(c.remainder_near(1, 2), d)
3422 self.assertEqual(c.remainder_near(Decimal(1), 2), d)
3423 self.assertEqual(c.remainder_near(1, Decimal(2)), d)
3424 self.assertRaises(TypeError, c.remainder_near, '1', 2)
3425 self.assertRaises(TypeError, c.remainder_near, 1, '2')
3426
3427 def test_rotate(self):
3428 Decimal = self.decimal.Decimal
3429 Context = self.decimal.Context
3430
3431 c = Context()
3432 d = c.rotate(Decimal(1), Decimal(2))
3433 self.assertEqual(c.rotate(1, 2), d)
3434 self.assertEqual(c.rotate(Decimal(1), 2), d)
3435 self.assertEqual(c.rotate(1, Decimal(2)), d)
3436 self.assertRaises(TypeError, c.rotate, '1', 2)
3437 self.assertRaises(TypeError, c.rotate, 1, '2')
3438
3439 def test_sqrt(self):
3440 Decimal = self.decimal.Decimal
3441 Context = self.decimal.Context
3442
3443 c = Context()
3444 d = c.sqrt(Decimal(10))
3445 self.assertEqual(c.sqrt(10), d)
3446 self.assertRaises(TypeError, c.sqrt, '10')
3447
3448 def test_same_quantum(self):
3449 Decimal = self.decimal.Decimal
3450 Context = self.decimal.Context
3451
3452 c = Context()
3453 d = c.same_quantum(Decimal(1), Decimal(2))
3454 self.assertEqual(c.same_quantum(1, 2), d)
3455 self.assertEqual(c.same_quantum(Decimal(1), 2), d)
3456 self.assertEqual(c.same_quantum(1, Decimal(2)), d)
3457 self.assertRaises(TypeError, c.same_quantum, '1', 2)
3458 self.assertRaises(TypeError, c.same_quantum, 1, '2')
3459
3460 def test_scaleb(self):
3461 Decimal = self.decimal.Decimal
3462 Context = self.decimal.Context
3463
3464 c = Context()
3465 d = c.scaleb(Decimal(1), Decimal(2))
3466 self.assertEqual(c.scaleb(1, 2), d)
3467 self.assertEqual(c.scaleb(Decimal(1), 2), d)
3468 self.assertEqual(c.scaleb(1, Decimal(2)), d)
3469 self.assertRaises(TypeError, c.scaleb, '1', 2)
3470 self.assertRaises(TypeError, c.scaleb, 1, '2')
3471
3472 def test_shift(self):
3473 Decimal = self.decimal.Decimal
3474 Context = self.decimal.Context
3475
3476 c = Context()
3477 d = c.shift(Decimal(1), Decimal(2))
3478 self.assertEqual(c.shift(1, 2), d)
3479 self.assertEqual(c.shift(Decimal(1), 2), d)
3480 self.assertEqual(c.shift(1, Decimal(2)), d)
3481 self.assertRaises(TypeError, c.shift, '1', 2)
3482 self.assertRaises(TypeError, c.shift, 1, '2')
3483
3484 def test_subtract(self):
3485 Decimal = self.decimal.Decimal
3486 Context = self.decimal.Context
3487
3488 c = Context()
3489 d = c.subtract(Decimal(1), Decimal(2))
3490 self.assertEqual(c.subtract(1, 2), d)
3491 self.assertEqual(c.subtract(Decimal(1), 2), d)
3492 self.assertEqual(c.subtract(1, Decimal(2)), d)
3493 self.assertRaises(TypeError, c.subtract, '1', 2)
3494 self.assertRaises(TypeError, c.subtract, 1, '2')
3495
3496 def test_to_eng_string(self):
3497 Decimal = self.decimal.Decimal
3498 Context = self.decimal.Context
3499
3500 c = Context()
3501 d = c.to_eng_string(Decimal(10))
3502 self.assertEqual(c.to_eng_string(10), d)
3503 self.assertRaises(TypeError, c.to_eng_string, '10')
3504
3505 def test_to_sci_string(self):
3506 Decimal = self.decimal.Decimal
3507 Context = self.decimal.Context
3508
3509 c = Context()
3510 d = c.to_sci_string(Decimal(10))
3511 self.assertEqual(c.to_sci_string(10), d)
3512 self.assertRaises(TypeError, c.to_sci_string, '10')
3513
3514 def test_to_integral_exact(self):
3515 Decimal = self.decimal.Decimal
3516 Context = self.decimal.Context
3517
3518 c = Context()
3519 d = c.to_integral_exact(Decimal(10))
3520 self.assertEqual(c.to_integral_exact(10), d)
3521 self.assertRaises(TypeError, c.to_integral_exact, '10')
3522
3523 def test_to_integral_value(self):
3524 Decimal = self.decimal.Decimal
3525 Context = self.decimal.Context
3526
3527 c = Context()
3528 d = c.to_integral_value(Decimal(10))
3529 self.assertEqual(c.to_integral_value(10), d)
3530 self.assertRaises(TypeError, c.to_integral_value, '10')
3531 self.assertRaises(TypeError, c.to_integral_value, 10, 'x')
3532
3533class CContextAPItests(ContextAPItests):
3534 decimal = C
3535class PyContextAPItests(ContextAPItests):
3536 decimal = P
3537
3538class ContextWithStatement(unittest.TestCase):
3539 # Can't do these as docstrings until Python 2.6
3540 # as doctest can't handle __future__ statements
3541
3542 def test_localcontext(self):
3543 # Use a copy of the current context in the block
3544 getcontext = self.decimal.getcontext
3545 localcontext = self.decimal.localcontext
3546
3547 orig_ctx = getcontext()
3548 with localcontext() as enter_ctx:
3549 set_ctx = getcontext()
3550 final_ctx = getcontext()
3551 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
3552 self.assertIsNot(orig_ctx, set_ctx, 'did not copy the context')
3553 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
3554
3555 def test_localcontextarg(self):
3556 # Use a copy of the supplied context in the block
3557 Context = self.decimal.Context
3558 getcontext = self.decimal.getcontext
3559 localcontext = self.decimal.localcontext
3560
3561 localcontext = self.decimal.localcontext
3562 orig_ctx = getcontext()
3563 new_ctx = Context(prec=42)
3564 with localcontext(new_ctx) as enter_ctx:
3565 set_ctx = getcontext()
3566 final_ctx = getcontext()
3567 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
3568 self.assertEqual(set_ctx.prec, new_ctx.prec, 'did not set correct context')
3569 self.assertIsNot(new_ctx, set_ctx, 'did not copy the context')
3570 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
3571
3572 def test_nested_with_statements(self):
3573 # Use a copy of the supplied context in the block
3574 Decimal = self.decimal.Decimal
3575 Context = self.decimal.Context
3576 getcontext = self.decimal.getcontext
3577 localcontext = self.decimal.localcontext
3578 Clamped = self.decimal.Clamped
3579 Overflow = self.decimal.Overflow
3580
3581 orig_ctx = getcontext()
3582 orig_ctx.clear_flags()
3583 new_ctx = Context(Emax=384)
3584 with localcontext() as c1:
3585 self.assertEqual(c1.flags, orig_ctx.flags)
3586 self.assertEqual(c1.traps, orig_ctx.traps)
3587 c1.traps[Clamped] = True
3588 c1.Emin = -383
3589 self.assertNotEqual(orig_ctx.Emin, -383)
3590 self.assertRaises(Clamped, c1.create_decimal, '0e-999')
3591 self.assertTrue(c1.flags[Clamped])
3592 with localcontext(new_ctx) as c2:
3593 self.assertEqual(c2.flags, new_ctx.flags)
3594 self.assertEqual(c2.traps, new_ctx.traps)
3595 self.assertRaises(Overflow, c2.power, Decimal('3.4e200'), 2)
3596 self.assertFalse(c2.flags[Clamped])
3597 self.assertTrue(c2.flags[Overflow])
3598 del c2
3599 self.assertFalse(c1.flags[Overflow])
3600 del c1
3601 self.assertNotEqual(orig_ctx.Emin, -383)
3602 self.assertFalse(orig_ctx.flags[Clamped])
3603 self.assertFalse(orig_ctx.flags[Overflow])
3604 self.assertFalse(new_ctx.flags[Clamped])
3605 self.assertFalse(new_ctx.flags[Overflow])
3606
3607 def test_with_statements_gc1(self):
3608 localcontext = self.decimal.localcontext
3609
3610 with localcontext() as c1:
3611 del c1
3612 with localcontext() as c2:
3613 del c2
3614 with localcontext() as c3:
3615 del c3
3616 with localcontext() as c4:
3617 del c4
3618
3619 def test_with_statements_gc2(self):
3620 localcontext = self.decimal.localcontext
3621
3622 with localcontext() as c1:
3623 with localcontext(c1) as c2:
3624 del c1
3625 with localcontext(c2) as c3:
3626 del c2
3627 with localcontext(c3) as c4:
3628 del c3
3629 del c4
3630
3631 def test_with_statements_gc3(self):
3632 Context = self.decimal.Context
3633 localcontext = self.decimal.localcontext
3634 getcontext = self.decimal.getcontext
3635 setcontext = self.decimal.setcontext
3636
3637 with localcontext() as c1:
3638 del c1
3639 n1 = Context(prec=1)
3640 setcontext(n1)
3641 with localcontext(n1) as c2:
3642 del n1
3643 self.assertEqual(c2.prec, 1)
3644 del c2
3645 n2 = Context(prec=2)
3646 setcontext(n2)
3647 del n2
3648 self.assertEqual(getcontext().prec, 2)
3649 n3 = Context(prec=3)
3650 setcontext(n3)
3651 self.assertEqual(getcontext().prec, 3)
3652 with localcontext(n3) as c3:
3653 del n3
3654 self.assertEqual(c3.prec, 3)
3655 del c3
3656 n4 = Context(prec=4)
3657 setcontext(n4)
3658 del n4
3659 self.assertEqual(getcontext().prec, 4)
3660 with localcontext() as c4:
3661 self.assertEqual(c4.prec, 4)
3662 del c4
3663
3664class CContextWithStatement(ContextWithStatement):
3665 decimal = C
3666class PyContextWithStatement(ContextWithStatement):
3667 decimal = P
3668
3669class ContextFlags(unittest.TestCase):
3670
3671 def test_flags_irrelevant(self):
3672 # check that the result (numeric result + flags raised) of an
3673 # arithmetic operation doesn't depend on the current flags
3674 Decimal = self.decimal.Decimal
3675 Context = self.decimal.Context
3676 Inexact = self.decimal.Inexact
3677 Rounded = self.decimal.Rounded
3678 Underflow = self.decimal.Underflow
3679 Clamped = self.decimal.Clamped
3680 Subnormal = self.decimal.Subnormal
Stefan Krah1919b7e2012-03-21 18:25:23 +01003681
3682 def raise_error(context, flag):
3683 if self.decimal == C:
3684 context.flags[flag] = True
3685 if context.traps[flag]:
3686 raise flag
3687 else:
3688 context._raise_error(flag)
3689
3690 context = Context(prec=9, Emin = -425000000, Emax = 425000000,
3691 rounding=ROUND_HALF_EVEN, traps=[], flags=[])
3692
3693 # operations that raise various flags, in the form (function, arglist)
3694 operations = [
3695 (context._apply, [Decimal("100E-425000010")]),
3696 (context.sqrt, [Decimal(2)]),
3697 (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]),
3698 (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]),
3699 (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]),
3700 ]
3701
3702 # try various flags individually, then a whole lot at once
3703 flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal],
3704 [Inexact, Rounded, Underflow, Clamped, Subnormal]]
3705
3706 for fn, args in operations:
3707 # find answer and flags raised using a clean context
3708 context.clear_flags()
3709 ans = fn(*args)
3710 flags = [k for k, v in context.flags.items() if v]
3711
3712 for extra_flags in flagsets:
3713 # set flags, before calling operation
3714 context.clear_flags()
3715 for flag in extra_flags:
3716 raise_error(context, flag)
3717 new_ans = fn(*args)
3718
3719 # flags that we expect to be set after the operation
3720 expected_flags = list(flags)
3721 for flag in extra_flags:
3722 if flag not in expected_flags:
3723 expected_flags.append(flag)
3724 expected_flags.sort(key=id)
3725
3726 # flags we actually got
3727 new_flags = [k for k,v in context.flags.items() if v]
3728 new_flags.sort(key=id)
3729
3730 self.assertEqual(ans, new_ans,
3731 "operation produces different answers depending on flags set: " +
3732 "expected %s, got %s." % (ans, new_ans))
3733 self.assertEqual(new_flags, expected_flags,
3734 "operation raises different flags depending on flags set: " +
3735 "expected %s, got %s" % (expected_flags, new_flags))
3736
3737 def test_flag_comparisons(self):
3738 Context = self.decimal.Context
3739 Inexact = self.decimal.Inexact
3740 Rounded = self.decimal.Rounded
3741
3742 c = Context()
3743
3744 # Valid SignalDict
3745 self.assertNotEqual(c.flags, c.traps)
3746 self.assertNotEqual(c.traps, c.flags)
3747
3748 c.flags = c.traps
3749 self.assertEqual(c.flags, c.traps)
3750 self.assertEqual(c.traps, c.flags)
3751
3752 c.flags[Rounded] = True
3753 c.traps = c.flags
3754 self.assertEqual(c.flags, c.traps)
3755 self.assertEqual(c.traps, c.flags)
3756
3757 d = {}
3758 d.update(c.flags)
3759 self.assertEqual(d, c.flags)
3760 self.assertEqual(c.flags, d)
3761
3762 d[Inexact] = True
3763 self.assertNotEqual(d, c.flags)
3764 self.assertNotEqual(c.flags, d)
3765
3766 # Invalid SignalDict
3767 d = {Inexact:False}
3768 self.assertNotEqual(d, c.flags)
3769 self.assertNotEqual(c.flags, d)
3770
3771 d = ["xyz"]
3772 self.assertNotEqual(d, c.flags)
3773 self.assertNotEqual(c.flags, d)
3774
3775 @requires_IEEE_754
3776 def test_float_operation(self):
3777 Decimal = self.decimal.Decimal
3778 FloatOperation = self.decimal.FloatOperation
3779 localcontext = self.decimal.localcontext
3780
3781 with localcontext() as c:
3782 ##### trap is off by default
3783 self.assertFalse(c.traps[FloatOperation])
3784
3785 # implicit conversion sets the flag
3786 c.clear_flags()
3787 self.assertEqual(Decimal(7.5), 7.5)
3788 self.assertTrue(c.flags[FloatOperation])
3789
3790 c.clear_flags()
3791 self.assertEqual(c.create_decimal(7.5), 7.5)
3792 self.assertTrue(c.flags[FloatOperation])
3793
3794 # explicit conversion does not set the flag
3795 c.clear_flags()
3796 x = Decimal.from_float(7.5)
3797 self.assertFalse(c.flags[FloatOperation])
3798 # comparison sets the flag
3799 self.assertEqual(x, 7.5)
3800 self.assertTrue(c.flags[FloatOperation])
3801
3802 c.clear_flags()
3803 x = c.create_decimal_from_float(7.5)
3804 self.assertFalse(c.flags[FloatOperation])
3805 self.assertEqual(x, 7.5)
3806 self.assertTrue(c.flags[FloatOperation])
3807
3808 ##### set the trap
3809 c.traps[FloatOperation] = True
3810
3811 # implicit conversion raises
3812 c.clear_flags()
3813 self.assertRaises(FloatOperation, Decimal, 7.5)
3814 self.assertTrue(c.flags[FloatOperation])
3815
3816 c.clear_flags()
3817 self.assertRaises(FloatOperation, c.create_decimal, 7.5)
3818 self.assertTrue(c.flags[FloatOperation])
3819
3820 # explicit conversion is silent
3821 c.clear_flags()
3822 x = Decimal.from_float(7.5)
3823 self.assertFalse(c.flags[FloatOperation])
3824
3825 c.clear_flags()
3826 x = c.create_decimal_from_float(7.5)
3827 self.assertFalse(c.flags[FloatOperation])
3828
3829 def test_float_comparison(self):
3830 Decimal = self.decimal.Decimal
3831 Context = self.decimal.Context
3832 FloatOperation = self.decimal.FloatOperation
3833 localcontext = self.decimal.localcontext
3834
3835 def assert_attr(a, b, attr, context, signal=None):
3836 context.clear_flags()
3837 f = getattr(a, attr)
3838 if signal == FloatOperation:
3839 self.assertRaises(signal, f, b)
3840 else:
3841 self.assertIs(f(b), True)
3842 self.assertTrue(context.flags[FloatOperation])
3843
3844 small_d = Decimal('0.25')
3845 big_d = Decimal('3.0')
3846 small_f = 0.25
3847 big_f = 3.0
3848
3849 zero_d = Decimal('0.0')
3850 neg_zero_d = Decimal('-0.0')
3851 zero_f = 0.0
3852 neg_zero_f = -0.0
3853
3854 inf_d = Decimal('Infinity')
3855 neg_inf_d = Decimal('-Infinity')
3856 inf_f = float('inf')
3857 neg_inf_f = float('-inf')
3858
3859 def doit(c, signal=None):
3860 # Order
3861 for attr in '__lt__', '__le__':
3862 assert_attr(small_d, big_f, attr, c, signal)
3863
3864 for attr in '__gt__', '__ge__':
3865 assert_attr(big_d, small_f, attr, c, signal)
3866
3867 # Equality
3868 assert_attr(small_d, small_f, '__eq__', c, None)
3869
3870 assert_attr(neg_zero_d, neg_zero_f, '__eq__', c, None)
3871 assert_attr(neg_zero_d, zero_f, '__eq__', c, None)
3872
3873 assert_attr(zero_d, neg_zero_f, '__eq__', c, None)
3874 assert_attr(zero_d, zero_f, '__eq__', c, None)
3875
3876 assert_attr(neg_inf_d, neg_inf_f, '__eq__', c, None)
3877 assert_attr(inf_d, inf_f, '__eq__', c, None)
3878
3879 # Inequality
3880 assert_attr(small_d, big_f, '__ne__', c, None)
3881
3882 assert_attr(Decimal('0.1'), 0.1, '__ne__', c, None)
3883
3884 assert_attr(neg_inf_d, inf_f, '__ne__', c, None)
3885 assert_attr(inf_d, neg_inf_f, '__ne__', c, None)
3886
3887 assert_attr(Decimal('NaN'), float('nan'), '__ne__', c, None)
3888
3889 def test_containers(c, signal=None):
3890 c.clear_flags()
3891 s = set([100.0, Decimal('100.0')])
3892 self.assertEqual(len(s), 1)
3893 self.assertTrue(c.flags[FloatOperation])
3894
3895 c.clear_flags()
3896 if signal:
3897 self.assertRaises(signal, sorted, [1.0, Decimal('10.0')])
3898 else:
3899 s = sorted([10.0, Decimal('10.0')])
3900 self.assertTrue(c.flags[FloatOperation])
3901
3902 c.clear_flags()
3903 b = 10.0 in [Decimal('10.0'), 1.0]
3904 self.assertTrue(c.flags[FloatOperation])
3905
3906 c.clear_flags()
3907 b = 10.0 in {Decimal('10.0'):'a', 1.0:'b'}
3908 self.assertTrue(c.flags[FloatOperation])
3909
3910 nc = Context()
3911 with localcontext(nc) as c:
3912 self.assertFalse(c.traps[FloatOperation])
3913 doit(c, signal=None)
3914 test_containers(c, signal=None)
3915
3916 c.traps[FloatOperation] = True
3917 doit(c, signal=FloatOperation)
3918 test_containers(c, signal=FloatOperation)
3919
3920 def test_float_operation_default(self):
3921 Decimal = self.decimal.Decimal
3922 Context = self.decimal.Context
3923 Inexact = self.decimal.Inexact
3924 FloatOperation= self.decimal.FloatOperation
3925
3926 context = Context()
3927 self.assertFalse(context.flags[FloatOperation])
3928 self.assertFalse(context.traps[FloatOperation])
3929
3930 context.clear_traps()
3931 context.traps[Inexact] = True
3932 context.traps[FloatOperation] = True
3933 self.assertTrue(context.traps[FloatOperation])
3934 self.assertTrue(context.traps[Inexact])
3935
3936class CContextFlags(ContextFlags):
3937 decimal = C
3938class PyContextFlags(ContextFlags):
3939 decimal = P
3940
3941class SpecialContexts(unittest.TestCase):
3942 """Test the context templates."""
3943
3944 def test_context_templates(self):
3945 BasicContext = self.decimal.BasicContext
3946 ExtendedContext = self.decimal.ExtendedContext
3947 getcontext = self.decimal.getcontext
3948 setcontext = self.decimal.setcontext
3949 InvalidOperation = self.decimal.InvalidOperation
3950 DivisionByZero = self.decimal.DivisionByZero
3951 Overflow = self.decimal.Overflow
3952 Underflow = self.decimal.Underflow
3953 Clamped = self.decimal.Clamped
3954
3955 assert_signals(self, BasicContext, 'traps',
3956 [InvalidOperation, DivisionByZero, Overflow, Underflow, Clamped]
3957 )
3958
3959 savecontext = getcontext().copy()
3960 basic_context_prec = BasicContext.prec
3961 extended_context_prec = ExtendedContext.prec
3962
3963 ex = None
3964 try:
3965 BasicContext.prec = ExtendedContext.prec = 441
3966 for template in BasicContext, ExtendedContext:
3967 setcontext(template)
3968 c = getcontext()
3969 self.assertIsNot(c, template)
3970 self.assertEqual(c.prec, 441)
3971 except Exception as e:
3972 ex = e.__class__
3973 finally:
3974 BasicContext.prec = basic_context_prec
3975 ExtendedContext.prec = extended_context_prec
3976 setcontext(savecontext)
3977 if ex:
3978 raise ex
3979
3980 def test_default_context(self):
3981 DefaultContext = self.decimal.DefaultContext
3982 BasicContext = self.decimal.BasicContext
3983 ExtendedContext = self.decimal.ExtendedContext
3984 getcontext = self.decimal.getcontext
3985 setcontext = self.decimal.setcontext
3986 InvalidOperation = self.decimal.InvalidOperation
3987 DivisionByZero = self.decimal.DivisionByZero
3988 Overflow = self.decimal.Overflow
3989
3990 self.assertEqual(BasicContext.prec, 9)
3991 self.assertEqual(ExtendedContext.prec, 9)
3992
3993 assert_signals(self, DefaultContext, 'traps',
3994 [InvalidOperation, DivisionByZero, Overflow]
3995 )
3996
3997 savecontext = getcontext().copy()
3998 default_context_prec = DefaultContext.prec
3999
4000 ex = None
4001 try:
4002 c = getcontext()
4003 saveprec = c.prec
4004
4005 DefaultContext.prec = 961
4006 c = getcontext()
4007 self.assertEqual(c.prec, saveprec)
4008
4009 setcontext(DefaultContext)
4010 c = getcontext()
4011 self.assertIsNot(c, DefaultContext)
4012 self.assertEqual(c.prec, 961)
4013 except Exception as e:
4014 ex = e.__class__
4015 finally:
4016 DefaultContext.prec = default_context_prec
4017 setcontext(savecontext)
4018 if ex:
4019 raise ex
4020
4021class CSpecialContexts(SpecialContexts):
4022 decimal = C
4023class PySpecialContexts(SpecialContexts):
4024 decimal = P
4025
4026class ContextInputValidation(unittest.TestCase):
4027
4028 def test_invalid_context(self):
4029 Context = self.decimal.Context
4030 DefaultContext = self.decimal.DefaultContext
4031
4032 c = DefaultContext.copy()
4033
4034 # prec, Emax
4035 for attr in ['prec', 'Emax']:
4036 setattr(c, attr, 999999)
4037 self.assertEqual(getattr(c, attr), 999999)
4038 self.assertRaises(ValueError, setattr, c, attr, -1)
4039 self.assertRaises(TypeError, setattr, c, attr, 'xyz')
4040
4041 # Emin
4042 setattr(c, 'Emin', -999999)
4043 self.assertEqual(getattr(c, 'Emin'), -999999)
4044 self.assertRaises(ValueError, setattr, c, 'Emin', 1)
4045 self.assertRaises(TypeError, setattr, c, 'Emin', (1,2,3))
4046
Stefan Krah1919b7e2012-03-21 18:25:23 +01004047 self.assertRaises(TypeError, setattr, c, 'rounding', -1)
4048 self.assertRaises(TypeError, setattr, c, 'rounding', 9)
4049 self.assertRaises(TypeError, setattr, c, 'rounding', 1.0)
4050 self.assertRaises(TypeError, setattr, c, 'rounding', 'xyz')
4051
4052 # capitals, clamp
4053 for attr in ['capitals', 'clamp']:
4054 self.assertRaises(ValueError, setattr, c, attr, -1)
4055 self.assertRaises(ValueError, setattr, c, attr, 2)
4056 self.assertRaises(TypeError, setattr, c, attr, [1,2,3])
4057
4058 # Invalid attribute
4059 self.assertRaises(AttributeError, setattr, c, 'emax', 100)
4060
4061 # Invalid signal dict
4062 self.assertRaises(TypeError, setattr, c, 'flags', [])
4063 self.assertRaises(KeyError, setattr, c, 'flags', {})
4064 self.assertRaises(KeyError, setattr, c, 'traps',
4065 {'InvalidOperation':0})
4066
4067 # Attributes cannot be deleted
4068 for attr in ['prec', 'Emax', 'Emin', 'rounding', 'capitals', 'clamp',
4069 'flags', 'traps']:
4070 self.assertRaises(AttributeError, c.__delattr__, attr)
4071
4072 # Invalid attributes
4073 self.assertRaises(TypeError, getattr, c, 9)
4074 self.assertRaises(TypeError, setattr, c, 9)
4075
4076 # Invalid values in constructor
4077 self.assertRaises(TypeError, Context, rounding=999999)
4078 self.assertRaises(TypeError, Context, rounding='xyz')
4079 self.assertRaises(ValueError, Context, clamp=2)
4080 self.assertRaises(ValueError, Context, capitals=-1)
4081 self.assertRaises(KeyError, Context, flags=["P"])
4082 self.assertRaises(KeyError, Context, traps=["Q"])
4083
4084 # Type error in conversion
4085 self.assertRaises(TypeError, Context, flags=(0,1))
4086 self.assertRaises(TypeError, Context, traps=(1,0))
4087
4088class CContextInputValidation(ContextInputValidation):
4089 decimal = C
4090class PyContextInputValidation(ContextInputValidation):
4091 decimal = P
4092
4093class ContextSubclassing(unittest.TestCase):
4094
4095 def test_context_subclassing(self):
4096 decimal = self.decimal
4097 Decimal = decimal.Decimal
4098 Context = decimal.Context
Stefan Krah1919b7e2012-03-21 18:25:23 +01004099 Clamped = decimal.Clamped
4100 DivisionByZero = decimal.DivisionByZero
4101 Inexact = decimal.Inexact
4102 Overflow = decimal.Overflow
4103 Rounded = decimal.Rounded
4104 Subnormal = decimal.Subnormal
4105 Underflow = decimal.Underflow
4106 InvalidOperation = decimal.InvalidOperation
4107
4108 class MyContext(Context):
4109 def __init__(self, prec=None, rounding=None, Emin=None, Emax=None,
4110 capitals=None, clamp=None, flags=None,
4111 traps=None):
4112 Context.__init__(self)
4113 if prec is not None:
4114 self.prec = prec
4115 if rounding is not None:
4116 self.rounding = rounding
4117 if Emin is not None:
4118 self.Emin = Emin
4119 if Emax is not None:
4120 self.Emax = Emax
4121 if capitals is not None:
4122 self.capitals = capitals
4123 if clamp is not None:
4124 self.clamp = clamp
4125 if flags is not None:
4126 if isinstance(flags, list):
4127 flags = {v:(v in flags) for v in OrderedSignals[decimal] + flags}
4128 self.flags = flags
4129 if traps is not None:
4130 if isinstance(traps, list):
4131 traps = {v:(v in traps) for v in OrderedSignals[decimal] + traps}
4132 self.traps = traps
4133
4134 c = Context()
4135 d = MyContext()
4136 for attr in ('prec', 'rounding', 'Emin', 'Emax', 'capitals', 'clamp',
4137 'flags', 'traps'):
4138 self.assertEqual(getattr(c, attr), getattr(d, attr))
4139
4140 # prec
4141 self.assertRaises(ValueError, MyContext, **{'prec':-1})
4142 c = MyContext(prec=1)
4143 self.assertEqual(c.prec, 1)
4144 self.assertRaises(InvalidOperation, c.quantize, Decimal('9e2'), 0)
4145
4146 # rounding
4147 self.assertRaises(TypeError, MyContext, **{'rounding':'XYZ'})
4148 c = MyContext(rounding=ROUND_DOWN, prec=1)
4149 self.assertEqual(c.rounding, ROUND_DOWN)
4150 self.assertEqual(c.plus(Decimal('9.9')), 9)
4151
4152 # Emin
4153 self.assertRaises(ValueError, MyContext, **{'Emin':5})
4154 c = MyContext(Emin=-1, prec=1)
4155 self.assertEqual(c.Emin, -1)
4156 x = c.add(Decimal('1e-99'), Decimal('2.234e-2000'))
4157 self.assertEqual(x, Decimal('0.0'))
4158 for signal in (Inexact, Underflow, Subnormal, Rounded, Clamped):
4159 self.assertTrue(c.flags[signal])
4160
4161 # Emax
4162 self.assertRaises(ValueError, MyContext, **{'Emax':-1})
4163 c = MyContext(Emax=1, prec=1)
4164 self.assertEqual(c.Emax, 1)
4165 self.assertRaises(Overflow, c.add, Decimal('1e99'), Decimal('2.234e2000'))
4166 if self.decimal == C:
4167 for signal in (Inexact, Overflow, Rounded):
4168 self.assertTrue(c.flags[signal])
4169
4170 # capitals
4171 self.assertRaises(ValueError, MyContext, **{'capitals':-1})
4172 c = MyContext(capitals=0)
4173 self.assertEqual(c.capitals, 0)
4174 x = c.create_decimal('1E222')
4175 self.assertEqual(c.to_sci_string(x), '1e+222')
4176
4177 # clamp
4178 self.assertRaises(ValueError, MyContext, **{'clamp':2})
4179 c = MyContext(clamp=1, Emax=99)
4180 self.assertEqual(c.clamp, 1)
4181 x = c.plus(Decimal('1e99'))
4182 self.assertEqual(str(x), '1.000000000000000000000000000E+99')
4183
4184 # flags
4185 self.assertRaises(TypeError, MyContext, **{'flags':'XYZ'})
4186 c = MyContext(flags=[Rounded, DivisionByZero])
4187 for signal in (Rounded, DivisionByZero):
4188 self.assertTrue(c.flags[signal])
4189 c.clear_flags()
4190 for signal in OrderedSignals[decimal]:
4191 self.assertFalse(c.flags[signal])
4192
4193 # traps
4194 self.assertRaises(TypeError, MyContext, **{'traps':'XYZ'})
4195 c = MyContext(traps=[Rounded, DivisionByZero])
4196 for signal in (Rounded, DivisionByZero):
4197 self.assertTrue(c.traps[signal])
4198 c.clear_traps()
4199 for signal in OrderedSignals[decimal]:
4200 self.assertFalse(c.traps[signal])
4201
4202class CContextSubclassing(ContextSubclassing):
4203 decimal = C
4204class PyContextSubclassing(ContextSubclassing):
4205 decimal = P
4206
4207@skip_if_extra_functionality
4208class CheckAttributes(unittest.TestCase):
4209
4210 def test_module_attributes(self):
4211
4212 # Architecture dependent context limits
4213 self.assertEqual(C.MAX_PREC, P.MAX_PREC)
4214 self.assertEqual(C.MAX_EMAX, P.MAX_EMAX)
4215 self.assertEqual(C.MIN_EMIN, P.MIN_EMIN)
4216 self.assertEqual(C.MIN_ETINY, P.MIN_ETINY)
4217
4218 self.assertTrue(C.HAVE_THREADS is True or C.HAVE_THREADS is False)
4219 self.assertTrue(P.HAVE_THREADS is True or P.HAVE_THREADS is False)
4220
4221 self.assertEqual(C.__version__, P.__version__)
4222
Stefan Krahb578f8a2014-09-10 17:58:15 +02004223 self.assertEqual(dir(C), dir(P))
Stefan Krah1919b7e2012-03-21 18:25:23 +01004224
4225 def test_context_attributes(self):
4226
4227 x = [s for s in dir(C.Context()) if '__' in s or not s.startswith('_')]
4228 y = [s for s in dir(P.Context()) if '__' in s or not s.startswith('_')]
4229 self.assertEqual(set(x) - set(y), set())
4230
4231 def test_decimal_attributes(self):
4232
4233 x = [s for s in dir(C.Decimal(9)) if '__' in s or not s.startswith('_')]
4234 y = [s for s in dir(C.Decimal(9)) if '__' in s or not s.startswith('_')]
4235 self.assertEqual(set(x) - set(y), set())
4236
4237class Coverage(unittest.TestCase):
4238
4239 def test_adjusted(self):
4240 Decimal = self.decimal.Decimal
4241
4242 self.assertEqual(Decimal('1234e9999').adjusted(), 10002)
4243 # XXX raise?
4244 self.assertEqual(Decimal('nan').adjusted(), 0)
4245 self.assertEqual(Decimal('inf').adjusted(), 0)
4246
4247 def test_canonical(self):
4248 Decimal = self.decimal.Decimal
4249 getcontext = self.decimal.getcontext
4250
4251 x = Decimal(9).canonical()
4252 self.assertEqual(x, 9)
4253
4254 c = getcontext()
4255 x = c.canonical(Decimal(9))
4256 self.assertEqual(x, 9)
4257
4258 def test_context_repr(self):
4259 c = self.decimal.DefaultContext.copy()
4260
4261 c.prec = 425000000
4262 c.Emax = 425000000
4263 c.Emin = -425000000
Stefan Krah59a4a932013-01-16 12:58:59 +01004264 c.rounding = ROUND_HALF_DOWN
Stefan Krah1919b7e2012-03-21 18:25:23 +01004265 c.capitals = 0
4266 c.clamp = 1
4267 for sig in OrderedSignals[self.decimal]:
4268 c.flags[sig] = False
4269 c.traps[sig] = False
4270
4271 s = c.__repr__()
4272 t = "Context(prec=425000000, rounding=ROUND_HALF_DOWN, " \
4273 "Emin=-425000000, Emax=425000000, capitals=0, clamp=1, " \
4274 "flags=[], traps=[])"
4275 self.assertEqual(s, t)
4276
4277 def test_implicit_context(self):
4278 Decimal = self.decimal.Decimal
4279 localcontext = self.decimal.localcontext
4280
4281 with localcontext() as c:
4282 c.prec = 1
4283 c.Emax = 1
4284 c.Emin = -1
4285
4286 # abs
4287 self.assertEqual(abs(Decimal("-10")), 10)
4288 # add
4289 self.assertEqual(Decimal("7") + 1, 8)
4290 # divide
4291 self.assertEqual(Decimal("10") / 5, 2)
4292 # divide_int
4293 self.assertEqual(Decimal("10") // 7, 1)
4294 # fma
4295 self.assertEqual(Decimal("1.2").fma(Decimal("0.01"), 1), 1)
4296 self.assertIs(Decimal("NaN").fma(7, 1).is_nan(), True)
4297 # three arg power
4298 self.assertEqual(pow(Decimal(10), 2, 7), 2)
4299 # exp
4300 self.assertEqual(Decimal("1.01").exp(), 3)
4301 # is_normal
4302 self.assertIs(Decimal("0.01").is_normal(), False)
4303 # is_subnormal
4304 self.assertIs(Decimal("0.01").is_subnormal(), True)
4305 # ln
4306 self.assertEqual(Decimal("20").ln(), 3)
4307 # log10
4308 self.assertEqual(Decimal("20").log10(), 1)
4309 # logb
4310 self.assertEqual(Decimal("580").logb(), 2)
4311 # logical_invert
4312 self.assertEqual(Decimal("10").logical_invert(), 1)
4313 # minus
4314 self.assertEqual(-Decimal("-10"), 10)
4315 # multiply
4316 self.assertEqual(Decimal("2") * 4, 8)
4317 # next_minus
4318 self.assertEqual(Decimal("10").next_minus(), 9)
4319 # next_plus
4320 self.assertEqual(Decimal("10").next_plus(), Decimal('2E+1'))
4321 # normalize
4322 self.assertEqual(Decimal("-10").normalize(), Decimal('-1E+1'))
4323 # number_class
4324 self.assertEqual(Decimal("10").number_class(), '+Normal')
4325 # plus
4326 self.assertEqual(+Decimal("-1"), -1)
4327 # remainder
4328 self.assertEqual(Decimal("10") % 7, 3)
4329 # subtract
4330 self.assertEqual(Decimal("10") - 7, 3)
4331 # to_integral_exact
4332 self.assertEqual(Decimal("1.12345").to_integral_exact(), 1)
4333
4334 # Boolean functions
4335 self.assertTrue(Decimal("1").is_canonical())
4336 self.assertTrue(Decimal("1").is_finite())
4337 self.assertTrue(Decimal("1").is_finite())
4338 self.assertTrue(Decimal("snan").is_snan())
4339 self.assertTrue(Decimal("-1").is_signed())
4340 self.assertTrue(Decimal("0").is_zero())
4341 self.assertTrue(Decimal("0").is_zero())
4342
4343 # Copy
4344 with localcontext() as c:
4345 c.prec = 10000
4346 x = 1228 ** 1523
4347 y = -Decimal(x)
4348
4349 z = y.copy_abs()
4350 self.assertEqual(z, x)
4351
4352 z = y.copy_negate()
4353 self.assertEqual(z, x)
4354
4355 z = y.copy_sign(Decimal(1))
4356 self.assertEqual(z, x)
4357
4358 def test_divmod(self):
4359 Decimal = self.decimal.Decimal
4360 localcontext = self.decimal.localcontext
4361 InvalidOperation = self.decimal.InvalidOperation
4362 DivisionByZero = self.decimal.DivisionByZero
4363
4364 with localcontext() as c:
4365 q, r = divmod(Decimal("10912837129"), 1001)
4366 self.assertEqual(q, Decimal('10901935'))
4367 self.assertEqual(r, Decimal('194'))
4368
4369 q, r = divmod(Decimal("NaN"), 7)
4370 self.assertTrue(q.is_nan() and r.is_nan())
4371
4372 c.traps[InvalidOperation] = False
4373 q, r = divmod(Decimal("NaN"), 7)
4374 self.assertTrue(q.is_nan() and r.is_nan())
4375
4376 c.traps[InvalidOperation] = False
4377 c.clear_flags()
4378 q, r = divmod(Decimal("inf"), Decimal("inf"))
4379 self.assertTrue(q.is_nan() and r.is_nan())
4380 self.assertTrue(c.flags[InvalidOperation])
4381
4382 c.clear_flags()
4383 q, r = divmod(Decimal("inf"), 101)
4384 self.assertTrue(q.is_infinite() and r.is_nan())
4385 self.assertTrue(c.flags[InvalidOperation])
4386
4387 c.clear_flags()
4388 q, r = divmod(Decimal(0), 0)
4389 self.assertTrue(q.is_nan() and r.is_nan())
4390 self.assertTrue(c.flags[InvalidOperation])
4391
4392 c.traps[DivisionByZero] = False
4393 c.clear_flags()
4394 q, r = divmod(Decimal(11), 0)
4395 self.assertTrue(q.is_infinite() and r.is_nan())
4396 self.assertTrue(c.flags[InvalidOperation] and
4397 c.flags[DivisionByZero])
4398
4399 def test_power(self):
4400 Decimal = self.decimal.Decimal
4401 localcontext = self.decimal.localcontext
4402 Overflow = self.decimal.Overflow
4403 Rounded = self.decimal.Rounded
4404
4405 with localcontext() as c:
4406 c.prec = 3
4407 c.clear_flags()
4408 self.assertEqual(Decimal("1.0") ** 100, Decimal('1.00'))
4409 self.assertTrue(c.flags[Rounded])
4410
4411 c.prec = 1
4412 c.Emax = 1
4413 c.Emin = -1
4414 c.clear_flags()
4415 c.traps[Overflow] = False
4416 self.assertEqual(Decimal(10000) ** Decimal("0.5"), Decimal('inf'))
4417 self.assertTrue(c.flags[Overflow])
4418
4419 def test_quantize(self):
4420 Decimal = self.decimal.Decimal
4421 localcontext = self.decimal.localcontext
4422 InvalidOperation = self.decimal.InvalidOperation
4423
4424 with localcontext() as c:
4425 c.prec = 1
4426 c.Emax = 1
4427 c.Emin = -1
4428 c.traps[InvalidOperation] = False
4429 x = Decimal(99).quantize(Decimal("1e1"))
4430 self.assertTrue(x.is_nan())
4431
4432 def test_radix(self):
4433 Decimal = self.decimal.Decimal
4434 getcontext = self.decimal.getcontext
4435
4436 c = getcontext()
4437 self.assertEqual(Decimal("1").radix(), 10)
4438 self.assertEqual(c.radix(), 10)
4439
4440 def test_rop(self):
4441 Decimal = self.decimal.Decimal
4442
4443 for attr in ('__radd__', '__rsub__', '__rmul__', '__rtruediv__',
4444 '__rdivmod__', '__rmod__', '__rfloordiv__', '__rpow__'):
4445 self.assertIs(getattr(Decimal("1"), attr)("xyz"), NotImplemented)
4446
4447 def test_round(self):
4448 # Python3 behavior: round() returns Decimal
4449 Decimal = self.decimal.Decimal
4450 getcontext = self.decimal.getcontext
4451
4452 c = getcontext()
4453 c.prec = 28
4454
4455 self.assertEqual(str(Decimal("9.99").__round__()), "10")
4456 self.assertEqual(str(Decimal("9.99e-5").__round__()), "0")
4457 self.assertEqual(str(Decimal("1.23456789").__round__(5)), "1.23457")
4458 self.assertEqual(str(Decimal("1.2345").__round__(10)), "1.2345000000")
4459 self.assertEqual(str(Decimal("1.2345").__round__(-10)), "0E+10")
4460
4461 self.assertRaises(TypeError, Decimal("1.23").__round__, "5")
4462 self.assertRaises(TypeError, Decimal("1.23").__round__, 5, 8)
4463
4464 def test_create_decimal(self):
4465 c = self.decimal.Context()
4466 self.assertRaises(ValueError, c.create_decimal, ["%"])
4467
4468 def test_int(self):
4469 Decimal = self.decimal.Decimal
4470 localcontext = self.decimal.localcontext
4471
4472 with localcontext() as c:
4473 c.prec = 9999
4474 x = Decimal(1221**1271) / 10**3923
4475 self.assertEqual(int(x), 1)
4476 self.assertEqual(x.to_integral(), 2)
4477
4478 def test_copy(self):
4479 Context = self.decimal.Context
4480
4481 c = Context()
4482 c.prec = 10000
4483 x = -(1172 ** 1712)
4484
4485 y = c.copy_abs(x)
4486 self.assertEqual(y, -x)
4487
4488 y = c.copy_negate(x)
4489 self.assertEqual(y, -x)
4490
4491 y = c.copy_sign(x, 1)
4492 self.assertEqual(y, -x)
4493
4494class CCoverage(Coverage):
4495 decimal = C
4496class PyCoverage(Coverage):
4497 decimal = P
4498
4499class PyFunctionality(unittest.TestCase):
4500 """Extra functionality in decimal.py"""
4501
Stefan Krah1919b7e2012-03-21 18:25:23 +01004502 def test_py_alternate_formatting(self):
4503 # triples giving a format, a Decimal, and the expected result
4504 Decimal = P.Decimal
4505 localcontext = P.localcontext
4506
4507 test_values = [
4508 # Issue 7094: Alternate formatting (specified by #)
4509 ('.0e', '1.0', '1e+0'),
4510 ('#.0e', '1.0', '1.e+0'),
4511 ('.0f', '1.0', '1'),
4512 ('#.0f', '1.0', '1.'),
4513 ('g', '1.1', '1.1'),
4514 ('#g', '1.1', '1.1'),
4515 ('.0g', '1', '1'),
4516 ('#.0g', '1', '1.'),
4517 ('.0%', '1.0', '100%'),
4518 ('#.0%', '1.0', '100.%'),
4519 ]
4520 for fmt, d, result in test_values:
4521 self.assertEqual(format(Decimal(d), fmt), result)
4522
4523class PyWhitebox(unittest.TestCase):
4524 """White box testing for decimal.py"""
4525
4526 def test_py_exact_power(self):
4527 # Rarely exercised lines in _power_exact.
4528 Decimal = P.Decimal
4529 localcontext = P.localcontext
4530
4531 with localcontext() as c:
4532 c.prec = 8
4533 x = Decimal(2**16) ** Decimal("-0.5")
4534 self.assertEqual(x, Decimal('0.00390625'))
4535
4536 x = Decimal(2**16) ** Decimal("-0.6")
4537 self.assertEqual(x, Decimal('0.0012885819'))
4538
4539 x = Decimal("256e7") ** Decimal("-0.5")
4540
4541 x = Decimal(152587890625) ** Decimal('-0.0625')
4542 self.assertEqual(x, Decimal("0.2"))
4543
4544 x = Decimal("152587890625e7") ** Decimal('-0.0625')
4545
4546 x = Decimal(5**2659) ** Decimal('-0.0625')
4547
4548 c.prec = 1
4549 x = Decimal("152587890625") ** Decimal('-0.5')
4550 c.prec = 201
4551 x = Decimal(2**578) ** Decimal("-0.5")
4552
4553 def test_py_immutability_operations(self):
Terry Jan Reedy0f847642013-03-11 18:34:00 -04004554 # Do operations and check that it didn't change internal objects.
Stefan Krah1919b7e2012-03-21 18:25:23 +01004555 Decimal = P.Decimal
4556 DefaultContext = P.DefaultContext
4557 setcontext = P.setcontext
4558
4559 c = DefaultContext.copy()
4560 c.traps = dict((s, 0) for s in OrderedSignals[P])
4561 setcontext(c)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004562
4563 d1 = Decimal('-25e55')
4564 b1 = Decimal('-25e55')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004565 d2 = Decimal('33e+33')
4566 b2 = Decimal('33e+33')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004567
4568 def checkSameDec(operation, useOther=False):
4569 if useOther:
4570 eval("d1." + operation + "(d2)")
4571 self.assertEqual(d1._sign, b1._sign)
4572 self.assertEqual(d1._int, b1._int)
4573 self.assertEqual(d1._exp, b1._exp)
4574 self.assertEqual(d2._sign, b2._sign)
4575 self.assertEqual(d2._int, b2._int)
4576 self.assertEqual(d2._exp, b2._exp)
4577 else:
4578 eval("d1." + operation + "()")
4579 self.assertEqual(d1._sign, b1._sign)
4580 self.assertEqual(d1._int, b1._int)
4581 self.assertEqual(d1._exp, b1._exp)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004582
4583 Decimal(d1)
4584 self.assertEqual(d1._sign, b1._sign)
4585 self.assertEqual(d1._int, b1._int)
4586 self.assertEqual(d1._exp, b1._exp)
4587
4588 checkSameDec("__abs__")
4589 checkSameDec("__add__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004590 checkSameDec("__divmod__", True)
Christian Heimes77c02eb2008-02-09 02:18:51 +00004591 checkSameDec("__eq__", True)
4592 checkSameDec("__ne__", True)
4593 checkSameDec("__le__", True)
4594 checkSameDec("__lt__", True)
4595 checkSameDec("__ge__", True)
4596 checkSameDec("__gt__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004597 checkSameDec("__float__")
4598 checkSameDec("__floordiv__", True)
4599 checkSameDec("__hash__")
4600 checkSameDec("__int__")
Christian Heimes969fe572008-01-25 11:23:10 +00004601 checkSameDec("__trunc__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004602 checkSameDec("__mod__", True)
4603 checkSameDec("__mul__", True)
4604 checkSameDec("__neg__")
Jack Diederich4dafcc42006-11-28 19:15:13 +00004605 checkSameDec("__bool__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004606 checkSameDec("__pos__")
4607 checkSameDec("__pow__", True)
4608 checkSameDec("__radd__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004609 checkSameDec("__rdivmod__", True)
4610 checkSameDec("__repr__")
4611 checkSameDec("__rfloordiv__", True)
4612 checkSameDec("__rmod__", True)
4613 checkSameDec("__rmul__", True)
4614 checkSameDec("__rpow__", True)
4615 checkSameDec("__rsub__", True)
4616 checkSameDec("__str__")
4617 checkSameDec("__sub__", True)
4618 checkSameDec("__truediv__", True)
4619 checkSameDec("adjusted")
4620 checkSameDec("as_tuple")
4621 checkSameDec("compare", True)
4622 checkSameDec("max", True)
4623 checkSameDec("min", True)
4624 checkSameDec("normalize")
4625 checkSameDec("quantize", True)
4626 checkSameDec("remainder_near", True)
4627 checkSameDec("same_quantum", True)
4628 checkSameDec("sqrt")
4629 checkSameDec("to_eng_string")
4630 checkSameDec("to_integral")
4631
Stefan Krah1919b7e2012-03-21 18:25:23 +01004632 def test_py_decimal_id(self):
4633 Decimal = P.Decimal
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004634
Stefan Krah1919b7e2012-03-21 18:25:23 +01004635 d = Decimal(45)
4636 e = Decimal(d)
4637 self.assertEqual(str(e), '45')
4638 self.assertNotEqual(id(d), id(e))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004639
Stefan Krah1919b7e2012-03-21 18:25:23 +01004640 def test_py_rescale(self):
4641 # Coverage
4642 Decimal = P.Decimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01004643 localcontext = P.localcontext
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004644
Stefan Krah1919b7e2012-03-21 18:25:23 +01004645 with localcontext() as c:
4646 x = Decimal("NaN")._rescale(3, ROUND_UP)
4647 self.assertTrue(x.is_nan())
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004648
Stefan Krah1919b7e2012-03-21 18:25:23 +01004649 def test_py__round(self):
4650 # Coverage
4651 Decimal = P.Decimal
Christian Heimes0348fb62008-03-26 12:55:56 +00004652
Stefan Krah1919b7e2012-03-21 18:25:23 +01004653 self.assertRaises(ValueError, Decimal("3.1234")._round, 0, ROUND_UP)
Mark Dickinsona2d1fe02009-10-29 12:23:02 +00004654
Stefan Krah1919b7e2012-03-21 18:25:23 +01004655class CFunctionality(unittest.TestCase):
4656 """Extra functionality in _decimal"""
Mark Dickinsona2d1fe02009-10-29 12:23:02 +00004657
Stefan Krah1919b7e2012-03-21 18:25:23 +01004658 @requires_extra_functionality
4659 def test_c_ieee_context(self):
4660 # issue 8786: Add support for IEEE 754 contexts to decimal module.
4661 IEEEContext = C.IEEEContext
4662 DECIMAL32 = C.DECIMAL32
4663 DECIMAL64 = C.DECIMAL64
4664 DECIMAL128 = C.DECIMAL128
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004665
Stefan Krah1919b7e2012-03-21 18:25:23 +01004666 def assert_rest(self, context):
4667 self.assertEqual(context.clamp, 1)
4668 assert_signals(self, context, 'traps', [])
4669 assert_signals(self, context, 'flags', [])
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004670
Stefan Krah1919b7e2012-03-21 18:25:23 +01004671 c = IEEEContext(DECIMAL32)
4672 self.assertEqual(c.prec, 7)
4673 self.assertEqual(c.Emax, 96)
4674 self.assertEqual(c.Emin, -95)
4675 assert_rest(self, c)
Raymond Hettinger82417ca2009-02-03 03:54:28 +00004676
Stefan Krah1919b7e2012-03-21 18:25:23 +01004677 c = IEEEContext(DECIMAL64)
4678 self.assertEqual(c.prec, 16)
4679 self.assertEqual(c.Emax, 384)
4680 self.assertEqual(c.Emin, -383)
4681 assert_rest(self, c)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004682
Stefan Krah1919b7e2012-03-21 18:25:23 +01004683 c = IEEEContext(DECIMAL128)
4684 self.assertEqual(c.prec, 34)
4685 self.assertEqual(c.Emax, 6144)
4686 self.assertEqual(c.Emin, -6143)
4687 assert_rest(self, c)
Raymond Hettinger5548be22004-07-05 18:49:38 +00004688
Stefan Krah1919b7e2012-03-21 18:25:23 +01004689 # Invalid values
4690 self.assertRaises(OverflowError, IEEEContext, 2**63)
4691 self.assertRaises(ValueError, IEEEContext, -1)
4692 self.assertRaises(ValueError, IEEEContext, 1024)
Mark Dickinson825fce32009-09-07 18:08:12 +00004693
Stefan Krah1919b7e2012-03-21 18:25:23 +01004694 @requires_extra_functionality
4695 def test_c_context(self):
4696 Context = C.Context
Christian Heimes969fe572008-01-25 11:23:10 +00004697
Stefan Krah1919b7e2012-03-21 18:25:23 +01004698 c = Context(flags=C.DecClamped, traps=C.DecRounded)
4699 self.assertEqual(c._flags, C.DecClamped)
4700 self.assertEqual(c._traps, C.DecRounded)
Raymond Hettinger771ed762009-01-03 19:20:32 +00004701
Stefan Krah1919b7e2012-03-21 18:25:23 +01004702 @requires_extra_functionality
4703 def test_constants(self):
4704 # Condition flags
4705 cond = (
4706 C.DecClamped, C.DecConversionSyntax, C.DecDivisionByZero,
4707 C.DecDivisionImpossible, C.DecDivisionUndefined,
4708 C.DecFpuError, C.DecInexact, C.DecInvalidContext,
4709 C.DecInvalidOperation, C.DecMallocError,
4710 C.DecFloatOperation, C.DecOverflow, C.DecRounded,
4711 C.DecSubnormal, C.DecUnderflow
Raymond Hettinger771ed762009-01-03 19:20:32 +00004712 )
Stefan Krah1919b7e2012-03-21 18:25:23 +01004713
4714 # IEEEContext
4715 self.assertEqual(C.DECIMAL32, 32)
4716 self.assertEqual(C.DECIMAL64, 64)
4717 self.assertEqual(C.DECIMAL128, 128)
4718 self.assertEqual(C.IEEE_CONTEXT_MAX_BITS, 512)
4719
Stefan Krah1919b7e2012-03-21 18:25:23 +01004720 # Conditions
4721 for i, v in enumerate(cond):
4722 self.assertEqual(v, 1<<i)
4723
4724 self.assertEqual(C.DecIEEEInvalidOperation,
4725 C.DecConversionSyntax|
4726 C.DecDivisionImpossible|
4727 C.DecDivisionUndefined|
4728 C.DecFpuError|
4729 C.DecInvalidContext|
4730 C.DecInvalidOperation|
4731 C.DecMallocError)
4732
4733 self.assertEqual(C.DecErrors,
4734 C.DecIEEEInvalidOperation|
4735 C.DecDivisionByZero)
4736
4737 self.assertEqual(C.DecTraps,
4738 C.DecErrors|C.DecOverflow|C.DecUnderflow)
4739
4740class CWhitebox(unittest.TestCase):
4741 """Whitebox testing for _decimal"""
4742
4743 def test_bignum(self):
4744 # Not exactly whitebox, but too slow with pydecimal.
4745
4746 Decimal = C.Decimal
4747 localcontext = C.localcontext
4748
4749 b1 = 10**35
4750 b2 = 10**36
4751 with localcontext() as c:
4752 c.prec = 1000000
4753 for i in range(5):
4754 a = random.randrange(b1, b2)
4755 b = random.randrange(1000, 1200)
4756 x = a ** b
4757 y = Decimal(a) ** Decimal(b)
4758 self.assertEqual(x, y)
4759
4760 def test_invalid_construction(self):
4761 self.assertRaises(TypeError, C.Decimal, 9, "xyz")
4762
4763 def test_c_input_restriction(self):
4764 # Too large for _decimal to be converted exactly
4765 Decimal = C.Decimal
4766 InvalidOperation = C.InvalidOperation
4767 Context = C.Context
4768 localcontext = C.localcontext
4769
4770 with localcontext(Context()):
4771 self.assertRaises(InvalidOperation, Decimal,
4772 "1e9999999999999999999")
4773
4774 def test_c_context_repr(self):
4775 # This test is _decimal-only because flags are not printed
4776 # in the same order.
4777 DefaultContext = C.DefaultContext
4778 FloatOperation = C.FloatOperation
Stefan Krah1919b7e2012-03-21 18:25:23 +01004779
4780 c = DefaultContext.copy()
4781
4782 c.prec = 425000000
4783 c.Emax = 425000000
4784 c.Emin = -425000000
4785 c.rounding = ROUND_HALF_DOWN
4786 c.capitals = 0
4787 c.clamp = 1
4788 for sig in OrderedSignals[C]:
4789 c.flags[sig] = True
4790 c.traps[sig] = True
4791 c.flags[FloatOperation] = True
4792 c.traps[FloatOperation] = True
4793
4794 s = c.__repr__()
4795 t = "Context(prec=425000000, rounding=ROUND_HALF_DOWN, " \
4796 "Emin=-425000000, Emax=425000000, capitals=0, clamp=1, " \
4797 "flags=[Clamped, InvalidOperation, DivisionByZero, Inexact, " \
4798 "FloatOperation, Overflow, Rounded, Subnormal, Underflow], " \
4799 "traps=[Clamped, InvalidOperation, DivisionByZero, Inexact, " \
4800 "FloatOperation, Overflow, Rounded, Subnormal, Underflow])"
4801 self.assertEqual(s, t)
4802
4803 def test_c_context_errors(self):
4804 Context = C.Context
4805 InvalidOperation = C.InvalidOperation
4806 Overflow = C.Overflow
4807 FloatOperation = C.FloatOperation
4808 localcontext = C.localcontext
4809 getcontext = C.getcontext
4810 setcontext = C.setcontext
4811 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
4812
4813 c = Context()
4814
4815 # SignalDict: input validation
4816 self.assertRaises(KeyError, c.flags.__setitem__, 801, 0)
4817 self.assertRaises(KeyError, c.traps.__setitem__, 801, 0)
4818 self.assertRaises(ValueError, c.flags.__delitem__, Overflow)
4819 self.assertRaises(ValueError, c.traps.__delitem__, InvalidOperation)
4820 self.assertRaises(TypeError, setattr, c, 'flags', ['x'])
4821 self.assertRaises(TypeError, setattr, c,'traps', ['y'])
4822 self.assertRaises(KeyError, setattr, c, 'flags', {0:1})
4823 self.assertRaises(KeyError, setattr, c, 'traps', {0:1})
4824
4825 # Test assignment from a signal dict with the correct length but
4826 # one invalid key.
4827 d = c.flags.copy()
4828 del d[FloatOperation]
4829 d["XYZ"] = 91283719
4830 self.assertRaises(KeyError, setattr, c, 'flags', d)
4831 self.assertRaises(KeyError, setattr, c, 'traps', d)
4832
4833 # Input corner cases
4834 int_max = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
4835 gt_max_emax = 10**18 if HAVE_CONFIG_64 else 10**9
4836
4837 # prec, Emax, Emin
4838 for attr in ['prec', 'Emax']:
4839 self.assertRaises(ValueError, setattr, c, attr, gt_max_emax)
4840 self.assertRaises(ValueError, setattr, c, 'Emin', -gt_max_emax)
4841
4842 # prec, Emax, Emin in context constructor
4843 self.assertRaises(ValueError, Context, prec=gt_max_emax)
4844 self.assertRaises(ValueError, Context, Emax=gt_max_emax)
4845 self.assertRaises(ValueError, Context, Emin=-gt_max_emax)
4846
4847 # Overflow in conversion
4848 self.assertRaises(OverflowError, Context, prec=int_max+1)
4849 self.assertRaises(OverflowError, Context, Emax=int_max+1)
4850 self.assertRaises(OverflowError, Context, Emin=-int_max-2)
Stefan Krah1919b7e2012-03-21 18:25:23 +01004851 self.assertRaises(OverflowError, Context, clamp=int_max+1)
4852 self.assertRaises(OverflowError, Context, capitals=int_max+1)
4853
4854 # OverflowError, general ValueError
4855 for attr in ('prec', 'Emin', 'Emax', 'capitals', 'clamp'):
4856 self.assertRaises(OverflowError, setattr, c, attr, int_max+1)
4857 self.assertRaises(OverflowError, setattr, c, attr, -int_max-2)
4858 if sys.platform != 'win32':
4859 self.assertRaises(ValueError, setattr, c, attr, int_max)
4860 self.assertRaises(ValueError, setattr, c, attr, -int_max-1)
4861
Stefan Krah1919b7e2012-03-21 18:25:23 +01004862 # OverflowError: _unsafe_setprec, _unsafe_setemin, _unsafe_setemax
4863 if C.MAX_PREC == 425000000:
4864 self.assertRaises(OverflowError, getattr(c, '_unsafe_setprec'),
4865 int_max+1)
4866 self.assertRaises(OverflowError, getattr(c, '_unsafe_setemax'),
4867 int_max+1)
4868 self.assertRaises(OverflowError, getattr(c, '_unsafe_setemin'),
4869 -int_max-2)
4870
4871 # ValueError: _unsafe_setprec, _unsafe_setemin, _unsafe_setemax
4872 if C.MAX_PREC == 425000000:
4873 self.assertRaises(ValueError, getattr(c, '_unsafe_setprec'), 0)
4874 self.assertRaises(ValueError, getattr(c, '_unsafe_setprec'),
4875 1070000001)
4876 self.assertRaises(ValueError, getattr(c, '_unsafe_setemax'), -1)
4877 self.assertRaises(ValueError, getattr(c, '_unsafe_setemax'),
4878 1070000001)
4879 self.assertRaises(ValueError, getattr(c, '_unsafe_setemin'),
4880 -1070000001)
4881 self.assertRaises(ValueError, getattr(c, '_unsafe_setemin'), 1)
4882
4883 # capitals, clamp
4884 for attr in ['capitals', 'clamp']:
4885 self.assertRaises(ValueError, setattr, c, attr, -1)
4886 self.assertRaises(ValueError, setattr, c, attr, 2)
4887 self.assertRaises(TypeError, setattr, c, attr, [1,2,3])
4888 if HAVE_CONFIG_64:
4889 self.assertRaises(ValueError, setattr, c, attr, 2**32)
4890 self.assertRaises(ValueError, setattr, c, attr, 2**32+1)
4891
4892 # Invalid local context
4893 self.assertRaises(TypeError, exec, 'with localcontext("xyz"): pass',
4894 locals())
Stefan Krah040e3112012-12-15 22:33:33 +01004895 self.assertRaises(TypeError, exec,
4896 'with localcontext(context=getcontext()): pass',
4897 locals())
Stefan Krah1919b7e2012-03-21 18:25:23 +01004898
4899 # setcontext
4900 saved_context = getcontext()
4901 self.assertRaises(TypeError, setcontext, "xyz")
4902 setcontext(saved_context)
4903
Stefan Krah59a4a932013-01-16 12:58:59 +01004904 def test_rounding_strings_interned(self):
4905
4906 self.assertIs(C.ROUND_UP, P.ROUND_UP)
4907 self.assertIs(C.ROUND_DOWN, P.ROUND_DOWN)
4908 self.assertIs(C.ROUND_CEILING, P.ROUND_CEILING)
4909 self.assertIs(C.ROUND_FLOOR, P.ROUND_FLOOR)
4910 self.assertIs(C.ROUND_HALF_UP, P.ROUND_HALF_UP)
4911 self.assertIs(C.ROUND_HALF_DOWN, P.ROUND_HALF_DOWN)
4912 self.assertIs(C.ROUND_HALF_EVEN, P.ROUND_HALF_EVEN)
4913 self.assertIs(C.ROUND_05UP, P.ROUND_05UP)
4914
Stefan Krah1919b7e2012-03-21 18:25:23 +01004915 @requires_extra_functionality
4916 def test_c_context_errors_extra(self):
4917 Context = C.Context
4918 InvalidOperation = C.InvalidOperation
4919 Overflow = C.Overflow
4920 localcontext = C.localcontext
4921 getcontext = C.getcontext
4922 setcontext = C.setcontext
4923 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
4924
4925 c = Context()
4926
4927 # Input corner cases
4928 int_max = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
4929
4930 # OverflowError, general ValueError
4931 self.assertRaises(OverflowError, setattr, c, '_allcr', int_max+1)
4932 self.assertRaises(OverflowError, setattr, c, '_allcr', -int_max-2)
4933 if sys.platform != 'win32':
4934 self.assertRaises(ValueError, setattr, c, '_allcr', int_max)
4935 self.assertRaises(ValueError, setattr, c, '_allcr', -int_max-1)
4936
4937 # OverflowError, general TypeError
4938 for attr in ('_flags', '_traps'):
4939 self.assertRaises(OverflowError, setattr, c, attr, int_max+1)
4940 self.assertRaises(OverflowError, setattr, c, attr, -int_max-2)
4941 if sys.platform != 'win32':
4942 self.assertRaises(TypeError, setattr, c, attr, int_max)
4943 self.assertRaises(TypeError, setattr, c, attr, -int_max-1)
4944
4945 # _allcr
4946 self.assertRaises(ValueError, setattr, c, '_allcr', -1)
4947 self.assertRaises(ValueError, setattr, c, '_allcr', 2)
4948 self.assertRaises(TypeError, setattr, c, '_allcr', [1,2,3])
4949 if HAVE_CONFIG_64:
4950 self.assertRaises(ValueError, setattr, c, '_allcr', 2**32)
4951 self.assertRaises(ValueError, setattr, c, '_allcr', 2**32+1)
4952
4953 # _flags, _traps
4954 for attr in ['_flags', '_traps']:
4955 self.assertRaises(TypeError, setattr, c, attr, 999999)
4956 self.assertRaises(TypeError, setattr, c, attr, 'x')
4957
4958 def test_c_valid_context(self):
4959 # These tests are for code coverage in _decimal.
4960 DefaultContext = C.DefaultContext
Stefan Krah1919b7e2012-03-21 18:25:23 +01004961 Clamped = C.Clamped
4962 Underflow = C.Underflow
4963 Inexact = C.Inexact
4964 Rounded = C.Rounded
4965 Subnormal = C.Subnormal
4966
4967 c = DefaultContext.copy()
4968
4969 # Exercise all getters and setters
4970 c.prec = 34
4971 c.rounding = ROUND_HALF_UP
4972 c.Emax = 3000
4973 c.Emin = -3000
4974 c.capitals = 1
4975 c.clamp = 0
4976
4977 self.assertEqual(c.prec, 34)
4978 self.assertEqual(c.rounding, ROUND_HALF_UP)
4979 self.assertEqual(c.Emin, -3000)
4980 self.assertEqual(c.Emax, 3000)
4981 self.assertEqual(c.capitals, 1)
4982 self.assertEqual(c.clamp, 0)
4983
4984 self.assertEqual(c.Etiny(), -3033)
4985 self.assertEqual(c.Etop(), 2967)
4986
4987 # Exercise all unsafe setters
4988 if C.MAX_PREC == 425000000:
4989 c._unsafe_setprec(999999999)
4990 c._unsafe_setemax(999999999)
4991 c._unsafe_setemin(-999999999)
4992 self.assertEqual(c.prec, 999999999)
4993 self.assertEqual(c.Emax, 999999999)
4994 self.assertEqual(c.Emin, -999999999)
4995
4996 @requires_extra_functionality
4997 def test_c_valid_context_extra(self):
4998 DefaultContext = C.DefaultContext
4999
5000 c = DefaultContext.copy()
5001 self.assertEqual(c._allcr, 1)
5002 c._allcr = 0
5003 self.assertEqual(c._allcr, 0)
5004
5005 def test_c_round(self):
5006 # Restricted input.
5007 Decimal = C.Decimal
5008 InvalidOperation = C.InvalidOperation
5009 localcontext = C.localcontext
5010 MAX_EMAX = C.MAX_EMAX
5011 MIN_ETINY = C.MIN_ETINY
5012 int_max = 2**63-1 if C.MAX_PREC > 425000000 else 2**31-1
5013
5014 with localcontext() as c:
5015 c.traps[InvalidOperation] = True
5016 self.assertRaises(InvalidOperation, Decimal("1.23").__round__,
5017 -int_max-1)
5018 self.assertRaises(InvalidOperation, Decimal("1.23").__round__,
5019 int_max)
5020 self.assertRaises(InvalidOperation, Decimal("1").__round__,
5021 int(MAX_EMAX+1))
5022 self.assertRaises(C.InvalidOperation, Decimal("1").__round__,
5023 -int(MIN_ETINY-1))
5024 self.assertRaises(OverflowError, Decimal("1.23").__round__,
5025 -int_max-2)
5026 self.assertRaises(OverflowError, Decimal("1.23").__round__,
5027 int_max+1)
5028
5029 def test_c_format(self):
5030 # Restricted input
5031 Decimal = C.Decimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01005032 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
5033
5034 self.assertRaises(TypeError, Decimal(1).__format__, "=10.10", [], 9)
5035 self.assertRaises(TypeError, Decimal(1).__format__, "=10.10", 9)
5036 self.assertRaises(TypeError, Decimal(1).__format__, [])
5037
Stefan Kraheb8c4512013-01-24 15:22:33 +01005038 self.assertRaises(ValueError, Decimal(1).__format__, "<>=10.10")
5039 maxsize = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
5040 self.assertRaises(ValueError, Decimal("1.23456789").__format__,
5041 "=%d.1" % maxsize)
Stefan Krah1919b7e2012-03-21 18:25:23 +01005042
5043 def test_c_integral(self):
5044 Decimal = C.Decimal
5045 Inexact = C.Inexact
Stefan Krah1919b7e2012-03-21 18:25:23 +01005046 localcontext = C.localcontext
5047
5048 x = Decimal(10)
5049 self.assertEqual(x.to_integral(), 10)
5050 self.assertRaises(TypeError, x.to_integral, '10')
5051 self.assertRaises(TypeError, x.to_integral, 10, 'x')
5052 self.assertRaises(TypeError, x.to_integral, 10)
5053
5054 self.assertEqual(x.to_integral_value(), 10)
5055 self.assertRaises(TypeError, x.to_integral_value, '10')
5056 self.assertRaises(TypeError, x.to_integral_value, 10, 'x')
5057 self.assertRaises(TypeError, x.to_integral_value, 10)
5058
5059 self.assertEqual(x.to_integral_exact(), 10)
5060 self.assertRaises(TypeError, x.to_integral_exact, '10')
5061 self.assertRaises(TypeError, x.to_integral_exact, 10, 'x')
5062 self.assertRaises(TypeError, x.to_integral_exact, 10)
5063
5064 with localcontext() as c:
5065 x = Decimal("99999999999999999999999999.9").to_integral_value(ROUND_UP)
5066 self.assertEqual(x, Decimal('100000000000000000000000000'))
5067
5068 x = Decimal("99999999999999999999999999.9").to_integral_exact(ROUND_UP)
5069 self.assertEqual(x, Decimal('100000000000000000000000000'))
5070
5071 c.traps[Inexact] = True
5072 self.assertRaises(Inexact, Decimal("999.9").to_integral_exact, ROUND_UP)
5073
5074 def test_c_funcs(self):
5075 # Invalid arguments
5076 Decimal = C.Decimal
5077 InvalidOperation = C.InvalidOperation
5078 DivisionByZero = C.DivisionByZero
Stefan Krah1919b7e2012-03-21 18:25:23 +01005079 getcontext = C.getcontext
5080 localcontext = C.localcontext
5081
5082 self.assertEqual(Decimal('9.99e10').to_eng_string(), '99.9E+9')
5083
5084 self.assertRaises(TypeError, pow, Decimal(1), 2, "3")
5085 self.assertRaises(TypeError, Decimal(9).number_class, "x", "y")
5086 self.assertRaises(TypeError, Decimal(9).same_quantum, 3, "x", "y")
5087
Raymond Hettinger771ed762009-01-03 19:20:32 +00005088 self.assertRaises(
Stefan Krah1919b7e2012-03-21 18:25:23 +01005089 TypeError,
5090 Decimal("1.23456789").quantize, Decimal('1e-100000'), []
Raymond Hettinger771ed762009-01-03 19:20:32 +00005091 )
Stefan Krah1919b7e2012-03-21 18:25:23 +01005092 self.assertRaises(
5093 TypeError,
5094 Decimal("1.23456789").quantize, Decimal('1e-100000'), getcontext()
5095 )
5096 self.assertRaises(
5097 TypeError,
5098 Decimal("1.23456789").quantize, Decimal('1e-100000'), 10
5099 )
5100 self.assertRaises(
5101 TypeError,
5102 Decimal("1.23456789").quantize, Decimal('1e-100000'), ROUND_UP, 1000
5103 )
Raymond Hettinger771ed762009-01-03 19:20:32 +00005104
Stefan Krah1919b7e2012-03-21 18:25:23 +01005105 with localcontext() as c:
5106 c.clear_traps()
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00005107
Stefan Krah1919b7e2012-03-21 18:25:23 +01005108 # Invalid arguments
5109 self.assertRaises(TypeError, c.copy_sign, Decimal(1), "x", "y")
5110 self.assertRaises(TypeError, c.canonical, 200)
5111 self.assertRaises(TypeError, c.is_canonical, 200)
5112 self.assertRaises(TypeError, c.divmod, 9, 8, "x", "y")
5113 self.assertRaises(TypeError, c.same_quantum, 9, 3, "x", "y")
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00005114
Stefan Krah1919b7e2012-03-21 18:25:23 +01005115 self.assertEqual(str(c.canonical(Decimal(200))), '200')
5116 self.assertEqual(c.radix(), 10)
Raymond Hettinger0aeac102004-07-05 22:53:03 +00005117
Stefan Krah1919b7e2012-03-21 18:25:23 +01005118 c.traps[DivisionByZero] = True
5119 self.assertRaises(DivisionByZero, Decimal(9).__divmod__, 0)
5120 self.assertRaises(DivisionByZero, c.divmod, 9, 0)
5121 self.assertTrue(c.flags[InvalidOperation])
Raymond Hettinger955d2b22004-08-08 20:17:45 +00005122
Stefan Krah1919b7e2012-03-21 18:25:23 +01005123 c.clear_flags()
5124 c.traps[InvalidOperation] = True
5125 self.assertRaises(InvalidOperation, Decimal(9).__divmod__, 0)
5126 self.assertRaises(InvalidOperation, c.divmod, 9, 0)
5127 self.assertTrue(c.flags[DivisionByZero])
Mark Dickinsonb1d8e322010-05-22 18:35:36 +00005128
Stefan Krah1919b7e2012-03-21 18:25:23 +01005129 c.traps[InvalidOperation] = True
5130 c.prec = 2
5131 self.assertRaises(InvalidOperation, pow, Decimal(1000), 1, 501)
Mark Dickinson84230a12010-02-18 14:49:50 +00005132
Stefan Krah040e3112012-12-15 22:33:33 +01005133 def test_va_args_exceptions(self):
5134 Decimal = C.Decimal
5135 Context = C.Context
5136
5137 x = Decimal("10001111111")
5138
5139 for attr in ['exp', 'is_normal', 'is_subnormal', 'ln', 'log10',
5140 'logb', 'logical_invert', 'next_minus', 'next_plus',
5141 'normalize', 'number_class', 'sqrt', 'to_eng_string']:
5142 func = getattr(x, attr)
5143 self.assertRaises(TypeError, func, context="x")
5144 self.assertRaises(TypeError, func, "x", context=None)
5145
5146 for attr in ['compare', 'compare_signal', 'logical_and',
5147 'logical_or', 'max', 'max_mag', 'min', 'min_mag',
5148 'remainder_near', 'rotate', 'scaleb', 'shift']:
5149 func = getattr(x, attr)
5150 self.assertRaises(TypeError, func, context="x")
5151 self.assertRaises(TypeError, func, "x", context=None)
5152
5153 self.assertRaises(TypeError, x.to_integral, rounding=None, context=[])
5154 self.assertRaises(TypeError, x.to_integral, rounding={}, context=[])
5155 self.assertRaises(TypeError, x.to_integral, [], [])
5156
5157 self.assertRaises(TypeError, x.to_integral_value, rounding=None, context=[])
5158 self.assertRaises(TypeError, x.to_integral_value, rounding={}, context=[])
5159 self.assertRaises(TypeError, x.to_integral_value, [], [])
5160
5161 self.assertRaises(TypeError, x.to_integral_exact, rounding=None, context=[])
5162 self.assertRaises(TypeError, x.to_integral_exact, rounding={}, context=[])
5163 self.assertRaises(TypeError, x.to_integral_exact, [], [])
5164
5165 self.assertRaises(TypeError, x.fma, 1, 2, context="x")
5166 self.assertRaises(TypeError, x.fma, 1, 2, "x", context=None)
5167
5168 self.assertRaises(TypeError, x.quantize, 1, [], context=None)
5169 self.assertRaises(TypeError, x.quantize, 1, [], rounding=None)
5170 self.assertRaises(TypeError, x.quantize, 1, [], [])
5171
5172 c = Context()
5173 self.assertRaises(TypeError, c.power, 1, 2, mod="x")
5174 self.assertRaises(TypeError, c.power, 1, "x", mod=None)
5175 self.assertRaises(TypeError, c.power, "x", 2, mod=None)
5176
Stefan Krah1919b7e2012-03-21 18:25:23 +01005177 @requires_extra_functionality
5178 def test_c_context_templates(self):
5179 self.assertEqual(
5180 C.BasicContext._traps,
5181 C.DecIEEEInvalidOperation|C.DecDivisionByZero|C.DecOverflow|
5182 C.DecUnderflow|C.DecClamped
5183 )
5184 self.assertEqual(
5185 C.DefaultContext._traps,
5186 C.DecIEEEInvalidOperation|C.DecDivisionByZero|C.DecOverflow
5187 )
Mark Dickinson84230a12010-02-18 14:49:50 +00005188
Stefan Krah1919b7e2012-03-21 18:25:23 +01005189 @requires_extra_functionality
5190 def test_c_signal_dict(self):
Mark Dickinson84230a12010-02-18 14:49:50 +00005191
Stefan Krah1919b7e2012-03-21 18:25:23 +01005192 # SignalDict coverage
5193 Context = C.Context
5194 DefaultContext = C.DefaultContext
Mark Dickinson84230a12010-02-18 14:49:50 +00005195
Stefan Krah1919b7e2012-03-21 18:25:23 +01005196 InvalidOperation = C.InvalidOperation
5197 DivisionByZero = C.DivisionByZero
5198 Overflow = C.Overflow
5199 Subnormal = C.Subnormal
5200 Underflow = C.Underflow
5201 Rounded = C.Rounded
5202 Inexact = C.Inexact
5203 Clamped = C.Clamped
Mark Dickinson84230a12010-02-18 14:49:50 +00005204
Stefan Krah1919b7e2012-03-21 18:25:23 +01005205 DecClamped = C.DecClamped
5206 DecInvalidOperation = C.DecInvalidOperation
5207 DecIEEEInvalidOperation = C.DecIEEEInvalidOperation
Mark Dickinson84230a12010-02-18 14:49:50 +00005208
Stefan Krah1919b7e2012-03-21 18:25:23 +01005209 def assertIsExclusivelySet(signal, signal_dict):
5210 for sig in signal_dict:
5211 if sig == signal:
5212 self.assertTrue(signal_dict[sig])
5213 else:
5214 self.assertFalse(signal_dict[sig])
Mark Dickinson84230a12010-02-18 14:49:50 +00005215
Stefan Krah1919b7e2012-03-21 18:25:23 +01005216 c = DefaultContext.copy()
Mark Dickinson84230a12010-02-18 14:49:50 +00005217
Stefan Krah1919b7e2012-03-21 18:25:23 +01005218 # Signal dict methods
5219 self.assertTrue(Overflow in c.traps)
5220 c.clear_traps()
5221 for k in c.traps.keys():
5222 c.traps[k] = True
5223 for v in c.traps.values():
5224 self.assertTrue(v)
5225 c.clear_traps()
5226 for k, v in c.traps.items():
5227 self.assertFalse(v)
Mark Dickinson84230a12010-02-18 14:49:50 +00005228
Stefan Krah1919b7e2012-03-21 18:25:23 +01005229 self.assertFalse(c.flags.get(Overflow))
5230 self.assertIs(c.flags.get("x"), None)
5231 self.assertEqual(c.flags.get("x", "y"), "y")
5232 self.assertRaises(TypeError, c.flags.get, "x", "y", "z")
Mark Dickinson84230a12010-02-18 14:49:50 +00005233
Stefan Krah1919b7e2012-03-21 18:25:23 +01005234 self.assertEqual(len(c.flags), len(c.traps))
5235 s = sys.getsizeof(c.flags)
5236 s = sys.getsizeof(c.traps)
5237 s = c.flags.__repr__()
Mark Dickinson84230a12010-02-18 14:49:50 +00005238
Stefan Krah1919b7e2012-03-21 18:25:23 +01005239 # Set flags/traps.
5240 c.clear_flags()
5241 c._flags = DecClamped
5242 self.assertTrue(c.flags[Clamped])
Mark Dickinson84230a12010-02-18 14:49:50 +00005243
Stefan Krah1919b7e2012-03-21 18:25:23 +01005244 c.clear_traps()
5245 c._traps = DecInvalidOperation
5246 self.assertTrue(c.traps[InvalidOperation])
Mark Dickinson84230a12010-02-18 14:49:50 +00005247
Stefan Krah1919b7e2012-03-21 18:25:23 +01005248 # Set flags/traps from dictionary.
5249 c.clear_flags()
5250 d = c.flags.copy()
5251 d[DivisionByZero] = True
5252 c.flags = d
5253 assertIsExclusivelySet(DivisionByZero, c.flags)
Mark Dickinson84230a12010-02-18 14:49:50 +00005254
Stefan Krah1919b7e2012-03-21 18:25:23 +01005255 c.clear_traps()
5256 d = c.traps.copy()
5257 d[Underflow] = True
5258 c.traps = d
5259 assertIsExclusivelySet(Underflow, c.traps)
Mark Dickinson84230a12010-02-18 14:49:50 +00005260
Stefan Krah1919b7e2012-03-21 18:25:23 +01005261 # Random constructors
5262 IntSignals = {
5263 Clamped: C.DecClamped,
5264 Rounded: C.DecRounded,
5265 Inexact: C.DecInexact,
5266 Subnormal: C.DecSubnormal,
5267 Underflow: C.DecUnderflow,
5268 Overflow: C.DecOverflow,
5269 DivisionByZero: C.DecDivisionByZero,
5270 InvalidOperation: C.DecIEEEInvalidOperation
5271 }
5272 IntCond = [
5273 C.DecDivisionImpossible, C.DecDivisionUndefined, C.DecFpuError,
5274 C.DecInvalidContext, C.DecInvalidOperation, C.DecMallocError,
5275 C.DecConversionSyntax,
5276 ]
Mark Dickinsonb455e582011-05-22 12:53:18 +01005277
Stefan Krah1919b7e2012-03-21 18:25:23 +01005278 lim = len(OrderedSignals[C])
5279 for r in range(lim):
5280 for t in range(lim):
Stefan Krah59a4a932013-01-16 12:58:59 +01005281 for round in RoundingModes:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005282 flags = random.sample(OrderedSignals[C], r)
5283 traps = random.sample(OrderedSignals[C], t)
5284 prec = random.randrange(1, 10000)
5285 emin = random.randrange(-10000, 0)
5286 emax = random.randrange(0, 10000)
5287 clamp = random.randrange(0, 2)
5288 caps = random.randrange(0, 2)
5289 cr = random.randrange(0, 2)
5290 c = Context(prec=prec, rounding=round, Emin=emin, Emax=emax,
5291 capitals=caps, clamp=clamp, flags=list(flags),
5292 traps=list(traps))
Mark Dickinson84230a12010-02-18 14:49:50 +00005293
Stefan Krah1919b7e2012-03-21 18:25:23 +01005294 self.assertEqual(c.prec, prec)
5295 self.assertEqual(c.rounding, round)
5296 self.assertEqual(c.Emin, emin)
5297 self.assertEqual(c.Emax, emax)
5298 self.assertEqual(c.capitals, caps)
5299 self.assertEqual(c.clamp, clamp)
Mark Dickinson84230a12010-02-18 14:49:50 +00005300
Stefan Krah1919b7e2012-03-21 18:25:23 +01005301 f = 0
5302 for x in flags:
5303 f |= IntSignals[x]
5304 self.assertEqual(c._flags, f)
Mark Dickinson84230a12010-02-18 14:49:50 +00005305
Stefan Krah1919b7e2012-03-21 18:25:23 +01005306 f = 0
5307 for x in traps:
5308 f |= IntSignals[x]
5309 self.assertEqual(c._traps, f)
Mark Dickinson84230a12010-02-18 14:49:50 +00005310
Stefan Krah1919b7e2012-03-21 18:25:23 +01005311 for cond in IntCond:
5312 c._flags = cond
5313 self.assertTrue(c._flags&DecIEEEInvalidOperation)
5314 assertIsExclusivelySet(InvalidOperation, c.flags)
Mark Dickinson84230a12010-02-18 14:49:50 +00005315
Stefan Krah1919b7e2012-03-21 18:25:23 +01005316 for cond in IntCond:
5317 c._traps = cond
5318 self.assertTrue(c._traps&DecIEEEInvalidOperation)
5319 assertIsExclusivelySet(InvalidOperation, c.traps)
Mark Dickinson84230a12010-02-18 14:49:50 +00005320
Stefan Krah1919b7e2012-03-21 18:25:23 +01005321 def test_invalid_override(self):
5322 Decimal = C.Decimal
Mark Dickinson84230a12010-02-18 14:49:50 +00005323
Stefan Krah1919b7e2012-03-21 18:25:23 +01005324 try:
5325 from locale import CHAR_MAX
5326 except ImportError:
Zachary Ware9fe6d862013-12-08 00:20:35 -06005327 self.skipTest('locale.CHAR_MAX not available')
Mark Dickinson84230a12010-02-18 14:49:50 +00005328
Stefan Krah1919b7e2012-03-21 18:25:23 +01005329 def make_grouping(lst):
5330 return ''.join([chr(x) for x in lst])
Mark Dickinson84230a12010-02-18 14:49:50 +00005331
Stefan Krah1919b7e2012-03-21 18:25:23 +01005332 def get_fmt(x, override=None, fmt='n'):
5333 return Decimal(x).__format__(fmt, override)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005334
Stefan Krah1919b7e2012-03-21 18:25:23 +01005335 invalid_grouping = {
5336 'decimal_point' : ',',
5337 'grouping' : make_grouping([255, 255, 0]),
5338 'thousands_sep' : ','
5339 }
5340 invalid_dot = {
5341 'decimal_point' : 'xxxxx',
5342 'grouping' : make_grouping([3, 3, 0]),
5343 'thousands_sep' : ','
5344 }
5345 invalid_sep = {
5346 'decimal_point' : '.',
5347 'grouping' : make_grouping([3, 3, 0]),
5348 'thousands_sep' : 'yyyyy'
5349 }
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005350
Stefan Krah1919b7e2012-03-21 18:25:23 +01005351 if CHAR_MAX == 127: # negative grouping in override
5352 self.assertRaises(ValueError, get_fmt, 12345,
5353 invalid_grouping, 'g')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005354
Stefan Krah1919b7e2012-03-21 18:25:23 +01005355 self.assertRaises(ValueError, get_fmt, 12345, invalid_dot, 'g')
5356 self.assertRaises(ValueError, get_fmt, 12345, invalid_sep, 'g')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005357
Stefan Krah0774e9b2012-04-05 15:21:58 +02005358 def test_exact_conversion(self):
5359 Decimal = C.Decimal
5360 localcontext = C.localcontext
5361 InvalidOperation = C.InvalidOperation
5362
5363 with localcontext() as c:
5364
5365 c.traps[InvalidOperation] = True
5366
5367 # Clamped
5368 x = "0e%d" % sys.maxsize
5369 self.assertRaises(InvalidOperation, Decimal, x)
5370
5371 x = "0e%d" % (-sys.maxsize-1)
5372 self.assertRaises(InvalidOperation, Decimal, x)
5373
5374 # Overflow
5375 x = "1e%d" % sys.maxsize
5376 self.assertRaises(InvalidOperation, Decimal, x)
5377
5378 # Underflow
5379 x = "1e%d" % (-sys.maxsize-1)
5380 self.assertRaises(InvalidOperation, Decimal, x)
5381
Stefan Krahff3eca02012-04-05 15:46:19 +02005382 def test_from_tuple(self):
5383 Decimal = C.Decimal
5384 localcontext = C.localcontext
5385 InvalidOperation = C.InvalidOperation
5386 Overflow = C.Overflow
5387 Underflow = C.Underflow
5388
5389 with localcontext() as c:
5390
5391 c.traps[InvalidOperation] = True
5392 c.traps[Overflow] = True
5393 c.traps[Underflow] = True
5394
5395 # SSIZE_MAX
5396 x = (1, (), sys.maxsize)
5397 self.assertEqual(str(c.create_decimal(x)), '-0E+999999')
5398 self.assertRaises(InvalidOperation, Decimal, x)
5399
5400 x = (1, (0, 1, 2), sys.maxsize)
5401 self.assertRaises(Overflow, c.create_decimal, x)
5402 self.assertRaises(InvalidOperation, Decimal, x)
5403
5404 # SSIZE_MIN
5405 x = (1, (), -sys.maxsize-1)
5406 self.assertEqual(str(c.create_decimal(x)), '-0E-1000026')
5407 self.assertRaises(InvalidOperation, Decimal, x)
5408
5409 x = (1, (0, 1, 2), -sys.maxsize-1)
5410 self.assertRaises(Underflow, c.create_decimal, x)
5411 self.assertRaises(InvalidOperation, Decimal, x)
5412
5413 # OverflowError
5414 x = (1, (), sys.maxsize+1)
5415 self.assertRaises(OverflowError, c.create_decimal, x)
5416 self.assertRaises(OverflowError, Decimal, x)
5417
5418 x = (1, (), -sys.maxsize-2)
5419 self.assertRaises(OverflowError, c.create_decimal, x)
5420 self.assertRaises(OverflowError, Decimal, x)
5421
5422 # Specials
5423 x = (1, (), "N")
5424 self.assertEqual(str(Decimal(x)), '-sNaN')
5425 x = (1, (0,), "N")
5426 self.assertEqual(str(Decimal(x)), '-sNaN')
5427 x = (1, (0, 1), "N")
5428 self.assertEqual(str(Decimal(x)), '-sNaN1')
5429
Stefan Krah891ca9e2013-05-29 19:14:17 +02005430 def test_sizeof(self):
5431 Decimal = C.Decimal
5432 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
5433
5434 self.assertGreater(Decimal(0).__sizeof__(), 0)
5435 if HAVE_CONFIG_64:
5436 x = Decimal(10**(19*24)).__sizeof__()
5437 y = Decimal(10**(19*25)).__sizeof__()
5438 self.assertEqual(y, x+8)
5439 else:
5440 x = Decimal(10**(9*24)).__sizeof__()
5441 y = Decimal(10**(9*25)).__sizeof__()
5442 self.assertEqual(y, x+4)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005443
Stefan Krah8c126f12016-07-17 14:01:42 +02005444 def test_internal_use_of_overridden_methods(self):
5445 Decimal = C.Decimal
5446
5447 # Unsound subtyping
5448 class X(float):
5449 def as_integer_ratio(self):
5450 return 1
5451 def __abs__(self):
5452 return self
5453
5454 class Y(float):
5455 def __abs__(self):
5456 return [1]*200
5457
5458 class I(int):
5459 def bit_length(self):
5460 return [1]*200
5461
5462 class Z(float):
5463 def as_integer_ratio(self):
5464 return (I(1), I(1))
5465 def __abs__(self):
5466 return self
5467
5468 for cls in X, Y, Z:
5469 self.assertEqual(Decimal.from_float(cls(101.1)),
5470 Decimal.from_float(101.1))
5471
Stefan Krah6b794b82014-05-01 17:42:33 +02005472@requires_docstrings
5473@unittest.skipUnless(C, "test requires C version")
Stefan Krah5de1f822014-05-01 15:53:42 +02005474class SignatureTest(unittest.TestCase):
5475 """Function signatures"""
5476
5477 def test_inspect_module(self):
5478 for attr in dir(P):
5479 if attr.startswith('_'):
5480 continue
5481 p_func = getattr(P, attr)
5482 c_func = getattr(C, attr)
5483 if (attr == 'Decimal' or attr == 'Context' or
5484 inspect.isfunction(p_func)):
5485 p_sig = inspect.signature(p_func)
5486 c_sig = inspect.signature(c_func)
5487
5488 # parameter names:
5489 c_names = list(c_sig.parameters.keys())
5490 p_names = [x for x in p_sig.parameters.keys() if not
5491 x.startswith('_')]
5492
5493 self.assertEqual(c_names, p_names,
5494 msg="parameter name mismatch in %s" % p_func)
5495
5496 c_kind = [x.kind for x in c_sig.parameters.values()]
5497 p_kind = [x[1].kind for x in p_sig.parameters.items() if not
5498 x[0].startswith('_')]
5499
5500 # parameters:
5501 if attr != 'setcontext':
5502 self.assertEqual(c_kind, p_kind,
5503 msg="parameter kind mismatch in %s" % p_func)
5504
5505 def test_inspect_types(self):
5506
5507 POS = inspect._ParameterKind.POSITIONAL_ONLY
5508 POS_KWD = inspect._ParameterKind.POSITIONAL_OR_KEYWORD
5509
5510 # Type heuristic (type annotations would help!):
5511 pdict = {C: {'other': C.Decimal(1),
5512 'third': C.Decimal(1),
5513 'x': C.Decimal(1),
5514 'y': C.Decimal(1),
5515 'z': C.Decimal(1),
5516 'a': C.Decimal(1),
5517 'b': C.Decimal(1),
5518 'c': C.Decimal(1),
5519 'exp': C.Decimal(1),
5520 'modulo': C.Decimal(1),
5521 'num': "1",
5522 'f': 1.0,
5523 'rounding': C.ROUND_HALF_UP,
5524 'context': C.getcontext()},
5525 P: {'other': P.Decimal(1),
5526 'third': P.Decimal(1),
5527 'a': P.Decimal(1),
5528 'b': P.Decimal(1),
5529 'c': P.Decimal(1),
5530 'exp': P.Decimal(1),
5531 'modulo': P.Decimal(1),
5532 'num': "1",
5533 'f': 1.0,
5534 'rounding': P.ROUND_HALF_UP,
5535 'context': P.getcontext()}}
5536
5537 def mkargs(module, sig):
5538 args = []
5539 kwargs = {}
5540 for name, param in sig.parameters.items():
5541 if name == 'self': continue
5542 if param.kind == POS:
5543 args.append(pdict[module][name])
5544 elif param.kind == POS_KWD:
5545 kwargs[name] = pdict[module][name]
5546 else:
5547 raise TestFailed("unexpected parameter kind")
5548 return args, kwargs
5549
5550 def tr(s):
5551 """The C Context docstrings use 'x' in order to prevent confusion
5552 with the article 'a' in the descriptions."""
5553 if s == 'x': return 'a'
5554 if s == 'y': return 'b'
5555 if s == 'z': return 'c'
5556 return s
5557
5558 def doit(ty):
5559 p_type = getattr(P, ty)
5560 c_type = getattr(C, ty)
5561 for attr in dir(p_type):
5562 if attr.startswith('_'):
5563 continue
5564 p_func = getattr(p_type, attr)
5565 c_func = getattr(c_type, attr)
5566 if inspect.isfunction(p_func):
5567 p_sig = inspect.signature(p_func)
5568 c_sig = inspect.signature(c_func)
5569
5570 # parameter names:
5571 p_names = list(p_sig.parameters.keys())
5572 c_names = [tr(x) for x in c_sig.parameters.keys()]
5573
5574 self.assertEqual(c_names, p_names,
5575 msg="parameter name mismatch in %s" % p_func)
5576
5577 p_kind = [x.kind for x in p_sig.parameters.values()]
5578 c_kind = [x.kind for x in c_sig.parameters.values()]
5579
5580 # 'self' parameter:
5581 self.assertIs(p_kind[0], POS_KWD)
5582 self.assertIs(c_kind[0], POS)
5583
5584 # remaining parameters:
5585 if ty == 'Decimal':
5586 self.assertEqual(c_kind[1:], p_kind[1:],
5587 msg="parameter kind mismatch in %s" % p_func)
5588 else: # Context methods are positional only in the C version.
5589 self.assertEqual(len(c_kind), len(p_kind),
5590 msg="parameter kind mismatch in %s" % p_func)
5591
5592 # Run the function:
5593 args, kwds = mkargs(C, c_sig)
5594 try:
5595 getattr(c_type(9), attr)(*args, **kwds)
5596 except Exception as err:
5597 raise TestFailed("invalid signature for %s: %s %s" % (c_func, args, kwds))
5598
5599 args, kwds = mkargs(P, p_sig)
5600 try:
5601 getattr(p_type(9), attr)(*args, **kwds)
5602 except Exception as err:
5603 raise TestFailed("invalid signature for %s: %s %s" % (p_func, args, kwds))
5604
5605 doit('Decimal')
5606 doit('Context')
5607
5608
Stefan Krah1919b7e2012-03-21 18:25:23 +01005609all_tests = [
5610 CExplicitConstructionTest, PyExplicitConstructionTest,
5611 CImplicitConstructionTest, PyImplicitConstructionTest,
5612 CFormatTest, PyFormatTest,
5613 CArithmeticOperatorsTest, PyArithmeticOperatorsTest,
5614 CThreadingTest, PyThreadingTest,
5615 CUsabilityTest, PyUsabilityTest,
5616 CPythonAPItests, PyPythonAPItests,
5617 CContextAPItests, PyContextAPItests,
5618 CContextWithStatement, PyContextWithStatement,
5619 CContextFlags, PyContextFlags,
5620 CSpecialContexts, PySpecialContexts,
5621 CContextInputValidation, PyContextInputValidation,
5622 CContextSubclassing, PyContextSubclassing,
5623 CCoverage, PyCoverage,
5624 CFunctionality, PyFunctionality,
5625 CWhitebox, PyWhitebox,
5626 CIBMTestCases, PyIBMTestCases,
5627]
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005628
Stefan Krah1919b7e2012-03-21 18:25:23 +01005629# Delete C tests if _decimal.so is not present.
5630if not C:
5631 all_tests = all_tests[1::2]
5632else:
5633 all_tests.insert(0, CheckAttributes)
Stefan Krah5de1f822014-05-01 15:53:42 +02005634 all_tests.insert(1, SignatureTest)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005635
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005636
Zachary Ware66f29282014-06-02 16:01:29 -05005637def test_main(arith=None, verbose=None, todo_tests=None, debug=None):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005638 """ Execute the tests.
5639
Raymond Hettingered20ad82004-09-04 20:09:13 +00005640 Runs all arithmetic tests if arith is True or if the "decimal" resource
5641 is enabled in regrtest.py
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005642 """
Raymond Hettingered20ad82004-09-04 20:09:13 +00005643
Stefan Krah1919b7e2012-03-21 18:25:23 +01005644 init(C)
5645 init(P)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005646 global TEST_ALL, DEBUG
Zachary Ware66f29282014-06-02 16:01:29 -05005647 TEST_ALL = arith if arith is not None else is_resource_enabled('decimal')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005648 DEBUG = debug
Raymond Hettingered20ad82004-09-04 20:09:13 +00005649
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005650 if todo_tests is None:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005651 test_classes = all_tests
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005652 else:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005653 test_classes = [CIBMTestCases, PyIBMTestCases]
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005654
5655 # Dynamically build custom test definition for each file in the test
5656 # directory and add the definitions to the DecimalTest class. This
5657 # procedure insures that new files do not get skipped.
5658 for filename in os.listdir(directory):
5659 if '.decTest' not in filename or filename.startswith("."):
5660 continue
5661 head, tail = filename.split('.')
5662 if todo_tests is not None and head not in todo_tests:
5663 continue
5664 tester = lambda self, f=filename: self.eval_file(directory + f)
Stefan Krah1919b7e2012-03-21 18:25:23 +01005665 setattr(CIBMTestCases, 'test_' + head, tester)
5666 setattr(PyIBMTestCases, 'test_' + head, tester)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005667 del filename, head, tail, tester
5668
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005669
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005670 try:
5671 run_unittest(*test_classes)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005672 if todo_tests is None:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005673 from doctest import IGNORE_EXCEPTION_DETAIL
5674 savedecimal = sys.modules['decimal']
5675 if C:
5676 sys.modules['decimal'] = C
5677 run_doctest(C, verbose, optionflags=IGNORE_EXCEPTION_DETAIL)
5678 sys.modules['decimal'] = P
5679 run_doctest(P, verbose)
5680 sys.modules['decimal'] = savedecimal
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005681 finally:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005682 if C: C.setcontext(ORIGINAL_CONTEXT[C])
5683 P.setcontext(ORIGINAL_CONTEXT[P])
5684 if not C:
5685 warnings.warn('C tests skipped: no module named _decimal.',
5686 UserWarning)
5687 if not orig_sys_decimal is sys.modules['decimal']:
5688 raise TestFailed("Internal error: unbalanced number of changes to "
5689 "sys.modules['decimal'].")
5690
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005691
5692if __name__ == '__main__':
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005693 import optparse
5694 p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]")
5695 p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test')
5696 p.add_option('--skip', '-s', action='store_true', help='skip over 90% of the arithmetic tests')
5697 (opt, args) = p.parse_args()
5698
5699 if opt.skip:
5700 test_main(arith=False, verbose=True)
5701 elif args:
5702 test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005703 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005704 test_main(arith=True, verbose=True)