blob: 59a17af278c05277303ac9cacea050f96d165b8a [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 Krah5de1f822014-05-01 15:53:42 +020040import inspect
Raymond Hettinger7e71fa52004-12-18 19:07:19 +000041try:
42 import threading
43except ImportError:
44 threading = None
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000045
Raymond Hettingerfed52962004-07-14 15:41:57 +000046
Stefan Krah1919b7e2012-03-21 18:25:23 +010047C = import_fresh_module('decimal', fresh=['_decimal'])
48P = import_fresh_module('decimal', blocked=['_decimal'])
49orig_sys_decimal = sys.modules['decimal']
50
51# fractions module must import the correct decimal module.
52cfractions = import_fresh_module('fractions', fresh=['fractions'])
53sys.modules['decimal'] = P
54pfractions = import_fresh_module('fractions', fresh=['fractions'])
55sys.modules['decimal'] = C
56fractions = {C:cfractions, P:pfractions}
57sys.modules['decimal'] = orig_sys_decimal
58
59
60# Useful Test Constant
61Signals = {
62 C: tuple(C.getcontext().flags.keys()) if C else None,
63 P: tuple(P.getcontext().flags.keys())
64}
Mark Dickinsonc69160e2010-05-04 14:35:33 +000065# Signals ordered with respect to precedence: when an operation
66# produces multiple signals, signals occurring later in the list
67# should be handled before those occurring earlier in the list.
Stefan Krah1919b7e2012-03-21 18:25:23 +010068OrderedSignals = {
69 C: [C.Clamped, C.Rounded, C.Inexact, C.Subnormal, C.Underflow,
70 C.Overflow, C.DivisionByZero, C.InvalidOperation,
71 C.FloatOperation] if C else None,
72 P: [P.Clamped, P.Rounded, P.Inexact, P.Subnormal, P.Underflow,
73 P.Overflow, P.DivisionByZero, P.InvalidOperation,
74 P.FloatOperation]
75}
76def assert_signals(cls, context, attr, expected):
77 d = getattr(context, attr)
78 cls.assertTrue(all(d[s] if s in expected else not d[s] for s in d))
79
Stefan Krah59a4a932013-01-16 12:58:59 +010080ROUND_UP = P.ROUND_UP
81ROUND_DOWN = P.ROUND_DOWN
82ROUND_CEILING = P.ROUND_CEILING
83ROUND_FLOOR = P.ROUND_FLOOR
84ROUND_HALF_UP = P.ROUND_HALF_UP
85ROUND_HALF_DOWN = P.ROUND_HALF_DOWN
86ROUND_HALF_EVEN = P.ROUND_HALF_EVEN
87ROUND_05UP = P.ROUND_05UP
88
89RoundingModes = [
90 ROUND_UP, ROUND_DOWN, ROUND_CEILING, ROUND_FLOOR,
91 ROUND_HALF_UP, ROUND_HALF_DOWN, ROUND_HALF_EVEN,
92 ROUND_05UP
93]
Mark Dickinsonc69160e2010-05-04 14:35:33 +000094
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000095# Tests are built around these assumed context defaults.
96# test_main() restores the original context.
Stefan Krah1919b7e2012-03-21 18:25:23 +010097ORIGINAL_CONTEXT = {
98 C: C.getcontext().copy() if C else None,
99 P: P.getcontext().copy()
100}
101def init(m):
102 if not m: return
103 DefaultTestContext = m.Context(
Stefan Krah59a4a932013-01-16 12:58:59 +0100104 prec=9, rounding=ROUND_HALF_EVEN, traps=dict.fromkeys(Signals[m], 0)
Stefan Krah1919b7e2012-03-21 18:25:23 +0100105 )
106 m.setcontext(DefaultTestContext)
Raymond Hettinger6ea48452004-07-03 12:26:21 +0000107
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000108TESTDATADIR = 'decimaltestdata'
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000109if __name__ == '__main__':
110 file = sys.argv[0]
111else:
112 file = __file__
113testdir = os.path.dirname(file) or os.curdir
Raymond Hettinger267b8682005-03-27 10:47:39 +0000114directory = testdir + os.sep + TESTDATADIR + os.sep
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000115
Raymond Hettinger267b8682005-03-27 10:47:39 +0000116skip_expected = not os.path.isdir(directory)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000117
118# Make sure it actually raises errors when not expected and caught in flags
119# Slower, since it runs some things several times.
120EXTENDEDERRORTEST = False
121
Stefan Krah1919b7e2012-03-21 18:25:23 +0100122# Test extra functionality in the C version (-DEXTRA_FUNCTIONALITY).
123EXTRA_FUNCTIONALITY = True if hasattr(C, 'DecClamped') else False
124requires_extra_functionality = unittest.skipUnless(
125 EXTRA_FUNCTIONALITY, "test requires build with -DEXTRA_FUNCTIONALITY")
126skip_if_extra_functionality = unittest.skipIf(
127 EXTRA_FUNCTIONALITY, "test requires regular build")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000128
129
Stefan Krah1919b7e2012-03-21 18:25:23 +0100130class IBMTestCases(unittest.TestCase):
131 """Class which tests the Decimal class against the IBM test cases."""
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000132
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000133 def setUp(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100134 self.context = self.decimal.Context()
135 self.readcontext = self.decimal.Context()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000136 self.ignore_list = ['#']
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000137
Stefan Krah1919b7e2012-03-21 18:25:23 +0100138 # List of individual .decTest test ids that correspond to tests that
139 # we're skipping for one reason or another.
140 self.skipped_test_ids = set([
141 # Skip implementation-specific scaleb tests.
142 'scbx164',
143 'scbx165',
144
145 # For some operations (currently exp, ln, log10, power), the decNumber
146 # reference implementation imposes additional restrictions on the context
147 # and operands. These restrictions are not part of the specification;
148 # however, the effect of these restrictions does show up in some of the
149 # testcases. We skip testcases that violate these restrictions, since
150 # Decimal behaves differently from decNumber for these testcases so these
151 # testcases would otherwise fail.
152 'expx901',
153 'expx902',
154 'expx903',
155 'expx905',
156 'lnx901',
157 'lnx902',
158 'lnx903',
159 'lnx905',
160 'logx901',
161 'logx902',
162 'logx903',
163 'logx905',
164 'powx1183',
165 'powx1184',
166 'powx4001',
167 'powx4002',
168 'powx4003',
169 'powx4005',
170 'powx4008',
171 'powx4010',
172 'powx4012',
173 'powx4014',
174 ])
175
176 if self.decimal == C:
177 # status has additional Subnormal, Underflow
178 self.skipped_test_ids.add('pwsx803')
179 self.skipped_test_ids.add('pwsx805')
180 # Correct rounding (skipped for decNumber, too)
181 self.skipped_test_ids.add('powx4302')
182 self.skipped_test_ids.add('powx4303')
183 self.skipped_test_ids.add('powx4342')
184 self.skipped_test_ids.add('powx4343')
185 # http://bugs.python.org/issue7049
186 self.skipped_test_ids.add('pwmx325')
187 self.skipped_test_ids.add('pwmx326')
188
189 # Map test directives to setter functions.
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000190 self.ChangeDict = {'precision' : self.change_precision,
Stefan Krah1919b7e2012-03-21 18:25:23 +0100191 'rounding' : self.change_rounding_method,
192 'maxexponent' : self.change_max_exponent,
193 'minexponent' : self.change_min_exponent,
194 'clamp' : self.change_clamp}
195
196 # Name adapter to be able to change the Decimal and Context
197 # interface without changing the test files from Cowlishaw.
198 self.NameAdapter = {'and':'logical_and',
199 'apply':'_apply',
200 'class':'number_class',
201 'comparesig':'compare_signal',
202 'comparetotal':'compare_total',
203 'comparetotmag':'compare_total_mag',
204 'copy':'copy_decimal',
205 'copyabs':'copy_abs',
206 'copynegate':'copy_negate',
207 'copysign':'copy_sign',
208 'divideint':'divide_int',
209 'invert':'logical_invert',
210 'iscanonical':'is_canonical',
211 'isfinite':'is_finite',
212 'isinfinite':'is_infinite',
213 'isnan':'is_nan',
214 'isnormal':'is_normal',
215 'isqnan':'is_qnan',
216 'issigned':'is_signed',
217 'issnan':'is_snan',
218 'issubnormal':'is_subnormal',
219 'iszero':'is_zero',
220 'maxmag':'max_mag',
221 'minmag':'min_mag',
222 'nextminus':'next_minus',
223 'nextplus':'next_plus',
224 'nexttoward':'next_toward',
225 'or':'logical_or',
226 'reduce':'normalize',
227 'remaindernear':'remainder_near',
228 'samequantum':'same_quantum',
229 'squareroot':'sqrt',
230 'toeng':'to_eng_string',
231 'tointegral':'to_integral_value',
232 'tointegralx':'to_integral_exact',
233 'tosci':'to_sci_string',
234 'xor':'logical_xor'}
235
236 # Map test-case names to roundings.
Stefan Krah59a4a932013-01-16 12:58:59 +0100237 self.RoundingDict = {'ceiling' : ROUND_CEILING,
238 'down' : ROUND_DOWN,
239 'floor' : ROUND_FLOOR,
240 'half_down' : ROUND_HALF_DOWN,
241 'half_even' : ROUND_HALF_EVEN,
242 'half_up' : ROUND_HALF_UP,
243 'up' : ROUND_UP,
244 '05up' : ROUND_05UP}
Stefan Krah1919b7e2012-03-21 18:25:23 +0100245
246 # Map the test cases' error names to the actual errors.
247 self.ErrorNames = {'clamped' : self.decimal.Clamped,
248 'conversion_syntax' : self.decimal.InvalidOperation,
249 'division_by_zero' : self.decimal.DivisionByZero,
250 'division_impossible' : self.decimal.InvalidOperation,
251 'division_undefined' : self.decimal.InvalidOperation,
252 'inexact' : self.decimal.Inexact,
253 'invalid_context' : self.decimal.InvalidOperation,
254 'invalid_operation' : self.decimal.InvalidOperation,
255 'overflow' : self.decimal.Overflow,
256 'rounded' : self.decimal.Rounded,
257 'subnormal' : self.decimal.Subnormal,
258 'underflow' : self.decimal.Underflow}
259
260 # The following functions return True/False rather than a
261 # Decimal instance.
262 self.LogicalFunctions = ('is_canonical',
263 'is_finite',
264 'is_infinite',
265 'is_nan',
266 'is_normal',
267 'is_qnan',
268 'is_signed',
269 'is_snan',
270 'is_subnormal',
271 'is_zero',
272 'same_quantum')
273
274 def read_unlimited(self, v, context):
275 """Work around the limitations of the 32-bit _decimal version. The
276 guaranteed maximum values for prec, Emax etc. are 425000000,
277 but higher values usually work, except for rare corner cases.
278 In particular, all of the IBM tests pass with maximum values
279 of 1070000000."""
280 if self.decimal == C and self.decimal.MAX_EMAX == 425000000:
281 self.readcontext._unsafe_setprec(1070000000)
282 self.readcontext._unsafe_setemax(1070000000)
283 self.readcontext._unsafe_setemin(-1070000000)
284 return self.readcontext.create_decimal(v)
285 else:
286 return self.decimal.Decimal(v, context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000287
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000288 def eval_file(self, file):
289 global skip_expected
290 if skip_expected:
Benjamin Petersone549ead2009-03-28 21:42:05 +0000291 raise unittest.SkipTest
Antoine Pitrou92f60ed2010-10-14 22:11:44 +0000292 with open(file) as f:
293 for line in f:
294 line = line.replace('\r\n', '').replace('\n', '')
295 #print line
296 try:
297 t = self.eval_line(line)
Stefan Krah1919b7e2012-03-21 18:25:23 +0100298 except self.decimal.DecimalException as exception:
Ezio Melotti13925002011-03-16 11:05:33 +0200299 #Exception raised where there shouldn't have been one.
Antoine Pitrou92f60ed2010-10-14 22:11:44 +0000300 self.fail('Exception "'+exception.__class__.__name__ + '" raised on line '+line)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000301
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000302
303 def eval_line(self, s):
304 if s.find(' -> ') >= 0 and s[:2] != '--' and not s.startswith(' --'):
305 s = (s.split('->')[0] + '->' +
306 s.split('->')[1].split('--')[0]).strip()
307 else:
308 s = s.split('--')[0].strip()
309
310 for ignore in self.ignore_list:
311 if s.find(ignore) >= 0:
312 #print s.split()[0], 'NotImplemented--', ignore
313 return
314 if not s:
315 return
316 elif ':' in s:
317 return self.eval_directive(s)
318 else:
319 return self.eval_equation(s)
320
321 def eval_directive(self, s):
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000322 funct, value = (x.strip().lower() for x in s.split(':'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000323 if funct == 'rounding':
Stefan Krah1919b7e2012-03-21 18:25:23 +0100324 value = self.RoundingDict[value]
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000325 else:
326 try:
327 value = int(value)
328 except ValueError:
329 pass
330
Stefan Krah1919b7e2012-03-21 18:25:23 +0100331 funct = self.ChangeDict.get(funct, (lambda *args: None))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000332 funct(value)
333
334 def eval_equation(self, s):
Raymond Hettingered20ad82004-09-04 20:09:13 +0000335
336 if not TEST_ALL and random.random() < 0.90:
337 return
338
Stefan Krah1919b7e2012-03-21 18:25:23 +0100339 self.context.clear_flags()
340
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000341 try:
342 Sides = s.split('->')
343 L = Sides[0].strip().split()
344 id = L[0]
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000345 if DEBUG:
346 print("Test ", id, end=" ")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000347 funct = L[1].lower()
348 valstemp = L[2:]
349 L = Sides[1].strip().split()
350 ans = L[0]
351 exceptions = L[1:]
352 except (TypeError, AttributeError, IndexError):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100353 raise self.decimal.InvalidOperation
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000354 def FixQuotes(val):
355 val = val.replace("''", 'SingleQuote').replace('""', 'DoubleQuote')
356 val = val.replace("'", '').replace('"', '')
357 val = val.replace('SingleQuote', "'").replace('DoubleQuote', '"')
358 return val
Mark Dickinson8a546532009-10-08 16:30:38 +0000359
Stefan Krah1919b7e2012-03-21 18:25:23 +0100360 if id in self.skipped_test_ids:
Mark Dickinson8a546532009-10-08 16:30:38 +0000361 return
362
Stefan Krah1919b7e2012-03-21 18:25:23 +0100363 fname = self.NameAdapter.get(funct, funct)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000364 if fname == 'rescale':
365 return
366 funct = getattr(self.context, fname)
367 vals = []
368 conglomerate = ''
369 quote = 0
Stefan Krah1919b7e2012-03-21 18:25:23 +0100370 theirexceptions = [self.ErrorNames[x.lower()] for x in exceptions]
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000371
Stefan Krah1919b7e2012-03-21 18:25:23 +0100372 for exception in Signals[self.decimal]:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000373 self.context.traps[exception] = 1 #Catch these bugs...
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000374 for exception in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000375 self.context.traps[exception] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000376 for i, val in enumerate(valstemp):
377 if val.count("'") % 2 == 1:
378 quote = 1 - quote
379 if quote:
380 conglomerate = conglomerate + ' ' + val
381 continue
382 else:
383 val = conglomerate + val
384 conglomerate = ''
385 v = FixQuotes(val)
386 if fname in ('to_sci_string', 'to_eng_string'):
387 if EXTENDEDERRORTEST:
388 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000389 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000390 try:
391 funct(self.context.create_decimal(v))
392 except error:
393 pass
Stefan Krah1919b7e2012-03-21 18:25:23 +0100394 except Signals[self.decimal] as e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000395 self.fail("Raised %s in %s when %s disabled" % \
396 (e, s, error))
397 else:
398 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000399 self.context.traps[error] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000400 v = self.context.create_decimal(v)
401 else:
Stefan Krah1919b7e2012-03-21 18:25:23 +0100402 v = self.read_unlimited(v, self.context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000403 vals.append(v)
404
405 ans = FixQuotes(ans)
406
407 if EXTENDEDERRORTEST and fname not in ('to_sci_string', 'to_eng_string'):
408 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000409 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000410 try:
411 funct(*vals)
412 except error:
413 pass
Stefan Krah1919b7e2012-03-21 18:25:23 +0100414 except Signals[self.decimal] as e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000415 self.fail("Raised %s in %s when %s disabled" % \
416 (e, s, error))
417 else:
418 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000419 self.context.traps[error] = 0
Mark Dickinsonc69160e2010-05-04 14:35:33 +0000420
421 # as above, but add traps cumulatively, to check precedence
Stefan Krah1919b7e2012-03-21 18:25:23 +0100422 ordered_errors = [e for e in OrderedSignals[self.decimal] if e in theirexceptions]
Mark Dickinsonc69160e2010-05-04 14:35:33 +0000423 for error in ordered_errors:
424 self.context.traps[error] = 1
425 try:
426 funct(*vals)
427 except error:
428 pass
Stefan Krah1919b7e2012-03-21 18:25:23 +0100429 except Signals[self.decimal] as e:
Mark Dickinsonc69160e2010-05-04 14:35:33 +0000430 self.fail("Raised %s in %s; expected %s" %
431 (type(e), s, error))
432 else:
433 self.fail("Did not raise %s in %s" % (error, s))
434 # reset traps
435 for error in ordered_errors:
436 self.context.traps[error] = 0
437
438
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000439 if DEBUG:
440 print("--", self.context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000441 try:
442 result = str(funct(*vals))
Stefan Krah1919b7e2012-03-21 18:25:23 +0100443 if fname in self.LogicalFunctions:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000444 result = str(int(eval(result))) # 'True', 'False' -> '1', '0'
Stefan Krah1919b7e2012-03-21 18:25:23 +0100445 except Signals[self.decimal] as error:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000446 self.fail("Raised %s in %s" % (error, s))
447 except: #Catch any error long enough to state the test case.
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000448 print("ERROR:", s)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000449 raise
450
451 myexceptions = self.getexceptions()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000452
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000453 myexceptions.sort(key=repr)
454 theirexceptions.sort(key=repr)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000455
456 self.assertEqual(result, ans,
457 'Incorrect answer for ' + s + ' -- got ' + result)
Stefan Krah1919b7e2012-03-21 18:25:23 +0100458
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000459 self.assertEqual(myexceptions, theirexceptions,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000460 'Incorrect flags set in ' + s + ' -- got ' + str(myexceptions))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000461
462 def getexceptions(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100463 return [e for e in Signals[self.decimal] if self.context.flags[e]]
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000464
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000465 def change_precision(self, prec):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100466 if self.decimal == C and self.decimal.MAX_PREC == 425000000:
467 self.context._unsafe_setprec(prec)
468 else:
469 self.context.prec = prec
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000470 def change_rounding_method(self, rounding):
471 self.context.rounding = rounding
472 def change_min_exponent(self, exp):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100473 if self.decimal == C and self.decimal.MAX_PREC == 425000000:
474 self.context._unsafe_setemin(exp)
475 else:
476 self.context.Emin = exp
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000477 def change_max_exponent(self, exp):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100478 if self.decimal == C and self.decimal.MAX_PREC == 425000000:
479 self.context._unsafe_setemax(exp)
480 else:
481 self.context.Emax = exp
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000482 def change_clamp(self, clamp):
Mark Dickinsonb1d8e322010-05-22 18:35:36 +0000483 self.context.clamp = clamp
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000484
Stefan Krah1919b7e2012-03-21 18:25:23 +0100485class CIBMTestCases(IBMTestCases):
486 decimal = C
487class PyIBMTestCases(IBMTestCases):
488 decimal = P
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000489
490# The following classes test the behaviour of Decimal according to PEP 327
491
Stefan Krah1919b7e2012-03-21 18:25:23 +0100492class ExplicitConstructionTest(unittest.TestCase):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000493 '''Unit tests for Explicit Construction cases of Decimal.'''
494
495 def test_explicit_empty(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100496 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000497 self.assertEqual(Decimal(), Decimal("0"))
498
499 def test_explicit_from_None(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100500 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000501 self.assertRaises(TypeError, Decimal, None)
502
503 def test_explicit_from_int(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100504 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000505
506 #positive
507 d = Decimal(45)
508 self.assertEqual(str(d), '45')
509
510 #very large positive
511 d = Decimal(500000123)
512 self.assertEqual(str(d), '500000123')
513
514 #negative
515 d = Decimal(-45)
516 self.assertEqual(str(d), '-45')
517
518 #zero
519 d = Decimal(0)
520 self.assertEqual(str(d), '0')
521
Stefan Krah1919b7e2012-03-21 18:25:23 +0100522 # single word longs
523 for n in range(0, 32):
524 for sign in (-1, 1):
525 for x in range(-5, 5):
526 i = sign * (2**n + x)
527 d = Decimal(i)
528 self.assertEqual(str(d), str(i))
529
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000530 def test_explicit_from_string(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100531 Decimal = self.decimal.Decimal
532 InvalidOperation = self.decimal.InvalidOperation
533 localcontext = self.decimal.localcontext
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000534
535 #empty
536 self.assertEqual(str(Decimal('')), 'NaN')
537
538 #int
539 self.assertEqual(str(Decimal('45')), '45')
540
541 #float
542 self.assertEqual(str(Decimal('45.34')), '45.34')
543
544 #engineer notation
545 self.assertEqual(str(Decimal('45e2')), '4.5E+3')
546
547 #just not a number
548 self.assertEqual(str(Decimal('ugly')), 'NaN')
549
Christian Heimesa62da1d2008-01-12 19:39:10 +0000550 #leading and trailing whitespace permitted
551 self.assertEqual(str(Decimal('1.3E4 \n')), '1.3E+4')
552 self.assertEqual(str(Decimal(' -7.89')), '-7.89')
Stefan Krah1919b7e2012-03-21 18:25:23 +0100553 self.assertEqual(str(Decimal(" 3.45679 ")), '3.45679')
554
Brett Cannona721aba2016-09-09 14:57:09 -0700555 # underscores
556 self.assertEqual(str(Decimal('1_3.3e4_0')), '1.33E+41')
557 self.assertEqual(str(Decimal('1_0_0_0')), '1000')
558
Stefan Krah1919b7e2012-03-21 18:25:23 +0100559 # unicode whitespace
560 for lead in ["", ' ', '\u00a0', '\u205f']:
561 for trail in ["", ' ', '\u00a0', '\u205f']:
562 self.assertEqual(str(Decimal(lead + '9.311E+28' + trail)),
563 '9.311E+28')
564
565 with localcontext() as c:
566 c.traps[InvalidOperation] = True
567 # Invalid string
568 self.assertRaises(InvalidOperation, Decimal, "xyz")
569 # Two arguments max
570 self.assertRaises(TypeError, Decimal, "1234", "x", "y")
571
572 # space within the numeric part
573 self.assertRaises(InvalidOperation, Decimal, "1\u00a02\u00a03")
574 self.assertRaises(InvalidOperation, Decimal, "\u00a01\u00a02\u00a0")
575
576 # unicode whitespace
577 self.assertRaises(InvalidOperation, Decimal, "\u00a0")
578 self.assertRaises(InvalidOperation, Decimal, "\u00a0\u00a0")
579
580 # embedded NUL
581 self.assertRaises(InvalidOperation, Decimal, "12\u00003")
582
Brett Cannona721aba2016-09-09 14:57:09 -0700583 # underscores don't prevent errors
584 self.assertRaises(InvalidOperation, Decimal, "1_2_\u00003")
585
Stefan Krah6e467042012-11-10 23:09:04 +0100586 @cpython_only
587 def test_from_legacy_strings(self):
588 import _testcapi
589 Decimal = self.decimal.Decimal
590 context = self.decimal.Context()
591
592 s = _testcapi.unicode_legacy_string('9.999999')
593 self.assertEqual(str(Decimal(s)), '9.999999')
594 self.assertEqual(str(context.create_decimal(s)), '9.999999')
Christian Heimesa62da1d2008-01-12 19:39:10 +0000595
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000596 def test_explicit_from_tuples(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100597 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000598
599 #zero
600 d = Decimal( (0, (0,), 0) )
601 self.assertEqual(str(d), '0')
602
603 #int
604 d = Decimal( (1, (4, 5), 0) )
605 self.assertEqual(str(d), '-45')
606
607 #float
608 d = Decimal( (0, (4, 5, 3, 4), -2) )
609 self.assertEqual(str(d), '45.34')
610
611 #weird
612 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
613 self.assertEqual(str(d), '-4.34913534E-17')
614
Stefan Krah1919b7e2012-03-21 18:25:23 +0100615 #inf
616 d = Decimal( (0, (), "F") )
617 self.assertEqual(str(d), 'Infinity')
618
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000619 #wrong number of items
620 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1)) )
621
622 #bad sign
623 self.assertRaises(ValueError, Decimal, (8, (4, 3, 4, 9, 1), 2) )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000624 self.assertRaises(ValueError, Decimal, (0., (4, 3, 4, 9, 1), 2) )
625 self.assertRaises(ValueError, Decimal, (Decimal(1), (4, 3, 4, 9, 1), 2))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000626
627 #bad exp
628 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 'wrong!') )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000629 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 0.) )
630 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), '1') )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000631
632 #bad coefficients
Stefan Krah1919b7e2012-03-21 18:25:23 +0100633 self.assertRaises(ValueError, Decimal, (1, "xyz", 2) )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000634 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, None, 1), 2) )
635 self.assertRaises(ValueError, Decimal, (1, (4, -3, 4, 9, 1), 2) )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000636 self.assertRaises(ValueError, Decimal, (1, (4, 10, 4, 9, 1), 2) )
Guido van Rossum0d3fb8a2007-11-26 23:23:18 +0000637 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 'a', 1), 2) )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000638
Stefan Krah1919b7e2012-03-21 18:25:23 +0100639 def test_explicit_from_list(self):
640 Decimal = self.decimal.Decimal
641
642 d = Decimal([0, [0], 0])
643 self.assertEqual(str(d), '0')
644
645 d = Decimal([1, [4, 3, 4, 9, 1, 3, 5, 3, 4], -25])
646 self.assertEqual(str(d), '-4.34913534E-17')
647
648 d = Decimal([1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25])
649 self.assertEqual(str(d), '-4.34913534E-17')
650
651 d = Decimal((1, [4, 3, 4, 9, 1, 3, 5, 3, 4], -25))
652 self.assertEqual(str(d), '-4.34913534E-17')
653
Antoine Pitrou503ab332010-03-30 18:56:19 +0000654 def test_explicit_from_bool(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100655 Decimal = self.decimal.Decimal
656
Antoine Pitrou503ab332010-03-30 18:56:19 +0000657 self.assertIs(bool(Decimal(0)), False)
658 self.assertIs(bool(Decimal(1)), True)
659 self.assertEqual(Decimal(False), Decimal(0))
660 self.assertEqual(Decimal(True), Decimal(1))
661
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000662 def test_explicit_from_Decimal(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100663 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000664
665 #positive
666 d = Decimal(45)
667 e = Decimal(d)
668 self.assertEqual(str(e), '45')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000669
670 #very large positive
671 d = Decimal(500000123)
672 e = Decimal(d)
673 self.assertEqual(str(e), '500000123')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000674
675 #negative
676 d = Decimal(-45)
677 e = Decimal(d)
678 self.assertEqual(str(e), '-45')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000679
680 #zero
681 d = Decimal(0)
682 e = Decimal(d)
683 self.assertEqual(str(e), '0')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000684
Raymond Hettinger96798592010-04-02 16:58:27 +0000685 @requires_IEEE_754
686 def test_explicit_from_float(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100687
688 Decimal = self.decimal.Decimal
689
Raymond Hettinger96798592010-04-02 16:58:27 +0000690 r = Decimal(0.1)
691 self.assertEqual(type(r), Decimal)
692 self.assertEqual(str(r),
693 '0.1000000000000000055511151231257827021181583404541015625')
694 self.assertTrue(Decimal(float('nan')).is_qnan())
695 self.assertTrue(Decimal(float('inf')).is_infinite())
696 self.assertTrue(Decimal(float('-inf')).is_infinite())
697 self.assertEqual(str(Decimal(float('nan'))),
698 str(Decimal('NaN')))
699 self.assertEqual(str(Decimal(float('inf'))),
700 str(Decimal('Infinity')))
701 self.assertEqual(str(Decimal(float('-inf'))),
702 str(Decimal('-Infinity')))
703 self.assertEqual(str(Decimal(float('-0.0'))),
704 str(Decimal('-0')))
705 for i in range(200):
706 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
707 self.assertEqual(x, float(Decimal(x))) # roundtrip
708
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000709 def test_explicit_context_create_decimal(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100710 Decimal = self.decimal.Decimal
711 InvalidOperation = self.decimal.InvalidOperation
712 Rounded = self.decimal.Rounded
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000713
Stefan Krah1919b7e2012-03-21 18:25:23 +0100714 nc = copy.copy(self.decimal.getcontext())
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000715 nc.prec = 3
716
717 # empty
Raymond Hettingerfed52962004-07-14 15:41:57 +0000718 d = Decimal()
719 self.assertEqual(str(d), '0')
720 d = nc.create_decimal()
721 self.assertEqual(str(d), '0')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000722
723 # from None
724 self.assertRaises(TypeError, nc.create_decimal, None)
725
726 # from int
727 d = nc.create_decimal(456)
Ezio Melottie9615932010-01-24 19:26:24 +0000728 self.assertIsInstance(d, Decimal)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000729 self.assertEqual(nc.create_decimal(45678),
730 nc.create_decimal('457E+2'))
731
732 # from string
733 d = Decimal('456789')
734 self.assertEqual(str(d), '456789')
735 d = nc.create_decimal('456789')
736 self.assertEqual(str(d), '4.57E+5')
Christian Heimesa62da1d2008-01-12 19:39:10 +0000737 # leading and trailing whitespace should result in a NaN;
738 # spaces are already checked in Cowlishaw's test-suite, so
739 # here we just check that a trailing newline results in a NaN
740 self.assertEqual(str(nc.create_decimal('3.14\n')), 'NaN')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000741
742 # from tuples
743 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
744 self.assertEqual(str(d), '-4.34913534E-17')
745 d = nc.create_decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
746 self.assertEqual(str(d), '-4.35E-17')
747
748 # from Decimal
749 prevdec = Decimal(500000123)
750 d = Decimal(prevdec)
751 self.assertEqual(str(d), '500000123')
752 d = nc.create_decimal(prevdec)
753 self.assertEqual(str(d), '5.00E+8')
754
Stefan Krah1919b7e2012-03-21 18:25:23 +0100755 # more integers
756 nc.prec = 28
757 nc.traps[InvalidOperation] = True
758
759 for v in [-2**63-1, -2**63, -2**31-1, -2**31, 0,
760 2**31-1, 2**31, 2**63-1, 2**63]:
761 d = nc.create_decimal(v)
762 self.assertTrue(isinstance(d, Decimal))
763 self.assertEqual(int(d), v)
764
765 nc.prec = 3
766 nc.traps[Rounded] = True
767 self.assertRaises(Rounded, nc.create_decimal, 1234)
768
769 # from string
770 nc.prec = 28
771 self.assertEqual(str(nc.create_decimal('0E-017')), '0E-17')
772 self.assertEqual(str(nc.create_decimal('45')), '45')
773 self.assertEqual(str(nc.create_decimal('-Inf')), '-Infinity')
774 self.assertEqual(str(nc.create_decimal('NaN123')), 'NaN123')
775
776 # invalid arguments
777 self.assertRaises(InvalidOperation, nc.create_decimal, "xyz")
778 self.assertRaises(ValueError, nc.create_decimal, (1, "xyz", -25))
779 self.assertRaises(TypeError, nc.create_decimal, "1234", "5678")
Brett Cannona721aba2016-09-09 14:57:09 -0700780 # no whitespace and underscore stripping is done with this method
781 self.assertRaises(InvalidOperation, nc.create_decimal, " 1234")
782 self.assertRaises(InvalidOperation, nc.create_decimal, "12_34")
Stefan Krah1919b7e2012-03-21 18:25:23 +0100783
784 # too many NaN payload digits
785 nc.prec = 3
786 self.assertRaises(InvalidOperation, nc.create_decimal, 'NaN12345')
787 self.assertRaises(InvalidOperation, nc.create_decimal,
788 Decimal('NaN12345'))
789
790 nc.traps[InvalidOperation] = False
791 self.assertEqual(str(nc.create_decimal('NaN12345')), 'NaN')
792 self.assertTrue(nc.flags[InvalidOperation])
793
794 nc.flags[InvalidOperation] = False
795 self.assertEqual(str(nc.create_decimal(Decimal('NaN12345'))), 'NaN')
796 self.assertTrue(nc.flags[InvalidOperation])
797
798 def test_explicit_context_create_from_float(self):
799
800 Decimal = self.decimal.Decimal
801
802 nc = self.decimal.Context()
803 r = nc.create_decimal(0.1)
804 self.assertEqual(type(r), Decimal)
805 self.assertEqual(str(r), '0.1000000000000000055511151231')
806 self.assertTrue(nc.create_decimal(float('nan')).is_qnan())
807 self.assertTrue(nc.create_decimal(float('inf')).is_infinite())
808 self.assertTrue(nc.create_decimal(float('-inf')).is_infinite())
809 self.assertEqual(str(nc.create_decimal(float('nan'))),
810 str(nc.create_decimal('NaN')))
811 self.assertEqual(str(nc.create_decimal(float('inf'))),
812 str(nc.create_decimal('Infinity')))
813 self.assertEqual(str(nc.create_decimal(float('-inf'))),
814 str(nc.create_decimal('-Infinity')))
815 self.assertEqual(str(nc.create_decimal(float('-0.0'))),
816 str(nc.create_decimal('-0')))
817 nc.prec = 100
818 for i in range(200):
819 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
820 self.assertEqual(x, float(nc.create_decimal(x))) # roundtrip
821
Mark Dickinson345adc42009-08-02 10:14:23 +0000822 def test_unicode_digits(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100823 Decimal = self.decimal.Decimal
824
Mark Dickinson345adc42009-08-02 10:14:23 +0000825 test_values = {
826 '\uff11': '1',
827 '\u0660.\u0660\u0663\u0667\u0662e-\u0663' : '0.0000372',
828 '-nan\u0c68\u0c6a\u0c66\u0c66' : '-NaN2400',
829 }
830 for input, expected in test_values.items():
831 self.assertEqual(str(Decimal(input)), expected)
832
Stefan Krah1919b7e2012-03-21 18:25:23 +0100833class CExplicitConstructionTest(ExplicitConstructionTest):
834 decimal = C
835class PyExplicitConstructionTest(ExplicitConstructionTest):
836 decimal = P
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000837
Stefan Krah1919b7e2012-03-21 18:25:23 +0100838class ImplicitConstructionTest(unittest.TestCase):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000839 '''Unit tests for Implicit Construction cases of Decimal.'''
840
841 def test_implicit_from_None(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100842 Decimal = self.decimal.Decimal
843 self.assertRaises(TypeError, eval, 'Decimal(5) + None', locals())
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000844
845 def test_implicit_from_int(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100846 Decimal = self.decimal.Decimal
847
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000848 #normal
849 self.assertEqual(str(Decimal(5) + 45), '50')
850 #exceeding precision
851 self.assertEqual(Decimal(5) + 123456789000, Decimal(123456789000))
852
853 def test_implicit_from_string(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100854 Decimal = self.decimal.Decimal
855 self.assertRaises(TypeError, eval, 'Decimal(5) + "3"', locals())
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000856
857 def test_implicit_from_float(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100858 Decimal = self.decimal.Decimal
859 self.assertRaises(TypeError, eval, 'Decimal(5) + 2.2', locals())
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000860
861 def test_implicit_from_Decimal(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100862 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000863 self.assertEqual(Decimal(5) + Decimal(45), Decimal(50))
864
Raymond Hettinger267b8682005-03-27 10:47:39 +0000865 def test_rop(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100866 Decimal = self.decimal.Decimal
867
Raymond Hettinger267b8682005-03-27 10:47:39 +0000868 # Allow other classes to be trained to interact with Decimals
869 class E:
870 def __divmod__(self, other):
871 return 'divmod ' + str(other)
872 def __rdivmod__(self, other):
873 return str(other) + ' rdivmod'
874 def __lt__(self, other):
875 return 'lt ' + str(other)
876 def __gt__(self, other):
877 return 'gt ' + str(other)
878 def __le__(self, other):
879 return 'le ' + str(other)
880 def __ge__(self, other):
881 return 'ge ' + str(other)
882 def __eq__(self, other):
883 return 'eq ' + str(other)
884 def __ne__(self, other):
885 return 'ne ' + str(other)
886
887 self.assertEqual(divmod(E(), Decimal(10)), 'divmod 10')
888 self.assertEqual(divmod(Decimal(10), E()), '10 rdivmod')
889 self.assertEqual(eval('Decimal(10) < E()'), 'gt 10')
890 self.assertEqual(eval('Decimal(10) > E()'), 'lt 10')
891 self.assertEqual(eval('Decimal(10) <= E()'), 'ge 10')
892 self.assertEqual(eval('Decimal(10) >= E()'), 'le 10')
893 self.assertEqual(eval('Decimal(10) == E()'), 'eq 10')
894 self.assertEqual(eval('Decimal(10) != E()'), 'ne 10')
895
896 # insert operator methods and then exercise them
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000897 oplist = [
898 ('+', '__add__', '__radd__'),
899 ('-', '__sub__', '__rsub__'),
900 ('*', '__mul__', '__rmul__'),
Thomas Woutersdcc6d322006-04-21 11:30:52 +0000901 ('/', '__truediv__', '__rtruediv__'),
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000902 ('%', '__mod__', '__rmod__'),
903 ('//', '__floordiv__', '__rfloordiv__'),
904 ('**', '__pow__', '__rpow__')
905 ]
Raymond Hettinger267b8682005-03-27 10:47:39 +0000906
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000907 for sym, lop, rop in oplist:
Raymond Hettinger267b8682005-03-27 10:47:39 +0000908 setattr(E, lop, lambda self, other: 'str' + lop + str(other))
909 setattr(E, rop, lambda self, other: str(other) + rop + 'str')
910 self.assertEqual(eval('E()' + sym + 'Decimal(10)'),
911 'str' + lop + '10')
912 self.assertEqual(eval('Decimal(10)' + sym + 'E()'),
913 '10' + rop + 'str')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000914
Stefan Krah1919b7e2012-03-21 18:25:23 +0100915class CImplicitConstructionTest(ImplicitConstructionTest):
916 decimal = C
917class PyImplicitConstructionTest(ImplicitConstructionTest):
918 decimal = P
Mark Dickinson79f52032009-03-17 23:12:51 +0000919
Stefan Krah1919b7e2012-03-21 18:25:23 +0100920class FormatTest(unittest.TestCase):
Christian Heimesf16baeb2008-02-29 14:57:44 +0000921 '''Unit tests for the format function.'''
922 def test_formatting(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100923 Decimal = self.decimal.Decimal
924
Christian Heimesf16baeb2008-02-29 14:57:44 +0000925 # triples giving a format, a Decimal, and the expected result
926 test_values = [
927 ('e', '0E-15', '0e-15'),
928 ('e', '2.3E-15', '2.3e-15'),
929 ('e', '2.30E+2', '2.30e+2'), # preserve significant zeros
930 ('e', '2.30000E-15', '2.30000e-15'),
931 ('e', '1.23456789123456789e40', '1.23456789123456789e+40'),
932 ('e', '1.5', '1.5e+0'),
933 ('e', '0.15', '1.5e-1'),
934 ('e', '0.015', '1.5e-2'),
935 ('e', '0.0000000000015', '1.5e-12'),
936 ('e', '15.0', '1.50e+1'),
937 ('e', '-15', '-1.5e+1'),
938 ('e', '0', '0e+0'),
939 ('e', '0E1', '0e+1'),
940 ('e', '0.0', '0e-1'),
941 ('e', '0.00', '0e-2'),
942 ('.6e', '0E-15', '0.000000e-9'),
943 ('.6e', '0', '0.000000e+6'),
944 ('.6e', '9.999999', '9.999999e+0'),
945 ('.6e', '9.9999999', '1.000000e+1'),
946 ('.6e', '-1.23e5', '-1.230000e+5'),
947 ('.6e', '1.23456789e-3', '1.234568e-3'),
948 ('f', '0', '0'),
949 ('f', '0.0', '0.0'),
950 ('f', '0E-2', '0.00'),
951 ('f', '0.00E-8', '0.0000000000'),
952 ('f', '0E1', '0'), # loses exponent information
953 ('f', '3.2E1', '32'),
954 ('f', '3.2E2', '320'),
955 ('f', '3.20E2', '320'),
956 ('f', '3.200E2', '320.0'),
957 ('f', '3.2E-6', '0.0000032'),
958 ('.6f', '0E-15', '0.000000'), # all zeros treated equally
959 ('.6f', '0E1', '0.000000'),
960 ('.6f', '0', '0.000000'),
961 ('.0f', '0', '0'), # no decimal point
962 ('.0f', '0e-2', '0'),
963 ('.0f', '3.14159265', '3'),
964 ('.1f', '3.14159265', '3.1'),
965 ('.4f', '3.14159265', '3.1416'),
966 ('.6f', '3.14159265', '3.141593'),
967 ('.7f', '3.14159265', '3.1415926'), # round-half-even!
968 ('.8f', '3.14159265', '3.14159265'),
969 ('.9f', '3.14159265', '3.141592650'),
970
971 ('g', '0', '0'),
972 ('g', '0.0', '0.0'),
973 ('g', '0E1', '0e+1'),
974 ('G', '0E1', '0E+1'),
975 ('g', '0E-5', '0.00000'),
976 ('g', '0E-6', '0.000000'),
977 ('g', '0E-7', '0e-7'),
978 ('g', '-0E2', '-0e+2'),
979 ('.0g', '3.14159265', '3'), # 0 sig fig -> 1 sig fig
Stefan Krah1919b7e2012-03-21 18:25:23 +0100980 ('.0n', '3.14159265', '3'), # same for 'n'
Christian Heimesf16baeb2008-02-29 14:57:44 +0000981 ('.1g', '3.14159265', '3'),
982 ('.2g', '3.14159265', '3.1'),
983 ('.5g', '3.14159265', '3.1416'),
984 ('.7g', '3.14159265', '3.141593'),
985 ('.8g', '3.14159265', '3.1415926'), # round-half-even!
986 ('.9g', '3.14159265', '3.14159265'),
987 ('.10g', '3.14159265', '3.14159265'), # don't pad
988
989 ('%', '0E1', '0%'),
990 ('%', '0E0', '0%'),
991 ('%', '0E-1', '0%'),
992 ('%', '0E-2', '0%'),
993 ('%', '0E-3', '0.0%'),
994 ('%', '0E-4', '0.00%'),
995
996 ('.3%', '0', '0.000%'), # all zeros treated equally
997 ('.3%', '0E10', '0.000%'),
998 ('.3%', '0E-10', '0.000%'),
999 ('.3%', '2.34', '234.000%'),
1000 ('.3%', '1.234567', '123.457%'),
1001 ('.0%', '1.23', '123%'),
1002
1003 ('e', 'NaN', 'NaN'),
1004 ('f', '-NaN123', '-NaN123'),
1005 ('+g', 'NaN456', '+NaN456'),
1006 ('.3e', 'Inf', 'Infinity'),
1007 ('.16f', '-Inf', '-Infinity'),
1008 ('.0g', '-sNaN', '-sNaN'),
1009
1010 ('', '1.00', '1.00'),
Mark Dickinsonad416342009-03-17 18:10:15 +00001011
Mark Dickinson79f52032009-03-17 23:12:51 +00001012 # test alignment and padding
Mark Dickinson46ab5d02009-09-08 20:22:46 +00001013 ('6', '123', ' 123'),
Mark Dickinsonad416342009-03-17 18:10:15 +00001014 ('<6', '123', '123 '),
1015 ('>6', '123', ' 123'),
1016 ('^6', '123', ' 123 '),
1017 ('=+6', '123', '+ 123'),
Mark Dickinson79f52032009-03-17 23:12:51 +00001018 ('#<10', 'NaN', 'NaN#######'),
1019 ('#<10', '-4.3', '-4.3######'),
1020 ('#<+10', '0.0130', '+0.0130###'),
1021 ('#< 10', '0.0130', ' 0.0130###'),
1022 ('@>10', '-Inf', '@-Infinity'),
1023 ('#>5', '-Inf', '-Infinity'),
1024 ('?^5', '123', '?123?'),
1025 ('%^6', '123', '%123%%'),
1026 (' ^6', '-45.6', '-45.6 '),
1027 ('/=10', '-45.6', '-/////45.6'),
1028 ('/=+10', '45.6', '+/////45.6'),
1029 ('/= 10', '45.6', ' /////45.6'),
Stefan Krah6edda142013-05-29 15:45:38 +02001030 ('\x00=10', '-inf', '-\x00Infinity'),
1031 ('\x00^16', '-inf', '\x00\x00\x00-Infinity\x00\x00\x00\x00'),
1032 ('\x00>10', '1.2345', '\x00\x00\x00\x001.2345'),
1033 ('\x00<10', '1.2345', '1.2345\x00\x00\x00\x00'),
Mark Dickinson79f52032009-03-17 23:12:51 +00001034
1035 # thousands separator
1036 (',', '1234567', '1,234,567'),
1037 (',', '123456', '123,456'),
1038 (',', '12345', '12,345'),
1039 (',', '1234', '1,234'),
1040 (',', '123', '123'),
1041 (',', '12', '12'),
1042 (',', '1', '1'),
1043 (',', '0', '0'),
1044 (',', '-1234567', '-1,234,567'),
1045 (',', '-123456', '-123,456'),
1046 ('7,', '123456', '123,456'),
Mark Dickinson46ab5d02009-09-08 20:22:46 +00001047 ('8,', '123456', ' 123,456'),
Mark Dickinson79f52032009-03-17 23:12:51 +00001048 ('08,', '123456', '0,123,456'), # special case: extra 0 needed
1049 ('+08,', '123456', '+123,456'), # but not if there's a sign
1050 (' 08,', '123456', ' 123,456'),
1051 ('08,', '-123456', '-123,456'),
1052 ('+09,', '123456', '+0,123,456'),
1053 # ... with fractional part...
1054 ('07,', '1234.56', '1,234.56'),
1055 ('08,', '1234.56', '1,234.56'),
1056 ('09,', '1234.56', '01,234.56'),
1057 ('010,', '1234.56', '001,234.56'),
1058 ('011,', '1234.56', '0,001,234.56'),
1059 ('012,', '1234.56', '0,001,234.56'),
1060 ('08,.1f', '1234.5', '01,234.5'),
1061 # no thousands separators in fraction part
1062 (',', '1.23456789', '1.23456789'),
1063 (',%', '123.456789', '12,345.6789%'),
1064 (',e', '123456', '1.23456e+5'),
1065 (',E', '123456', '1.23456E+5'),
Mark Dickinson7718d2b2009-09-07 16:21:56 +00001066
1067 # issue 6850
1068 ('a=-7.0', '0.12345', 'aaaa0.1'),
Stefan Krah298131a2014-08-26 20:46:49 +02001069
1070 # issue 22090
1071 ('<^+15.20%', 'inf', '<<+Infinity%<<<'),
1072 ('\x07>,%', 'sNaN1234567', 'sNaN1234567%'),
1073 ('=10.10%', 'NaN123', ' NaN123%'),
Christian Heimesf16baeb2008-02-29 14:57:44 +00001074 ]
1075 for fmt, d, result in test_values:
1076 self.assertEqual(format(Decimal(d), fmt), result)
1077
Stefan Krah1919b7e2012-03-21 18:25:23 +01001078 # bytes format argument
1079 self.assertRaises(TypeError, Decimal(1).__format__, b'-020')
1080
Mark Dickinson79f52032009-03-17 23:12:51 +00001081 def test_n_format(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001082 Decimal = self.decimal.Decimal
1083
Mark Dickinson79f52032009-03-17 23:12:51 +00001084 try:
1085 from locale import CHAR_MAX
1086 except ImportError:
Zachary Ware9fe6d862013-12-08 00:20:35 -06001087 self.skipTest('locale.CHAR_MAX not available')
Mark Dickinson79f52032009-03-17 23:12:51 +00001088
Stefan Krah1919b7e2012-03-21 18:25:23 +01001089 def make_grouping(lst):
1090 return ''.join([chr(x) for x in lst]) if self.decimal == C else lst
1091
1092 def get_fmt(x, override=None, fmt='n'):
1093 if self.decimal == C:
1094 return Decimal(x).__format__(fmt, override)
1095 else:
1096 return Decimal(x).__format__(fmt, _localeconv=override)
1097
Mark Dickinson79f52032009-03-17 23:12:51 +00001098 # Set up some localeconv-like dictionaries
1099 en_US = {
1100 'decimal_point' : '.',
Stefan Krah1919b7e2012-03-21 18:25:23 +01001101 'grouping' : make_grouping([3, 3, 0]),
1102 'thousands_sep' : ','
Mark Dickinson79f52032009-03-17 23:12:51 +00001103 }
1104
1105 fr_FR = {
1106 'decimal_point' : ',',
Stefan Krah1919b7e2012-03-21 18:25:23 +01001107 'grouping' : make_grouping([CHAR_MAX]),
Mark Dickinson79f52032009-03-17 23:12:51 +00001108 'thousands_sep' : ''
1109 }
1110
1111 ru_RU = {
1112 'decimal_point' : ',',
Stefan Krah1919b7e2012-03-21 18:25:23 +01001113 'grouping': make_grouping([3, 3, 0]),
Mark Dickinson79f52032009-03-17 23:12:51 +00001114 'thousands_sep' : ' '
1115 }
1116
1117 crazy = {
1118 'decimal_point' : '&',
Stefan Krah1919b7e2012-03-21 18:25:23 +01001119 'grouping': make_grouping([1, 4, 2, CHAR_MAX]),
Mark Dickinson79f52032009-03-17 23:12:51 +00001120 'thousands_sep' : '-'
1121 }
1122
Stefan Krah1919b7e2012-03-21 18:25:23 +01001123 dotsep_wide = {
1124 'decimal_point' : b'\xc2\xbf'.decode('utf-8'),
1125 'grouping': make_grouping([3, 3, 0]),
1126 'thousands_sep' : b'\xc2\xb4'.decode('utf-8')
1127 }
Mark Dickinson79f52032009-03-17 23:12:51 +00001128
1129 self.assertEqual(get_fmt(Decimal('12.7'), en_US), '12.7')
1130 self.assertEqual(get_fmt(Decimal('12.7'), fr_FR), '12,7')
1131 self.assertEqual(get_fmt(Decimal('12.7'), ru_RU), '12,7')
1132 self.assertEqual(get_fmt(Decimal('12.7'), crazy), '1-2&7')
1133
1134 self.assertEqual(get_fmt(123456789, en_US), '123,456,789')
1135 self.assertEqual(get_fmt(123456789, fr_FR), '123456789')
1136 self.assertEqual(get_fmt(123456789, ru_RU), '123 456 789')
1137 self.assertEqual(get_fmt(1234567890123, crazy), '123456-78-9012-3')
1138
1139 self.assertEqual(get_fmt(123456789, en_US, '.6n'), '1.23457e+8')
1140 self.assertEqual(get_fmt(123456789, fr_FR, '.6n'), '1,23457e+8')
1141 self.assertEqual(get_fmt(123456789, ru_RU, '.6n'), '1,23457e+8')
1142 self.assertEqual(get_fmt(123456789, crazy, '.6n'), '1&23457e+8')
1143
Mark Dickinson7303b592009-03-18 08:25:36 +00001144 # zero padding
1145 self.assertEqual(get_fmt(1234, fr_FR, '03n'), '1234')
1146 self.assertEqual(get_fmt(1234, fr_FR, '04n'), '1234')
1147 self.assertEqual(get_fmt(1234, fr_FR, '05n'), '01234')
1148 self.assertEqual(get_fmt(1234, fr_FR, '06n'), '001234')
1149
1150 self.assertEqual(get_fmt(12345, en_US, '05n'), '12,345')
1151 self.assertEqual(get_fmt(12345, en_US, '06n'), '12,345')
1152 self.assertEqual(get_fmt(12345, en_US, '07n'), '012,345')
1153 self.assertEqual(get_fmt(12345, en_US, '08n'), '0,012,345')
1154 self.assertEqual(get_fmt(12345, en_US, '09n'), '0,012,345')
1155 self.assertEqual(get_fmt(12345, en_US, '010n'), '00,012,345')
1156
1157 self.assertEqual(get_fmt(123456, crazy, '06n'), '1-2345-6')
1158 self.assertEqual(get_fmt(123456, crazy, '07n'), '1-2345-6')
1159 self.assertEqual(get_fmt(123456, crazy, '08n'), '1-2345-6')
1160 self.assertEqual(get_fmt(123456, crazy, '09n'), '01-2345-6')
1161 self.assertEqual(get_fmt(123456, crazy, '010n'), '0-01-2345-6')
1162 self.assertEqual(get_fmt(123456, crazy, '011n'), '0-01-2345-6')
1163 self.assertEqual(get_fmt(123456, crazy, '012n'), '00-01-2345-6')
1164 self.assertEqual(get_fmt(123456, crazy, '013n'), '000-01-2345-6')
1165
Stefan Krah1919b7e2012-03-21 18:25:23 +01001166 # wide char separator and decimal point
1167 self.assertEqual(get_fmt(Decimal('-1.5'), dotsep_wide, '020n'),
1168 '-0\u00b4000\u00b4000\u00b4000\u00b4001\u00bf5')
Mark Dickinson79f52032009-03-17 23:12:51 +00001169
Stefan Krah6fb204a2012-09-28 16:18:54 +02001170 @run_with_locale('LC_ALL', 'ps_AF')
Stefan Krah1919b7e2012-03-21 18:25:23 +01001171 def test_wide_char_separator_decimal_point(self):
1172 # locale with wide char separator and decimal point
Stefan Krah8a491a82012-09-28 17:17:11 +02001173 import locale
Stefan Krah1919b7e2012-03-21 18:25:23 +01001174 Decimal = self.decimal.Decimal
1175
Stefan Krah8a491a82012-09-28 17:17:11 +02001176 decimal_point = locale.localeconv()['decimal_point']
1177 thousands_sep = locale.localeconv()['thousands_sep']
Zachary Ware9fe6d862013-12-08 00:20:35 -06001178 if decimal_point != '\u066b':
1179 self.skipTest('inappropriate decimal point separator'
Zachary Ware0f533ac2013-12-12 10:32:16 -06001180 '({!a} not {!a})'.format(decimal_point, '\u066b'))
Zachary Ware9fe6d862013-12-08 00:20:35 -06001181 if thousands_sep != '\u066c':
1182 self.skipTest('inappropriate thousands separator'
Zachary Ware0f533ac2013-12-12 10:32:16 -06001183 '({!a} not {!a})'.format(thousands_sep, '\u066c'))
Stefan Krah8a491a82012-09-28 17:17:11 +02001184
Stefan Krah1919b7e2012-03-21 18:25:23 +01001185 self.assertEqual(format(Decimal('100000000.123'), 'n'),
1186 '100\u066c000\u066c000\u066b123')
Stefan Krah1919b7e2012-03-21 18:25:23 +01001187
1188class CFormatTest(FormatTest):
1189 decimal = C
1190class PyFormatTest(FormatTest):
1191 decimal = P
1192
1193class ArithmeticOperatorsTest(unittest.TestCase):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001194 '''Unit tests for all arithmetic operators, binary and unary.'''
1195
1196 def test_addition(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001197 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001198
1199 d1 = Decimal('-11.1')
1200 d2 = Decimal('22.2')
1201
1202 #two Decimals
1203 self.assertEqual(d1+d2, Decimal('11.1'))
1204 self.assertEqual(d2+d1, Decimal('11.1'))
1205
1206 #with other type, left
1207 c = d1 + 5
1208 self.assertEqual(c, Decimal('-6.1'))
1209 self.assertEqual(type(c), type(d1))
1210
1211 #with other type, right
1212 c = 5 + d1
1213 self.assertEqual(c, Decimal('-6.1'))
1214 self.assertEqual(type(c), type(d1))
1215
1216 #inline with decimal
1217 d1 += d2
1218 self.assertEqual(d1, Decimal('11.1'))
1219
1220 #inline with other type
1221 d1 += 5
1222 self.assertEqual(d1, Decimal('16.1'))
1223
1224 def test_subtraction(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001225 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001226
1227 d1 = Decimal('-11.1')
1228 d2 = Decimal('22.2')
1229
1230 #two Decimals
1231 self.assertEqual(d1-d2, Decimal('-33.3'))
1232 self.assertEqual(d2-d1, Decimal('33.3'))
1233
1234 #with other type, left
1235 c = d1 - 5
1236 self.assertEqual(c, Decimal('-16.1'))
1237 self.assertEqual(type(c), type(d1))
1238
1239 #with other type, right
1240 c = 5 - d1
1241 self.assertEqual(c, Decimal('16.1'))
1242 self.assertEqual(type(c), type(d1))
1243
1244 #inline with decimal
1245 d1 -= d2
1246 self.assertEqual(d1, Decimal('-33.3'))
1247
1248 #inline with other type
1249 d1 -= 5
1250 self.assertEqual(d1, Decimal('-38.3'))
1251
1252 def test_multiplication(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001253 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001254
1255 d1 = Decimal('-5')
1256 d2 = Decimal('3')
1257
1258 #two Decimals
1259 self.assertEqual(d1*d2, Decimal('-15'))
1260 self.assertEqual(d2*d1, Decimal('-15'))
1261
1262 #with other type, left
1263 c = d1 * 5
1264 self.assertEqual(c, Decimal('-25'))
1265 self.assertEqual(type(c), type(d1))
1266
1267 #with other type, right
1268 c = 5 * d1
1269 self.assertEqual(c, Decimal('-25'))
1270 self.assertEqual(type(c), type(d1))
1271
1272 #inline with decimal
1273 d1 *= d2
1274 self.assertEqual(d1, Decimal('-15'))
1275
1276 #inline with other type
1277 d1 *= 5
1278 self.assertEqual(d1, Decimal('-75'))
1279
1280 def test_division(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001281 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001282
1283 d1 = Decimal('-5')
1284 d2 = Decimal('2')
1285
1286 #two Decimals
1287 self.assertEqual(d1/d2, Decimal('-2.5'))
1288 self.assertEqual(d2/d1, Decimal('-0.4'))
1289
1290 #with other type, left
1291 c = d1 / 4
1292 self.assertEqual(c, Decimal('-1.25'))
1293 self.assertEqual(type(c), type(d1))
1294
1295 #with other type, right
1296 c = 4 / d1
1297 self.assertEqual(c, Decimal('-0.8'))
1298 self.assertEqual(type(c), type(d1))
1299
1300 #inline with decimal
1301 d1 /= d2
1302 self.assertEqual(d1, Decimal('-2.5'))
1303
1304 #inline with other type
1305 d1 /= 4
1306 self.assertEqual(d1, Decimal('-0.625'))
1307
1308 def test_floor_division(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001309 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001310
1311 d1 = Decimal('5')
1312 d2 = Decimal('2')
1313
1314 #two Decimals
1315 self.assertEqual(d1//d2, Decimal('2'))
1316 self.assertEqual(d2//d1, Decimal('0'))
1317
1318 #with other type, left
1319 c = d1 // 4
1320 self.assertEqual(c, Decimal('1'))
1321 self.assertEqual(type(c), type(d1))
1322
1323 #with other type, right
1324 c = 7 // d1
1325 self.assertEqual(c, Decimal('1'))
1326 self.assertEqual(type(c), type(d1))
1327
1328 #inline with decimal
1329 d1 //= d2
1330 self.assertEqual(d1, Decimal('2'))
1331
1332 #inline with other type
1333 d1 //= 2
1334 self.assertEqual(d1, Decimal('1'))
1335
1336 def test_powering(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001337 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001338
1339 d1 = Decimal('5')
1340 d2 = Decimal('2')
1341
1342 #two Decimals
1343 self.assertEqual(d1**d2, Decimal('25'))
1344 self.assertEqual(d2**d1, Decimal('32'))
1345
1346 #with other type, left
1347 c = d1 ** 4
1348 self.assertEqual(c, Decimal('625'))
1349 self.assertEqual(type(c), type(d1))
1350
1351 #with other type, right
1352 c = 7 ** d1
1353 self.assertEqual(c, Decimal('16807'))
1354 self.assertEqual(type(c), type(d1))
1355
1356 #inline with decimal
1357 d1 **= d2
1358 self.assertEqual(d1, Decimal('25'))
1359
1360 #inline with other type
1361 d1 **= 4
1362 self.assertEqual(d1, Decimal('390625'))
1363
1364 def test_module(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001365 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001366
1367 d1 = Decimal('5')
1368 d2 = Decimal('2')
1369
1370 #two Decimals
1371 self.assertEqual(d1%d2, Decimal('1'))
1372 self.assertEqual(d2%d1, Decimal('2'))
1373
1374 #with other type, left
1375 c = d1 % 4
1376 self.assertEqual(c, Decimal('1'))
1377 self.assertEqual(type(c), type(d1))
1378
1379 #with other type, right
1380 c = 7 % d1
1381 self.assertEqual(c, Decimal('2'))
1382 self.assertEqual(type(c), type(d1))
1383
1384 #inline with decimal
1385 d1 %= d2
1386 self.assertEqual(d1, Decimal('1'))
1387
1388 #inline with other type
1389 d1 %= 4
1390 self.assertEqual(d1, Decimal('1'))
1391
1392 def test_floor_div_module(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001393 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001394
1395 d1 = Decimal('5')
1396 d2 = Decimal('2')
1397
1398 #two Decimals
1399 (p, q) = divmod(d1, d2)
1400 self.assertEqual(p, Decimal('2'))
1401 self.assertEqual(q, Decimal('1'))
1402 self.assertEqual(type(p), type(d1))
1403 self.assertEqual(type(q), type(d1))
1404
1405 #with other type, left
1406 (p, q) = divmod(d1, 4)
1407 self.assertEqual(p, Decimal('1'))
1408 self.assertEqual(q, Decimal('1'))
1409 self.assertEqual(type(p), type(d1))
1410 self.assertEqual(type(q), type(d1))
1411
1412 #with other type, right
1413 (p, q) = divmod(7, d1)
1414 self.assertEqual(p, Decimal('1'))
1415 self.assertEqual(q, Decimal('2'))
1416 self.assertEqual(type(p), type(d1))
1417 self.assertEqual(type(q), type(d1))
1418
1419 def test_unary_operators(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001420 Decimal = self.decimal.Decimal
1421
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001422 self.assertEqual(+Decimal(45), Decimal(+45)) # +
1423 self.assertEqual(-Decimal(45), Decimal(-45)) # -
1424 self.assertEqual(abs(Decimal(45)), abs(Decimal(-45))) # abs
1425
Christian Heimes77c02eb2008-02-09 02:18:51 +00001426 def test_nan_comparisons(self):
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001427 # comparisons involving signaling nans signal InvalidOperation
1428
1429 # order comparisons (<, <=, >, >=) involving only quiet nans
1430 # also signal InvalidOperation
1431
1432 # equality comparisons (==, !=) involving only quiet nans
1433 # don't signal, but return False or True respectively.
Stefan Krah1919b7e2012-03-21 18:25:23 +01001434 Decimal = self.decimal.Decimal
1435 InvalidOperation = self.decimal.InvalidOperation
1436 localcontext = self.decimal.localcontext
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001437
Christian Heimes77c02eb2008-02-09 02:18:51 +00001438 n = Decimal('NaN')
1439 s = Decimal('sNaN')
1440 i = Decimal('Inf')
1441 f = Decimal('2')
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001442
1443 qnan_pairs = (n, n), (n, i), (i, n), (n, f), (f, n)
1444 snan_pairs = (s, n), (n, s), (s, i), (i, s), (s, f), (f, s), (s, s)
1445 order_ops = operator.lt, operator.le, operator.gt, operator.ge
1446 equality_ops = operator.eq, operator.ne
1447
1448 # results when InvalidOperation is not trapped
1449 for x, y in qnan_pairs + snan_pairs:
1450 for op in order_ops + equality_ops:
1451 got = op(x, y)
1452 expected = True if op is operator.ne else False
1453 self.assertIs(expected, got,
1454 "expected {0!r} for operator.{1}({2!r}, {3!r}); "
1455 "got {4!r}".format(
1456 expected, op.__name__, x, y, got))
1457
1458 # repeat the above, but this time trap the InvalidOperation
1459 with localcontext() as ctx:
1460 ctx.traps[InvalidOperation] = 1
1461
1462 for x, y in qnan_pairs:
1463 for op in equality_ops:
1464 got = op(x, y)
1465 expected = True if op is operator.ne else False
1466 self.assertIs(expected, got,
1467 "expected {0!r} for "
1468 "operator.{1}({2!r}, {3!r}); "
1469 "got {4!r}".format(
1470 expected, op.__name__, x, y, got))
1471
1472 for x, y in snan_pairs:
1473 for op in equality_ops:
1474 self.assertRaises(InvalidOperation, operator.eq, x, y)
1475 self.assertRaises(InvalidOperation, operator.ne, x, y)
1476
1477 for x, y in qnan_pairs + snan_pairs:
1478 for op in order_ops:
1479 self.assertRaises(InvalidOperation, op, x, y)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001480
Mark Dickinson84230a12010-02-18 14:49:50 +00001481 def test_copy_sign(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001482 Decimal = self.decimal.Decimal
Mark Dickinson84230a12010-02-18 14:49:50 +00001483
Stefan Krah1919b7e2012-03-21 18:25:23 +01001484 d = Decimal(1).copy_sign(Decimal(-2))
Mark Dickinson84230a12010-02-18 14:49:50 +00001485 self.assertEqual(Decimal(1).copy_sign(-2), d)
1486 self.assertRaises(TypeError, Decimal(1).copy_sign, '-2')
1487
Stefan Krah1919b7e2012-03-21 18:25:23 +01001488class CArithmeticOperatorsTest(ArithmeticOperatorsTest):
1489 decimal = C
1490class PyArithmeticOperatorsTest(ArithmeticOperatorsTest):
1491 decimal = P
1492
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001493# The following are two functions used to test threading in the next class
1494
1495def thfunc1(cls):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001496 Decimal = cls.decimal.Decimal
1497 InvalidOperation = cls.decimal.InvalidOperation
1498 DivisionByZero = cls.decimal.DivisionByZero
1499 Overflow = cls.decimal.Overflow
1500 Underflow = cls.decimal.Underflow
1501 Inexact = cls.decimal.Inexact
1502 getcontext = cls.decimal.getcontext
1503 localcontext = cls.decimal.localcontext
1504
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001505 d1 = Decimal(1)
1506 d3 = Decimal(3)
Christian Heimesfe337bf2008-03-23 21:54:12 +00001507 test1 = d1/d3
Christian Heimesfe337bf2008-03-23 21:54:12 +00001508
Stefan Krah1919b7e2012-03-21 18:25:23 +01001509 cls.finish1.set()
1510 cls.synchro.wait()
1511
1512 test2 = d1/d3
1513 with localcontext() as c2:
1514 cls.assertTrue(c2.flags[Inexact])
1515 cls.assertRaises(DivisionByZero, c2.divide, d1, 0)
1516 cls.assertTrue(c2.flags[DivisionByZero])
1517 with localcontext() as c3:
1518 cls.assertTrue(c3.flags[Inexact])
1519 cls.assertTrue(c3.flags[DivisionByZero])
1520 cls.assertRaises(InvalidOperation, c3.compare, d1, Decimal('sNaN'))
1521 cls.assertTrue(c3.flags[InvalidOperation])
1522 del c3
1523 cls.assertFalse(c2.flags[InvalidOperation])
1524 del c2
1525
1526 cls.assertEqual(test1, Decimal('0.333333333333333333333333'))
1527 cls.assertEqual(test2, Decimal('0.333333333333333333333333'))
1528
1529 c1 = getcontext()
1530 cls.assertTrue(c1.flags[Inexact])
1531 for sig in Overflow, Underflow, DivisionByZero, InvalidOperation:
1532 cls.assertFalse(c1.flags[sig])
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001533
1534def thfunc2(cls):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001535 Decimal = cls.decimal.Decimal
1536 InvalidOperation = cls.decimal.InvalidOperation
1537 DivisionByZero = cls.decimal.DivisionByZero
1538 Overflow = cls.decimal.Overflow
1539 Underflow = cls.decimal.Underflow
1540 Inexact = cls.decimal.Inexact
1541 getcontext = cls.decimal.getcontext
1542 localcontext = cls.decimal.localcontext
1543
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001544 d1 = Decimal(1)
1545 d3 = Decimal(3)
Christian Heimesfe337bf2008-03-23 21:54:12 +00001546 test1 = d1/d3
Stefan Krah1919b7e2012-03-21 18:25:23 +01001547
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001548 thiscontext = getcontext()
1549 thiscontext.prec = 18
Christian Heimesfe337bf2008-03-23 21:54:12 +00001550 test2 = d1/d3
Stefan Krah1919b7e2012-03-21 18:25:23 +01001551
1552 with localcontext() as c2:
1553 cls.assertTrue(c2.flags[Inexact])
1554 cls.assertRaises(Overflow, c2.multiply, Decimal('1e425000000'), 999)
1555 cls.assertTrue(c2.flags[Overflow])
1556 with localcontext(thiscontext) as c3:
1557 cls.assertTrue(c3.flags[Inexact])
1558 cls.assertFalse(c3.flags[Overflow])
1559 c3.traps[Underflow] = True
1560 cls.assertRaises(Underflow, c3.divide, Decimal('1e-425000000'), 999)
1561 cls.assertTrue(c3.flags[Underflow])
1562 del c3
1563 cls.assertFalse(c2.flags[Underflow])
1564 cls.assertFalse(c2.traps[Underflow])
1565 del c2
1566
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001567 cls.synchro.set()
1568 cls.finish2.set()
Christian Heimesfe337bf2008-03-23 21:54:12 +00001569
Stefan Krah1919b7e2012-03-21 18:25:23 +01001570 cls.assertEqual(test1, Decimal('0.333333333333333333333333'))
Christian Heimesfe337bf2008-03-23 21:54:12 +00001571 cls.assertEqual(test2, Decimal('0.333333333333333333'))
Stefan Krah1919b7e2012-03-21 18:25:23 +01001572
1573 cls.assertFalse(thiscontext.traps[Underflow])
1574 cls.assertTrue(thiscontext.flags[Inexact])
1575 for sig in Overflow, Underflow, DivisionByZero, InvalidOperation:
1576 cls.assertFalse(thiscontext.flags[sig])
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001577
Stefan Krah1919b7e2012-03-21 18:25:23 +01001578class ThreadingTest(unittest.TestCase):
1579 '''Unit tests for thread local contexts in Decimal.'''
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001580
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001581 # Take care executing this test from IDLE, there's an issue in threading
1582 # that hangs IDLE and I couldn't find it
1583
1584 def test_threading(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001585 DefaultContext = self.decimal.DefaultContext
1586
1587 if self.decimal == C and not self.decimal.HAVE_THREADS:
1588 self.skipTest("compiled without threading")
1589 # Test the "threading isolation" of a Context. Also test changing
1590 # the DefaultContext, which acts as a template for the thread-local
1591 # contexts.
1592 save_prec = DefaultContext.prec
1593 save_emax = DefaultContext.Emax
1594 save_emin = DefaultContext.Emin
1595 DefaultContext.prec = 24
1596 DefaultContext.Emax = 425000000
1597 DefaultContext.Emin = -425000000
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001598
1599 self.synchro = threading.Event()
1600 self.finish1 = threading.Event()
1601 self.finish2 = threading.Event()
1602
1603 th1 = threading.Thread(target=thfunc1, args=(self,))
1604 th2 = threading.Thread(target=thfunc2, args=(self,))
1605
1606 th1.start()
1607 th2.start()
1608
1609 self.finish1.wait()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001610 self.finish2.wait()
Stefan Krah1919b7e2012-03-21 18:25:23 +01001611
1612 for sig in Signals[self.decimal]:
1613 self.assertFalse(DefaultContext.flags[sig])
1614
1615 DefaultContext.prec = save_prec
1616 DefaultContext.Emax = save_emax
1617 DefaultContext.Emin = save_emin
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001618
Stefan Krah1919b7e2012-03-21 18:25:23 +01001619@unittest.skipUnless(threading, 'threading required')
1620class CThreadingTest(ThreadingTest):
1621 decimal = C
1622@unittest.skipUnless(threading, 'threading required')
1623class PyThreadingTest(ThreadingTest):
1624 decimal = P
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001625
Stefan Krah1919b7e2012-03-21 18:25:23 +01001626class UsabilityTest(unittest.TestCase):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001627 '''Unit tests for Usability cases of Decimal.'''
1628
1629 def test_comparison_operators(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001630
Stefan Krah1919b7e2012-03-21 18:25:23 +01001631 Decimal = self.decimal.Decimal
1632
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001633 da = Decimal('23.42')
1634 db = Decimal('23.42')
1635 dc = Decimal('45')
1636
1637 #two Decimals
Ezio Melotti6607d512010-04-03 14:59:49 +00001638 self.assertGreater(dc, da)
1639 self.assertGreaterEqual(dc, da)
1640 self.assertLess(da, dc)
1641 self.assertLessEqual(da, dc)
Guido van Rossume61fd5b2007-07-11 12:20:59 +00001642 self.assertEqual(da, db)
Ezio Melotti6607d512010-04-03 14:59:49 +00001643 self.assertNotEqual(da, dc)
1644 self.assertLessEqual(da, db)
1645 self.assertGreaterEqual(da, db)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001646
1647 #a Decimal and an int
Ezio Melotti6607d512010-04-03 14:59:49 +00001648 self.assertGreater(dc, 23)
1649 self.assertLess(23, dc)
Guido van Rossume61fd5b2007-07-11 12:20:59 +00001650 self.assertEqual(dc, 45)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001651
1652 #a Decimal and uncomparable
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001653 self.assertNotEqual(da, 'ugly')
1654 self.assertNotEqual(da, 32.7)
1655 self.assertNotEqual(da, object())
1656 self.assertNotEqual(da, object)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001657
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001658 # sortable
Guido van Rossumc1f779c2007-07-03 08:25:58 +00001659 a = list(map(Decimal, range(100)))
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001660 b = a[:]
1661 random.shuffle(a)
1662 a.sort()
1663 self.assertEqual(a, b)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001664
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001665 def test_decimal_float_comparison(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001666 Decimal = self.decimal.Decimal
1667
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001668 da = Decimal('0.25')
1669 db = Decimal('3.0')
Ezio Melotti6607d512010-04-03 14:59:49 +00001670 self.assertLess(da, 3.0)
1671 self.assertLessEqual(da, 3.0)
1672 self.assertGreater(db, 0.25)
1673 self.assertGreaterEqual(db, 0.25)
1674 self.assertNotEqual(da, 1.5)
1675 self.assertEqual(da, 0.25)
1676 self.assertGreater(3.0, da)
1677 self.assertGreaterEqual(3.0, da)
1678 self.assertLess(0.25, db)
1679 self.assertLessEqual(0.25, db)
1680 self.assertNotEqual(0.25, db)
1681 self.assertEqual(3.0, db)
1682 self.assertNotEqual(0.1, Decimal('0.1'))
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001683
Stefan Krah1919b7e2012-03-21 18:25:23 +01001684 def test_decimal_complex_comparison(self):
1685 Decimal = self.decimal.Decimal
1686
1687 da = Decimal('0.25')
1688 db = Decimal('3.0')
1689 self.assertNotEqual(da, (1.5+0j))
1690 self.assertNotEqual((1.5+0j), da)
1691 self.assertEqual(da, (0.25+0j))
1692 self.assertEqual((0.25+0j), da)
1693 self.assertEqual((3.0+0j), db)
1694 self.assertEqual(db, (3.0+0j))
1695
1696 self.assertNotEqual(db, (3.0+1j))
1697 self.assertNotEqual((3.0+1j), db)
1698
1699 self.assertIs(db.__lt__(3.0+0j), NotImplemented)
1700 self.assertIs(db.__le__(3.0+0j), NotImplemented)
1701 self.assertIs(db.__gt__(3.0+0j), NotImplemented)
1702 self.assertIs(db.__le__(3.0+0j), NotImplemented)
1703
1704 def test_decimal_fraction_comparison(self):
1705 D = self.decimal.Decimal
1706 F = fractions[self.decimal].Fraction
1707 Context = self.decimal.Context
1708 localcontext = self.decimal.localcontext
1709 InvalidOperation = self.decimal.InvalidOperation
1710
1711
1712 emax = C.MAX_EMAX if C else 999999999
1713 emin = C.MIN_EMIN if C else -999999999
1714 etiny = C.MIN_ETINY if C else -1999999997
1715 c = Context(Emax=emax, Emin=emin)
1716
1717 with localcontext(c):
1718 c.prec = emax
1719 self.assertLess(D(0), F(1,9999999999999999999999999999999999999))
1720 self.assertLess(F(-1,9999999999999999999999999999999999999), D(0))
1721 self.assertLess(F(0,1), D("1e" + str(etiny)))
1722 self.assertLess(D("-1e" + str(etiny)), F(0,1))
1723 self.assertLess(F(0,9999999999999999999999999), D("1e" + str(etiny)))
1724 self.assertLess(D("-1e" + str(etiny)), F(0,9999999999999999999999999))
1725
1726 self.assertEqual(D("0.1"), F(1,10))
1727 self.assertEqual(F(1,10), D("0.1"))
1728
1729 c.prec = 300
1730 self.assertNotEqual(D(1)/3, F(1,3))
1731 self.assertNotEqual(F(1,3), D(1)/3)
1732
1733 self.assertLessEqual(F(120984237, 9999999999), D("9e" + str(emax)))
1734 self.assertGreaterEqual(D("9e" + str(emax)), F(120984237, 9999999999))
1735
1736 self.assertGreater(D('inf'), F(99999999999,123))
1737 self.assertGreater(D('inf'), F(-99999999999,123))
1738 self.assertLess(D('-inf'), F(99999999999,123))
1739 self.assertLess(D('-inf'), F(-99999999999,123))
1740
1741 self.assertRaises(InvalidOperation, D('nan').__gt__, F(-9,123))
1742 self.assertIs(NotImplemented, F(-9,123).__lt__(D('nan')))
1743 self.assertNotEqual(D('nan'), F(-9,123))
1744 self.assertNotEqual(F(-9,123), D('nan'))
1745
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001746 def test_copy_and_deepcopy_methods(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001747 Decimal = self.decimal.Decimal
1748
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001749 d = Decimal('43.24')
1750 c = copy.copy(d)
1751 self.assertEqual(id(c), id(d))
1752 dc = copy.deepcopy(d)
1753 self.assertEqual(id(dc), id(d))
1754
1755 def test_hash_method(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001756
1757 Decimal = self.decimal.Decimal
1758 localcontext = self.decimal.localcontext
1759
Stefan Krahdc817b22010-11-17 11:16:34 +00001760 def hashit(d):
1761 a = hash(d)
1762 b = d.__hash__()
1763 self.assertEqual(a, b)
1764 return a
1765
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001766 #just that it's hashable
Stefan Krahdc817b22010-11-17 11:16:34 +00001767 hashit(Decimal(23))
1768 hashit(Decimal('Infinity'))
1769 hashit(Decimal('-Infinity'))
1770 hashit(Decimal('nan123'))
1771 hashit(Decimal('-NaN'))
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001772
1773 test_values = [Decimal(sign*(2**m + n))
1774 for m in [0, 14, 15, 16, 17, 30, 31,
Stefan Krahdc817b22010-11-17 11:16:34 +00001775 32, 33, 61, 62, 63, 64, 65, 66]
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001776 for n in range(-10, 10)
1777 for sign in [-1, 1]]
1778 test_values.extend([
Stefan Krahdc817b22010-11-17 11:16:34 +00001779 Decimal("-1"), # ==> -2
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001780 Decimal("-0"), # zeros
1781 Decimal("0.00"),
1782 Decimal("-0.000"),
1783 Decimal("0E10"),
1784 Decimal("-0E12"),
1785 Decimal("10.0"), # negative exponent
1786 Decimal("-23.00000"),
1787 Decimal("1230E100"), # positive exponent
1788 Decimal("-4.5678E50"),
1789 # a value for which hash(n) != hash(n % (2**64-1))
1790 # in Python pre-2.6
1791 Decimal(2**64 + 2**32 - 1),
1792 # selection of values which fail with the old (before
1793 # version 2.6) long.__hash__
1794 Decimal("1.634E100"),
1795 Decimal("90.697E100"),
1796 Decimal("188.83E100"),
1797 Decimal("1652.9E100"),
1798 Decimal("56531E100"),
1799 ])
1800
1801 # check that hash(d) == hash(int(d)) for integral values
1802 for value in test_values:
Stefan Krahdc817b22010-11-17 11:16:34 +00001803 self.assertEqual(hashit(value), hashit(int(value)))
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001804
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001805 #the same hash that to an int
Stefan Krahdc817b22010-11-17 11:16:34 +00001806 self.assertEqual(hashit(Decimal(23)), hashit(23))
Raymond Hettingerd325c4b2010-11-21 04:08:28 +00001807 self.assertRaises(TypeError, hash, Decimal('sNaN'))
Stefan Krahdc817b22010-11-17 11:16:34 +00001808 self.assertTrue(hashit(Decimal('Inf')))
1809 self.assertTrue(hashit(Decimal('-Inf')))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001810
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001811 # check that the hashes of a Decimal float match when they
1812 # represent exactly the same values
1813 test_strings = ['inf', '-Inf', '0.0', '-.0e1',
1814 '34.0', '2.5', '112390.625', '-0.515625']
1815 for s in test_strings:
1816 f = float(s)
1817 d = Decimal(s)
Stefan Krahdc817b22010-11-17 11:16:34 +00001818 self.assertEqual(hashit(f), hashit(d))
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001819
Stefan Krah1919b7e2012-03-21 18:25:23 +01001820 with localcontext() as c:
1821 # check that the value of the hash doesn't depend on the
1822 # current context (issue #1757)
1823 x = Decimal("123456789.1")
Christian Heimes2380ac72008-01-09 00:17:24 +00001824
Stefan Krah1919b7e2012-03-21 18:25:23 +01001825 c.prec = 6
1826 h1 = hashit(x)
1827 c.prec = 10
1828 h2 = hashit(x)
1829 c.prec = 16
1830 h3 = hashit(x)
Christian Heimes2380ac72008-01-09 00:17:24 +00001831
Stefan Krah1919b7e2012-03-21 18:25:23 +01001832 self.assertEqual(h1, h2)
1833 self.assertEqual(h1, h3)
1834
1835 c.prec = 10000
1836 x = 1100 ** 1248
1837 self.assertEqual(hashit(Decimal(x)), hashit(x))
Christian Heimes2380ac72008-01-09 00:17:24 +00001838
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001839 def test_min_and_max_methods(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001840 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001841
1842 d1 = Decimal('15.32')
1843 d2 = Decimal('28.5')
1844 l1 = 15
1845 l2 = 28
1846
1847 #between Decimals
Ezio Melotti6607d512010-04-03 14:59:49 +00001848 self.assertIs(min(d1,d2), d1)
1849 self.assertIs(min(d2,d1), d1)
1850 self.assertIs(max(d1,d2), d2)
1851 self.assertIs(max(d2,d1), d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001852
Serhiy Storchaka95949422013-08-27 19:40:23 +03001853 #between Decimal and int
Ezio Melotti6607d512010-04-03 14:59:49 +00001854 self.assertIs(min(d1,l2), d1)
1855 self.assertIs(min(l2,d1), d1)
1856 self.assertIs(max(l1,d2), d2)
1857 self.assertIs(max(d2,l1), d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001858
1859 def test_as_nonzero(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001860 Decimal = self.decimal.Decimal
1861
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001862 #as false
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001863 self.assertFalse(Decimal(0))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001864 #as true
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001865 self.assertTrue(Decimal('0.372'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001866
1867 def test_tostring_methods(self):
1868 #Test str and repr methods.
Stefan Krah1919b7e2012-03-21 18:25:23 +01001869 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001870
1871 d = Decimal('15.32')
1872 self.assertEqual(str(d), '15.32') # str
Christian Heimes68f5fbe2008-02-14 08:27:37 +00001873 self.assertEqual(repr(d), "Decimal('15.32')") # repr
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001874
1875 def test_tonum_methods(self):
Mark Dickinson5c2db372009-12-05 20:28:34 +00001876 #Test float and int methods.
Stefan Krah1919b7e2012-03-21 18:25:23 +01001877 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001878
1879 d1 = Decimal('66')
1880 d2 = Decimal('15.32')
1881
1882 #int
1883 self.assertEqual(int(d1), 66)
1884 self.assertEqual(int(d2), 15)
1885
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001886 #float
1887 self.assertEqual(float(d1), 66)
1888 self.assertEqual(float(d2), 15.32)
1889
Mark Dickinsonb27406c2008-05-09 13:42:33 +00001890 #floor
1891 test_pairs = [
1892 ('123.00', 123),
1893 ('3.2', 3),
1894 ('3.54', 3),
1895 ('3.899', 3),
1896 ('-2.3', -3),
1897 ('-11.0', -11),
1898 ('0.0', 0),
1899 ('-0E3', 0),
Stefan Krah1919b7e2012-03-21 18:25:23 +01001900 ('89891211712379812736.1', 89891211712379812736),
Mark Dickinsonb27406c2008-05-09 13:42:33 +00001901 ]
1902 for d, i in test_pairs:
1903 self.assertEqual(math.floor(Decimal(d)), i)
1904 self.assertRaises(ValueError, math.floor, Decimal('-NaN'))
1905 self.assertRaises(ValueError, math.floor, Decimal('sNaN'))
1906 self.assertRaises(ValueError, math.floor, Decimal('NaN123'))
1907 self.assertRaises(OverflowError, math.floor, Decimal('Inf'))
1908 self.assertRaises(OverflowError, math.floor, Decimal('-Inf'))
1909
1910 #ceiling
1911 test_pairs = [
1912 ('123.00', 123),
1913 ('3.2', 4),
1914 ('3.54', 4),
1915 ('3.899', 4),
1916 ('-2.3', -2),
1917 ('-11.0', -11),
1918 ('0.0', 0),
1919 ('-0E3', 0),
Stefan Krah1919b7e2012-03-21 18:25:23 +01001920 ('89891211712379812736.1', 89891211712379812737),
Mark Dickinsonb27406c2008-05-09 13:42:33 +00001921 ]
1922 for d, i in test_pairs:
1923 self.assertEqual(math.ceil(Decimal(d)), i)
1924 self.assertRaises(ValueError, math.ceil, Decimal('-NaN'))
1925 self.assertRaises(ValueError, math.ceil, Decimal('sNaN'))
1926 self.assertRaises(ValueError, math.ceil, Decimal('NaN123'))
1927 self.assertRaises(OverflowError, math.ceil, Decimal('Inf'))
1928 self.assertRaises(OverflowError, math.ceil, Decimal('-Inf'))
1929
1930 #round, single argument
1931 test_pairs = [
1932 ('123.00', 123),
1933 ('3.2', 3),
1934 ('3.54', 4),
1935 ('3.899', 4),
1936 ('-2.3', -2),
1937 ('-11.0', -11),
1938 ('0.0', 0),
1939 ('-0E3', 0),
1940 ('-3.5', -4),
1941 ('-2.5', -2),
1942 ('-1.5', -2),
1943 ('-0.5', 0),
1944 ('0.5', 0),
1945 ('1.5', 2),
1946 ('2.5', 2),
1947 ('3.5', 4),
1948 ]
1949 for d, i in test_pairs:
1950 self.assertEqual(round(Decimal(d)), i)
1951 self.assertRaises(ValueError, round, Decimal('-NaN'))
1952 self.assertRaises(ValueError, round, Decimal('sNaN'))
1953 self.assertRaises(ValueError, round, Decimal('NaN123'))
1954 self.assertRaises(OverflowError, round, Decimal('Inf'))
1955 self.assertRaises(OverflowError, round, Decimal('-Inf'))
1956
1957 #round, two arguments; this is essentially equivalent
1958 #to quantize, which is already extensively tested
1959 test_triples = [
1960 ('123.456', -4, '0E+4'),
1961 ('123.456', -3, '0E+3'),
1962 ('123.456', -2, '1E+2'),
1963 ('123.456', -1, '1.2E+2'),
1964 ('123.456', 0, '123'),
1965 ('123.456', 1, '123.5'),
1966 ('123.456', 2, '123.46'),
1967 ('123.456', 3, '123.456'),
1968 ('123.456', 4, '123.4560'),
1969 ('123.455', 2, '123.46'),
1970 ('123.445', 2, '123.44'),
1971 ('Inf', 4, 'NaN'),
1972 ('-Inf', -23, 'NaN'),
1973 ('sNaN314', 3, 'NaN314'),
1974 ]
1975 for d, n, r in test_triples:
1976 self.assertEqual(str(round(Decimal(d), n)), r)
1977
Mark Dickinsonfc33d4c2012-08-24 18:53:10 +01001978 def test_nan_to_float(self):
1979 # Test conversions of decimal NANs to float.
1980 # See http://bugs.python.org/issue15544
1981 Decimal = self.decimal.Decimal
1982 for s in ('nan', 'nan1234', '-nan', '-nan2468'):
1983 f = float(Decimal(s))
1984 self.assertTrue(math.isnan(f))
1985 sign = math.copysign(1.0, f)
1986 self.assertEqual(sign, -1.0 if s.startswith('-') else 1.0)
1987
1988 def test_snan_to_float(self):
1989 Decimal = self.decimal.Decimal
1990 for s in ('snan', '-snan', 'snan1357', '-snan1234'):
1991 d = Decimal(s)
1992 self.assertRaises(ValueError, float, d)
1993
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001994 def test_eval_round_trip(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001995 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001996
1997 #with zero
1998 d = Decimal( (0, (0,), 0) )
1999 self.assertEqual(d, eval(repr(d)))
2000
2001 #int
2002 d = Decimal( (1, (4, 5), 0) )
2003 self.assertEqual(d, eval(repr(d)))
2004
2005 #float
2006 d = Decimal( (0, (4, 5, 3, 4), -2) )
2007 self.assertEqual(d, eval(repr(d)))
2008
2009 #weird
2010 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
2011 self.assertEqual(d, eval(repr(d)))
2012
2013 def test_as_tuple(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01002014 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002015
2016 #with zero
2017 d = Decimal(0)
2018 self.assertEqual(d.as_tuple(), (0, (0,), 0) )
2019
2020 #int
2021 d = Decimal(-45)
2022 self.assertEqual(d.as_tuple(), (1, (4, 5), 0) )
2023
2024 #complicated string
2025 d = Decimal("-4.34913534E-17")
2026 self.assertEqual(d.as_tuple(), (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
2027
Stefan Krah76e12172012-09-10 19:34:58 +02002028 # The '0' coefficient is implementation specific to decimal.py.
2029 # It has no meaning in the C-version and is ignored there.
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002030 d = Decimal("Infinity")
2031 self.assertEqual(d.as_tuple(), (0, (0,), 'F') )
2032
Guido van Rossum8ce8a782007-11-01 19:42:39 +00002033 #leading zeros in coefficient should be stripped
2034 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), -2) )
2035 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), -2) )
2036 d = Decimal( (1, (0, 0, 0), 37) )
2037 self.assertEqual(d.as_tuple(), (1, (0,), 37))
2038 d = Decimal( (1, (), 37) )
2039 self.assertEqual(d.as_tuple(), (1, (0,), 37))
2040
2041 #leading zeros in NaN diagnostic info should be stripped
2042 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), 'n') )
2043 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), 'n') )
2044 d = Decimal( (1, (0, 0, 0), 'N') )
2045 self.assertEqual(d.as_tuple(), (1, (), 'N') )
2046 d = Decimal( (1, (), 'n') )
2047 self.assertEqual(d.as_tuple(), (1, (), 'n') )
2048
Stefan Krah76e12172012-09-10 19:34:58 +02002049 # For infinities, decimal.py has always silently accepted any
2050 # coefficient tuple.
2051 d = Decimal( (0, (0,), 'F') )
2052 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
2053 d = Decimal( (0, (4, 5, 3, 4), 'F') )
2054 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
2055 d = Decimal( (1, (0, 2, 7, 1), 'F') )
2056 self.assertEqual(d.as_tuple(), (1, (0,), 'F'))
Guido van Rossum8ce8a782007-11-01 19:42:39 +00002057
Stefan Krah53f2e0a2015-12-28 23:02:02 +01002058 def test_as_integer_ratio(self):
2059 Decimal = self.decimal.Decimal
2060
2061 # exceptional cases
2062 self.assertRaises(OverflowError,
2063 Decimal.as_integer_ratio, Decimal('inf'))
2064 self.assertRaises(OverflowError,
2065 Decimal.as_integer_ratio, Decimal('-inf'))
2066 self.assertRaises(ValueError,
2067 Decimal.as_integer_ratio, Decimal('-nan'))
2068 self.assertRaises(ValueError,
2069 Decimal.as_integer_ratio, Decimal('snan123'))
2070
2071 for exp in range(-4, 2):
2072 for coeff in range(1000):
2073 for sign in '+', '-':
2074 d = Decimal('%s%dE%d' % (sign, coeff, exp))
2075 pq = d.as_integer_ratio()
2076 p, q = pq
2077
2078 # check return type
2079 self.assertIsInstance(pq, tuple)
2080 self.assertIsInstance(p, int)
2081 self.assertIsInstance(q, int)
2082
2083 # check normalization: q should be positive;
2084 # p should be relatively prime to q.
2085 self.assertGreater(q, 0)
2086 self.assertEqual(math.gcd(p, q), 1)
2087
2088 # check that p/q actually gives the correct value
2089 self.assertEqual(Decimal(p) / Decimal(q), d)
2090
Stefan Krah1919b7e2012-03-21 18:25:23 +01002091 def test_subclassing(self):
2092 # Different behaviours when subclassing Decimal
2093 Decimal = self.decimal.Decimal
2094
2095 class MyDecimal(Decimal):
Stefan Krah0f82b762012-11-08 11:17:29 +01002096 y = None
Stefan Krah1919b7e2012-03-21 18:25:23 +01002097
2098 d1 = MyDecimal(1)
2099 d2 = MyDecimal(2)
2100 d = d1 + d2
2101 self.assertIs(type(d), Decimal)
2102
2103 d = d1.max(d2)
2104 self.assertIs(type(d), Decimal)
2105
2106 d = copy.copy(d1)
2107 self.assertIs(type(d), MyDecimal)
2108 self.assertEqual(d, d1)
2109
2110 d = copy.deepcopy(d1)
2111 self.assertIs(type(d), MyDecimal)
2112 self.assertEqual(d, d1)
2113
Stefan Krah0f82b762012-11-08 11:17:29 +01002114 # Decimal(Decimal)
2115 d = Decimal('1.0')
2116 x = Decimal(d)
2117 self.assertIs(type(x), Decimal)
2118 self.assertEqual(x, d)
Stefan Krahf4abc7b2012-11-07 23:12:25 +01002119
Stefan Krah0f82b762012-11-08 11:17:29 +01002120 # MyDecimal(Decimal)
2121 m = MyDecimal(d)
2122 self.assertIs(type(m), MyDecimal)
2123 self.assertEqual(m, d)
2124 self.assertIs(m.y, None)
2125
2126 # Decimal(MyDecimal)
2127 x = Decimal(m)
2128 self.assertIs(type(x), Decimal)
2129 self.assertEqual(x, d)
2130
2131 # MyDecimal(MyDecimal)
2132 m.y = 9
2133 x = MyDecimal(m)
2134 self.assertIs(type(x), MyDecimal)
2135 self.assertEqual(x, d)
2136 self.assertIs(x.y, None)
Stefan Krahed16eff2012-11-07 23:47:19 +01002137
Stefan Krah1919b7e2012-03-21 18:25:23 +01002138 def test_implicit_context(self):
2139 Decimal = self.decimal.Decimal
2140 getcontext = self.decimal.getcontext
2141
2142 # Check results when context given implicitly. (Issue 2478)
2143 c = getcontext()
2144 self.assertEqual(str(Decimal(0).sqrt()),
2145 str(c.sqrt(Decimal(0))))
2146
Stefan Krah040e3112012-12-15 22:33:33 +01002147 def test_none_args(self):
2148 Decimal = self.decimal.Decimal
2149 Context = self.decimal.Context
2150 localcontext = self.decimal.localcontext
2151 InvalidOperation = self.decimal.InvalidOperation
2152 DivisionByZero = self.decimal.DivisionByZero
2153 Overflow = self.decimal.Overflow
2154 Underflow = self.decimal.Underflow
2155 Subnormal = self.decimal.Subnormal
2156 Inexact = self.decimal.Inexact
2157 Rounded = self.decimal.Rounded
2158 Clamped = self.decimal.Clamped
Stefan Krah040e3112012-12-15 22:33:33 +01002159
2160 with localcontext(Context()) as c:
2161 c.prec = 7
2162 c.Emax = 999
2163 c.Emin = -999
2164
2165 x = Decimal("111")
2166 y = Decimal("1e9999")
2167 z = Decimal("1e-9999")
2168
2169 ##### Unary functions
2170 c.clear_flags()
2171 self.assertEqual(str(x.exp(context=None)), '1.609487E+48')
2172 self.assertTrue(c.flags[Inexact])
2173 self.assertTrue(c.flags[Rounded])
2174 c.clear_flags()
2175 self.assertRaises(Overflow, y.exp, context=None)
2176 self.assertTrue(c.flags[Overflow])
2177
2178 self.assertIs(z.is_normal(context=None), False)
2179 self.assertIs(z.is_subnormal(context=None), True)
2180
2181 c.clear_flags()
2182 self.assertEqual(str(x.ln(context=None)), '4.709530')
2183 self.assertTrue(c.flags[Inexact])
2184 self.assertTrue(c.flags[Rounded])
2185 c.clear_flags()
2186 self.assertRaises(InvalidOperation, Decimal(-1).ln, context=None)
2187 self.assertTrue(c.flags[InvalidOperation])
2188
2189 c.clear_flags()
2190 self.assertEqual(str(x.log10(context=None)), '2.045323')
2191 self.assertTrue(c.flags[Inexact])
2192 self.assertTrue(c.flags[Rounded])
2193 c.clear_flags()
2194 self.assertRaises(InvalidOperation, Decimal(-1).log10, context=None)
2195 self.assertTrue(c.flags[InvalidOperation])
2196
2197 c.clear_flags()
2198 self.assertEqual(str(x.logb(context=None)), '2')
2199 self.assertRaises(DivisionByZero, Decimal(0).logb, context=None)
2200 self.assertTrue(c.flags[DivisionByZero])
2201
2202 c.clear_flags()
2203 self.assertEqual(str(x.logical_invert(context=None)), '1111000')
2204 self.assertRaises(InvalidOperation, y.logical_invert, context=None)
2205 self.assertTrue(c.flags[InvalidOperation])
2206
2207 c.clear_flags()
2208 self.assertEqual(str(y.next_minus(context=None)), '9.999999E+999')
2209 self.assertRaises(InvalidOperation, Decimal('sNaN').next_minus, context=None)
2210 self.assertTrue(c.flags[InvalidOperation])
2211
2212 c.clear_flags()
2213 self.assertEqual(str(y.next_plus(context=None)), 'Infinity')
2214 self.assertRaises(InvalidOperation, Decimal('sNaN').next_plus, context=None)
2215 self.assertTrue(c.flags[InvalidOperation])
2216
2217 c.clear_flags()
2218 self.assertEqual(str(z.normalize(context=None)), '0')
2219 self.assertRaises(Overflow, y.normalize, context=None)
2220 self.assertTrue(c.flags[Overflow])
2221
2222 self.assertEqual(str(z.number_class(context=None)), '+Subnormal')
2223
2224 c.clear_flags()
2225 self.assertEqual(str(z.sqrt(context=None)), '0E-1005')
2226 self.assertTrue(c.flags[Clamped])
2227 self.assertTrue(c.flags[Inexact])
2228 self.assertTrue(c.flags[Rounded])
2229 self.assertTrue(c.flags[Subnormal])
2230 self.assertTrue(c.flags[Underflow])
2231 c.clear_flags()
2232 self.assertRaises(Overflow, y.sqrt, context=None)
2233 self.assertTrue(c.flags[Overflow])
2234
2235 c.capitals = 0
2236 self.assertEqual(str(z.to_eng_string(context=None)), '1e-9999')
2237 c.capitals = 1
2238
2239
2240 ##### Binary functions
2241 c.clear_flags()
2242 ans = str(x.compare(Decimal('Nan891287828'), context=None))
2243 self.assertEqual(ans, 'NaN1287828')
2244 self.assertRaises(InvalidOperation, x.compare, Decimal('sNaN'), context=None)
2245 self.assertTrue(c.flags[InvalidOperation])
2246
2247 c.clear_flags()
2248 ans = str(x.compare_signal(8224, context=None))
2249 self.assertEqual(ans, '-1')
2250 self.assertRaises(InvalidOperation, x.compare_signal, Decimal('NaN'), context=None)
2251 self.assertTrue(c.flags[InvalidOperation])
2252
2253 c.clear_flags()
2254 ans = str(x.logical_and(101, context=None))
2255 self.assertEqual(ans, '101')
2256 self.assertRaises(InvalidOperation, x.logical_and, 123, context=None)
2257 self.assertTrue(c.flags[InvalidOperation])
2258
2259 c.clear_flags()
2260 ans = str(x.logical_or(101, context=None))
2261 self.assertEqual(ans, '111')
2262 self.assertRaises(InvalidOperation, x.logical_or, 123, context=None)
2263 self.assertTrue(c.flags[InvalidOperation])
2264
2265 c.clear_flags()
2266 ans = str(x.logical_xor(101, context=None))
2267 self.assertEqual(ans, '10')
2268 self.assertRaises(InvalidOperation, x.logical_xor, 123, context=None)
2269 self.assertTrue(c.flags[InvalidOperation])
2270
2271 c.clear_flags()
2272 ans = str(x.max(101, context=None))
2273 self.assertEqual(ans, '111')
2274 self.assertRaises(InvalidOperation, x.max, Decimal('sNaN'), context=None)
2275 self.assertTrue(c.flags[InvalidOperation])
2276
2277 c.clear_flags()
2278 ans = str(x.max_mag(101, context=None))
2279 self.assertEqual(ans, '111')
2280 self.assertRaises(InvalidOperation, x.max_mag, Decimal('sNaN'), context=None)
2281 self.assertTrue(c.flags[InvalidOperation])
2282
2283 c.clear_flags()
2284 ans = str(x.min(101, context=None))
2285 self.assertEqual(ans, '101')
2286 self.assertRaises(InvalidOperation, x.min, Decimal('sNaN'), context=None)
2287 self.assertTrue(c.flags[InvalidOperation])
2288
2289 c.clear_flags()
2290 ans = str(x.min_mag(101, context=None))
2291 self.assertEqual(ans, '101')
2292 self.assertRaises(InvalidOperation, x.min_mag, Decimal('sNaN'), context=None)
2293 self.assertTrue(c.flags[InvalidOperation])
2294
2295 c.clear_flags()
2296 ans = str(x.remainder_near(101, context=None))
2297 self.assertEqual(ans, '10')
2298 self.assertRaises(InvalidOperation, y.remainder_near, 101, context=None)
2299 self.assertTrue(c.flags[InvalidOperation])
2300
2301 c.clear_flags()
2302 ans = str(x.rotate(2, context=None))
2303 self.assertEqual(ans, '11100')
2304 self.assertRaises(InvalidOperation, x.rotate, 101, context=None)
2305 self.assertTrue(c.flags[InvalidOperation])
2306
2307 c.clear_flags()
2308 ans = str(x.scaleb(7, context=None))
2309 self.assertEqual(ans, '1.11E+9')
2310 self.assertRaises(InvalidOperation, x.scaleb, 10000, context=None)
2311 self.assertTrue(c.flags[InvalidOperation])
2312
2313 c.clear_flags()
2314 ans = str(x.shift(2, context=None))
2315 self.assertEqual(ans, '11100')
2316 self.assertRaises(InvalidOperation, x.shift, 10000, context=None)
2317 self.assertTrue(c.flags[InvalidOperation])
2318
2319
2320 ##### Ternary functions
2321 c.clear_flags()
2322 ans = str(x.fma(2, 3, context=None))
2323 self.assertEqual(ans, '225')
2324 self.assertRaises(Overflow, x.fma, Decimal('1e9999'), 3, context=None)
2325 self.assertTrue(c.flags[Overflow])
2326
2327
2328 ##### Special cases
2329 c.rounding = ROUND_HALF_EVEN
2330 ans = str(Decimal('1.5').to_integral(rounding=None, context=None))
2331 self.assertEqual(ans, '2')
2332 c.rounding = ROUND_DOWN
2333 ans = str(Decimal('1.5').to_integral(rounding=None, context=None))
2334 self.assertEqual(ans, '1')
2335 ans = str(Decimal('1.5').to_integral(rounding=ROUND_UP, context=None))
2336 self.assertEqual(ans, '2')
2337 c.clear_flags()
2338 self.assertRaises(InvalidOperation, Decimal('sNaN').to_integral, context=None)
2339 self.assertTrue(c.flags[InvalidOperation])
2340
2341 c.rounding = ROUND_HALF_EVEN
2342 ans = str(Decimal('1.5').to_integral_value(rounding=None, context=None))
2343 self.assertEqual(ans, '2')
2344 c.rounding = ROUND_DOWN
2345 ans = str(Decimal('1.5').to_integral_value(rounding=None, context=None))
2346 self.assertEqual(ans, '1')
2347 ans = str(Decimal('1.5').to_integral_value(rounding=ROUND_UP, context=None))
2348 self.assertEqual(ans, '2')
2349 c.clear_flags()
2350 self.assertRaises(InvalidOperation, Decimal('sNaN').to_integral_value, context=None)
2351 self.assertTrue(c.flags[InvalidOperation])
2352
2353 c.rounding = ROUND_HALF_EVEN
2354 ans = str(Decimal('1.5').to_integral_exact(rounding=None, context=None))
2355 self.assertEqual(ans, '2')
2356 c.rounding = ROUND_DOWN
2357 ans = str(Decimal('1.5').to_integral_exact(rounding=None, context=None))
2358 self.assertEqual(ans, '1')
2359 ans = str(Decimal('1.5').to_integral_exact(rounding=ROUND_UP, context=None))
2360 self.assertEqual(ans, '2')
2361 c.clear_flags()
2362 self.assertRaises(InvalidOperation, Decimal('sNaN').to_integral_exact, context=None)
2363 self.assertTrue(c.flags[InvalidOperation])
2364
2365 c.rounding = ROUND_UP
2366 ans = str(Decimal('1.50001').quantize(exp=Decimal('1e-3'), rounding=None, context=None))
2367 self.assertEqual(ans, '1.501')
2368 c.rounding = ROUND_DOWN
2369 ans = str(Decimal('1.50001').quantize(exp=Decimal('1e-3'), rounding=None, context=None))
2370 self.assertEqual(ans, '1.500')
2371 ans = str(Decimal('1.50001').quantize(exp=Decimal('1e-3'), rounding=ROUND_UP, context=None))
2372 self.assertEqual(ans, '1.501')
2373 c.clear_flags()
2374 self.assertRaises(InvalidOperation, y.quantize, Decimal('1e-10'), rounding=ROUND_UP, context=None)
2375 self.assertTrue(c.flags[InvalidOperation])
2376
2377 with localcontext(Context()) as context:
2378 context.prec = 7
2379 context.Emax = 999
2380 context.Emin = -999
2381 with localcontext(ctx=None) as c:
2382 self.assertEqual(c.prec, 7)
2383 self.assertEqual(c.Emax, 999)
2384 self.assertEqual(c.Emin, -999)
2385
Stefan Krah1919b7e2012-03-21 18:25:23 +01002386 def test_conversions_from_int(self):
2387 # Check that methods taking a second Decimal argument will
2388 # always accept an integer in place of a Decimal.
2389 Decimal = self.decimal.Decimal
2390
2391 self.assertEqual(Decimal(4).compare(3),
2392 Decimal(4).compare(Decimal(3)))
2393 self.assertEqual(Decimal(4).compare_signal(3),
2394 Decimal(4).compare_signal(Decimal(3)))
2395 self.assertEqual(Decimal(4).compare_total(3),
2396 Decimal(4).compare_total(Decimal(3)))
2397 self.assertEqual(Decimal(4).compare_total_mag(3),
2398 Decimal(4).compare_total_mag(Decimal(3)))
2399 self.assertEqual(Decimal(10101).logical_and(1001),
2400 Decimal(10101).logical_and(Decimal(1001)))
2401 self.assertEqual(Decimal(10101).logical_or(1001),
2402 Decimal(10101).logical_or(Decimal(1001)))
2403 self.assertEqual(Decimal(10101).logical_xor(1001),
2404 Decimal(10101).logical_xor(Decimal(1001)))
2405 self.assertEqual(Decimal(567).max(123),
2406 Decimal(567).max(Decimal(123)))
2407 self.assertEqual(Decimal(567).max_mag(123),
2408 Decimal(567).max_mag(Decimal(123)))
2409 self.assertEqual(Decimal(567).min(123),
2410 Decimal(567).min(Decimal(123)))
2411 self.assertEqual(Decimal(567).min_mag(123),
2412 Decimal(567).min_mag(Decimal(123)))
2413 self.assertEqual(Decimal(567).next_toward(123),
2414 Decimal(567).next_toward(Decimal(123)))
2415 self.assertEqual(Decimal(1234).quantize(100),
2416 Decimal(1234).quantize(Decimal(100)))
2417 self.assertEqual(Decimal(768).remainder_near(1234),
2418 Decimal(768).remainder_near(Decimal(1234)))
2419 self.assertEqual(Decimal(123).rotate(1),
2420 Decimal(123).rotate(Decimal(1)))
2421 self.assertEqual(Decimal(1234).same_quantum(1000),
2422 Decimal(1234).same_quantum(Decimal(1000)))
2423 self.assertEqual(Decimal('9.123').scaleb(-100),
2424 Decimal('9.123').scaleb(Decimal(-100)))
2425 self.assertEqual(Decimal(456).shift(-1),
2426 Decimal(456).shift(Decimal(-1)))
2427
2428 self.assertEqual(Decimal(-12).fma(Decimal(45), 67),
2429 Decimal(-12).fma(Decimal(45), Decimal(67)))
2430 self.assertEqual(Decimal(-12).fma(45, 67),
2431 Decimal(-12).fma(Decimal(45), Decimal(67)))
2432 self.assertEqual(Decimal(-12).fma(45, Decimal(67)),
2433 Decimal(-12).fma(Decimal(45), Decimal(67)))
2434
2435class CUsabilityTest(UsabilityTest):
2436 decimal = C
2437class PyUsabilityTest(UsabilityTest):
2438 decimal = P
2439
2440class PythonAPItests(unittest.TestCase):
2441
2442 def test_abc(self):
2443 Decimal = self.decimal.Decimal
2444
2445 self.assertTrue(issubclass(Decimal, numbers.Number))
2446 self.assertFalse(issubclass(Decimal, numbers.Real))
2447 self.assertIsInstance(Decimal(0), numbers.Number)
2448 self.assertNotIsInstance(Decimal(0), numbers.Real)
2449
2450 def test_pickle(self):
Serhiy Storchakabad12572014-12-15 14:03:42 +02002451 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
2452 Decimal = self.decimal.Decimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01002453
Serhiy Storchakabad12572014-12-15 14:03:42 +02002454 savedecimal = sys.modules['decimal']
Stefan Krah1919b7e2012-03-21 18:25:23 +01002455
Serhiy Storchakabad12572014-12-15 14:03:42 +02002456 # Round trip
2457 sys.modules['decimal'] = self.decimal
2458 d = Decimal('-3.141590000')
2459 p = pickle.dumps(d, proto)
2460 e = pickle.loads(p)
2461 self.assertEqual(d, e)
Stefan Krah1919b7e2012-03-21 18:25:23 +01002462
Serhiy Storchakabad12572014-12-15 14:03:42 +02002463 if C:
2464 # Test interchangeability
2465 x = C.Decimal('-3.123e81723')
2466 y = P.Decimal('-3.123e81723')
Stefan Krah1919b7e2012-03-21 18:25:23 +01002467
Serhiy Storchakabad12572014-12-15 14:03:42 +02002468 sys.modules['decimal'] = C
2469 sx = pickle.dumps(x, proto)
2470 sys.modules['decimal'] = P
2471 r = pickle.loads(sx)
2472 self.assertIsInstance(r, P.Decimal)
2473 self.assertEqual(r, y)
Stefan Krah1919b7e2012-03-21 18:25:23 +01002474
Serhiy Storchakabad12572014-12-15 14:03:42 +02002475 sys.modules['decimal'] = P
2476 sy = pickle.dumps(y, proto)
2477 sys.modules['decimal'] = C
2478 r = pickle.loads(sy)
2479 self.assertIsInstance(r, C.Decimal)
2480 self.assertEqual(r, x)
Stefan Krah1919b7e2012-03-21 18:25:23 +01002481
Serhiy Storchakabad12572014-12-15 14:03:42 +02002482 x = C.Decimal('-3.123e81723').as_tuple()
2483 y = P.Decimal('-3.123e81723').as_tuple()
Stefan Krahf1d4e422014-04-29 18:23:35 +02002484
Serhiy Storchakabad12572014-12-15 14:03:42 +02002485 sys.modules['decimal'] = C
2486 sx = pickle.dumps(x, proto)
2487 sys.modules['decimal'] = P
2488 r = pickle.loads(sx)
2489 self.assertIsInstance(r, P.DecimalTuple)
2490 self.assertEqual(r, y)
Stefan Krahf1d4e422014-04-29 18:23:35 +02002491
Serhiy Storchakabad12572014-12-15 14:03:42 +02002492 sys.modules['decimal'] = P
2493 sy = pickle.dumps(y, proto)
2494 sys.modules['decimal'] = C
2495 r = pickle.loads(sy)
2496 self.assertIsInstance(r, C.DecimalTuple)
2497 self.assertEqual(r, x)
Stefan Krahf1d4e422014-04-29 18:23:35 +02002498
Serhiy Storchakabad12572014-12-15 14:03:42 +02002499 sys.modules['decimal'] = savedecimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01002500
2501 def test_int(self):
2502 Decimal = self.decimal.Decimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01002503
2504 for x in range(-250, 250):
2505 s = '%0.2f' % (x / 100.0)
2506 # should work the same as for floats
2507 self.assertEqual(int(Decimal(s)), int(float(s)))
2508 # should work the same as to_integral in the ROUND_DOWN mode
2509 d = Decimal(s)
2510 r = d.to_integral(ROUND_DOWN)
2511 self.assertEqual(Decimal(int(d)), r)
2512
2513 self.assertRaises(ValueError, int, Decimal('-nan'))
2514 self.assertRaises(ValueError, int, Decimal('snan'))
2515 self.assertRaises(OverflowError, int, Decimal('inf'))
2516 self.assertRaises(OverflowError, int, Decimal('-inf'))
2517
2518 def test_trunc(self):
2519 Decimal = self.decimal.Decimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01002520
2521 for x in range(-250, 250):
2522 s = '%0.2f' % (x / 100.0)
2523 # should work the same as for floats
2524 self.assertEqual(int(Decimal(s)), int(float(s)))
2525 # should work the same as to_integral in the ROUND_DOWN mode
2526 d = Decimal(s)
2527 r = d.to_integral(ROUND_DOWN)
2528 self.assertEqual(Decimal(math.trunc(d)), r)
2529
2530 def test_from_float(self):
2531
2532 Decimal = self.decimal.Decimal
2533
2534 class MyDecimal(Decimal):
Stefan Krah6817c592016-06-20 12:10:13 +02002535 def __init__(self, _):
2536 self.x = 'y'
Stefan Krah1919b7e2012-03-21 18:25:23 +01002537
2538 self.assertTrue(issubclass(MyDecimal, Decimal))
2539
2540 r = MyDecimal.from_float(0.1)
2541 self.assertEqual(type(r), MyDecimal)
2542 self.assertEqual(str(r),
2543 '0.1000000000000000055511151231257827021181583404541015625')
Stefan Krah6817c592016-06-20 12:10:13 +02002544 self.assertEqual(r.x, 'y')
2545
Stefan Krah1919b7e2012-03-21 18:25:23 +01002546 bigint = 12345678901234567890123456789
2547 self.assertEqual(MyDecimal.from_float(bigint), MyDecimal(bigint))
2548 self.assertTrue(MyDecimal.from_float(float('nan')).is_qnan())
2549 self.assertTrue(MyDecimal.from_float(float('inf')).is_infinite())
2550 self.assertTrue(MyDecimal.from_float(float('-inf')).is_infinite())
2551 self.assertEqual(str(MyDecimal.from_float(float('nan'))),
2552 str(Decimal('NaN')))
2553 self.assertEqual(str(MyDecimal.from_float(float('inf'))),
2554 str(Decimal('Infinity')))
2555 self.assertEqual(str(MyDecimal.from_float(float('-inf'))),
2556 str(Decimal('-Infinity')))
2557 self.assertRaises(TypeError, MyDecimal.from_float, 'abc')
2558 for i in range(200):
2559 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
2560 self.assertEqual(x, float(MyDecimal.from_float(x))) # roundtrip
2561
2562 def test_create_decimal_from_float(self):
2563 Decimal = self.decimal.Decimal
2564 Context = self.decimal.Context
Stefan Krah1919b7e2012-03-21 18:25:23 +01002565 Inexact = self.decimal.Inexact
2566
2567 context = Context(prec=5, rounding=ROUND_DOWN)
2568 self.assertEqual(
2569 context.create_decimal_from_float(math.pi),
2570 Decimal('3.1415')
2571 )
2572 context = Context(prec=5, rounding=ROUND_UP)
2573 self.assertEqual(
2574 context.create_decimal_from_float(math.pi),
2575 Decimal('3.1416')
2576 )
2577 context = Context(prec=5, traps=[Inexact])
2578 self.assertRaises(
2579 Inexact,
2580 context.create_decimal_from_float,
2581 math.pi
2582 )
2583 self.assertEqual(repr(context.create_decimal_from_float(-0.0)),
2584 "Decimal('-0')")
2585 self.assertEqual(repr(context.create_decimal_from_float(1.0)),
2586 "Decimal('1')")
2587 self.assertEqual(repr(context.create_decimal_from_float(10)),
2588 "Decimal('10')")
2589
2590 def test_quantize(self):
2591 Decimal = self.decimal.Decimal
2592 Context = self.decimal.Context
2593 InvalidOperation = self.decimal.InvalidOperation
Stefan Krah1919b7e2012-03-21 18:25:23 +01002594
2595 c = Context(Emax=99999, Emin=-99999)
2596 self.assertEqual(
2597 Decimal('7.335').quantize(Decimal('.01')),
2598 Decimal('7.34')
2599 )
2600 self.assertEqual(
2601 Decimal('7.335').quantize(Decimal('.01'), rounding=ROUND_DOWN),
2602 Decimal('7.33')
2603 )
2604 self.assertRaises(
2605 InvalidOperation,
2606 Decimal("10e99999").quantize, Decimal('1e100000'), context=c
2607 )
2608
2609 c = Context()
2610 d = Decimal("0.871831e800")
2611 x = d.quantize(context=c, exp=Decimal("1e797"), rounding=ROUND_DOWN)
2612 self.assertEqual(x, Decimal('8.71E+799'))
2613
2614 def test_complex(self):
2615 Decimal = self.decimal.Decimal
2616
2617 x = Decimal("9.8182731e181273")
2618 self.assertEqual(x.real, x)
2619 self.assertEqual(x.imag, 0)
2620 self.assertEqual(x.conjugate(), x)
2621
2622 x = Decimal("1")
2623 self.assertEqual(complex(x), complex(float(1)))
2624
2625 self.assertRaises(AttributeError, setattr, x, 'real', 100)
2626 self.assertRaises(AttributeError, setattr, x, 'imag', 100)
2627 self.assertRaises(AttributeError, setattr, x, 'conjugate', 100)
2628 self.assertRaises(AttributeError, setattr, x, '__complex__', 100)
2629
2630 def test_named_parameters(self):
2631 D = self.decimal.Decimal
2632 Context = self.decimal.Context
2633 localcontext = self.decimal.localcontext
2634 InvalidOperation = self.decimal.InvalidOperation
2635 Overflow = self.decimal.Overflow
2636
2637 xc = Context()
2638 xc.prec = 1
2639 xc.Emax = 1
2640 xc.Emin = -1
2641
2642 with localcontext() as c:
2643 c.clear_flags()
2644
2645 self.assertEqual(D(9, xc), 9)
2646 self.assertEqual(D(9, context=xc), 9)
2647 self.assertEqual(D(context=xc, value=9), 9)
2648 self.assertEqual(D(context=xc), 0)
2649 xc.clear_flags()
2650 self.assertRaises(InvalidOperation, D, "xyz", context=xc)
2651 self.assertTrue(xc.flags[InvalidOperation])
2652 self.assertFalse(c.flags[InvalidOperation])
2653
2654 xc.clear_flags()
2655 self.assertEqual(D(2).exp(context=xc), 7)
2656 self.assertRaises(Overflow, D(8).exp, context=xc)
2657 self.assertTrue(xc.flags[Overflow])
2658 self.assertFalse(c.flags[Overflow])
2659
2660 xc.clear_flags()
2661 self.assertEqual(D(2).ln(context=xc), D('0.7'))
2662 self.assertRaises(InvalidOperation, D(-1).ln, context=xc)
2663 self.assertTrue(xc.flags[InvalidOperation])
2664 self.assertFalse(c.flags[InvalidOperation])
2665
2666 self.assertEqual(D(0).log10(context=xc), D('-inf'))
2667 self.assertEqual(D(-1).next_minus(context=xc), -2)
2668 self.assertEqual(D(-1).next_plus(context=xc), D('-0.9'))
2669 self.assertEqual(D("9.73").normalize(context=xc), D('1E+1'))
2670 self.assertEqual(D("9999").to_integral(context=xc), 9999)
2671 self.assertEqual(D("-2000").to_integral_exact(context=xc), -2000)
2672 self.assertEqual(D("123").to_integral_value(context=xc), 123)
2673 self.assertEqual(D("0.0625").sqrt(context=xc), D('0.2'))
2674
2675 self.assertEqual(D("0.0625").compare(context=xc, other=3), -1)
2676 xc.clear_flags()
2677 self.assertRaises(InvalidOperation,
2678 D("0").compare_signal, D('nan'), context=xc)
2679 self.assertTrue(xc.flags[InvalidOperation])
2680 self.assertFalse(c.flags[InvalidOperation])
2681 self.assertEqual(D("0.01").max(D('0.0101'), context=xc), D('0.0'))
2682 self.assertEqual(D("0.01").max(D('0.0101'), context=xc), D('0.0'))
2683 self.assertEqual(D("0.2").max_mag(D('-0.3'), context=xc),
2684 D('-0.3'))
2685 self.assertEqual(D("0.02").min(D('-0.03'), context=xc), D('-0.0'))
2686 self.assertEqual(D("0.02").min_mag(D('-0.03'), context=xc),
2687 D('0.0'))
2688 self.assertEqual(D("0.2").next_toward(D('-1'), context=xc), D('0.1'))
2689 xc.clear_flags()
2690 self.assertRaises(InvalidOperation,
2691 D("0.2").quantize, D('1e10'), context=xc)
2692 self.assertTrue(xc.flags[InvalidOperation])
2693 self.assertFalse(c.flags[InvalidOperation])
2694 self.assertEqual(D("9.99").remainder_near(D('1.5'), context=xc),
2695 D('-0.5'))
2696
2697 self.assertEqual(D("9.9").fma(third=D('0.9'), context=xc, other=7),
2698 D('7E+1'))
2699
2700 self.assertRaises(TypeError, D(1).is_canonical, context=xc)
2701 self.assertRaises(TypeError, D(1).is_finite, context=xc)
2702 self.assertRaises(TypeError, D(1).is_infinite, context=xc)
2703 self.assertRaises(TypeError, D(1).is_nan, context=xc)
2704 self.assertRaises(TypeError, D(1).is_qnan, context=xc)
2705 self.assertRaises(TypeError, D(1).is_snan, context=xc)
2706 self.assertRaises(TypeError, D(1).is_signed, context=xc)
2707 self.assertRaises(TypeError, D(1).is_zero, context=xc)
2708
2709 self.assertFalse(D("0.01").is_normal(context=xc))
2710 self.assertTrue(D("0.01").is_subnormal(context=xc))
2711
2712 self.assertRaises(TypeError, D(1).adjusted, context=xc)
2713 self.assertRaises(TypeError, D(1).conjugate, context=xc)
2714 self.assertRaises(TypeError, D(1).radix, context=xc)
2715
2716 self.assertEqual(D(-111).logb(context=xc), 2)
2717 self.assertEqual(D(0).logical_invert(context=xc), 1)
2718 self.assertEqual(D('0.01').number_class(context=xc), '+Subnormal')
2719 self.assertEqual(D('0.21').to_eng_string(context=xc), '0.21')
2720
2721 self.assertEqual(D('11').logical_and(D('10'), context=xc), 0)
2722 self.assertEqual(D('11').logical_or(D('10'), context=xc), 1)
2723 self.assertEqual(D('01').logical_xor(D('10'), context=xc), 1)
2724 self.assertEqual(D('23').rotate(1, context=xc), 3)
2725 self.assertEqual(D('23').rotate(1, context=xc), 3)
2726 xc.clear_flags()
2727 self.assertRaises(Overflow,
2728 D('23').scaleb, 1, context=xc)
2729 self.assertTrue(xc.flags[Overflow])
2730 self.assertFalse(c.flags[Overflow])
2731 self.assertEqual(D('23').shift(-1, context=xc), 0)
2732
2733 self.assertRaises(TypeError, D.from_float, 1.1, context=xc)
2734 self.assertRaises(TypeError, D(0).as_tuple, context=xc)
2735
Stefan Krah040e3112012-12-15 22:33:33 +01002736 self.assertEqual(D(1).canonical(), 1)
2737 self.assertRaises(TypeError, D("-1").copy_abs, context=xc)
2738 self.assertRaises(TypeError, D("-1").copy_negate, context=xc)
2739 self.assertRaises(TypeError, D(1).canonical, context="x")
2740 self.assertRaises(TypeError, D(1).canonical, xyz="x")
Stefan Krah1919b7e2012-03-21 18:25:23 +01002741
Stefan Krahb6405ef2012-03-23 14:46:48 +01002742 def test_exception_hierarchy(self):
2743
2744 decimal = self.decimal
2745 DecimalException = decimal.DecimalException
2746 InvalidOperation = decimal.InvalidOperation
2747 FloatOperation = decimal.FloatOperation
2748 DivisionByZero = decimal.DivisionByZero
2749 Overflow = decimal.Overflow
2750 Underflow = decimal.Underflow
2751 Subnormal = decimal.Subnormal
2752 Inexact = decimal.Inexact
2753 Rounded = decimal.Rounded
2754 Clamped = decimal.Clamped
2755
2756 self.assertTrue(issubclass(DecimalException, ArithmeticError))
2757
2758 self.assertTrue(issubclass(InvalidOperation, DecimalException))
2759 self.assertTrue(issubclass(FloatOperation, DecimalException))
2760 self.assertTrue(issubclass(FloatOperation, TypeError))
2761 self.assertTrue(issubclass(DivisionByZero, DecimalException))
2762 self.assertTrue(issubclass(DivisionByZero, ZeroDivisionError))
2763 self.assertTrue(issubclass(Overflow, Rounded))
2764 self.assertTrue(issubclass(Overflow, Inexact))
2765 self.assertTrue(issubclass(Overflow, DecimalException))
2766 self.assertTrue(issubclass(Underflow, Inexact))
2767 self.assertTrue(issubclass(Underflow, Rounded))
2768 self.assertTrue(issubclass(Underflow, Subnormal))
2769 self.assertTrue(issubclass(Underflow, DecimalException))
2770
2771 self.assertTrue(issubclass(Subnormal, DecimalException))
2772 self.assertTrue(issubclass(Inexact, DecimalException))
2773 self.assertTrue(issubclass(Rounded, DecimalException))
2774 self.assertTrue(issubclass(Clamped, DecimalException))
2775
2776 self.assertTrue(issubclass(decimal.ConversionSyntax, InvalidOperation))
2777 self.assertTrue(issubclass(decimal.DivisionImpossible, InvalidOperation))
2778 self.assertTrue(issubclass(decimal.DivisionUndefined, InvalidOperation))
2779 self.assertTrue(issubclass(decimal.DivisionUndefined, ZeroDivisionError))
2780 self.assertTrue(issubclass(decimal.InvalidContext, InvalidOperation))
2781
Stefan Krah1919b7e2012-03-21 18:25:23 +01002782class CPythonAPItests(PythonAPItests):
2783 decimal = C
2784class PyPythonAPItests(PythonAPItests):
2785 decimal = P
2786
2787class ContextAPItests(unittest.TestCase):
2788
Stefan Krah9a4ff432012-12-16 21:10:35 +01002789 def test_none_args(self):
2790 Context = self.decimal.Context
2791 InvalidOperation = self.decimal.InvalidOperation
2792 DivisionByZero = self.decimal.DivisionByZero
2793 Overflow = self.decimal.Overflow
Stefan Krah9a4ff432012-12-16 21:10:35 +01002794
2795 c1 = Context()
2796 c2 = Context(prec=None, rounding=None, Emax=None, Emin=None,
2797 capitals=None, clamp=None, flags=None, traps=None)
2798 for c in [c1, c2]:
2799 self.assertEqual(c.prec, 28)
2800 self.assertEqual(c.rounding, ROUND_HALF_EVEN)
2801 self.assertEqual(c.Emax, 999999)
2802 self.assertEqual(c.Emin, -999999)
2803 self.assertEqual(c.capitals, 1)
2804 self.assertEqual(c.clamp, 0)
2805 assert_signals(self, c, 'flags', [])
2806 assert_signals(self, c, 'traps', [InvalidOperation, DivisionByZero,
2807 Overflow])
2808
Stefan Krah59a4a932013-01-16 12:58:59 +01002809 @cpython_only
2810 def test_from_legacy_strings(self):
2811 import _testcapi
2812 c = self.decimal.Context()
2813
2814 for rnd in RoundingModes:
2815 c.rounding = _testcapi.unicode_legacy_string(rnd)
2816 self.assertEqual(c.rounding, rnd)
2817
2818 s = _testcapi.unicode_legacy_string('')
2819 self.assertRaises(TypeError, setattr, c, 'rounding', s)
2820
2821 s = _testcapi.unicode_legacy_string('ROUND_\x00UP')
2822 self.assertRaises(TypeError, setattr, c, 'rounding', s)
2823
Stefan Krah1919b7e2012-03-21 18:25:23 +01002824 def test_pickle(self):
2825
Serhiy Storchakabad12572014-12-15 14:03:42 +02002826 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
2827 Context = self.decimal.Context
Stefan Krah1919b7e2012-03-21 18:25:23 +01002828
Serhiy Storchakabad12572014-12-15 14:03:42 +02002829 savedecimal = sys.modules['decimal']
Stefan Krah1919b7e2012-03-21 18:25:23 +01002830
Serhiy Storchakabad12572014-12-15 14:03:42 +02002831 # Round trip
2832 sys.modules['decimal'] = self.decimal
2833 c = Context()
2834 e = pickle.loads(pickle.dumps(c, proto))
Stefan Krah1919b7e2012-03-21 18:25:23 +01002835
Serhiy Storchakabad12572014-12-15 14:03:42 +02002836 self.assertEqual(c.prec, e.prec)
2837 self.assertEqual(c.Emin, e.Emin)
2838 self.assertEqual(c.Emax, e.Emax)
2839 self.assertEqual(c.rounding, e.rounding)
2840 self.assertEqual(c.capitals, e.capitals)
2841 self.assertEqual(c.clamp, e.clamp)
2842 self.assertEqual(c.flags, e.flags)
2843 self.assertEqual(c.traps, e.traps)
Stefan Krah1919b7e2012-03-21 18:25:23 +01002844
Serhiy Storchakabad12572014-12-15 14:03:42 +02002845 # Test interchangeability
2846 combinations = [(C, P), (P, C)] if C else [(P, P)]
2847 for dumper, loader in combinations:
2848 for ri, _ in enumerate(RoundingModes):
2849 for fi, _ in enumerate(OrderedSignals[dumper]):
2850 for ti, _ in enumerate(OrderedSignals[dumper]):
Stefan Krah1919b7e2012-03-21 18:25:23 +01002851
Serhiy Storchakabad12572014-12-15 14:03:42 +02002852 prec = random.randrange(1, 100)
2853 emin = random.randrange(-100, 0)
2854 emax = random.randrange(1, 100)
2855 caps = random.randrange(2)
2856 clamp = random.randrange(2)
Stefan Krah1919b7e2012-03-21 18:25:23 +01002857
Serhiy Storchakabad12572014-12-15 14:03:42 +02002858 # One module dumps
2859 sys.modules['decimal'] = dumper
2860 c = dumper.Context(
2861 prec=prec, Emin=emin, Emax=emax,
2862 rounding=RoundingModes[ri],
2863 capitals=caps, clamp=clamp,
2864 flags=OrderedSignals[dumper][:fi],
2865 traps=OrderedSignals[dumper][:ti]
2866 )
2867 s = pickle.dumps(c, proto)
Stefan Krah1919b7e2012-03-21 18:25:23 +01002868
Serhiy Storchakabad12572014-12-15 14:03:42 +02002869 # The other module loads
2870 sys.modules['decimal'] = loader
2871 d = pickle.loads(s)
2872 self.assertIsInstance(d, loader.Context)
Stefan Krah1919b7e2012-03-21 18:25:23 +01002873
Serhiy Storchakabad12572014-12-15 14:03:42 +02002874 self.assertEqual(d.prec, prec)
2875 self.assertEqual(d.Emin, emin)
2876 self.assertEqual(d.Emax, emax)
2877 self.assertEqual(d.rounding, RoundingModes[ri])
2878 self.assertEqual(d.capitals, caps)
2879 self.assertEqual(d.clamp, clamp)
2880 assert_signals(self, d, 'flags', OrderedSignals[loader][:fi])
2881 assert_signals(self, d, 'traps', OrderedSignals[loader][:ti])
Stefan Krah1919b7e2012-03-21 18:25:23 +01002882
Serhiy Storchakabad12572014-12-15 14:03:42 +02002883 sys.modules['decimal'] = savedecimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01002884
2885 def test_equality_with_other_types(self):
2886 Decimal = self.decimal.Decimal
2887
2888 self.assertIn(Decimal(10), ['a', 1.0, Decimal(10), (1,2), {}])
2889 self.assertNotIn(Decimal(10), ['a', 1.0, (1,2), {}])
2890
2891 def test_copy(self):
2892 # All copies should be deep
2893 Decimal = self.decimal.Decimal
2894 Context = self.decimal.Context
2895
2896 c = Context()
2897 d = c.copy()
2898 self.assertNotEqual(id(c), id(d))
2899 self.assertNotEqual(id(c.flags), id(d.flags))
2900 self.assertNotEqual(id(c.traps), id(d.traps))
2901 k1 = set(c.flags.keys())
2902 k2 = set(d.flags.keys())
2903 self.assertEqual(k1, k2)
2904 self.assertEqual(c.flags, d.flags)
2905
2906 def test__clamp(self):
2907 # In Python 3.2, the private attribute `_clamp` was made
2908 # public (issue 8540), with the old `_clamp` becoming a
2909 # property wrapping `clamp`. For the duration of Python 3.2
2910 # only, the attribute should be gettable/settable via both
2911 # `clamp` and `_clamp`; in Python 3.3, `_clamp` should be
2912 # removed.
2913 Context = self.decimal.Context
2914 c = Context()
2915 self.assertRaises(AttributeError, getattr, c, '_clamp')
2916
2917 def test_abs(self):
2918 Decimal = self.decimal.Decimal
2919 Context = self.decimal.Context
2920
2921 c = Context()
2922 d = c.abs(Decimal(-1))
2923 self.assertEqual(c.abs(-1), d)
2924 self.assertRaises(TypeError, c.abs, '-1')
2925
2926 def test_add(self):
2927 Decimal = self.decimal.Decimal
2928 Context = self.decimal.Context
2929
2930 c = Context()
2931 d = c.add(Decimal(1), Decimal(1))
2932 self.assertEqual(c.add(1, 1), d)
2933 self.assertEqual(c.add(Decimal(1), 1), d)
2934 self.assertEqual(c.add(1, Decimal(1)), d)
2935 self.assertRaises(TypeError, c.add, '1', 1)
2936 self.assertRaises(TypeError, c.add, 1, '1')
2937
2938 def test_compare(self):
2939 Decimal = self.decimal.Decimal
2940 Context = self.decimal.Context
2941
2942 c = Context()
2943 d = c.compare(Decimal(1), Decimal(1))
2944 self.assertEqual(c.compare(1, 1), d)
2945 self.assertEqual(c.compare(Decimal(1), 1), d)
2946 self.assertEqual(c.compare(1, Decimal(1)), d)
2947 self.assertRaises(TypeError, c.compare, '1', 1)
2948 self.assertRaises(TypeError, c.compare, 1, '1')
2949
2950 def test_compare_signal(self):
2951 Decimal = self.decimal.Decimal
2952 Context = self.decimal.Context
2953
2954 c = Context()
2955 d = c.compare_signal(Decimal(1), Decimal(1))
2956 self.assertEqual(c.compare_signal(1, 1), d)
2957 self.assertEqual(c.compare_signal(Decimal(1), 1), d)
2958 self.assertEqual(c.compare_signal(1, Decimal(1)), d)
2959 self.assertRaises(TypeError, c.compare_signal, '1', 1)
2960 self.assertRaises(TypeError, c.compare_signal, 1, '1')
2961
2962 def test_compare_total(self):
2963 Decimal = self.decimal.Decimal
2964 Context = self.decimal.Context
2965
2966 c = Context()
2967 d = c.compare_total(Decimal(1), Decimal(1))
2968 self.assertEqual(c.compare_total(1, 1), d)
2969 self.assertEqual(c.compare_total(Decimal(1), 1), d)
2970 self.assertEqual(c.compare_total(1, Decimal(1)), d)
2971 self.assertRaises(TypeError, c.compare_total, '1', 1)
2972 self.assertRaises(TypeError, c.compare_total, 1, '1')
2973
2974 def test_compare_total_mag(self):
2975 Decimal = self.decimal.Decimal
2976 Context = self.decimal.Context
2977
2978 c = Context()
2979 d = c.compare_total_mag(Decimal(1), Decimal(1))
2980 self.assertEqual(c.compare_total_mag(1, 1), d)
2981 self.assertEqual(c.compare_total_mag(Decimal(1), 1), d)
2982 self.assertEqual(c.compare_total_mag(1, Decimal(1)), d)
2983 self.assertRaises(TypeError, c.compare_total_mag, '1', 1)
2984 self.assertRaises(TypeError, c.compare_total_mag, 1, '1')
2985
2986 def test_copy_abs(self):
2987 Decimal = self.decimal.Decimal
2988 Context = self.decimal.Context
2989
2990 c = Context()
2991 d = c.copy_abs(Decimal(-1))
2992 self.assertEqual(c.copy_abs(-1), d)
2993 self.assertRaises(TypeError, c.copy_abs, '-1')
2994
2995 def test_copy_decimal(self):
2996 Decimal = self.decimal.Decimal
2997 Context = self.decimal.Context
2998
2999 c = Context()
3000 d = c.copy_decimal(Decimal(-1))
3001 self.assertEqual(c.copy_decimal(-1), d)
3002 self.assertRaises(TypeError, c.copy_decimal, '-1')
3003
3004 def test_copy_negate(self):
3005 Decimal = self.decimal.Decimal
3006 Context = self.decimal.Context
3007
3008 c = Context()
3009 d = c.copy_negate(Decimal(-1))
3010 self.assertEqual(c.copy_negate(-1), d)
3011 self.assertRaises(TypeError, c.copy_negate, '-1')
3012
3013 def test_copy_sign(self):
3014 Decimal = self.decimal.Decimal
3015 Context = self.decimal.Context
3016
3017 c = Context()
3018 d = c.copy_sign(Decimal(1), Decimal(-2))
3019 self.assertEqual(c.copy_sign(1, -2), d)
3020 self.assertEqual(c.copy_sign(Decimal(1), -2), d)
3021 self.assertEqual(c.copy_sign(1, Decimal(-2)), d)
3022 self.assertRaises(TypeError, c.copy_sign, '1', -2)
3023 self.assertRaises(TypeError, c.copy_sign, 1, '-2')
3024
3025 def test_divide(self):
3026 Decimal = self.decimal.Decimal
3027 Context = self.decimal.Context
3028
3029 c = Context()
3030 d = c.divide(Decimal(1), Decimal(2))
3031 self.assertEqual(c.divide(1, 2), d)
3032 self.assertEqual(c.divide(Decimal(1), 2), d)
3033 self.assertEqual(c.divide(1, Decimal(2)), d)
3034 self.assertRaises(TypeError, c.divide, '1', 2)
3035 self.assertRaises(TypeError, c.divide, 1, '2')
3036
3037 def test_divide_int(self):
3038 Decimal = self.decimal.Decimal
3039 Context = self.decimal.Context
3040
3041 c = Context()
3042 d = c.divide_int(Decimal(1), Decimal(2))
3043 self.assertEqual(c.divide_int(1, 2), d)
3044 self.assertEqual(c.divide_int(Decimal(1), 2), d)
3045 self.assertEqual(c.divide_int(1, Decimal(2)), d)
3046 self.assertRaises(TypeError, c.divide_int, '1', 2)
3047 self.assertRaises(TypeError, c.divide_int, 1, '2')
3048
3049 def test_divmod(self):
3050 Decimal = self.decimal.Decimal
3051 Context = self.decimal.Context
3052
3053 c = Context()
3054 d = c.divmod(Decimal(1), Decimal(2))
3055 self.assertEqual(c.divmod(1, 2), d)
3056 self.assertEqual(c.divmod(Decimal(1), 2), d)
3057 self.assertEqual(c.divmod(1, Decimal(2)), d)
3058 self.assertRaises(TypeError, c.divmod, '1', 2)
3059 self.assertRaises(TypeError, c.divmod, 1, '2')
3060
3061 def test_exp(self):
3062 Decimal = self.decimal.Decimal
3063 Context = self.decimal.Context
3064
3065 c = Context()
3066 d = c.exp(Decimal(10))
3067 self.assertEqual(c.exp(10), d)
3068 self.assertRaises(TypeError, c.exp, '10')
3069
3070 def test_fma(self):
3071 Decimal = self.decimal.Decimal
3072 Context = self.decimal.Context
3073
3074 c = Context()
3075 d = c.fma(Decimal(2), Decimal(3), Decimal(4))
3076 self.assertEqual(c.fma(2, 3, 4), d)
3077 self.assertEqual(c.fma(Decimal(2), 3, 4), d)
3078 self.assertEqual(c.fma(2, Decimal(3), 4), d)
3079 self.assertEqual(c.fma(2, 3, Decimal(4)), d)
3080 self.assertEqual(c.fma(Decimal(2), Decimal(3), 4), d)
3081 self.assertRaises(TypeError, c.fma, '2', 3, 4)
3082 self.assertRaises(TypeError, c.fma, 2, '3', 4)
3083 self.assertRaises(TypeError, c.fma, 2, 3, '4')
3084
3085 # Issue 12079 for Context.fma ...
3086 self.assertRaises(TypeError, c.fma,
3087 Decimal('Infinity'), Decimal(0), "not a decimal")
3088 self.assertRaises(TypeError, c.fma,
3089 Decimal(1), Decimal('snan'), 1.222)
3090 # ... and for Decimal.fma.
3091 self.assertRaises(TypeError, Decimal('Infinity').fma,
3092 Decimal(0), "not a decimal")
3093 self.assertRaises(TypeError, Decimal(1).fma,
3094 Decimal('snan'), 1.222)
3095
3096 def test_is_finite(self):
3097 Decimal = self.decimal.Decimal
3098 Context = self.decimal.Context
3099
3100 c = Context()
3101 d = c.is_finite(Decimal(10))
3102 self.assertEqual(c.is_finite(10), d)
3103 self.assertRaises(TypeError, c.is_finite, '10')
3104
3105 def test_is_infinite(self):
3106 Decimal = self.decimal.Decimal
3107 Context = self.decimal.Context
3108
3109 c = Context()
3110 d = c.is_infinite(Decimal(10))
3111 self.assertEqual(c.is_infinite(10), d)
3112 self.assertRaises(TypeError, c.is_infinite, '10')
3113
3114 def test_is_nan(self):
3115 Decimal = self.decimal.Decimal
3116 Context = self.decimal.Context
3117
3118 c = Context()
3119 d = c.is_nan(Decimal(10))
3120 self.assertEqual(c.is_nan(10), d)
3121 self.assertRaises(TypeError, c.is_nan, '10')
3122
3123 def test_is_normal(self):
3124 Decimal = self.decimal.Decimal
3125 Context = self.decimal.Context
3126
3127 c = Context()
3128 d = c.is_normal(Decimal(10))
3129 self.assertEqual(c.is_normal(10), d)
3130 self.assertRaises(TypeError, c.is_normal, '10')
3131
3132 def test_is_qnan(self):
3133 Decimal = self.decimal.Decimal
3134 Context = self.decimal.Context
3135
3136 c = Context()
3137 d = c.is_qnan(Decimal(10))
3138 self.assertEqual(c.is_qnan(10), d)
3139 self.assertRaises(TypeError, c.is_qnan, '10')
3140
3141 def test_is_signed(self):
3142 Decimal = self.decimal.Decimal
3143 Context = self.decimal.Context
3144
3145 c = Context()
3146 d = c.is_signed(Decimal(10))
3147 self.assertEqual(c.is_signed(10), d)
3148 self.assertRaises(TypeError, c.is_signed, '10')
3149
3150 def test_is_snan(self):
3151 Decimal = self.decimal.Decimal
3152 Context = self.decimal.Context
3153
3154 c = Context()
3155 d = c.is_snan(Decimal(10))
3156 self.assertEqual(c.is_snan(10), d)
3157 self.assertRaises(TypeError, c.is_snan, '10')
3158
3159 def test_is_subnormal(self):
3160 Decimal = self.decimal.Decimal
3161 Context = self.decimal.Context
3162
3163 c = Context()
3164 d = c.is_subnormal(Decimal(10))
3165 self.assertEqual(c.is_subnormal(10), d)
3166 self.assertRaises(TypeError, c.is_subnormal, '10')
3167
3168 def test_is_zero(self):
3169 Decimal = self.decimal.Decimal
3170 Context = self.decimal.Context
3171
3172 c = Context()
3173 d = c.is_zero(Decimal(10))
3174 self.assertEqual(c.is_zero(10), d)
3175 self.assertRaises(TypeError, c.is_zero, '10')
3176
3177 def test_ln(self):
3178 Decimal = self.decimal.Decimal
3179 Context = self.decimal.Context
3180
3181 c = Context()
3182 d = c.ln(Decimal(10))
3183 self.assertEqual(c.ln(10), d)
3184 self.assertRaises(TypeError, c.ln, '10')
3185
3186 def test_log10(self):
3187 Decimal = self.decimal.Decimal
3188 Context = self.decimal.Context
3189
3190 c = Context()
3191 d = c.log10(Decimal(10))
3192 self.assertEqual(c.log10(10), d)
3193 self.assertRaises(TypeError, c.log10, '10')
3194
3195 def test_logb(self):
3196 Decimal = self.decimal.Decimal
3197 Context = self.decimal.Context
3198
3199 c = Context()
3200 d = c.logb(Decimal(10))
3201 self.assertEqual(c.logb(10), d)
3202 self.assertRaises(TypeError, c.logb, '10')
3203
3204 def test_logical_and(self):
3205 Decimal = self.decimal.Decimal
3206 Context = self.decimal.Context
3207
3208 c = Context()
3209 d = c.logical_and(Decimal(1), Decimal(1))
3210 self.assertEqual(c.logical_and(1, 1), d)
3211 self.assertEqual(c.logical_and(Decimal(1), 1), d)
3212 self.assertEqual(c.logical_and(1, Decimal(1)), d)
3213 self.assertRaises(TypeError, c.logical_and, '1', 1)
3214 self.assertRaises(TypeError, c.logical_and, 1, '1')
3215
3216 def test_logical_invert(self):
3217 Decimal = self.decimal.Decimal
3218 Context = self.decimal.Context
3219
3220 c = Context()
3221 d = c.logical_invert(Decimal(1000))
3222 self.assertEqual(c.logical_invert(1000), d)
3223 self.assertRaises(TypeError, c.logical_invert, '1000')
3224
3225 def test_logical_or(self):
3226 Decimal = self.decimal.Decimal
3227 Context = self.decimal.Context
3228
3229 c = Context()
3230 d = c.logical_or(Decimal(1), Decimal(1))
3231 self.assertEqual(c.logical_or(1, 1), d)
3232 self.assertEqual(c.logical_or(Decimal(1), 1), d)
3233 self.assertEqual(c.logical_or(1, Decimal(1)), d)
3234 self.assertRaises(TypeError, c.logical_or, '1', 1)
3235 self.assertRaises(TypeError, c.logical_or, 1, '1')
3236
3237 def test_logical_xor(self):
3238 Decimal = self.decimal.Decimal
3239 Context = self.decimal.Context
3240
3241 c = Context()
3242 d = c.logical_xor(Decimal(1), Decimal(1))
3243 self.assertEqual(c.logical_xor(1, 1), d)
3244 self.assertEqual(c.logical_xor(Decimal(1), 1), d)
3245 self.assertEqual(c.logical_xor(1, Decimal(1)), d)
3246 self.assertRaises(TypeError, c.logical_xor, '1', 1)
3247 self.assertRaises(TypeError, c.logical_xor, 1, '1')
3248
3249 def test_max(self):
3250 Decimal = self.decimal.Decimal
3251 Context = self.decimal.Context
3252
3253 c = Context()
3254 d = c.max(Decimal(1), Decimal(2))
3255 self.assertEqual(c.max(1, 2), d)
3256 self.assertEqual(c.max(Decimal(1), 2), d)
3257 self.assertEqual(c.max(1, Decimal(2)), d)
3258 self.assertRaises(TypeError, c.max, '1', 2)
3259 self.assertRaises(TypeError, c.max, 1, '2')
3260
3261 def test_max_mag(self):
3262 Decimal = self.decimal.Decimal
3263 Context = self.decimal.Context
3264
3265 c = Context()
3266 d = c.max_mag(Decimal(1), Decimal(2))
3267 self.assertEqual(c.max_mag(1, 2), d)
3268 self.assertEqual(c.max_mag(Decimal(1), 2), d)
3269 self.assertEqual(c.max_mag(1, Decimal(2)), d)
3270 self.assertRaises(TypeError, c.max_mag, '1', 2)
3271 self.assertRaises(TypeError, c.max_mag, 1, '2')
3272
3273 def test_min(self):
3274 Decimal = self.decimal.Decimal
3275 Context = self.decimal.Context
3276
3277 c = Context()
3278 d = c.min(Decimal(1), Decimal(2))
3279 self.assertEqual(c.min(1, 2), d)
3280 self.assertEqual(c.min(Decimal(1), 2), d)
3281 self.assertEqual(c.min(1, Decimal(2)), d)
3282 self.assertRaises(TypeError, c.min, '1', 2)
3283 self.assertRaises(TypeError, c.min, 1, '2')
3284
3285 def test_min_mag(self):
3286 Decimal = self.decimal.Decimal
3287 Context = self.decimal.Context
3288
3289 c = Context()
3290 d = c.min_mag(Decimal(1), Decimal(2))
3291 self.assertEqual(c.min_mag(1, 2), d)
3292 self.assertEqual(c.min_mag(Decimal(1), 2), d)
3293 self.assertEqual(c.min_mag(1, Decimal(2)), d)
3294 self.assertRaises(TypeError, c.min_mag, '1', 2)
3295 self.assertRaises(TypeError, c.min_mag, 1, '2')
3296
3297 def test_minus(self):
3298 Decimal = self.decimal.Decimal
3299 Context = self.decimal.Context
3300
3301 c = Context()
3302 d = c.minus(Decimal(10))
3303 self.assertEqual(c.minus(10), d)
3304 self.assertRaises(TypeError, c.minus, '10')
3305
3306 def test_multiply(self):
3307 Decimal = self.decimal.Decimal
3308 Context = self.decimal.Context
3309
3310 c = Context()
3311 d = c.multiply(Decimal(1), Decimal(2))
3312 self.assertEqual(c.multiply(1, 2), d)
3313 self.assertEqual(c.multiply(Decimal(1), 2), d)
3314 self.assertEqual(c.multiply(1, Decimal(2)), d)
3315 self.assertRaises(TypeError, c.multiply, '1', 2)
3316 self.assertRaises(TypeError, c.multiply, 1, '2')
3317
3318 def test_next_minus(self):
3319 Decimal = self.decimal.Decimal
3320 Context = self.decimal.Context
3321
3322 c = Context()
3323 d = c.next_minus(Decimal(10))
3324 self.assertEqual(c.next_minus(10), d)
3325 self.assertRaises(TypeError, c.next_minus, '10')
3326
3327 def test_next_plus(self):
3328 Decimal = self.decimal.Decimal
3329 Context = self.decimal.Context
3330
3331 c = Context()
3332 d = c.next_plus(Decimal(10))
3333 self.assertEqual(c.next_plus(10), d)
3334 self.assertRaises(TypeError, c.next_plus, '10')
3335
3336 def test_next_toward(self):
3337 Decimal = self.decimal.Decimal
3338 Context = self.decimal.Context
3339
3340 c = Context()
3341 d = c.next_toward(Decimal(1), Decimal(2))
3342 self.assertEqual(c.next_toward(1, 2), d)
3343 self.assertEqual(c.next_toward(Decimal(1), 2), d)
3344 self.assertEqual(c.next_toward(1, Decimal(2)), d)
3345 self.assertRaises(TypeError, c.next_toward, '1', 2)
3346 self.assertRaises(TypeError, c.next_toward, 1, '2')
3347
3348 def test_normalize(self):
3349 Decimal = self.decimal.Decimal
3350 Context = self.decimal.Context
3351
3352 c = Context()
3353 d = c.normalize(Decimal(10))
3354 self.assertEqual(c.normalize(10), d)
3355 self.assertRaises(TypeError, c.normalize, '10')
3356
3357 def test_number_class(self):
3358 Decimal = self.decimal.Decimal
3359 Context = self.decimal.Context
3360
3361 c = Context()
3362 self.assertEqual(c.number_class(123), c.number_class(Decimal(123)))
3363 self.assertEqual(c.number_class(0), c.number_class(Decimal(0)))
3364 self.assertEqual(c.number_class(-45), c.number_class(Decimal(-45)))
3365
3366 def test_plus(self):
3367 Decimal = self.decimal.Decimal
3368 Context = self.decimal.Context
3369
3370 c = Context()
3371 d = c.plus(Decimal(10))
3372 self.assertEqual(c.plus(10), d)
3373 self.assertRaises(TypeError, c.plus, '10')
3374
3375 def test_power(self):
3376 Decimal = self.decimal.Decimal
3377 Context = self.decimal.Context
3378
3379 c = Context()
3380 d = c.power(Decimal(1), Decimal(4))
3381 self.assertEqual(c.power(1, 4), d)
3382 self.assertEqual(c.power(Decimal(1), 4), d)
3383 self.assertEqual(c.power(1, Decimal(4)), d)
3384 self.assertEqual(c.power(Decimal(1), Decimal(4)), d)
3385 self.assertRaises(TypeError, c.power, '1', 4)
3386 self.assertRaises(TypeError, c.power, 1, '4')
3387 self.assertEqual(c.power(modulo=5, b=8, a=2), 1)
3388
3389 def test_quantize(self):
3390 Decimal = self.decimal.Decimal
3391 Context = self.decimal.Context
3392
3393 c = Context()
3394 d = c.quantize(Decimal(1), Decimal(2))
3395 self.assertEqual(c.quantize(1, 2), d)
3396 self.assertEqual(c.quantize(Decimal(1), 2), d)
3397 self.assertEqual(c.quantize(1, Decimal(2)), d)
3398 self.assertRaises(TypeError, c.quantize, '1', 2)
3399 self.assertRaises(TypeError, c.quantize, 1, '2')
3400
3401 def test_remainder(self):
3402 Decimal = self.decimal.Decimal
3403 Context = self.decimal.Context
3404
3405 c = Context()
3406 d = c.remainder(Decimal(1), Decimal(2))
3407 self.assertEqual(c.remainder(1, 2), d)
3408 self.assertEqual(c.remainder(Decimal(1), 2), d)
3409 self.assertEqual(c.remainder(1, Decimal(2)), d)
3410 self.assertRaises(TypeError, c.remainder, '1', 2)
3411 self.assertRaises(TypeError, c.remainder, 1, '2')
3412
3413 def test_remainder_near(self):
3414 Decimal = self.decimal.Decimal
3415 Context = self.decimal.Context
3416
3417 c = Context()
3418 d = c.remainder_near(Decimal(1), Decimal(2))
3419 self.assertEqual(c.remainder_near(1, 2), d)
3420 self.assertEqual(c.remainder_near(Decimal(1), 2), d)
3421 self.assertEqual(c.remainder_near(1, Decimal(2)), d)
3422 self.assertRaises(TypeError, c.remainder_near, '1', 2)
3423 self.assertRaises(TypeError, c.remainder_near, 1, '2')
3424
3425 def test_rotate(self):
3426 Decimal = self.decimal.Decimal
3427 Context = self.decimal.Context
3428
3429 c = Context()
3430 d = c.rotate(Decimal(1), Decimal(2))
3431 self.assertEqual(c.rotate(1, 2), d)
3432 self.assertEqual(c.rotate(Decimal(1), 2), d)
3433 self.assertEqual(c.rotate(1, Decimal(2)), d)
3434 self.assertRaises(TypeError, c.rotate, '1', 2)
3435 self.assertRaises(TypeError, c.rotate, 1, '2')
3436
3437 def test_sqrt(self):
3438 Decimal = self.decimal.Decimal
3439 Context = self.decimal.Context
3440
3441 c = Context()
3442 d = c.sqrt(Decimal(10))
3443 self.assertEqual(c.sqrt(10), d)
3444 self.assertRaises(TypeError, c.sqrt, '10')
3445
3446 def test_same_quantum(self):
3447 Decimal = self.decimal.Decimal
3448 Context = self.decimal.Context
3449
3450 c = Context()
3451 d = c.same_quantum(Decimal(1), Decimal(2))
3452 self.assertEqual(c.same_quantum(1, 2), d)
3453 self.assertEqual(c.same_quantum(Decimal(1), 2), d)
3454 self.assertEqual(c.same_quantum(1, Decimal(2)), d)
3455 self.assertRaises(TypeError, c.same_quantum, '1', 2)
3456 self.assertRaises(TypeError, c.same_quantum, 1, '2')
3457
3458 def test_scaleb(self):
3459 Decimal = self.decimal.Decimal
3460 Context = self.decimal.Context
3461
3462 c = Context()
3463 d = c.scaleb(Decimal(1), Decimal(2))
3464 self.assertEqual(c.scaleb(1, 2), d)
3465 self.assertEqual(c.scaleb(Decimal(1), 2), d)
3466 self.assertEqual(c.scaleb(1, Decimal(2)), d)
3467 self.assertRaises(TypeError, c.scaleb, '1', 2)
3468 self.assertRaises(TypeError, c.scaleb, 1, '2')
3469
3470 def test_shift(self):
3471 Decimal = self.decimal.Decimal
3472 Context = self.decimal.Context
3473
3474 c = Context()
3475 d = c.shift(Decimal(1), Decimal(2))
3476 self.assertEqual(c.shift(1, 2), d)
3477 self.assertEqual(c.shift(Decimal(1), 2), d)
3478 self.assertEqual(c.shift(1, Decimal(2)), d)
3479 self.assertRaises(TypeError, c.shift, '1', 2)
3480 self.assertRaises(TypeError, c.shift, 1, '2')
3481
3482 def test_subtract(self):
3483 Decimal = self.decimal.Decimal
3484 Context = self.decimal.Context
3485
3486 c = Context()
3487 d = c.subtract(Decimal(1), Decimal(2))
3488 self.assertEqual(c.subtract(1, 2), d)
3489 self.assertEqual(c.subtract(Decimal(1), 2), d)
3490 self.assertEqual(c.subtract(1, Decimal(2)), d)
3491 self.assertRaises(TypeError, c.subtract, '1', 2)
3492 self.assertRaises(TypeError, c.subtract, 1, '2')
3493
3494 def test_to_eng_string(self):
3495 Decimal = self.decimal.Decimal
3496 Context = self.decimal.Context
3497
3498 c = Context()
3499 d = c.to_eng_string(Decimal(10))
3500 self.assertEqual(c.to_eng_string(10), d)
3501 self.assertRaises(TypeError, c.to_eng_string, '10')
3502
3503 def test_to_sci_string(self):
3504 Decimal = self.decimal.Decimal
3505 Context = self.decimal.Context
3506
3507 c = Context()
3508 d = c.to_sci_string(Decimal(10))
3509 self.assertEqual(c.to_sci_string(10), d)
3510 self.assertRaises(TypeError, c.to_sci_string, '10')
3511
3512 def test_to_integral_exact(self):
3513 Decimal = self.decimal.Decimal
3514 Context = self.decimal.Context
3515
3516 c = Context()
3517 d = c.to_integral_exact(Decimal(10))
3518 self.assertEqual(c.to_integral_exact(10), d)
3519 self.assertRaises(TypeError, c.to_integral_exact, '10')
3520
3521 def test_to_integral_value(self):
3522 Decimal = self.decimal.Decimal
3523 Context = self.decimal.Context
3524
3525 c = Context()
3526 d = c.to_integral_value(Decimal(10))
3527 self.assertEqual(c.to_integral_value(10), d)
3528 self.assertRaises(TypeError, c.to_integral_value, '10')
3529 self.assertRaises(TypeError, c.to_integral_value, 10, 'x')
3530
3531class CContextAPItests(ContextAPItests):
3532 decimal = C
3533class PyContextAPItests(ContextAPItests):
3534 decimal = P
3535
3536class ContextWithStatement(unittest.TestCase):
3537 # Can't do these as docstrings until Python 2.6
3538 # as doctest can't handle __future__ statements
3539
3540 def test_localcontext(self):
3541 # Use a copy of the current context in the block
3542 getcontext = self.decimal.getcontext
3543 localcontext = self.decimal.localcontext
3544
3545 orig_ctx = getcontext()
3546 with localcontext() as enter_ctx:
3547 set_ctx = getcontext()
3548 final_ctx = getcontext()
3549 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
3550 self.assertIsNot(orig_ctx, set_ctx, 'did not copy the context')
3551 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
3552
3553 def test_localcontextarg(self):
3554 # Use a copy of the supplied context in the block
3555 Context = self.decimal.Context
3556 getcontext = self.decimal.getcontext
3557 localcontext = self.decimal.localcontext
3558
3559 localcontext = self.decimal.localcontext
3560 orig_ctx = getcontext()
3561 new_ctx = Context(prec=42)
3562 with localcontext(new_ctx) as enter_ctx:
3563 set_ctx = getcontext()
3564 final_ctx = getcontext()
3565 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
3566 self.assertEqual(set_ctx.prec, new_ctx.prec, 'did not set correct context')
3567 self.assertIsNot(new_ctx, set_ctx, 'did not copy the context')
3568 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
3569
3570 def test_nested_with_statements(self):
3571 # Use a copy of the supplied context in the block
3572 Decimal = self.decimal.Decimal
3573 Context = self.decimal.Context
3574 getcontext = self.decimal.getcontext
3575 localcontext = self.decimal.localcontext
3576 Clamped = self.decimal.Clamped
3577 Overflow = self.decimal.Overflow
3578
3579 orig_ctx = getcontext()
3580 orig_ctx.clear_flags()
3581 new_ctx = Context(Emax=384)
3582 with localcontext() as c1:
3583 self.assertEqual(c1.flags, orig_ctx.flags)
3584 self.assertEqual(c1.traps, orig_ctx.traps)
3585 c1.traps[Clamped] = True
3586 c1.Emin = -383
3587 self.assertNotEqual(orig_ctx.Emin, -383)
3588 self.assertRaises(Clamped, c1.create_decimal, '0e-999')
3589 self.assertTrue(c1.flags[Clamped])
3590 with localcontext(new_ctx) as c2:
3591 self.assertEqual(c2.flags, new_ctx.flags)
3592 self.assertEqual(c2.traps, new_ctx.traps)
3593 self.assertRaises(Overflow, c2.power, Decimal('3.4e200'), 2)
3594 self.assertFalse(c2.flags[Clamped])
3595 self.assertTrue(c2.flags[Overflow])
3596 del c2
3597 self.assertFalse(c1.flags[Overflow])
3598 del c1
3599 self.assertNotEqual(orig_ctx.Emin, -383)
3600 self.assertFalse(orig_ctx.flags[Clamped])
3601 self.assertFalse(orig_ctx.flags[Overflow])
3602 self.assertFalse(new_ctx.flags[Clamped])
3603 self.assertFalse(new_ctx.flags[Overflow])
3604
3605 def test_with_statements_gc1(self):
3606 localcontext = self.decimal.localcontext
3607
3608 with localcontext() as c1:
3609 del c1
3610 with localcontext() as c2:
3611 del c2
3612 with localcontext() as c3:
3613 del c3
3614 with localcontext() as c4:
3615 del c4
3616
3617 def test_with_statements_gc2(self):
3618 localcontext = self.decimal.localcontext
3619
3620 with localcontext() as c1:
3621 with localcontext(c1) as c2:
3622 del c1
3623 with localcontext(c2) as c3:
3624 del c2
3625 with localcontext(c3) as c4:
3626 del c3
3627 del c4
3628
3629 def test_with_statements_gc3(self):
3630 Context = self.decimal.Context
3631 localcontext = self.decimal.localcontext
3632 getcontext = self.decimal.getcontext
3633 setcontext = self.decimal.setcontext
3634
3635 with localcontext() as c1:
3636 del c1
3637 n1 = Context(prec=1)
3638 setcontext(n1)
3639 with localcontext(n1) as c2:
3640 del n1
3641 self.assertEqual(c2.prec, 1)
3642 del c2
3643 n2 = Context(prec=2)
3644 setcontext(n2)
3645 del n2
3646 self.assertEqual(getcontext().prec, 2)
3647 n3 = Context(prec=3)
3648 setcontext(n3)
3649 self.assertEqual(getcontext().prec, 3)
3650 with localcontext(n3) as c3:
3651 del n3
3652 self.assertEqual(c3.prec, 3)
3653 del c3
3654 n4 = Context(prec=4)
3655 setcontext(n4)
3656 del n4
3657 self.assertEqual(getcontext().prec, 4)
3658 with localcontext() as c4:
3659 self.assertEqual(c4.prec, 4)
3660 del c4
3661
3662class CContextWithStatement(ContextWithStatement):
3663 decimal = C
3664class PyContextWithStatement(ContextWithStatement):
3665 decimal = P
3666
3667class ContextFlags(unittest.TestCase):
3668
3669 def test_flags_irrelevant(self):
3670 # check that the result (numeric result + flags raised) of an
3671 # arithmetic operation doesn't depend on the current flags
3672 Decimal = self.decimal.Decimal
3673 Context = self.decimal.Context
3674 Inexact = self.decimal.Inexact
3675 Rounded = self.decimal.Rounded
3676 Underflow = self.decimal.Underflow
3677 Clamped = self.decimal.Clamped
3678 Subnormal = self.decimal.Subnormal
Stefan Krah1919b7e2012-03-21 18:25:23 +01003679
3680 def raise_error(context, flag):
3681 if self.decimal == C:
3682 context.flags[flag] = True
3683 if context.traps[flag]:
3684 raise flag
3685 else:
3686 context._raise_error(flag)
3687
3688 context = Context(prec=9, Emin = -425000000, Emax = 425000000,
3689 rounding=ROUND_HALF_EVEN, traps=[], flags=[])
3690
3691 # operations that raise various flags, in the form (function, arglist)
3692 operations = [
3693 (context._apply, [Decimal("100E-425000010")]),
3694 (context.sqrt, [Decimal(2)]),
3695 (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]),
3696 (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]),
3697 (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]),
3698 ]
3699
3700 # try various flags individually, then a whole lot at once
3701 flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal],
3702 [Inexact, Rounded, Underflow, Clamped, Subnormal]]
3703
3704 for fn, args in operations:
3705 # find answer and flags raised using a clean context
3706 context.clear_flags()
3707 ans = fn(*args)
3708 flags = [k for k, v in context.flags.items() if v]
3709
3710 for extra_flags in flagsets:
3711 # set flags, before calling operation
3712 context.clear_flags()
3713 for flag in extra_flags:
3714 raise_error(context, flag)
3715 new_ans = fn(*args)
3716
3717 # flags that we expect to be set after the operation
3718 expected_flags = list(flags)
3719 for flag in extra_flags:
3720 if flag not in expected_flags:
3721 expected_flags.append(flag)
3722 expected_flags.sort(key=id)
3723
3724 # flags we actually got
3725 new_flags = [k for k,v in context.flags.items() if v]
3726 new_flags.sort(key=id)
3727
3728 self.assertEqual(ans, new_ans,
3729 "operation produces different answers depending on flags set: " +
3730 "expected %s, got %s." % (ans, new_ans))
3731 self.assertEqual(new_flags, expected_flags,
3732 "operation raises different flags depending on flags set: " +
3733 "expected %s, got %s" % (expected_flags, new_flags))
3734
3735 def test_flag_comparisons(self):
3736 Context = self.decimal.Context
3737 Inexact = self.decimal.Inexact
3738 Rounded = self.decimal.Rounded
3739
3740 c = Context()
3741
3742 # Valid SignalDict
3743 self.assertNotEqual(c.flags, c.traps)
3744 self.assertNotEqual(c.traps, c.flags)
3745
3746 c.flags = c.traps
3747 self.assertEqual(c.flags, c.traps)
3748 self.assertEqual(c.traps, c.flags)
3749
3750 c.flags[Rounded] = True
3751 c.traps = c.flags
3752 self.assertEqual(c.flags, c.traps)
3753 self.assertEqual(c.traps, c.flags)
3754
3755 d = {}
3756 d.update(c.flags)
3757 self.assertEqual(d, c.flags)
3758 self.assertEqual(c.flags, d)
3759
3760 d[Inexact] = True
3761 self.assertNotEqual(d, c.flags)
3762 self.assertNotEqual(c.flags, d)
3763
3764 # Invalid SignalDict
3765 d = {Inexact:False}
3766 self.assertNotEqual(d, c.flags)
3767 self.assertNotEqual(c.flags, d)
3768
3769 d = ["xyz"]
3770 self.assertNotEqual(d, c.flags)
3771 self.assertNotEqual(c.flags, d)
3772
3773 @requires_IEEE_754
3774 def test_float_operation(self):
3775 Decimal = self.decimal.Decimal
3776 FloatOperation = self.decimal.FloatOperation
3777 localcontext = self.decimal.localcontext
3778
3779 with localcontext() as c:
3780 ##### trap is off by default
3781 self.assertFalse(c.traps[FloatOperation])
3782
3783 # implicit conversion sets the flag
3784 c.clear_flags()
3785 self.assertEqual(Decimal(7.5), 7.5)
3786 self.assertTrue(c.flags[FloatOperation])
3787
3788 c.clear_flags()
3789 self.assertEqual(c.create_decimal(7.5), 7.5)
3790 self.assertTrue(c.flags[FloatOperation])
3791
3792 # explicit conversion does not set the flag
3793 c.clear_flags()
3794 x = Decimal.from_float(7.5)
3795 self.assertFalse(c.flags[FloatOperation])
3796 # comparison sets the flag
3797 self.assertEqual(x, 7.5)
3798 self.assertTrue(c.flags[FloatOperation])
3799
3800 c.clear_flags()
3801 x = c.create_decimal_from_float(7.5)
3802 self.assertFalse(c.flags[FloatOperation])
3803 self.assertEqual(x, 7.5)
3804 self.assertTrue(c.flags[FloatOperation])
3805
3806 ##### set the trap
3807 c.traps[FloatOperation] = True
3808
3809 # implicit conversion raises
3810 c.clear_flags()
3811 self.assertRaises(FloatOperation, Decimal, 7.5)
3812 self.assertTrue(c.flags[FloatOperation])
3813
3814 c.clear_flags()
3815 self.assertRaises(FloatOperation, c.create_decimal, 7.5)
3816 self.assertTrue(c.flags[FloatOperation])
3817
3818 # explicit conversion is silent
3819 c.clear_flags()
3820 x = Decimal.from_float(7.5)
3821 self.assertFalse(c.flags[FloatOperation])
3822
3823 c.clear_flags()
3824 x = c.create_decimal_from_float(7.5)
3825 self.assertFalse(c.flags[FloatOperation])
3826
3827 def test_float_comparison(self):
3828 Decimal = self.decimal.Decimal
3829 Context = self.decimal.Context
3830 FloatOperation = self.decimal.FloatOperation
3831 localcontext = self.decimal.localcontext
3832
3833 def assert_attr(a, b, attr, context, signal=None):
3834 context.clear_flags()
3835 f = getattr(a, attr)
3836 if signal == FloatOperation:
3837 self.assertRaises(signal, f, b)
3838 else:
3839 self.assertIs(f(b), True)
3840 self.assertTrue(context.flags[FloatOperation])
3841
3842 small_d = Decimal('0.25')
3843 big_d = Decimal('3.0')
3844 small_f = 0.25
3845 big_f = 3.0
3846
3847 zero_d = Decimal('0.0')
3848 neg_zero_d = Decimal('-0.0')
3849 zero_f = 0.0
3850 neg_zero_f = -0.0
3851
3852 inf_d = Decimal('Infinity')
3853 neg_inf_d = Decimal('-Infinity')
3854 inf_f = float('inf')
3855 neg_inf_f = float('-inf')
3856
3857 def doit(c, signal=None):
3858 # Order
3859 for attr in '__lt__', '__le__':
3860 assert_attr(small_d, big_f, attr, c, signal)
3861
3862 for attr in '__gt__', '__ge__':
3863 assert_attr(big_d, small_f, attr, c, signal)
3864
3865 # Equality
3866 assert_attr(small_d, small_f, '__eq__', c, None)
3867
3868 assert_attr(neg_zero_d, neg_zero_f, '__eq__', c, None)
3869 assert_attr(neg_zero_d, zero_f, '__eq__', c, None)
3870
3871 assert_attr(zero_d, neg_zero_f, '__eq__', c, None)
3872 assert_attr(zero_d, zero_f, '__eq__', c, None)
3873
3874 assert_attr(neg_inf_d, neg_inf_f, '__eq__', c, None)
3875 assert_attr(inf_d, inf_f, '__eq__', c, None)
3876
3877 # Inequality
3878 assert_attr(small_d, big_f, '__ne__', c, None)
3879
3880 assert_attr(Decimal('0.1'), 0.1, '__ne__', c, None)
3881
3882 assert_attr(neg_inf_d, inf_f, '__ne__', c, None)
3883 assert_attr(inf_d, neg_inf_f, '__ne__', c, None)
3884
3885 assert_attr(Decimal('NaN'), float('nan'), '__ne__', c, None)
3886
3887 def test_containers(c, signal=None):
3888 c.clear_flags()
3889 s = set([100.0, Decimal('100.0')])
3890 self.assertEqual(len(s), 1)
3891 self.assertTrue(c.flags[FloatOperation])
3892
3893 c.clear_flags()
3894 if signal:
3895 self.assertRaises(signal, sorted, [1.0, Decimal('10.0')])
3896 else:
3897 s = sorted([10.0, Decimal('10.0')])
3898 self.assertTrue(c.flags[FloatOperation])
3899
3900 c.clear_flags()
3901 b = 10.0 in [Decimal('10.0'), 1.0]
3902 self.assertTrue(c.flags[FloatOperation])
3903
3904 c.clear_flags()
3905 b = 10.0 in {Decimal('10.0'):'a', 1.0:'b'}
3906 self.assertTrue(c.flags[FloatOperation])
3907
3908 nc = Context()
3909 with localcontext(nc) as c:
3910 self.assertFalse(c.traps[FloatOperation])
3911 doit(c, signal=None)
3912 test_containers(c, signal=None)
3913
3914 c.traps[FloatOperation] = True
3915 doit(c, signal=FloatOperation)
3916 test_containers(c, signal=FloatOperation)
3917
3918 def test_float_operation_default(self):
3919 Decimal = self.decimal.Decimal
3920 Context = self.decimal.Context
3921 Inexact = self.decimal.Inexact
3922 FloatOperation= self.decimal.FloatOperation
3923
3924 context = Context()
3925 self.assertFalse(context.flags[FloatOperation])
3926 self.assertFalse(context.traps[FloatOperation])
3927
3928 context.clear_traps()
3929 context.traps[Inexact] = True
3930 context.traps[FloatOperation] = True
3931 self.assertTrue(context.traps[FloatOperation])
3932 self.assertTrue(context.traps[Inexact])
3933
3934class CContextFlags(ContextFlags):
3935 decimal = C
3936class PyContextFlags(ContextFlags):
3937 decimal = P
3938
3939class SpecialContexts(unittest.TestCase):
3940 """Test the context templates."""
3941
3942 def test_context_templates(self):
3943 BasicContext = self.decimal.BasicContext
3944 ExtendedContext = self.decimal.ExtendedContext
3945 getcontext = self.decimal.getcontext
3946 setcontext = self.decimal.setcontext
3947 InvalidOperation = self.decimal.InvalidOperation
3948 DivisionByZero = self.decimal.DivisionByZero
3949 Overflow = self.decimal.Overflow
3950 Underflow = self.decimal.Underflow
3951 Clamped = self.decimal.Clamped
3952
3953 assert_signals(self, BasicContext, 'traps',
3954 [InvalidOperation, DivisionByZero, Overflow, Underflow, Clamped]
3955 )
3956
3957 savecontext = getcontext().copy()
3958 basic_context_prec = BasicContext.prec
3959 extended_context_prec = ExtendedContext.prec
3960
3961 ex = None
3962 try:
3963 BasicContext.prec = ExtendedContext.prec = 441
3964 for template in BasicContext, ExtendedContext:
3965 setcontext(template)
3966 c = getcontext()
3967 self.assertIsNot(c, template)
3968 self.assertEqual(c.prec, 441)
3969 except Exception as e:
3970 ex = e.__class__
3971 finally:
3972 BasicContext.prec = basic_context_prec
3973 ExtendedContext.prec = extended_context_prec
3974 setcontext(savecontext)
3975 if ex:
3976 raise ex
3977
3978 def test_default_context(self):
3979 DefaultContext = self.decimal.DefaultContext
3980 BasicContext = self.decimal.BasicContext
3981 ExtendedContext = self.decimal.ExtendedContext
3982 getcontext = self.decimal.getcontext
3983 setcontext = self.decimal.setcontext
3984 InvalidOperation = self.decimal.InvalidOperation
3985 DivisionByZero = self.decimal.DivisionByZero
3986 Overflow = self.decimal.Overflow
3987
3988 self.assertEqual(BasicContext.prec, 9)
3989 self.assertEqual(ExtendedContext.prec, 9)
3990
3991 assert_signals(self, DefaultContext, 'traps',
3992 [InvalidOperation, DivisionByZero, Overflow]
3993 )
3994
3995 savecontext = getcontext().copy()
3996 default_context_prec = DefaultContext.prec
3997
3998 ex = None
3999 try:
4000 c = getcontext()
4001 saveprec = c.prec
4002
4003 DefaultContext.prec = 961
4004 c = getcontext()
4005 self.assertEqual(c.prec, saveprec)
4006
4007 setcontext(DefaultContext)
4008 c = getcontext()
4009 self.assertIsNot(c, DefaultContext)
4010 self.assertEqual(c.prec, 961)
4011 except Exception as e:
4012 ex = e.__class__
4013 finally:
4014 DefaultContext.prec = default_context_prec
4015 setcontext(savecontext)
4016 if ex:
4017 raise ex
4018
4019class CSpecialContexts(SpecialContexts):
4020 decimal = C
4021class PySpecialContexts(SpecialContexts):
4022 decimal = P
4023
4024class ContextInputValidation(unittest.TestCase):
4025
4026 def test_invalid_context(self):
4027 Context = self.decimal.Context
4028 DefaultContext = self.decimal.DefaultContext
4029
4030 c = DefaultContext.copy()
4031
4032 # prec, Emax
4033 for attr in ['prec', 'Emax']:
4034 setattr(c, attr, 999999)
4035 self.assertEqual(getattr(c, attr), 999999)
4036 self.assertRaises(ValueError, setattr, c, attr, -1)
4037 self.assertRaises(TypeError, setattr, c, attr, 'xyz')
4038
4039 # Emin
4040 setattr(c, 'Emin', -999999)
4041 self.assertEqual(getattr(c, 'Emin'), -999999)
4042 self.assertRaises(ValueError, setattr, c, 'Emin', 1)
4043 self.assertRaises(TypeError, setattr, c, 'Emin', (1,2,3))
4044
Stefan Krah1919b7e2012-03-21 18:25:23 +01004045 self.assertRaises(TypeError, setattr, c, 'rounding', -1)
4046 self.assertRaises(TypeError, setattr, c, 'rounding', 9)
4047 self.assertRaises(TypeError, setattr, c, 'rounding', 1.0)
4048 self.assertRaises(TypeError, setattr, c, 'rounding', 'xyz')
4049
4050 # capitals, clamp
4051 for attr in ['capitals', 'clamp']:
4052 self.assertRaises(ValueError, setattr, c, attr, -1)
4053 self.assertRaises(ValueError, setattr, c, attr, 2)
4054 self.assertRaises(TypeError, setattr, c, attr, [1,2,3])
4055
4056 # Invalid attribute
4057 self.assertRaises(AttributeError, setattr, c, 'emax', 100)
4058
4059 # Invalid signal dict
4060 self.assertRaises(TypeError, setattr, c, 'flags', [])
4061 self.assertRaises(KeyError, setattr, c, 'flags', {})
4062 self.assertRaises(KeyError, setattr, c, 'traps',
4063 {'InvalidOperation':0})
4064
4065 # Attributes cannot be deleted
4066 for attr in ['prec', 'Emax', 'Emin', 'rounding', 'capitals', 'clamp',
4067 'flags', 'traps']:
4068 self.assertRaises(AttributeError, c.__delattr__, attr)
4069
4070 # Invalid attributes
4071 self.assertRaises(TypeError, getattr, c, 9)
4072 self.assertRaises(TypeError, setattr, c, 9)
4073
4074 # Invalid values in constructor
4075 self.assertRaises(TypeError, Context, rounding=999999)
4076 self.assertRaises(TypeError, Context, rounding='xyz')
4077 self.assertRaises(ValueError, Context, clamp=2)
4078 self.assertRaises(ValueError, Context, capitals=-1)
4079 self.assertRaises(KeyError, Context, flags=["P"])
4080 self.assertRaises(KeyError, Context, traps=["Q"])
4081
4082 # Type error in conversion
4083 self.assertRaises(TypeError, Context, flags=(0,1))
4084 self.assertRaises(TypeError, Context, traps=(1,0))
4085
4086class CContextInputValidation(ContextInputValidation):
4087 decimal = C
4088class PyContextInputValidation(ContextInputValidation):
4089 decimal = P
4090
4091class ContextSubclassing(unittest.TestCase):
4092
4093 def test_context_subclassing(self):
4094 decimal = self.decimal
4095 Decimal = decimal.Decimal
4096 Context = decimal.Context
Stefan Krah1919b7e2012-03-21 18:25:23 +01004097 Clamped = decimal.Clamped
4098 DivisionByZero = decimal.DivisionByZero
4099 Inexact = decimal.Inexact
4100 Overflow = decimal.Overflow
4101 Rounded = decimal.Rounded
4102 Subnormal = decimal.Subnormal
4103 Underflow = decimal.Underflow
4104 InvalidOperation = decimal.InvalidOperation
4105
4106 class MyContext(Context):
4107 def __init__(self, prec=None, rounding=None, Emin=None, Emax=None,
4108 capitals=None, clamp=None, flags=None,
4109 traps=None):
4110 Context.__init__(self)
4111 if prec is not None:
4112 self.prec = prec
4113 if rounding is not None:
4114 self.rounding = rounding
4115 if Emin is not None:
4116 self.Emin = Emin
4117 if Emax is not None:
4118 self.Emax = Emax
4119 if capitals is not None:
4120 self.capitals = capitals
4121 if clamp is not None:
4122 self.clamp = clamp
4123 if flags is not None:
4124 if isinstance(flags, list):
4125 flags = {v:(v in flags) for v in OrderedSignals[decimal] + flags}
4126 self.flags = flags
4127 if traps is not None:
4128 if isinstance(traps, list):
4129 traps = {v:(v in traps) for v in OrderedSignals[decimal] + traps}
4130 self.traps = traps
4131
4132 c = Context()
4133 d = MyContext()
4134 for attr in ('prec', 'rounding', 'Emin', 'Emax', 'capitals', 'clamp',
4135 'flags', 'traps'):
4136 self.assertEqual(getattr(c, attr), getattr(d, attr))
4137
4138 # prec
4139 self.assertRaises(ValueError, MyContext, **{'prec':-1})
4140 c = MyContext(prec=1)
4141 self.assertEqual(c.prec, 1)
4142 self.assertRaises(InvalidOperation, c.quantize, Decimal('9e2'), 0)
4143
4144 # rounding
4145 self.assertRaises(TypeError, MyContext, **{'rounding':'XYZ'})
4146 c = MyContext(rounding=ROUND_DOWN, prec=1)
4147 self.assertEqual(c.rounding, ROUND_DOWN)
4148 self.assertEqual(c.plus(Decimal('9.9')), 9)
4149
4150 # Emin
4151 self.assertRaises(ValueError, MyContext, **{'Emin':5})
4152 c = MyContext(Emin=-1, prec=1)
4153 self.assertEqual(c.Emin, -1)
4154 x = c.add(Decimal('1e-99'), Decimal('2.234e-2000'))
4155 self.assertEqual(x, Decimal('0.0'))
4156 for signal in (Inexact, Underflow, Subnormal, Rounded, Clamped):
4157 self.assertTrue(c.flags[signal])
4158
4159 # Emax
4160 self.assertRaises(ValueError, MyContext, **{'Emax':-1})
4161 c = MyContext(Emax=1, prec=1)
4162 self.assertEqual(c.Emax, 1)
4163 self.assertRaises(Overflow, c.add, Decimal('1e99'), Decimal('2.234e2000'))
4164 if self.decimal == C:
4165 for signal in (Inexact, Overflow, Rounded):
4166 self.assertTrue(c.flags[signal])
4167
4168 # capitals
4169 self.assertRaises(ValueError, MyContext, **{'capitals':-1})
4170 c = MyContext(capitals=0)
4171 self.assertEqual(c.capitals, 0)
4172 x = c.create_decimal('1E222')
4173 self.assertEqual(c.to_sci_string(x), '1e+222')
4174
4175 # clamp
4176 self.assertRaises(ValueError, MyContext, **{'clamp':2})
4177 c = MyContext(clamp=1, Emax=99)
4178 self.assertEqual(c.clamp, 1)
4179 x = c.plus(Decimal('1e99'))
4180 self.assertEqual(str(x), '1.000000000000000000000000000E+99')
4181
4182 # flags
4183 self.assertRaises(TypeError, MyContext, **{'flags':'XYZ'})
4184 c = MyContext(flags=[Rounded, DivisionByZero])
4185 for signal in (Rounded, DivisionByZero):
4186 self.assertTrue(c.flags[signal])
4187 c.clear_flags()
4188 for signal in OrderedSignals[decimal]:
4189 self.assertFalse(c.flags[signal])
4190
4191 # traps
4192 self.assertRaises(TypeError, MyContext, **{'traps':'XYZ'})
4193 c = MyContext(traps=[Rounded, DivisionByZero])
4194 for signal in (Rounded, DivisionByZero):
4195 self.assertTrue(c.traps[signal])
4196 c.clear_traps()
4197 for signal in OrderedSignals[decimal]:
4198 self.assertFalse(c.traps[signal])
4199
4200class CContextSubclassing(ContextSubclassing):
4201 decimal = C
4202class PyContextSubclassing(ContextSubclassing):
4203 decimal = P
4204
4205@skip_if_extra_functionality
4206class CheckAttributes(unittest.TestCase):
4207
4208 def test_module_attributes(self):
4209
4210 # Architecture dependent context limits
4211 self.assertEqual(C.MAX_PREC, P.MAX_PREC)
4212 self.assertEqual(C.MAX_EMAX, P.MAX_EMAX)
4213 self.assertEqual(C.MIN_EMIN, P.MIN_EMIN)
4214 self.assertEqual(C.MIN_ETINY, P.MIN_ETINY)
4215
4216 self.assertTrue(C.HAVE_THREADS is True or C.HAVE_THREADS is False)
4217 self.assertTrue(P.HAVE_THREADS is True or P.HAVE_THREADS is False)
4218
4219 self.assertEqual(C.__version__, P.__version__)
4220
Stefan Krahb578f8a2014-09-10 17:58:15 +02004221 self.assertEqual(dir(C), dir(P))
Stefan Krah1919b7e2012-03-21 18:25:23 +01004222
4223 def test_context_attributes(self):
4224
4225 x = [s for s in dir(C.Context()) if '__' in s or not s.startswith('_')]
4226 y = [s for s in dir(P.Context()) if '__' in s or not s.startswith('_')]
4227 self.assertEqual(set(x) - set(y), set())
4228
4229 def test_decimal_attributes(self):
4230
4231 x = [s for s in dir(C.Decimal(9)) if '__' in s or not s.startswith('_')]
4232 y = [s for s in dir(C.Decimal(9)) if '__' in s or not s.startswith('_')]
4233 self.assertEqual(set(x) - set(y), set())
4234
4235class Coverage(unittest.TestCase):
4236
4237 def test_adjusted(self):
4238 Decimal = self.decimal.Decimal
4239
4240 self.assertEqual(Decimal('1234e9999').adjusted(), 10002)
4241 # XXX raise?
4242 self.assertEqual(Decimal('nan').adjusted(), 0)
4243 self.assertEqual(Decimal('inf').adjusted(), 0)
4244
4245 def test_canonical(self):
4246 Decimal = self.decimal.Decimal
4247 getcontext = self.decimal.getcontext
4248
4249 x = Decimal(9).canonical()
4250 self.assertEqual(x, 9)
4251
4252 c = getcontext()
4253 x = c.canonical(Decimal(9))
4254 self.assertEqual(x, 9)
4255
4256 def test_context_repr(self):
4257 c = self.decimal.DefaultContext.copy()
4258
4259 c.prec = 425000000
4260 c.Emax = 425000000
4261 c.Emin = -425000000
Stefan Krah59a4a932013-01-16 12:58:59 +01004262 c.rounding = ROUND_HALF_DOWN
Stefan Krah1919b7e2012-03-21 18:25:23 +01004263 c.capitals = 0
4264 c.clamp = 1
4265 for sig in OrderedSignals[self.decimal]:
4266 c.flags[sig] = False
4267 c.traps[sig] = False
4268
4269 s = c.__repr__()
4270 t = "Context(prec=425000000, rounding=ROUND_HALF_DOWN, " \
4271 "Emin=-425000000, Emax=425000000, capitals=0, clamp=1, " \
4272 "flags=[], traps=[])"
4273 self.assertEqual(s, t)
4274
4275 def test_implicit_context(self):
4276 Decimal = self.decimal.Decimal
4277 localcontext = self.decimal.localcontext
4278
4279 with localcontext() as c:
4280 c.prec = 1
4281 c.Emax = 1
4282 c.Emin = -1
4283
4284 # abs
4285 self.assertEqual(abs(Decimal("-10")), 10)
4286 # add
4287 self.assertEqual(Decimal("7") + 1, 8)
4288 # divide
4289 self.assertEqual(Decimal("10") / 5, 2)
4290 # divide_int
4291 self.assertEqual(Decimal("10") // 7, 1)
4292 # fma
4293 self.assertEqual(Decimal("1.2").fma(Decimal("0.01"), 1), 1)
4294 self.assertIs(Decimal("NaN").fma(7, 1).is_nan(), True)
4295 # three arg power
4296 self.assertEqual(pow(Decimal(10), 2, 7), 2)
4297 # exp
4298 self.assertEqual(Decimal("1.01").exp(), 3)
4299 # is_normal
4300 self.assertIs(Decimal("0.01").is_normal(), False)
4301 # is_subnormal
4302 self.assertIs(Decimal("0.01").is_subnormal(), True)
4303 # ln
4304 self.assertEqual(Decimal("20").ln(), 3)
4305 # log10
4306 self.assertEqual(Decimal("20").log10(), 1)
4307 # logb
4308 self.assertEqual(Decimal("580").logb(), 2)
4309 # logical_invert
4310 self.assertEqual(Decimal("10").logical_invert(), 1)
4311 # minus
4312 self.assertEqual(-Decimal("-10"), 10)
4313 # multiply
4314 self.assertEqual(Decimal("2") * 4, 8)
4315 # next_minus
4316 self.assertEqual(Decimal("10").next_minus(), 9)
4317 # next_plus
4318 self.assertEqual(Decimal("10").next_plus(), Decimal('2E+1'))
4319 # normalize
4320 self.assertEqual(Decimal("-10").normalize(), Decimal('-1E+1'))
4321 # number_class
4322 self.assertEqual(Decimal("10").number_class(), '+Normal')
4323 # plus
4324 self.assertEqual(+Decimal("-1"), -1)
4325 # remainder
4326 self.assertEqual(Decimal("10") % 7, 3)
4327 # subtract
4328 self.assertEqual(Decimal("10") - 7, 3)
4329 # to_integral_exact
4330 self.assertEqual(Decimal("1.12345").to_integral_exact(), 1)
4331
4332 # Boolean functions
4333 self.assertTrue(Decimal("1").is_canonical())
4334 self.assertTrue(Decimal("1").is_finite())
4335 self.assertTrue(Decimal("1").is_finite())
4336 self.assertTrue(Decimal("snan").is_snan())
4337 self.assertTrue(Decimal("-1").is_signed())
4338 self.assertTrue(Decimal("0").is_zero())
4339 self.assertTrue(Decimal("0").is_zero())
4340
4341 # Copy
4342 with localcontext() as c:
4343 c.prec = 10000
4344 x = 1228 ** 1523
4345 y = -Decimal(x)
4346
4347 z = y.copy_abs()
4348 self.assertEqual(z, x)
4349
4350 z = y.copy_negate()
4351 self.assertEqual(z, x)
4352
4353 z = y.copy_sign(Decimal(1))
4354 self.assertEqual(z, x)
4355
4356 def test_divmod(self):
4357 Decimal = self.decimal.Decimal
4358 localcontext = self.decimal.localcontext
4359 InvalidOperation = self.decimal.InvalidOperation
4360 DivisionByZero = self.decimal.DivisionByZero
4361
4362 with localcontext() as c:
4363 q, r = divmod(Decimal("10912837129"), 1001)
4364 self.assertEqual(q, Decimal('10901935'))
4365 self.assertEqual(r, Decimal('194'))
4366
4367 q, r = divmod(Decimal("NaN"), 7)
4368 self.assertTrue(q.is_nan() and r.is_nan())
4369
4370 c.traps[InvalidOperation] = False
4371 q, r = divmod(Decimal("NaN"), 7)
4372 self.assertTrue(q.is_nan() and r.is_nan())
4373
4374 c.traps[InvalidOperation] = False
4375 c.clear_flags()
4376 q, r = divmod(Decimal("inf"), Decimal("inf"))
4377 self.assertTrue(q.is_nan() and r.is_nan())
4378 self.assertTrue(c.flags[InvalidOperation])
4379
4380 c.clear_flags()
4381 q, r = divmod(Decimal("inf"), 101)
4382 self.assertTrue(q.is_infinite() and r.is_nan())
4383 self.assertTrue(c.flags[InvalidOperation])
4384
4385 c.clear_flags()
4386 q, r = divmod(Decimal(0), 0)
4387 self.assertTrue(q.is_nan() and r.is_nan())
4388 self.assertTrue(c.flags[InvalidOperation])
4389
4390 c.traps[DivisionByZero] = False
4391 c.clear_flags()
4392 q, r = divmod(Decimal(11), 0)
4393 self.assertTrue(q.is_infinite() and r.is_nan())
4394 self.assertTrue(c.flags[InvalidOperation] and
4395 c.flags[DivisionByZero])
4396
4397 def test_power(self):
4398 Decimal = self.decimal.Decimal
4399 localcontext = self.decimal.localcontext
4400 Overflow = self.decimal.Overflow
4401 Rounded = self.decimal.Rounded
4402
4403 with localcontext() as c:
4404 c.prec = 3
4405 c.clear_flags()
4406 self.assertEqual(Decimal("1.0") ** 100, Decimal('1.00'))
4407 self.assertTrue(c.flags[Rounded])
4408
4409 c.prec = 1
4410 c.Emax = 1
4411 c.Emin = -1
4412 c.clear_flags()
4413 c.traps[Overflow] = False
4414 self.assertEqual(Decimal(10000) ** Decimal("0.5"), Decimal('inf'))
4415 self.assertTrue(c.flags[Overflow])
4416
4417 def test_quantize(self):
4418 Decimal = self.decimal.Decimal
4419 localcontext = self.decimal.localcontext
4420 InvalidOperation = self.decimal.InvalidOperation
4421
4422 with localcontext() as c:
4423 c.prec = 1
4424 c.Emax = 1
4425 c.Emin = -1
4426 c.traps[InvalidOperation] = False
4427 x = Decimal(99).quantize(Decimal("1e1"))
4428 self.assertTrue(x.is_nan())
4429
4430 def test_radix(self):
4431 Decimal = self.decimal.Decimal
4432 getcontext = self.decimal.getcontext
4433
4434 c = getcontext()
4435 self.assertEqual(Decimal("1").radix(), 10)
4436 self.assertEqual(c.radix(), 10)
4437
4438 def test_rop(self):
4439 Decimal = self.decimal.Decimal
4440
4441 for attr in ('__radd__', '__rsub__', '__rmul__', '__rtruediv__',
4442 '__rdivmod__', '__rmod__', '__rfloordiv__', '__rpow__'):
4443 self.assertIs(getattr(Decimal("1"), attr)("xyz"), NotImplemented)
4444
4445 def test_round(self):
4446 # Python3 behavior: round() returns Decimal
4447 Decimal = self.decimal.Decimal
4448 getcontext = self.decimal.getcontext
4449
4450 c = getcontext()
4451 c.prec = 28
4452
4453 self.assertEqual(str(Decimal("9.99").__round__()), "10")
4454 self.assertEqual(str(Decimal("9.99e-5").__round__()), "0")
4455 self.assertEqual(str(Decimal("1.23456789").__round__(5)), "1.23457")
4456 self.assertEqual(str(Decimal("1.2345").__round__(10)), "1.2345000000")
4457 self.assertEqual(str(Decimal("1.2345").__round__(-10)), "0E+10")
4458
4459 self.assertRaises(TypeError, Decimal("1.23").__round__, "5")
4460 self.assertRaises(TypeError, Decimal("1.23").__round__, 5, 8)
4461
4462 def test_create_decimal(self):
4463 c = self.decimal.Context()
4464 self.assertRaises(ValueError, c.create_decimal, ["%"])
4465
4466 def test_int(self):
4467 Decimal = self.decimal.Decimal
4468 localcontext = self.decimal.localcontext
4469
4470 with localcontext() as c:
4471 c.prec = 9999
4472 x = Decimal(1221**1271) / 10**3923
4473 self.assertEqual(int(x), 1)
4474 self.assertEqual(x.to_integral(), 2)
4475
4476 def test_copy(self):
4477 Context = self.decimal.Context
4478
4479 c = Context()
4480 c.prec = 10000
4481 x = -(1172 ** 1712)
4482
4483 y = c.copy_abs(x)
4484 self.assertEqual(y, -x)
4485
4486 y = c.copy_negate(x)
4487 self.assertEqual(y, -x)
4488
4489 y = c.copy_sign(x, 1)
4490 self.assertEqual(y, -x)
4491
4492class CCoverage(Coverage):
4493 decimal = C
4494class PyCoverage(Coverage):
4495 decimal = P
4496
4497class PyFunctionality(unittest.TestCase):
4498 """Extra functionality in decimal.py"""
4499
Stefan Krah1919b7e2012-03-21 18:25:23 +01004500 def test_py_alternate_formatting(self):
4501 # triples giving a format, a Decimal, and the expected result
4502 Decimal = P.Decimal
4503 localcontext = P.localcontext
4504
4505 test_values = [
4506 # Issue 7094: Alternate formatting (specified by #)
4507 ('.0e', '1.0', '1e+0'),
4508 ('#.0e', '1.0', '1.e+0'),
4509 ('.0f', '1.0', '1'),
4510 ('#.0f', '1.0', '1.'),
4511 ('g', '1.1', '1.1'),
4512 ('#g', '1.1', '1.1'),
4513 ('.0g', '1', '1'),
4514 ('#.0g', '1', '1.'),
4515 ('.0%', '1.0', '100%'),
4516 ('#.0%', '1.0', '100.%'),
4517 ]
4518 for fmt, d, result in test_values:
4519 self.assertEqual(format(Decimal(d), fmt), result)
4520
4521class PyWhitebox(unittest.TestCase):
4522 """White box testing for decimal.py"""
4523
4524 def test_py_exact_power(self):
4525 # Rarely exercised lines in _power_exact.
4526 Decimal = P.Decimal
4527 localcontext = P.localcontext
4528
4529 with localcontext() as c:
4530 c.prec = 8
4531 x = Decimal(2**16) ** Decimal("-0.5")
4532 self.assertEqual(x, Decimal('0.00390625'))
4533
4534 x = Decimal(2**16) ** Decimal("-0.6")
4535 self.assertEqual(x, Decimal('0.0012885819'))
4536
4537 x = Decimal("256e7") ** Decimal("-0.5")
4538
4539 x = Decimal(152587890625) ** Decimal('-0.0625')
4540 self.assertEqual(x, Decimal("0.2"))
4541
4542 x = Decimal("152587890625e7") ** Decimal('-0.0625')
4543
4544 x = Decimal(5**2659) ** Decimal('-0.0625')
4545
4546 c.prec = 1
4547 x = Decimal("152587890625") ** Decimal('-0.5')
4548 c.prec = 201
4549 x = Decimal(2**578) ** Decimal("-0.5")
4550
4551 def test_py_immutability_operations(self):
Terry Jan Reedy0f847642013-03-11 18:34:00 -04004552 # Do operations and check that it didn't change internal objects.
Stefan Krah1919b7e2012-03-21 18:25:23 +01004553 Decimal = P.Decimal
4554 DefaultContext = P.DefaultContext
4555 setcontext = P.setcontext
4556
4557 c = DefaultContext.copy()
4558 c.traps = dict((s, 0) for s in OrderedSignals[P])
4559 setcontext(c)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004560
4561 d1 = Decimal('-25e55')
4562 b1 = Decimal('-25e55')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004563 d2 = Decimal('33e+33')
4564 b2 = Decimal('33e+33')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004565
4566 def checkSameDec(operation, useOther=False):
4567 if useOther:
4568 eval("d1." + operation + "(d2)")
4569 self.assertEqual(d1._sign, b1._sign)
4570 self.assertEqual(d1._int, b1._int)
4571 self.assertEqual(d1._exp, b1._exp)
4572 self.assertEqual(d2._sign, b2._sign)
4573 self.assertEqual(d2._int, b2._int)
4574 self.assertEqual(d2._exp, b2._exp)
4575 else:
4576 eval("d1." + operation + "()")
4577 self.assertEqual(d1._sign, b1._sign)
4578 self.assertEqual(d1._int, b1._int)
4579 self.assertEqual(d1._exp, b1._exp)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004580
4581 Decimal(d1)
4582 self.assertEqual(d1._sign, b1._sign)
4583 self.assertEqual(d1._int, b1._int)
4584 self.assertEqual(d1._exp, b1._exp)
4585
4586 checkSameDec("__abs__")
4587 checkSameDec("__add__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004588 checkSameDec("__divmod__", True)
Christian Heimes77c02eb2008-02-09 02:18:51 +00004589 checkSameDec("__eq__", True)
4590 checkSameDec("__ne__", True)
4591 checkSameDec("__le__", True)
4592 checkSameDec("__lt__", True)
4593 checkSameDec("__ge__", True)
4594 checkSameDec("__gt__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004595 checkSameDec("__float__")
4596 checkSameDec("__floordiv__", True)
4597 checkSameDec("__hash__")
4598 checkSameDec("__int__")
Christian Heimes969fe572008-01-25 11:23:10 +00004599 checkSameDec("__trunc__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004600 checkSameDec("__mod__", True)
4601 checkSameDec("__mul__", True)
4602 checkSameDec("__neg__")
Jack Diederich4dafcc42006-11-28 19:15:13 +00004603 checkSameDec("__bool__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004604 checkSameDec("__pos__")
4605 checkSameDec("__pow__", True)
4606 checkSameDec("__radd__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004607 checkSameDec("__rdivmod__", True)
4608 checkSameDec("__repr__")
4609 checkSameDec("__rfloordiv__", True)
4610 checkSameDec("__rmod__", True)
4611 checkSameDec("__rmul__", True)
4612 checkSameDec("__rpow__", True)
4613 checkSameDec("__rsub__", True)
4614 checkSameDec("__str__")
4615 checkSameDec("__sub__", True)
4616 checkSameDec("__truediv__", True)
4617 checkSameDec("adjusted")
4618 checkSameDec("as_tuple")
4619 checkSameDec("compare", True)
4620 checkSameDec("max", True)
4621 checkSameDec("min", True)
4622 checkSameDec("normalize")
4623 checkSameDec("quantize", True)
4624 checkSameDec("remainder_near", True)
4625 checkSameDec("same_quantum", True)
4626 checkSameDec("sqrt")
4627 checkSameDec("to_eng_string")
4628 checkSameDec("to_integral")
4629
Stefan Krah1919b7e2012-03-21 18:25:23 +01004630 def test_py_decimal_id(self):
4631 Decimal = P.Decimal
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004632
Stefan Krah1919b7e2012-03-21 18:25:23 +01004633 d = Decimal(45)
4634 e = Decimal(d)
4635 self.assertEqual(str(e), '45')
4636 self.assertNotEqual(id(d), id(e))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004637
Stefan Krah1919b7e2012-03-21 18:25:23 +01004638 def test_py_rescale(self):
4639 # Coverage
4640 Decimal = P.Decimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01004641 localcontext = P.localcontext
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004642
Stefan Krah1919b7e2012-03-21 18:25:23 +01004643 with localcontext() as c:
4644 x = Decimal("NaN")._rescale(3, ROUND_UP)
4645 self.assertTrue(x.is_nan())
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004646
Stefan Krah1919b7e2012-03-21 18:25:23 +01004647 def test_py__round(self):
4648 # Coverage
4649 Decimal = P.Decimal
Christian Heimes0348fb62008-03-26 12:55:56 +00004650
Stefan Krah1919b7e2012-03-21 18:25:23 +01004651 self.assertRaises(ValueError, Decimal("3.1234")._round, 0, ROUND_UP)
Mark Dickinsona2d1fe02009-10-29 12:23:02 +00004652
Stefan Krah1919b7e2012-03-21 18:25:23 +01004653class CFunctionality(unittest.TestCase):
4654 """Extra functionality in _decimal"""
Mark Dickinsona2d1fe02009-10-29 12:23:02 +00004655
Stefan Krah1919b7e2012-03-21 18:25:23 +01004656 @requires_extra_functionality
4657 def test_c_ieee_context(self):
4658 # issue 8786: Add support for IEEE 754 contexts to decimal module.
4659 IEEEContext = C.IEEEContext
4660 DECIMAL32 = C.DECIMAL32
4661 DECIMAL64 = C.DECIMAL64
4662 DECIMAL128 = C.DECIMAL128
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004663
Stefan Krah1919b7e2012-03-21 18:25:23 +01004664 def assert_rest(self, context):
4665 self.assertEqual(context.clamp, 1)
4666 assert_signals(self, context, 'traps', [])
4667 assert_signals(self, context, 'flags', [])
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004668
Stefan Krah1919b7e2012-03-21 18:25:23 +01004669 c = IEEEContext(DECIMAL32)
4670 self.assertEqual(c.prec, 7)
4671 self.assertEqual(c.Emax, 96)
4672 self.assertEqual(c.Emin, -95)
4673 assert_rest(self, c)
Raymond Hettinger82417ca2009-02-03 03:54:28 +00004674
Stefan Krah1919b7e2012-03-21 18:25:23 +01004675 c = IEEEContext(DECIMAL64)
4676 self.assertEqual(c.prec, 16)
4677 self.assertEqual(c.Emax, 384)
4678 self.assertEqual(c.Emin, -383)
4679 assert_rest(self, c)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004680
Stefan Krah1919b7e2012-03-21 18:25:23 +01004681 c = IEEEContext(DECIMAL128)
4682 self.assertEqual(c.prec, 34)
4683 self.assertEqual(c.Emax, 6144)
4684 self.assertEqual(c.Emin, -6143)
4685 assert_rest(self, c)
Raymond Hettinger5548be22004-07-05 18:49:38 +00004686
Stefan Krah1919b7e2012-03-21 18:25:23 +01004687 # Invalid values
4688 self.assertRaises(OverflowError, IEEEContext, 2**63)
4689 self.assertRaises(ValueError, IEEEContext, -1)
4690 self.assertRaises(ValueError, IEEEContext, 1024)
Mark Dickinson825fce32009-09-07 18:08:12 +00004691
Stefan Krah1919b7e2012-03-21 18:25:23 +01004692 @requires_extra_functionality
4693 def test_c_context(self):
4694 Context = C.Context
Christian Heimes969fe572008-01-25 11:23:10 +00004695
Stefan Krah1919b7e2012-03-21 18:25:23 +01004696 c = Context(flags=C.DecClamped, traps=C.DecRounded)
4697 self.assertEqual(c._flags, C.DecClamped)
4698 self.assertEqual(c._traps, C.DecRounded)
Raymond Hettinger771ed762009-01-03 19:20:32 +00004699
Stefan Krah1919b7e2012-03-21 18:25:23 +01004700 @requires_extra_functionality
4701 def test_constants(self):
4702 # Condition flags
4703 cond = (
4704 C.DecClamped, C.DecConversionSyntax, C.DecDivisionByZero,
4705 C.DecDivisionImpossible, C.DecDivisionUndefined,
4706 C.DecFpuError, C.DecInexact, C.DecInvalidContext,
4707 C.DecInvalidOperation, C.DecMallocError,
4708 C.DecFloatOperation, C.DecOverflow, C.DecRounded,
4709 C.DecSubnormal, C.DecUnderflow
Raymond Hettinger771ed762009-01-03 19:20:32 +00004710 )
Stefan Krah1919b7e2012-03-21 18:25:23 +01004711
4712 # IEEEContext
4713 self.assertEqual(C.DECIMAL32, 32)
4714 self.assertEqual(C.DECIMAL64, 64)
4715 self.assertEqual(C.DECIMAL128, 128)
4716 self.assertEqual(C.IEEE_CONTEXT_MAX_BITS, 512)
4717
Stefan Krah1919b7e2012-03-21 18:25:23 +01004718 # Conditions
4719 for i, v in enumerate(cond):
4720 self.assertEqual(v, 1<<i)
4721
4722 self.assertEqual(C.DecIEEEInvalidOperation,
4723 C.DecConversionSyntax|
4724 C.DecDivisionImpossible|
4725 C.DecDivisionUndefined|
4726 C.DecFpuError|
4727 C.DecInvalidContext|
4728 C.DecInvalidOperation|
4729 C.DecMallocError)
4730
4731 self.assertEqual(C.DecErrors,
4732 C.DecIEEEInvalidOperation|
4733 C.DecDivisionByZero)
4734
4735 self.assertEqual(C.DecTraps,
4736 C.DecErrors|C.DecOverflow|C.DecUnderflow)
4737
4738class CWhitebox(unittest.TestCase):
4739 """Whitebox testing for _decimal"""
4740
4741 def test_bignum(self):
4742 # Not exactly whitebox, but too slow with pydecimal.
4743
4744 Decimal = C.Decimal
4745 localcontext = C.localcontext
4746
4747 b1 = 10**35
4748 b2 = 10**36
4749 with localcontext() as c:
4750 c.prec = 1000000
4751 for i in range(5):
4752 a = random.randrange(b1, b2)
4753 b = random.randrange(1000, 1200)
4754 x = a ** b
4755 y = Decimal(a) ** Decimal(b)
4756 self.assertEqual(x, y)
4757
4758 def test_invalid_construction(self):
4759 self.assertRaises(TypeError, C.Decimal, 9, "xyz")
4760
4761 def test_c_input_restriction(self):
4762 # Too large for _decimal to be converted exactly
4763 Decimal = C.Decimal
4764 InvalidOperation = C.InvalidOperation
4765 Context = C.Context
4766 localcontext = C.localcontext
4767
4768 with localcontext(Context()):
4769 self.assertRaises(InvalidOperation, Decimal,
4770 "1e9999999999999999999")
4771
4772 def test_c_context_repr(self):
4773 # This test is _decimal-only because flags are not printed
4774 # in the same order.
4775 DefaultContext = C.DefaultContext
4776 FloatOperation = C.FloatOperation
Stefan Krah1919b7e2012-03-21 18:25:23 +01004777
4778 c = DefaultContext.copy()
4779
4780 c.prec = 425000000
4781 c.Emax = 425000000
4782 c.Emin = -425000000
4783 c.rounding = ROUND_HALF_DOWN
4784 c.capitals = 0
4785 c.clamp = 1
4786 for sig in OrderedSignals[C]:
4787 c.flags[sig] = True
4788 c.traps[sig] = True
4789 c.flags[FloatOperation] = True
4790 c.traps[FloatOperation] = True
4791
4792 s = c.__repr__()
4793 t = "Context(prec=425000000, rounding=ROUND_HALF_DOWN, " \
4794 "Emin=-425000000, Emax=425000000, capitals=0, clamp=1, " \
4795 "flags=[Clamped, InvalidOperation, DivisionByZero, Inexact, " \
4796 "FloatOperation, Overflow, Rounded, Subnormal, Underflow], " \
4797 "traps=[Clamped, InvalidOperation, DivisionByZero, Inexact, " \
4798 "FloatOperation, Overflow, Rounded, Subnormal, Underflow])"
4799 self.assertEqual(s, t)
4800
4801 def test_c_context_errors(self):
4802 Context = C.Context
4803 InvalidOperation = C.InvalidOperation
4804 Overflow = C.Overflow
4805 FloatOperation = C.FloatOperation
4806 localcontext = C.localcontext
4807 getcontext = C.getcontext
4808 setcontext = C.setcontext
4809 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
4810
4811 c = Context()
4812
4813 # SignalDict: input validation
4814 self.assertRaises(KeyError, c.flags.__setitem__, 801, 0)
4815 self.assertRaises(KeyError, c.traps.__setitem__, 801, 0)
4816 self.assertRaises(ValueError, c.flags.__delitem__, Overflow)
4817 self.assertRaises(ValueError, c.traps.__delitem__, InvalidOperation)
4818 self.assertRaises(TypeError, setattr, c, 'flags', ['x'])
4819 self.assertRaises(TypeError, setattr, c,'traps', ['y'])
4820 self.assertRaises(KeyError, setattr, c, 'flags', {0:1})
4821 self.assertRaises(KeyError, setattr, c, 'traps', {0:1})
4822
4823 # Test assignment from a signal dict with the correct length but
4824 # one invalid key.
4825 d = c.flags.copy()
4826 del d[FloatOperation]
4827 d["XYZ"] = 91283719
4828 self.assertRaises(KeyError, setattr, c, 'flags', d)
4829 self.assertRaises(KeyError, setattr, c, 'traps', d)
4830
4831 # Input corner cases
4832 int_max = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
4833 gt_max_emax = 10**18 if HAVE_CONFIG_64 else 10**9
4834
4835 # prec, Emax, Emin
4836 for attr in ['prec', 'Emax']:
4837 self.assertRaises(ValueError, setattr, c, attr, gt_max_emax)
4838 self.assertRaises(ValueError, setattr, c, 'Emin', -gt_max_emax)
4839
4840 # prec, Emax, Emin in context constructor
4841 self.assertRaises(ValueError, Context, prec=gt_max_emax)
4842 self.assertRaises(ValueError, Context, Emax=gt_max_emax)
4843 self.assertRaises(ValueError, Context, Emin=-gt_max_emax)
4844
4845 # Overflow in conversion
4846 self.assertRaises(OverflowError, Context, prec=int_max+1)
4847 self.assertRaises(OverflowError, Context, Emax=int_max+1)
4848 self.assertRaises(OverflowError, Context, Emin=-int_max-2)
Stefan Krah1919b7e2012-03-21 18:25:23 +01004849 self.assertRaises(OverflowError, Context, clamp=int_max+1)
4850 self.assertRaises(OverflowError, Context, capitals=int_max+1)
4851
4852 # OverflowError, general ValueError
4853 for attr in ('prec', 'Emin', 'Emax', 'capitals', 'clamp'):
4854 self.assertRaises(OverflowError, setattr, c, attr, int_max+1)
4855 self.assertRaises(OverflowError, setattr, c, attr, -int_max-2)
4856 if sys.platform != 'win32':
4857 self.assertRaises(ValueError, setattr, c, attr, int_max)
4858 self.assertRaises(ValueError, setattr, c, attr, -int_max-1)
4859
Stefan Krah1919b7e2012-03-21 18:25:23 +01004860 # OverflowError: _unsafe_setprec, _unsafe_setemin, _unsafe_setemax
4861 if C.MAX_PREC == 425000000:
4862 self.assertRaises(OverflowError, getattr(c, '_unsafe_setprec'),
4863 int_max+1)
4864 self.assertRaises(OverflowError, getattr(c, '_unsafe_setemax'),
4865 int_max+1)
4866 self.assertRaises(OverflowError, getattr(c, '_unsafe_setemin'),
4867 -int_max-2)
4868
4869 # ValueError: _unsafe_setprec, _unsafe_setemin, _unsafe_setemax
4870 if C.MAX_PREC == 425000000:
4871 self.assertRaises(ValueError, getattr(c, '_unsafe_setprec'), 0)
4872 self.assertRaises(ValueError, getattr(c, '_unsafe_setprec'),
4873 1070000001)
4874 self.assertRaises(ValueError, getattr(c, '_unsafe_setemax'), -1)
4875 self.assertRaises(ValueError, getattr(c, '_unsafe_setemax'),
4876 1070000001)
4877 self.assertRaises(ValueError, getattr(c, '_unsafe_setemin'),
4878 -1070000001)
4879 self.assertRaises(ValueError, getattr(c, '_unsafe_setemin'), 1)
4880
4881 # capitals, clamp
4882 for attr in ['capitals', 'clamp']:
4883 self.assertRaises(ValueError, setattr, c, attr, -1)
4884 self.assertRaises(ValueError, setattr, c, attr, 2)
4885 self.assertRaises(TypeError, setattr, c, attr, [1,2,3])
4886 if HAVE_CONFIG_64:
4887 self.assertRaises(ValueError, setattr, c, attr, 2**32)
4888 self.assertRaises(ValueError, setattr, c, attr, 2**32+1)
4889
4890 # Invalid local context
4891 self.assertRaises(TypeError, exec, 'with localcontext("xyz"): pass',
4892 locals())
Stefan Krah040e3112012-12-15 22:33:33 +01004893 self.assertRaises(TypeError, exec,
4894 'with localcontext(context=getcontext()): pass',
4895 locals())
Stefan Krah1919b7e2012-03-21 18:25:23 +01004896
4897 # setcontext
4898 saved_context = getcontext()
4899 self.assertRaises(TypeError, setcontext, "xyz")
4900 setcontext(saved_context)
4901
Stefan Krah59a4a932013-01-16 12:58:59 +01004902 def test_rounding_strings_interned(self):
4903
4904 self.assertIs(C.ROUND_UP, P.ROUND_UP)
4905 self.assertIs(C.ROUND_DOWN, P.ROUND_DOWN)
4906 self.assertIs(C.ROUND_CEILING, P.ROUND_CEILING)
4907 self.assertIs(C.ROUND_FLOOR, P.ROUND_FLOOR)
4908 self.assertIs(C.ROUND_HALF_UP, P.ROUND_HALF_UP)
4909 self.assertIs(C.ROUND_HALF_DOWN, P.ROUND_HALF_DOWN)
4910 self.assertIs(C.ROUND_HALF_EVEN, P.ROUND_HALF_EVEN)
4911 self.assertIs(C.ROUND_05UP, P.ROUND_05UP)
4912
Stefan Krah1919b7e2012-03-21 18:25:23 +01004913 @requires_extra_functionality
4914 def test_c_context_errors_extra(self):
4915 Context = C.Context
4916 InvalidOperation = C.InvalidOperation
4917 Overflow = C.Overflow
4918 localcontext = C.localcontext
4919 getcontext = C.getcontext
4920 setcontext = C.setcontext
4921 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
4922
4923 c = Context()
4924
4925 # Input corner cases
4926 int_max = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
4927
4928 # OverflowError, general ValueError
4929 self.assertRaises(OverflowError, setattr, c, '_allcr', int_max+1)
4930 self.assertRaises(OverflowError, setattr, c, '_allcr', -int_max-2)
4931 if sys.platform != 'win32':
4932 self.assertRaises(ValueError, setattr, c, '_allcr', int_max)
4933 self.assertRaises(ValueError, setattr, c, '_allcr', -int_max-1)
4934
4935 # OverflowError, general TypeError
4936 for attr in ('_flags', '_traps'):
4937 self.assertRaises(OverflowError, setattr, c, attr, int_max+1)
4938 self.assertRaises(OverflowError, setattr, c, attr, -int_max-2)
4939 if sys.platform != 'win32':
4940 self.assertRaises(TypeError, setattr, c, attr, int_max)
4941 self.assertRaises(TypeError, setattr, c, attr, -int_max-1)
4942
4943 # _allcr
4944 self.assertRaises(ValueError, setattr, c, '_allcr', -1)
4945 self.assertRaises(ValueError, setattr, c, '_allcr', 2)
4946 self.assertRaises(TypeError, setattr, c, '_allcr', [1,2,3])
4947 if HAVE_CONFIG_64:
4948 self.assertRaises(ValueError, setattr, c, '_allcr', 2**32)
4949 self.assertRaises(ValueError, setattr, c, '_allcr', 2**32+1)
4950
4951 # _flags, _traps
4952 for attr in ['_flags', '_traps']:
4953 self.assertRaises(TypeError, setattr, c, attr, 999999)
4954 self.assertRaises(TypeError, setattr, c, attr, 'x')
4955
4956 def test_c_valid_context(self):
4957 # These tests are for code coverage in _decimal.
4958 DefaultContext = C.DefaultContext
Stefan Krah1919b7e2012-03-21 18:25:23 +01004959 Clamped = C.Clamped
4960 Underflow = C.Underflow
4961 Inexact = C.Inexact
4962 Rounded = C.Rounded
4963 Subnormal = C.Subnormal
4964
4965 c = DefaultContext.copy()
4966
4967 # Exercise all getters and setters
4968 c.prec = 34
4969 c.rounding = ROUND_HALF_UP
4970 c.Emax = 3000
4971 c.Emin = -3000
4972 c.capitals = 1
4973 c.clamp = 0
4974
4975 self.assertEqual(c.prec, 34)
4976 self.assertEqual(c.rounding, ROUND_HALF_UP)
4977 self.assertEqual(c.Emin, -3000)
4978 self.assertEqual(c.Emax, 3000)
4979 self.assertEqual(c.capitals, 1)
4980 self.assertEqual(c.clamp, 0)
4981
4982 self.assertEqual(c.Etiny(), -3033)
4983 self.assertEqual(c.Etop(), 2967)
4984
4985 # Exercise all unsafe setters
4986 if C.MAX_PREC == 425000000:
4987 c._unsafe_setprec(999999999)
4988 c._unsafe_setemax(999999999)
4989 c._unsafe_setemin(-999999999)
4990 self.assertEqual(c.prec, 999999999)
4991 self.assertEqual(c.Emax, 999999999)
4992 self.assertEqual(c.Emin, -999999999)
4993
4994 @requires_extra_functionality
4995 def test_c_valid_context_extra(self):
4996 DefaultContext = C.DefaultContext
4997
4998 c = DefaultContext.copy()
4999 self.assertEqual(c._allcr, 1)
5000 c._allcr = 0
5001 self.assertEqual(c._allcr, 0)
5002
5003 def test_c_round(self):
5004 # Restricted input.
5005 Decimal = C.Decimal
5006 InvalidOperation = C.InvalidOperation
5007 localcontext = C.localcontext
5008 MAX_EMAX = C.MAX_EMAX
5009 MIN_ETINY = C.MIN_ETINY
5010 int_max = 2**63-1 if C.MAX_PREC > 425000000 else 2**31-1
5011
5012 with localcontext() as c:
5013 c.traps[InvalidOperation] = True
5014 self.assertRaises(InvalidOperation, Decimal("1.23").__round__,
5015 -int_max-1)
5016 self.assertRaises(InvalidOperation, Decimal("1.23").__round__,
5017 int_max)
5018 self.assertRaises(InvalidOperation, Decimal("1").__round__,
5019 int(MAX_EMAX+1))
5020 self.assertRaises(C.InvalidOperation, Decimal("1").__round__,
5021 -int(MIN_ETINY-1))
5022 self.assertRaises(OverflowError, Decimal("1.23").__round__,
5023 -int_max-2)
5024 self.assertRaises(OverflowError, Decimal("1.23").__round__,
5025 int_max+1)
5026
5027 def test_c_format(self):
5028 # Restricted input
5029 Decimal = C.Decimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01005030 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
5031
5032 self.assertRaises(TypeError, Decimal(1).__format__, "=10.10", [], 9)
5033 self.assertRaises(TypeError, Decimal(1).__format__, "=10.10", 9)
5034 self.assertRaises(TypeError, Decimal(1).__format__, [])
5035
Stefan Kraheb8c4512013-01-24 15:22:33 +01005036 self.assertRaises(ValueError, Decimal(1).__format__, "<>=10.10")
5037 maxsize = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
5038 self.assertRaises(ValueError, Decimal("1.23456789").__format__,
5039 "=%d.1" % maxsize)
Stefan Krah1919b7e2012-03-21 18:25:23 +01005040
5041 def test_c_integral(self):
5042 Decimal = C.Decimal
5043 Inexact = C.Inexact
Stefan Krah1919b7e2012-03-21 18:25:23 +01005044 localcontext = C.localcontext
5045
5046 x = Decimal(10)
5047 self.assertEqual(x.to_integral(), 10)
5048 self.assertRaises(TypeError, x.to_integral, '10')
5049 self.assertRaises(TypeError, x.to_integral, 10, 'x')
5050 self.assertRaises(TypeError, x.to_integral, 10)
5051
5052 self.assertEqual(x.to_integral_value(), 10)
5053 self.assertRaises(TypeError, x.to_integral_value, '10')
5054 self.assertRaises(TypeError, x.to_integral_value, 10, 'x')
5055 self.assertRaises(TypeError, x.to_integral_value, 10)
5056
5057 self.assertEqual(x.to_integral_exact(), 10)
5058 self.assertRaises(TypeError, x.to_integral_exact, '10')
5059 self.assertRaises(TypeError, x.to_integral_exact, 10, 'x')
5060 self.assertRaises(TypeError, x.to_integral_exact, 10)
5061
5062 with localcontext() as c:
5063 x = Decimal("99999999999999999999999999.9").to_integral_value(ROUND_UP)
5064 self.assertEqual(x, Decimal('100000000000000000000000000'))
5065
5066 x = Decimal("99999999999999999999999999.9").to_integral_exact(ROUND_UP)
5067 self.assertEqual(x, Decimal('100000000000000000000000000'))
5068
5069 c.traps[Inexact] = True
5070 self.assertRaises(Inexact, Decimal("999.9").to_integral_exact, ROUND_UP)
5071
5072 def test_c_funcs(self):
5073 # Invalid arguments
5074 Decimal = C.Decimal
5075 InvalidOperation = C.InvalidOperation
5076 DivisionByZero = C.DivisionByZero
Stefan Krah1919b7e2012-03-21 18:25:23 +01005077 getcontext = C.getcontext
5078 localcontext = C.localcontext
5079
5080 self.assertEqual(Decimal('9.99e10').to_eng_string(), '99.9E+9')
5081
5082 self.assertRaises(TypeError, pow, Decimal(1), 2, "3")
5083 self.assertRaises(TypeError, Decimal(9).number_class, "x", "y")
5084 self.assertRaises(TypeError, Decimal(9).same_quantum, 3, "x", "y")
5085
Raymond Hettinger771ed762009-01-03 19:20:32 +00005086 self.assertRaises(
Stefan Krah1919b7e2012-03-21 18:25:23 +01005087 TypeError,
5088 Decimal("1.23456789").quantize, Decimal('1e-100000'), []
Raymond Hettinger771ed762009-01-03 19:20:32 +00005089 )
Stefan Krah1919b7e2012-03-21 18:25:23 +01005090 self.assertRaises(
5091 TypeError,
5092 Decimal("1.23456789").quantize, Decimal('1e-100000'), getcontext()
5093 )
5094 self.assertRaises(
5095 TypeError,
5096 Decimal("1.23456789").quantize, Decimal('1e-100000'), 10
5097 )
5098 self.assertRaises(
5099 TypeError,
5100 Decimal("1.23456789").quantize, Decimal('1e-100000'), ROUND_UP, 1000
5101 )
Raymond Hettinger771ed762009-01-03 19:20:32 +00005102
Stefan Krah1919b7e2012-03-21 18:25:23 +01005103 with localcontext() as c:
5104 c.clear_traps()
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00005105
Stefan Krah1919b7e2012-03-21 18:25:23 +01005106 # Invalid arguments
5107 self.assertRaises(TypeError, c.copy_sign, Decimal(1), "x", "y")
5108 self.assertRaises(TypeError, c.canonical, 200)
5109 self.assertRaises(TypeError, c.is_canonical, 200)
5110 self.assertRaises(TypeError, c.divmod, 9, 8, "x", "y")
5111 self.assertRaises(TypeError, c.same_quantum, 9, 3, "x", "y")
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00005112
Stefan Krah1919b7e2012-03-21 18:25:23 +01005113 self.assertEqual(str(c.canonical(Decimal(200))), '200')
5114 self.assertEqual(c.radix(), 10)
Raymond Hettinger0aeac102004-07-05 22:53:03 +00005115
Stefan Krah1919b7e2012-03-21 18:25:23 +01005116 c.traps[DivisionByZero] = True
5117 self.assertRaises(DivisionByZero, Decimal(9).__divmod__, 0)
5118 self.assertRaises(DivisionByZero, c.divmod, 9, 0)
5119 self.assertTrue(c.flags[InvalidOperation])
Raymond Hettinger955d2b22004-08-08 20:17:45 +00005120
Stefan Krah1919b7e2012-03-21 18:25:23 +01005121 c.clear_flags()
5122 c.traps[InvalidOperation] = True
5123 self.assertRaises(InvalidOperation, Decimal(9).__divmod__, 0)
5124 self.assertRaises(InvalidOperation, c.divmod, 9, 0)
5125 self.assertTrue(c.flags[DivisionByZero])
Mark Dickinsonb1d8e322010-05-22 18:35:36 +00005126
Stefan Krah1919b7e2012-03-21 18:25:23 +01005127 c.traps[InvalidOperation] = True
5128 c.prec = 2
5129 self.assertRaises(InvalidOperation, pow, Decimal(1000), 1, 501)
Mark Dickinson84230a12010-02-18 14:49:50 +00005130
Stefan Krah040e3112012-12-15 22:33:33 +01005131 def test_va_args_exceptions(self):
5132 Decimal = C.Decimal
5133 Context = C.Context
5134
5135 x = Decimal("10001111111")
5136
5137 for attr in ['exp', 'is_normal', 'is_subnormal', 'ln', 'log10',
5138 'logb', 'logical_invert', 'next_minus', 'next_plus',
5139 'normalize', 'number_class', 'sqrt', 'to_eng_string']:
5140 func = getattr(x, attr)
5141 self.assertRaises(TypeError, func, context="x")
5142 self.assertRaises(TypeError, func, "x", context=None)
5143
5144 for attr in ['compare', 'compare_signal', 'logical_and',
5145 'logical_or', 'max', 'max_mag', 'min', 'min_mag',
5146 'remainder_near', 'rotate', 'scaleb', 'shift']:
5147 func = getattr(x, attr)
5148 self.assertRaises(TypeError, func, context="x")
5149 self.assertRaises(TypeError, func, "x", context=None)
5150
5151 self.assertRaises(TypeError, x.to_integral, rounding=None, context=[])
5152 self.assertRaises(TypeError, x.to_integral, rounding={}, context=[])
5153 self.assertRaises(TypeError, x.to_integral, [], [])
5154
5155 self.assertRaises(TypeError, x.to_integral_value, rounding=None, context=[])
5156 self.assertRaises(TypeError, x.to_integral_value, rounding={}, context=[])
5157 self.assertRaises(TypeError, x.to_integral_value, [], [])
5158
5159 self.assertRaises(TypeError, x.to_integral_exact, rounding=None, context=[])
5160 self.assertRaises(TypeError, x.to_integral_exact, rounding={}, context=[])
5161 self.assertRaises(TypeError, x.to_integral_exact, [], [])
5162
5163 self.assertRaises(TypeError, x.fma, 1, 2, context="x")
5164 self.assertRaises(TypeError, x.fma, 1, 2, "x", context=None)
5165
5166 self.assertRaises(TypeError, x.quantize, 1, [], context=None)
5167 self.assertRaises(TypeError, x.quantize, 1, [], rounding=None)
5168 self.assertRaises(TypeError, x.quantize, 1, [], [])
5169
5170 c = Context()
5171 self.assertRaises(TypeError, c.power, 1, 2, mod="x")
5172 self.assertRaises(TypeError, c.power, 1, "x", mod=None)
5173 self.assertRaises(TypeError, c.power, "x", 2, mod=None)
5174
Stefan Krah1919b7e2012-03-21 18:25:23 +01005175 @requires_extra_functionality
5176 def test_c_context_templates(self):
5177 self.assertEqual(
5178 C.BasicContext._traps,
5179 C.DecIEEEInvalidOperation|C.DecDivisionByZero|C.DecOverflow|
5180 C.DecUnderflow|C.DecClamped
5181 )
5182 self.assertEqual(
5183 C.DefaultContext._traps,
5184 C.DecIEEEInvalidOperation|C.DecDivisionByZero|C.DecOverflow
5185 )
Mark Dickinson84230a12010-02-18 14:49:50 +00005186
Stefan Krah1919b7e2012-03-21 18:25:23 +01005187 @requires_extra_functionality
5188 def test_c_signal_dict(self):
Mark Dickinson84230a12010-02-18 14:49:50 +00005189
Stefan Krah1919b7e2012-03-21 18:25:23 +01005190 # SignalDict coverage
5191 Context = C.Context
5192 DefaultContext = C.DefaultContext
Mark Dickinson84230a12010-02-18 14:49:50 +00005193
Stefan Krah1919b7e2012-03-21 18:25:23 +01005194 InvalidOperation = C.InvalidOperation
5195 DivisionByZero = C.DivisionByZero
5196 Overflow = C.Overflow
5197 Subnormal = C.Subnormal
5198 Underflow = C.Underflow
5199 Rounded = C.Rounded
5200 Inexact = C.Inexact
5201 Clamped = C.Clamped
Mark Dickinson84230a12010-02-18 14:49:50 +00005202
Stefan Krah1919b7e2012-03-21 18:25:23 +01005203 DecClamped = C.DecClamped
5204 DecInvalidOperation = C.DecInvalidOperation
5205 DecIEEEInvalidOperation = C.DecIEEEInvalidOperation
Mark Dickinson84230a12010-02-18 14:49:50 +00005206
Stefan Krah1919b7e2012-03-21 18:25:23 +01005207 def assertIsExclusivelySet(signal, signal_dict):
5208 for sig in signal_dict:
5209 if sig == signal:
5210 self.assertTrue(signal_dict[sig])
5211 else:
5212 self.assertFalse(signal_dict[sig])
Mark Dickinson84230a12010-02-18 14:49:50 +00005213
Stefan Krah1919b7e2012-03-21 18:25:23 +01005214 c = DefaultContext.copy()
Mark Dickinson84230a12010-02-18 14:49:50 +00005215
Stefan Krah1919b7e2012-03-21 18:25:23 +01005216 # Signal dict methods
5217 self.assertTrue(Overflow in c.traps)
5218 c.clear_traps()
5219 for k in c.traps.keys():
5220 c.traps[k] = True
5221 for v in c.traps.values():
5222 self.assertTrue(v)
5223 c.clear_traps()
5224 for k, v in c.traps.items():
5225 self.assertFalse(v)
Mark Dickinson84230a12010-02-18 14:49:50 +00005226
Stefan Krah1919b7e2012-03-21 18:25:23 +01005227 self.assertFalse(c.flags.get(Overflow))
5228 self.assertIs(c.flags.get("x"), None)
5229 self.assertEqual(c.flags.get("x", "y"), "y")
5230 self.assertRaises(TypeError, c.flags.get, "x", "y", "z")
Mark Dickinson84230a12010-02-18 14:49:50 +00005231
Stefan Krah1919b7e2012-03-21 18:25:23 +01005232 self.assertEqual(len(c.flags), len(c.traps))
5233 s = sys.getsizeof(c.flags)
5234 s = sys.getsizeof(c.traps)
5235 s = c.flags.__repr__()
Mark Dickinson84230a12010-02-18 14:49:50 +00005236
Stefan Krah1919b7e2012-03-21 18:25:23 +01005237 # Set flags/traps.
5238 c.clear_flags()
5239 c._flags = DecClamped
5240 self.assertTrue(c.flags[Clamped])
Mark Dickinson84230a12010-02-18 14:49:50 +00005241
Stefan Krah1919b7e2012-03-21 18:25:23 +01005242 c.clear_traps()
5243 c._traps = DecInvalidOperation
5244 self.assertTrue(c.traps[InvalidOperation])
Mark Dickinson84230a12010-02-18 14:49:50 +00005245
Stefan Krah1919b7e2012-03-21 18:25:23 +01005246 # Set flags/traps from dictionary.
5247 c.clear_flags()
5248 d = c.flags.copy()
5249 d[DivisionByZero] = True
5250 c.flags = d
5251 assertIsExclusivelySet(DivisionByZero, c.flags)
Mark Dickinson84230a12010-02-18 14:49:50 +00005252
Stefan Krah1919b7e2012-03-21 18:25:23 +01005253 c.clear_traps()
5254 d = c.traps.copy()
5255 d[Underflow] = True
5256 c.traps = d
5257 assertIsExclusivelySet(Underflow, c.traps)
Mark Dickinson84230a12010-02-18 14:49:50 +00005258
Stefan Krah1919b7e2012-03-21 18:25:23 +01005259 # Random constructors
5260 IntSignals = {
5261 Clamped: C.DecClamped,
5262 Rounded: C.DecRounded,
5263 Inexact: C.DecInexact,
5264 Subnormal: C.DecSubnormal,
5265 Underflow: C.DecUnderflow,
5266 Overflow: C.DecOverflow,
5267 DivisionByZero: C.DecDivisionByZero,
5268 InvalidOperation: C.DecIEEEInvalidOperation
5269 }
5270 IntCond = [
5271 C.DecDivisionImpossible, C.DecDivisionUndefined, C.DecFpuError,
5272 C.DecInvalidContext, C.DecInvalidOperation, C.DecMallocError,
5273 C.DecConversionSyntax,
5274 ]
Mark Dickinsonb455e582011-05-22 12:53:18 +01005275
Stefan Krah1919b7e2012-03-21 18:25:23 +01005276 lim = len(OrderedSignals[C])
5277 for r in range(lim):
5278 for t in range(lim):
Stefan Krah59a4a932013-01-16 12:58:59 +01005279 for round in RoundingModes:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005280 flags = random.sample(OrderedSignals[C], r)
5281 traps = random.sample(OrderedSignals[C], t)
5282 prec = random.randrange(1, 10000)
5283 emin = random.randrange(-10000, 0)
5284 emax = random.randrange(0, 10000)
5285 clamp = random.randrange(0, 2)
5286 caps = random.randrange(0, 2)
5287 cr = random.randrange(0, 2)
5288 c = Context(prec=prec, rounding=round, Emin=emin, Emax=emax,
5289 capitals=caps, clamp=clamp, flags=list(flags),
5290 traps=list(traps))
Mark Dickinson84230a12010-02-18 14:49:50 +00005291
Stefan Krah1919b7e2012-03-21 18:25:23 +01005292 self.assertEqual(c.prec, prec)
5293 self.assertEqual(c.rounding, round)
5294 self.assertEqual(c.Emin, emin)
5295 self.assertEqual(c.Emax, emax)
5296 self.assertEqual(c.capitals, caps)
5297 self.assertEqual(c.clamp, clamp)
Mark Dickinson84230a12010-02-18 14:49:50 +00005298
Stefan Krah1919b7e2012-03-21 18:25:23 +01005299 f = 0
5300 for x in flags:
5301 f |= IntSignals[x]
5302 self.assertEqual(c._flags, f)
Mark Dickinson84230a12010-02-18 14:49:50 +00005303
Stefan Krah1919b7e2012-03-21 18:25:23 +01005304 f = 0
5305 for x in traps:
5306 f |= IntSignals[x]
5307 self.assertEqual(c._traps, f)
Mark Dickinson84230a12010-02-18 14:49:50 +00005308
Stefan Krah1919b7e2012-03-21 18:25:23 +01005309 for cond in IntCond:
5310 c._flags = cond
5311 self.assertTrue(c._flags&DecIEEEInvalidOperation)
5312 assertIsExclusivelySet(InvalidOperation, c.flags)
Mark Dickinson84230a12010-02-18 14:49:50 +00005313
Stefan Krah1919b7e2012-03-21 18:25:23 +01005314 for cond in IntCond:
5315 c._traps = cond
5316 self.assertTrue(c._traps&DecIEEEInvalidOperation)
5317 assertIsExclusivelySet(InvalidOperation, c.traps)
Mark Dickinson84230a12010-02-18 14:49:50 +00005318
Stefan Krah1919b7e2012-03-21 18:25:23 +01005319 def test_invalid_override(self):
5320 Decimal = C.Decimal
Mark Dickinson84230a12010-02-18 14:49:50 +00005321
Stefan Krah1919b7e2012-03-21 18:25:23 +01005322 try:
5323 from locale import CHAR_MAX
5324 except ImportError:
Zachary Ware9fe6d862013-12-08 00:20:35 -06005325 self.skipTest('locale.CHAR_MAX not available')
Mark Dickinson84230a12010-02-18 14:49:50 +00005326
Stefan Krah1919b7e2012-03-21 18:25:23 +01005327 def make_grouping(lst):
5328 return ''.join([chr(x) for x in lst])
Mark Dickinson84230a12010-02-18 14:49:50 +00005329
Stefan Krah1919b7e2012-03-21 18:25:23 +01005330 def get_fmt(x, override=None, fmt='n'):
5331 return Decimal(x).__format__(fmt, override)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005332
Stefan Krah1919b7e2012-03-21 18:25:23 +01005333 invalid_grouping = {
5334 'decimal_point' : ',',
5335 'grouping' : make_grouping([255, 255, 0]),
5336 'thousands_sep' : ','
5337 }
5338 invalid_dot = {
5339 'decimal_point' : 'xxxxx',
5340 'grouping' : make_grouping([3, 3, 0]),
5341 'thousands_sep' : ','
5342 }
5343 invalid_sep = {
5344 'decimal_point' : '.',
5345 'grouping' : make_grouping([3, 3, 0]),
5346 'thousands_sep' : 'yyyyy'
5347 }
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005348
Stefan Krah1919b7e2012-03-21 18:25:23 +01005349 if CHAR_MAX == 127: # negative grouping in override
5350 self.assertRaises(ValueError, get_fmt, 12345,
5351 invalid_grouping, 'g')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005352
Stefan Krah1919b7e2012-03-21 18:25:23 +01005353 self.assertRaises(ValueError, get_fmt, 12345, invalid_dot, 'g')
5354 self.assertRaises(ValueError, get_fmt, 12345, invalid_sep, 'g')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005355
Stefan Krah0774e9b2012-04-05 15:21:58 +02005356 def test_exact_conversion(self):
5357 Decimal = C.Decimal
5358 localcontext = C.localcontext
5359 InvalidOperation = C.InvalidOperation
5360
5361 with localcontext() as c:
5362
5363 c.traps[InvalidOperation] = True
5364
5365 # Clamped
5366 x = "0e%d" % sys.maxsize
5367 self.assertRaises(InvalidOperation, Decimal, x)
5368
5369 x = "0e%d" % (-sys.maxsize-1)
5370 self.assertRaises(InvalidOperation, Decimal, x)
5371
5372 # Overflow
5373 x = "1e%d" % sys.maxsize
5374 self.assertRaises(InvalidOperation, Decimal, x)
5375
5376 # Underflow
5377 x = "1e%d" % (-sys.maxsize-1)
5378 self.assertRaises(InvalidOperation, Decimal, x)
5379
Stefan Krahff3eca02012-04-05 15:46:19 +02005380 def test_from_tuple(self):
5381 Decimal = C.Decimal
5382 localcontext = C.localcontext
5383 InvalidOperation = C.InvalidOperation
5384 Overflow = C.Overflow
5385 Underflow = C.Underflow
5386
5387 with localcontext() as c:
5388
5389 c.traps[InvalidOperation] = True
5390 c.traps[Overflow] = True
5391 c.traps[Underflow] = True
5392
5393 # SSIZE_MAX
5394 x = (1, (), sys.maxsize)
5395 self.assertEqual(str(c.create_decimal(x)), '-0E+999999')
5396 self.assertRaises(InvalidOperation, Decimal, x)
5397
5398 x = (1, (0, 1, 2), sys.maxsize)
5399 self.assertRaises(Overflow, c.create_decimal, x)
5400 self.assertRaises(InvalidOperation, Decimal, x)
5401
5402 # SSIZE_MIN
5403 x = (1, (), -sys.maxsize-1)
5404 self.assertEqual(str(c.create_decimal(x)), '-0E-1000026')
5405 self.assertRaises(InvalidOperation, Decimal, x)
5406
5407 x = (1, (0, 1, 2), -sys.maxsize-1)
5408 self.assertRaises(Underflow, c.create_decimal, x)
5409 self.assertRaises(InvalidOperation, Decimal, x)
5410
5411 # OverflowError
5412 x = (1, (), sys.maxsize+1)
5413 self.assertRaises(OverflowError, c.create_decimal, x)
5414 self.assertRaises(OverflowError, Decimal, x)
5415
5416 x = (1, (), -sys.maxsize-2)
5417 self.assertRaises(OverflowError, c.create_decimal, x)
5418 self.assertRaises(OverflowError, Decimal, x)
5419
5420 # Specials
5421 x = (1, (), "N")
5422 self.assertEqual(str(Decimal(x)), '-sNaN')
5423 x = (1, (0,), "N")
5424 self.assertEqual(str(Decimal(x)), '-sNaN')
5425 x = (1, (0, 1), "N")
5426 self.assertEqual(str(Decimal(x)), '-sNaN1')
5427
Stefan Krah891ca9e2013-05-29 19:14:17 +02005428 def test_sizeof(self):
5429 Decimal = C.Decimal
5430 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
5431
5432 self.assertGreater(Decimal(0).__sizeof__(), 0)
5433 if HAVE_CONFIG_64:
5434 x = Decimal(10**(19*24)).__sizeof__()
5435 y = Decimal(10**(19*25)).__sizeof__()
5436 self.assertEqual(y, x+8)
5437 else:
5438 x = Decimal(10**(9*24)).__sizeof__()
5439 y = Decimal(10**(9*25)).__sizeof__()
5440 self.assertEqual(y, x+4)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005441
Stefan Krah8c126f12016-07-17 14:01:42 +02005442 def test_internal_use_of_overridden_methods(self):
5443 Decimal = C.Decimal
5444
5445 # Unsound subtyping
5446 class X(float):
5447 def as_integer_ratio(self):
5448 return 1
5449 def __abs__(self):
5450 return self
5451
5452 class Y(float):
5453 def __abs__(self):
5454 return [1]*200
5455
5456 class I(int):
5457 def bit_length(self):
5458 return [1]*200
5459
5460 class Z(float):
5461 def as_integer_ratio(self):
5462 return (I(1), I(1))
5463 def __abs__(self):
5464 return self
5465
5466 for cls in X, Y, Z:
5467 self.assertEqual(Decimal.from_float(cls(101.1)),
5468 Decimal.from_float(101.1))
5469
Stefan Krah6b794b82014-05-01 17:42:33 +02005470@requires_docstrings
5471@unittest.skipUnless(C, "test requires C version")
Stefan Krah5de1f822014-05-01 15:53:42 +02005472class SignatureTest(unittest.TestCase):
5473 """Function signatures"""
5474
5475 def test_inspect_module(self):
5476 for attr in dir(P):
5477 if attr.startswith('_'):
5478 continue
5479 p_func = getattr(P, attr)
5480 c_func = getattr(C, attr)
5481 if (attr == 'Decimal' or attr == 'Context' or
5482 inspect.isfunction(p_func)):
5483 p_sig = inspect.signature(p_func)
5484 c_sig = inspect.signature(c_func)
5485
5486 # parameter names:
5487 c_names = list(c_sig.parameters.keys())
5488 p_names = [x for x in p_sig.parameters.keys() if not
5489 x.startswith('_')]
5490
5491 self.assertEqual(c_names, p_names,
5492 msg="parameter name mismatch in %s" % p_func)
5493
5494 c_kind = [x.kind for x in c_sig.parameters.values()]
5495 p_kind = [x[1].kind for x in p_sig.parameters.items() if not
5496 x[0].startswith('_')]
5497
5498 # parameters:
5499 if attr != 'setcontext':
5500 self.assertEqual(c_kind, p_kind,
5501 msg="parameter kind mismatch in %s" % p_func)
5502
5503 def test_inspect_types(self):
5504
5505 POS = inspect._ParameterKind.POSITIONAL_ONLY
5506 POS_KWD = inspect._ParameterKind.POSITIONAL_OR_KEYWORD
5507
5508 # Type heuristic (type annotations would help!):
5509 pdict = {C: {'other': C.Decimal(1),
5510 'third': C.Decimal(1),
5511 'x': C.Decimal(1),
5512 'y': C.Decimal(1),
5513 'z': C.Decimal(1),
5514 'a': C.Decimal(1),
5515 'b': C.Decimal(1),
5516 'c': C.Decimal(1),
5517 'exp': C.Decimal(1),
5518 'modulo': C.Decimal(1),
5519 'num': "1",
5520 'f': 1.0,
5521 'rounding': C.ROUND_HALF_UP,
5522 'context': C.getcontext()},
5523 P: {'other': P.Decimal(1),
5524 'third': P.Decimal(1),
5525 'a': P.Decimal(1),
5526 'b': P.Decimal(1),
5527 'c': P.Decimal(1),
5528 'exp': P.Decimal(1),
5529 'modulo': P.Decimal(1),
5530 'num': "1",
5531 'f': 1.0,
5532 'rounding': P.ROUND_HALF_UP,
5533 'context': P.getcontext()}}
5534
5535 def mkargs(module, sig):
5536 args = []
5537 kwargs = {}
5538 for name, param in sig.parameters.items():
5539 if name == 'self': continue
5540 if param.kind == POS:
5541 args.append(pdict[module][name])
5542 elif param.kind == POS_KWD:
5543 kwargs[name] = pdict[module][name]
5544 else:
5545 raise TestFailed("unexpected parameter kind")
5546 return args, kwargs
5547
5548 def tr(s):
5549 """The C Context docstrings use 'x' in order to prevent confusion
5550 with the article 'a' in the descriptions."""
5551 if s == 'x': return 'a'
5552 if s == 'y': return 'b'
5553 if s == 'z': return 'c'
5554 return s
5555
5556 def doit(ty):
5557 p_type = getattr(P, ty)
5558 c_type = getattr(C, ty)
5559 for attr in dir(p_type):
5560 if attr.startswith('_'):
5561 continue
5562 p_func = getattr(p_type, attr)
5563 c_func = getattr(c_type, attr)
5564 if inspect.isfunction(p_func):
5565 p_sig = inspect.signature(p_func)
5566 c_sig = inspect.signature(c_func)
5567
5568 # parameter names:
5569 p_names = list(p_sig.parameters.keys())
5570 c_names = [tr(x) for x in c_sig.parameters.keys()]
5571
5572 self.assertEqual(c_names, p_names,
5573 msg="parameter name mismatch in %s" % p_func)
5574
5575 p_kind = [x.kind for x in p_sig.parameters.values()]
5576 c_kind = [x.kind for x in c_sig.parameters.values()]
5577
5578 # 'self' parameter:
5579 self.assertIs(p_kind[0], POS_KWD)
5580 self.assertIs(c_kind[0], POS)
5581
5582 # remaining parameters:
5583 if ty == 'Decimal':
5584 self.assertEqual(c_kind[1:], p_kind[1:],
5585 msg="parameter kind mismatch in %s" % p_func)
5586 else: # Context methods are positional only in the C version.
5587 self.assertEqual(len(c_kind), len(p_kind),
5588 msg="parameter kind mismatch in %s" % p_func)
5589
5590 # Run the function:
5591 args, kwds = mkargs(C, c_sig)
5592 try:
5593 getattr(c_type(9), attr)(*args, **kwds)
5594 except Exception as err:
5595 raise TestFailed("invalid signature for %s: %s %s" % (c_func, args, kwds))
5596
5597 args, kwds = mkargs(P, p_sig)
5598 try:
5599 getattr(p_type(9), attr)(*args, **kwds)
5600 except Exception as err:
5601 raise TestFailed("invalid signature for %s: %s %s" % (p_func, args, kwds))
5602
5603 doit('Decimal')
5604 doit('Context')
5605
5606
Stefan Krah1919b7e2012-03-21 18:25:23 +01005607all_tests = [
5608 CExplicitConstructionTest, PyExplicitConstructionTest,
5609 CImplicitConstructionTest, PyImplicitConstructionTest,
5610 CFormatTest, PyFormatTest,
5611 CArithmeticOperatorsTest, PyArithmeticOperatorsTest,
5612 CThreadingTest, PyThreadingTest,
5613 CUsabilityTest, PyUsabilityTest,
5614 CPythonAPItests, PyPythonAPItests,
5615 CContextAPItests, PyContextAPItests,
5616 CContextWithStatement, PyContextWithStatement,
5617 CContextFlags, PyContextFlags,
5618 CSpecialContexts, PySpecialContexts,
5619 CContextInputValidation, PyContextInputValidation,
5620 CContextSubclassing, PyContextSubclassing,
5621 CCoverage, PyCoverage,
5622 CFunctionality, PyFunctionality,
5623 CWhitebox, PyWhitebox,
5624 CIBMTestCases, PyIBMTestCases,
5625]
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005626
Stefan Krah1919b7e2012-03-21 18:25:23 +01005627# Delete C tests if _decimal.so is not present.
5628if not C:
5629 all_tests = all_tests[1::2]
5630else:
5631 all_tests.insert(0, CheckAttributes)
Stefan Krah5de1f822014-05-01 15:53:42 +02005632 all_tests.insert(1, SignatureTest)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005633
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005634
Zachary Ware66f29282014-06-02 16:01:29 -05005635def test_main(arith=None, verbose=None, todo_tests=None, debug=None):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005636 """ Execute the tests.
5637
Raymond Hettingered20ad82004-09-04 20:09:13 +00005638 Runs all arithmetic tests if arith is True or if the "decimal" resource
5639 is enabled in regrtest.py
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005640 """
Raymond Hettingered20ad82004-09-04 20:09:13 +00005641
Stefan Krah1919b7e2012-03-21 18:25:23 +01005642 init(C)
5643 init(P)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005644 global TEST_ALL, DEBUG
Zachary Ware66f29282014-06-02 16:01:29 -05005645 TEST_ALL = arith if arith is not None else is_resource_enabled('decimal')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005646 DEBUG = debug
Raymond Hettingered20ad82004-09-04 20:09:13 +00005647
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005648 if todo_tests is None:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005649 test_classes = all_tests
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005650 else:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005651 test_classes = [CIBMTestCases, PyIBMTestCases]
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005652
5653 # Dynamically build custom test definition for each file in the test
5654 # directory and add the definitions to the DecimalTest class. This
5655 # procedure insures that new files do not get skipped.
5656 for filename in os.listdir(directory):
5657 if '.decTest' not in filename or filename.startswith("."):
5658 continue
5659 head, tail = filename.split('.')
5660 if todo_tests is not None and head not in todo_tests:
5661 continue
5662 tester = lambda self, f=filename: self.eval_file(directory + f)
Stefan Krah1919b7e2012-03-21 18:25:23 +01005663 setattr(CIBMTestCases, 'test_' + head, tester)
5664 setattr(PyIBMTestCases, 'test_' + head, tester)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005665 del filename, head, tail, tester
5666
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005667
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005668 try:
5669 run_unittest(*test_classes)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005670 if todo_tests is None:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005671 from doctest import IGNORE_EXCEPTION_DETAIL
5672 savedecimal = sys.modules['decimal']
5673 if C:
5674 sys.modules['decimal'] = C
5675 run_doctest(C, verbose, optionflags=IGNORE_EXCEPTION_DETAIL)
5676 sys.modules['decimal'] = P
5677 run_doctest(P, verbose)
5678 sys.modules['decimal'] = savedecimal
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005679 finally:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005680 if C: C.setcontext(ORIGINAL_CONTEXT[C])
5681 P.setcontext(ORIGINAL_CONTEXT[P])
5682 if not C:
5683 warnings.warn('C tests skipped: no module named _decimal.',
5684 UserWarning)
5685 if not orig_sys_decimal is sys.modules['decimal']:
5686 raise TestFailed("Internal error: unbalanced number of changes to "
5687 "sys.modules['decimal'].")
5688
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005689
5690if __name__ == '__main__':
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005691 import optparse
5692 p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]")
5693 p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test')
5694 p.add_option('--skip', '-s', action='store_true', help='skip over 90% of the arithmetic tests')
5695 (opt, args) = p.parse_args()
5696
5697 if opt.skip:
5698 test_main(arith=False, verbose=True)
5699 elif args:
5700 test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005701 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005702 test_main(arith=True, verbose=True)