blob: 48360d1baedb641b444fbbbbb1deffba31c0d3cd [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
Andrew Nester6d1dece2017-02-14 21:22:55 +03001188 def test_decimal_from_float_argument_type(self):
1189 class A(self.decimal.Decimal):
1190 def __init__(self, a):
1191 self.a_type = type(a)
1192 a = A.from_float(42.5)
1193 self.assertEqual(self.decimal.Decimal, a.a_type)
1194
1195 a = A.from_float(42)
1196 self.assertEqual(self.decimal.Decimal, a.a_type)
1197
Stefan Krah1919b7e2012-03-21 18:25:23 +01001198class CFormatTest(FormatTest):
1199 decimal = C
1200class PyFormatTest(FormatTest):
1201 decimal = P
1202
1203class ArithmeticOperatorsTest(unittest.TestCase):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001204 '''Unit tests for all arithmetic operators, binary and unary.'''
1205
1206 def test_addition(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001207 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001208
1209 d1 = Decimal('-11.1')
1210 d2 = Decimal('22.2')
1211
1212 #two Decimals
1213 self.assertEqual(d1+d2, Decimal('11.1'))
1214 self.assertEqual(d2+d1, Decimal('11.1'))
1215
1216 #with other type, left
1217 c = d1 + 5
1218 self.assertEqual(c, Decimal('-6.1'))
1219 self.assertEqual(type(c), type(d1))
1220
1221 #with other type, right
1222 c = 5 + d1
1223 self.assertEqual(c, Decimal('-6.1'))
1224 self.assertEqual(type(c), type(d1))
1225
1226 #inline with decimal
1227 d1 += d2
1228 self.assertEqual(d1, Decimal('11.1'))
1229
1230 #inline with other type
1231 d1 += 5
1232 self.assertEqual(d1, Decimal('16.1'))
1233
1234 def test_subtraction(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001235 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001236
1237 d1 = Decimal('-11.1')
1238 d2 = Decimal('22.2')
1239
1240 #two Decimals
1241 self.assertEqual(d1-d2, Decimal('-33.3'))
1242 self.assertEqual(d2-d1, Decimal('33.3'))
1243
1244 #with other type, left
1245 c = d1 - 5
1246 self.assertEqual(c, Decimal('-16.1'))
1247 self.assertEqual(type(c), type(d1))
1248
1249 #with other type, right
1250 c = 5 - d1
1251 self.assertEqual(c, Decimal('16.1'))
1252 self.assertEqual(type(c), type(d1))
1253
1254 #inline with decimal
1255 d1 -= d2
1256 self.assertEqual(d1, Decimal('-33.3'))
1257
1258 #inline with other type
1259 d1 -= 5
1260 self.assertEqual(d1, Decimal('-38.3'))
1261
1262 def test_multiplication(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001263 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001264
1265 d1 = Decimal('-5')
1266 d2 = Decimal('3')
1267
1268 #two Decimals
1269 self.assertEqual(d1*d2, Decimal('-15'))
1270 self.assertEqual(d2*d1, Decimal('-15'))
1271
1272 #with other type, left
1273 c = d1 * 5
1274 self.assertEqual(c, Decimal('-25'))
1275 self.assertEqual(type(c), type(d1))
1276
1277 #with other type, right
1278 c = 5 * d1
1279 self.assertEqual(c, Decimal('-25'))
1280 self.assertEqual(type(c), type(d1))
1281
1282 #inline with decimal
1283 d1 *= d2
1284 self.assertEqual(d1, Decimal('-15'))
1285
1286 #inline with other type
1287 d1 *= 5
1288 self.assertEqual(d1, Decimal('-75'))
1289
1290 def test_division(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001291 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001292
1293 d1 = Decimal('-5')
1294 d2 = Decimal('2')
1295
1296 #two Decimals
1297 self.assertEqual(d1/d2, Decimal('-2.5'))
1298 self.assertEqual(d2/d1, Decimal('-0.4'))
1299
1300 #with other type, left
1301 c = d1 / 4
1302 self.assertEqual(c, Decimal('-1.25'))
1303 self.assertEqual(type(c), type(d1))
1304
1305 #with other type, right
1306 c = 4 / d1
1307 self.assertEqual(c, Decimal('-0.8'))
1308 self.assertEqual(type(c), type(d1))
1309
1310 #inline with decimal
1311 d1 /= d2
1312 self.assertEqual(d1, Decimal('-2.5'))
1313
1314 #inline with other type
1315 d1 /= 4
1316 self.assertEqual(d1, Decimal('-0.625'))
1317
1318 def test_floor_division(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001319 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001320
1321 d1 = Decimal('5')
1322 d2 = Decimal('2')
1323
1324 #two Decimals
1325 self.assertEqual(d1//d2, Decimal('2'))
1326 self.assertEqual(d2//d1, Decimal('0'))
1327
1328 #with other type, left
1329 c = d1 // 4
1330 self.assertEqual(c, Decimal('1'))
1331 self.assertEqual(type(c), type(d1))
1332
1333 #with other type, right
1334 c = 7 // d1
1335 self.assertEqual(c, Decimal('1'))
1336 self.assertEqual(type(c), type(d1))
1337
1338 #inline with decimal
1339 d1 //= d2
1340 self.assertEqual(d1, Decimal('2'))
1341
1342 #inline with other type
1343 d1 //= 2
1344 self.assertEqual(d1, Decimal('1'))
1345
1346 def test_powering(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001347 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001348
1349 d1 = Decimal('5')
1350 d2 = Decimal('2')
1351
1352 #two Decimals
1353 self.assertEqual(d1**d2, Decimal('25'))
1354 self.assertEqual(d2**d1, Decimal('32'))
1355
1356 #with other type, left
1357 c = d1 ** 4
1358 self.assertEqual(c, Decimal('625'))
1359 self.assertEqual(type(c), type(d1))
1360
1361 #with other type, right
1362 c = 7 ** d1
1363 self.assertEqual(c, Decimal('16807'))
1364 self.assertEqual(type(c), type(d1))
1365
1366 #inline with decimal
1367 d1 **= d2
1368 self.assertEqual(d1, Decimal('25'))
1369
1370 #inline with other type
1371 d1 **= 4
1372 self.assertEqual(d1, Decimal('390625'))
1373
1374 def test_module(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001375 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001376
1377 d1 = Decimal('5')
1378 d2 = Decimal('2')
1379
1380 #two Decimals
1381 self.assertEqual(d1%d2, Decimal('1'))
1382 self.assertEqual(d2%d1, Decimal('2'))
1383
1384 #with other type, left
1385 c = d1 % 4
1386 self.assertEqual(c, Decimal('1'))
1387 self.assertEqual(type(c), type(d1))
1388
1389 #with other type, right
1390 c = 7 % d1
1391 self.assertEqual(c, Decimal('2'))
1392 self.assertEqual(type(c), type(d1))
1393
1394 #inline with decimal
1395 d1 %= d2
1396 self.assertEqual(d1, Decimal('1'))
1397
1398 #inline with other type
1399 d1 %= 4
1400 self.assertEqual(d1, Decimal('1'))
1401
1402 def test_floor_div_module(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001403 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001404
1405 d1 = Decimal('5')
1406 d2 = Decimal('2')
1407
1408 #two Decimals
1409 (p, q) = divmod(d1, d2)
1410 self.assertEqual(p, Decimal('2'))
1411 self.assertEqual(q, Decimal('1'))
1412 self.assertEqual(type(p), type(d1))
1413 self.assertEqual(type(q), type(d1))
1414
1415 #with other type, left
1416 (p, q) = divmod(d1, 4)
1417 self.assertEqual(p, Decimal('1'))
1418 self.assertEqual(q, Decimal('1'))
1419 self.assertEqual(type(p), type(d1))
1420 self.assertEqual(type(q), type(d1))
1421
1422 #with other type, right
1423 (p, q) = divmod(7, d1)
1424 self.assertEqual(p, Decimal('1'))
1425 self.assertEqual(q, Decimal('2'))
1426 self.assertEqual(type(p), type(d1))
1427 self.assertEqual(type(q), type(d1))
1428
1429 def test_unary_operators(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001430 Decimal = self.decimal.Decimal
1431
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001432 self.assertEqual(+Decimal(45), Decimal(+45)) # +
1433 self.assertEqual(-Decimal(45), Decimal(-45)) # -
1434 self.assertEqual(abs(Decimal(45)), abs(Decimal(-45))) # abs
1435
Christian Heimes77c02eb2008-02-09 02:18:51 +00001436 def test_nan_comparisons(self):
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001437 # comparisons involving signaling nans signal InvalidOperation
1438
1439 # order comparisons (<, <=, >, >=) involving only quiet nans
1440 # also signal InvalidOperation
1441
1442 # equality comparisons (==, !=) involving only quiet nans
1443 # don't signal, but return False or True respectively.
Stefan Krah1919b7e2012-03-21 18:25:23 +01001444 Decimal = self.decimal.Decimal
1445 InvalidOperation = self.decimal.InvalidOperation
1446 localcontext = self.decimal.localcontext
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001447
Christian Heimes77c02eb2008-02-09 02:18:51 +00001448 n = Decimal('NaN')
1449 s = Decimal('sNaN')
1450 i = Decimal('Inf')
1451 f = Decimal('2')
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001452
1453 qnan_pairs = (n, n), (n, i), (i, n), (n, f), (f, n)
1454 snan_pairs = (s, n), (n, s), (s, i), (i, s), (s, f), (f, s), (s, s)
1455 order_ops = operator.lt, operator.le, operator.gt, operator.ge
1456 equality_ops = operator.eq, operator.ne
1457
1458 # results when InvalidOperation is not trapped
1459 for x, y in qnan_pairs + snan_pairs:
1460 for op in order_ops + equality_ops:
1461 got = op(x, y)
1462 expected = True if op is operator.ne else False
1463 self.assertIs(expected, got,
1464 "expected {0!r} for operator.{1}({2!r}, {3!r}); "
1465 "got {4!r}".format(
1466 expected, op.__name__, x, y, got))
1467
1468 # repeat the above, but this time trap the InvalidOperation
1469 with localcontext() as ctx:
1470 ctx.traps[InvalidOperation] = 1
1471
1472 for x, y in qnan_pairs:
1473 for op in equality_ops:
1474 got = op(x, y)
1475 expected = True if op is operator.ne else False
1476 self.assertIs(expected, got,
1477 "expected {0!r} for "
1478 "operator.{1}({2!r}, {3!r}); "
1479 "got {4!r}".format(
1480 expected, op.__name__, x, y, got))
1481
1482 for x, y in snan_pairs:
1483 for op in equality_ops:
1484 self.assertRaises(InvalidOperation, operator.eq, x, y)
1485 self.assertRaises(InvalidOperation, operator.ne, x, y)
1486
1487 for x, y in qnan_pairs + snan_pairs:
1488 for op in order_ops:
1489 self.assertRaises(InvalidOperation, op, x, y)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001490
Mark Dickinson84230a12010-02-18 14:49:50 +00001491 def test_copy_sign(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001492 Decimal = self.decimal.Decimal
Mark Dickinson84230a12010-02-18 14:49:50 +00001493
Stefan Krah1919b7e2012-03-21 18:25:23 +01001494 d = Decimal(1).copy_sign(Decimal(-2))
Mark Dickinson84230a12010-02-18 14:49:50 +00001495 self.assertEqual(Decimal(1).copy_sign(-2), d)
1496 self.assertRaises(TypeError, Decimal(1).copy_sign, '-2')
1497
Stefan Krah1919b7e2012-03-21 18:25:23 +01001498class CArithmeticOperatorsTest(ArithmeticOperatorsTest):
1499 decimal = C
1500class PyArithmeticOperatorsTest(ArithmeticOperatorsTest):
1501 decimal = P
1502
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001503# The following are two functions used to test threading in the next class
1504
1505def thfunc1(cls):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001506 Decimal = cls.decimal.Decimal
1507 InvalidOperation = cls.decimal.InvalidOperation
1508 DivisionByZero = cls.decimal.DivisionByZero
1509 Overflow = cls.decimal.Overflow
1510 Underflow = cls.decimal.Underflow
1511 Inexact = cls.decimal.Inexact
1512 getcontext = cls.decimal.getcontext
1513 localcontext = cls.decimal.localcontext
1514
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001515 d1 = Decimal(1)
1516 d3 = Decimal(3)
Christian Heimesfe337bf2008-03-23 21:54:12 +00001517 test1 = d1/d3
Christian Heimesfe337bf2008-03-23 21:54:12 +00001518
Stefan Krah1919b7e2012-03-21 18:25:23 +01001519 cls.finish1.set()
1520 cls.synchro.wait()
1521
1522 test2 = d1/d3
1523 with localcontext() as c2:
1524 cls.assertTrue(c2.flags[Inexact])
1525 cls.assertRaises(DivisionByZero, c2.divide, d1, 0)
1526 cls.assertTrue(c2.flags[DivisionByZero])
1527 with localcontext() as c3:
1528 cls.assertTrue(c3.flags[Inexact])
1529 cls.assertTrue(c3.flags[DivisionByZero])
1530 cls.assertRaises(InvalidOperation, c3.compare, d1, Decimal('sNaN'))
1531 cls.assertTrue(c3.flags[InvalidOperation])
1532 del c3
1533 cls.assertFalse(c2.flags[InvalidOperation])
1534 del c2
1535
1536 cls.assertEqual(test1, Decimal('0.333333333333333333333333'))
1537 cls.assertEqual(test2, Decimal('0.333333333333333333333333'))
1538
1539 c1 = getcontext()
1540 cls.assertTrue(c1.flags[Inexact])
1541 for sig in Overflow, Underflow, DivisionByZero, InvalidOperation:
1542 cls.assertFalse(c1.flags[sig])
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001543
1544def thfunc2(cls):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001545 Decimal = cls.decimal.Decimal
1546 InvalidOperation = cls.decimal.InvalidOperation
1547 DivisionByZero = cls.decimal.DivisionByZero
1548 Overflow = cls.decimal.Overflow
1549 Underflow = cls.decimal.Underflow
1550 Inexact = cls.decimal.Inexact
1551 getcontext = cls.decimal.getcontext
1552 localcontext = cls.decimal.localcontext
1553
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001554 d1 = Decimal(1)
1555 d3 = Decimal(3)
Christian Heimesfe337bf2008-03-23 21:54:12 +00001556 test1 = d1/d3
Stefan Krah1919b7e2012-03-21 18:25:23 +01001557
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001558 thiscontext = getcontext()
1559 thiscontext.prec = 18
Christian Heimesfe337bf2008-03-23 21:54:12 +00001560 test2 = d1/d3
Stefan Krah1919b7e2012-03-21 18:25:23 +01001561
1562 with localcontext() as c2:
1563 cls.assertTrue(c2.flags[Inexact])
1564 cls.assertRaises(Overflow, c2.multiply, Decimal('1e425000000'), 999)
1565 cls.assertTrue(c2.flags[Overflow])
1566 with localcontext(thiscontext) as c3:
1567 cls.assertTrue(c3.flags[Inexact])
1568 cls.assertFalse(c3.flags[Overflow])
1569 c3.traps[Underflow] = True
1570 cls.assertRaises(Underflow, c3.divide, Decimal('1e-425000000'), 999)
1571 cls.assertTrue(c3.flags[Underflow])
1572 del c3
1573 cls.assertFalse(c2.flags[Underflow])
1574 cls.assertFalse(c2.traps[Underflow])
1575 del c2
1576
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001577 cls.synchro.set()
1578 cls.finish2.set()
Christian Heimesfe337bf2008-03-23 21:54:12 +00001579
Stefan Krah1919b7e2012-03-21 18:25:23 +01001580 cls.assertEqual(test1, Decimal('0.333333333333333333333333'))
Christian Heimesfe337bf2008-03-23 21:54:12 +00001581 cls.assertEqual(test2, Decimal('0.333333333333333333'))
Stefan Krah1919b7e2012-03-21 18:25:23 +01001582
1583 cls.assertFalse(thiscontext.traps[Underflow])
1584 cls.assertTrue(thiscontext.flags[Inexact])
1585 for sig in Overflow, Underflow, DivisionByZero, InvalidOperation:
1586 cls.assertFalse(thiscontext.flags[sig])
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001587
Stefan Krah1919b7e2012-03-21 18:25:23 +01001588class ThreadingTest(unittest.TestCase):
1589 '''Unit tests for thread local contexts in Decimal.'''
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001590
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001591 # Take care executing this test from IDLE, there's an issue in threading
1592 # that hangs IDLE and I couldn't find it
1593
1594 def test_threading(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001595 DefaultContext = self.decimal.DefaultContext
1596
1597 if self.decimal == C and not self.decimal.HAVE_THREADS:
1598 self.skipTest("compiled without threading")
1599 # Test the "threading isolation" of a Context. Also test changing
1600 # the DefaultContext, which acts as a template for the thread-local
1601 # contexts.
1602 save_prec = DefaultContext.prec
1603 save_emax = DefaultContext.Emax
1604 save_emin = DefaultContext.Emin
1605 DefaultContext.prec = 24
1606 DefaultContext.Emax = 425000000
1607 DefaultContext.Emin = -425000000
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001608
1609 self.synchro = threading.Event()
1610 self.finish1 = threading.Event()
1611 self.finish2 = threading.Event()
1612
1613 th1 = threading.Thread(target=thfunc1, args=(self,))
1614 th2 = threading.Thread(target=thfunc2, args=(self,))
1615
1616 th1.start()
1617 th2.start()
1618
1619 self.finish1.wait()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001620 self.finish2.wait()
Stefan Krah1919b7e2012-03-21 18:25:23 +01001621
1622 for sig in Signals[self.decimal]:
1623 self.assertFalse(DefaultContext.flags[sig])
1624
1625 DefaultContext.prec = save_prec
1626 DefaultContext.Emax = save_emax
1627 DefaultContext.Emin = save_emin
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001628
Stefan Krah1919b7e2012-03-21 18:25:23 +01001629@unittest.skipUnless(threading, 'threading required')
1630class CThreadingTest(ThreadingTest):
1631 decimal = C
1632@unittest.skipUnless(threading, 'threading required')
1633class PyThreadingTest(ThreadingTest):
1634 decimal = P
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001635
Stefan Krah1919b7e2012-03-21 18:25:23 +01001636class UsabilityTest(unittest.TestCase):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001637 '''Unit tests for Usability cases of Decimal.'''
1638
1639 def test_comparison_operators(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001640
Stefan Krah1919b7e2012-03-21 18:25:23 +01001641 Decimal = self.decimal.Decimal
1642
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001643 da = Decimal('23.42')
1644 db = Decimal('23.42')
1645 dc = Decimal('45')
1646
1647 #two Decimals
Ezio Melotti6607d512010-04-03 14:59:49 +00001648 self.assertGreater(dc, da)
1649 self.assertGreaterEqual(dc, da)
1650 self.assertLess(da, dc)
1651 self.assertLessEqual(da, dc)
Guido van Rossume61fd5b2007-07-11 12:20:59 +00001652 self.assertEqual(da, db)
Ezio Melotti6607d512010-04-03 14:59:49 +00001653 self.assertNotEqual(da, dc)
1654 self.assertLessEqual(da, db)
1655 self.assertGreaterEqual(da, db)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001656
1657 #a Decimal and an int
Ezio Melotti6607d512010-04-03 14:59:49 +00001658 self.assertGreater(dc, 23)
1659 self.assertLess(23, dc)
Guido van Rossume61fd5b2007-07-11 12:20:59 +00001660 self.assertEqual(dc, 45)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001661
1662 #a Decimal and uncomparable
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001663 self.assertNotEqual(da, 'ugly')
1664 self.assertNotEqual(da, 32.7)
1665 self.assertNotEqual(da, object())
1666 self.assertNotEqual(da, object)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001667
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001668 # sortable
Guido van Rossumc1f779c2007-07-03 08:25:58 +00001669 a = list(map(Decimal, range(100)))
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001670 b = a[:]
1671 random.shuffle(a)
1672 a.sort()
1673 self.assertEqual(a, b)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001674
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001675 def test_decimal_float_comparison(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001676 Decimal = self.decimal.Decimal
1677
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001678 da = Decimal('0.25')
1679 db = Decimal('3.0')
Ezio Melotti6607d512010-04-03 14:59:49 +00001680 self.assertLess(da, 3.0)
1681 self.assertLessEqual(da, 3.0)
1682 self.assertGreater(db, 0.25)
1683 self.assertGreaterEqual(db, 0.25)
1684 self.assertNotEqual(da, 1.5)
1685 self.assertEqual(da, 0.25)
1686 self.assertGreater(3.0, da)
1687 self.assertGreaterEqual(3.0, da)
1688 self.assertLess(0.25, db)
1689 self.assertLessEqual(0.25, db)
1690 self.assertNotEqual(0.25, db)
1691 self.assertEqual(3.0, db)
1692 self.assertNotEqual(0.1, Decimal('0.1'))
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001693
Stefan Krah1919b7e2012-03-21 18:25:23 +01001694 def test_decimal_complex_comparison(self):
1695 Decimal = self.decimal.Decimal
1696
1697 da = Decimal('0.25')
1698 db = Decimal('3.0')
1699 self.assertNotEqual(da, (1.5+0j))
1700 self.assertNotEqual((1.5+0j), da)
1701 self.assertEqual(da, (0.25+0j))
1702 self.assertEqual((0.25+0j), da)
1703 self.assertEqual((3.0+0j), db)
1704 self.assertEqual(db, (3.0+0j))
1705
1706 self.assertNotEqual(db, (3.0+1j))
1707 self.assertNotEqual((3.0+1j), db)
1708
1709 self.assertIs(db.__lt__(3.0+0j), NotImplemented)
1710 self.assertIs(db.__le__(3.0+0j), NotImplemented)
1711 self.assertIs(db.__gt__(3.0+0j), NotImplemented)
1712 self.assertIs(db.__le__(3.0+0j), NotImplemented)
1713
1714 def test_decimal_fraction_comparison(self):
1715 D = self.decimal.Decimal
1716 F = fractions[self.decimal].Fraction
1717 Context = self.decimal.Context
1718 localcontext = self.decimal.localcontext
1719 InvalidOperation = self.decimal.InvalidOperation
1720
1721
1722 emax = C.MAX_EMAX if C else 999999999
1723 emin = C.MIN_EMIN if C else -999999999
1724 etiny = C.MIN_ETINY if C else -1999999997
1725 c = Context(Emax=emax, Emin=emin)
1726
1727 with localcontext(c):
1728 c.prec = emax
1729 self.assertLess(D(0), F(1,9999999999999999999999999999999999999))
1730 self.assertLess(F(-1,9999999999999999999999999999999999999), D(0))
1731 self.assertLess(F(0,1), D("1e" + str(etiny)))
1732 self.assertLess(D("-1e" + str(etiny)), F(0,1))
1733 self.assertLess(F(0,9999999999999999999999999), D("1e" + str(etiny)))
1734 self.assertLess(D("-1e" + str(etiny)), F(0,9999999999999999999999999))
1735
1736 self.assertEqual(D("0.1"), F(1,10))
1737 self.assertEqual(F(1,10), D("0.1"))
1738
1739 c.prec = 300
1740 self.assertNotEqual(D(1)/3, F(1,3))
1741 self.assertNotEqual(F(1,3), D(1)/3)
1742
1743 self.assertLessEqual(F(120984237, 9999999999), D("9e" + str(emax)))
1744 self.assertGreaterEqual(D("9e" + str(emax)), F(120984237, 9999999999))
1745
1746 self.assertGreater(D('inf'), F(99999999999,123))
1747 self.assertGreater(D('inf'), F(-99999999999,123))
1748 self.assertLess(D('-inf'), F(99999999999,123))
1749 self.assertLess(D('-inf'), F(-99999999999,123))
1750
1751 self.assertRaises(InvalidOperation, D('nan').__gt__, F(-9,123))
1752 self.assertIs(NotImplemented, F(-9,123).__lt__(D('nan')))
1753 self.assertNotEqual(D('nan'), F(-9,123))
1754 self.assertNotEqual(F(-9,123), D('nan'))
1755
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001756 def test_copy_and_deepcopy_methods(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001757 Decimal = self.decimal.Decimal
1758
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001759 d = Decimal('43.24')
1760 c = copy.copy(d)
1761 self.assertEqual(id(c), id(d))
1762 dc = copy.deepcopy(d)
1763 self.assertEqual(id(dc), id(d))
1764
1765 def test_hash_method(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001766
1767 Decimal = self.decimal.Decimal
1768 localcontext = self.decimal.localcontext
1769
Stefan Krahdc817b22010-11-17 11:16:34 +00001770 def hashit(d):
1771 a = hash(d)
1772 b = d.__hash__()
1773 self.assertEqual(a, b)
1774 return a
1775
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001776 #just that it's hashable
Stefan Krahdc817b22010-11-17 11:16:34 +00001777 hashit(Decimal(23))
1778 hashit(Decimal('Infinity'))
1779 hashit(Decimal('-Infinity'))
1780 hashit(Decimal('nan123'))
1781 hashit(Decimal('-NaN'))
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001782
1783 test_values = [Decimal(sign*(2**m + n))
1784 for m in [0, 14, 15, 16, 17, 30, 31,
Stefan Krahdc817b22010-11-17 11:16:34 +00001785 32, 33, 61, 62, 63, 64, 65, 66]
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001786 for n in range(-10, 10)
1787 for sign in [-1, 1]]
1788 test_values.extend([
Stefan Krahdc817b22010-11-17 11:16:34 +00001789 Decimal("-1"), # ==> -2
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001790 Decimal("-0"), # zeros
1791 Decimal("0.00"),
1792 Decimal("-0.000"),
1793 Decimal("0E10"),
1794 Decimal("-0E12"),
1795 Decimal("10.0"), # negative exponent
1796 Decimal("-23.00000"),
1797 Decimal("1230E100"), # positive exponent
1798 Decimal("-4.5678E50"),
1799 # a value for which hash(n) != hash(n % (2**64-1))
1800 # in Python pre-2.6
1801 Decimal(2**64 + 2**32 - 1),
1802 # selection of values which fail with the old (before
1803 # version 2.6) long.__hash__
1804 Decimal("1.634E100"),
1805 Decimal("90.697E100"),
1806 Decimal("188.83E100"),
1807 Decimal("1652.9E100"),
1808 Decimal("56531E100"),
1809 ])
1810
1811 # check that hash(d) == hash(int(d)) for integral values
1812 for value in test_values:
Stefan Krahdc817b22010-11-17 11:16:34 +00001813 self.assertEqual(hashit(value), hashit(int(value)))
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001814
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001815 #the same hash that to an int
Stefan Krahdc817b22010-11-17 11:16:34 +00001816 self.assertEqual(hashit(Decimal(23)), hashit(23))
Raymond Hettingerd325c4b2010-11-21 04:08:28 +00001817 self.assertRaises(TypeError, hash, Decimal('sNaN'))
Stefan Krahdc817b22010-11-17 11:16:34 +00001818 self.assertTrue(hashit(Decimal('Inf')))
1819 self.assertTrue(hashit(Decimal('-Inf')))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001820
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001821 # check that the hashes of a Decimal float match when they
1822 # represent exactly the same values
1823 test_strings = ['inf', '-Inf', '0.0', '-.0e1',
1824 '34.0', '2.5', '112390.625', '-0.515625']
1825 for s in test_strings:
1826 f = float(s)
1827 d = Decimal(s)
Stefan Krahdc817b22010-11-17 11:16:34 +00001828 self.assertEqual(hashit(f), hashit(d))
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001829
Stefan Krah1919b7e2012-03-21 18:25:23 +01001830 with localcontext() as c:
1831 # check that the value of the hash doesn't depend on the
1832 # current context (issue #1757)
1833 x = Decimal("123456789.1")
Christian Heimes2380ac72008-01-09 00:17:24 +00001834
Stefan Krah1919b7e2012-03-21 18:25:23 +01001835 c.prec = 6
1836 h1 = hashit(x)
1837 c.prec = 10
1838 h2 = hashit(x)
1839 c.prec = 16
1840 h3 = hashit(x)
Christian Heimes2380ac72008-01-09 00:17:24 +00001841
Stefan Krah1919b7e2012-03-21 18:25:23 +01001842 self.assertEqual(h1, h2)
1843 self.assertEqual(h1, h3)
1844
1845 c.prec = 10000
1846 x = 1100 ** 1248
1847 self.assertEqual(hashit(Decimal(x)), hashit(x))
Christian Heimes2380ac72008-01-09 00:17:24 +00001848
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001849 def test_min_and_max_methods(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001850 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001851
1852 d1 = Decimal('15.32')
1853 d2 = Decimal('28.5')
1854 l1 = 15
1855 l2 = 28
1856
1857 #between Decimals
Ezio Melotti6607d512010-04-03 14:59:49 +00001858 self.assertIs(min(d1,d2), d1)
1859 self.assertIs(min(d2,d1), d1)
1860 self.assertIs(max(d1,d2), d2)
1861 self.assertIs(max(d2,d1), d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001862
Serhiy Storchaka95949422013-08-27 19:40:23 +03001863 #between Decimal and int
Ezio Melotti6607d512010-04-03 14:59:49 +00001864 self.assertIs(min(d1,l2), d1)
1865 self.assertIs(min(l2,d1), d1)
1866 self.assertIs(max(l1,d2), d2)
1867 self.assertIs(max(d2,l1), d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001868
1869 def test_as_nonzero(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001870 Decimal = self.decimal.Decimal
1871
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001872 #as false
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001873 self.assertFalse(Decimal(0))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001874 #as true
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001875 self.assertTrue(Decimal('0.372'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001876
1877 def test_tostring_methods(self):
1878 #Test str and repr methods.
Stefan Krah1919b7e2012-03-21 18:25:23 +01001879 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001880
1881 d = Decimal('15.32')
1882 self.assertEqual(str(d), '15.32') # str
Christian Heimes68f5fbe2008-02-14 08:27:37 +00001883 self.assertEqual(repr(d), "Decimal('15.32')") # repr
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001884
1885 def test_tonum_methods(self):
Mark Dickinson5c2db372009-12-05 20:28:34 +00001886 #Test float and int methods.
Stefan Krah1919b7e2012-03-21 18:25:23 +01001887 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001888
1889 d1 = Decimal('66')
1890 d2 = Decimal('15.32')
1891
1892 #int
1893 self.assertEqual(int(d1), 66)
1894 self.assertEqual(int(d2), 15)
1895
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001896 #float
1897 self.assertEqual(float(d1), 66)
1898 self.assertEqual(float(d2), 15.32)
1899
Mark Dickinsonb27406c2008-05-09 13:42:33 +00001900 #floor
1901 test_pairs = [
1902 ('123.00', 123),
1903 ('3.2', 3),
1904 ('3.54', 3),
1905 ('3.899', 3),
1906 ('-2.3', -3),
1907 ('-11.0', -11),
1908 ('0.0', 0),
1909 ('-0E3', 0),
Stefan Krah1919b7e2012-03-21 18:25:23 +01001910 ('89891211712379812736.1', 89891211712379812736),
Mark Dickinsonb27406c2008-05-09 13:42:33 +00001911 ]
1912 for d, i in test_pairs:
1913 self.assertEqual(math.floor(Decimal(d)), i)
1914 self.assertRaises(ValueError, math.floor, Decimal('-NaN'))
1915 self.assertRaises(ValueError, math.floor, Decimal('sNaN'))
1916 self.assertRaises(ValueError, math.floor, Decimal('NaN123'))
1917 self.assertRaises(OverflowError, math.floor, Decimal('Inf'))
1918 self.assertRaises(OverflowError, math.floor, Decimal('-Inf'))
1919
1920 #ceiling
1921 test_pairs = [
1922 ('123.00', 123),
1923 ('3.2', 4),
1924 ('3.54', 4),
1925 ('3.899', 4),
1926 ('-2.3', -2),
1927 ('-11.0', -11),
1928 ('0.0', 0),
1929 ('-0E3', 0),
Stefan Krah1919b7e2012-03-21 18:25:23 +01001930 ('89891211712379812736.1', 89891211712379812737),
Mark Dickinsonb27406c2008-05-09 13:42:33 +00001931 ]
1932 for d, i in test_pairs:
1933 self.assertEqual(math.ceil(Decimal(d)), i)
1934 self.assertRaises(ValueError, math.ceil, Decimal('-NaN'))
1935 self.assertRaises(ValueError, math.ceil, Decimal('sNaN'))
1936 self.assertRaises(ValueError, math.ceil, Decimal('NaN123'))
1937 self.assertRaises(OverflowError, math.ceil, Decimal('Inf'))
1938 self.assertRaises(OverflowError, math.ceil, Decimal('-Inf'))
1939
1940 #round, single argument
1941 test_pairs = [
1942 ('123.00', 123),
1943 ('3.2', 3),
1944 ('3.54', 4),
1945 ('3.899', 4),
1946 ('-2.3', -2),
1947 ('-11.0', -11),
1948 ('0.0', 0),
1949 ('-0E3', 0),
1950 ('-3.5', -4),
1951 ('-2.5', -2),
1952 ('-1.5', -2),
1953 ('-0.5', 0),
1954 ('0.5', 0),
1955 ('1.5', 2),
1956 ('2.5', 2),
1957 ('3.5', 4),
1958 ]
1959 for d, i in test_pairs:
1960 self.assertEqual(round(Decimal(d)), i)
1961 self.assertRaises(ValueError, round, Decimal('-NaN'))
1962 self.assertRaises(ValueError, round, Decimal('sNaN'))
1963 self.assertRaises(ValueError, round, Decimal('NaN123'))
1964 self.assertRaises(OverflowError, round, Decimal('Inf'))
1965 self.assertRaises(OverflowError, round, Decimal('-Inf'))
1966
1967 #round, two arguments; this is essentially equivalent
1968 #to quantize, which is already extensively tested
1969 test_triples = [
1970 ('123.456', -4, '0E+4'),
1971 ('123.456', -3, '0E+3'),
1972 ('123.456', -2, '1E+2'),
1973 ('123.456', -1, '1.2E+2'),
1974 ('123.456', 0, '123'),
1975 ('123.456', 1, '123.5'),
1976 ('123.456', 2, '123.46'),
1977 ('123.456', 3, '123.456'),
1978 ('123.456', 4, '123.4560'),
1979 ('123.455', 2, '123.46'),
1980 ('123.445', 2, '123.44'),
1981 ('Inf', 4, 'NaN'),
1982 ('-Inf', -23, 'NaN'),
1983 ('sNaN314', 3, 'NaN314'),
1984 ]
1985 for d, n, r in test_triples:
1986 self.assertEqual(str(round(Decimal(d), n)), r)
1987
Mark Dickinsonfc33d4c2012-08-24 18:53:10 +01001988 def test_nan_to_float(self):
1989 # Test conversions of decimal NANs to float.
1990 # See http://bugs.python.org/issue15544
1991 Decimal = self.decimal.Decimal
1992 for s in ('nan', 'nan1234', '-nan', '-nan2468'):
1993 f = float(Decimal(s))
1994 self.assertTrue(math.isnan(f))
1995 sign = math.copysign(1.0, f)
1996 self.assertEqual(sign, -1.0 if s.startswith('-') else 1.0)
1997
1998 def test_snan_to_float(self):
1999 Decimal = self.decimal.Decimal
2000 for s in ('snan', '-snan', 'snan1357', '-snan1234'):
2001 d = Decimal(s)
2002 self.assertRaises(ValueError, float, d)
2003
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002004 def test_eval_round_trip(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01002005 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002006
2007 #with zero
2008 d = Decimal( (0, (0,), 0) )
2009 self.assertEqual(d, eval(repr(d)))
2010
2011 #int
2012 d = Decimal( (1, (4, 5), 0) )
2013 self.assertEqual(d, eval(repr(d)))
2014
2015 #float
2016 d = Decimal( (0, (4, 5, 3, 4), -2) )
2017 self.assertEqual(d, eval(repr(d)))
2018
2019 #weird
2020 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
2021 self.assertEqual(d, eval(repr(d)))
2022
2023 def test_as_tuple(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01002024 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002025
2026 #with zero
2027 d = Decimal(0)
2028 self.assertEqual(d.as_tuple(), (0, (0,), 0) )
2029
2030 #int
2031 d = Decimal(-45)
2032 self.assertEqual(d.as_tuple(), (1, (4, 5), 0) )
2033
2034 #complicated string
2035 d = Decimal("-4.34913534E-17")
2036 self.assertEqual(d.as_tuple(), (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
2037
Stefan Krah76e12172012-09-10 19:34:58 +02002038 # The '0' coefficient is implementation specific to decimal.py.
2039 # It has no meaning in the C-version and is ignored there.
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002040 d = Decimal("Infinity")
2041 self.assertEqual(d.as_tuple(), (0, (0,), 'F') )
2042
Guido van Rossum8ce8a782007-11-01 19:42:39 +00002043 #leading zeros in coefficient should be stripped
2044 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), -2) )
2045 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), -2) )
2046 d = Decimal( (1, (0, 0, 0), 37) )
2047 self.assertEqual(d.as_tuple(), (1, (0,), 37))
2048 d = Decimal( (1, (), 37) )
2049 self.assertEqual(d.as_tuple(), (1, (0,), 37))
2050
2051 #leading zeros in NaN diagnostic info should be stripped
2052 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), 'n') )
2053 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), 'n') )
2054 d = Decimal( (1, (0, 0, 0), 'N') )
2055 self.assertEqual(d.as_tuple(), (1, (), 'N') )
2056 d = Decimal( (1, (), 'n') )
2057 self.assertEqual(d.as_tuple(), (1, (), 'n') )
2058
Stefan Krah76e12172012-09-10 19:34:58 +02002059 # For infinities, decimal.py has always silently accepted any
2060 # coefficient tuple.
2061 d = Decimal( (0, (0,), 'F') )
2062 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
2063 d = Decimal( (0, (4, 5, 3, 4), 'F') )
2064 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
2065 d = Decimal( (1, (0, 2, 7, 1), 'F') )
2066 self.assertEqual(d.as_tuple(), (1, (0,), 'F'))
Guido van Rossum8ce8a782007-11-01 19:42:39 +00002067
Stefan Krah53f2e0a2015-12-28 23:02:02 +01002068 def test_as_integer_ratio(self):
2069 Decimal = self.decimal.Decimal
2070
2071 # exceptional cases
2072 self.assertRaises(OverflowError,
2073 Decimal.as_integer_ratio, Decimal('inf'))
2074 self.assertRaises(OverflowError,
2075 Decimal.as_integer_ratio, Decimal('-inf'))
2076 self.assertRaises(ValueError,
2077 Decimal.as_integer_ratio, Decimal('-nan'))
2078 self.assertRaises(ValueError,
2079 Decimal.as_integer_ratio, Decimal('snan123'))
2080
2081 for exp in range(-4, 2):
2082 for coeff in range(1000):
2083 for sign in '+', '-':
2084 d = Decimal('%s%dE%d' % (sign, coeff, exp))
2085 pq = d.as_integer_ratio()
2086 p, q = pq
2087
2088 # check return type
2089 self.assertIsInstance(pq, tuple)
2090 self.assertIsInstance(p, int)
2091 self.assertIsInstance(q, int)
2092
2093 # check normalization: q should be positive;
2094 # p should be relatively prime to q.
2095 self.assertGreater(q, 0)
2096 self.assertEqual(math.gcd(p, q), 1)
2097
2098 # check that p/q actually gives the correct value
2099 self.assertEqual(Decimal(p) / Decimal(q), d)
2100
Stefan Krah1919b7e2012-03-21 18:25:23 +01002101 def test_subclassing(self):
2102 # Different behaviours when subclassing Decimal
2103 Decimal = self.decimal.Decimal
2104
2105 class MyDecimal(Decimal):
Stefan Krah0f82b762012-11-08 11:17:29 +01002106 y = None
Stefan Krah1919b7e2012-03-21 18:25:23 +01002107
2108 d1 = MyDecimal(1)
2109 d2 = MyDecimal(2)
2110 d = d1 + d2
2111 self.assertIs(type(d), Decimal)
2112
2113 d = d1.max(d2)
2114 self.assertIs(type(d), Decimal)
2115
2116 d = copy.copy(d1)
2117 self.assertIs(type(d), MyDecimal)
2118 self.assertEqual(d, d1)
2119
2120 d = copy.deepcopy(d1)
2121 self.assertIs(type(d), MyDecimal)
2122 self.assertEqual(d, d1)
2123
Stefan Krah0f82b762012-11-08 11:17:29 +01002124 # Decimal(Decimal)
2125 d = Decimal('1.0')
2126 x = Decimal(d)
2127 self.assertIs(type(x), Decimal)
2128 self.assertEqual(x, d)
Stefan Krahf4abc7b2012-11-07 23:12:25 +01002129
Stefan Krah0f82b762012-11-08 11:17:29 +01002130 # MyDecimal(Decimal)
2131 m = MyDecimal(d)
2132 self.assertIs(type(m), MyDecimal)
2133 self.assertEqual(m, d)
2134 self.assertIs(m.y, None)
2135
2136 # Decimal(MyDecimal)
2137 x = Decimal(m)
2138 self.assertIs(type(x), Decimal)
2139 self.assertEqual(x, d)
2140
2141 # MyDecimal(MyDecimal)
2142 m.y = 9
2143 x = MyDecimal(m)
2144 self.assertIs(type(x), MyDecimal)
2145 self.assertEqual(x, d)
2146 self.assertIs(x.y, None)
Stefan Krahed16eff2012-11-07 23:47:19 +01002147
Stefan Krah1919b7e2012-03-21 18:25:23 +01002148 def test_implicit_context(self):
2149 Decimal = self.decimal.Decimal
2150 getcontext = self.decimal.getcontext
2151
2152 # Check results when context given implicitly. (Issue 2478)
2153 c = getcontext()
2154 self.assertEqual(str(Decimal(0).sqrt()),
2155 str(c.sqrt(Decimal(0))))
2156
Stefan Krah040e3112012-12-15 22:33:33 +01002157 def test_none_args(self):
2158 Decimal = self.decimal.Decimal
2159 Context = self.decimal.Context
2160 localcontext = self.decimal.localcontext
2161 InvalidOperation = self.decimal.InvalidOperation
2162 DivisionByZero = self.decimal.DivisionByZero
2163 Overflow = self.decimal.Overflow
2164 Underflow = self.decimal.Underflow
2165 Subnormal = self.decimal.Subnormal
2166 Inexact = self.decimal.Inexact
2167 Rounded = self.decimal.Rounded
2168 Clamped = self.decimal.Clamped
Stefan Krah040e3112012-12-15 22:33:33 +01002169
2170 with localcontext(Context()) as c:
2171 c.prec = 7
2172 c.Emax = 999
2173 c.Emin = -999
2174
2175 x = Decimal("111")
2176 y = Decimal("1e9999")
2177 z = Decimal("1e-9999")
2178
2179 ##### Unary functions
2180 c.clear_flags()
2181 self.assertEqual(str(x.exp(context=None)), '1.609487E+48')
2182 self.assertTrue(c.flags[Inexact])
2183 self.assertTrue(c.flags[Rounded])
2184 c.clear_flags()
2185 self.assertRaises(Overflow, y.exp, context=None)
2186 self.assertTrue(c.flags[Overflow])
2187
2188 self.assertIs(z.is_normal(context=None), False)
2189 self.assertIs(z.is_subnormal(context=None), True)
2190
2191 c.clear_flags()
2192 self.assertEqual(str(x.ln(context=None)), '4.709530')
2193 self.assertTrue(c.flags[Inexact])
2194 self.assertTrue(c.flags[Rounded])
2195 c.clear_flags()
2196 self.assertRaises(InvalidOperation, Decimal(-1).ln, context=None)
2197 self.assertTrue(c.flags[InvalidOperation])
2198
2199 c.clear_flags()
2200 self.assertEqual(str(x.log10(context=None)), '2.045323')
2201 self.assertTrue(c.flags[Inexact])
2202 self.assertTrue(c.flags[Rounded])
2203 c.clear_flags()
2204 self.assertRaises(InvalidOperation, Decimal(-1).log10, context=None)
2205 self.assertTrue(c.flags[InvalidOperation])
2206
2207 c.clear_flags()
2208 self.assertEqual(str(x.logb(context=None)), '2')
2209 self.assertRaises(DivisionByZero, Decimal(0).logb, context=None)
2210 self.assertTrue(c.flags[DivisionByZero])
2211
2212 c.clear_flags()
2213 self.assertEqual(str(x.logical_invert(context=None)), '1111000')
2214 self.assertRaises(InvalidOperation, y.logical_invert, context=None)
2215 self.assertTrue(c.flags[InvalidOperation])
2216
2217 c.clear_flags()
2218 self.assertEqual(str(y.next_minus(context=None)), '9.999999E+999')
2219 self.assertRaises(InvalidOperation, Decimal('sNaN').next_minus, context=None)
2220 self.assertTrue(c.flags[InvalidOperation])
2221
2222 c.clear_flags()
2223 self.assertEqual(str(y.next_plus(context=None)), 'Infinity')
2224 self.assertRaises(InvalidOperation, Decimal('sNaN').next_plus, context=None)
2225 self.assertTrue(c.flags[InvalidOperation])
2226
2227 c.clear_flags()
2228 self.assertEqual(str(z.normalize(context=None)), '0')
2229 self.assertRaises(Overflow, y.normalize, context=None)
2230 self.assertTrue(c.flags[Overflow])
2231
2232 self.assertEqual(str(z.number_class(context=None)), '+Subnormal')
2233
2234 c.clear_flags()
2235 self.assertEqual(str(z.sqrt(context=None)), '0E-1005')
2236 self.assertTrue(c.flags[Clamped])
2237 self.assertTrue(c.flags[Inexact])
2238 self.assertTrue(c.flags[Rounded])
2239 self.assertTrue(c.flags[Subnormal])
2240 self.assertTrue(c.flags[Underflow])
2241 c.clear_flags()
2242 self.assertRaises(Overflow, y.sqrt, context=None)
2243 self.assertTrue(c.flags[Overflow])
2244
2245 c.capitals = 0
2246 self.assertEqual(str(z.to_eng_string(context=None)), '1e-9999')
2247 c.capitals = 1
2248
2249
2250 ##### Binary functions
2251 c.clear_flags()
2252 ans = str(x.compare(Decimal('Nan891287828'), context=None))
2253 self.assertEqual(ans, 'NaN1287828')
2254 self.assertRaises(InvalidOperation, x.compare, Decimal('sNaN'), context=None)
2255 self.assertTrue(c.flags[InvalidOperation])
2256
2257 c.clear_flags()
2258 ans = str(x.compare_signal(8224, context=None))
2259 self.assertEqual(ans, '-1')
2260 self.assertRaises(InvalidOperation, x.compare_signal, Decimal('NaN'), context=None)
2261 self.assertTrue(c.flags[InvalidOperation])
2262
2263 c.clear_flags()
2264 ans = str(x.logical_and(101, context=None))
2265 self.assertEqual(ans, '101')
2266 self.assertRaises(InvalidOperation, x.logical_and, 123, context=None)
2267 self.assertTrue(c.flags[InvalidOperation])
2268
2269 c.clear_flags()
2270 ans = str(x.logical_or(101, context=None))
2271 self.assertEqual(ans, '111')
2272 self.assertRaises(InvalidOperation, x.logical_or, 123, context=None)
2273 self.assertTrue(c.flags[InvalidOperation])
2274
2275 c.clear_flags()
2276 ans = str(x.logical_xor(101, context=None))
2277 self.assertEqual(ans, '10')
2278 self.assertRaises(InvalidOperation, x.logical_xor, 123, context=None)
2279 self.assertTrue(c.flags[InvalidOperation])
2280
2281 c.clear_flags()
2282 ans = str(x.max(101, context=None))
2283 self.assertEqual(ans, '111')
2284 self.assertRaises(InvalidOperation, x.max, Decimal('sNaN'), context=None)
2285 self.assertTrue(c.flags[InvalidOperation])
2286
2287 c.clear_flags()
2288 ans = str(x.max_mag(101, context=None))
2289 self.assertEqual(ans, '111')
2290 self.assertRaises(InvalidOperation, x.max_mag, Decimal('sNaN'), context=None)
2291 self.assertTrue(c.flags[InvalidOperation])
2292
2293 c.clear_flags()
2294 ans = str(x.min(101, context=None))
2295 self.assertEqual(ans, '101')
2296 self.assertRaises(InvalidOperation, x.min, Decimal('sNaN'), context=None)
2297 self.assertTrue(c.flags[InvalidOperation])
2298
2299 c.clear_flags()
2300 ans = str(x.min_mag(101, context=None))
2301 self.assertEqual(ans, '101')
2302 self.assertRaises(InvalidOperation, x.min_mag, Decimal('sNaN'), context=None)
2303 self.assertTrue(c.flags[InvalidOperation])
2304
2305 c.clear_flags()
2306 ans = str(x.remainder_near(101, context=None))
2307 self.assertEqual(ans, '10')
2308 self.assertRaises(InvalidOperation, y.remainder_near, 101, context=None)
2309 self.assertTrue(c.flags[InvalidOperation])
2310
2311 c.clear_flags()
2312 ans = str(x.rotate(2, context=None))
2313 self.assertEqual(ans, '11100')
2314 self.assertRaises(InvalidOperation, x.rotate, 101, context=None)
2315 self.assertTrue(c.flags[InvalidOperation])
2316
2317 c.clear_flags()
2318 ans = str(x.scaleb(7, context=None))
2319 self.assertEqual(ans, '1.11E+9')
2320 self.assertRaises(InvalidOperation, x.scaleb, 10000, context=None)
2321 self.assertTrue(c.flags[InvalidOperation])
2322
2323 c.clear_flags()
2324 ans = str(x.shift(2, context=None))
2325 self.assertEqual(ans, '11100')
2326 self.assertRaises(InvalidOperation, x.shift, 10000, context=None)
2327 self.assertTrue(c.flags[InvalidOperation])
2328
2329
2330 ##### Ternary functions
2331 c.clear_flags()
2332 ans = str(x.fma(2, 3, context=None))
2333 self.assertEqual(ans, '225')
2334 self.assertRaises(Overflow, x.fma, Decimal('1e9999'), 3, context=None)
2335 self.assertTrue(c.flags[Overflow])
2336
2337
2338 ##### Special cases
2339 c.rounding = ROUND_HALF_EVEN
2340 ans = str(Decimal('1.5').to_integral(rounding=None, context=None))
2341 self.assertEqual(ans, '2')
2342 c.rounding = ROUND_DOWN
2343 ans = str(Decimal('1.5').to_integral(rounding=None, context=None))
2344 self.assertEqual(ans, '1')
2345 ans = str(Decimal('1.5').to_integral(rounding=ROUND_UP, context=None))
2346 self.assertEqual(ans, '2')
2347 c.clear_flags()
2348 self.assertRaises(InvalidOperation, Decimal('sNaN').to_integral, context=None)
2349 self.assertTrue(c.flags[InvalidOperation])
2350
2351 c.rounding = ROUND_HALF_EVEN
2352 ans = str(Decimal('1.5').to_integral_value(rounding=None, context=None))
2353 self.assertEqual(ans, '2')
2354 c.rounding = ROUND_DOWN
2355 ans = str(Decimal('1.5').to_integral_value(rounding=None, context=None))
2356 self.assertEqual(ans, '1')
2357 ans = str(Decimal('1.5').to_integral_value(rounding=ROUND_UP, context=None))
2358 self.assertEqual(ans, '2')
2359 c.clear_flags()
2360 self.assertRaises(InvalidOperation, Decimal('sNaN').to_integral_value, context=None)
2361 self.assertTrue(c.flags[InvalidOperation])
2362
2363 c.rounding = ROUND_HALF_EVEN
2364 ans = str(Decimal('1.5').to_integral_exact(rounding=None, context=None))
2365 self.assertEqual(ans, '2')
2366 c.rounding = ROUND_DOWN
2367 ans = str(Decimal('1.5').to_integral_exact(rounding=None, context=None))
2368 self.assertEqual(ans, '1')
2369 ans = str(Decimal('1.5').to_integral_exact(rounding=ROUND_UP, context=None))
2370 self.assertEqual(ans, '2')
2371 c.clear_flags()
2372 self.assertRaises(InvalidOperation, Decimal('sNaN').to_integral_exact, context=None)
2373 self.assertTrue(c.flags[InvalidOperation])
2374
2375 c.rounding = ROUND_UP
2376 ans = str(Decimal('1.50001').quantize(exp=Decimal('1e-3'), rounding=None, context=None))
2377 self.assertEqual(ans, '1.501')
2378 c.rounding = ROUND_DOWN
2379 ans = str(Decimal('1.50001').quantize(exp=Decimal('1e-3'), rounding=None, context=None))
2380 self.assertEqual(ans, '1.500')
2381 ans = str(Decimal('1.50001').quantize(exp=Decimal('1e-3'), rounding=ROUND_UP, context=None))
2382 self.assertEqual(ans, '1.501')
2383 c.clear_flags()
2384 self.assertRaises(InvalidOperation, y.quantize, Decimal('1e-10'), rounding=ROUND_UP, context=None)
2385 self.assertTrue(c.flags[InvalidOperation])
2386
2387 with localcontext(Context()) as context:
2388 context.prec = 7
2389 context.Emax = 999
2390 context.Emin = -999
2391 with localcontext(ctx=None) as c:
2392 self.assertEqual(c.prec, 7)
2393 self.assertEqual(c.Emax, 999)
2394 self.assertEqual(c.Emin, -999)
2395
Stefan Krah1919b7e2012-03-21 18:25:23 +01002396 def test_conversions_from_int(self):
2397 # Check that methods taking a second Decimal argument will
2398 # always accept an integer in place of a Decimal.
2399 Decimal = self.decimal.Decimal
2400
2401 self.assertEqual(Decimal(4).compare(3),
2402 Decimal(4).compare(Decimal(3)))
2403 self.assertEqual(Decimal(4).compare_signal(3),
2404 Decimal(4).compare_signal(Decimal(3)))
2405 self.assertEqual(Decimal(4).compare_total(3),
2406 Decimal(4).compare_total(Decimal(3)))
2407 self.assertEqual(Decimal(4).compare_total_mag(3),
2408 Decimal(4).compare_total_mag(Decimal(3)))
2409 self.assertEqual(Decimal(10101).logical_and(1001),
2410 Decimal(10101).logical_and(Decimal(1001)))
2411 self.assertEqual(Decimal(10101).logical_or(1001),
2412 Decimal(10101).logical_or(Decimal(1001)))
2413 self.assertEqual(Decimal(10101).logical_xor(1001),
2414 Decimal(10101).logical_xor(Decimal(1001)))
2415 self.assertEqual(Decimal(567).max(123),
2416 Decimal(567).max(Decimal(123)))
2417 self.assertEqual(Decimal(567).max_mag(123),
2418 Decimal(567).max_mag(Decimal(123)))
2419 self.assertEqual(Decimal(567).min(123),
2420 Decimal(567).min(Decimal(123)))
2421 self.assertEqual(Decimal(567).min_mag(123),
2422 Decimal(567).min_mag(Decimal(123)))
2423 self.assertEqual(Decimal(567).next_toward(123),
2424 Decimal(567).next_toward(Decimal(123)))
2425 self.assertEqual(Decimal(1234).quantize(100),
2426 Decimal(1234).quantize(Decimal(100)))
2427 self.assertEqual(Decimal(768).remainder_near(1234),
2428 Decimal(768).remainder_near(Decimal(1234)))
2429 self.assertEqual(Decimal(123).rotate(1),
2430 Decimal(123).rotate(Decimal(1)))
2431 self.assertEqual(Decimal(1234).same_quantum(1000),
2432 Decimal(1234).same_quantum(Decimal(1000)))
2433 self.assertEqual(Decimal('9.123').scaleb(-100),
2434 Decimal('9.123').scaleb(Decimal(-100)))
2435 self.assertEqual(Decimal(456).shift(-1),
2436 Decimal(456).shift(Decimal(-1)))
2437
2438 self.assertEqual(Decimal(-12).fma(Decimal(45), 67),
2439 Decimal(-12).fma(Decimal(45), Decimal(67)))
2440 self.assertEqual(Decimal(-12).fma(45, 67),
2441 Decimal(-12).fma(Decimal(45), Decimal(67)))
2442 self.assertEqual(Decimal(-12).fma(45, Decimal(67)),
2443 Decimal(-12).fma(Decimal(45), Decimal(67)))
2444
2445class CUsabilityTest(UsabilityTest):
2446 decimal = C
2447class PyUsabilityTest(UsabilityTest):
2448 decimal = P
2449
2450class PythonAPItests(unittest.TestCase):
2451
2452 def test_abc(self):
2453 Decimal = self.decimal.Decimal
2454
2455 self.assertTrue(issubclass(Decimal, numbers.Number))
2456 self.assertFalse(issubclass(Decimal, numbers.Real))
2457 self.assertIsInstance(Decimal(0), numbers.Number)
2458 self.assertNotIsInstance(Decimal(0), numbers.Real)
2459
2460 def test_pickle(self):
Serhiy Storchakabad12572014-12-15 14:03:42 +02002461 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
2462 Decimal = self.decimal.Decimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01002463
Serhiy Storchakabad12572014-12-15 14:03:42 +02002464 savedecimal = sys.modules['decimal']
Stefan Krah1919b7e2012-03-21 18:25:23 +01002465
Serhiy Storchakabad12572014-12-15 14:03:42 +02002466 # Round trip
2467 sys.modules['decimal'] = self.decimal
2468 d = Decimal('-3.141590000')
2469 p = pickle.dumps(d, proto)
2470 e = pickle.loads(p)
2471 self.assertEqual(d, e)
Stefan Krah1919b7e2012-03-21 18:25:23 +01002472
Serhiy Storchakabad12572014-12-15 14:03:42 +02002473 if C:
2474 # Test interchangeability
2475 x = C.Decimal('-3.123e81723')
2476 y = P.Decimal('-3.123e81723')
Stefan Krah1919b7e2012-03-21 18:25:23 +01002477
Serhiy Storchakabad12572014-12-15 14:03:42 +02002478 sys.modules['decimal'] = C
2479 sx = pickle.dumps(x, proto)
2480 sys.modules['decimal'] = P
2481 r = pickle.loads(sx)
2482 self.assertIsInstance(r, P.Decimal)
2483 self.assertEqual(r, y)
Stefan Krah1919b7e2012-03-21 18:25:23 +01002484
Serhiy Storchakabad12572014-12-15 14:03:42 +02002485 sys.modules['decimal'] = P
2486 sy = pickle.dumps(y, proto)
2487 sys.modules['decimal'] = C
2488 r = pickle.loads(sy)
2489 self.assertIsInstance(r, C.Decimal)
2490 self.assertEqual(r, x)
Stefan Krah1919b7e2012-03-21 18:25:23 +01002491
Serhiy Storchakabad12572014-12-15 14:03:42 +02002492 x = C.Decimal('-3.123e81723').as_tuple()
2493 y = P.Decimal('-3.123e81723').as_tuple()
Stefan Krahf1d4e422014-04-29 18:23:35 +02002494
Serhiy Storchakabad12572014-12-15 14:03:42 +02002495 sys.modules['decimal'] = C
2496 sx = pickle.dumps(x, proto)
2497 sys.modules['decimal'] = P
2498 r = pickle.loads(sx)
2499 self.assertIsInstance(r, P.DecimalTuple)
2500 self.assertEqual(r, y)
Stefan Krahf1d4e422014-04-29 18:23:35 +02002501
Serhiy Storchakabad12572014-12-15 14:03:42 +02002502 sys.modules['decimal'] = P
2503 sy = pickle.dumps(y, proto)
2504 sys.modules['decimal'] = C
2505 r = pickle.loads(sy)
2506 self.assertIsInstance(r, C.DecimalTuple)
2507 self.assertEqual(r, x)
Stefan Krahf1d4e422014-04-29 18:23:35 +02002508
Serhiy Storchakabad12572014-12-15 14:03:42 +02002509 sys.modules['decimal'] = savedecimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01002510
2511 def test_int(self):
2512 Decimal = self.decimal.Decimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01002513
2514 for x in range(-250, 250):
2515 s = '%0.2f' % (x / 100.0)
2516 # should work the same as for floats
2517 self.assertEqual(int(Decimal(s)), int(float(s)))
2518 # should work the same as to_integral in the ROUND_DOWN mode
2519 d = Decimal(s)
2520 r = d.to_integral(ROUND_DOWN)
2521 self.assertEqual(Decimal(int(d)), r)
2522
2523 self.assertRaises(ValueError, int, Decimal('-nan'))
2524 self.assertRaises(ValueError, int, Decimal('snan'))
2525 self.assertRaises(OverflowError, int, Decimal('inf'))
2526 self.assertRaises(OverflowError, int, Decimal('-inf'))
2527
2528 def test_trunc(self):
2529 Decimal = self.decimal.Decimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01002530
2531 for x in range(-250, 250):
2532 s = '%0.2f' % (x / 100.0)
2533 # should work the same as for floats
2534 self.assertEqual(int(Decimal(s)), int(float(s)))
2535 # should work the same as to_integral in the ROUND_DOWN mode
2536 d = Decimal(s)
2537 r = d.to_integral(ROUND_DOWN)
2538 self.assertEqual(Decimal(math.trunc(d)), r)
2539
2540 def test_from_float(self):
2541
2542 Decimal = self.decimal.Decimal
2543
2544 class MyDecimal(Decimal):
Stefan Krah6817c592016-06-20 12:10:13 +02002545 def __init__(self, _):
2546 self.x = 'y'
Stefan Krah1919b7e2012-03-21 18:25:23 +01002547
2548 self.assertTrue(issubclass(MyDecimal, Decimal))
2549
2550 r = MyDecimal.from_float(0.1)
2551 self.assertEqual(type(r), MyDecimal)
2552 self.assertEqual(str(r),
2553 '0.1000000000000000055511151231257827021181583404541015625')
Stefan Krah6817c592016-06-20 12:10:13 +02002554 self.assertEqual(r.x, 'y')
2555
Stefan Krah1919b7e2012-03-21 18:25:23 +01002556 bigint = 12345678901234567890123456789
2557 self.assertEqual(MyDecimal.from_float(bigint), MyDecimal(bigint))
2558 self.assertTrue(MyDecimal.from_float(float('nan')).is_qnan())
2559 self.assertTrue(MyDecimal.from_float(float('inf')).is_infinite())
2560 self.assertTrue(MyDecimal.from_float(float('-inf')).is_infinite())
2561 self.assertEqual(str(MyDecimal.from_float(float('nan'))),
2562 str(Decimal('NaN')))
2563 self.assertEqual(str(MyDecimal.from_float(float('inf'))),
2564 str(Decimal('Infinity')))
2565 self.assertEqual(str(MyDecimal.from_float(float('-inf'))),
2566 str(Decimal('-Infinity')))
2567 self.assertRaises(TypeError, MyDecimal.from_float, 'abc')
2568 for i in range(200):
2569 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
2570 self.assertEqual(x, float(MyDecimal.from_float(x))) # roundtrip
2571
2572 def test_create_decimal_from_float(self):
2573 Decimal = self.decimal.Decimal
2574 Context = self.decimal.Context
Stefan Krah1919b7e2012-03-21 18:25:23 +01002575 Inexact = self.decimal.Inexact
2576
2577 context = Context(prec=5, rounding=ROUND_DOWN)
2578 self.assertEqual(
2579 context.create_decimal_from_float(math.pi),
2580 Decimal('3.1415')
2581 )
2582 context = Context(prec=5, rounding=ROUND_UP)
2583 self.assertEqual(
2584 context.create_decimal_from_float(math.pi),
2585 Decimal('3.1416')
2586 )
2587 context = Context(prec=5, traps=[Inexact])
2588 self.assertRaises(
2589 Inexact,
2590 context.create_decimal_from_float,
2591 math.pi
2592 )
2593 self.assertEqual(repr(context.create_decimal_from_float(-0.0)),
2594 "Decimal('-0')")
2595 self.assertEqual(repr(context.create_decimal_from_float(1.0)),
2596 "Decimal('1')")
2597 self.assertEqual(repr(context.create_decimal_from_float(10)),
2598 "Decimal('10')")
2599
2600 def test_quantize(self):
2601 Decimal = self.decimal.Decimal
2602 Context = self.decimal.Context
2603 InvalidOperation = self.decimal.InvalidOperation
Stefan Krah1919b7e2012-03-21 18:25:23 +01002604
2605 c = Context(Emax=99999, Emin=-99999)
2606 self.assertEqual(
2607 Decimal('7.335').quantize(Decimal('.01')),
2608 Decimal('7.34')
2609 )
2610 self.assertEqual(
2611 Decimal('7.335').quantize(Decimal('.01'), rounding=ROUND_DOWN),
2612 Decimal('7.33')
2613 )
2614 self.assertRaises(
2615 InvalidOperation,
2616 Decimal("10e99999").quantize, Decimal('1e100000'), context=c
2617 )
2618
2619 c = Context()
2620 d = Decimal("0.871831e800")
2621 x = d.quantize(context=c, exp=Decimal("1e797"), rounding=ROUND_DOWN)
2622 self.assertEqual(x, Decimal('8.71E+799'))
2623
2624 def test_complex(self):
2625 Decimal = self.decimal.Decimal
2626
2627 x = Decimal("9.8182731e181273")
2628 self.assertEqual(x.real, x)
2629 self.assertEqual(x.imag, 0)
2630 self.assertEqual(x.conjugate(), x)
2631
2632 x = Decimal("1")
2633 self.assertEqual(complex(x), complex(float(1)))
2634
2635 self.assertRaises(AttributeError, setattr, x, 'real', 100)
2636 self.assertRaises(AttributeError, setattr, x, 'imag', 100)
2637 self.assertRaises(AttributeError, setattr, x, 'conjugate', 100)
2638 self.assertRaises(AttributeError, setattr, x, '__complex__', 100)
2639
2640 def test_named_parameters(self):
2641 D = self.decimal.Decimal
2642 Context = self.decimal.Context
2643 localcontext = self.decimal.localcontext
2644 InvalidOperation = self.decimal.InvalidOperation
2645 Overflow = self.decimal.Overflow
2646
2647 xc = Context()
2648 xc.prec = 1
2649 xc.Emax = 1
2650 xc.Emin = -1
2651
2652 with localcontext() as c:
2653 c.clear_flags()
2654
2655 self.assertEqual(D(9, xc), 9)
2656 self.assertEqual(D(9, context=xc), 9)
2657 self.assertEqual(D(context=xc, value=9), 9)
2658 self.assertEqual(D(context=xc), 0)
2659 xc.clear_flags()
2660 self.assertRaises(InvalidOperation, D, "xyz", context=xc)
2661 self.assertTrue(xc.flags[InvalidOperation])
2662 self.assertFalse(c.flags[InvalidOperation])
2663
2664 xc.clear_flags()
2665 self.assertEqual(D(2).exp(context=xc), 7)
2666 self.assertRaises(Overflow, D(8).exp, context=xc)
2667 self.assertTrue(xc.flags[Overflow])
2668 self.assertFalse(c.flags[Overflow])
2669
2670 xc.clear_flags()
2671 self.assertEqual(D(2).ln(context=xc), D('0.7'))
2672 self.assertRaises(InvalidOperation, D(-1).ln, context=xc)
2673 self.assertTrue(xc.flags[InvalidOperation])
2674 self.assertFalse(c.flags[InvalidOperation])
2675
2676 self.assertEqual(D(0).log10(context=xc), D('-inf'))
2677 self.assertEqual(D(-1).next_minus(context=xc), -2)
2678 self.assertEqual(D(-1).next_plus(context=xc), D('-0.9'))
2679 self.assertEqual(D("9.73").normalize(context=xc), D('1E+1'))
2680 self.assertEqual(D("9999").to_integral(context=xc), 9999)
2681 self.assertEqual(D("-2000").to_integral_exact(context=xc), -2000)
2682 self.assertEqual(D("123").to_integral_value(context=xc), 123)
2683 self.assertEqual(D("0.0625").sqrt(context=xc), D('0.2'))
2684
2685 self.assertEqual(D("0.0625").compare(context=xc, other=3), -1)
2686 xc.clear_flags()
2687 self.assertRaises(InvalidOperation,
2688 D("0").compare_signal, D('nan'), context=xc)
2689 self.assertTrue(xc.flags[InvalidOperation])
2690 self.assertFalse(c.flags[InvalidOperation])
2691 self.assertEqual(D("0.01").max(D('0.0101'), context=xc), D('0.0'))
2692 self.assertEqual(D("0.01").max(D('0.0101'), context=xc), D('0.0'))
2693 self.assertEqual(D("0.2").max_mag(D('-0.3'), context=xc),
2694 D('-0.3'))
2695 self.assertEqual(D("0.02").min(D('-0.03'), context=xc), D('-0.0'))
2696 self.assertEqual(D("0.02").min_mag(D('-0.03'), context=xc),
2697 D('0.0'))
2698 self.assertEqual(D("0.2").next_toward(D('-1'), context=xc), D('0.1'))
2699 xc.clear_flags()
2700 self.assertRaises(InvalidOperation,
2701 D("0.2").quantize, D('1e10'), context=xc)
2702 self.assertTrue(xc.flags[InvalidOperation])
2703 self.assertFalse(c.flags[InvalidOperation])
2704 self.assertEqual(D("9.99").remainder_near(D('1.5'), context=xc),
2705 D('-0.5'))
2706
2707 self.assertEqual(D("9.9").fma(third=D('0.9'), context=xc, other=7),
2708 D('7E+1'))
2709
2710 self.assertRaises(TypeError, D(1).is_canonical, context=xc)
2711 self.assertRaises(TypeError, D(1).is_finite, context=xc)
2712 self.assertRaises(TypeError, D(1).is_infinite, context=xc)
2713 self.assertRaises(TypeError, D(1).is_nan, context=xc)
2714 self.assertRaises(TypeError, D(1).is_qnan, context=xc)
2715 self.assertRaises(TypeError, D(1).is_snan, context=xc)
2716 self.assertRaises(TypeError, D(1).is_signed, context=xc)
2717 self.assertRaises(TypeError, D(1).is_zero, context=xc)
2718
2719 self.assertFalse(D("0.01").is_normal(context=xc))
2720 self.assertTrue(D("0.01").is_subnormal(context=xc))
2721
2722 self.assertRaises(TypeError, D(1).adjusted, context=xc)
2723 self.assertRaises(TypeError, D(1).conjugate, context=xc)
2724 self.assertRaises(TypeError, D(1).radix, context=xc)
2725
2726 self.assertEqual(D(-111).logb(context=xc), 2)
2727 self.assertEqual(D(0).logical_invert(context=xc), 1)
2728 self.assertEqual(D('0.01').number_class(context=xc), '+Subnormal')
2729 self.assertEqual(D('0.21').to_eng_string(context=xc), '0.21')
2730
2731 self.assertEqual(D('11').logical_and(D('10'), context=xc), 0)
2732 self.assertEqual(D('11').logical_or(D('10'), context=xc), 1)
2733 self.assertEqual(D('01').logical_xor(D('10'), context=xc), 1)
2734 self.assertEqual(D('23').rotate(1, context=xc), 3)
2735 self.assertEqual(D('23').rotate(1, context=xc), 3)
2736 xc.clear_flags()
2737 self.assertRaises(Overflow,
2738 D('23').scaleb, 1, context=xc)
2739 self.assertTrue(xc.flags[Overflow])
2740 self.assertFalse(c.flags[Overflow])
2741 self.assertEqual(D('23').shift(-1, context=xc), 0)
2742
2743 self.assertRaises(TypeError, D.from_float, 1.1, context=xc)
2744 self.assertRaises(TypeError, D(0).as_tuple, context=xc)
2745
Stefan Krah040e3112012-12-15 22:33:33 +01002746 self.assertEqual(D(1).canonical(), 1)
2747 self.assertRaises(TypeError, D("-1").copy_abs, context=xc)
2748 self.assertRaises(TypeError, D("-1").copy_negate, context=xc)
2749 self.assertRaises(TypeError, D(1).canonical, context="x")
2750 self.assertRaises(TypeError, D(1).canonical, xyz="x")
Stefan Krah1919b7e2012-03-21 18:25:23 +01002751
Stefan Krahb6405ef2012-03-23 14:46:48 +01002752 def test_exception_hierarchy(self):
2753
2754 decimal = self.decimal
2755 DecimalException = decimal.DecimalException
2756 InvalidOperation = decimal.InvalidOperation
2757 FloatOperation = decimal.FloatOperation
2758 DivisionByZero = decimal.DivisionByZero
2759 Overflow = decimal.Overflow
2760 Underflow = decimal.Underflow
2761 Subnormal = decimal.Subnormal
2762 Inexact = decimal.Inexact
2763 Rounded = decimal.Rounded
2764 Clamped = decimal.Clamped
2765
2766 self.assertTrue(issubclass(DecimalException, ArithmeticError))
2767
2768 self.assertTrue(issubclass(InvalidOperation, DecimalException))
2769 self.assertTrue(issubclass(FloatOperation, DecimalException))
2770 self.assertTrue(issubclass(FloatOperation, TypeError))
2771 self.assertTrue(issubclass(DivisionByZero, DecimalException))
2772 self.assertTrue(issubclass(DivisionByZero, ZeroDivisionError))
2773 self.assertTrue(issubclass(Overflow, Rounded))
2774 self.assertTrue(issubclass(Overflow, Inexact))
2775 self.assertTrue(issubclass(Overflow, DecimalException))
2776 self.assertTrue(issubclass(Underflow, Inexact))
2777 self.assertTrue(issubclass(Underflow, Rounded))
2778 self.assertTrue(issubclass(Underflow, Subnormal))
2779 self.assertTrue(issubclass(Underflow, DecimalException))
2780
2781 self.assertTrue(issubclass(Subnormal, DecimalException))
2782 self.assertTrue(issubclass(Inexact, DecimalException))
2783 self.assertTrue(issubclass(Rounded, DecimalException))
2784 self.assertTrue(issubclass(Clamped, DecimalException))
2785
2786 self.assertTrue(issubclass(decimal.ConversionSyntax, InvalidOperation))
2787 self.assertTrue(issubclass(decimal.DivisionImpossible, InvalidOperation))
2788 self.assertTrue(issubclass(decimal.DivisionUndefined, InvalidOperation))
2789 self.assertTrue(issubclass(decimal.DivisionUndefined, ZeroDivisionError))
2790 self.assertTrue(issubclass(decimal.InvalidContext, InvalidOperation))
2791
Stefan Krah1919b7e2012-03-21 18:25:23 +01002792class CPythonAPItests(PythonAPItests):
2793 decimal = C
2794class PyPythonAPItests(PythonAPItests):
2795 decimal = P
2796
2797class ContextAPItests(unittest.TestCase):
2798
Stefan Krah9a4ff432012-12-16 21:10:35 +01002799 def test_none_args(self):
2800 Context = self.decimal.Context
2801 InvalidOperation = self.decimal.InvalidOperation
2802 DivisionByZero = self.decimal.DivisionByZero
2803 Overflow = self.decimal.Overflow
Stefan Krah9a4ff432012-12-16 21:10:35 +01002804
2805 c1 = Context()
2806 c2 = Context(prec=None, rounding=None, Emax=None, Emin=None,
2807 capitals=None, clamp=None, flags=None, traps=None)
2808 for c in [c1, c2]:
2809 self.assertEqual(c.prec, 28)
2810 self.assertEqual(c.rounding, ROUND_HALF_EVEN)
2811 self.assertEqual(c.Emax, 999999)
2812 self.assertEqual(c.Emin, -999999)
2813 self.assertEqual(c.capitals, 1)
2814 self.assertEqual(c.clamp, 0)
2815 assert_signals(self, c, 'flags', [])
2816 assert_signals(self, c, 'traps', [InvalidOperation, DivisionByZero,
2817 Overflow])
2818
Stefan Krah59a4a932013-01-16 12:58:59 +01002819 @cpython_only
2820 def test_from_legacy_strings(self):
2821 import _testcapi
2822 c = self.decimal.Context()
2823
2824 for rnd in RoundingModes:
2825 c.rounding = _testcapi.unicode_legacy_string(rnd)
2826 self.assertEqual(c.rounding, rnd)
2827
2828 s = _testcapi.unicode_legacy_string('')
2829 self.assertRaises(TypeError, setattr, c, 'rounding', s)
2830
2831 s = _testcapi.unicode_legacy_string('ROUND_\x00UP')
2832 self.assertRaises(TypeError, setattr, c, 'rounding', s)
2833
Stefan Krah1919b7e2012-03-21 18:25:23 +01002834 def test_pickle(self):
2835
Serhiy Storchakabad12572014-12-15 14:03:42 +02002836 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
2837 Context = self.decimal.Context
Stefan Krah1919b7e2012-03-21 18:25:23 +01002838
Serhiy Storchakabad12572014-12-15 14:03:42 +02002839 savedecimal = sys.modules['decimal']
Stefan Krah1919b7e2012-03-21 18:25:23 +01002840
Serhiy Storchakabad12572014-12-15 14:03:42 +02002841 # Round trip
2842 sys.modules['decimal'] = self.decimal
2843 c = Context()
2844 e = pickle.loads(pickle.dumps(c, proto))
Stefan Krah1919b7e2012-03-21 18:25:23 +01002845
Serhiy Storchakabad12572014-12-15 14:03:42 +02002846 self.assertEqual(c.prec, e.prec)
2847 self.assertEqual(c.Emin, e.Emin)
2848 self.assertEqual(c.Emax, e.Emax)
2849 self.assertEqual(c.rounding, e.rounding)
2850 self.assertEqual(c.capitals, e.capitals)
2851 self.assertEqual(c.clamp, e.clamp)
2852 self.assertEqual(c.flags, e.flags)
2853 self.assertEqual(c.traps, e.traps)
Stefan Krah1919b7e2012-03-21 18:25:23 +01002854
Serhiy Storchakabad12572014-12-15 14:03:42 +02002855 # Test interchangeability
2856 combinations = [(C, P), (P, C)] if C else [(P, P)]
2857 for dumper, loader in combinations:
2858 for ri, _ in enumerate(RoundingModes):
2859 for fi, _ in enumerate(OrderedSignals[dumper]):
2860 for ti, _ in enumerate(OrderedSignals[dumper]):
Stefan Krah1919b7e2012-03-21 18:25:23 +01002861
Serhiy Storchakabad12572014-12-15 14:03:42 +02002862 prec = random.randrange(1, 100)
2863 emin = random.randrange(-100, 0)
2864 emax = random.randrange(1, 100)
2865 caps = random.randrange(2)
2866 clamp = random.randrange(2)
Stefan Krah1919b7e2012-03-21 18:25:23 +01002867
Serhiy Storchakabad12572014-12-15 14:03:42 +02002868 # One module dumps
2869 sys.modules['decimal'] = dumper
2870 c = dumper.Context(
2871 prec=prec, Emin=emin, Emax=emax,
2872 rounding=RoundingModes[ri],
2873 capitals=caps, clamp=clamp,
2874 flags=OrderedSignals[dumper][:fi],
2875 traps=OrderedSignals[dumper][:ti]
2876 )
2877 s = pickle.dumps(c, proto)
Stefan Krah1919b7e2012-03-21 18:25:23 +01002878
Serhiy Storchakabad12572014-12-15 14:03:42 +02002879 # The other module loads
2880 sys.modules['decimal'] = loader
2881 d = pickle.loads(s)
2882 self.assertIsInstance(d, loader.Context)
Stefan Krah1919b7e2012-03-21 18:25:23 +01002883
Serhiy Storchakabad12572014-12-15 14:03:42 +02002884 self.assertEqual(d.prec, prec)
2885 self.assertEqual(d.Emin, emin)
2886 self.assertEqual(d.Emax, emax)
2887 self.assertEqual(d.rounding, RoundingModes[ri])
2888 self.assertEqual(d.capitals, caps)
2889 self.assertEqual(d.clamp, clamp)
2890 assert_signals(self, d, 'flags', OrderedSignals[loader][:fi])
2891 assert_signals(self, d, 'traps', OrderedSignals[loader][:ti])
Stefan Krah1919b7e2012-03-21 18:25:23 +01002892
Serhiy Storchakabad12572014-12-15 14:03:42 +02002893 sys.modules['decimal'] = savedecimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01002894
2895 def test_equality_with_other_types(self):
2896 Decimal = self.decimal.Decimal
2897
2898 self.assertIn(Decimal(10), ['a', 1.0, Decimal(10), (1,2), {}])
2899 self.assertNotIn(Decimal(10), ['a', 1.0, (1,2), {}])
2900
2901 def test_copy(self):
2902 # All copies should be deep
2903 Decimal = self.decimal.Decimal
2904 Context = self.decimal.Context
2905
2906 c = Context()
2907 d = c.copy()
2908 self.assertNotEqual(id(c), id(d))
2909 self.assertNotEqual(id(c.flags), id(d.flags))
2910 self.assertNotEqual(id(c.traps), id(d.traps))
2911 k1 = set(c.flags.keys())
2912 k2 = set(d.flags.keys())
2913 self.assertEqual(k1, k2)
2914 self.assertEqual(c.flags, d.flags)
2915
2916 def test__clamp(self):
2917 # In Python 3.2, the private attribute `_clamp` was made
2918 # public (issue 8540), with the old `_clamp` becoming a
2919 # property wrapping `clamp`. For the duration of Python 3.2
2920 # only, the attribute should be gettable/settable via both
2921 # `clamp` and `_clamp`; in Python 3.3, `_clamp` should be
2922 # removed.
2923 Context = self.decimal.Context
2924 c = Context()
2925 self.assertRaises(AttributeError, getattr, c, '_clamp')
2926
2927 def test_abs(self):
2928 Decimal = self.decimal.Decimal
2929 Context = self.decimal.Context
2930
2931 c = Context()
2932 d = c.abs(Decimal(-1))
2933 self.assertEqual(c.abs(-1), d)
2934 self.assertRaises(TypeError, c.abs, '-1')
2935
2936 def test_add(self):
2937 Decimal = self.decimal.Decimal
2938 Context = self.decimal.Context
2939
2940 c = Context()
2941 d = c.add(Decimal(1), Decimal(1))
2942 self.assertEqual(c.add(1, 1), d)
2943 self.assertEqual(c.add(Decimal(1), 1), d)
2944 self.assertEqual(c.add(1, Decimal(1)), d)
2945 self.assertRaises(TypeError, c.add, '1', 1)
2946 self.assertRaises(TypeError, c.add, 1, '1')
2947
2948 def test_compare(self):
2949 Decimal = self.decimal.Decimal
2950 Context = self.decimal.Context
2951
2952 c = Context()
2953 d = c.compare(Decimal(1), Decimal(1))
2954 self.assertEqual(c.compare(1, 1), d)
2955 self.assertEqual(c.compare(Decimal(1), 1), d)
2956 self.assertEqual(c.compare(1, Decimal(1)), d)
2957 self.assertRaises(TypeError, c.compare, '1', 1)
2958 self.assertRaises(TypeError, c.compare, 1, '1')
2959
2960 def test_compare_signal(self):
2961 Decimal = self.decimal.Decimal
2962 Context = self.decimal.Context
2963
2964 c = Context()
2965 d = c.compare_signal(Decimal(1), Decimal(1))
2966 self.assertEqual(c.compare_signal(1, 1), d)
2967 self.assertEqual(c.compare_signal(Decimal(1), 1), d)
2968 self.assertEqual(c.compare_signal(1, Decimal(1)), d)
2969 self.assertRaises(TypeError, c.compare_signal, '1', 1)
2970 self.assertRaises(TypeError, c.compare_signal, 1, '1')
2971
2972 def test_compare_total(self):
2973 Decimal = self.decimal.Decimal
2974 Context = self.decimal.Context
2975
2976 c = Context()
2977 d = c.compare_total(Decimal(1), Decimal(1))
2978 self.assertEqual(c.compare_total(1, 1), d)
2979 self.assertEqual(c.compare_total(Decimal(1), 1), d)
2980 self.assertEqual(c.compare_total(1, Decimal(1)), d)
2981 self.assertRaises(TypeError, c.compare_total, '1', 1)
2982 self.assertRaises(TypeError, c.compare_total, 1, '1')
2983
2984 def test_compare_total_mag(self):
2985 Decimal = self.decimal.Decimal
2986 Context = self.decimal.Context
2987
2988 c = Context()
2989 d = c.compare_total_mag(Decimal(1), Decimal(1))
2990 self.assertEqual(c.compare_total_mag(1, 1), d)
2991 self.assertEqual(c.compare_total_mag(Decimal(1), 1), d)
2992 self.assertEqual(c.compare_total_mag(1, Decimal(1)), d)
2993 self.assertRaises(TypeError, c.compare_total_mag, '1', 1)
2994 self.assertRaises(TypeError, c.compare_total_mag, 1, '1')
2995
2996 def test_copy_abs(self):
2997 Decimal = self.decimal.Decimal
2998 Context = self.decimal.Context
2999
3000 c = Context()
3001 d = c.copy_abs(Decimal(-1))
3002 self.assertEqual(c.copy_abs(-1), d)
3003 self.assertRaises(TypeError, c.copy_abs, '-1')
3004
3005 def test_copy_decimal(self):
3006 Decimal = self.decimal.Decimal
3007 Context = self.decimal.Context
3008
3009 c = Context()
3010 d = c.copy_decimal(Decimal(-1))
3011 self.assertEqual(c.copy_decimal(-1), d)
3012 self.assertRaises(TypeError, c.copy_decimal, '-1')
3013
3014 def test_copy_negate(self):
3015 Decimal = self.decimal.Decimal
3016 Context = self.decimal.Context
3017
3018 c = Context()
3019 d = c.copy_negate(Decimal(-1))
3020 self.assertEqual(c.copy_negate(-1), d)
3021 self.assertRaises(TypeError, c.copy_negate, '-1')
3022
3023 def test_copy_sign(self):
3024 Decimal = self.decimal.Decimal
3025 Context = self.decimal.Context
3026
3027 c = Context()
3028 d = c.copy_sign(Decimal(1), Decimal(-2))
3029 self.assertEqual(c.copy_sign(1, -2), d)
3030 self.assertEqual(c.copy_sign(Decimal(1), -2), d)
3031 self.assertEqual(c.copy_sign(1, Decimal(-2)), d)
3032 self.assertRaises(TypeError, c.copy_sign, '1', -2)
3033 self.assertRaises(TypeError, c.copy_sign, 1, '-2')
3034
3035 def test_divide(self):
3036 Decimal = self.decimal.Decimal
3037 Context = self.decimal.Context
3038
3039 c = Context()
3040 d = c.divide(Decimal(1), Decimal(2))
3041 self.assertEqual(c.divide(1, 2), d)
3042 self.assertEqual(c.divide(Decimal(1), 2), d)
3043 self.assertEqual(c.divide(1, Decimal(2)), d)
3044 self.assertRaises(TypeError, c.divide, '1', 2)
3045 self.assertRaises(TypeError, c.divide, 1, '2')
3046
3047 def test_divide_int(self):
3048 Decimal = self.decimal.Decimal
3049 Context = self.decimal.Context
3050
3051 c = Context()
3052 d = c.divide_int(Decimal(1), Decimal(2))
3053 self.assertEqual(c.divide_int(1, 2), d)
3054 self.assertEqual(c.divide_int(Decimal(1), 2), d)
3055 self.assertEqual(c.divide_int(1, Decimal(2)), d)
3056 self.assertRaises(TypeError, c.divide_int, '1', 2)
3057 self.assertRaises(TypeError, c.divide_int, 1, '2')
3058
3059 def test_divmod(self):
3060 Decimal = self.decimal.Decimal
3061 Context = self.decimal.Context
3062
3063 c = Context()
3064 d = c.divmod(Decimal(1), Decimal(2))
3065 self.assertEqual(c.divmod(1, 2), d)
3066 self.assertEqual(c.divmod(Decimal(1), 2), d)
3067 self.assertEqual(c.divmod(1, Decimal(2)), d)
3068 self.assertRaises(TypeError, c.divmod, '1', 2)
3069 self.assertRaises(TypeError, c.divmod, 1, '2')
3070
3071 def test_exp(self):
3072 Decimal = self.decimal.Decimal
3073 Context = self.decimal.Context
3074
3075 c = Context()
3076 d = c.exp(Decimal(10))
3077 self.assertEqual(c.exp(10), d)
3078 self.assertRaises(TypeError, c.exp, '10')
3079
3080 def test_fma(self):
3081 Decimal = self.decimal.Decimal
3082 Context = self.decimal.Context
3083
3084 c = Context()
3085 d = c.fma(Decimal(2), Decimal(3), Decimal(4))
3086 self.assertEqual(c.fma(2, 3, 4), d)
3087 self.assertEqual(c.fma(Decimal(2), 3, 4), d)
3088 self.assertEqual(c.fma(2, Decimal(3), 4), d)
3089 self.assertEqual(c.fma(2, 3, Decimal(4)), d)
3090 self.assertEqual(c.fma(Decimal(2), Decimal(3), 4), d)
3091 self.assertRaises(TypeError, c.fma, '2', 3, 4)
3092 self.assertRaises(TypeError, c.fma, 2, '3', 4)
3093 self.assertRaises(TypeError, c.fma, 2, 3, '4')
3094
3095 # Issue 12079 for Context.fma ...
3096 self.assertRaises(TypeError, c.fma,
3097 Decimal('Infinity'), Decimal(0), "not a decimal")
3098 self.assertRaises(TypeError, c.fma,
3099 Decimal(1), Decimal('snan'), 1.222)
3100 # ... and for Decimal.fma.
3101 self.assertRaises(TypeError, Decimal('Infinity').fma,
3102 Decimal(0), "not a decimal")
3103 self.assertRaises(TypeError, Decimal(1).fma,
3104 Decimal('snan'), 1.222)
3105
3106 def test_is_finite(self):
3107 Decimal = self.decimal.Decimal
3108 Context = self.decimal.Context
3109
3110 c = Context()
3111 d = c.is_finite(Decimal(10))
3112 self.assertEqual(c.is_finite(10), d)
3113 self.assertRaises(TypeError, c.is_finite, '10')
3114
3115 def test_is_infinite(self):
3116 Decimal = self.decimal.Decimal
3117 Context = self.decimal.Context
3118
3119 c = Context()
3120 d = c.is_infinite(Decimal(10))
3121 self.assertEqual(c.is_infinite(10), d)
3122 self.assertRaises(TypeError, c.is_infinite, '10')
3123
3124 def test_is_nan(self):
3125 Decimal = self.decimal.Decimal
3126 Context = self.decimal.Context
3127
3128 c = Context()
3129 d = c.is_nan(Decimal(10))
3130 self.assertEqual(c.is_nan(10), d)
3131 self.assertRaises(TypeError, c.is_nan, '10')
3132
3133 def test_is_normal(self):
3134 Decimal = self.decimal.Decimal
3135 Context = self.decimal.Context
3136
3137 c = Context()
3138 d = c.is_normal(Decimal(10))
3139 self.assertEqual(c.is_normal(10), d)
3140 self.assertRaises(TypeError, c.is_normal, '10')
3141
3142 def test_is_qnan(self):
3143 Decimal = self.decimal.Decimal
3144 Context = self.decimal.Context
3145
3146 c = Context()
3147 d = c.is_qnan(Decimal(10))
3148 self.assertEqual(c.is_qnan(10), d)
3149 self.assertRaises(TypeError, c.is_qnan, '10')
3150
3151 def test_is_signed(self):
3152 Decimal = self.decimal.Decimal
3153 Context = self.decimal.Context
3154
3155 c = Context()
3156 d = c.is_signed(Decimal(10))
3157 self.assertEqual(c.is_signed(10), d)
3158 self.assertRaises(TypeError, c.is_signed, '10')
3159
3160 def test_is_snan(self):
3161 Decimal = self.decimal.Decimal
3162 Context = self.decimal.Context
3163
3164 c = Context()
3165 d = c.is_snan(Decimal(10))
3166 self.assertEqual(c.is_snan(10), d)
3167 self.assertRaises(TypeError, c.is_snan, '10')
3168
3169 def test_is_subnormal(self):
3170 Decimal = self.decimal.Decimal
3171 Context = self.decimal.Context
3172
3173 c = Context()
3174 d = c.is_subnormal(Decimal(10))
3175 self.assertEqual(c.is_subnormal(10), d)
3176 self.assertRaises(TypeError, c.is_subnormal, '10')
3177
3178 def test_is_zero(self):
3179 Decimal = self.decimal.Decimal
3180 Context = self.decimal.Context
3181
3182 c = Context()
3183 d = c.is_zero(Decimal(10))
3184 self.assertEqual(c.is_zero(10), d)
3185 self.assertRaises(TypeError, c.is_zero, '10')
3186
3187 def test_ln(self):
3188 Decimal = self.decimal.Decimal
3189 Context = self.decimal.Context
3190
3191 c = Context()
3192 d = c.ln(Decimal(10))
3193 self.assertEqual(c.ln(10), d)
3194 self.assertRaises(TypeError, c.ln, '10')
3195
3196 def test_log10(self):
3197 Decimal = self.decimal.Decimal
3198 Context = self.decimal.Context
3199
3200 c = Context()
3201 d = c.log10(Decimal(10))
3202 self.assertEqual(c.log10(10), d)
3203 self.assertRaises(TypeError, c.log10, '10')
3204
3205 def test_logb(self):
3206 Decimal = self.decimal.Decimal
3207 Context = self.decimal.Context
3208
3209 c = Context()
3210 d = c.logb(Decimal(10))
3211 self.assertEqual(c.logb(10), d)
3212 self.assertRaises(TypeError, c.logb, '10')
3213
3214 def test_logical_and(self):
3215 Decimal = self.decimal.Decimal
3216 Context = self.decimal.Context
3217
3218 c = Context()
3219 d = c.logical_and(Decimal(1), Decimal(1))
3220 self.assertEqual(c.logical_and(1, 1), d)
3221 self.assertEqual(c.logical_and(Decimal(1), 1), d)
3222 self.assertEqual(c.logical_and(1, Decimal(1)), d)
3223 self.assertRaises(TypeError, c.logical_and, '1', 1)
3224 self.assertRaises(TypeError, c.logical_and, 1, '1')
3225
3226 def test_logical_invert(self):
3227 Decimal = self.decimal.Decimal
3228 Context = self.decimal.Context
3229
3230 c = Context()
3231 d = c.logical_invert(Decimal(1000))
3232 self.assertEqual(c.logical_invert(1000), d)
3233 self.assertRaises(TypeError, c.logical_invert, '1000')
3234
3235 def test_logical_or(self):
3236 Decimal = self.decimal.Decimal
3237 Context = self.decimal.Context
3238
3239 c = Context()
3240 d = c.logical_or(Decimal(1), Decimal(1))
3241 self.assertEqual(c.logical_or(1, 1), d)
3242 self.assertEqual(c.logical_or(Decimal(1), 1), d)
3243 self.assertEqual(c.logical_or(1, Decimal(1)), d)
3244 self.assertRaises(TypeError, c.logical_or, '1', 1)
3245 self.assertRaises(TypeError, c.logical_or, 1, '1')
3246
3247 def test_logical_xor(self):
3248 Decimal = self.decimal.Decimal
3249 Context = self.decimal.Context
3250
3251 c = Context()
3252 d = c.logical_xor(Decimal(1), Decimal(1))
3253 self.assertEqual(c.logical_xor(1, 1), d)
3254 self.assertEqual(c.logical_xor(Decimal(1), 1), d)
3255 self.assertEqual(c.logical_xor(1, Decimal(1)), d)
3256 self.assertRaises(TypeError, c.logical_xor, '1', 1)
3257 self.assertRaises(TypeError, c.logical_xor, 1, '1')
3258
3259 def test_max(self):
3260 Decimal = self.decimal.Decimal
3261 Context = self.decimal.Context
3262
3263 c = Context()
3264 d = c.max(Decimal(1), Decimal(2))
3265 self.assertEqual(c.max(1, 2), d)
3266 self.assertEqual(c.max(Decimal(1), 2), d)
3267 self.assertEqual(c.max(1, Decimal(2)), d)
3268 self.assertRaises(TypeError, c.max, '1', 2)
3269 self.assertRaises(TypeError, c.max, 1, '2')
3270
3271 def test_max_mag(self):
3272 Decimal = self.decimal.Decimal
3273 Context = self.decimal.Context
3274
3275 c = Context()
3276 d = c.max_mag(Decimal(1), Decimal(2))
3277 self.assertEqual(c.max_mag(1, 2), d)
3278 self.assertEqual(c.max_mag(Decimal(1), 2), d)
3279 self.assertEqual(c.max_mag(1, Decimal(2)), d)
3280 self.assertRaises(TypeError, c.max_mag, '1', 2)
3281 self.assertRaises(TypeError, c.max_mag, 1, '2')
3282
3283 def test_min(self):
3284 Decimal = self.decimal.Decimal
3285 Context = self.decimal.Context
3286
3287 c = Context()
3288 d = c.min(Decimal(1), Decimal(2))
3289 self.assertEqual(c.min(1, 2), d)
3290 self.assertEqual(c.min(Decimal(1), 2), d)
3291 self.assertEqual(c.min(1, Decimal(2)), d)
3292 self.assertRaises(TypeError, c.min, '1', 2)
3293 self.assertRaises(TypeError, c.min, 1, '2')
3294
3295 def test_min_mag(self):
3296 Decimal = self.decimal.Decimal
3297 Context = self.decimal.Context
3298
3299 c = Context()
3300 d = c.min_mag(Decimal(1), Decimal(2))
3301 self.assertEqual(c.min_mag(1, 2), d)
3302 self.assertEqual(c.min_mag(Decimal(1), 2), d)
3303 self.assertEqual(c.min_mag(1, Decimal(2)), d)
3304 self.assertRaises(TypeError, c.min_mag, '1', 2)
3305 self.assertRaises(TypeError, c.min_mag, 1, '2')
3306
3307 def test_minus(self):
3308 Decimal = self.decimal.Decimal
3309 Context = self.decimal.Context
3310
3311 c = Context()
3312 d = c.minus(Decimal(10))
3313 self.assertEqual(c.minus(10), d)
3314 self.assertRaises(TypeError, c.minus, '10')
3315
3316 def test_multiply(self):
3317 Decimal = self.decimal.Decimal
3318 Context = self.decimal.Context
3319
3320 c = Context()
3321 d = c.multiply(Decimal(1), Decimal(2))
3322 self.assertEqual(c.multiply(1, 2), d)
3323 self.assertEqual(c.multiply(Decimal(1), 2), d)
3324 self.assertEqual(c.multiply(1, Decimal(2)), d)
3325 self.assertRaises(TypeError, c.multiply, '1', 2)
3326 self.assertRaises(TypeError, c.multiply, 1, '2')
3327
3328 def test_next_minus(self):
3329 Decimal = self.decimal.Decimal
3330 Context = self.decimal.Context
3331
3332 c = Context()
3333 d = c.next_minus(Decimal(10))
3334 self.assertEqual(c.next_minus(10), d)
3335 self.assertRaises(TypeError, c.next_minus, '10')
3336
3337 def test_next_plus(self):
3338 Decimal = self.decimal.Decimal
3339 Context = self.decimal.Context
3340
3341 c = Context()
3342 d = c.next_plus(Decimal(10))
3343 self.assertEqual(c.next_plus(10), d)
3344 self.assertRaises(TypeError, c.next_plus, '10')
3345
3346 def test_next_toward(self):
3347 Decimal = self.decimal.Decimal
3348 Context = self.decimal.Context
3349
3350 c = Context()
3351 d = c.next_toward(Decimal(1), Decimal(2))
3352 self.assertEqual(c.next_toward(1, 2), d)
3353 self.assertEqual(c.next_toward(Decimal(1), 2), d)
3354 self.assertEqual(c.next_toward(1, Decimal(2)), d)
3355 self.assertRaises(TypeError, c.next_toward, '1', 2)
3356 self.assertRaises(TypeError, c.next_toward, 1, '2')
3357
3358 def test_normalize(self):
3359 Decimal = self.decimal.Decimal
3360 Context = self.decimal.Context
3361
3362 c = Context()
3363 d = c.normalize(Decimal(10))
3364 self.assertEqual(c.normalize(10), d)
3365 self.assertRaises(TypeError, c.normalize, '10')
3366
3367 def test_number_class(self):
3368 Decimal = self.decimal.Decimal
3369 Context = self.decimal.Context
3370
3371 c = Context()
3372 self.assertEqual(c.number_class(123), c.number_class(Decimal(123)))
3373 self.assertEqual(c.number_class(0), c.number_class(Decimal(0)))
3374 self.assertEqual(c.number_class(-45), c.number_class(Decimal(-45)))
3375
3376 def test_plus(self):
3377 Decimal = self.decimal.Decimal
3378 Context = self.decimal.Context
3379
3380 c = Context()
3381 d = c.plus(Decimal(10))
3382 self.assertEqual(c.plus(10), d)
3383 self.assertRaises(TypeError, c.plus, '10')
3384
3385 def test_power(self):
3386 Decimal = self.decimal.Decimal
3387 Context = self.decimal.Context
3388
3389 c = Context()
3390 d = c.power(Decimal(1), Decimal(4))
3391 self.assertEqual(c.power(1, 4), d)
3392 self.assertEqual(c.power(Decimal(1), 4), d)
3393 self.assertEqual(c.power(1, Decimal(4)), d)
3394 self.assertEqual(c.power(Decimal(1), Decimal(4)), d)
3395 self.assertRaises(TypeError, c.power, '1', 4)
3396 self.assertRaises(TypeError, c.power, 1, '4')
3397 self.assertEqual(c.power(modulo=5, b=8, a=2), 1)
3398
3399 def test_quantize(self):
3400 Decimal = self.decimal.Decimal
3401 Context = self.decimal.Context
3402
3403 c = Context()
3404 d = c.quantize(Decimal(1), Decimal(2))
3405 self.assertEqual(c.quantize(1, 2), d)
3406 self.assertEqual(c.quantize(Decimal(1), 2), d)
3407 self.assertEqual(c.quantize(1, Decimal(2)), d)
3408 self.assertRaises(TypeError, c.quantize, '1', 2)
3409 self.assertRaises(TypeError, c.quantize, 1, '2')
3410
3411 def test_remainder(self):
3412 Decimal = self.decimal.Decimal
3413 Context = self.decimal.Context
3414
3415 c = Context()
3416 d = c.remainder(Decimal(1), Decimal(2))
3417 self.assertEqual(c.remainder(1, 2), d)
3418 self.assertEqual(c.remainder(Decimal(1), 2), d)
3419 self.assertEqual(c.remainder(1, Decimal(2)), d)
3420 self.assertRaises(TypeError, c.remainder, '1', 2)
3421 self.assertRaises(TypeError, c.remainder, 1, '2')
3422
3423 def test_remainder_near(self):
3424 Decimal = self.decimal.Decimal
3425 Context = self.decimal.Context
3426
3427 c = Context()
3428 d = c.remainder_near(Decimal(1), Decimal(2))
3429 self.assertEqual(c.remainder_near(1, 2), d)
3430 self.assertEqual(c.remainder_near(Decimal(1), 2), d)
3431 self.assertEqual(c.remainder_near(1, Decimal(2)), d)
3432 self.assertRaises(TypeError, c.remainder_near, '1', 2)
3433 self.assertRaises(TypeError, c.remainder_near, 1, '2')
3434
3435 def test_rotate(self):
3436 Decimal = self.decimal.Decimal
3437 Context = self.decimal.Context
3438
3439 c = Context()
3440 d = c.rotate(Decimal(1), Decimal(2))
3441 self.assertEqual(c.rotate(1, 2), d)
3442 self.assertEqual(c.rotate(Decimal(1), 2), d)
3443 self.assertEqual(c.rotate(1, Decimal(2)), d)
3444 self.assertRaises(TypeError, c.rotate, '1', 2)
3445 self.assertRaises(TypeError, c.rotate, 1, '2')
3446
3447 def test_sqrt(self):
3448 Decimal = self.decimal.Decimal
3449 Context = self.decimal.Context
3450
3451 c = Context()
3452 d = c.sqrt(Decimal(10))
3453 self.assertEqual(c.sqrt(10), d)
3454 self.assertRaises(TypeError, c.sqrt, '10')
3455
3456 def test_same_quantum(self):
3457 Decimal = self.decimal.Decimal
3458 Context = self.decimal.Context
3459
3460 c = Context()
3461 d = c.same_quantum(Decimal(1), Decimal(2))
3462 self.assertEqual(c.same_quantum(1, 2), d)
3463 self.assertEqual(c.same_quantum(Decimal(1), 2), d)
3464 self.assertEqual(c.same_quantum(1, Decimal(2)), d)
3465 self.assertRaises(TypeError, c.same_quantum, '1', 2)
3466 self.assertRaises(TypeError, c.same_quantum, 1, '2')
3467
3468 def test_scaleb(self):
3469 Decimal = self.decimal.Decimal
3470 Context = self.decimal.Context
3471
3472 c = Context()
3473 d = c.scaleb(Decimal(1), Decimal(2))
3474 self.assertEqual(c.scaleb(1, 2), d)
3475 self.assertEqual(c.scaleb(Decimal(1), 2), d)
3476 self.assertEqual(c.scaleb(1, Decimal(2)), d)
3477 self.assertRaises(TypeError, c.scaleb, '1', 2)
3478 self.assertRaises(TypeError, c.scaleb, 1, '2')
3479
3480 def test_shift(self):
3481 Decimal = self.decimal.Decimal
3482 Context = self.decimal.Context
3483
3484 c = Context()
3485 d = c.shift(Decimal(1), Decimal(2))
3486 self.assertEqual(c.shift(1, 2), d)
3487 self.assertEqual(c.shift(Decimal(1), 2), d)
3488 self.assertEqual(c.shift(1, Decimal(2)), d)
3489 self.assertRaises(TypeError, c.shift, '1', 2)
3490 self.assertRaises(TypeError, c.shift, 1, '2')
3491
3492 def test_subtract(self):
3493 Decimal = self.decimal.Decimal
3494 Context = self.decimal.Context
3495
3496 c = Context()
3497 d = c.subtract(Decimal(1), Decimal(2))
3498 self.assertEqual(c.subtract(1, 2), d)
3499 self.assertEqual(c.subtract(Decimal(1), 2), d)
3500 self.assertEqual(c.subtract(1, Decimal(2)), d)
3501 self.assertRaises(TypeError, c.subtract, '1', 2)
3502 self.assertRaises(TypeError, c.subtract, 1, '2')
3503
3504 def test_to_eng_string(self):
3505 Decimal = self.decimal.Decimal
3506 Context = self.decimal.Context
3507
3508 c = Context()
3509 d = c.to_eng_string(Decimal(10))
3510 self.assertEqual(c.to_eng_string(10), d)
3511 self.assertRaises(TypeError, c.to_eng_string, '10')
3512
3513 def test_to_sci_string(self):
3514 Decimal = self.decimal.Decimal
3515 Context = self.decimal.Context
3516
3517 c = Context()
3518 d = c.to_sci_string(Decimal(10))
3519 self.assertEqual(c.to_sci_string(10), d)
3520 self.assertRaises(TypeError, c.to_sci_string, '10')
3521
3522 def test_to_integral_exact(self):
3523 Decimal = self.decimal.Decimal
3524 Context = self.decimal.Context
3525
3526 c = Context()
3527 d = c.to_integral_exact(Decimal(10))
3528 self.assertEqual(c.to_integral_exact(10), d)
3529 self.assertRaises(TypeError, c.to_integral_exact, '10')
3530
3531 def test_to_integral_value(self):
3532 Decimal = self.decimal.Decimal
3533 Context = self.decimal.Context
3534
3535 c = Context()
3536 d = c.to_integral_value(Decimal(10))
3537 self.assertEqual(c.to_integral_value(10), d)
3538 self.assertRaises(TypeError, c.to_integral_value, '10')
3539 self.assertRaises(TypeError, c.to_integral_value, 10, 'x')
3540
3541class CContextAPItests(ContextAPItests):
3542 decimal = C
3543class PyContextAPItests(ContextAPItests):
3544 decimal = P
3545
3546class ContextWithStatement(unittest.TestCase):
3547 # Can't do these as docstrings until Python 2.6
3548 # as doctest can't handle __future__ statements
3549
3550 def test_localcontext(self):
3551 # Use a copy of the current context in the block
3552 getcontext = self.decimal.getcontext
3553 localcontext = self.decimal.localcontext
3554
3555 orig_ctx = getcontext()
3556 with localcontext() as enter_ctx:
3557 set_ctx = getcontext()
3558 final_ctx = getcontext()
3559 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
3560 self.assertIsNot(orig_ctx, set_ctx, 'did not copy the context')
3561 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
3562
3563 def test_localcontextarg(self):
3564 # Use a copy of the supplied context in the block
3565 Context = self.decimal.Context
3566 getcontext = self.decimal.getcontext
3567 localcontext = self.decimal.localcontext
3568
3569 localcontext = self.decimal.localcontext
3570 orig_ctx = getcontext()
3571 new_ctx = Context(prec=42)
3572 with localcontext(new_ctx) as enter_ctx:
3573 set_ctx = getcontext()
3574 final_ctx = getcontext()
3575 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
3576 self.assertEqual(set_ctx.prec, new_ctx.prec, 'did not set correct context')
3577 self.assertIsNot(new_ctx, set_ctx, 'did not copy the context')
3578 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
3579
3580 def test_nested_with_statements(self):
3581 # Use a copy of the supplied context in the block
3582 Decimal = self.decimal.Decimal
3583 Context = self.decimal.Context
3584 getcontext = self.decimal.getcontext
3585 localcontext = self.decimal.localcontext
3586 Clamped = self.decimal.Clamped
3587 Overflow = self.decimal.Overflow
3588
3589 orig_ctx = getcontext()
3590 orig_ctx.clear_flags()
3591 new_ctx = Context(Emax=384)
3592 with localcontext() as c1:
3593 self.assertEqual(c1.flags, orig_ctx.flags)
3594 self.assertEqual(c1.traps, orig_ctx.traps)
3595 c1.traps[Clamped] = True
3596 c1.Emin = -383
3597 self.assertNotEqual(orig_ctx.Emin, -383)
3598 self.assertRaises(Clamped, c1.create_decimal, '0e-999')
3599 self.assertTrue(c1.flags[Clamped])
3600 with localcontext(new_ctx) as c2:
3601 self.assertEqual(c2.flags, new_ctx.flags)
3602 self.assertEqual(c2.traps, new_ctx.traps)
3603 self.assertRaises(Overflow, c2.power, Decimal('3.4e200'), 2)
3604 self.assertFalse(c2.flags[Clamped])
3605 self.assertTrue(c2.flags[Overflow])
3606 del c2
3607 self.assertFalse(c1.flags[Overflow])
3608 del c1
3609 self.assertNotEqual(orig_ctx.Emin, -383)
3610 self.assertFalse(orig_ctx.flags[Clamped])
3611 self.assertFalse(orig_ctx.flags[Overflow])
3612 self.assertFalse(new_ctx.flags[Clamped])
3613 self.assertFalse(new_ctx.flags[Overflow])
3614
3615 def test_with_statements_gc1(self):
3616 localcontext = self.decimal.localcontext
3617
3618 with localcontext() as c1:
3619 del c1
3620 with localcontext() as c2:
3621 del c2
3622 with localcontext() as c3:
3623 del c3
3624 with localcontext() as c4:
3625 del c4
3626
3627 def test_with_statements_gc2(self):
3628 localcontext = self.decimal.localcontext
3629
3630 with localcontext() as c1:
3631 with localcontext(c1) as c2:
3632 del c1
3633 with localcontext(c2) as c3:
3634 del c2
3635 with localcontext(c3) as c4:
3636 del c3
3637 del c4
3638
3639 def test_with_statements_gc3(self):
3640 Context = self.decimal.Context
3641 localcontext = self.decimal.localcontext
3642 getcontext = self.decimal.getcontext
3643 setcontext = self.decimal.setcontext
3644
3645 with localcontext() as c1:
3646 del c1
3647 n1 = Context(prec=1)
3648 setcontext(n1)
3649 with localcontext(n1) as c2:
3650 del n1
3651 self.assertEqual(c2.prec, 1)
3652 del c2
3653 n2 = Context(prec=2)
3654 setcontext(n2)
3655 del n2
3656 self.assertEqual(getcontext().prec, 2)
3657 n3 = Context(prec=3)
3658 setcontext(n3)
3659 self.assertEqual(getcontext().prec, 3)
3660 with localcontext(n3) as c3:
3661 del n3
3662 self.assertEqual(c3.prec, 3)
3663 del c3
3664 n4 = Context(prec=4)
3665 setcontext(n4)
3666 del n4
3667 self.assertEqual(getcontext().prec, 4)
3668 with localcontext() as c4:
3669 self.assertEqual(c4.prec, 4)
3670 del c4
3671
3672class CContextWithStatement(ContextWithStatement):
3673 decimal = C
3674class PyContextWithStatement(ContextWithStatement):
3675 decimal = P
3676
3677class ContextFlags(unittest.TestCase):
3678
3679 def test_flags_irrelevant(self):
3680 # check that the result (numeric result + flags raised) of an
3681 # arithmetic operation doesn't depend on the current flags
3682 Decimal = self.decimal.Decimal
3683 Context = self.decimal.Context
3684 Inexact = self.decimal.Inexact
3685 Rounded = self.decimal.Rounded
3686 Underflow = self.decimal.Underflow
3687 Clamped = self.decimal.Clamped
3688 Subnormal = self.decimal.Subnormal
Stefan Krah1919b7e2012-03-21 18:25:23 +01003689
3690 def raise_error(context, flag):
3691 if self.decimal == C:
3692 context.flags[flag] = True
3693 if context.traps[flag]:
3694 raise flag
3695 else:
3696 context._raise_error(flag)
3697
3698 context = Context(prec=9, Emin = -425000000, Emax = 425000000,
3699 rounding=ROUND_HALF_EVEN, traps=[], flags=[])
3700
3701 # operations that raise various flags, in the form (function, arglist)
3702 operations = [
3703 (context._apply, [Decimal("100E-425000010")]),
3704 (context.sqrt, [Decimal(2)]),
3705 (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]),
3706 (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]),
3707 (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]),
3708 ]
3709
3710 # try various flags individually, then a whole lot at once
3711 flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal],
3712 [Inexact, Rounded, Underflow, Clamped, Subnormal]]
3713
3714 for fn, args in operations:
3715 # find answer and flags raised using a clean context
3716 context.clear_flags()
3717 ans = fn(*args)
3718 flags = [k for k, v in context.flags.items() if v]
3719
3720 for extra_flags in flagsets:
3721 # set flags, before calling operation
3722 context.clear_flags()
3723 for flag in extra_flags:
3724 raise_error(context, flag)
3725 new_ans = fn(*args)
3726
3727 # flags that we expect to be set after the operation
3728 expected_flags = list(flags)
3729 for flag in extra_flags:
3730 if flag not in expected_flags:
3731 expected_flags.append(flag)
3732 expected_flags.sort(key=id)
3733
3734 # flags we actually got
3735 new_flags = [k for k,v in context.flags.items() if v]
3736 new_flags.sort(key=id)
3737
3738 self.assertEqual(ans, new_ans,
3739 "operation produces different answers depending on flags set: " +
3740 "expected %s, got %s." % (ans, new_ans))
3741 self.assertEqual(new_flags, expected_flags,
3742 "operation raises different flags depending on flags set: " +
3743 "expected %s, got %s" % (expected_flags, new_flags))
3744
3745 def test_flag_comparisons(self):
3746 Context = self.decimal.Context
3747 Inexact = self.decimal.Inexact
3748 Rounded = self.decimal.Rounded
3749
3750 c = Context()
3751
3752 # Valid SignalDict
3753 self.assertNotEqual(c.flags, c.traps)
3754 self.assertNotEqual(c.traps, c.flags)
3755
3756 c.flags = c.traps
3757 self.assertEqual(c.flags, c.traps)
3758 self.assertEqual(c.traps, c.flags)
3759
3760 c.flags[Rounded] = True
3761 c.traps = c.flags
3762 self.assertEqual(c.flags, c.traps)
3763 self.assertEqual(c.traps, c.flags)
3764
3765 d = {}
3766 d.update(c.flags)
3767 self.assertEqual(d, c.flags)
3768 self.assertEqual(c.flags, d)
3769
3770 d[Inexact] = True
3771 self.assertNotEqual(d, c.flags)
3772 self.assertNotEqual(c.flags, d)
3773
3774 # Invalid SignalDict
3775 d = {Inexact:False}
3776 self.assertNotEqual(d, c.flags)
3777 self.assertNotEqual(c.flags, d)
3778
3779 d = ["xyz"]
3780 self.assertNotEqual(d, c.flags)
3781 self.assertNotEqual(c.flags, d)
3782
3783 @requires_IEEE_754
3784 def test_float_operation(self):
3785 Decimal = self.decimal.Decimal
3786 FloatOperation = self.decimal.FloatOperation
3787 localcontext = self.decimal.localcontext
3788
3789 with localcontext() as c:
3790 ##### trap is off by default
3791 self.assertFalse(c.traps[FloatOperation])
3792
3793 # implicit conversion sets the flag
3794 c.clear_flags()
3795 self.assertEqual(Decimal(7.5), 7.5)
3796 self.assertTrue(c.flags[FloatOperation])
3797
3798 c.clear_flags()
3799 self.assertEqual(c.create_decimal(7.5), 7.5)
3800 self.assertTrue(c.flags[FloatOperation])
3801
3802 # explicit conversion does not set the flag
3803 c.clear_flags()
3804 x = Decimal.from_float(7.5)
3805 self.assertFalse(c.flags[FloatOperation])
3806 # comparison sets the flag
3807 self.assertEqual(x, 7.5)
3808 self.assertTrue(c.flags[FloatOperation])
3809
3810 c.clear_flags()
3811 x = c.create_decimal_from_float(7.5)
3812 self.assertFalse(c.flags[FloatOperation])
3813 self.assertEqual(x, 7.5)
3814 self.assertTrue(c.flags[FloatOperation])
3815
3816 ##### set the trap
3817 c.traps[FloatOperation] = True
3818
3819 # implicit conversion raises
3820 c.clear_flags()
3821 self.assertRaises(FloatOperation, Decimal, 7.5)
3822 self.assertTrue(c.flags[FloatOperation])
3823
3824 c.clear_flags()
3825 self.assertRaises(FloatOperation, c.create_decimal, 7.5)
3826 self.assertTrue(c.flags[FloatOperation])
3827
3828 # explicit conversion is silent
3829 c.clear_flags()
3830 x = Decimal.from_float(7.5)
3831 self.assertFalse(c.flags[FloatOperation])
3832
3833 c.clear_flags()
3834 x = c.create_decimal_from_float(7.5)
3835 self.assertFalse(c.flags[FloatOperation])
3836
3837 def test_float_comparison(self):
3838 Decimal = self.decimal.Decimal
3839 Context = self.decimal.Context
3840 FloatOperation = self.decimal.FloatOperation
3841 localcontext = self.decimal.localcontext
3842
3843 def assert_attr(a, b, attr, context, signal=None):
3844 context.clear_flags()
3845 f = getattr(a, attr)
3846 if signal == FloatOperation:
3847 self.assertRaises(signal, f, b)
3848 else:
3849 self.assertIs(f(b), True)
3850 self.assertTrue(context.flags[FloatOperation])
3851
3852 small_d = Decimal('0.25')
3853 big_d = Decimal('3.0')
3854 small_f = 0.25
3855 big_f = 3.0
3856
3857 zero_d = Decimal('0.0')
3858 neg_zero_d = Decimal('-0.0')
3859 zero_f = 0.0
3860 neg_zero_f = -0.0
3861
3862 inf_d = Decimal('Infinity')
3863 neg_inf_d = Decimal('-Infinity')
3864 inf_f = float('inf')
3865 neg_inf_f = float('-inf')
3866
3867 def doit(c, signal=None):
3868 # Order
3869 for attr in '__lt__', '__le__':
3870 assert_attr(small_d, big_f, attr, c, signal)
3871
3872 for attr in '__gt__', '__ge__':
3873 assert_attr(big_d, small_f, attr, c, signal)
3874
3875 # Equality
3876 assert_attr(small_d, small_f, '__eq__', c, None)
3877
3878 assert_attr(neg_zero_d, neg_zero_f, '__eq__', c, None)
3879 assert_attr(neg_zero_d, zero_f, '__eq__', c, None)
3880
3881 assert_attr(zero_d, neg_zero_f, '__eq__', c, None)
3882 assert_attr(zero_d, zero_f, '__eq__', c, None)
3883
3884 assert_attr(neg_inf_d, neg_inf_f, '__eq__', c, None)
3885 assert_attr(inf_d, inf_f, '__eq__', c, None)
3886
3887 # Inequality
3888 assert_attr(small_d, big_f, '__ne__', c, None)
3889
3890 assert_attr(Decimal('0.1'), 0.1, '__ne__', c, None)
3891
3892 assert_attr(neg_inf_d, inf_f, '__ne__', c, None)
3893 assert_attr(inf_d, neg_inf_f, '__ne__', c, None)
3894
3895 assert_attr(Decimal('NaN'), float('nan'), '__ne__', c, None)
3896
3897 def test_containers(c, signal=None):
3898 c.clear_flags()
3899 s = set([100.0, Decimal('100.0')])
3900 self.assertEqual(len(s), 1)
3901 self.assertTrue(c.flags[FloatOperation])
3902
3903 c.clear_flags()
3904 if signal:
3905 self.assertRaises(signal, sorted, [1.0, Decimal('10.0')])
3906 else:
3907 s = sorted([10.0, Decimal('10.0')])
3908 self.assertTrue(c.flags[FloatOperation])
3909
3910 c.clear_flags()
3911 b = 10.0 in [Decimal('10.0'), 1.0]
3912 self.assertTrue(c.flags[FloatOperation])
3913
3914 c.clear_flags()
3915 b = 10.0 in {Decimal('10.0'):'a', 1.0:'b'}
3916 self.assertTrue(c.flags[FloatOperation])
3917
3918 nc = Context()
3919 with localcontext(nc) as c:
3920 self.assertFalse(c.traps[FloatOperation])
3921 doit(c, signal=None)
3922 test_containers(c, signal=None)
3923
3924 c.traps[FloatOperation] = True
3925 doit(c, signal=FloatOperation)
3926 test_containers(c, signal=FloatOperation)
3927
3928 def test_float_operation_default(self):
3929 Decimal = self.decimal.Decimal
3930 Context = self.decimal.Context
3931 Inexact = self.decimal.Inexact
3932 FloatOperation= self.decimal.FloatOperation
3933
3934 context = Context()
3935 self.assertFalse(context.flags[FloatOperation])
3936 self.assertFalse(context.traps[FloatOperation])
3937
3938 context.clear_traps()
3939 context.traps[Inexact] = True
3940 context.traps[FloatOperation] = True
3941 self.assertTrue(context.traps[FloatOperation])
3942 self.assertTrue(context.traps[Inexact])
3943
3944class CContextFlags(ContextFlags):
3945 decimal = C
3946class PyContextFlags(ContextFlags):
3947 decimal = P
3948
3949class SpecialContexts(unittest.TestCase):
3950 """Test the context templates."""
3951
3952 def test_context_templates(self):
3953 BasicContext = self.decimal.BasicContext
3954 ExtendedContext = self.decimal.ExtendedContext
3955 getcontext = self.decimal.getcontext
3956 setcontext = self.decimal.setcontext
3957 InvalidOperation = self.decimal.InvalidOperation
3958 DivisionByZero = self.decimal.DivisionByZero
3959 Overflow = self.decimal.Overflow
3960 Underflow = self.decimal.Underflow
3961 Clamped = self.decimal.Clamped
3962
3963 assert_signals(self, BasicContext, 'traps',
3964 [InvalidOperation, DivisionByZero, Overflow, Underflow, Clamped]
3965 )
3966
3967 savecontext = getcontext().copy()
3968 basic_context_prec = BasicContext.prec
3969 extended_context_prec = ExtendedContext.prec
3970
3971 ex = None
3972 try:
3973 BasicContext.prec = ExtendedContext.prec = 441
3974 for template in BasicContext, ExtendedContext:
3975 setcontext(template)
3976 c = getcontext()
3977 self.assertIsNot(c, template)
3978 self.assertEqual(c.prec, 441)
3979 except Exception as e:
3980 ex = e.__class__
3981 finally:
3982 BasicContext.prec = basic_context_prec
3983 ExtendedContext.prec = extended_context_prec
3984 setcontext(savecontext)
3985 if ex:
3986 raise ex
3987
3988 def test_default_context(self):
3989 DefaultContext = self.decimal.DefaultContext
3990 BasicContext = self.decimal.BasicContext
3991 ExtendedContext = self.decimal.ExtendedContext
3992 getcontext = self.decimal.getcontext
3993 setcontext = self.decimal.setcontext
3994 InvalidOperation = self.decimal.InvalidOperation
3995 DivisionByZero = self.decimal.DivisionByZero
3996 Overflow = self.decimal.Overflow
3997
3998 self.assertEqual(BasicContext.prec, 9)
3999 self.assertEqual(ExtendedContext.prec, 9)
4000
4001 assert_signals(self, DefaultContext, 'traps',
4002 [InvalidOperation, DivisionByZero, Overflow]
4003 )
4004
4005 savecontext = getcontext().copy()
4006 default_context_prec = DefaultContext.prec
4007
4008 ex = None
4009 try:
4010 c = getcontext()
4011 saveprec = c.prec
4012
4013 DefaultContext.prec = 961
4014 c = getcontext()
4015 self.assertEqual(c.prec, saveprec)
4016
4017 setcontext(DefaultContext)
4018 c = getcontext()
4019 self.assertIsNot(c, DefaultContext)
4020 self.assertEqual(c.prec, 961)
4021 except Exception as e:
4022 ex = e.__class__
4023 finally:
4024 DefaultContext.prec = default_context_prec
4025 setcontext(savecontext)
4026 if ex:
4027 raise ex
4028
4029class CSpecialContexts(SpecialContexts):
4030 decimal = C
4031class PySpecialContexts(SpecialContexts):
4032 decimal = P
4033
4034class ContextInputValidation(unittest.TestCase):
4035
4036 def test_invalid_context(self):
4037 Context = self.decimal.Context
4038 DefaultContext = self.decimal.DefaultContext
4039
4040 c = DefaultContext.copy()
4041
4042 # prec, Emax
4043 for attr in ['prec', 'Emax']:
4044 setattr(c, attr, 999999)
4045 self.assertEqual(getattr(c, attr), 999999)
4046 self.assertRaises(ValueError, setattr, c, attr, -1)
4047 self.assertRaises(TypeError, setattr, c, attr, 'xyz')
4048
4049 # Emin
4050 setattr(c, 'Emin', -999999)
4051 self.assertEqual(getattr(c, 'Emin'), -999999)
4052 self.assertRaises(ValueError, setattr, c, 'Emin', 1)
4053 self.assertRaises(TypeError, setattr, c, 'Emin', (1,2,3))
4054
Stefan Krah1919b7e2012-03-21 18:25:23 +01004055 self.assertRaises(TypeError, setattr, c, 'rounding', -1)
4056 self.assertRaises(TypeError, setattr, c, 'rounding', 9)
4057 self.assertRaises(TypeError, setattr, c, 'rounding', 1.0)
4058 self.assertRaises(TypeError, setattr, c, 'rounding', 'xyz')
4059
4060 # capitals, clamp
4061 for attr in ['capitals', 'clamp']:
4062 self.assertRaises(ValueError, setattr, c, attr, -1)
4063 self.assertRaises(ValueError, setattr, c, attr, 2)
4064 self.assertRaises(TypeError, setattr, c, attr, [1,2,3])
4065
4066 # Invalid attribute
4067 self.assertRaises(AttributeError, setattr, c, 'emax', 100)
4068
4069 # Invalid signal dict
4070 self.assertRaises(TypeError, setattr, c, 'flags', [])
4071 self.assertRaises(KeyError, setattr, c, 'flags', {})
4072 self.assertRaises(KeyError, setattr, c, 'traps',
4073 {'InvalidOperation':0})
4074
4075 # Attributes cannot be deleted
4076 for attr in ['prec', 'Emax', 'Emin', 'rounding', 'capitals', 'clamp',
4077 'flags', 'traps']:
4078 self.assertRaises(AttributeError, c.__delattr__, attr)
4079
4080 # Invalid attributes
4081 self.assertRaises(TypeError, getattr, c, 9)
4082 self.assertRaises(TypeError, setattr, c, 9)
4083
4084 # Invalid values in constructor
4085 self.assertRaises(TypeError, Context, rounding=999999)
4086 self.assertRaises(TypeError, Context, rounding='xyz')
4087 self.assertRaises(ValueError, Context, clamp=2)
4088 self.assertRaises(ValueError, Context, capitals=-1)
4089 self.assertRaises(KeyError, Context, flags=["P"])
4090 self.assertRaises(KeyError, Context, traps=["Q"])
4091
4092 # Type error in conversion
4093 self.assertRaises(TypeError, Context, flags=(0,1))
4094 self.assertRaises(TypeError, Context, traps=(1,0))
4095
4096class CContextInputValidation(ContextInputValidation):
4097 decimal = C
4098class PyContextInputValidation(ContextInputValidation):
4099 decimal = P
4100
4101class ContextSubclassing(unittest.TestCase):
4102
4103 def test_context_subclassing(self):
4104 decimal = self.decimal
4105 Decimal = decimal.Decimal
4106 Context = decimal.Context
Stefan Krah1919b7e2012-03-21 18:25:23 +01004107 Clamped = decimal.Clamped
4108 DivisionByZero = decimal.DivisionByZero
4109 Inexact = decimal.Inexact
4110 Overflow = decimal.Overflow
4111 Rounded = decimal.Rounded
4112 Subnormal = decimal.Subnormal
4113 Underflow = decimal.Underflow
4114 InvalidOperation = decimal.InvalidOperation
4115
4116 class MyContext(Context):
4117 def __init__(self, prec=None, rounding=None, Emin=None, Emax=None,
4118 capitals=None, clamp=None, flags=None,
4119 traps=None):
4120 Context.__init__(self)
4121 if prec is not None:
4122 self.prec = prec
4123 if rounding is not None:
4124 self.rounding = rounding
4125 if Emin is not None:
4126 self.Emin = Emin
4127 if Emax is not None:
4128 self.Emax = Emax
4129 if capitals is not None:
4130 self.capitals = capitals
4131 if clamp is not None:
4132 self.clamp = clamp
4133 if flags is not None:
4134 if isinstance(flags, list):
4135 flags = {v:(v in flags) for v in OrderedSignals[decimal] + flags}
4136 self.flags = flags
4137 if traps is not None:
4138 if isinstance(traps, list):
4139 traps = {v:(v in traps) for v in OrderedSignals[decimal] + traps}
4140 self.traps = traps
4141
4142 c = Context()
4143 d = MyContext()
4144 for attr in ('prec', 'rounding', 'Emin', 'Emax', 'capitals', 'clamp',
4145 'flags', 'traps'):
4146 self.assertEqual(getattr(c, attr), getattr(d, attr))
4147
4148 # prec
4149 self.assertRaises(ValueError, MyContext, **{'prec':-1})
4150 c = MyContext(prec=1)
4151 self.assertEqual(c.prec, 1)
4152 self.assertRaises(InvalidOperation, c.quantize, Decimal('9e2'), 0)
4153
4154 # rounding
4155 self.assertRaises(TypeError, MyContext, **{'rounding':'XYZ'})
4156 c = MyContext(rounding=ROUND_DOWN, prec=1)
4157 self.assertEqual(c.rounding, ROUND_DOWN)
4158 self.assertEqual(c.plus(Decimal('9.9')), 9)
4159
4160 # Emin
4161 self.assertRaises(ValueError, MyContext, **{'Emin':5})
4162 c = MyContext(Emin=-1, prec=1)
4163 self.assertEqual(c.Emin, -1)
4164 x = c.add(Decimal('1e-99'), Decimal('2.234e-2000'))
4165 self.assertEqual(x, Decimal('0.0'))
4166 for signal in (Inexact, Underflow, Subnormal, Rounded, Clamped):
4167 self.assertTrue(c.flags[signal])
4168
4169 # Emax
4170 self.assertRaises(ValueError, MyContext, **{'Emax':-1})
4171 c = MyContext(Emax=1, prec=1)
4172 self.assertEqual(c.Emax, 1)
4173 self.assertRaises(Overflow, c.add, Decimal('1e99'), Decimal('2.234e2000'))
4174 if self.decimal == C:
4175 for signal in (Inexact, Overflow, Rounded):
4176 self.assertTrue(c.flags[signal])
4177
4178 # capitals
4179 self.assertRaises(ValueError, MyContext, **{'capitals':-1})
4180 c = MyContext(capitals=0)
4181 self.assertEqual(c.capitals, 0)
4182 x = c.create_decimal('1E222')
4183 self.assertEqual(c.to_sci_string(x), '1e+222')
4184
4185 # clamp
4186 self.assertRaises(ValueError, MyContext, **{'clamp':2})
4187 c = MyContext(clamp=1, Emax=99)
4188 self.assertEqual(c.clamp, 1)
4189 x = c.plus(Decimal('1e99'))
4190 self.assertEqual(str(x), '1.000000000000000000000000000E+99')
4191
4192 # flags
4193 self.assertRaises(TypeError, MyContext, **{'flags':'XYZ'})
4194 c = MyContext(flags=[Rounded, DivisionByZero])
4195 for signal in (Rounded, DivisionByZero):
4196 self.assertTrue(c.flags[signal])
4197 c.clear_flags()
4198 for signal in OrderedSignals[decimal]:
4199 self.assertFalse(c.flags[signal])
4200
4201 # traps
4202 self.assertRaises(TypeError, MyContext, **{'traps':'XYZ'})
4203 c = MyContext(traps=[Rounded, DivisionByZero])
4204 for signal in (Rounded, DivisionByZero):
4205 self.assertTrue(c.traps[signal])
4206 c.clear_traps()
4207 for signal in OrderedSignals[decimal]:
4208 self.assertFalse(c.traps[signal])
4209
4210class CContextSubclassing(ContextSubclassing):
4211 decimal = C
4212class PyContextSubclassing(ContextSubclassing):
4213 decimal = P
4214
4215@skip_if_extra_functionality
4216class CheckAttributes(unittest.TestCase):
4217
4218 def test_module_attributes(self):
4219
4220 # Architecture dependent context limits
4221 self.assertEqual(C.MAX_PREC, P.MAX_PREC)
4222 self.assertEqual(C.MAX_EMAX, P.MAX_EMAX)
4223 self.assertEqual(C.MIN_EMIN, P.MIN_EMIN)
4224 self.assertEqual(C.MIN_ETINY, P.MIN_ETINY)
4225
4226 self.assertTrue(C.HAVE_THREADS is True or C.HAVE_THREADS is False)
4227 self.assertTrue(P.HAVE_THREADS is True or P.HAVE_THREADS is False)
4228
4229 self.assertEqual(C.__version__, P.__version__)
4230
Stefan Krahb578f8a2014-09-10 17:58:15 +02004231 self.assertEqual(dir(C), dir(P))
Stefan Krah1919b7e2012-03-21 18:25:23 +01004232
4233 def test_context_attributes(self):
4234
4235 x = [s for s in dir(C.Context()) if '__' in s or not s.startswith('_')]
4236 y = [s for s in dir(P.Context()) if '__' in s or not s.startswith('_')]
4237 self.assertEqual(set(x) - set(y), set())
4238
4239 def test_decimal_attributes(self):
4240
4241 x = [s for s in dir(C.Decimal(9)) if '__' in s or not s.startswith('_')]
4242 y = [s for s in dir(C.Decimal(9)) if '__' in s or not s.startswith('_')]
4243 self.assertEqual(set(x) - set(y), set())
4244
4245class Coverage(unittest.TestCase):
4246
4247 def test_adjusted(self):
4248 Decimal = self.decimal.Decimal
4249
4250 self.assertEqual(Decimal('1234e9999').adjusted(), 10002)
4251 # XXX raise?
4252 self.assertEqual(Decimal('nan').adjusted(), 0)
4253 self.assertEqual(Decimal('inf').adjusted(), 0)
4254
4255 def test_canonical(self):
4256 Decimal = self.decimal.Decimal
4257 getcontext = self.decimal.getcontext
4258
4259 x = Decimal(9).canonical()
4260 self.assertEqual(x, 9)
4261
4262 c = getcontext()
4263 x = c.canonical(Decimal(9))
4264 self.assertEqual(x, 9)
4265
4266 def test_context_repr(self):
4267 c = self.decimal.DefaultContext.copy()
4268
4269 c.prec = 425000000
4270 c.Emax = 425000000
4271 c.Emin = -425000000
Stefan Krah59a4a932013-01-16 12:58:59 +01004272 c.rounding = ROUND_HALF_DOWN
Stefan Krah1919b7e2012-03-21 18:25:23 +01004273 c.capitals = 0
4274 c.clamp = 1
4275 for sig in OrderedSignals[self.decimal]:
4276 c.flags[sig] = False
4277 c.traps[sig] = False
4278
4279 s = c.__repr__()
4280 t = "Context(prec=425000000, rounding=ROUND_HALF_DOWN, " \
4281 "Emin=-425000000, Emax=425000000, capitals=0, clamp=1, " \
4282 "flags=[], traps=[])"
4283 self.assertEqual(s, t)
4284
4285 def test_implicit_context(self):
4286 Decimal = self.decimal.Decimal
4287 localcontext = self.decimal.localcontext
4288
4289 with localcontext() as c:
4290 c.prec = 1
4291 c.Emax = 1
4292 c.Emin = -1
4293
4294 # abs
4295 self.assertEqual(abs(Decimal("-10")), 10)
4296 # add
4297 self.assertEqual(Decimal("7") + 1, 8)
4298 # divide
4299 self.assertEqual(Decimal("10") / 5, 2)
4300 # divide_int
4301 self.assertEqual(Decimal("10") // 7, 1)
4302 # fma
4303 self.assertEqual(Decimal("1.2").fma(Decimal("0.01"), 1), 1)
4304 self.assertIs(Decimal("NaN").fma(7, 1).is_nan(), True)
4305 # three arg power
4306 self.assertEqual(pow(Decimal(10), 2, 7), 2)
4307 # exp
4308 self.assertEqual(Decimal("1.01").exp(), 3)
4309 # is_normal
4310 self.assertIs(Decimal("0.01").is_normal(), False)
4311 # is_subnormal
4312 self.assertIs(Decimal("0.01").is_subnormal(), True)
4313 # ln
4314 self.assertEqual(Decimal("20").ln(), 3)
4315 # log10
4316 self.assertEqual(Decimal("20").log10(), 1)
4317 # logb
4318 self.assertEqual(Decimal("580").logb(), 2)
4319 # logical_invert
4320 self.assertEqual(Decimal("10").logical_invert(), 1)
4321 # minus
4322 self.assertEqual(-Decimal("-10"), 10)
4323 # multiply
4324 self.assertEqual(Decimal("2") * 4, 8)
4325 # next_minus
4326 self.assertEqual(Decimal("10").next_minus(), 9)
4327 # next_plus
4328 self.assertEqual(Decimal("10").next_plus(), Decimal('2E+1'))
4329 # normalize
4330 self.assertEqual(Decimal("-10").normalize(), Decimal('-1E+1'))
4331 # number_class
4332 self.assertEqual(Decimal("10").number_class(), '+Normal')
4333 # plus
4334 self.assertEqual(+Decimal("-1"), -1)
4335 # remainder
4336 self.assertEqual(Decimal("10") % 7, 3)
4337 # subtract
4338 self.assertEqual(Decimal("10") - 7, 3)
4339 # to_integral_exact
4340 self.assertEqual(Decimal("1.12345").to_integral_exact(), 1)
4341
4342 # Boolean functions
4343 self.assertTrue(Decimal("1").is_canonical())
4344 self.assertTrue(Decimal("1").is_finite())
4345 self.assertTrue(Decimal("1").is_finite())
4346 self.assertTrue(Decimal("snan").is_snan())
4347 self.assertTrue(Decimal("-1").is_signed())
4348 self.assertTrue(Decimal("0").is_zero())
4349 self.assertTrue(Decimal("0").is_zero())
4350
4351 # Copy
4352 with localcontext() as c:
4353 c.prec = 10000
4354 x = 1228 ** 1523
4355 y = -Decimal(x)
4356
4357 z = y.copy_abs()
4358 self.assertEqual(z, x)
4359
4360 z = y.copy_negate()
4361 self.assertEqual(z, x)
4362
4363 z = y.copy_sign(Decimal(1))
4364 self.assertEqual(z, x)
4365
4366 def test_divmod(self):
4367 Decimal = self.decimal.Decimal
4368 localcontext = self.decimal.localcontext
4369 InvalidOperation = self.decimal.InvalidOperation
4370 DivisionByZero = self.decimal.DivisionByZero
4371
4372 with localcontext() as c:
4373 q, r = divmod(Decimal("10912837129"), 1001)
4374 self.assertEqual(q, Decimal('10901935'))
4375 self.assertEqual(r, Decimal('194'))
4376
4377 q, r = divmod(Decimal("NaN"), 7)
4378 self.assertTrue(q.is_nan() and r.is_nan())
4379
4380 c.traps[InvalidOperation] = False
4381 q, r = divmod(Decimal("NaN"), 7)
4382 self.assertTrue(q.is_nan() and r.is_nan())
4383
4384 c.traps[InvalidOperation] = False
4385 c.clear_flags()
4386 q, r = divmod(Decimal("inf"), Decimal("inf"))
4387 self.assertTrue(q.is_nan() and r.is_nan())
4388 self.assertTrue(c.flags[InvalidOperation])
4389
4390 c.clear_flags()
4391 q, r = divmod(Decimal("inf"), 101)
4392 self.assertTrue(q.is_infinite() and r.is_nan())
4393 self.assertTrue(c.flags[InvalidOperation])
4394
4395 c.clear_flags()
4396 q, r = divmod(Decimal(0), 0)
4397 self.assertTrue(q.is_nan() and r.is_nan())
4398 self.assertTrue(c.flags[InvalidOperation])
4399
4400 c.traps[DivisionByZero] = False
4401 c.clear_flags()
4402 q, r = divmod(Decimal(11), 0)
4403 self.assertTrue(q.is_infinite() and r.is_nan())
4404 self.assertTrue(c.flags[InvalidOperation] and
4405 c.flags[DivisionByZero])
4406
4407 def test_power(self):
4408 Decimal = self.decimal.Decimal
4409 localcontext = self.decimal.localcontext
4410 Overflow = self.decimal.Overflow
4411 Rounded = self.decimal.Rounded
4412
4413 with localcontext() as c:
4414 c.prec = 3
4415 c.clear_flags()
4416 self.assertEqual(Decimal("1.0") ** 100, Decimal('1.00'))
4417 self.assertTrue(c.flags[Rounded])
4418
4419 c.prec = 1
4420 c.Emax = 1
4421 c.Emin = -1
4422 c.clear_flags()
4423 c.traps[Overflow] = False
4424 self.assertEqual(Decimal(10000) ** Decimal("0.5"), Decimal('inf'))
4425 self.assertTrue(c.flags[Overflow])
4426
4427 def test_quantize(self):
4428 Decimal = self.decimal.Decimal
4429 localcontext = self.decimal.localcontext
4430 InvalidOperation = self.decimal.InvalidOperation
4431
4432 with localcontext() as c:
4433 c.prec = 1
4434 c.Emax = 1
4435 c.Emin = -1
4436 c.traps[InvalidOperation] = False
4437 x = Decimal(99).quantize(Decimal("1e1"))
4438 self.assertTrue(x.is_nan())
4439
4440 def test_radix(self):
4441 Decimal = self.decimal.Decimal
4442 getcontext = self.decimal.getcontext
4443
4444 c = getcontext()
4445 self.assertEqual(Decimal("1").radix(), 10)
4446 self.assertEqual(c.radix(), 10)
4447
4448 def test_rop(self):
4449 Decimal = self.decimal.Decimal
4450
4451 for attr in ('__radd__', '__rsub__', '__rmul__', '__rtruediv__',
4452 '__rdivmod__', '__rmod__', '__rfloordiv__', '__rpow__'):
4453 self.assertIs(getattr(Decimal("1"), attr)("xyz"), NotImplemented)
4454
4455 def test_round(self):
4456 # Python3 behavior: round() returns Decimal
4457 Decimal = self.decimal.Decimal
4458 getcontext = self.decimal.getcontext
4459
4460 c = getcontext()
4461 c.prec = 28
4462
4463 self.assertEqual(str(Decimal("9.99").__round__()), "10")
4464 self.assertEqual(str(Decimal("9.99e-5").__round__()), "0")
4465 self.assertEqual(str(Decimal("1.23456789").__round__(5)), "1.23457")
4466 self.assertEqual(str(Decimal("1.2345").__round__(10)), "1.2345000000")
4467 self.assertEqual(str(Decimal("1.2345").__round__(-10)), "0E+10")
4468
4469 self.assertRaises(TypeError, Decimal("1.23").__round__, "5")
4470 self.assertRaises(TypeError, Decimal("1.23").__round__, 5, 8)
4471
4472 def test_create_decimal(self):
4473 c = self.decimal.Context()
4474 self.assertRaises(ValueError, c.create_decimal, ["%"])
4475
4476 def test_int(self):
4477 Decimal = self.decimal.Decimal
4478 localcontext = self.decimal.localcontext
4479
4480 with localcontext() as c:
4481 c.prec = 9999
4482 x = Decimal(1221**1271) / 10**3923
4483 self.assertEqual(int(x), 1)
4484 self.assertEqual(x.to_integral(), 2)
4485
4486 def test_copy(self):
4487 Context = self.decimal.Context
4488
4489 c = Context()
4490 c.prec = 10000
4491 x = -(1172 ** 1712)
4492
4493 y = c.copy_abs(x)
4494 self.assertEqual(y, -x)
4495
4496 y = c.copy_negate(x)
4497 self.assertEqual(y, -x)
4498
4499 y = c.copy_sign(x, 1)
4500 self.assertEqual(y, -x)
4501
4502class CCoverage(Coverage):
4503 decimal = C
4504class PyCoverage(Coverage):
4505 decimal = P
4506
4507class PyFunctionality(unittest.TestCase):
4508 """Extra functionality in decimal.py"""
4509
Stefan Krah1919b7e2012-03-21 18:25:23 +01004510 def test_py_alternate_formatting(self):
4511 # triples giving a format, a Decimal, and the expected result
4512 Decimal = P.Decimal
4513 localcontext = P.localcontext
4514
4515 test_values = [
4516 # Issue 7094: Alternate formatting (specified by #)
4517 ('.0e', '1.0', '1e+0'),
4518 ('#.0e', '1.0', '1.e+0'),
4519 ('.0f', '1.0', '1'),
4520 ('#.0f', '1.0', '1.'),
4521 ('g', '1.1', '1.1'),
4522 ('#g', '1.1', '1.1'),
4523 ('.0g', '1', '1'),
4524 ('#.0g', '1', '1.'),
4525 ('.0%', '1.0', '100%'),
4526 ('#.0%', '1.0', '100.%'),
4527 ]
4528 for fmt, d, result in test_values:
4529 self.assertEqual(format(Decimal(d), fmt), result)
4530
4531class PyWhitebox(unittest.TestCase):
4532 """White box testing for decimal.py"""
4533
4534 def test_py_exact_power(self):
4535 # Rarely exercised lines in _power_exact.
4536 Decimal = P.Decimal
4537 localcontext = P.localcontext
4538
4539 with localcontext() as c:
4540 c.prec = 8
4541 x = Decimal(2**16) ** Decimal("-0.5")
4542 self.assertEqual(x, Decimal('0.00390625'))
4543
4544 x = Decimal(2**16) ** Decimal("-0.6")
4545 self.assertEqual(x, Decimal('0.0012885819'))
4546
4547 x = Decimal("256e7") ** Decimal("-0.5")
4548
4549 x = Decimal(152587890625) ** Decimal('-0.0625')
4550 self.assertEqual(x, Decimal("0.2"))
4551
4552 x = Decimal("152587890625e7") ** Decimal('-0.0625')
4553
4554 x = Decimal(5**2659) ** Decimal('-0.0625')
4555
4556 c.prec = 1
4557 x = Decimal("152587890625") ** Decimal('-0.5')
4558 c.prec = 201
4559 x = Decimal(2**578) ** Decimal("-0.5")
4560
4561 def test_py_immutability_operations(self):
Terry Jan Reedy0f847642013-03-11 18:34:00 -04004562 # Do operations and check that it didn't change internal objects.
Stefan Krah1919b7e2012-03-21 18:25:23 +01004563 Decimal = P.Decimal
4564 DefaultContext = P.DefaultContext
4565 setcontext = P.setcontext
4566
4567 c = DefaultContext.copy()
4568 c.traps = dict((s, 0) for s in OrderedSignals[P])
4569 setcontext(c)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004570
4571 d1 = Decimal('-25e55')
4572 b1 = Decimal('-25e55')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004573 d2 = Decimal('33e+33')
4574 b2 = Decimal('33e+33')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004575
4576 def checkSameDec(operation, useOther=False):
4577 if useOther:
4578 eval("d1." + operation + "(d2)")
4579 self.assertEqual(d1._sign, b1._sign)
4580 self.assertEqual(d1._int, b1._int)
4581 self.assertEqual(d1._exp, b1._exp)
4582 self.assertEqual(d2._sign, b2._sign)
4583 self.assertEqual(d2._int, b2._int)
4584 self.assertEqual(d2._exp, b2._exp)
4585 else:
4586 eval("d1." + operation + "()")
4587 self.assertEqual(d1._sign, b1._sign)
4588 self.assertEqual(d1._int, b1._int)
4589 self.assertEqual(d1._exp, b1._exp)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004590
4591 Decimal(d1)
4592 self.assertEqual(d1._sign, b1._sign)
4593 self.assertEqual(d1._int, b1._int)
4594 self.assertEqual(d1._exp, b1._exp)
4595
4596 checkSameDec("__abs__")
4597 checkSameDec("__add__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004598 checkSameDec("__divmod__", True)
Christian Heimes77c02eb2008-02-09 02:18:51 +00004599 checkSameDec("__eq__", True)
4600 checkSameDec("__ne__", True)
4601 checkSameDec("__le__", True)
4602 checkSameDec("__lt__", True)
4603 checkSameDec("__ge__", True)
4604 checkSameDec("__gt__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004605 checkSameDec("__float__")
4606 checkSameDec("__floordiv__", True)
4607 checkSameDec("__hash__")
4608 checkSameDec("__int__")
Christian Heimes969fe572008-01-25 11:23:10 +00004609 checkSameDec("__trunc__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004610 checkSameDec("__mod__", True)
4611 checkSameDec("__mul__", True)
4612 checkSameDec("__neg__")
Jack Diederich4dafcc42006-11-28 19:15:13 +00004613 checkSameDec("__bool__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004614 checkSameDec("__pos__")
4615 checkSameDec("__pow__", True)
4616 checkSameDec("__radd__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004617 checkSameDec("__rdivmod__", True)
4618 checkSameDec("__repr__")
4619 checkSameDec("__rfloordiv__", True)
4620 checkSameDec("__rmod__", True)
4621 checkSameDec("__rmul__", True)
4622 checkSameDec("__rpow__", True)
4623 checkSameDec("__rsub__", True)
4624 checkSameDec("__str__")
4625 checkSameDec("__sub__", True)
4626 checkSameDec("__truediv__", True)
4627 checkSameDec("adjusted")
4628 checkSameDec("as_tuple")
4629 checkSameDec("compare", True)
4630 checkSameDec("max", True)
4631 checkSameDec("min", True)
4632 checkSameDec("normalize")
4633 checkSameDec("quantize", True)
4634 checkSameDec("remainder_near", True)
4635 checkSameDec("same_quantum", True)
4636 checkSameDec("sqrt")
4637 checkSameDec("to_eng_string")
4638 checkSameDec("to_integral")
4639
Stefan Krah1919b7e2012-03-21 18:25:23 +01004640 def test_py_decimal_id(self):
4641 Decimal = P.Decimal
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004642
Stefan Krah1919b7e2012-03-21 18:25:23 +01004643 d = Decimal(45)
4644 e = Decimal(d)
4645 self.assertEqual(str(e), '45')
4646 self.assertNotEqual(id(d), id(e))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004647
Stefan Krah1919b7e2012-03-21 18:25:23 +01004648 def test_py_rescale(self):
4649 # Coverage
4650 Decimal = P.Decimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01004651 localcontext = P.localcontext
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004652
Stefan Krah1919b7e2012-03-21 18:25:23 +01004653 with localcontext() as c:
4654 x = Decimal("NaN")._rescale(3, ROUND_UP)
4655 self.assertTrue(x.is_nan())
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004656
Stefan Krah1919b7e2012-03-21 18:25:23 +01004657 def test_py__round(self):
4658 # Coverage
4659 Decimal = P.Decimal
Christian Heimes0348fb62008-03-26 12:55:56 +00004660
Stefan Krah1919b7e2012-03-21 18:25:23 +01004661 self.assertRaises(ValueError, Decimal("3.1234")._round, 0, ROUND_UP)
Mark Dickinsona2d1fe02009-10-29 12:23:02 +00004662
Stefan Krah1919b7e2012-03-21 18:25:23 +01004663class CFunctionality(unittest.TestCase):
4664 """Extra functionality in _decimal"""
Mark Dickinsona2d1fe02009-10-29 12:23:02 +00004665
Stefan Krah1919b7e2012-03-21 18:25:23 +01004666 @requires_extra_functionality
4667 def test_c_ieee_context(self):
4668 # issue 8786: Add support for IEEE 754 contexts to decimal module.
4669 IEEEContext = C.IEEEContext
4670 DECIMAL32 = C.DECIMAL32
4671 DECIMAL64 = C.DECIMAL64
4672 DECIMAL128 = C.DECIMAL128
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004673
Stefan Krah1919b7e2012-03-21 18:25:23 +01004674 def assert_rest(self, context):
4675 self.assertEqual(context.clamp, 1)
4676 assert_signals(self, context, 'traps', [])
4677 assert_signals(self, context, 'flags', [])
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004678
Stefan Krah1919b7e2012-03-21 18:25:23 +01004679 c = IEEEContext(DECIMAL32)
4680 self.assertEqual(c.prec, 7)
4681 self.assertEqual(c.Emax, 96)
4682 self.assertEqual(c.Emin, -95)
4683 assert_rest(self, c)
Raymond Hettinger82417ca2009-02-03 03:54:28 +00004684
Stefan Krah1919b7e2012-03-21 18:25:23 +01004685 c = IEEEContext(DECIMAL64)
4686 self.assertEqual(c.prec, 16)
4687 self.assertEqual(c.Emax, 384)
4688 self.assertEqual(c.Emin, -383)
4689 assert_rest(self, c)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004690
Stefan Krah1919b7e2012-03-21 18:25:23 +01004691 c = IEEEContext(DECIMAL128)
4692 self.assertEqual(c.prec, 34)
4693 self.assertEqual(c.Emax, 6144)
4694 self.assertEqual(c.Emin, -6143)
4695 assert_rest(self, c)
Raymond Hettinger5548be22004-07-05 18:49:38 +00004696
Stefan Krah1919b7e2012-03-21 18:25:23 +01004697 # Invalid values
4698 self.assertRaises(OverflowError, IEEEContext, 2**63)
4699 self.assertRaises(ValueError, IEEEContext, -1)
4700 self.assertRaises(ValueError, IEEEContext, 1024)
Mark Dickinson825fce32009-09-07 18:08:12 +00004701
Stefan Krah1919b7e2012-03-21 18:25:23 +01004702 @requires_extra_functionality
4703 def test_c_context(self):
4704 Context = C.Context
Christian Heimes969fe572008-01-25 11:23:10 +00004705
Stefan Krah1919b7e2012-03-21 18:25:23 +01004706 c = Context(flags=C.DecClamped, traps=C.DecRounded)
4707 self.assertEqual(c._flags, C.DecClamped)
4708 self.assertEqual(c._traps, C.DecRounded)
Raymond Hettinger771ed762009-01-03 19:20:32 +00004709
Stefan Krah1919b7e2012-03-21 18:25:23 +01004710 @requires_extra_functionality
4711 def test_constants(self):
4712 # Condition flags
4713 cond = (
4714 C.DecClamped, C.DecConversionSyntax, C.DecDivisionByZero,
4715 C.DecDivisionImpossible, C.DecDivisionUndefined,
4716 C.DecFpuError, C.DecInexact, C.DecInvalidContext,
4717 C.DecInvalidOperation, C.DecMallocError,
4718 C.DecFloatOperation, C.DecOverflow, C.DecRounded,
4719 C.DecSubnormal, C.DecUnderflow
Raymond Hettinger771ed762009-01-03 19:20:32 +00004720 )
Stefan Krah1919b7e2012-03-21 18:25:23 +01004721
4722 # IEEEContext
4723 self.assertEqual(C.DECIMAL32, 32)
4724 self.assertEqual(C.DECIMAL64, 64)
4725 self.assertEqual(C.DECIMAL128, 128)
4726 self.assertEqual(C.IEEE_CONTEXT_MAX_BITS, 512)
4727
Stefan Krah1919b7e2012-03-21 18:25:23 +01004728 # Conditions
4729 for i, v in enumerate(cond):
4730 self.assertEqual(v, 1<<i)
4731
4732 self.assertEqual(C.DecIEEEInvalidOperation,
4733 C.DecConversionSyntax|
4734 C.DecDivisionImpossible|
4735 C.DecDivisionUndefined|
4736 C.DecFpuError|
4737 C.DecInvalidContext|
4738 C.DecInvalidOperation|
4739 C.DecMallocError)
4740
4741 self.assertEqual(C.DecErrors,
4742 C.DecIEEEInvalidOperation|
4743 C.DecDivisionByZero)
4744
4745 self.assertEqual(C.DecTraps,
4746 C.DecErrors|C.DecOverflow|C.DecUnderflow)
4747
4748class CWhitebox(unittest.TestCase):
4749 """Whitebox testing for _decimal"""
4750
4751 def test_bignum(self):
4752 # Not exactly whitebox, but too slow with pydecimal.
4753
4754 Decimal = C.Decimal
4755 localcontext = C.localcontext
4756
4757 b1 = 10**35
4758 b2 = 10**36
4759 with localcontext() as c:
4760 c.prec = 1000000
4761 for i in range(5):
4762 a = random.randrange(b1, b2)
4763 b = random.randrange(1000, 1200)
4764 x = a ** b
4765 y = Decimal(a) ** Decimal(b)
4766 self.assertEqual(x, y)
4767
4768 def test_invalid_construction(self):
4769 self.assertRaises(TypeError, C.Decimal, 9, "xyz")
4770
4771 def test_c_input_restriction(self):
4772 # Too large for _decimal to be converted exactly
4773 Decimal = C.Decimal
4774 InvalidOperation = C.InvalidOperation
4775 Context = C.Context
4776 localcontext = C.localcontext
4777
4778 with localcontext(Context()):
4779 self.assertRaises(InvalidOperation, Decimal,
4780 "1e9999999999999999999")
4781
4782 def test_c_context_repr(self):
4783 # This test is _decimal-only because flags are not printed
4784 # in the same order.
4785 DefaultContext = C.DefaultContext
4786 FloatOperation = C.FloatOperation
Stefan Krah1919b7e2012-03-21 18:25:23 +01004787
4788 c = DefaultContext.copy()
4789
4790 c.prec = 425000000
4791 c.Emax = 425000000
4792 c.Emin = -425000000
4793 c.rounding = ROUND_HALF_DOWN
4794 c.capitals = 0
4795 c.clamp = 1
4796 for sig in OrderedSignals[C]:
4797 c.flags[sig] = True
4798 c.traps[sig] = True
4799 c.flags[FloatOperation] = True
4800 c.traps[FloatOperation] = True
4801
4802 s = c.__repr__()
4803 t = "Context(prec=425000000, rounding=ROUND_HALF_DOWN, " \
4804 "Emin=-425000000, Emax=425000000, capitals=0, clamp=1, " \
4805 "flags=[Clamped, InvalidOperation, DivisionByZero, Inexact, " \
4806 "FloatOperation, Overflow, Rounded, Subnormal, Underflow], " \
4807 "traps=[Clamped, InvalidOperation, DivisionByZero, Inexact, " \
4808 "FloatOperation, Overflow, Rounded, Subnormal, Underflow])"
4809 self.assertEqual(s, t)
4810
4811 def test_c_context_errors(self):
4812 Context = C.Context
4813 InvalidOperation = C.InvalidOperation
4814 Overflow = C.Overflow
4815 FloatOperation = C.FloatOperation
4816 localcontext = C.localcontext
4817 getcontext = C.getcontext
4818 setcontext = C.setcontext
4819 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
4820
4821 c = Context()
4822
4823 # SignalDict: input validation
4824 self.assertRaises(KeyError, c.flags.__setitem__, 801, 0)
4825 self.assertRaises(KeyError, c.traps.__setitem__, 801, 0)
4826 self.assertRaises(ValueError, c.flags.__delitem__, Overflow)
4827 self.assertRaises(ValueError, c.traps.__delitem__, InvalidOperation)
4828 self.assertRaises(TypeError, setattr, c, 'flags', ['x'])
4829 self.assertRaises(TypeError, setattr, c,'traps', ['y'])
4830 self.assertRaises(KeyError, setattr, c, 'flags', {0:1})
4831 self.assertRaises(KeyError, setattr, c, 'traps', {0:1})
4832
4833 # Test assignment from a signal dict with the correct length but
4834 # one invalid key.
4835 d = c.flags.copy()
4836 del d[FloatOperation]
4837 d["XYZ"] = 91283719
4838 self.assertRaises(KeyError, setattr, c, 'flags', d)
4839 self.assertRaises(KeyError, setattr, c, 'traps', d)
4840
4841 # Input corner cases
4842 int_max = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
4843 gt_max_emax = 10**18 if HAVE_CONFIG_64 else 10**9
4844
4845 # prec, Emax, Emin
4846 for attr in ['prec', 'Emax']:
4847 self.assertRaises(ValueError, setattr, c, attr, gt_max_emax)
4848 self.assertRaises(ValueError, setattr, c, 'Emin', -gt_max_emax)
4849
4850 # prec, Emax, Emin in context constructor
4851 self.assertRaises(ValueError, Context, prec=gt_max_emax)
4852 self.assertRaises(ValueError, Context, Emax=gt_max_emax)
4853 self.assertRaises(ValueError, Context, Emin=-gt_max_emax)
4854
4855 # Overflow in conversion
4856 self.assertRaises(OverflowError, Context, prec=int_max+1)
4857 self.assertRaises(OverflowError, Context, Emax=int_max+1)
4858 self.assertRaises(OverflowError, Context, Emin=-int_max-2)
Stefan Krah1919b7e2012-03-21 18:25:23 +01004859 self.assertRaises(OverflowError, Context, clamp=int_max+1)
4860 self.assertRaises(OverflowError, Context, capitals=int_max+1)
4861
4862 # OverflowError, general ValueError
4863 for attr in ('prec', 'Emin', 'Emax', 'capitals', 'clamp'):
4864 self.assertRaises(OverflowError, setattr, c, attr, int_max+1)
4865 self.assertRaises(OverflowError, setattr, c, attr, -int_max-2)
4866 if sys.platform != 'win32':
4867 self.assertRaises(ValueError, setattr, c, attr, int_max)
4868 self.assertRaises(ValueError, setattr, c, attr, -int_max-1)
4869
Stefan Krah1919b7e2012-03-21 18:25:23 +01004870 # OverflowError: _unsafe_setprec, _unsafe_setemin, _unsafe_setemax
4871 if C.MAX_PREC == 425000000:
4872 self.assertRaises(OverflowError, getattr(c, '_unsafe_setprec'),
4873 int_max+1)
4874 self.assertRaises(OverflowError, getattr(c, '_unsafe_setemax'),
4875 int_max+1)
4876 self.assertRaises(OverflowError, getattr(c, '_unsafe_setemin'),
4877 -int_max-2)
4878
4879 # ValueError: _unsafe_setprec, _unsafe_setemin, _unsafe_setemax
4880 if C.MAX_PREC == 425000000:
4881 self.assertRaises(ValueError, getattr(c, '_unsafe_setprec'), 0)
4882 self.assertRaises(ValueError, getattr(c, '_unsafe_setprec'),
4883 1070000001)
4884 self.assertRaises(ValueError, getattr(c, '_unsafe_setemax'), -1)
4885 self.assertRaises(ValueError, getattr(c, '_unsafe_setemax'),
4886 1070000001)
4887 self.assertRaises(ValueError, getattr(c, '_unsafe_setemin'),
4888 -1070000001)
4889 self.assertRaises(ValueError, getattr(c, '_unsafe_setemin'), 1)
4890
4891 # capitals, clamp
4892 for attr in ['capitals', 'clamp']:
4893 self.assertRaises(ValueError, setattr, c, attr, -1)
4894 self.assertRaises(ValueError, setattr, c, attr, 2)
4895 self.assertRaises(TypeError, setattr, c, attr, [1,2,3])
4896 if HAVE_CONFIG_64:
4897 self.assertRaises(ValueError, setattr, c, attr, 2**32)
4898 self.assertRaises(ValueError, setattr, c, attr, 2**32+1)
4899
4900 # Invalid local context
4901 self.assertRaises(TypeError, exec, 'with localcontext("xyz"): pass',
4902 locals())
Stefan Krah040e3112012-12-15 22:33:33 +01004903 self.assertRaises(TypeError, exec,
4904 'with localcontext(context=getcontext()): pass',
4905 locals())
Stefan Krah1919b7e2012-03-21 18:25:23 +01004906
4907 # setcontext
4908 saved_context = getcontext()
4909 self.assertRaises(TypeError, setcontext, "xyz")
4910 setcontext(saved_context)
4911
Stefan Krah59a4a932013-01-16 12:58:59 +01004912 def test_rounding_strings_interned(self):
4913
4914 self.assertIs(C.ROUND_UP, P.ROUND_UP)
4915 self.assertIs(C.ROUND_DOWN, P.ROUND_DOWN)
4916 self.assertIs(C.ROUND_CEILING, P.ROUND_CEILING)
4917 self.assertIs(C.ROUND_FLOOR, P.ROUND_FLOOR)
4918 self.assertIs(C.ROUND_HALF_UP, P.ROUND_HALF_UP)
4919 self.assertIs(C.ROUND_HALF_DOWN, P.ROUND_HALF_DOWN)
4920 self.assertIs(C.ROUND_HALF_EVEN, P.ROUND_HALF_EVEN)
4921 self.assertIs(C.ROUND_05UP, P.ROUND_05UP)
4922
Stefan Krah1919b7e2012-03-21 18:25:23 +01004923 @requires_extra_functionality
4924 def test_c_context_errors_extra(self):
4925 Context = C.Context
4926 InvalidOperation = C.InvalidOperation
4927 Overflow = C.Overflow
4928 localcontext = C.localcontext
4929 getcontext = C.getcontext
4930 setcontext = C.setcontext
4931 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
4932
4933 c = Context()
4934
4935 # Input corner cases
4936 int_max = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
4937
4938 # OverflowError, general ValueError
4939 self.assertRaises(OverflowError, setattr, c, '_allcr', int_max+1)
4940 self.assertRaises(OverflowError, setattr, c, '_allcr', -int_max-2)
4941 if sys.platform != 'win32':
4942 self.assertRaises(ValueError, setattr, c, '_allcr', int_max)
4943 self.assertRaises(ValueError, setattr, c, '_allcr', -int_max-1)
4944
4945 # OverflowError, general TypeError
4946 for attr in ('_flags', '_traps'):
4947 self.assertRaises(OverflowError, setattr, c, attr, int_max+1)
4948 self.assertRaises(OverflowError, setattr, c, attr, -int_max-2)
4949 if sys.platform != 'win32':
4950 self.assertRaises(TypeError, setattr, c, attr, int_max)
4951 self.assertRaises(TypeError, setattr, c, attr, -int_max-1)
4952
4953 # _allcr
4954 self.assertRaises(ValueError, setattr, c, '_allcr', -1)
4955 self.assertRaises(ValueError, setattr, c, '_allcr', 2)
4956 self.assertRaises(TypeError, setattr, c, '_allcr', [1,2,3])
4957 if HAVE_CONFIG_64:
4958 self.assertRaises(ValueError, setattr, c, '_allcr', 2**32)
4959 self.assertRaises(ValueError, setattr, c, '_allcr', 2**32+1)
4960
4961 # _flags, _traps
4962 for attr in ['_flags', '_traps']:
4963 self.assertRaises(TypeError, setattr, c, attr, 999999)
4964 self.assertRaises(TypeError, setattr, c, attr, 'x')
4965
4966 def test_c_valid_context(self):
4967 # These tests are for code coverage in _decimal.
4968 DefaultContext = C.DefaultContext
Stefan Krah1919b7e2012-03-21 18:25:23 +01004969 Clamped = C.Clamped
4970 Underflow = C.Underflow
4971 Inexact = C.Inexact
4972 Rounded = C.Rounded
4973 Subnormal = C.Subnormal
4974
4975 c = DefaultContext.copy()
4976
4977 # Exercise all getters and setters
4978 c.prec = 34
4979 c.rounding = ROUND_HALF_UP
4980 c.Emax = 3000
4981 c.Emin = -3000
4982 c.capitals = 1
4983 c.clamp = 0
4984
4985 self.assertEqual(c.prec, 34)
4986 self.assertEqual(c.rounding, ROUND_HALF_UP)
4987 self.assertEqual(c.Emin, -3000)
4988 self.assertEqual(c.Emax, 3000)
4989 self.assertEqual(c.capitals, 1)
4990 self.assertEqual(c.clamp, 0)
4991
4992 self.assertEqual(c.Etiny(), -3033)
4993 self.assertEqual(c.Etop(), 2967)
4994
4995 # Exercise all unsafe setters
4996 if C.MAX_PREC == 425000000:
4997 c._unsafe_setprec(999999999)
4998 c._unsafe_setemax(999999999)
4999 c._unsafe_setemin(-999999999)
5000 self.assertEqual(c.prec, 999999999)
5001 self.assertEqual(c.Emax, 999999999)
5002 self.assertEqual(c.Emin, -999999999)
5003
5004 @requires_extra_functionality
5005 def test_c_valid_context_extra(self):
5006 DefaultContext = C.DefaultContext
5007
5008 c = DefaultContext.copy()
5009 self.assertEqual(c._allcr, 1)
5010 c._allcr = 0
5011 self.assertEqual(c._allcr, 0)
5012
5013 def test_c_round(self):
5014 # Restricted input.
5015 Decimal = C.Decimal
5016 InvalidOperation = C.InvalidOperation
5017 localcontext = C.localcontext
5018 MAX_EMAX = C.MAX_EMAX
5019 MIN_ETINY = C.MIN_ETINY
5020 int_max = 2**63-1 if C.MAX_PREC > 425000000 else 2**31-1
5021
5022 with localcontext() as c:
5023 c.traps[InvalidOperation] = True
5024 self.assertRaises(InvalidOperation, Decimal("1.23").__round__,
5025 -int_max-1)
5026 self.assertRaises(InvalidOperation, Decimal("1.23").__round__,
5027 int_max)
5028 self.assertRaises(InvalidOperation, Decimal("1").__round__,
5029 int(MAX_EMAX+1))
5030 self.assertRaises(C.InvalidOperation, Decimal("1").__round__,
5031 -int(MIN_ETINY-1))
5032 self.assertRaises(OverflowError, Decimal("1.23").__round__,
5033 -int_max-2)
5034 self.assertRaises(OverflowError, Decimal("1.23").__round__,
5035 int_max+1)
5036
5037 def test_c_format(self):
5038 # Restricted input
5039 Decimal = C.Decimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01005040 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
5041
5042 self.assertRaises(TypeError, Decimal(1).__format__, "=10.10", [], 9)
5043 self.assertRaises(TypeError, Decimal(1).__format__, "=10.10", 9)
5044 self.assertRaises(TypeError, Decimal(1).__format__, [])
5045
Stefan Kraheb8c4512013-01-24 15:22:33 +01005046 self.assertRaises(ValueError, Decimal(1).__format__, "<>=10.10")
5047 maxsize = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
5048 self.assertRaises(ValueError, Decimal("1.23456789").__format__,
5049 "=%d.1" % maxsize)
Stefan Krah1919b7e2012-03-21 18:25:23 +01005050
5051 def test_c_integral(self):
5052 Decimal = C.Decimal
5053 Inexact = C.Inexact
Stefan Krah1919b7e2012-03-21 18:25:23 +01005054 localcontext = C.localcontext
5055
5056 x = Decimal(10)
5057 self.assertEqual(x.to_integral(), 10)
5058 self.assertRaises(TypeError, x.to_integral, '10')
5059 self.assertRaises(TypeError, x.to_integral, 10, 'x')
5060 self.assertRaises(TypeError, x.to_integral, 10)
5061
5062 self.assertEqual(x.to_integral_value(), 10)
5063 self.assertRaises(TypeError, x.to_integral_value, '10')
5064 self.assertRaises(TypeError, x.to_integral_value, 10, 'x')
5065 self.assertRaises(TypeError, x.to_integral_value, 10)
5066
5067 self.assertEqual(x.to_integral_exact(), 10)
5068 self.assertRaises(TypeError, x.to_integral_exact, '10')
5069 self.assertRaises(TypeError, x.to_integral_exact, 10, 'x')
5070 self.assertRaises(TypeError, x.to_integral_exact, 10)
5071
5072 with localcontext() as c:
5073 x = Decimal("99999999999999999999999999.9").to_integral_value(ROUND_UP)
5074 self.assertEqual(x, Decimal('100000000000000000000000000'))
5075
5076 x = Decimal("99999999999999999999999999.9").to_integral_exact(ROUND_UP)
5077 self.assertEqual(x, Decimal('100000000000000000000000000'))
5078
5079 c.traps[Inexact] = True
5080 self.assertRaises(Inexact, Decimal("999.9").to_integral_exact, ROUND_UP)
5081
5082 def test_c_funcs(self):
5083 # Invalid arguments
5084 Decimal = C.Decimal
5085 InvalidOperation = C.InvalidOperation
5086 DivisionByZero = C.DivisionByZero
Stefan Krah1919b7e2012-03-21 18:25:23 +01005087 getcontext = C.getcontext
5088 localcontext = C.localcontext
5089
5090 self.assertEqual(Decimal('9.99e10').to_eng_string(), '99.9E+9')
5091
5092 self.assertRaises(TypeError, pow, Decimal(1), 2, "3")
5093 self.assertRaises(TypeError, Decimal(9).number_class, "x", "y")
5094 self.assertRaises(TypeError, Decimal(9).same_quantum, 3, "x", "y")
5095
Raymond Hettinger771ed762009-01-03 19:20:32 +00005096 self.assertRaises(
Stefan Krah1919b7e2012-03-21 18:25:23 +01005097 TypeError,
5098 Decimal("1.23456789").quantize, Decimal('1e-100000'), []
Raymond Hettinger771ed762009-01-03 19:20:32 +00005099 )
Stefan Krah1919b7e2012-03-21 18:25:23 +01005100 self.assertRaises(
5101 TypeError,
5102 Decimal("1.23456789").quantize, Decimal('1e-100000'), getcontext()
5103 )
5104 self.assertRaises(
5105 TypeError,
5106 Decimal("1.23456789").quantize, Decimal('1e-100000'), 10
5107 )
5108 self.assertRaises(
5109 TypeError,
5110 Decimal("1.23456789").quantize, Decimal('1e-100000'), ROUND_UP, 1000
5111 )
Raymond Hettinger771ed762009-01-03 19:20:32 +00005112
Stefan Krah1919b7e2012-03-21 18:25:23 +01005113 with localcontext() as c:
5114 c.clear_traps()
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00005115
Stefan Krah1919b7e2012-03-21 18:25:23 +01005116 # Invalid arguments
5117 self.assertRaises(TypeError, c.copy_sign, Decimal(1), "x", "y")
5118 self.assertRaises(TypeError, c.canonical, 200)
5119 self.assertRaises(TypeError, c.is_canonical, 200)
5120 self.assertRaises(TypeError, c.divmod, 9, 8, "x", "y")
5121 self.assertRaises(TypeError, c.same_quantum, 9, 3, "x", "y")
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00005122
Stefan Krah1919b7e2012-03-21 18:25:23 +01005123 self.assertEqual(str(c.canonical(Decimal(200))), '200')
5124 self.assertEqual(c.radix(), 10)
Raymond Hettinger0aeac102004-07-05 22:53:03 +00005125
Stefan Krah1919b7e2012-03-21 18:25:23 +01005126 c.traps[DivisionByZero] = True
5127 self.assertRaises(DivisionByZero, Decimal(9).__divmod__, 0)
5128 self.assertRaises(DivisionByZero, c.divmod, 9, 0)
5129 self.assertTrue(c.flags[InvalidOperation])
Raymond Hettinger955d2b22004-08-08 20:17:45 +00005130
Stefan Krah1919b7e2012-03-21 18:25:23 +01005131 c.clear_flags()
5132 c.traps[InvalidOperation] = True
5133 self.assertRaises(InvalidOperation, Decimal(9).__divmod__, 0)
5134 self.assertRaises(InvalidOperation, c.divmod, 9, 0)
5135 self.assertTrue(c.flags[DivisionByZero])
Mark Dickinsonb1d8e322010-05-22 18:35:36 +00005136
Stefan Krah1919b7e2012-03-21 18:25:23 +01005137 c.traps[InvalidOperation] = True
5138 c.prec = 2
5139 self.assertRaises(InvalidOperation, pow, Decimal(1000), 1, 501)
Mark Dickinson84230a12010-02-18 14:49:50 +00005140
Stefan Krah040e3112012-12-15 22:33:33 +01005141 def test_va_args_exceptions(self):
5142 Decimal = C.Decimal
5143 Context = C.Context
5144
5145 x = Decimal("10001111111")
5146
5147 for attr in ['exp', 'is_normal', 'is_subnormal', 'ln', 'log10',
5148 'logb', 'logical_invert', 'next_minus', 'next_plus',
5149 'normalize', 'number_class', 'sqrt', 'to_eng_string']:
5150 func = getattr(x, attr)
5151 self.assertRaises(TypeError, func, context="x")
5152 self.assertRaises(TypeError, func, "x", context=None)
5153
5154 for attr in ['compare', 'compare_signal', 'logical_and',
5155 'logical_or', 'max', 'max_mag', 'min', 'min_mag',
5156 'remainder_near', 'rotate', 'scaleb', 'shift']:
5157 func = getattr(x, attr)
5158 self.assertRaises(TypeError, func, context="x")
5159 self.assertRaises(TypeError, func, "x", context=None)
5160
5161 self.assertRaises(TypeError, x.to_integral, rounding=None, context=[])
5162 self.assertRaises(TypeError, x.to_integral, rounding={}, context=[])
5163 self.assertRaises(TypeError, x.to_integral, [], [])
5164
5165 self.assertRaises(TypeError, x.to_integral_value, rounding=None, context=[])
5166 self.assertRaises(TypeError, x.to_integral_value, rounding={}, context=[])
5167 self.assertRaises(TypeError, x.to_integral_value, [], [])
5168
5169 self.assertRaises(TypeError, x.to_integral_exact, rounding=None, context=[])
5170 self.assertRaises(TypeError, x.to_integral_exact, rounding={}, context=[])
5171 self.assertRaises(TypeError, x.to_integral_exact, [], [])
5172
5173 self.assertRaises(TypeError, x.fma, 1, 2, context="x")
5174 self.assertRaises(TypeError, x.fma, 1, 2, "x", context=None)
5175
5176 self.assertRaises(TypeError, x.quantize, 1, [], context=None)
5177 self.assertRaises(TypeError, x.quantize, 1, [], rounding=None)
5178 self.assertRaises(TypeError, x.quantize, 1, [], [])
5179
5180 c = Context()
5181 self.assertRaises(TypeError, c.power, 1, 2, mod="x")
5182 self.assertRaises(TypeError, c.power, 1, "x", mod=None)
5183 self.assertRaises(TypeError, c.power, "x", 2, mod=None)
5184
Stefan Krah1919b7e2012-03-21 18:25:23 +01005185 @requires_extra_functionality
5186 def test_c_context_templates(self):
5187 self.assertEqual(
5188 C.BasicContext._traps,
5189 C.DecIEEEInvalidOperation|C.DecDivisionByZero|C.DecOverflow|
5190 C.DecUnderflow|C.DecClamped
5191 )
5192 self.assertEqual(
5193 C.DefaultContext._traps,
5194 C.DecIEEEInvalidOperation|C.DecDivisionByZero|C.DecOverflow
5195 )
Mark Dickinson84230a12010-02-18 14:49:50 +00005196
Stefan Krah1919b7e2012-03-21 18:25:23 +01005197 @requires_extra_functionality
5198 def test_c_signal_dict(self):
Mark Dickinson84230a12010-02-18 14:49:50 +00005199
Stefan Krah1919b7e2012-03-21 18:25:23 +01005200 # SignalDict coverage
5201 Context = C.Context
5202 DefaultContext = C.DefaultContext
Mark Dickinson84230a12010-02-18 14:49:50 +00005203
Stefan Krah1919b7e2012-03-21 18:25:23 +01005204 InvalidOperation = C.InvalidOperation
5205 DivisionByZero = C.DivisionByZero
5206 Overflow = C.Overflow
5207 Subnormal = C.Subnormal
5208 Underflow = C.Underflow
5209 Rounded = C.Rounded
5210 Inexact = C.Inexact
5211 Clamped = C.Clamped
Mark Dickinson84230a12010-02-18 14:49:50 +00005212
Stefan Krah1919b7e2012-03-21 18:25:23 +01005213 DecClamped = C.DecClamped
5214 DecInvalidOperation = C.DecInvalidOperation
5215 DecIEEEInvalidOperation = C.DecIEEEInvalidOperation
Mark Dickinson84230a12010-02-18 14:49:50 +00005216
Stefan Krah1919b7e2012-03-21 18:25:23 +01005217 def assertIsExclusivelySet(signal, signal_dict):
5218 for sig in signal_dict:
5219 if sig == signal:
5220 self.assertTrue(signal_dict[sig])
5221 else:
5222 self.assertFalse(signal_dict[sig])
Mark Dickinson84230a12010-02-18 14:49:50 +00005223
Stefan Krah1919b7e2012-03-21 18:25:23 +01005224 c = DefaultContext.copy()
Mark Dickinson84230a12010-02-18 14:49:50 +00005225
Stefan Krah1919b7e2012-03-21 18:25:23 +01005226 # Signal dict methods
5227 self.assertTrue(Overflow in c.traps)
5228 c.clear_traps()
5229 for k in c.traps.keys():
5230 c.traps[k] = True
5231 for v in c.traps.values():
5232 self.assertTrue(v)
5233 c.clear_traps()
5234 for k, v in c.traps.items():
5235 self.assertFalse(v)
Mark Dickinson84230a12010-02-18 14:49:50 +00005236
Stefan Krah1919b7e2012-03-21 18:25:23 +01005237 self.assertFalse(c.flags.get(Overflow))
5238 self.assertIs(c.flags.get("x"), None)
5239 self.assertEqual(c.flags.get("x", "y"), "y")
5240 self.assertRaises(TypeError, c.flags.get, "x", "y", "z")
Mark Dickinson84230a12010-02-18 14:49:50 +00005241
Stefan Krah1919b7e2012-03-21 18:25:23 +01005242 self.assertEqual(len(c.flags), len(c.traps))
5243 s = sys.getsizeof(c.flags)
5244 s = sys.getsizeof(c.traps)
5245 s = c.flags.__repr__()
Mark Dickinson84230a12010-02-18 14:49:50 +00005246
Stefan Krah1919b7e2012-03-21 18:25:23 +01005247 # Set flags/traps.
5248 c.clear_flags()
5249 c._flags = DecClamped
5250 self.assertTrue(c.flags[Clamped])
Mark Dickinson84230a12010-02-18 14:49:50 +00005251
Stefan Krah1919b7e2012-03-21 18:25:23 +01005252 c.clear_traps()
5253 c._traps = DecInvalidOperation
5254 self.assertTrue(c.traps[InvalidOperation])
Mark Dickinson84230a12010-02-18 14:49:50 +00005255
Stefan Krah1919b7e2012-03-21 18:25:23 +01005256 # Set flags/traps from dictionary.
5257 c.clear_flags()
5258 d = c.flags.copy()
5259 d[DivisionByZero] = True
5260 c.flags = d
5261 assertIsExclusivelySet(DivisionByZero, c.flags)
Mark Dickinson84230a12010-02-18 14:49:50 +00005262
Stefan Krah1919b7e2012-03-21 18:25:23 +01005263 c.clear_traps()
5264 d = c.traps.copy()
5265 d[Underflow] = True
5266 c.traps = d
5267 assertIsExclusivelySet(Underflow, c.traps)
Mark Dickinson84230a12010-02-18 14:49:50 +00005268
Stefan Krah1919b7e2012-03-21 18:25:23 +01005269 # Random constructors
5270 IntSignals = {
5271 Clamped: C.DecClamped,
5272 Rounded: C.DecRounded,
5273 Inexact: C.DecInexact,
5274 Subnormal: C.DecSubnormal,
5275 Underflow: C.DecUnderflow,
5276 Overflow: C.DecOverflow,
5277 DivisionByZero: C.DecDivisionByZero,
5278 InvalidOperation: C.DecIEEEInvalidOperation
5279 }
5280 IntCond = [
5281 C.DecDivisionImpossible, C.DecDivisionUndefined, C.DecFpuError,
5282 C.DecInvalidContext, C.DecInvalidOperation, C.DecMallocError,
5283 C.DecConversionSyntax,
5284 ]
Mark Dickinsonb455e582011-05-22 12:53:18 +01005285
Stefan Krah1919b7e2012-03-21 18:25:23 +01005286 lim = len(OrderedSignals[C])
5287 for r in range(lim):
5288 for t in range(lim):
Stefan Krah59a4a932013-01-16 12:58:59 +01005289 for round in RoundingModes:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005290 flags = random.sample(OrderedSignals[C], r)
5291 traps = random.sample(OrderedSignals[C], t)
5292 prec = random.randrange(1, 10000)
5293 emin = random.randrange(-10000, 0)
5294 emax = random.randrange(0, 10000)
5295 clamp = random.randrange(0, 2)
5296 caps = random.randrange(0, 2)
5297 cr = random.randrange(0, 2)
5298 c = Context(prec=prec, rounding=round, Emin=emin, Emax=emax,
5299 capitals=caps, clamp=clamp, flags=list(flags),
5300 traps=list(traps))
Mark Dickinson84230a12010-02-18 14:49:50 +00005301
Stefan Krah1919b7e2012-03-21 18:25:23 +01005302 self.assertEqual(c.prec, prec)
5303 self.assertEqual(c.rounding, round)
5304 self.assertEqual(c.Emin, emin)
5305 self.assertEqual(c.Emax, emax)
5306 self.assertEqual(c.capitals, caps)
5307 self.assertEqual(c.clamp, clamp)
Mark Dickinson84230a12010-02-18 14:49:50 +00005308
Stefan Krah1919b7e2012-03-21 18:25:23 +01005309 f = 0
5310 for x in flags:
5311 f |= IntSignals[x]
5312 self.assertEqual(c._flags, f)
Mark Dickinson84230a12010-02-18 14:49:50 +00005313
Stefan Krah1919b7e2012-03-21 18:25:23 +01005314 f = 0
5315 for x in traps:
5316 f |= IntSignals[x]
5317 self.assertEqual(c._traps, f)
Mark Dickinson84230a12010-02-18 14:49:50 +00005318
Stefan Krah1919b7e2012-03-21 18:25:23 +01005319 for cond in IntCond:
5320 c._flags = cond
5321 self.assertTrue(c._flags&DecIEEEInvalidOperation)
5322 assertIsExclusivelySet(InvalidOperation, c.flags)
Mark Dickinson84230a12010-02-18 14:49:50 +00005323
Stefan Krah1919b7e2012-03-21 18:25:23 +01005324 for cond in IntCond:
5325 c._traps = cond
5326 self.assertTrue(c._traps&DecIEEEInvalidOperation)
5327 assertIsExclusivelySet(InvalidOperation, c.traps)
Mark Dickinson84230a12010-02-18 14:49:50 +00005328
Stefan Krah1919b7e2012-03-21 18:25:23 +01005329 def test_invalid_override(self):
5330 Decimal = C.Decimal
Mark Dickinson84230a12010-02-18 14:49:50 +00005331
Stefan Krah1919b7e2012-03-21 18:25:23 +01005332 try:
5333 from locale import CHAR_MAX
5334 except ImportError:
Zachary Ware9fe6d862013-12-08 00:20:35 -06005335 self.skipTest('locale.CHAR_MAX not available')
Mark Dickinson84230a12010-02-18 14:49:50 +00005336
Stefan Krah1919b7e2012-03-21 18:25:23 +01005337 def make_grouping(lst):
5338 return ''.join([chr(x) for x in lst])
Mark Dickinson84230a12010-02-18 14:49:50 +00005339
Stefan Krah1919b7e2012-03-21 18:25:23 +01005340 def get_fmt(x, override=None, fmt='n'):
5341 return Decimal(x).__format__(fmt, override)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005342
Stefan Krah1919b7e2012-03-21 18:25:23 +01005343 invalid_grouping = {
5344 'decimal_point' : ',',
5345 'grouping' : make_grouping([255, 255, 0]),
5346 'thousands_sep' : ','
5347 }
5348 invalid_dot = {
5349 'decimal_point' : 'xxxxx',
5350 'grouping' : make_grouping([3, 3, 0]),
5351 'thousands_sep' : ','
5352 }
5353 invalid_sep = {
5354 'decimal_point' : '.',
5355 'grouping' : make_grouping([3, 3, 0]),
5356 'thousands_sep' : 'yyyyy'
5357 }
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005358
Stefan Krah1919b7e2012-03-21 18:25:23 +01005359 if CHAR_MAX == 127: # negative grouping in override
5360 self.assertRaises(ValueError, get_fmt, 12345,
5361 invalid_grouping, 'g')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005362
Stefan Krah1919b7e2012-03-21 18:25:23 +01005363 self.assertRaises(ValueError, get_fmt, 12345, invalid_dot, 'g')
5364 self.assertRaises(ValueError, get_fmt, 12345, invalid_sep, 'g')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005365
Stefan Krah0774e9b2012-04-05 15:21:58 +02005366 def test_exact_conversion(self):
5367 Decimal = C.Decimal
5368 localcontext = C.localcontext
5369 InvalidOperation = C.InvalidOperation
5370
5371 with localcontext() as c:
5372
5373 c.traps[InvalidOperation] = True
5374
5375 # Clamped
5376 x = "0e%d" % sys.maxsize
5377 self.assertRaises(InvalidOperation, Decimal, x)
5378
5379 x = "0e%d" % (-sys.maxsize-1)
5380 self.assertRaises(InvalidOperation, Decimal, x)
5381
5382 # Overflow
5383 x = "1e%d" % sys.maxsize
5384 self.assertRaises(InvalidOperation, Decimal, x)
5385
5386 # Underflow
5387 x = "1e%d" % (-sys.maxsize-1)
5388 self.assertRaises(InvalidOperation, Decimal, x)
5389
Stefan Krahff3eca02012-04-05 15:46:19 +02005390 def test_from_tuple(self):
5391 Decimal = C.Decimal
5392 localcontext = C.localcontext
5393 InvalidOperation = C.InvalidOperation
5394 Overflow = C.Overflow
5395 Underflow = C.Underflow
5396
5397 with localcontext() as c:
5398
5399 c.traps[InvalidOperation] = True
5400 c.traps[Overflow] = True
5401 c.traps[Underflow] = True
5402
5403 # SSIZE_MAX
5404 x = (1, (), sys.maxsize)
5405 self.assertEqual(str(c.create_decimal(x)), '-0E+999999')
5406 self.assertRaises(InvalidOperation, Decimal, x)
5407
5408 x = (1, (0, 1, 2), sys.maxsize)
5409 self.assertRaises(Overflow, c.create_decimal, x)
5410 self.assertRaises(InvalidOperation, Decimal, x)
5411
5412 # SSIZE_MIN
5413 x = (1, (), -sys.maxsize-1)
5414 self.assertEqual(str(c.create_decimal(x)), '-0E-1000026')
5415 self.assertRaises(InvalidOperation, Decimal, x)
5416
5417 x = (1, (0, 1, 2), -sys.maxsize-1)
5418 self.assertRaises(Underflow, c.create_decimal, x)
5419 self.assertRaises(InvalidOperation, Decimal, x)
5420
5421 # OverflowError
5422 x = (1, (), sys.maxsize+1)
5423 self.assertRaises(OverflowError, c.create_decimal, x)
5424 self.assertRaises(OverflowError, Decimal, x)
5425
5426 x = (1, (), -sys.maxsize-2)
5427 self.assertRaises(OverflowError, c.create_decimal, x)
5428 self.assertRaises(OverflowError, Decimal, x)
5429
5430 # Specials
5431 x = (1, (), "N")
5432 self.assertEqual(str(Decimal(x)), '-sNaN')
5433 x = (1, (0,), "N")
5434 self.assertEqual(str(Decimal(x)), '-sNaN')
5435 x = (1, (0, 1), "N")
5436 self.assertEqual(str(Decimal(x)), '-sNaN1')
5437
Stefan Krah891ca9e2013-05-29 19:14:17 +02005438 def test_sizeof(self):
5439 Decimal = C.Decimal
5440 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
5441
5442 self.assertGreater(Decimal(0).__sizeof__(), 0)
5443 if HAVE_CONFIG_64:
5444 x = Decimal(10**(19*24)).__sizeof__()
5445 y = Decimal(10**(19*25)).__sizeof__()
5446 self.assertEqual(y, x+8)
5447 else:
5448 x = Decimal(10**(9*24)).__sizeof__()
5449 y = Decimal(10**(9*25)).__sizeof__()
5450 self.assertEqual(y, x+4)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005451
Stefan Krah8c126f12016-07-17 14:01:42 +02005452 def test_internal_use_of_overridden_methods(self):
5453 Decimal = C.Decimal
5454
5455 # Unsound subtyping
5456 class X(float):
5457 def as_integer_ratio(self):
5458 return 1
5459 def __abs__(self):
5460 return self
5461
5462 class Y(float):
5463 def __abs__(self):
5464 return [1]*200
5465
5466 class I(int):
5467 def bit_length(self):
5468 return [1]*200
5469
5470 class Z(float):
5471 def as_integer_ratio(self):
5472 return (I(1), I(1))
5473 def __abs__(self):
5474 return self
5475
5476 for cls in X, Y, Z:
5477 self.assertEqual(Decimal.from_float(cls(101.1)),
5478 Decimal.from_float(101.1))
5479
Stefan Krah6b794b82014-05-01 17:42:33 +02005480@requires_docstrings
5481@unittest.skipUnless(C, "test requires C version")
Stefan Krah5de1f822014-05-01 15:53:42 +02005482class SignatureTest(unittest.TestCase):
5483 """Function signatures"""
5484
5485 def test_inspect_module(self):
5486 for attr in dir(P):
5487 if attr.startswith('_'):
5488 continue
5489 p_func = getattr(P, attr)
5490 c_func = getattr(C, attr)
5491 if (attr == 'Decimal' or attr == 'Context' or
5492 inspect.isfunction(p_func)):
5493 p_sig = inspect.signature(p_func)
5494 c_sig = inspect.signature(c_func)
5495
5496 # parameter names:
5497 c_names = list(c_sig.parameters.keys())
5498 p_names = [x for x in p_sig.parameters.keys() if not
5499 x.startswith('_')]
5500
5501 self.assertEqual(c_names, p_names,
5502 msg="parameter name mismatch in %s" % p_func)
5503
5504 c_kind = [x.kind for x in c_sig.parameters.values()]
5505 p_kind = [x[1].kind for x in p_sig.parameters.items() if not
5506 x[0].startswith('_')]
5507
5508 # parameters:
5509 if attr != 'setcontext':
5510 self.assertEqual(c_kind, p_kind,
5511 msg="parameter kind mismatch in %s" % p_func)
5512
5513 def test_inspect_types(self):
5514
5515 POS = inspect._ParameterKind.POSITIONAL_ONLY
5516 POS_KWD = inspect._ParameterKind.POSITIONAL_OR_KEYWORD
5517
5518 # Type heuristic (type annotations would help!):
5519 pdict = {C: {'other': C.Decimal(1),
5520 'third': C.Decimal(1),
5521 'x': C.Decimal(1),
5522 'y': C.Decimal(1),
5523 'z': C.Decimal(1),
5524 'a': C.Decimal(1),
5525 'b': C.Decimal(1),
5526 'c': C.Decimal(1),
5527 'exp': C.Decimal(1),
5528 'modulo': C.Decimal(1),
5529 'num': "1",
5530 'f': 1.0,
5531 'rounding': C.ROUND_HALF_UP,
5532 'context': C.getcontext()},
5533 P: {'other': P.Decimal(1),
5534 'third': P.Decimal(1),
5535 'a': P.Decimal(1),
5536 'b': P.Decimal(1),
5537 'c': P.Decimal(1),
5538 'exp': P.Decimal(1),
5539 'modulo': P.Decimal(1),
5540 'num': "1",
5541 'f': 1.0,
5542 'rounding': P.ROUND_HALF_UP,
5543 'context': P.getcontext()}}
5544
5545 def mkargs(module, sig):
5546 args = []
5547 kwargs = {}
5548 for name, param in sig.parameters.items():
5549 if name == 'self': continue
5550 if param.kind == POS:
5551 args.append(pdict[module][name])
5552 elif param.kind == POS_KWD:
5553 kwargs[name] = pdict[module][name]
5554 else:
5555 raise TestFailed("unexpected parameter kind")
5556 return args, kwargs
5557
5558 def tr(s):
5559 """The C Context docstrings use 'x' in order to prevent confusion
5560 with the article 'a' in the descriptions."""
5561 if s == 'x': return 'a'
5562 if s == 'y': return 'b'
5563 if s == 'z': return 'c'
5564 return s
5565
5566 def doit(ty):
5567 p_type = getattr(P, ty)
5568 c_type = getattr(C, ty)
5569 for attr in dir(p_type):
5570 if attr.startswith('_'):
5571 continue
5572 p_func = getattr(p_type, attr)
5573 c_func = getattr(c_type, attr)
5574 if inspect.isfunction(p_func):
5575 p_sig = inspect.signature(p_func)
5576 c_sig = inspect.signature(c_func)
5577
5578 # parameter names:
5579 p_names = list(p_sig.parameters.keys())
5580 c_names = [tr(x) for x in c_sig.parameters.keys()]
5581
5582 self.assertEqual(c_names, p_names,
5583 msg="parameter name mismatch in %s" % p_func)
5584
5585 p_kind = [x.kind for x in p_sig.parameters.values()]
5586 c_kind = [x.kind for x in c_sig.parameters.values()]
5587
5588 # 'self' parameter:
5589 self.assertIs(p_kind[0], POS_KWD)
5590 self.assertIs(c_kind[0], POS)
5591
5592 # remaining parameters:
5593 if ty == 'Decimal':
5594 self.assertEqual(c_kind[1:], p_kind[1:],
5595 msg="parameter kind mismatch in %s" % p_func)
5596 else: # Context methods are positional only in the C version.
5597 self.assertEqual(len(c_kind), len(p_kind),
5598 msg="parameter kind mismatch in %s" % p_func)
5599
5600 # Run the function:
5601 args, kwds = mkargs(C, c_sig)
5602 try:
5603 getattr(c_type(9), attr)(*args, **kwds)
5604 except Exception as err:
5605 raise TestFailed("invalid signature for %s: %s %s" % (c_func, args, kwds))
5606
5607 args, kwds = mkargs(P, p_sig)
5608 try:
5609 getattr(p_type(9), attr)(*args, **kwds)
5610 except Exception as err:
5611 raise TestFailed("invalid signature for %s: %s %s" % (p_func, args, kwds))
5612
5613 doit('Decimal')
5614 doit('Context')
5615
5616
Stefan Krah1919b7e2012-03-21 18:25:23 +01005617all_tests = [
5618 CExplicitConstructionTest, PyExplicitConstructionTest,
5619 CImplicitConstructionTest, PyImplicitConstructionTest,
5620 CFormatTest, PyFormatTest,
5621 CArithmeticOperatorsTest, PyArithmeticOperatorsTest,
5622 CThreadingTest, PyThreadingTest,
5623 CUsabilityTest, PyUsabilityTest,
5624 CPythonAPItests, PyPythonAPItests,
5625 CContextAPItests, PyContextAPItests,
5626 CContextWithStatement, PyContextWithStatement,
5627 CContextFlags, PyContextFlags,
5628 CSpecialContexts, PySpecialContexts,
5629 CContextInputValidation, PyContextInputValidation,
5630 CContextSubclassing, PyContextSubclassing,
5631 CCoverage, PyCoverage,
5632 CFunctionality, PyFunctionality,
5633 CWhitebox, PyWhitebox,
5634 CIBMTestCases, PyIBMTestCases,
5635]
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005636
Stefan Krah1919b7e2012-03-21 18:25:23 +01005637# Delete C tests if _decimal.so is not present.
5638if not C:
5639 all_tests = all_tests[1::2]
5640else:
5641 all_tests.insert(0, CheckAttributes)
Stefan Krah5de1f822014-05-01 15:53:42 +02005642 all_tests.insert(1, SignatureTest)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005643
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005644
Zachary Ware66f29282014-06-02 16:01:29 -05005645def test_main(arith=None, verbose=None, todo_tests=None, debug=None):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005646 """ Execute the tests.
5647
Raymond Hettingered20ad82004-09-04 20:09:13 +00005648 Runs all arithmetic tests if arith is True or if the "decimal" resource
5649 is enabled in regrtest.py
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005650 """
Raymond Hettingered20ad82004-09-04 20:09:13 +00005651
Stefan Krah1919b7e2012-03-21 18:25:23 +01005652 init(C)
5653 init(P)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005654 global TEST_ALL, DEBUG
Zachary Ware66f29282014-06-02 16:01:29 -05005655 TEST_ALL = arith if arith is not None else is_resource_enabled('decimal')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005656 DEBUG = debug
Raymond Hettingered20ad82004-09-04 20:09:13 +00005657
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005658 if todo_tests is None:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005659 test_classes = all_tests
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005660 else:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005661 test_classes = [CIBMTestCases, PyIBMTestCases]
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005662
5663 # Dynamically build custom test definition for each file in the test
5664 # directory and add the definitions to the DecimalTest class. This
5665 # procedure insures that new files do not get skipped.
5666 for filename in os.listdir(directory):
5667 if '.decTest' not in filename or filename.startswith("."):
5668 continue
5669 head, tail = filename.split('.')
5670 if todo_tests is not None and head not in todo_tests:
5671 continue
5672 tester = lambda self, f=filename: self.eval_file(directory + f)
Stefan Krah1919b7e2012-03-21 18:25:23 +01005673 setattr(CIBMTestCases, 'test_' + head, tester)
5674 setattr(PyIBMTestCases, 'test_' + head, tester)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005675 del filename, head, tail, tester
5676
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005677
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005678 try:
5679 run_unittest(*test_classes)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005680 if todo_tests is None:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005681 from doctest import IGNORE_EXCEPTION_DETAIL
5682 savedecimal = sys.modules['decimal']
5683 if C:
5684 sys.modules['decimal'] = C
5685 run_doctest(C, verbose, optionflags=IGNORE_EXCEPTION_DETAIL)
5686 sys.modules['decimal'] = P
5687 run_doctest(P, verbose)
5688 sys.modules['decimal'] = savedecimal
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005689 finally:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005690 if C: C.setcontext(ORIGINAL_CONTEXT[C])
5691 P.setcontext(ORIGINAL_CONTEXT[P])
5692 if not C:
5693 warnings.warn('C tests skipped: no module named _decimal.',
5694 UserWarning)
5695 if not orig_sys_decimal is sys.modules['decimal']:
5696 raise TestFailed("Internal error: unbalanced number of changes to "
5697 "sys.modules['decimal'].")
5698
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005699
5700if __name__ == '__main__':
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005701 import optparse
5702 p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]")
5703 p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test')
5704 p.add_option('--skip', '-s', action='store_true', help='skip over 90% of the arithmetic tests')
5705 (opt, args) = p.parse_args()
5706
5707 if opt.skip:
5708 test_main(arith=False, verbose=True)
5709 elif args:
5710 test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005711 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005712 test_main(arith=True, verbose=True)