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