blob: ac8a7bebc11d3d87d071d5f8bb27d4018289d202 [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,
36 requires_IEEE_754)
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
Raymond Hettinger7e71fa52004-12-18 19:07:19 +000042try:
43 import threading
44except ImportError:
45 threading = None
Raymond Hettinger7c85fa42004-07-01 11:01:35 +000046
Raymond Hettingerfed52962004-07-14 15:41:57 +000047
Stefan Krah1919b7e2012-03-21 18:25:23 +010048C = import_fresh_module('decimal', fresh=['_decimal'])
49P = import_fresh_module('decimal', blocked=['_decimal'])
50orig_sys_decimal = sys.modules['decimal']
51
52# fractions module must import the correct decimal module.
53cfractions = import_fresh_module('fractions', fresh=['fractions'])
54sys.modules['decimal'] = P
55pfractions = import_fresh_module('fractions', fresh=['fractions'])
56sys.modules['decimal'] = C
57fractions = {C:cfractions, P:pfractions}
58sys.modules['decimal'] = orig_sys_decimal
59
60
61# Useful Test Constant
62Signals = {
63 C: tuple(C.getcontext().flags.keys()) if C else None,
64 P: tuple(P.getcontext().flags.keys())
65}
Mark Dickinsonc69160e2010-05-04 14:35:33 +000066# Signals ordered with respect to precedence: when an operation
67# produces multiple signals, signals occurring later in the list
68# should be handled before those occurring earlier in the list.
Stefan Krah1919b7e2012-03-21 18:25:23 +010069OrderedSignals = {
70 C: [C.Clamped, C.Rounded, C.Inexact, C.Subnormal, C.Underflow,
71 C.Overflow, C.DivisionByZero, C.InvalidOperation,
72 C.FloatOperation] if C else None,
73 P: [P.Clamped, P.Rounded, P.Inexact, P.Subnormal, P.Underflow,
74 P.Overflow, P.DivisionByZero, P.InvalidOperation,
75 P.FloatOperation]
76}
77def assert_signals(cls, context, attr, expected):
78 d = getattr(context, attr)
79 cls.assertTrue(all(d[s] if s in expected else not d[s] for s in d))
80
Stefan Krah59a4a932013-01-16 12:58:59 +010081ROUND_UP = P.ROUND_UP
82ROUND_DOWN = P.ROUND_DOWN
83ROUND_CEILING = P.ROUND_CEILING
84ROUND_FLOOR = P.ROUND_FLOOR
85ROUND_HALF_UP = P.ROUND_HALF_UP
86ROUND_HALF_DOWN = P.ROUND_HALF_DOWN
87ROUND_HALF_EVEN = P.ROUND_HALF_EVEN
88ROUND_05UP = P.ROUND_05UP
89
90RoundingModes = [
91 ROUND_UP, ROUND_DOWN, ROUND_CEILING, ROUND_FLOOR,
92 ROUND_HALF_UP, ROUND_HALF_DOWN, ROUND_HALF_EVEN,
93 ROUND_05UP
94]
Mark Dickinsonc69160e2010-05-04 14:35:33 +000095
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000096# Tests are built around these assumed context defaults.
97# test_main() restores the original context.
Stefan Krah1919b7e2012-03-21 18:25:23 +010098ORIGINAL_CONTEXT = {
99 C: C.getcontext().copy() if C else None,
100 P: P.getcontext().copy()
101}
102def init(m):
103 if not m: return
104 DefaultTestContext = m.Context(
Stefan Krah59a4a932013-01-16 12:58:59 +0100105 prec=9, rounding=ROUND_HALF_EVEN, traps=dict.fromkeys(Signals[m], 0)
Stefan Krah1919b7e2012-03-21 18:25:23 +0100106 )
107 m.setcontext(DefaultTestContext)
Raymond Hettinger6ea48452004-07-03 12:26:21 +0000108
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000109TESTDATADIR = 'decimaltestdata'
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +0000110if __name__ == '__main__':
111 file = sys.argv[0]
112else:
113 file = __file__
114testdir = os.path.dirname(file) or os.curdir
Raymond Hettinger267b8682005-03-27 10:47:39 +0000115directory = testdir + os.sep + TESTDATADIR + os.sep
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000116
Raymond Hettinger267b8682005-03-27 10:47:39 +0000117skip_expected = not os.path.isdir(directory)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000118
119# Make sure it actually raises errors when not expected and caught in flags
120# Slower, since it runs some things several times.
121EXTENDEDERRORTEST = False
122
Stefan Krah1919b7e2012-03-21 18:25:23 +0100123# Test extra functionality in the C version (-DEXTRA_FUNCTIONALITY).
124EXTRA_FUNCTIONALITY = True if hasattr(C, 'DecClamped') else False
125requires_extra_functionality = unittest.skipUnless(
126 EXTRA_FUNCTIONALITY, "test requires build with -DEXTRA_FUNCTIONALITY")
127skip_if_extra_functionality = unittest.skipIf(
128 EXTRA_FUNCTIONALITY, "test requires regular build")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000129
130
Stefan Krah1919b7e2012-03-21 18:25:23 +0100131class IBMTestCases(unittest.TestCase):
132 """Class which tests the Decimal class against the IBM test cases."""
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000133
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000134 def setUp(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100135 self.context = self.decimal.Context()
136 self.readcontext = self.decimal.Context()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000137 self.ignore_list = ['#']
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000138
Stefan Krah1919b7e2012-03-21 18:25:23 +0100139 # List of individual .decTest test ids that correspond to tests that
140 # we're skipping for one reason or another.
141 self.skipped_test_ids = set([
142 # Skip implementation-specific scaleb tests.
143 'scbx164',
144 'scbx165',
145
146 # For some operations (currently exp, ln, log10, power), the decNumber
147 # reference implementation imposes additional restrictions on the context
148 # and operands. These restrictions are not part of the specification;
149 # however, the effect of these restrictions does show up in some of the
150 # testcases. We skip testcases that violate these restrictions, since
151 # Decimal behaves differently from decNumber for these testcases so these
152 # testcases would otherwise fail.
153 'expx901',
154 'expx902',
155 'expx903',
156 'expx905',
157 'lnx901',
158 'lnx902',
159 'lnx903',
160 'lnx905',
161 'logx901',
162 'logx902',
163 'logx903',
164 'logx905',
165 'powx1183',
166 'powx1184',
167 'powx4001',
168 'powx4002',
169 'powx4003',
170 'powx4005',
171 'powx4008',
172 'powx4010',
173 'powx4012',
174 'powx4014',
175 ])
176
177 if self.decimal == C:
178 # status has additional Subnormal, Underflow
179 self.skipped_test_ids.add('pwsx803')
180 self.skipped_test_ids.add('pwsx805')
181 # Correct rounding (skipped for decNumber, too)
182 self.skipped_test_ids.add('powx4302')
183 self.skipped_test_ids.add('powx4303')
184 self.skipped_test_ids.add('powx4342')
185 self.skipped_test_ids.add('powx4343')
186 # http://bugs.python.org/issue7049
187 self.skipped_test_ids.add('pwmx325')
188 self.skipped_test_ids.add('pwmx326')
189
190 # Map test directives to setter functions.
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000191 self.ChangeDict = {'precision' : self.change_precision,
Stefan Krah1919b7e2012-03-21 18:25:23 +0100192 'rounding' : self.change_rounding_method,
193 'maxexponent' : self.change_max_exponent,
194 'minexponent' : self.change_min_exponent,
195 'clamp' : self.change_clamp}
196
197 # Name adapter to be able to change the Decimal and Context
198 # interface without changing the test files from Cowlishaw.
199 self.NameAdapter = {'and':'logical_and',
200 'apply':'_apply',
201 'class':'number_class',
202 'comparesig':'compare_signal',
203 'comparetotal':'compare_total',
204 'comparetotmag':'compare_total_mag',
205 'copy':'copy_decimal',
206 'copyabs':'copy_abs',
207 'copynegate':'copy_negate',
208 'copysign':'copy_sign',
209 'divideint':'divide_int',
210 'invert':'logical_invert',
211 'iscanonical':'is_canonical',
212 'isfinite':'is_finite',
213 'isinfinite':'is_infinite',
214 'isnan':'is_nan',
215 'isnormal':'is_normal',
216 'isqnan':'is_qnan',
217 'issigned':'is_signed',
218 'issnan':'is_snan',
219 'issubnormal':'is_subnormal',
220 'iszero':'is_zero',
221 'maxmag':'max_mag',
222 'minmag':'min_mag',
223 'nextminus':'next_minus',
224 'nextplus':'next_plus',
225 'nexttoward':'next_toward',
226 'or':'logical_or',
227 'reduce':'normalize',
228 'remaindernear':'remainder_near',
229 'samequantum':'same_quantum',
230 'squareroot':'sqrt',
231 'toeng':'to_eng_string',
232 'tointegral':'to_integral_value',
233 'tointegralx':'to_integral_exact',
234 'tosci':'to_sci_string',
235 'xor':'logical_xor'}
236
237 # Map test-case names to roundings.
Stefan Krah59a4a932013-01-16 12:58:59 +0100238 self.RoundingDict = {'ceiling' : ROUND_CEILING,
239 'down' : ROUND_DOWN,
240 'floor' : ROUND_FLOOR,
241 'half_down' : ROUND_HALF_DOWN,
242 'half_even' : ROUND_HALF_EVEN,
243 'half_up' : ROUND_HALF_UP,
244 'up' : ROUND_UP,
245 '05up' : ROUND_05UP}
Stefan Krah1919b7e2012-03-21 18:25:23 +0100246
247 # Map the test cases' error names to the actual errors.
248 self.ErrorNames = {'clamped' : self.decimal.Clamped,
249 'conversion_syntax' : self.decimal.InvalidOperation,
250 'division_by_zero' : self.decimal.DivisionByZero,
251 'division_impossible' : self.decimal.InvalidOperation,
252 'division_undefined' : self.decimal.InvalidOperation,
253 'inexact' : self.decimal.Inexact,
254 'invalid_context' : self.decimal.InvalidOperation,
255 'invalid_operation' : self.decimal.InvalidOperation,
256 'overflow' : self.decimal.Overflow,
257 'rounded' : self.decimal.Rounded,
258 'subnormal' : self.decimal.Subnormal,
259 'underflow' : self.decimal.Underflow}
260
261 # The following functions return True/False rather than a
262 # Decimal instance.
263 self.LogicalFunctions = ('is_canonical',
264 'is_finite',
265 'is_infinite',
266 'is_nan',
267 'is_normal',
268 'is_qnan',
269 'is_signed',
270 'is_snan',
271 'is_subnormal',
272 'is_zero',
273 'same_quantum')
274
275 def read_unlimited(self, v, context):
276 """Work around the limitations of the 32-bit _decimal version. The
277 guaranteed maximum values for prec, Emax etc. are 425000000,
278 but higher values usually work, except for rare corner cases.
279 In particular, all of the IBM tests pass with maximum values
280 of 1070000000."""
281 if self.decimal == C and self.decimal.MAX_EMAX == 425000000:
282 self.readcontext._unsafe_setprec(1070000000)
283 self.readcontext._unsafe_setemax(1070000000)
284 self.readcontext._unsafe_setemin(-1070000000)
285 return self.readcontext.create_decimal(v)
286 else:
287 return self.decimal.Decimal(v, context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000288
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000289 def eval_file(self, file):
290 global skip_expected
291 if skip_expected:
Benjamin Petersone549ead2009-03-28 21:42:05 +0000292 raise unittest.SkipTest
Antoine Pitrou92f60ed2010-10-14 22:11:44 +0000293 with open(file) as f:
294 for line in f:
295 line = line.replace('\r\n', '').replace('\n', '')
296 #print line
297 try:
298 t = self.eval_line(line)
Stefan Krah1919b7e2012-03-21 18:25:23 +0100299 except self.decimal.DecimalException as exception:
Ezio Melotti13925002011-03-16 11:05:33 +0200300 #Exception raised where there shouldn't have been one.
Antoine Pitrou92f60ed2010-10-14 22:11:44 +0000301 self.fail('Exception "'+exception.__class__.__name__ + '" raised on line '+line)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000302
303 return
304
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 return
464
465 def getexceptions(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100466 return [e for e in Signals[self.decimal] if self.context.flags[e]]
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000467
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000468 def change_precision(self, prec):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100469 if self.decimal == C and self.decimal.MAX_PREC == 425000000:
470 self.context._unsafe_setprec(prec)
471 else:
472 self.context.prec = prec
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000473 def change_rounding_method(self, rounding):
474 self.context.rounding = rounding
475 def change_min_exponent(self, exp):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100476 if self.decimal == C and self.decimal.MAX_PREC == 425000000:
477 self.context._unsafe_setemin(exp)
478 else:
479 self.context.Emin = exp
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000480 def change_max_exponent(self, exp):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100481 if self.decimal == C and self.decimal.MAX_PREC == 425000000:
482 self.context._unsafe_setemax(exp)
483 else:
484 self.context.Emax = exp
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000485 def change_clamp(self, clamp):
Mark Dickinsonb1d8e322010-05-22 18:35:36 +0000486 self.context.clamp = clamp
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000487
Stefan Krah1919b7e2012-03-21 18:25:23 +0100488class CIBMTestCases(IBMTestCases):
489 decimal = C
490class PyIBMTestCases(IBMTestCases):
491 decimal = P
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000492
493# The following classes test the behaviour of Decimal according to PEP 327
494
Stefan Krah1919b7e2012-03-21 18:25:23 +0100495class ExplicitConstructionTest(unittest.TestCase):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000496 '''Unit tests for Explicit Construction cases of Decimal.'''
497
498 def test_explicit_empty(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100499 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000500 self.assertEqual(Decimal(), Decimal("0"))
501
502 def test_explicit_from_None(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100503 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000504 self.assertRaises(TypeError, Decimal, None)
505
506 def test_explicit_from_int(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100507 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000508
509 #positive
510 d = Decimal(45)
511 self.assertEqual(str(d), '45')
512
513 #very large positive
514 d = Decimal(500000123)
515 self.assertEqual(str(d), '500000123')
516
517 #negative
518 d = Decimal(-45)
519 self.assertEqual(str(d), '-45')
520
521 #zero
522 d = Decimal(0)
523 self.assertEqual(str(d), '0')
524
Stefan Krah1919b7e2012-03-21 18:25:23 +0100525 # single word longs
526 for n in range(0, 32):
527 for sign in (-1, 1):
528 for x in range(-5, 5):
529 i = sign * (2**n + x)
530 d = Decimal(i)
531 self.assertEqual(str(d), str(i))
532
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000533 def test_explicit_from_string(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100534 Decimal = self.decimal.Decimal
535 InvalidOperation = self.decimal.InvalidOperation
536 localcontext = self.decimal.localcontext
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000537
538 #empty
539 self.assertEqual(str(Decimal('')), 'NaN')
540
541 #int
542 self.assertEqual(str(Decimal('45')), '45')
543
544 #float
545 self.assertEqual(str(Decimal('45.34')), '45.34')
546
547 #engineer notation
548 self.assertEqual(str(Decimal('45e2')), '4.5E+3')
549
550 #just not a number
551 self.assertEqual(str(Decimal('ugly')), 'NaN')
552
Christian Heimesa62da1d2008-01-12 19:39:10 +0000553 #leading and trailing whitespace permitted
554 self.assertEqual(str(Decimal('1.3E4 \n')), '1.3E+4')
555 self.assertEqual(str(Decimal(' -7.89')), '-7.89')
Stefan Krah1919b7e2012-03-21 18:25:23 +0100556 self.assertEqual(str(Decimal(" 3.45679 ")), '3.45679')
557
558 # unicode whitespace
559 for lead in ["", ' ', '\u00a0', '\u205f']:
560 for trail in ["", ' ', '\u00a0', '\u205f']:
561 self.assertEqual(str(Decimal(lead + '9.311E+28' + trail)),
562 '9.311E+28')
563
564 with localcontext() as c:
565 c.traps[InvalidOperation] = True
566 # Invalid string
567 self.assertRaises(InvalidOperation, Decimal, "xyz")
568 # Two arguments max
569 self.assertRaises(TypeError, Decimal, "1234", "x", "y")
570
571 # space within the numeric part
572 self.assertRaises(InvalidOperation, Decimal, "1\u00a02\u00a03")
573 self.assertRaises(InvalidOperation, Decimal, "\u00a01\u00a02\u00a0")
574
575 # unicode whitespace
576 self.assertRaises(InvalidOperation, Decimal, "\u00a0")
577 self.assertRaises(InvalidOperation, Decimal, "\u00a0\u00a0")
578
579 # embedded NUL
580 self.assertRaises(InvalidOperation, Decimal, "12\u00003")
581
Stefan Krah6e467042012-11-10 23:09:04 +0100582 @cpython_only
583 def test_from_legacy_strings(self):
584 import _testcapi
585 Decimal = self.decimal.Decimal
586 context = self.decimal.Context()
587
588 s = _testcapi.unicode_legacy_string('9.999999')
589 self.assertEqual(str(Decimal(s)), '9.999999')
590 self.assertEqual(str(context.create_decimal(s)), '9.999999')
Christian Heimesa62da1d2008-01-12 19:39:10 +0000591
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000592 def test_explicit_from_tuples(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100593 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000594
595 #zero
596 d = Decimal( (0, (0,), 0) )
597 self.assertEqual(str(d), '0')
598
599 #int
600 d = Decimal( (1, (4, 5), 0) )
601 self.assertEqual(str(d), '-45')
602
603 #float
604 d = Decimal( (0, (4, 5, 3, 4), -2) )
605 self.assertEqual(str(d), '45.34')
606
607 #weird
608 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
609 self.assertEqual(str(d), '-4.34913534E-17')
610
Stefan Krah1919b7e2012-03-21 18:25:23 +0100611 #inf
612 d = Decimal( (0, (), "F") )
613 self.assertEqual(str(d), 'Infinity')
614
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000615 #wrong number of items
616 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1)) )
617
618 #bad sign
619 self.assertRaises(ValueError, Decimal, (8, (4, 3, 4, 9, 1), 2) )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000620 self.assertRaises(ValueError, Decimal, (0., (4, 3, 4, 9, 1), 2) )
621 self.assertRaises(ValueError, Decimal, (Decimal(1), (4, 3, 4, 9, 1), 2))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000622
623 #bad exp
624 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 'wrong!') )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000625 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 0.) )
626 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), '1') )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000627
628 #bad coefficients
Stefan Krah1919b7e2012-03-21 18:25:23 +0100629 self.assertRaises(ValueError, Decimal, (1, "xyz", 2) )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000630 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, None, 1), 2) )
631 self.assertRaises(ValueError, Decimal, (1, (4, -3, 4, 9, 1), 2) )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000632 self.assertRaises(ValueError, Decimal, (1, (4, 10, 4, 9, 1), 2) )
Guido van Rossum0d3fb8a2007-11-26 23:23:18 +0000633 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 'a', 1), 2) )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000634
Stefan Krah1919b7e2012-03-21 18:25:23 +0100635 def test_explicit_from_list(self):
636 Decimal = self.decimal.Decimal
637
638 d = Decimal([0, [0], 0])
639 self.assertEqual(str(d), '0')
640
641 d = Decimal([1, [4, 3, 4, 9, 1, 3, 5, 3, 4], -25])
642 self.assertEqual(str(d), '-4.34913534E-17')
643
644 d = Decimal([1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25])
645 self.assertEqual(str(d), '-4.34913534E-17')
646
647 d = Decimal((1, [4, 3, 4, 9, 1, 3, 5, 3, 4], -25))
648 self.assertEqual(str(d), '-4.34913534E-17')
649
Antoine Pitrou503ab332010-03-30 18:56:19 +0000650 def test_explicit_from_bool(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100651 Decimal = self.decimal.Decimal
652
Antoine Pitrou503ab332010-03-30 18:56:19 +0000653 self.assertIs(bool(Decimal(0)), False)
654 self.assertIs(bool(Decimal(1)), True)
655 self.assertEqual(Decimal(False), Decimal(0))
656 self.assertEqual(Decimal(True), Decimal(1))
657
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000658 def test_explicit_from_Decimal(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100659 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000660
661 #positive
662 d = Decimal(45)
663 e = Decimal(d)
664 self.assertEqual(str(e), '45')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000665
666 #very large positive
667 d = Decimal(500000123)
668 e = Decimal(d)
669 self.assertEqual(str(e), '500000123')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000670
671 #negative
672 d = Decimal(-45)
673 e = Decimal(d)
674 self.assertEqual(str(e), '-45')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000675
676 #zero
677 d = Decimal(0)
678 e = Decimal(d)
679 self.assertEqual(str(e), '0')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000680
Raymond Hettinger96798592010-04-02 16:58:27 +0000681 @requires_IEEE_754
682 def test_explicit_from_float(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100683
684 Decimal = self.decimal.Decimal
685
Raymond Hettinger96798592010-04-02 16:58:27 +0000686 r = Decimal(0.1)
687 self.assertEqual(type(r), Decimal)
688 self.assertEqual(str(r),
689 '0.1000000000000000055511151231257827021181583404541015625')
690 self.assertTrue(Decimal(float('nan')).is_qnan())
691 self.assertTrue(Decimal(float('inf')).is_infinite())
692 self.assertTrue(Decimal(float('-inf')).is_infinite())
693 self.assertEqual(str(Decimal(float('nan'))),
694 str(Decimal('NaN')))
695 self.assertEqual(str(Decimal(float('inf'))),
696 str(Decimal('Infinity')))
697 self.assertEqual(str(Decimal(float('-inf'))),
698 str(Decimal('-Infinity')))
699 self.assertEqual(str(Decimal(float('-0.0'))),
700 str(Decimal('-0')))
701 for i in range(200):
702 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
703 self.assertEqual(x, float(Decimal(x))) # roundtrip
704
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000705 def test_explicit_context_create_decimal(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100706 Decimal = self.decimal.Decimal
707 InvalidOperation = self.decimal.InvalidOperation
708 Rounded = self.decimal.Rounded
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000709
Stefan Krah1919b7e2012-03-21 18:25:23 +0100710 nc = copy.copy(self.decimal.getcontext())
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000711 nc.prec = 3
712
713 # empty
Raymond Hettingerfed52962004-07-14 15:41:57 +0000714 d = Decimal()
715 self.assertEqual(str(d), '0')
716 d = nc.create_decimal()
717 self.assertEqual(str(d), '0')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000718
719 # from None
720 self.assertRaises(TypeError, nc.create_decimal, None)
721
722 # from int
723 d = nc.create_decimal(456)
Ezio Melottie9615932010-01-24 19:26:24 +0000724 self.assertIsInstance(d, Decimal)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000725 self.assertEqual(nc.create_decimal(45678),
726 nc.create_decimal('457E+2'))
727
728 # from string
729 d = Decimal('456789')
730 self.assertEqual(str(d), '456789')
731 d = nc.create_decimal('456789')
732 self.assertEqual(str(d), '4.57E+5')
Christian Heimesa62da1d2008-01-12 19:39:10 +0000733 # leading and trailing whitespace should result in a NaN;
734 # spaces are already checked in Cowlishaw's test-suite, so
735 # here we just check that a trailing newline results in a NaN
736 self.assertEqual(str(nc.create_decimal('3.14\n')), 'NaN')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000737
738 # from tuples
739 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
740 self.assertEqual(str(d), '-4.34913534E-17')
741 d = nc.create_decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
742 self.assertEqual(str(d), '-4.35E-17')
743
744 # from Decimal
745 prevdec = Decimal(500000123)
746 d = Decimal(prevdec)
747 self.assertEqual(str(d), '500000123')
748 d = nc.create_decimal(prevdec)
749 self.assertEqual(str(d), '5.00E+8')
750
Stefan Krah1919b7e2012-03-21 18:25:23 +0100751 # more integers
752 nc.prec = 28
753 nc.traps[InvalidOperation] = True
754
755 for v in [-2**63-1, -2**63, -2**31-1, -2**31, 0,
756 2**31-1, 2**31, 2**63-1, 2**63]:
757 d = nc.create_decimal(v)
758 self.assertTrue(isinstance(d, Decimal))
759 self.assertEqual(int(d), v)
760
761 nc.prec = 3
762 nc.traps[Rounded] = True
763 self.assertRaises(Rounded, nc.create_decimal, 1234)
764
765 # from string
766 nc.prec = 28
767 self.assertEqual(str(nc.create_decimal('0E-017')), '0E-17')
768 self.assertEqual(str(nc.create_decimal('45')), '45')
769 self.assertEqual(str(nc.create_decimal('-Inf')), '-Infinity')
770 self.assertEqual(str(nc.create_decimal('NaN123')), 'NaN123')
771
772 # invalid arguments
773 self.assertRaises(InvalidOperation, nc.create_decimal, "xyz")
774 self.assertRaises(ValueError, nc.create_decimal, (1, "xyz", -25))
775 self.assertRaises(TypeError, nc.create_decimal, "1234", "5678")
776
777 # too many NaN payload digits
778 nc.prec = 3
779 self.assertRaises(InvalidOperation, nc.create_decimal, 'NaN12345')
780 self.assertRaises(InvalidOperation, nc.create_decimal,
781 Decimal('NaN12345'))
782
783 nc.traps[InvalidOperation] = False
784 self.assertEqual(str(nc.create_decimal('NaN12345')), 'NaN')
785 self.assertTrue(nc.flags[InvalidOperation])
786
787 nc.flags[InvalidOperation] = False
788 self.assertEqual(str(nc.create_decimal(Decimal('NaN12345'))), 'NaN')
789 self.assertTrue(nc.flags[InvalidOperation])
790
791 def test_explicit_context_create_from_float(self):
792
793 Decimal = self.decimal.Decimal
794
795 nc = self.decimal.Context()
796 r = nc.create_decimal(0.1)
797 self.assertEqual(type(r), Decimal)
798 self.assertEqual(str(r), '0.1000000000000000055511151231')
799 self.assertTrue(nc.create_decimal(float('nan')).is_qnan())
800 self.assertTrue(nc.create_decimal(float('inf')).is_infinite())
801 self.assertTrue(nc.create_decimal(float('-inf')).is_infinite())
802 self.assertEqual(str(nc.create_decimal(float('nan'))),
803 str(nc.create_decimal('NaN')))
804 self.assertEqual(str(nc.create_decimal(float('inf'))),
805 str(nc.create_decimal('Infinity')))
806 self.assertEqual(str(nc.create_decimal(float('-inf'))),
807 str(nc.create_decimal('-Infinity')))
808 self.assertEqual(str(nc.create_decimal(float('-0.0'))),
809 str(nc.create_decimal('-0')))
810 nc.prec = 100
811 for i in range(200):
812 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
813 self.assertEqual(x, float(nc.create_decimal(x))) # roundtrip
814
Mark Dickinson345adc42009-08-02 10:14:23 +0000815 def test_unicode_digits(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100816 Decimal = self.decimal.Decimal
817
Mark Dickinson345adc42009-08-02 10:14:23 +0000818 test_values = {
819 '\uff11': '1',
820 '\u0660.\u0660\u0663\u0667\u0662e-\u0663' : '0.0000372',
821 '-nan\u0c68\u0c6a\u0c66\u0c66' : '-NaN2400',
822 }
823 for input, expected in test_values.items():
824 self.assertEqual(str(Decimal(input)), expected)
825
Stefan Krah1919b7e2012-03-21 18:25:23 +0100826class CExplicitConstructionTest(ExplicitConstructionTest):
827 decimal = C
828class PyExplicitConstructionTest(ExplicitConstructionTest):
829 decimal = P
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000830
Stefan Krah1919b7e2012-03-21 18:25:23 +0100831class ImplicitConstructionTest(unittest.TestCase):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000832 '''Unit tests for Implicit Construction cases of Decimal.'''
833
834 def test_implicit_from_None(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100835 Decimal = self.decimal.Decimal
836 self.assertRaises(TypeError, eval, 'Decimal(5) + None', locals())
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000837
838 def test_implicit_from_int(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100839 Decimal = self.decimal.Decimal
840
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000841 #normal
842 self.assertEqual(str(Decimal(5) + 45), '50')
843 #exceeding precision
844 self.assertEqual(Decimal(5) + 123456789000, Decimal(123456789000))
845
846 def test_implicit_from_string(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100847 Decimal = self.decimal.Decimal
848 self.assertRaises(TypeError, eval, 'Decimal(5) + "3"', locals())
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000849
850 def test_implicit_from_float(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100851 Decimal = self.decimal.Decimal
852 self.assertRaises(TypeError, eval, 'Decimal(5) + 2.2', locals())
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000853
854 def test_implicit_from_Decimal(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100855 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000856 self.assertEqual(Decimal(5) + Decimal(45), Decimal(50))
857
Raymond Hettinger267b8682005-03-27 10:47:39 +0000858 def test_rop(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100859 Decimal = self.decimal.Decimal
860
Raymond Hettinger267b8682005-03-27 10:47:39 +0000861 # Allow other classes to be trained to interact with Decimals
862 class E:
863 def __divmod__(self, other):
864 return 'divmod ' + str(other)
865 def __rdivmod__(self, other):
866 return str(other) + ' rdivmod'
867 def __lt__(self, other):
868 return 'lt ' + str(other)
869 def __gt__(self, other):
870 return 'gt ' + str(other)
871 def __le__(self, other):
872 return 'le ' + str(other)
873 def __ge__(self, other):
874 return 'ge ' + str(other)
875 def __eq__(self, other):
876 return 'eq ' + str(other)
877 def __ne__(self, other):
878 return 'ne ' + str(other)
879
880 self.assertEqual(divmod(E(), Decimal(10)), 'divmod 10')
881 self.assertEqual(divmod(Decimal(10), E()), '10 rdivmod')
882 self.assertEqual(eval('Decimal(10) < E()'), 'gt 10')
883 self.assertEqual(eval('Decimal(10) > E()'), 'lt 10')
884 self.assertEqual(eval('Decimal(10) <= E()'), 'ge 10')
885 self.assertEqual(eval('Decimal(10) >= E()'), 'le 10')
886 self.assertEqual(eval('Decimal(10) == E()'), 'eq 10')
887 self.assertEqual(eval('Decimal(10) != E()'), 'ne 10')
888
889 # insert operator methods and then exercise them
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000890 oplist = [
891 ('+', '__add__', '__radd__'),
892 ('-', '__sub__', '__rsub__'),
893 ('*', '__mul__', '__rmul__'),
Thomas Woutersdcc6d322006-04-21 11:30:52 +0000894 ('/', '__truediv__', '__rtruediv__'),
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000895 ('%', '__mod__', '__rmod__'),
896 ('//', '__floordiv__', '__rfloordiv__'),
897 ('**', '__pow__', '__rpow__')
898 ]
Raymond Hettinger267b8682005-03-27 10:47:39 +0000899
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000900 for sym, lop, rop in oplist:
Raymond Hettinger267b8682005-03-27 10:47:39 +0000901 setattr(E, lop, lambda self, other: 'str' + lop + str(other))
902 setattr(E, rop, lambda self, other: str(other) + rop + 'str')
903 self.assertEqual(eval('E()' + sym + 'Decimal(10)'),
904 'str' + lop + '10')
905 self.assertEqual(eval('Decimal(10)' + sym + 'E()'),
906 '10' + rop + 'str')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000907
Stefan Krah1919b7e2012-03-21 18:25:23 +0100908class CImplicitConstructionTest(ImplicitConstructionTest):
909 decimal = C
910class PyImplicitConstructionTest(ImplicitConstructionTest):
911 decimal = P
Mark Dickinson79f52032009-03-17 23:12:51 +0000912
Stefan Krah1919b7e2012-03-21 18:25:23 +0100913class FormatTest(unittest.TestCase):
Christian Heimesf16baeb2008-02-29 14:57:44 +0000914 '''Unit tests for the format function.'''
915 def test_formatting(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100916 Decimal = self.decimal.Decimal
917
Christian Heimesf16baeb2008-02-29 14:57:44 +0000918 # triples giving a format, a Decimal, and the expected result
919 test_values = [
920 ('e', '0E-15', '0e-15'),
921 ('e', '2.3E-15', '2.3e-15'),
922 ('e', '2.30E+2', '2.30e+2'), # preserve significant zeros
923 ('e', '2.30000E-15', '2.30000e-15'),
924 ('e', '1.23456789123456789e40', '1.23456789123456789e+40'),
925 ('e', '1.5', '1.5e+0'),
926 ('e', '0.15', '1.5e-1'),
927 ('e', '0.015', '1.5e-2'),
928 ('e', '0.0000000000015', '1.5e-12'),
929 ('e', '15.0', '1.50e+1'),
930 ('e', '-15', '-1.5e+1'),
931 ('e', '0', '0e+0'),
932 ('e', '0E1', '0e+1'),
933 ('e', '0.0', '0e-1'),
934 ('e', '0.00', '0e-2'),
935 ('.6e', '0E-15', '0.000000e-9'),
936 ('.6e', '0', '0.000000e+6'),
937 ('.6e', '9.999999', '9.999999e+0'),
938 ('.6e', '9.9999999', '1.000000e+1'),
939 ('.6e', '-1.23e5', '-1.230000e+5'),
940 ('.6e', '1.23456789e-3', '1.234568e-3'),
941 ('f', '0', '0'),
942 ('f', '0.0', '0.0'),
943 ('f', '0E-2', '0.00'),
944 ('f', '0.00E-8', '0.0000000000'),
945 ('f', '0E1', '0'), # loses exponent information
946 ('f', '3.2E1', '32'),
947 ('f', '3.2E2', '320'),
948 ('f', '3.20E2', '320'),
949 ('f', '3.200E2', '320.0'),
950 ('f', '3.2E-6', '0.0000032'),
951 ('.6f', '0E-15', '0.000000'), # all zeros treated equally
952 ('.6f', '0E1', '0.000000'),
953 ('.6f', '0', '0.000000'),
954 ('.0f', '0', '0'), # no decimal point
955 ('.0f', '0e-2', '0'),
956 ('.0f', '3.14159265', '3'),
957 ('.1f', '3.14159265', '3.1'),
958 ('.4f', '3.14159265', '3.1416'),
959 ('.6f', '3.14159265', '3.141593'),
960 ('.7f', '3.14159265', '3.1415926'), # round-half-even!
961 ('.8f', '3.14159265', '3.14159265'),
962 ('.9f', '3.14159265', '3.141592650'),
963
964 ('g', '0', '0'),
965 ('g', '0.0', '0.0'),
966 ('g', '0E1', '0e+1'),
967 ('G', '0E1', '0E+1'),
968 ('g', '0E-5', '0.00000'),
969 ('g', '0E-6', '0.000000'),
970 ('g', '0E-7', '0e-7'),
971 ('g', '-0E2', '-0e+2'),
972 ('.0g', '3.14159265', '3'), # 0 sig fig -> 1 sig fig
Stefan Krah1919b7e2012-03-21 18:25:23 +0100973 ('.0n', '3.14159265', '3'), # same for 'n'
Christian Heimesf16baeb2008-02-29 14:57:44 +0000974 ('.1g', '3.14159265', '3'),
975 ('.2g', '3.14159265', '3.1'),
976 ('.5g', '3.14159265', '3.1416'),
977 ('.7g', '3.14159265', '3.141593'),
978 ('.8g', '3.14159265', '3.1415926'), # round-half-even!
979 ('.9g', '3.14159265', '3.14159265'),
980 ('.10g', '3.14159265', '3.14159265'), # don't pad
981
982 ('%', '0E1', '0%'),
983 ('%', '0E0', '0%'),
984 ('%', '0E-1', '0%'),
985 ('%', '0E-2', '0%'),
986 ('%', '0E-3', '0.0%'),
987 ('%', '0E-4', '0.00%'),
988
989 ('.3%', '0', '0.000%'), # all zeros treated equally
990 ('.3%', '0E10', '0.000%'),
991 ('.3%', '0E-10', '0.000%'),
992 ('.3%', '2.34', '234.000%'),
993 ('.3%', '1.234567', '123.457%'),
994 ('.0%', '1.23', '123%'),
995
996 ('e', 'NaN', 'NaN'),
997 ('f', '-NaN123', '-NaN123'),
998 ('+g', 'NaN456', '+NaN456'),
999 ('.3e', 'Inf', 'Infinity'),
1000 ('.16f', '-Inf', '-Infinity'),
1001 ('.0g', '-sNaN', '-sNaN'),
1002
1003 ('', '1.00', '1.00'),
Mark Dickinsonad416342009-03-17 18:10:15 +00001004
Mark Dickinson79f52032009-03-17 23:12:51 +00001005 # test alignment and padding
Mark Dickinson46ab5d02009-09-08 20:22:46 +00001006 ('6', '123', ' 123'),
Mark Dickinsonad416342009-03-17 18:10:15 +00001007 ('<6', '123', '123 '),
1008 ('>6', '123', ' 123'),
1009 ('^6', '123', ' 123 '),
1010 ('=+6', '123', '+ 123'),
Mark Dickinson79f52032009-03-17 23:12:51 +00001011 ('#<10', 'NaN', 'NaN#######'),
1012 ('#<10', '-4.3', '-4.3######'),
1013 ('#<+10', '0.0130', '+0.0130###'),
1014 ('#< 10', '0.0130', ' 0.0130###'),
1015 ('@>10', '-Inf', '@-Infinity'),
1016 ('#>5', '-Inf', '-Infinity'),
1017 ('?^5', '123', '?123?'),
1018 ('%^6', '123', '%123%%'),
1019 (' ^6', '-45.6', '-45.6 '),
1020 ('/=10', '-45.6', '-/////45.6'),
1021 ('/=+10', '45.6', '+/////45.6'),
1022 ('/= 10', '45.6', ' /////45.6'),
Stefan Krah6edda142013-05-29 15:45:38 +02001023 ('\x00=10', '-inf', '-\x00Infinity'),
1024 ('\x00^16', '-inf', '\x00\x00\x00-Infinity\x00\x00\x00\x00'),
1025 ('\x00>10', '1.2345', '\x00\x00\x00\x001.2345'),
1026 ('\x00<10', '1.2345', '1.2345\x00\x00\x00\x00'),
Mark Dickinson79f52032009-03-17 23:12:51 +00001027
1028 # thousands separator
1029 (',', '1234567', '1,234,567'),
1030 (',', '123456', '123,456'),
1031 (',', '12345', '12,345'),
1032 (',', '1234', '1,234'),
1033 (',', '123', '123'),
1034 (',', '12', '12'),
1035 (',', '1', '1'),
1036 (',', '0', '0'),
1037 (',', '-1234567', '-1,234,567'),
1038 (',', '-123456', '-123,456'),
1039 ('7,', '123456', '123,456'),
Mark Dickinson46ab5d02009-09-08 20:22:46 +00001040 ('8,', '123456', ' 123,456'),
Mark Dickinson79f52032009-03-17 23:12:51 +00001041 ('08,', '123456', '0,123,456'), # special case: extra 0 needed
1042 ('+08,', '123456', '+123,456'), # but not if there's a sign
1043 (' 08,', '123456', ' 123,456'),
1044 ('08,', '-123456', '-123,456'),
1045 ('+09,', '123456', '+0,123,456'),
1046 # ... with fractional part...
1047 ('07,', '1234.56', '1,234.56'),
1048 ('08,', '1234.56', '1,234.56'),
1049 ('09,', '1234.56', '01,234.56'),
1050 ('010,', '1234.56', '001,234.56'),
1051 ('011,', '1234.56', '0,001,234.56'),
1052 ('012,', '1234.56', '0,001,234.56'),
1053 ('08,.1f', '1234.5', '01,234.5'),
1054 # no thousands separators in fraction part
1055 (',', '1.23456789', '1.23456789'),
1056 (',%', '123.456789', '12,345.6789%'),
1057 (',e', '123456', '1.23456e+5'),
1058 (',E', '123456', '1.23456E+5'),
Mark Dickinson7718d2b2009-09-07 16:21:56 +00001059
1060 # issue 6850
1061 ('a=-7.0', '0.12345', 'aaaa0.1'),
Christian Heimesf16baeb2008-02-29 14:57:44 +00001062 ]
1063 for fmt, d, result in test_values:
1064 self.assertEqual(format(Decimal(d), fmt), result)
1065
Stefan Krah1919b7e2012-03-21 18:25:23 +01001066 # bytes format argument
1067 self.assertRaises(TypeError, Decimal(1).__format__, b'-020')
1068
Mark Dickinson79f52032009-03-17 23:12:51 +00001069 def test_n_format(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001070 Decimal = self.decimal.Decimal
1071
Mark Dickinson79f52032009-03-17 23:12:51 +00001072 try:
1073 from locale import CHAR_MAX
1074 except ImportError:
1075 return
1076
Stefan Krah1919b7e2012-03-21 18:25:23 +01001077 def make_grouping(lst):
1078 return ''.join([chr(x) for x in lst]) if self.decimal == C else lst
1079
1080 def get_fmt(x, override=None, fmt='n'):
1081 if self.decimal == C:
1082 return Decimal(x).__format__(fmt, override)
1083 else:
1084 return Decimal(x).__format__(fmt, _localeconv=override)
1085
Mark Dickinson79f52032009-03-17 23:12:51 +00001086 # Set up some localeconv-like dictionaries
1087 en_US = {
1088 'decimal_point' : '.',
Stefan Krah1919b7e2012-03-21 18:25:23 +01001089 'grouping' : make_grouping([3, 3, 0]),
1090 'thousands_sep' : ','
Mark Dickinson79f52032009-03-17 23:12:51 +00001091 }
1092
1093 fr_FR = {
1094 'decimal_point' : ',',
Stefan Krah1919b7e2012-03-21 18:25:23 +01001095 'grouping' : make_grouping([CHAR_MAX]),
Mark Dickinson79f52032009-03-17 23:12:51 +00001096 'thousands_sep' : ''
1097 }
1098
1099 ru_RU = {
1100 'decimal_point' : ',',
Stefan Krah1919b7e2012-03-21 18:25:23 +01001101 'grouping': make_grouping([3, 3, 0]),
Mark Dickinson79f52032009-03-17 23:12:51 +00001102 'thousands_sep' : ' '
1103 }
1104
1105 crazy = {
1106 'decimal_point' : '&',
Stefan Krah1919b7e2012-03-21 18:25:23 +01001107 'grouping': make_grouping([1, 4, 2, CHAR_MAX]),
Mark Dickinson79f52032009-03-17 23:12:51 +00001108 'thousands_sep' : '-'
1109 }
1110
Stefan Krah1919b7e2012-03-21 18:25:23 +01001111 dotsep_wide = {
1112 'decimal_point' : b'\xc2\xbf'.decode('utf-8'),
1113 'grouping': make_grouping([3, 3, 0]),
1114 'thousands_sep' : b'\xc2\xb4'.decode('utf-8')
1115 }
Mark Dickinson79f52032009-03-17 23:12:51 +00001116
1117 self.assertEqual(get_fmt(Decimal('12.7'), en_US), '12.7')
1118 self.assertEqual(get_fmt(Decimal('12.7'), fr_FR), '12,7')
1119 self.assertEqual(get_fmt(Decimal('12.7'), ru_RU), '12,7')
1120 self.assertEqual(get_fmt(Decimal('12.7'), crazy), '1-2&7')
1121
1122 self.assertEqual(get_fmt(123456789, en_US), '123,456,789')
1123 self.assertEqual(get_fmt(123456789, fr_FR), '123456789')
1124 self.assertEqual(get_fmt(123456789, ru_RU), '123 456 789')
1125 self.assertEqual(get_fmt(1234567890123, crazy), '123456-78-9012-3')
1126
1127 self.assertEqual(get_fmt(123456789, en_US, '.6n'), '1.23457e+8')
1128 self.assertEqual(get_fmt(123456789, fr_FR, '.6n'), '1,23457e+8')
1129 self.assertEqual(get_fmt(123456789, ru_RU, '.6n'), '1,23457e+8')
1130 self.assertEqual(get_fmt(123456789, crazy, '.6n'), '1&23457e+8')
1131
Mark Dickinson7303b592009-03-18 08:25:36 +00001132 # zero padding
1133 self.assertEqual(get_fmt(1234, fr_FR, '03n'), '1234')
1134 self.assertEqual(get_fmt(1234, fr_FR, '04n'), '1234')
1135 self.assertEqual(get_fmt(1234, fr_FR, '05n'), '01234')
1136 self.assertEqual(get_fmt(1234, fr_FR, '06n'), '001234')
1137
1138 self.assertEqual(get_fmt(12345, en_US, '05n'), '12,345')
1139 self.assertEqual(get_fmt(12345, en_US, '06n'), '12,345')
1140 self.assertEqual(get_fmt(12345, en_US, '07n'), '012,345')
1141 self.assertEqual(get_fmt(12345, en_US, '08n'), '0,012,345')
1142 self.assertEqual(get_fmt(12345, en_US, '09n'), '0,012,345')
1143 self.assertEqual(get_fmt(12345, en_US, '010n'), '00,012,345')
1144
1145 self.assertEqual(get_fmt(123456, crazy, '06n'), '1-2345-6')
1146 self.assertEqual(get_fmt(123456, crazy, '07n'), '1-2345-6')
1147 self.assertEqual(get_fmt(123456, crazy, '08n'), '1-2345-6')
1148 self.assertEqual(get_fmt(123456, crazy, '09n'), '01-2345-6')
1149 self.assertEqual(get_fmt(123456, crazy, '010n'), '0-01-2345-6')
1150 self.assertEqual(get_fmt(123456, crazy, '011n'), '0-01-2345-6')
1151 self.assertEqual(get_fmt(123456, crazy, '012n'), '00-01-2345-6')
1152 self.assertEqual(get_fmt(123456, crazy, '013n'), '000-01-2345-6')
1153
Stefan Krah1919b7e2012-03-21 18:25:23 +01001154 # wide char separator and decimal point
1155 self.assertEqual(get_fmt(Decimal('-1.5'), dotsep_wide, '020n'),
1156 '-0\u00b4000\u00b4000\u00b4000\u00b4001\u00bf5')
Mark Dickinson79f52032009-03-17 23:12:51 +00001157
Stefan Krah6fb204a2012-09-28 16:18:54 +02001158 @run_with_locale('LC_ALL', 'ps_AF')
Stefan Krah1919b7e2012-03-21 18:25:23 +01001159 def test_wide_char_separator_decimal_point(self):
1160 # locale with wide char separator and decimal point
Stefan Krah8a491a82012-09-28 17:17:11 +02001161 import locale
Stefan Krah1919b7e2012-03-21 18:25:23 +01001162 Decimal = self.decimal.Decimal
1163
Stefan Krah8a491a82012-09-28 17:17:11 +02001164 decimal_point = locale.localeconv()['decimal_point']
1165 thousands_sep = locale.localeconv()['thousands_sep']
1166 if decimal_point != '\u066b' or thousands_sep != '\u066c':
1167 return
1168
Stefan Krah1919b7e2012-03-21 18:25:23 +01001169 self.assertEqual(format(Decimal('100000000.123'), 'n'),
1170 '100\u066c000\u066c000\u066b123')
Stefan Krah1919b7e2012-03-21 18:25:23 +01001171
1172class CFormatTest(FormatTest):
1173 decimal = C
1174class PyFormatTest(FormatTest):
1175 decimal = P
1176
1177class ArithmeticOperatorsTest(unittest.TestCase):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001178 '''Unit tests for all arithmetic operators, binary and unary.'''
1179
1180 def test_addition(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001181 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001182
1183 d1 = Decimal('-11.1')
1184 d2 = Decimal('22.2')
1185
1186 #two Decimals
1187 self.assertEqual(d1+d2, Decimal('11.1'))
1188 self.assertEqual(d2+d1, Decimal('11.1'))
1189
1190 #with other type, left
1191 c = d1 + 5
1192 self.assertEqual(c, Decimal('-6.1'))
1193 self.assertEqual(type(c), type(d1))
1194
1195 #with other type, right
1196 c = 5 + d1
1197 self.assertEqual(c, Decimal('-6.1'))
1198 self.assertEqual(type(c), type(d1))
1199
1200 #inline with decimal
1201 d1 += d2
1202 self.assertEqual(d1, Decimal('11.1'))
1203
1204 #inline with other type
1205 d1 += 5
1206 self.assertEqual(d1, Decimal('16.1'))
1207
1208 def test_subtraction(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001209 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001210
1211 d1 = Decimal('-11.1')
1212 d2 = Decimal('22.2')
1213
1214 #two Decimals
1215 self.assertEqual(d1-d2, Decimal('-33.3'))
1216 self.assertEqual(d2-d1, Decimal('33.3'))
1217
1218 #with other type, left
1219 c = d1 - 5
1220 self.assertEqual(c, Decimal('-16.1'))
1221 self.assertEqual(type(c), type(d1))
1222
1223 #with other type, right
1224 c = 5 - d1
1225 self.assertEqual(c, Decimal('16.1'))
1226 self.assertEqual(type(c), type(d1))
1227
1228 #inline with decimal
1229 d1 -= d2
1230 self.assertEqual(d1, Decimal('-33.3'))
1231
1232 #inline with other type
1233 d1 -= 5
1234 self.assertEqual(d1, Decimal('-38.3'))
1235
1236 def test_multiplication(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001237 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001238
1239 d1 = Decimal('-5')
1240 d2 = Decimal('3')
1241
1242 #two Decimals
1243 self.assertEqual(d1*d2, Decimal('-15'))
1244 self.assertEqual(d2*d1, Decimal('-15'))
1245
1246 #with other type, left
1247 c = d1 * 5
1248 self.assertEqual(c, Decimal('-25'))
1249 self.assertEqual(type(c), type(d1))
1250
1251 #with other type, right
1252 c = 5 * d1
1253 self.assertEqual(c, Decimal('-25'))
1254 self.assertEqual(type(c), type(d1))
1255
1256 #inline with decimal
1257 d1 *= d2
1258 self.assertEqual(d1, Decimal('-15'))
1259
1260 #inline with other type
1261 d1 *= 5
1262 self.assertEqual(d1, Decimal('-75'))
1263
1264 def test_division(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001265 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001266
1267 d1 = Decimal('-5')
1268 d2 = Decimal('2')
1269
1270 #two Decimals
1271 self.assertEqual(d1/d2, Decimal('-2.5'))
1272 self.assertEqual(d2/d1, Decimal('-0.4'))
1273
1274 #with other type, left
1275 c = d1 / 4
1276 self.assertEqual(c, Decimal('-1.25'))
1277 self.assertEqual(type(c), type(d1))
1278
1279 #with other type, right
1280 c = 4 / d1
1281 self.assertEqual(c, Decimal('-0.8'))
1282 self.assertEqual(type(c), type(d1))
1283
1284 #inline with decimal
1285 d1 /= d2
1286 self.assertEqual(d1, Decimal('-2.5'))
1287
1288 #inline with other type
1289 d1 /= 4
1290 self.assertEqual(d1, Decimal('-0.625'))
1291
1292 def test_floor_division(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001293 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001294
1295 d1 = Decimal('5')
1296 d2 = Decimal('2')
1297
1298 #two Decimals
1299 self.assertEqual(d1//d2, Decimal('2'))
1300 self.assertEqual(d2//d1, Decimal('0'))
1301
1302 #with other type, left
1303 c = d1 // 4
1304 self.assertEqual(c, Decimal('1'))
1305 self.assertEqual(type(c), type(d1))
1306
1307 #with other type, right
1308 c = 7 // d1
1309 self.assertEqual(c, Decimal('1'))
1310 self.assertEqual(type(c), type(d1))
1311
1312 #inline with decimal
1313 d1 //= d2
1314 self.assertEqual(d1, Decimal('2'))
1315
1316 #inline with other type
1317 d1 //= 2
1318 self.assertEqual(d1, Decimal('1'))
1319
1320 def test_powering(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001321 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001322
1323 d1 = Decimal('5')
1324 d2 = Decimal('2')
1325
1326 #two Decimals
1327 self.assertEqual(d1**d2, Decimal('25'))
1328 self.assertEqual(d2**d1, Decimal('32'))
1329
1330 #with other type, left
1331 c = d1 ** 4
1332 self.assertEqual(c, Decimal('625'))
1333 self.assertEqual(type(c), type(d1))
1334
1335 #with other type, right
1336 c = 7 ** d1
1337 self.assertEqual(c, Decimal('16807'))
1338 self.assertEqual(type(c), type(d1))
1339
1340 #inline with decimal
1341 d1 **= d2
1342 self.assertEqual(d1, Decimal('25'))
1343
1344 #inline with other type
1345 d1 **= 4
1346 self.assertEqual(d1, Decimal('390625'))
1347
1348 def test_module(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001349 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001350
1351 d1 = Decimal('5')
1352 d2 = Decimal('2')
1353
1354 #two Decimals
1355 self.assertEqual(d1%d2, Decimal('1'))
1356 self.assertEqual(d2%d1, Decimal('2'))
1357
1358 #with other type, left
1359 c = d1 % 4
1360 self.assertEqual(c, Decimal('1'))
1361 self.assertEqual(type(c), type(d1))
1362
1363 #with other type, right
1364 c = 7 % d1
1365 self.assertEqual(c, Decimal('2'))
1366 self.assertEqual(type(c), type(d1))
1367
1368 #inline with decimal
1369 d1 %= d2
1370 self.assertEqual(d1, Decimal('1'))
1371
1372 #inline with other type
1373 d1 %= 4
1374 self.assertEqual(d1, Decimal('1'))
1375
1376 def test_floor_div_module(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001377 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001378
1379 d1 = Decimal('5')
1380 d2 = Decimal('2')
1381
1382 #two Decimals
1383 (p, q) = divmod(d1, d2)
1384 self.assertEqual(p, Decimal('2'))
1385 self.assertEqual(q, Decimal('1'))
1386 self.assertEqual(type(p), type(d1))
1387 self.assertEqual(type(q), type(d1))
1388
1389 #with other type, left
1390 (p, q) = divmod(d1, 4)
1391 self.assertEqual(p, Decimal('1'))
1392 self.assertEqual(q, Decimal('1'))
1393 self.assertEqual(type(p), type(d1))
1394 self.assertEqual(type(q), type(d1))
1395
1396 #with other type, right
1397 (p, q) = divmod(7, d1)
1398 self.assertEqual(p, Decimal('1'))
1399 self.assertEqual(q, Decimal('2'))
1400 self.assertEqual(type(p), type(d1))
1401 self.assertEqual(type(q), type(d1))
1402
1403 def test_unary_operators(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001404 Decimal = self.decimal.Decimal
1405
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001406 self.assertEqual(+Decimal(45), Decimal(+45)) # +
1407 self.assertEqual(-Decimal(45), Decimal(-45)) # -
1408 self.assertEqual(abs(Decimal(45)), abs(Decimal(-45))) # abs
1409
Christian Heimes77c02eb2008-02-09 02:18:51 +00001410 def test_nan_comparisons(self):
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001411 # comparisons involving signaling nans signal InvalidOperation
1412
1413 # order comparisons (<, <=, >, >=) involving only quiet nans
1414 # also signal InvalidOperation
1415
1416 # equality comparisons (==, !=) involving only quiet nans
1417 # don't signal, but return False or True respectively.
Stefan Krah1919b7e2012-03-21 18:25:23 +01001418 Decimal = self.decimal.Decimal
1419 InvalidOperation = self.decimal.InvalidOperation
1420 localcontext = self.decimal.localcontext
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001421
Christian Heimes77c02eb2008-02-09 02:18:51 +00001422 n = Decimal('NaN')
1423 s = Decimal('sNaN')
1424 i = Decimal('Inf')
1425 f = Decimal('2')
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001426
1427 qnan_pairs = (n, n), (n, i), (i, n), (n, f), (f, n)
1428 snan_pairs = (s, n), (n, s), (s, i), (i, s), (s, f), (f, s), (s, s)
1429 order_ops = operator.lt, operator.le, operator.gt, operator.ge
1430 equality_ops = operator.eq, operator.ne
1431
1432 # results when InvalidOperation is not trapped
1433 for x, y in qnan_pairs + snan_pairs:
1434 for op in order_ops + equality_ops:
1435 got = op(x, y)
1436 expected = True if op is operator.ne else False
1437 self.assertIs(expected, got,
1438 "expected {0!r} for operator.{1}({2!r}, {3!r}); "
1439 "got {4!r}".format(
1440 expected, op.__name__, x, y, got))
1441
1442 # repeat the above, but this time trap the InvalidOperation
1443 with localcontext() as ctx:
1444 ctx.traps[InvalidOperation] = 1
1445
1446 for x, y in qnan_pairs:
1447 for op in equality_ops:
1448 got = op(x, y)
1449 expected = True if op is operator.ne else False
1450 self.assertIs(expected, got,
1451 "expected {0!r} for "
1452 "operator.{1}({2!r}, {3!r}); "
1453 "got {4!r}".format(
1454 expected, op.__name__, x, y, got))
1455
1456 for x, y in snan_pairs:
1457 for op in equality_ops:
1458 self.assertRaises(InvalidOperation, operator.eq, x, y)
1459 self.assertRaises(InvalidOperation, operator.ne, x, y)
1460
1461 for x, y in qnan_pairs + snan_pairs:
1462 for op in order_ops:
1463 self.assertRaises(InvalidOperation, op, x, y)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001464
Mark Dickinson84230a12010-02-18 14:49:50 +00001465 def test_copy_sign(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001466 Decimal = self.decimal.Decimal
Mark Dickinson84230a12010-02-18 14:49:50 +00001467
Stefan Krah1919b7e2012-03-21 18:25:23 +01001468 d = Decimal(1).copy_sign(Decimal(-2))
Mark Dickinson84230a12010-02-18 14:49:50 +00001469 self.assertEqual(Decimal(1).copy_sign(-2), d)
1470 self.assertRaises(TypeError, Decimal(1).copy_sign, '-2')
1471
Stefan Krah1919b7e2012-03-21 18:25:23 +01001472class CArithmeticOperatorsTest(ArithmeticOperatorsTest):
1473 decimal = C
1474class PyArithmeticOperatorsTest(ArithmeticOperatorsTest):
1475 decimal = P
1476
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001477# The following are two functions used to test threading in the next class
1478
1479def thfunc1(cls):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001480 Decimal = cls.decimal.Decimal
1481 InvalidOperation = cls.decimal.InvalidOperation
1482 DivisionByZero = cls.decimal.DivisionByZero
1483 Overflow = cls.decimal.Overflow
1484 Underflow = cls.decimal.Underflow
1485 Inexact = cls.decimal.Inexact
1486 getcontext = cls.decimal.getcontext
1487 localcontext = cls.decimal.localcontext
1488
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001489 d1 = Decimal(1)
1490 d3 = Decimal(3)
Christian Heimesfe337bf2008-03-23 21:54:12 +00001491 test1 = d1/d3
Christian Heimesfe337bf2008-03-23 21:54:12 +00001492
Stefan Krah1919b7e2012-03-21 18:25:23 +01001493 cls.finish1.set()
1494 cls.synchro.wait()
1495
1496 test2 = d1/d3
1497 with localcontext() as c2:
1498 cls.assertTrue(c2.flags[Inexact])
1499 cls.assertRaises(DivisionByZero, c2.divide, d1, 0)
1500 cls.assertTrue(c2.flags[DivisionByZero])
1501 with localcontext() as c3:
1502 cls.assertTrue(c3.flags[Inexact])
1503 cls.assertTrue(c3.flags[DivisionByZero])
1504 cls.assertRaises(InvalidOperation, c3.compare, d1, Decimal('sNaN'))
1505 cls.assertTrue(c3.flags[InvalidOperation])
1506 del c3
1507 cls.assertFalse(c2.flags[InvalidOperation])
1508 del c2
1509
1510 cls.assertEqual(test1, Decimal('0.333333333333333333333333'))
1511 cls.assertEqual(test2, Decimal('0.333333333333333333333333'))
1512
1513 c1 = getcontext()
1514 cls.assertTrue(c1.flags[Inexact])
1515 for sig in Overflow, Underflow, DivisionByZero, InvalidOperation:
1516 cls.assertFalse(c1.flags[sig])
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001517 return
1518
1519def thfunc2(cls):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001520 Decimal = cls.decimal.Decimal
1521 InvalidOperation = cls.decimal.InvalidOperation
1522 DivisionByZero = cls.decimal.DivisionByZero
1523 Overflow = cls.decimal.Overflow
1524 Underflow = cls.decimal.Underflow
1525 Inexact = cls.decimal.Inexact
1526 getcontext = cls.decimal.getcontext
1527 localcontext = cls.decimal.localcontext
1528
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001529 d1 = Decimal(1)
1530 d3 = Decimal(3)
Christian Heimesfe337bf2008-03-23 21:54:12 +00001531 test1 = d1/d3
Stefan Krah1919b7e2012-03-21 18:25:23 +01001532
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001533 thiscontext = getcontext()
1534 thiscontext.prec = 18
Christian Heimesfe337bf2008-03-23 21:54:12 +00001535 test2 = d1/d3
Stefan Krah1919b7e2012-03-21 18:25:23 +01001536
1537 with localcontext() as c2:
1538 cls.assertTrue(c2.flags[Inexact])
1539 cls.assertRaises(Overflow, c2.multiply, Decimal('1e425000000'), 999)
1540 cls.assertTrue(c2.flags[Overflow])
1541 with localcontext(thiscontext) as c3:
1542 cls.assertTrue(c3.flags[Inexact])
1543 cls.assertFalse(c3.flags[Overflow])
1544 c3.traps[Underflow] = True
1545 cls.assertRaises(Underflow, c3.divide, Decimal('1e-425000000'), 999)
1546 cls.assertTrue(c3.flags[Underflow])
1547 del c3
1548 cls.assertFalse(c2.flags[Underflow])
1549 cls.assertFalse(c2.traps[Underflow])
1550 del c2
1551
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001552 cls.synchro.set()
1553 cls.finish2.set()
Christian Heimesfe337bf2008-03-23 21:54:12 +00001554
Stefan Krah1919b7e2012-03-21 18:25:23 +01001555 cls.assertEqual(test1, Decimal('0.333333333333333333333333'))
Christian Heimesfe337bf2008-03-23 21:54:12 +00001556 cls.assertEqual(test2, Decimal('0.333333333333333333'))
Stefan Krah1919b7e2012-03-21 18:25:23 +01001557
1558 cls.assertFalse(thiscontext.traps[Underflow])
1559 cls.assertTrue(thiscontext.flags[Inexact])
1560 for sig in Overflow, Underflow, DivisionByZero, InvalidOperation:
1561 cls.assertFalse(thiscontext.flags[sig])
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001562 return
1563
Stefan Krah1919b7e2012-03-21 18:25:23 +01001564class ThreadingTest(unittest.TestCase):
1565 '''Unit tests for thread local contexts in Decimal.'''
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001566
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001567 # Take care executing this test from IDLE, there's an issue in threading
1568 # that hangs IDLE and I couldn't find it
1569
1570 def test_threading(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001571 DefaultContext = self.decimal.DefaultContext
1572
1573 if self.decimal == C and not self.decimal.HAVE_THREADS:
1574 self.skipTest("compiled without threading")
1575 # Test the "threading isolation" of a Context. Also test changing
1576 # the DefaultContext, which acts as a template for the thread-local
1577 # contexts.
1578 save_prec = DefaultContext.prec
1579 save_emax = DefaultContext.Emax
1580 save_emin = DefaultContext.Emin
1581 DefaultContext.prec = 24
1582 DefaultContext.Emax = 425000000
1583 DefaultContext.Emin = -425000000
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001584
1585 self.synchro = threading.Event()
1586 self.finish1 = threading.Event()
1587 self.finish2 = threading.Event()
1588
1589 th1 = threading.Thread(target=thfunc1, args=(self,))
1590 th2 = threading.Thread(target=thfunc2, args=(self,))
1591
1592 th1.start()
1593 th2.start()
1594
1595 self.finish1.wait()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001596 self.finish2.wait()
Stefan Krah1919b7e2012-03-21 18:25:23 +01001597
1598 for sig in Signals[self.decimal]:
1599 self.assertFalse(DefaultContext.flags[sig])
1600
1601 DefaultContext.prec = save_prec
1602 DefaultContext.Emax = save_emax
1603 DefaultContext.Emin = save_emin
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001604 return
1605
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
2435 sys.modules['decimal'] = savedecimal
2436
2437 def test_int(self):
2438 Decimal = self.decimal.Decimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01002439
2440 for x in range(-250, 250):
2441 s = '%0.2f' % (x / 100.0)
2442 # should work the same as for floats
2443 self.assertEqual(int(Decimal(s)), int(float(s)))
2444 # should work the same as to_integral in the ROUND_DOWN mode
2445 d = Decimal(s)
2446 r = d.to_integral(ROUND_DOWN)
2447 self.assertEqual(Decimal(int(d)), r)
2448
2449 self.assertRaises(ValueError, int, Decimal('-nan'))
2450 self.assertRaises(ValueError, int, Decimal('snan'))
2451 self.assertRaises(OverflowError, int, Decimal('inf'))
2452 self.assertRaises(OverflowError, int, Decimal('-inf'))
2453
2454 def test_trunc(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(math.trunc(d)), r)
2465
2466 def test_from_float(self):
2467
2468 Decimal = self.decimal.Decimal
2469
2470 class MyDecimal(Decimal):
2471 pass
2472
2473 self.assertTrue(issubclass(MyDecimal, Decimal))
2474
2475 r = MyDecimal.from_float(0.1)
2476 self.assertEqual(type(r), MyDecimal)
2477 self.assertEqual(str(r),
2478 '0.1000000000000000055511151231257827021181583404541015625')
2479 bigint = 12345678901234567890123456789
2480 self.assertEqual(MyDecimal.from_float(bigint), MyDecimal(bigint))
2481 self.assertTrue(MyDecimal.from_float(float('nan')).is_qnan())
2482 self.assertTrue(MyDecimal.from_float(float('inf')).is_infinite())
2483 self.assertTrue(MyDecimal.from_float(float('-inf')).is_infinite())
2484 self.assertEqual(str(MyDecimal.from_float(float('nan'))),
2485 str(Decimal('NaN')))
2486 self.assertEqual(str(MyDecimal.from_float(float('inf'))),
2487 str(Decimal('Infinity')))
2488 self.assertEqual(str(MyDecimal.from_float(float('-inf'))),
2489 str(Decimal('-Infinity')))
2490 self.assertRaises(TypeError, MyDecimal.from_float, 'abc')
2491 for i in range(200):
2492 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
2493 self.assertEqual(x, float(MyDecimal.from_float(x))) # roundtrip
2494
2495 def test_create_decimal_from_float(self):
2496 Decimal = self.decimal.Decimal
2497 Context = self.decimal.Context
Stefan Krah1919b7e2012-03-21 18:25:23 +01002498 Inexact = self.decimal.Inexact
2499
2500 context = Context(prec=5, rounding=ROUND_DOWN)
2501 self.assertEqual(
2502 context.create_decimal_from_float(math.pi),
2503 Decimal('3.1415')
2504 )
2505 context = Context(prec=5, rounding=ROUND_UP)
2506 self.assertEqual(
2507 context.create_decimal_from_float(math.pi),
2508 Decimal('3.1416')
2509 )
2510 context = Context(prec=5, traps=[Inexact])
2511 self.assertRaises(
2512 Inexact,
2513 context.create_decimal_from_float,
2514 math.pi
2515 )
2516 self.assertEqual(repr(context.create_decimal_from_float(-0.0)),
2517 "Decimal('-0')")
2518 self.assertEqual(repr(context.create_decimal_from_float(1.0)),
2519 "Decimal('1')")
2520 self.assertEqual(repr(context.create_decimal_from_float(10)),
2521 "Decimal('10')")
2522
2523 def test_quantize(self):
2524 Decimal = self.decimal.Decimal
2525 Context = self.decimal.Context
2526 InvalidOperation = self.decimal.InvalidOperation
Stefan Krah1919b7e2012-03-21 18:25:23 +01002527
2528 c = Context(Emax=99999, Emin=-99999)
2529 self.assertEqual(
2530 Decimal('7.335').quantize(Decimal('.01')),
2531 Decimal('7.34')
2532 )
2533 self.assertEqual(
2534 Decimal('7.335').quantize(Decimal('.01'), rounding=ROUND_DOWN),
2535 Decimal('7.33')
2536 )
2537 self.assertRaises(
2538 InvalidOperation,
2539 Decimal("10e99999").quantize, Decimal('1e100000'), context=c
2540 )
2541
2542 c = Context()
2543 d = Decimal("0.871831e800")
2544 x = d.quantize(context=c, exp=Decimal("1e797"), rounding=ROUND_DOWN)
2545 self.assertEqual(x, Decimal('8.71E+799'))
2546
2547 def test_complex(self):
2548 Decimal = self.decimal.Decimal
2549
2550 x = Decimal("9.8182731e181273")
2551 self.assertEqual(x.real, x)
2552 self.assertEqual(x.imag, 0)
2553 self.assertEqual(x.conjugate(), x)
2554
2555 x = Decimal("1")
2556 self.assertEqual(complex(x), complex(float(1)))
2557
2558 self.assertRaises(AttributeError, setattr, x, 'real', 100)
2559 self.assertRaises(AttributeError, setattr, x, 'imag', 100)
2560 self.assertRaises(AttributeError, setattr, x, 'conjugate', 100)
2561 self.assertRaises(AttributeError, setattr, x, '__complex__', 100)
2562
2563 def test_named_parameters(self):
2564 D = self.decimal.Decimal
2565 Context = self.decimal.Context
2566 localcontext = self.decimal.localcontext
2567 InvalidOperation = self.decimal.InvalidOperation
2568 Overflow = self.decimal.Overflow
2569
2570 xc = Context()
2571 xc.prec = 1
2572 xc.Emax = 1
2573 xc.Emin = -1
2574
2575 with localcontext() as c:
2576 c.clear_flags()
2577
2578 self.assertEqual(D(9, xc), 9)
2579 self.assertEqual(D(9, context=xc), 9)
2580 self.assertEqual(D(context=xc, value=9), 9)
2581 self.assertEqual(D(context=xc), 0)
2582 xc.clear_flags()
2583 self.assertRaises(InvalidOperation, D, "xyz", context=xc)
2584 self.assertTrue(xc.flags[InvalidOperation])
2585 self.assertFalse(c.flags[InvalidOperation])
2586
2587 xc.clear_flags()
2588 self.assertEqual(D(2).exp(context=xc), 7)
2589 self.assertRaises(Overflow, D(8).exp, context=xc)
2590 self.assertTrue(xc.flags[Overflow])
2591 self.assertFalse(c.flags[Overflow])
2592
2593 xc.clear_flags()
2594 self.assertEqual(D(2).ln(context=xc), D('0.7'))
2595 self.assertRaises(InvalidOperation, D(-1).ln, context=xc)
2596 self.assertTrue(xc.flags[InvalidOperation])
2597 self.assertFalse(c.flags[InvalidOperation])
2598
2599 self.assertEqual(D(0).log10(context=xc), D('-inf'))
2600 self.assertEqual(D(-1).next_minus(context=xc), -2)
2601 self.assertEqual(D(-1).next_plus(context=xc), D('-0.9'))
2602 self.assertEqual(D("9.73").normalize(context=xc), D('1E+1'))
2603 self.assertEqual(D("9999").to_integral(context=xc), 9999)
2604 self.assertEqual(D("-2000").to_integral_exact(context=xc), -2000)
2605 self.assertEqual(D("123").to_integral_value(context=xc), 123)
2606 self.assertEqual(D("0.0625").sqrt(context=xc), D('0.2'))
2607
2608 self.assertEqual(D("0.0625").compare(context=xc, other=3), -1)
2609 xc.clear_flags()
2610 self.assertRaises(InvalidOperation,
2611 D("0").compare_signal, D('nan'), context=xc)
2612 self.assertTrue(xc.flags[InvalidOperation])
2613 self.assertFalse(c.flags[InvalidOperation])
2614 self.assertEqual(D("0.01").max(D('0.0101'), context=xc), D('0.0'))
2615 self.assertEqual(D("0.01").max(D('0.0101'), context=xc), D('0.0'))
2616 self.assertEqual(D("0.2").max_mag(D('-0.3'), context=xc),
2617 D('-0.3'))
2618 self.assertEqual(D("0.02").min(D('-0.03'), context=xc), D('-0.0'))
2619 self.assertEqual(D("0.02").min_mag(D('-0.03'), context=xc),
2620 D('0.0'))
2621 self.assertEqual(D("0.2").next_toward(D('-1'), context=xc), D('0.1'))
2622 xc.clear_flags()
2623 self.assertRaises(InvalidOperation,
2624 D("0.2").quantize, D('1e10'), context=xc)
2625 self.assertTrue(xc.flags[InvalidOperation])
2626 self.assertFalse(c.flags[InvalidOperation])
2627 self.assertEqual(D("9.99").remainder_near(D('1.5'), context=xc),
2628 D('-0.5'))
2629
2630 self.assertEqual(D("9.9").fma(third=D('0.9'), context=xc, other=7),
2631 D('7E+1'))
2632
2633 self.assertRaises(TypeError, D(1).is_canonical, context=xc)
2634 self.assertRaises(TypeError, D(1).is_finite, context=xc)
2635 self.assertRaises(TypeError, D(1).is_infinite, context=xc)
2636 self.assertRaises(TypeError, D(1).is_nan, context=xc)
2637 self.assertRaises(TypeError, D(1).is_qnan, context=xc)
2638 self.assertRaises(TypeError, D(1).is_snan, context=xc)
2639 self.assertRaises(TypeError, D(1).is_signed, context=xc)
2640 self.assertRaises(TypeError, D(1).is_zero, context=xc)
2641
2642 self.assertFalse(D("0.01").is_normal(context=xc))
2643 self.assertTrue(D("0.01").is_subnormal(context=xc))
2644
2645 self.assertRaises(TypeError, D(1).adjusted, context=xc)
2646 self.assertRaises(TypeError, D(1).conjugate, context=xc)
2647 self.assertRaises(TypeError, D(1).radix, context=xc)
2648
2649 self.assertEqual(D(-111).logb(context=xc), 2)
2650 self.assertEqual(D(0).logical_invert(context=xc), 1)
2651 self.assertEqual(D('0.01').number_class(context=xc), '+Subnormal')
2652 self.assertEqual(D('0.21').to_eng_string(context=xc), '0.21')
2653
2654 self.assertEqual(D('11').logical_and(D('10'), context=xc), 0)
2655 self.assertEqual(D('11').logical_or(D('10'), context=xc), 1)
2656 self.assertEqual(D('01').logical_xor(D('10'), context=xc), 1)
2657 self.assertEqual(D('23').rotate(1, context=xc), 3)
2658 self.assertEqual(D('23').rotate(1, context=xc), 3)
2659 xc.clear_flags()
2660 self.assertRaises(Overflow,
2661 D('23').scaleb, 1, context=xc)
2662 self.assertTrue(xc.flags[Overflow])
2663 self.assertFalse(c.flags[Overflow])
2664 self.assertEqual(D('23').shift(-1, context=xc), 0)
2665
2666 self.assertRaises(TypeError, D.from_float, 1.1, context=xc)
2667 self.assertRaises(TypeError, D(0).as_tuple, context=xc)
2668
Stefan Krah040e3112012-12-15 22:33:33 +01002669 self.assertEqual(D(1).canonical(), 1)
2670 self.assertRaises(TypeError, D("-1").copy_abs, context=xc)
2671 self.assertRaises(TypeError, D("-1").copy_negate, context=xc)
2672 self.assertRaises(TypeError, D(1).canonical, context="x")
2673 self.assertRaises(TypeError, D(1).canonical, xyz="x")
Stefan Krah1919b7e2012-03-21 18:25:23 +01002674
Stefan Krahb6405ef2012-03-23 14:46:48 +01002675 def test_exception_hierarchy(self):
2676
2677 decimal = self.decimal
2678 DecimalException = decimal.DecimalException
2679 InvalidOperation = decimal.InvalidOperation
2680 FloatOperation = decimal.FloatOperation
2681 DivisionByZero = decimal.DivisionByZero
2682 Overflow = decimal.Overflow
2683 Underflow = decimal.Underflow
2684 Subnormal = decimal.Subnormal
2685 Inexact = decimal.Inexact
2686 Rounded = decimal.Rounded
2687 Clamped = decimal.Clamped
2688
2689 self.assertTrue(issubclass(DecimalException, ArithmeticError))
2690
2691 self.assertTrue(issubclass(InvalidOperation, DecimalException))
2692 self.assertTrue(issubclass(FloatOperation, DecimalException))
2693 self.assertTrue(issubclass(FloatOperation, TypeError))
2694 self.assertTrue(issubclass(DivisionByZero, DecimalException))
2695 self.assertTrue(issubclass(DivisionByZero, ZeroDivisionError))
2696 self.assertTrue(issubclass(Overflow, Rounded))
2697 self.assertTrue(issubclass(Overflow, Inexact))
2698 self.assertTrue(issubclass(Overflow, DecimalException))
2699 self.assertTrue(issubclass(Underflow, Inexact))
2700 self.assertTrue(issubclass(Underflow, Rounded))
2701 self.assertTrue(issubclass(Underflow, Subnormal))
2702 self.assertTrue(issubclass(Underflow, DecimalException))
2703
2704 self.assertTrue(issubclass(Subnormal, DecimalException))
2705 self.assertTrue(issubclass(Inexact, DecimalException))
2706 self.assertTrue(issubclass(Rounded, DecimalException))
2707 self.assertTrue(issubclass(Clamped, DecimalException))
2708
2709 self.assertTrue(issubclass(decimal.ConversionSyntax, InvalidOperation))
2710 self.assertTrue(issubclass(decimal.DivisionImpossible, InvalidOperation))
2711 self.assertTrue(issubclass(decimal.DivisionUndefined, InvalidOperation))
2712 self.assertTrue(issubclass(decimal.DivisionUndefined, ZeroDivisionError))
2713 self.assertTrue(issubclass(decimal.InvalidContext, InvalidOperation))
2714
Stefan Krah1919b7e2012-03-21 18:25:23 +01002715class CPythonAPItests(PythonAPItests):
2716 decimal = C
2717class PyPythonAPItests(PythonAPItests):
2718 decimal = P
2719
2720class ContextAPItests(unittest.TestCase):
2721
Stefan Krah9a4ff432012-12-16 21:10:35 +01002722 def test_none_args(self):
2723 Context = self.decimal.Context
2724 InvalidOperation = self.decimal.InvalidOperation
2725 DivisionByZero = self.decimal.DivisionByZero
2726 Overflow = self.decimal.Overflow
Stefan Krah9a4ff432012-12-16 21:10:35 +01002727
2728 c1 = Context()
2729 c2 = Context(prec=None, rounding=None, Emax=None, Emin=None,
2730 capitals=None, clamp=None, flags=None, traps=None)
2731 for c in [c1, c2]:
2732 self.assertEqual(c.prec, 28)
2733 self.assertEqual(c.rounding, ROUND_HALF_EVEN)
2734 self.assertEqual(c.Emax, 999999)
2735 self.assertEqual(c.Emin, -999999)
2736 self.assertEqual(c.capitals, 1)
2737 self.assertEqual(c.clamp, 0)
2738 assert_signals(self, c, 'flags', [])
2739 assert_signals(self, c, 'traps', [InvalidOperation, DivisionByZero,
2740 Overflow])
2741
Stefan Krah59a4a932013-01-16 12:58:59 +01002742 @cpython_only
2743 def test_from_legacy_strings(self):
2744 import _testcapi
2745 c = self.decimal.Context()
2746
2747 for rnd in RoundingModes:
2748 c.rounding = _testcapi.unicode_legacy_string(rnd)
2749 self.assertEqual(c.rounding, rnd)
2750
2751 s = _testcapi.unicode_legacy_string('')
2752 self.assertRaises(TypeError, setattr, c, 'rounding', s)
2753
2754 s = _testcapi.unicode_legacy_string('ROUND_\x00UP')
2755 self.assertRaises(TypeError, setattr, c, 'rounding', s)
2756
Stefan Krah1919b7e2012-03-21 18:25:23 +01002757 def test_pickle(self):
2758
2759 Context = self.decimal.Context
2760
2761 savedecimal = sys.modules['decimal']
2762
2763 # Round trip
2764 sys.modules['decimal'] = self.decimal
2765 c = Context()
2766 e = pickle.loads(pickle.dumps(c))
2767
2768 self.assertEqual(c.prec, e.prec)
2769 self.assertEqual(c.Emin, e.Emin)
2770 self.assertEqual(c.Emax, e.Emax)
2771 self.assertEqual(c.rounding, e.rounding)
2772 self.assertEqual(c.capitals, e.capitals)
2773 self.assertEqual(c.clamp, e.clamp)
2774 self.assertEqual(c.flags, e.flags)
2775 self.assertEqual(c.traps, e.traps)
2776
2777 # Test interchangeability
2778 combinations = [(C, P), (P, C)] if C else [(P, P)]
2779 for dumper, loader in combinations:
Stefan Krah59a4a932013-01-16 12:58:59 +01002780 for ri, _ in enumerate(RoundingModes):
Stefan Krah1919b7e2012-03-21 18:25:23 +01002781 for fi, _ in enumerate(OrderedSignals[dumper]):
2782 for ti, _ in enumerate(OrderedSignals[dumper]):
2783
2784 prec = random.randrange(1, 100)
2785 emin = random.randrange(-100, 0)
2786 emax = random.randrange(1, 100)
2787 caps = random.randrange(2)
2788 clamp = random.randrange(2)
2789
2790 # One module dumps
2791 sys.modules['decimal'] = dumper
2792 c = dumper.Context(
2793 prec=prec, Emin=emin, Emax=emax,
Stefan Krah59a4a932013-01-16 12:58:59 +01002794 rounding=RoundingModes[ri],
Stefan Krah1919b7e2012-03-21 18:25:23 +01002795 capitals=caps, clamp=clamp,
2796 flags=OrderedSignals[dumper][:fi],
2797 traps=OrderedSignals[dumper][:ti]
2798 )
2799 s = pickle.dumps(c)
2800
2801 # The other module loads
2802 sys.modules['decimal'] = loader
2803 d = pickle.loads(s)
2804 self.assertIsInstance(d, loader.Context)
2805
2806 self.assertEqual(d.prec, prec)
2807 self.assertEqual(d.Emin, emin)
2808 self.assertEqual(d.Emax, emax)
Stefan Krah59a4a932013-01-16 12:58:59 +01002809 self.assertEqual(d.rounding, RoundingModes[ri])
Stefan Krah1919b7e2012-03-21 18:25:23 +01002810 self.assertEqual(d.capitals, caps)
2811 self.assertEqual(d.clamp, clamp)
2812 assert_signals(self, d, 'flags', OrderedSignals[loader][:fi])
2813 assert_signals(self, d, 'traps', OrderedSignals[loader][:ti])
2814
2815 sys.modules['decimal'] = savedecimal
2816
2817 def test_equality_with_other_types(self):
2818 Decimal = self.decimal.Decimal
2819
2820 self.assertIn(Decimal(10), ['a', 1.0, Decimal(10), (1,2), {}])
2821 self.assertNotIn(Decimal(10), ['a', 1.0, (1,2), {}])
2822
2823 def test_copy(self):
2824 # All copies should be deep
2825 Decimal = self.decimal.Decimal
2826 Context = self.decimal.Context
2827
2828 c = Context()
2829 d = c.copy()
2830 self.assertNotEqual(id(c), id(d))
2831 self.assertNotEqual(id(c.flags), id(d.flags))
2832 self.assertNotEqual(id(c.traps), id(d.traps))
2833 k1 = set(c.flags.keys())
2834 k2 = set(d.flags.keys())
2835 self.assertEqual(k1, k2)
2836 self.assertEqual(c.flags, d.flags)
2837
2838 def test__clamp(self):
2839 # In Python 3.2, the private attribute `_clamp` was made
2840 # public (issue 8540), with the old `_clamp` becoming a
2841 # property wrapping `clamp`. For the duration of Python 3.2
2842 # only, the attribute should be gettable/settable via both
2843 # `clamp` and `_clamp`; in Python 3.3, `_clamp` should be
2844 # removed.
2845 Context = self.decimal.Context
2846 c = Context()
2847 self.assertRaises(AttributeError, getattr, c, '_clamp')
2848
2849 def test_abs(self):
2850 Decimal = self.decimal.Decimal
2851 Context = self.decimal.Context
2852
2853 c = Context()
2854 d = c.abs(Decimal(-1))
2855 self.assertEqual(c.abs(-1), d)
2856 self.assertRaises(TypeError, c.abs, '-1')
2857
2858 def test_add(self):
2859 Decimal = self.decimal.Decimal
2860 Context = self.decimal.Context
2861
2862 c = Context()
2863 d = c.add(Decimal(1), Decimal(1))
2864 self.assertEqual(c.add(1, 1), d)
2865 self.assertEqual(c.add(Decimal(1), 1), d)
2866 self.assertEqual(c.add(1, Decimal(1)), d)
2867 self.assertRaises(TypeError, c.add, '1', 1)
2868 self.assertRaises(TypeError, c.add, 1, '1')
2869
2870 def test_compare(self):
2871 Decimal = self.decimal.Decimal
2872 Context = self.decimal.Context
2873
2874 c = Context()
2875 d = c.compare(Decimal(1), Decimal(1))
2876 self.assertEqual(c.compare(1, 1), d)
2877 self.assertEqual(c.compare(Decimal(1), 1), d)
2878 self.assertEqual(c.compare(1, Decimal(1)), d)
2879 self.assertRaises(TypeError, c.compare, '1', 1)
2880 self.assertRaises(TypeError, c.compare, 1, '1')
2881
2882 def test_compare_signal(self):
2883 Decimal = self.decimal.Decimal
2884 Context = self.decimal.Context
2885
2886 c = Context()
2887 d = c.compare_signal(Decimal(1), Decimal(1))
2888 self.assertEqual(c.compare_signal(1, 1), d)
2889 self.assertEqual(c.compare_signal(Decimal(1), 1), d)
2890 self.assertEqual(c.compare_signal(1, Decimal(1)), d)
2891 self.assertRaises(TypeError, c.compare_signal, '1', 1)
2892 self.assertRaises(TypeError, c.compare_signal, 1, '1')
2893
2894 def test_compare_total(self):
2895 Decimal = self.decimal.Decimal
2896 Context = self.decimal.Context
2897
2898 c = Context()
2899 d = c.compare_total(Decimal(1), Decimal(1))
2900 self.assertEqual(c.compare_total(1, 1), d)
2901 self.assertEqual(c.compare_total(Decimal(1), 1), d)
2902 self.assertEqual(c.compare_total(1, Decimal(1)), d)
2903 self.assertRaises(TypeError, c.compare_total, '1', 1)
2904 self.assertRaises(TypeError, c.compare_total, 1, '1')
2905
2906 def test_compare_total_mag(self):
2907 Decimal = self.decimal.Decimal
2908 Context = self.decimal.Context
2909
2910 c = Context()
2911 d = c.compare_total_mag(Decimal(1), Decimal(1))
2912 self.assertEqual(c.compare_total_mag(1, 1), d)
2913 self.assertEqual(c.compare_total_mag(Decimal(1), 1), d)
2914 self.assertEqual(c.compare_total_mag(1, Decimal(1)), d)
2915 self.assertRaises(TypeError, c.compare_total_mag, '1', 1)
2916 self.assertRaises(TypeError, c.compare_total_mag, 1, '1')
2917
2918 def test_copy_abs(self):
2919 Decimal = self.decimal.Decimal
2920 Context = self.decimal.Context
2921
2922 c = Context()
2923 d = c.copy_abs(Decimal(-1))
2924 self.assertEqual(c.copy_abs(-1), d)
2925 self.assertRaises(TypeError, c.copy_abs, '-1')
2926
2927 def test_copy_decimal(self):
2928 Decimal = self.decimal.Decimal
2929 Context = self.decimal.Context
2930
2931 c = Context()
2932 d = c.copy_decimal(Decimal(-1))
2933 self.assertEqual(c.copy_decimal(-1), d)
2934 self.assertRaises(TypeError, c.copy_decimal, '-1')
2935
2936 def test_copy_negate(self):
2937 Decimal = self.decimal.Decimal
2938 Context = self.decimal.Context
2939
2940 c = Context()
2941 d = c.copy_negate(Decimal(-1))
2942 self.assertEqual(c.copy_negate(-1), d)
2943 self.assertRaises(TypeError, c.copy_negate, '-1')
2944
2945 def test_copy_sign(self):
2946 Decimal = self.decimal.Decimal
2947 Context = self.decimal.Context
2948
2949 c = Context()
2950 d = c.copy_sign(Decimal(1), Decimal(-2))
2951 self.assertEqual(c.copy_sign(1, -2), d)
2952 self.assertEqual(c.copy_sign(Decimal(1), -2), d)
2953 self.assertEqual(c.copy_sign(1, Decimal(-2)), d)
2954 self.assertRaises(TypeError, c.copy_sign, '1', -2)
2955 self.assertRaises(TypeError, c.copy_sign, 1, '-2')
2956
2957 def test_divide(self):
2958 Decimal = self.decimal.Decimal
2959 Context = self.decimal.Context
2960
2961 c = Context()
2962 d = c.divide(Decimal(1), Decimal(2))
2963 self.assertEqual(c.divide(1, 2), d)
2964 self.assertEqual(c.divide(Decimal(1), 2), d)
2965 self.assertEqual(c.divide(1, Decimal(2)), d)
2966 self.assertRaises(TypeError, c.divide, '1', 2)
2967 self.assertRaises(TypeError, c.divide, 1, '2')
2968
2969 def test_divide_int(self):
2970 Decimal = self.decimal.Decimal
2971 Context = self.decimal.Context
2972
2973 c = Context()
2974 d = c.divide_int(Decimal(1), Decimal(2))
2975 self.assertEqual(c.divide_int(1, 2), d)
2976 self.assertEqual(c.divide_int(Decimal(1), 2), d)
2977 self.assertEqual(c.divide_int(1, Decimal(2)), d)
2978 self.assertRaises(TypeError, c.divide_int, '1', 2)
2979 self.assertRaises(TypeError, c.divide_int, 1, '2')
2980
2981 def test_divmod(self):
2982 Decimal = self.decimal.Decimal
2983 Context = self.decimal.Context
2984
2985 c = Context()
2986 d = c.divmod(Decimal(1), Decimal(2))
2987 self.assertEqual(c.divmod(1, 2), d)
2988 self.assertEqual(c.divmod(Decimal(1), 2), d)
2989 self.assertEqual(c.divmod(1, Decimal(2)), d)
2990 self.assertRaises(TypeError, c.divmod, '1', 2)
2991 self.assertRaises(TypeError, c.divmod, 1, '2')
2992
2993 def test_exp(self):
2994 Decimal = self.decimal.Decimal
2995 Context = self.decimal.Context
2996
2997 c = Context()
2998 d = c.exp(Decimal(10))
2999 self.assertEqual(c.exp(10), d)
3000 self.assertRaises(TypeError, c.exp, '10')
3001
3002 def test_fma(self):
3003 Decimal = self.decimal.Decimal
3004 Context = self.decimal.Context
3005
3006 c = Context()
3007 d = c.fma(Decimal(2), Decimal(3), Decimal(4))
3008 self.assertEqual(c.fma(2, 3, 4), d)
3009 self.assertEqual(c.fma(Decimal(2), 3, 4), d)
3010 self.assertEqual(c.fma(2, Decimal(3), 4), d)
3011 self.assertEqual(c.fma(2, 3, Decimal(4)), d)
3012 self.assertEqual(c.fma(Decimal(2), Decimal(3), 4), d)
3013 self.assertRaises(TypeError, c.fma, '2', 3, 4)
3014 self.assertRaises(TypeError, c.fma, 2, '3', 4)
3015 self.assertRaises(TypeError, c.fma, 2, 3, '4')
3016
3017 # Issue 12079 for Context.fma ...
3018 self.assertRaises(TypeError, c.fma,
3019 Decimal('Infinity'), Decimal(0), "not a decimal")
3020 self.assertRaises(TypeError, c.fma,
3021 Decimal(1), Decimal('snan'), 1.222)
3022 # ... and for Decimal.fma.
3023 self.assertRaises(TypeError, Decimal('Infinity').fma,
3024 Decimal(0), "not a decimal")
3025 self.assertRaises(TypeError, Decimal(1).fma,
3026 Decimal('snan'), 1.222)
3027
3028 def test_is_finite(self):
3029 Decimal = self.decimal.Decimal
3030 Context = self.decimal.Context
3031
3032 c = Context()
3033 d = c.is_finite(Decimal(10))
3034 self.assertEqual(c.is_finite(10), d)
3035 self.assertRaises(TypeError, c.is_finite, '10')
3036
3037 def test_is_infinite(self):
3038 Decimal = self.decimal.Decimal
3039 Context = self.decimal.Context
3040
3041 c = Context()
3042 d = c.is_infinite(Decimal(10))
3043 self.assertEqual(c.is_infinite(10), d)
3044 self.assertRaises(TypeError, c.is_infinite, '10')
3045
3046 def test_is_nan(self):
3047 Decimal = self.decimal.Decimal
3048 Context = self.decimal.Context
3049
3050 c = Context()
3051 d = c.is_nan(Decimal(10))
3052 self.assertEqual(c.is_nan(10), d)
3053 self.assertRaises(TypeError, c.is_nan, '10')
3054
3055 def test_is_normal(self):
3056 Decimal = self.decimal.Decimal
3057 Context = self.decimal.Context
3058
3059 c = Context()
3060 d = c.is_normal(Decimal(10))
3061 self.assertEqual(c.is_normal(10), d)
3062 self.assertRaises(TypeError, c.is_normal, '10')
3063
3064 def test_is_qnan(self):
3065 Decimal = self.decimal.Decimal
3066 Context = self.decimal.Context
3067
3068 c = Context()
3069 d = c.is_qnan(Decimal(10))
3070 self.assertEqual(c.is_qnan(10), d)
3071 self.assertRaises(TypeError, c.is_qnan, '10')
3072
3073 def test_is_signed(self):
3074 Decimal = self.decimal.Decimal
3075 Context = self.decimal.Context
3076
3077 c = Context()
3078 d = c.is_signed(Decimal(10))
3079 self.assertEqual(c.is_signed(10), d)
3080 self.assertRaises(TypeError, c.is_signed, '10')
3081
3082 def test_is_snan(self):
3083 Decimal = self.decimal.Decimal
3084 Context = self.decimal.Context
3085
3086 c = Context()
3087 d = c.is_snan(Decimal(10))
3088 self.assertEqual(c.is_snan(10), d)
3089 self.assertRaises(TypeError, c.is_snan, '10')
3090
3091 def test_is_subnormal(self):
3092 Decimal = self.decimal.Decimal
3093 Context = self.decimal.Context
3094
3095 c = Context()
3096 d = c.is_subnormal(Decimal(10))
3097 self.assertEqual(c.is_subnormal(10), d)
3098 self.assertRaises(TypeError, c.is_subnormal, '10')
3099
3100 def test_is_zero(self):
3101 Decimal = self.decimal.Decimal
3102 Context = self.decimal.Context
3103
3104 c = Context()
3105 d = c.is_zero(Decimal(10))
3106 self.assertEqual(c.is_zero(10), d)
3107 self.assertRaises(TypeError, c.is_zero, '10')
3108
3109 def test_ln(self):
3110 Decimal = self.decimal.Decimal
3111 Context = self.decimal.Context
3112
3113 c = Context()
3114 d = c.ln(Decimal(10))
3115 self.assertEqual(c.ln(10), d)
3116 self.assertRaises(TypeError, c.ln, '10')
3117
3118 def test_log10(self):
3119 Decimal = self.decimal.Decimal
3120 Context = self.decimal.Context
3121
3122 c = Context()
3123 d = c.log10(Decimal(10))
3124 self.assertEqual(c.log10(10), d)
3125 self.assertRaises(TypeError, c.log10, '10')
3126
3127 def test_logb(self):
3128 Decimal = self.decimal.Decimal
3129 Context = self.decimal.Context
3130
3131 c = Context()
3132 d = c.logb(Decimal(10))
3133 self.assertEqual(c.logb(10), d)
3134 self.assertRaises(TypeError, c.logb, '10')
3135
3136 def test_logical_and(self):
3137 Decimal = self.decimal.Decimal
3138 Context = self.decimal.Context
3139
3140 c = Context()
3141 d = c.logical_and(Decimal(1), Decimal(1))
3142 self.assertEqual(c.logical_and(1, 1), d)
3143 self.assertEqual(c.logical_and(Decimal(1), 1), d)
3144 self.assertEqual(c.logical_and(1, Decimal(1)), d)
3145 self.assertRaises(TypeError, c.logical_and, '1', 1)
3146 self.assertRaises(TypeError, c.logical_and, 1, '1')
3147
3148 def test_logical_invert(self):
3149 Decimal = self.decimal.Decimal
3150 Context = self.decimal.Context
3151
3152 c = Context()
3153 d = c.logical_invert(Decimal(1000))
3154 self.assertEqual(c.logical_invert(1000), d)
3155 self.assertRaises(TypeError, c.logical_invert, '1000')
3156
3157 def test_logical_or(self):
3158 Decimal = self.decimal.Decimal
3159 Context = self.decimal.Context
3160
3161 c = Context()
3162 d = c.logical_or(Decimal(1), Decimal(1))
3163 self.assertEqual(c.logical_or(1, 1), d)
3164 self.assertEqual(c.logical_or(Decimal(1), 1), d)
3165 self.assertEqual(c.logical_or(1, Decimal(1)), d)
3166 self.assertRaises(TypeError, c.logical_or, '1', 1)
3167 self.assertRaises(TypeError, c.logical_or, 1, '1')
3168
3169 def test_logical_xor(self):
3170 Decimal = self.decimal.Decimal
3171 Context = self.decimal.Context
3172
3173 c = Context()
3174 d = c.logical_xor(Decimal(1), Decimal(1))
3175 self.assertEqual(c.logical_xor(1, 1), d)
3176 self.assertEqual(c.logical_xor(Decimal(1), 1), d)
3177 self.assertEqual(c.logical_xor(1, Decimal(1)), d)
3178 self.assertRaises(TypeError, c.logical_xor, '1', 1)
3179 self.assertRaises(TypeError, c.logical_xor, 1, '1')
3180
3181 def test_max(self):
3182 Decimal = self.decimal.Decimal
3183 Context = self.decimal.Context
3184
3185 c = Context()
3186 d = c.max(Decimal(1), Decimal(2))
3187 self.assertEqual(c.max(1, 2), d)
3188 self.assertEqual(c.max(Decimal(1), 2), d)
3189 self.assertEqual(c.max(1, Decimal(2)), d)
3190 self.assertRaises(TypeError, c.max, '1', 2)
3191 self.assertRaises(TypeError, c.max, 1, '2')
3192
3193 def test_max_mag(self):
3194 Decimal = self.decimal.Decimal
3195 Context = self.decimal.Context
3196
3197 c = Context()
3198 d = c.max_mag(Decimal(1), Decimal(2))
3199 self.assertEqual(c.max_mag(1, 2), d)
3200 self.assertEqual(c.max_mag(Decimal(1), 2), d)
3201 self.assertEqual(c.max_mag(1, Decimal(2)), d)
3202 self.assertRaises(TypeError, c.max_mag, '1', 2)
3203 self.assertRaises(TypeError, c.max_mag, 1, '2')
3204
3205 def test_min(self):
3206 Decimal = self.decimal.Decimal
3207 Context = self.decimal.Context
3208
3209 c = Context()
3210 d = c.min(Decimal(1), Decimal(2))
3211 self.assertEqual(c.min(1, 2), d)
3212 self.assertEqual(c.min(Decimal(1), 2), d)
3213 self.assertEqual(c.min(1, Decimal(2)), d)
3214 self.assertRaises(TypeError, c.min, '1', 2)
3215 self.assertRaises(TypeError, c.min, 1, '2')
3216
3217 def test_min_mag(self):
3218 Decimal = self.decimal.Decimal
3219 Context = self.decimal.Context
3220
3221 c = Context()
3222 d = c.min_mag(Decimal(1), Decimal(2))
3223 self.assertEqual(c.min_mag(1, 2), d)
3224 self.assertEqual(c.min_mag(Decimal(1), 2), d)
3225 self.assertEqual(c.min_mag(1, Decimal(2)), d)
3226 self.assertRaises(TypeError, c.min_mag, '1', 2)
3227 self.assertRaises(TypeError, c.min_mag, 1, '2')
3228
3229 def test_minus(self):
3230 Decimal = self.decimal.Decimal
3231 Context = self.decimal.Context
3232
3233 c = Context()
3234 d = c.minus(Decimal(10))
3235 self.assertEqual(c.minus(10), d)
3236 self.assertRaises(TypeError, c.minus, '10')
3237
3238 def test_multiply(self):
3239 Decimal = self.decimal.Decimal
3240 Context = self.decimal.Context
3241
3242 c = Context()
3243 d = c.multiply(Decimal(1), Decimal(2))
3244 self.assertEqual(c.multiply(1, 2), d)
3245 self.assertEqual(c.multiply(Decimal(1), 2), d)
3246 self.assertEqual(c.multiply(1, Decimal(2)), d)
3247 self.assertRaises(TypeError, c.multiply, '1', 2)
3248 self.assertRaises(TypeError, c.multiply, 1, '2')
3249
3250 def test_next_minus(self):
3251 Decimal = self.decimal.Decimal
3252 Context = self.decimal.Context
3253
3254 c = Context()
3255 d = c.next_minus(Decimal(10))
3256 self.assertEqual(c.next_minus(10), d)
3257 self.assertRaises(TypeError, c.next_minus, '10')
3258
3259 def test_next_plus(self):
3260 Decimal = self.decimal.Decimal
3261 Context = self.decimal.Context
3262
3263 c = Context()
3264 d = c.next_plus(Decimal(10))
3265 self.assertEqual(c.next_plus(10), d)
3266 self.assertRaises(TypeError, c.next_plus, '10')
3267
3268 def test_next_toward(self):
3269 Decimal = self.decimal.Decimal
3270 Context = self.decimal.Context
3271
3272 c = Context()
3273 d = c.next_toward(Decimal(1), Decimal(2))
3274 self.assertEqual(c.next_toward(1, 2), d)
3275 self.assertEqual(c.next_toward(Decimal(1), 2), d)
3276 self.assertEqual(c.next_toward(1, Decimal(2)), d)
3277 self.assertRaises(TypeError, c.next_toward, '1', 2)
3278 self.assertRaises(TypeError, c.next_toward, 1, '2')
3279
3280 def test_normalize(self):
3281 Decimal = self.decimal.Decimal
3282 Context = self.decimal.Context
3283
3284 c = Context()
3285 d = c.normalize(Decimal(10))
3286 self.assertEqual(c.normalize(10), d)
3287 self.assertRaises(TypeError, c.normalize, '10')
3288
3289 def test_number_class(self):
3290 Decimal = self.decimal.Decimal
3291 Context = self.decimal.Context
3292
3293 c = Context()
3294 self.assertEqual(c.number_class(123), c.number_class(Decimal(123)))
3295 self.assertEqual(c.number_class(0), c.number_class(Decimal(0)))
3296 self.assertEqual(c.number_class(-45), c.number_class(Decimal(-45)))
3297
3298 def test_plus(self):
3299 Decimal = self.decimal.Decimal
3300 Context = self.decimal.Context
3301
3302 c = Context()
3303 d = c.plus(Decimal(10))
3304 self.assertEqual(c.plus(10), d)
3305 self.assertRaises(TypeError, c.plus, '10')
3306
3307 def test_power(self):
3308 Decimal = self.decimal.Decimal
3309 Context = self.decimal.Context
3310
3311 c = Context()
3312 d = c.power(Decimal(1), Decimal(4))
3313 self.assertEqual(c.power(1, 4), d)
3314 self.assertEqual(c.power(Decimal(1), 4), d)
3315 self.assertEqual(c.power(1, Decimal(4)), d)
3316 self.assertEqual(c.power(Decimal(1), Decimal(4)), d)
3317 self.assertRaises(TypeError, c.power, '1', 4)
3318 self.assertRaises(TypeError, c.power, 1, '4')
3319 self.assertEqual(c.power(modulo=5, b=8, a=2), 1)
3320
3321 def test_quantize(self):
3322 Decimal = self.decimal.Decimal
3323 Context = self.decimal.Context
3324
3325 c = Context()
3326 d = c.quantize(Decimal(1), Decimal(2))
3327 self.assertEqual(c.quantize(1, 2), d)
3328 self.assertEqual(c.quantize(Decimal(1), 2), d)
3329 self.assertEqual(c.quantize(1, Decimal(2)), d)
3330 self.assertRaises(TypeError, c.quantize, '1', 2)
3331 self.assertRaises(TypeError, c.quantize, 1, '2')
3332
3333 def test_remainder(self):
3334 Decimal = self.decimal.Decimal
3335 Context = self.decimal.Context
3336
3337 c = Context()
3338 d = c.remainder(Decimal(1), Decimal(2))
3339 self.assertEqual(c.remainder(1, 2), d)
3340 self.assertEqual(c.remainder(Decimal(1), 2), d)
3341 self.assertEqual(c.remainder(1, Decimal(2)), d)
3342 self.assertRaises(TypeError, c.remainder, '1', 2)
3343 self.assertRaises(TypeError, c.remainder, 1, '2')
3344
3345 def test_remainder_near(self):
3346 Decimal = self.decimal.Decimal
3347 Context = self.decimal.Context
3348
3349 c = Context()
3350 d = c.remainder_near(Decimal(1), Decimal(2))
3351 self.assertEqual(c.remainder_near(1, 2), d)
3352 self.assertEqual(c.remainder_near(Decimal(1), 2), d)
3353 self.assertEqual(c.remainder_near(1, Decimal(2)), d)
3354 self.assertRaises(TypeError, c.remainder_near, '1', 2)
3355 self.assertRaises(TypeError, c.remainder_near, 1, '2')
3356
3357 def test_rotate(self):
3358 Decimal = self.decimal.Decimal
3359 Context = self.decimal.Context
3360
3361 c = Context()
3362 d = c.rotate(Decimal(1), Decimal(2))
3363 self.assertEqual(c.rotate(1, 2), d)
3364 self.assertEqual(c.rotate(Decimal(1), 2), d)
3365 self.assertEqual(c.rotate(1, Decimal(2)), d)
3366 self.assertRaises(TypeError, c.rotate, '1', 2)
3367 self.assertRaises(TypeError, c.rotate, 1, '2')
3368
3369 def test_sqrt(self):
3370 Decimal = self.decimal.Decimal
3371 Context = self.decimal.Context
3372
3373 c = Context()
3374 d = c.sqrt(Decimal(10))
3375 self.assertEqual(c.sqrt(10), d)
3376 self.assertRaises(TypeError, c.sqrt, '10')
3377
3378 def test_same_quantum(self):
3379 Decimal = self.decimal.Decimal
3380 Context = self.decimal.Context
3381
3382 c = Context()
3383 d = c.same_quantum(Decimal(1), Decimal(2))
3384 self.assertEqual(c.same_quantum(1, 2), d)
3385 self.assertEqual(c.same_quantum(Decimal(1), 2), d)
3386 self.assertEqual(c.same_quantum(1, Decimal(2)), d)
3387 self.assertRaises(TypeError, c.same_quantum, '1', 2)
3388 self.assertRaises(TypeError, c.same_quantum, 1, '2')
3389
3390 def test_scaleb(self):
3391 Decimal = self.decimal.Decimal
3392 Context = self.decimal.Context
3393
3394 c = Context()
3395 d = c.scaleb(Decimal(1), Decimal(2))
3396 self.assertEqual(c.scaleb(1, 2), d)
3397 self.assertEqual(c.scaleb(Decimal(1), 2), d)
3398 self.assertEqual(c.scaleb(1, Decimal(2)), d)
3399 self.assertRaises(TypeError, c.scaleb, '1', 2)
3400 self.assertRaises(TypeError, c.scaleb, 1, '2')
3401
3402 def test_shift(self):
3403 Decimal = self.decimal.Decimal
3404 Context = self.decimal.Context
3405
3406 c = Context()
3407 d = c.shift(Decimal(1), Decimal(2))
3408 self.assertEqual(c.shift(1, 2), d)
3409 self.assertEqual(c.shift(Decimal(1), 2), d)
3410 self.assertEqual(c.shift(1, Decimal(2)), d)
3411 self.assertRaises(TypeError, c.shift, '1', 2)
3412 self.assertRaises(TypeError, c.shift, 1, '2')
3413
3414 def test_subtract(self):
3415 Decimal = self.decimal.Decimal
3416 Context = self.decimal.Context
3417
3418 c = Context()
3419 d = c.subtract(Decimal(1), Decimal(2))
3420 self.assertEqual(c.subtract(1, 2), d)
3421 self.assertEqual(c.subtract(Decimal(1), 2), d)
3422 self.assertEqual(c.subtract(1, Decimal(2)), d)
3423 self.assertRaises(TypeError, c.subtract, '1', 2)
3424 self.assertRaises(TypeError, c.subtract, 1, '2')
3425
3426 def test_to_eng_string(self):
3427 Decimal = self.decimal.Decimal
3428 Context = self.decimal.Context
3429
3430 c = Context()
3431 d = c.to_eng_string(Decimal(10))
3432 self.assertEqual(c.to_eng_string(10), d)
3433 self.assertRaises(TypeError, c.to_eng_string, '10')
3434
3435 def test_to_sci_string(self):
3436 Decimal = self.decimal.Decimal
3437 Context = self.decimal.Context
3438
3439 c = Context()
3440 d = c.to_sci_string(Decimal(10))
3441 self.assertEqual(c.to_sci_string(10), d)
3442 self.assertRaises(TypeError, c.to_sci_string, '10')
3443
3444 def test_to_integral_exact(self):
3445 Decimal = self.decimal.Decimal
3446 Context = self.decimal.Context
3447
3448 c = Context()
3449 d = c.to_integral_exact(Decimal(10))
3450 self.assertEqual(c.to_integral_exact(10), d)
3451 self.assertRaises(TypeError, c.to_integral_exact, '10')
3452
3453 def test_to_integral_value(self):
3454 Decimal = self.decimal.Decimal
3455 Context = self.decimal.Context
3456
3457 c = Context()
3458 d = c.to_integral_value(Decimal(10))
3459 self.assertEqual(c.to_integral_value(10), d)
3460 self.assertRaises(TypeError, c.to_integral_value, '10')
3461 self.assertRaises(TypeError, c.to_integral_value, 10, 'x')
3462
3463class CContextAPItests(ContextAPItests):
3464 decimal = C
3465class PyContextAPItests(ContextAPItests):
3466 decimal = P
3467
3468class ContextWithStatement(unittest.TestCase):
3469 # Can't do these as docstrings until Python 2.6
3470 # as doctest can't handle __future__ statements
3471
3472 def test_localcontext(self):
3473 # Use a copy of the current context in the block
3474 getcontext = self.decimal.getcontext
3475 localcontext = self.decimal.localcontext
3476
3477 orig_ctx = getcontext()
3478 with localcontext() as enter_ctx:
3479 set_ctx = getcontext()
3480 final_ctx = getcontext()
3481 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
3482 self.assertIsNot(orig_ctx, set_ctx, 'did not copy the context')
3483 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
3484
3485 def test_localcontextarg(self):
3486 # Use a copy of the supplied context in the block
3487 Context = self.decimal.Context
3488 getcontext = self.decimal.getcontext
3489 localcontext = self.decimal.localcontext
3490
3491 localcontext = self.decimal.localcontext
3492 orig_ctx = getcontext()
3493 new_ctx = Context(prec=42)
3494 with localcontext(new_ctx) as enter_ctx:
3495 set_ctx = getcontext()
3496 final_ctx = getcontext()
3497 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
3498 self.assertEqual(set_ctx.prec, new_ctx.prec, 'did not set correct context')
3499 self.assertIsNot(new_ctx, set_ctx, 'did not copy the context')
3500 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
3501
3502 def test_nested_with_statements(self):
3503 # Use a copy of the supplied context in the block
3504 Decimal = self.decimal.Decimal
3505 Context = self.decimal.Context
3506 getcontext = self.decimal.getcontext
3507 localcontext = self.decimal.localcontext
3508 Clamped = self.decimal.Clamped
3509 Overflow = self.decimal.Overflow
3510
3511 orig_ctx = getcontext()
3512 orig_ctx.clear_flags()
3513 new_ctx = Context(Emax=384)
3514 with localcontext() as c1:
3515 self.assertEqual(c1.flags, orig_ctx.flags)
3516 self.assertEqual(c1.traps, orig_ctx.traps)
3517 c1.traps[Clamped] = True
3518 c1.Emin = -383
3519 self.assertNotEqual(orig_ctx.Emin, -383)
3520 self.assertRaises(Clamped, c1.create_decimal, '0e-999')
3521 self.assertTrue(c1.flags[Clamped])
3522 with localcontext(new_ctx) as c2:
3523 self.assertEqual(c2.flags, new_ctx.flags)
3524 self.assertEqual(c2.traps, new_ctx.traps)
3525 self.assertRaises(Overflow, c2.power, Decimal('3.4e200'), 2)
3526 self.assertFalse(c2.flags[Clamped])
3527 self.assertTrue(c2.flags[Overflow])
3528 del c2
3529 self.assertFalse(c1.flags[Overflow])
3530 del c1
3531 self.assertNotEqual(orig_ctx.Emin, -383)
3532 self.assertFalse(orig_ctx.flags[Clamped])
3533 self.assertFalse(orig_ctx.flags[Overflow])
3534 self.assertFalse(new_ctx.flags[Clamped])
3535 self.assertFalse(new_ctx.flags[Overflow])
3536
3537 def test_with_statements_gc1(self):
3538 localcontext = self.decimal.localcontext
3539
3540 with localcontext() as c1:
3541 del c1
3542 with localcontext() as c2:
3543 del c2
3544 with localcontext() as c3:
3545 del c3
3546 with localcontext() as c4:
3547 del c4
3548
3549 def test_with_statements_gc2(self):
3550 localcontext = self.decimal.localcontext
3551
3552 with localcontext() as c1:
3553 with localcontext(c1) as c2:
3554 del c1
3555 with localcontext(c2) as c3:
3556 del c2
3557 with localcontext(c3) as c4:
3558 del c3
3559 del c4
3560
3561 def test_with_statements_gc3(self):
3562 Context = self.decimal.Context
3563 localcontext = self.decimal.localcontext
3564 getcontext = self.decimal.getcontext
3565 setcontext = self.decimal.setcontext
3566
3567 with localcontext() as c1:
3568 del c1
3569 n1 = Context(prec=1)
3570 setcontext(n1)
3571 with localcontext(n1) as c2:
3572 del n1
3573 self.assertEqual(c2.prec, 1)
3574 del c2
3575 n2 = Context(prec=2)
3576 setcontext(n2)
3577 del n2
3578 self.assertEqual(getcontext().prec, 2)
3579 n3 = Context(prec=3)
3580 setcontext(n3)
3581 self.assertEqual(getcontext().prec, 3)
3582 with localcontext(n3) as c3:
3583 del n3
3584 self.assertEqual(c3.prec, 3)
3585 del c3
3586 n4 = Context(prec=4)
3587 setcontext(n4)
3588 del n4
3589 self.assertEqual(getcontext().prec, 4)
3590 with localcontext() as c4:
3591 self.assertEqual(c4.prec, 4)
3592 del c4
3593
3594class CContextWithStatement(ContextWithStatement):
3595 decimal = C
3596class PyContextWithStatement(ContextWithStatement):
3597 decimal = P
3598
3599class ContextFlags(unittest.TestCase):
3600
3601 def test_flags_irrelevant(self):
3602 # check that the result (numeric result + flags raised) of an
3603 # arithmetic operation doesn't depend on the current flags
3604 Decimal = self.decimal.Decimal
3605 Context = self.decimal.Context
3606 Inexact = self.decimal.Inexact
3607 Rounded = self.decimal.Rounded
3608 Underflow = self.decimal.Underflow
3609 Clamped = self.decimal.Clamped
3610 Subnormal = self.decimal.Subnormal
Stefan Krah1919b7e2012-03-21 18:25:23 +01003611
3612 def raise_error(context, flag):
3613 if self.decimal == C:
3614 context.flags[flag] = True
3615 if context.traps[flag]:
3616 raise flag
3617 else:
3618 context._raise_error(flag)
3619
3620 context = Context(prec=9, Emin = -425000000, Emax = 425000000,
3621 rounding=ROUND_HALF_EVEN, traps=[], flags=[])
3622
3623 # operations that raise various flags, in the form (function, arglist)
3624 operations = [
3625 (context._apply, [Decimal("100E-425000010")]),
3626 (context.sqrt, [Decimal(2)]),
3627 (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]),
3628 (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]),
3629 (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]),
3630 ]
3631
3632 # try various flags individually, then a whole lot at once
3633 flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal],
3634 [Inexact, Rounded, Underflow, Clamped, Subnormal]]
3635
3636 for fn, args in operations:
3637 # find answer and flags raised using a clean context
3638 context.clear_flags()
3639 ans = fn(*args)
3640 flags = [k for k, v in context.flags.items() if v]
3641
3642 for extra_flags in flagsets:
3643 # set flags, before calling operation
3644 context.clear_flags()
3645 for flag in extra_flags:
3646 raise_error(context, flag)
3647 new_ans = fn(*args)
3648
3649 # flags that we expect to be set after the operation
3650 expected_flags = list(flags)
3651 for flag in extra_flags:
3652 if flag not in expected_flags:
3653 expected_flags.append(flag)
3654 expected_flags.sort(key=id)
3655
3656 # flags we actually got
3657 new_flags = [k for k,v in context.flags.items() if v]
3658 new_flags.sort(key=id)
3659
3660 self.assertEqual(ans, new_ans,
3661 "operation produces different answers depending on flags set: " +
3662 "expected %s, got %s." % (ans, new_ans))
3663 self.assertEqual(new_flags, expected_flags,
3664 "operation raises different flags depending on flags set: " +
3665 "expected %s, got %s" % (expected_flags, new_flags))
3666
3667 def test_flag_comparisons(self):
3668 Context = self.decimal.Context
3669 Inexact = self.decimal.Inexact
3670 Rounded = self.decimal.Rounded
3671
3672 c = Context()
3673
3674 # Valid SignalDict
3675 self.assertNotEqual(c.flags, c.traps)
3676 self.assertNotEqual(c.traps, c.flags)
3677
3678 c.flags = c.traps
3679 self.assertEqual(c.flags, c.traps)
3680 self.assertEqual(c.traps, c.flags)
3681
3682 c.flags[Rounded] = True
3683 c.traps = c.flags
3684 self.assertEqual(c.flags, c.traps)
3685 self.assertEqual(c.traps, c.flags)
3686
3687 d = {}
3688 d.update(c.flags)
3689 self.assertEqual(d, c.flags)
3690 self.assertEqual(c.flags, d)
3691
3692 d[Inexact] = True
3693 self.assertNotEqual(d, c.flags)
3694 self.assertNotEqual(c.flags, d)
3695
3696 # Invalid SignalDict
3697 d = {Inexact:False}
3698 self.assertNotEqual(d, c.flags)
3699 self.assertNotEqual(c.flags, d)
3700
3701 d = ["xyz"]
3702 self.assertNotEqual(d, c.flags)
3703 self.assertNotEqual(c.flags, d)
3704
3705 @requires_IEEE_754
3706 def test_float_operation(self):
3707 Decimal = self.decimal.Decimal
3708 FloatOperation = self.decimal.FloatOperation
3709 localcontext = self.decimal.localcontext
3710
3711 with localcontext() as c:
3712 ##### trap is off by default
3713 self.assertFalse(c.traps[FloatOperation])
3714
3715 # implicit conversion sets the flag
3716 c.clear_flags()
3717 self.assertEqual(Decimal(7.5), 7.5)
3718 self.assertTrue(c.flags[FloatOperation])
3719
3720 c.clear_flags()
3721 self.assertEqual(c.create_decimal(7.5), 7.5)
3722 self.assertTrue(c.flags[FloatOperation])
3723
3724 # explicit conversion does not set the flag
3725 c.clear_flags()
3726 x = Decimal.from_float(7.5)
3727 self.assertFalse(c.flags[FloatOperation])
3728 # comparison sets the flag
3729 self.assertEqual(x, 7.5)
3730 self.assertTrue(c.flags[FloatOperation])
3731
3732 c.clear_flags()
3733 x = c.create_decimal_from_float(7.5)
3734 self.assertFalse(c.flags[FloatOperation])
3735 self.assertEqual(x, 7.5)
3736 self.assertTrue(c.flags[FloatOperation])
3737
3738 ##### set the trap
3739 c.traps[FloatOperation] = True
3740
3741 # implicit conversion raises
3742 c.clear_flags()
3743 self.assertRaises(FloatOperation, Decimal, 7.5)
3744 self.assertTrue(c.flags[FloatOperation])
3745
3746 c.clear_flags()
3747 self.assertRaises(FloatOperation, c.create_decimal, 7.5)
3748 self.assertTrue(c.flags[FloatOperation])
3749
3750 # explicit conversion is silent
3751 c.clear_flags()
3752 x = Decimal.from_float(7.5)
3753 self.assertFalse(c.flags[FloatOperation])
3754
3755 c.clear_flags()
3756 x = c.create_decimal_from_float(7.5)
3757 self.assertFalse(c.flags[FloatOperation])
3758
3759 def test_float_comparison(self):
3760 Decimal = self.decimal.Decimal
3761 Context = self.decimal.Context
3762 FloatOperation = self.decimal.FloatOperation
3763 localcontext = self.decimal.localcontext
3764
3765 def assert_attr(a, b, attr, context, signal=None):
3766 context.clear_flags()
3767 f = getattr(a, attr)
3768 if signal == FloatOperation:
3769 self.assertRaises(signal, f, b)
3770 else:
3771 self.assertIs(f(b), True)
3772 self.assertTrue(context.flags[FloatOperation])
3773
3774 small_d = Decimal('0.25')
3775 big_d = Decimal('3.0')
3776 small_f = 0.25
3777 big_f = 3.0
3778
3779 zero_d = Decimal('0.0')
3780 neg_zero_d = Decimal('-0.0')
3781 zero_f = 0.0
3782 neg_zero_f = -0.0
3783
3784 inf_d = Decimal('Infinity')
3785 neg_inf_d = Decimal('-Infinity')
3786 inf_f = float('inf')
3787 neg_inf_f = float('-inf')
3788
3789 def doit(c, signal=None):
3790 # Order
3791 for attr in '__lt__', '__le__':
3792 assert_attr(small_d, big_f, attr, c, signal)
3793
3794 for attr in '__gt__', '__ge__':
3795 assert_attr(big_d, small_f, attr, c, signal)
3796
3797 # Equality
3798 assert_attr(small_d, small_f, '__eq__', c, None)
3799
3800 assert_attr(neg_zero_d, neg_zero_f, '__eq__', c, None)
3801 assert_attr(neg_zero_d, zero_f, '__eq__', c, None)
3802
3803 assert_attr(zero_d, neg_zero_f, '__eq__', c, None)
3804 assert_attr(zero_d, zero_f, '__eq__', c, None)
3805
3806 assert_attr(neg_inf_d, neg_inf_f, '__eq__', c, None)
3807 assert_attr(inf_d, inf_f, '__eq__', c, None)
3808
3809 # Inequality
3810 assert_attr(small_d, big_f, '__ne__', c, None)
3811
3812 assert_attr(Decimal('0.1'), 0.1, '__ne__', c, None)
3813
3814 assert_attr(neg_inf_d, inf_f, '__ne__', c, None)
3815 assert_attr(inf_d, neg_inf_f, '__ne__', c, None)
3816
3817 assert_attr(Decimal('NaN'), float('nan'), '__ne__', c, None)
3818
3819 def test_containers(c, signal=None):
3820 c.clear_flags()
3821 s = set([100.0, Decimal('100.0')])
3822 self.assertEqual(len(s), 1)
3823 self.assertTrue(c.flags[FloatOperation])
3824
3825 c.clear_flags()
3826 if signal:
3827 self.assertRaises(signal, sorted, [1.0, Decimal('10.0')])
3828 else:
3829 s = sorted([10.0, Decimal('10.0')])
3830 self.assertTrue(c.flags[FloatOperation])
3831
3832 c.clear_flags()
3833 b = 10.0 in [Decimal('10.0'), 1.0]
3834 self.assertTrue(c.flags[FloatOperation])
3835
3836 c.clear_flags()
3837 b = 10.0 in {Decimal('10.0'):'a', 1.0:'b'}
3838 self.assertTrue(c.flags[FloatOperation])
3839
3840 nc = Context()
3841 with localcontext(nc) as c:
3842 self.assertFalse(c.traps[FloatOperation])
3843 doit(c, signal=None)
3844 test_containers(c, signal=None)
3845
3846 c.traps[FloatOperation] = True
3847 doit(c, signal=FloatOperation)
3848 test_containers(c, signal=FloatOperation)
3849
3850 def test_float_operation_default(self):
3851 Decimal = self.decimal.Decimal
3852 Context = self.decimal.Context
3853 Inexact = self.decimal.Inexact
3854 FloatOperation= self.decimal.FloatOperation
3855
3856 context = Context()
3857 self.assertFalse(context.flags[FloatOperation])
3858 self.assertFalse(context.traps[FloatOperation])
3859
3860 context.clear_traps()
3861 context.traps[Inexact] = True
3862 context.traps[FloatOperation] = True
3863 self.assertTrue(context.traps[FloatOperation])
3864 self.assertTrue(context.traps[Inexact])
3865
3866class CContextFlags(ContextFlags):
3867 decimal = C
3868class PyContextFlags(ContextFlags):
3869 decimal = P
3870
3871class SpecialContexts(unittest.TestCase):
3872 """Test the context templates."""
3873
3874 def test_context_templates(self):
3875 BasicContext = self.decimal.BasicContext
3876 ExtendedContext = self.decimal.ExtendedContext
3877 getcontext = self.decimal.getcontext
3878 setcontext = self.decimal.setcontext
3879 InvalidOperation = self.decimal.InvalidOperation
3880 DivisionByZero = self.decimal.DivisionByZero
3881 Overflow = self.decimal.Overflow
3882 Underflow = self.decimal.Underflow
3883 Clamped = self.decimal.Clamped
3884
3885 assert_signals(self, BasicContext, 'traps',
3886 [InvalidOperation, DivisionByZero, Overflow, Underflow, Clamped]
3887 )
3888
3889 savecontext = getcontext().copy()
3890 basic_context_prec = BasicContext.prec
3891 extended_context_prec = ExtendedContext.prec
3892
3893 ex = None
3894 try:
3895 BasicContext.prec = ExtendedContext.prec = 441
3896 for template in BasicContext, ExtendedContext:
3897 setcontext(template)
3898 c = getcontext()
3899 self.assertIsNot(c, template)
3900 self.assertEqual(c.prec, 441)
3901 except Exception as e:
3902 ex = e.__class__
3903 finally:
3904 BasicContext.prec = basic_context_prec
3905 ExtendedContext.prec = extended_context_prec
3906 setcontext(savecontext)
3907 if ex:
3908 raise ex
3909
3910 def test_default_context(self):
3911 DefaultContext = self.decimal.DefaultContext
3912 BasicContext = self.decimal.BasicContext
3913 ExtendedContext = self.decimal.ExtendedContext
3914 getcontext = self.decimal.getcontext
3915 setcontext = self.decimal.setcontext
3916 InvalidOperation = self.decimal.InvalidOperation
3917 DivisionByZero = self.decimal.DivisionByZero
3918 Overflow = self.decimal.Overflow
3919
3920 self.assertEqual(BasicContext.prec, 9)
3921 self.assertEqual(ExtendedContext.prec, 9)
3922
3923 assert_signals(self, DefaultContext, 'traps',
3924 [InvalidOperation, DivisionByZero, Overflow]
3925 )
3926
3927 savecontext = getcontext().copy()
3928 default_context_prec = DefaultContext.prec
3929
3930 ex = None
3931 try:
3932 c = getcontext()
3933 saveprec = c.prec
3934
3935 DefaultContext.prec = 961
3936 c = getcontext()
3937 self.assertEqual(c.prec, saveprec)
3938
3939 setcontext(DefaultContext)
3940 c = getcontext()
3941 self.assertIsNot(c, DefaultContext)
3942 self.assertEqual(c.prec, 961)
3943 except Exception as e:
3944 ex = e.__class__
3945 finally:
3946 DefaultContext.prec = default_context_prec
3947 setcontext(savecontext)
3948 if ex:
3949 raise ex
3950
3951class CSpecialContexts(SpecialContexts):
3952 decimal = C
3953class PySpecialContexts(SpecialContexts):
3954 decimal = P
3955
3956class ContextInputValidation(unittest.TestCase):
3957
3958 def test_invalid_context(self):
3959 Context = self.decimal.Context
3960 DefaultContext = self.decimal.DefaultContext
3961
3962 c = DefaultContext.copy()
3963
3964 # prec, Emax
3965 for attr in ['prec', 'Emax']:
3966 setattr(c, attr, 999999)
3967 self.assertEqual(getattr(c, attr), 999999)
3968 self.assertRaises(ValueError, setattr, c, attr, -1)
3969 self.assertRaises(TypeError, setattr, c, attr, 'xyz')
3970
3971 # Emin
3972 setattr(c, 'Emin', -999999)
3973 self.assertEqual(getattr(c, 'Emin'), -999999)
3974 self.assertRaises(ValueError, setattr, c, 'Emin', 1)
3975 self.assertRaises(TypeError, setattr, c, 'Emin', (1,2,3))
3976
Stefan Krah1919b7e2012-03-21 18:25:23 +01003977 self.assertRaises(TypeError, setattr, c, 'rounding', -1)
3978 self.assertRaises(TypeError, setattr, c, 'rounding', 9)
3979 self.assertRaises(TypeError, setattr, c, 'rounding', 1.0)
3980 self.assertRaises(TypeError, setattr, c, 'rounding', 'xyz')
3981
3982 # capitals, clamp
3983 for attr in ['capitals', 'clamp']:
3984 self.assertRaises(ValueError, setattr, c, attr, -1)
3985 self.assertRaises(ValueError, setattr, c, attr, 2)
3986 self.assertRaises(TypeError, setattr, c, attr, [1,2,3])
3987
3988 # Invalid attribute
3989 self.assertRaises(AttributeError, setattr, c, 'emax', 100)
3990
3991 # Invalid signal dict
3992 self.assertRaises(TypeError, setattr, c, 'flags', [])
3993 self.assertRaises(KeyError, setattr, c, 'flags', {})
3994 self.assertRaises(KeyError, setattr, c, 'traps',
3995 {'InvalidOperation':0})
3996
3997 # Attributes cannot be deleted
3998 for attr in ['prec', 'Emax', 'Emin', 'rounding', 'capitals', 'clamp',
3999 'flags', 'traps']:
4000 self.assertRaises(AttributeError, c.__delattr__, attr)
4001
4002 # Invalid attributes
4003 self.assertRaises(TypeError, getattr, c, 9)
4004 self.assertRaises(TypeError, setattr, c, 9)
4005
4006 # Invalid values in constructor
4007 self.assertRaises(TypeError, Context, rounding=999999)
4008 self.assertRaises(TypeError, Context, rounding='xyz')
4009 self.assertRaises(ValueError, Context, clamp=2)
4010 self.assertRaises(ValueError, Context, capitals=-1)
4011 self.assertRaises(KeyError, Context, flags=["P"])
4012 self.assertRaises(KeyError, Context, traps=["Q"])
4013
4014 # Type error in conversion
4015 self.assertRaises(TypeError, Context, flags=(0,1))
4016 self.assertRaises(TypeError, Context, traps=(1,0))
4017
4018class CContextInputValidation(ContextInputValidation):
4019 decimal = C
4020class PyContextInputValidation(ContextInputValidation):
4021 decimal = P
4022
4023class ContextSubclassing(unittest.TestCase):
4024
4025 def test_context_subclassing(self):
4026 decimal = self.decimal
4027 Decimal = decimal.Decimal
4028 Context = decimal.Context
Stefan Krah1919b7e2012-03-21 18:25:23 +01004029 Clamped = decimal.Clamped
4030 DivisionByZero = decimal.DivisionByZero
4031 Inexact = decimal.Inexact
4032 Overflow = decimal.Overflow
4033 Rounded = decimal.Rounded
4034 Subnormal = decimal.Subnormal
4035 Underflow = decimal.Underflow
4036 InvalidOperation = decimal.InvalidOperation
4037
4038 class MyContext(Context):
4039 def __init__(self, prec=None, rounding=None, Emin=None, Emax=None,
4040 capitals=None, clamp=None, flags=None,
4041 traps=None):
4042 Context.__init__(self)
4043 if prec is not None:
4044 self.prec = prec
4045 if rounding is not None:
4046 self.rounding = rounding
4047 if Emin is not None:
4048 self.Emin = Emin
4049 if Emax is not None:
4050 self.Emax = Emax
4051 if capitals is not None:
4052 self.capitals = capitals
4053 if clamp is not None:
4054 self.clamp = clamp
4055 if flags is not None:
4056 if isinstance(flags, list):
4057 flags = {v:(v in flags) for v in OrderedSignals[decimal] + flags}
4058 self.flags = flags
4059 if traps is not None:
4060 if isinstance(traps, list):
4061 traps = {v:(v in traps) for v in OrderedSignals[decimal] + traps}
4062 self.traps = traps
4063
4064 c = Context()
4065 d = MyContext()
4066 for attr in ('prec', 'rounding', 'Emin', 'Emax', 'capitals', 'clamp',
4067 'flags', 'traps'):
4068 self.assertEqual(getattr(c, attr), getattr(d, attr))
4069
4070 # prec
4071 self.assertRaises(ValueError, MyContext, **{'prec':-1})
4072 c = MyContext(prec=1)
4073 self.assertEqual(c.prec, 1)
4074 self.assertRaises(InvalidOperation, c.quantize, Decimal('9e2'), 0)
4075
4076 # rounding
4077 self.assertRaises(TypeError, MyContext, **{'rounding':'XYZ'})
4078 c = MyContext(rounding=ROUND_DOWN, prec=1)
4079 self.assertEqual(c.rounding, ROUND_DOWN)
4080 self.assertEqual(c.plus(Decimal('9.9')), 9)
4081
4082 # Emin
4083 self.assertRaises(ValueError, MyContext, **{'Emin':5})
4084 c = MyContext(Emin=-1, prec=1)
4085 self.assertEqual(c.Emin, -1)
4086 x = c.add(Decimal('1e-99'), Decimal('2.234e-2000'))
4087 self.assertEqual(x, Decimal('0.0'))
4088 for signal in (Inexact, Underflow, Subnormal, Rounded, Clamped):
4089 self.assertTrue(c.flags[signal])
4090
4091 # Emax
4092 self.assertRaises(ValueError, MyContext, **{'Emax':-1})
4093 c = MyContext(Emax=1, prec=1)
4094 self.assertEqual(c.Emax, 1)
4095 self.assertRaises(Overflow, c.add, Decimal('1e99'), Decimal('2.234e2000'))
4096 if self.decimal == C:
4097 for signal in (Inexact, Overflow, Rounded):
4098 self.assertTrue(c.flags[signal])
4099
4100 # capitals
4101 self.assertRaises(ValueError, MyContext, **{'capitals':-1})
4102 c = MyContext(capitals=0)
4103 self.assertEqual(c.capitals, 0)
4104 x = c.create_decimal('1E222')
4105 self.assertEqual(c.to_sci_string(x), '1e+222')
4106
4107 # clamp
4108 self.assertRaises(ValueError, MyContext, **{'clamp':2})
4109 c = MyContext(clamp=1, Emax=99)
4110 self.assertEqual(c.clamp, 1)
4111 x = c.plus(Decimal('1e99'))
4112 self.assertEqual(str(x), '1.000000000000000000000000000E+99')
4113
4114 # flags
4115 self.assertRaises(TypeError, MyContext, **{'flags':'XYZ'})
4116 c = MyContext(flags=[Rounded, DivisionByZero])
4117 for signal in (Rounded, DivisionByZero):
4118 self.assertTrue(c.flags[signal])
4119 c.clear_flags()
4120 for signal in OrderedSignals[decimal]:
4121 self.assertFalse(c.flags[signal])
4122
4123 # traps
4124 self.assertRaises(TypeError, MyContext, **{'traps':'XYZ'})
4125 c = MyContext(traps=[Rounded, DivisionByZero])
4126 for signal in (Rounded, DivisionByZero):
4127 self.assertTrue(c.traps[signal])
4128 c.clear_traps()
4129 for signal in OrderedSignals[decimal]:
4130 self.assertFalse(c.traps[signal])
4131
4132class CContextSubclassing(ContextSubclassing):
4133 decimal = C
4134class PyContextSubclassing(ContextSubclassing):
4135 decimal = P
4136
4137@skip_if_extra_functionality
4138class CheckAttributes(unittest.TestCase):
4139
4140 def test_module_attributes(self):
4141
4142 # Architecture dependent context limits
4143 self.assertEqual(C.MAX_PREC, P.MAX_PREC)
4144 self.assertEqual(C.MAX_EMAX, P.MAX_EMAX)
4145 self.assertEqual(C.MIN_EMIN, P.MIN_EMIN)
4146 self.assertEqual(C.MIN_ETINY, P.MIN_ETINY)
4147
4148 self.assertTrue(C.HAVE_THREADS is True or C.HAVE_THREADS is False)
4149 self.assertTrue(P.HAVE_THREADS is True or P.HAVE_THREADS is False)
4150
4151 self.assertEqual(C.__version__, P.__version__)
4152
4153 x = dir(C)
4154 y = [s for s in dir(P) if '__' in s or not s.startswith('_')]
Stefan Krahfe17b2b2012-03-25 18:59:21 +02004155 self.assertEqual(set(x) - set(y), set())
Stefan Krah1919b7e2012-03-21 18:25:23 +01004156
4157 def test_context_attributes(self):
4158
4159 x = [s for s in dir(C.Context()) if '__' in s or not s.startswith('_')]
4160 y = [s for s in dir(P.Context()) if '__' in s or not s.startswith('_')]
4161 self.assertEqual(set(x) - set(y), set())
4162
4163 def test_decimal_attributes(self):
4164
4165 x = [s for s in dir(C.Decimal(9)) if '__' in s or not s.startswith('_')]
4166 y = [s for s in dir(C.Decimal(9)) if '__' in s or not s.startswith('_')]
4167 self.assertEqual(set(x) - set(y), set())
4168
4169class Coverage(unittest.TestCase):
4170
4171 def test_adjusted(self):
4172 Decimal = self.decimal.Decimal
4173
4174 self.assertEqual(Decimal('1234e9999').adjusted(), 10002)
4175 # XXX raise?
4176 self.assertEqual(Decimal('nan').adjusted(), 0)
4177 self.assertEqual(Decimal('inf').adjusted(), 0)
4178
4179 def test_canonical(self):
4180 Decimal = self.decimal.Decimal
4181 getcontext = self.decimal.getcontext
4182
4183 x = Decimal(9).canonical()
4184 self.assertEqual(x, 9)
4185
4186 c = getcontext()
4187 x = c.canonical(Decimal(9))
4188 self.assertEqual(x, 9)
4189
4190 def test_context_repr(self):
4191 c = self.decimal.DefaultContext.copy()
4192
4193 c.prec = 425000000
4194 c.Emax = 425000000
4195 c.Emin = -425000000
Stefan Krah59a4a932013-01-16 12:58:59 +01004196 c.rounding = ROUND_HALF_DOWN
Stefan Krah1919b7e2012-03-21 18:25:23 +01004197 c.capitals = 0
4198 c.clamp = 1
4199 for sig in OrderedSignals[self.decimal]:
4200 c.flags[sig] = False
4201 c.traps[sig] = False
4202
4203 s = c.__repr__()
4204 t = "Context(prec=425000000, rounding=ROUND_HALF_DOWN, " \
4205 "Emin=-425000000, Emax=425000000, capitals=0, clamp=1, " \
4206 "flags=[], traps=[])"
4207 self.assertEqual(s, t)
4208
4209 def test_implicit_context(self):
4210 Decimal = self.decimal.Decimal
4211 localcontext = self.decimal.localcontext
4212
4213 with localcontext() as c:
4214 c.prec = 1
4215 c.Emax = 1
4216 c.Emin = -1
4217
4218 # abs
4219 self.assertEqual(abs(Decimal("-10")), 10)
4220 # add
4221 self.assertEqual(Decimal("7") + 1, 8)
4222 # divide
4223 self.assertEqual(Decimal("10") / 5, 2)
4224 # divide_int
4225 self.assertEqual(Decimal("10") // 7, 1)
4226 # fma
4227 self.assertEqual(Decimal("1.2").fma(Decimal("0.01"), 1), 1)
4228 self.assertIs(Decimal("NaN").fma(7, 1).is_nan(), True)
4229 # three arg power
4230 self.assertEqual(pow(Decimal(10), 2, 7), 2)
4231 # exp
4232 self.assertEqual(Decimal("1.01").exp(), 3)
4233 # is_normal
4234 self.assertIs(Decimal("0.01").is_normal(), False)
4235 # is_subnormal
4236 self.assertIs(Decimal("0.01").is_subnormal(), True)
4237 # ln
4238 self.assertEqual(Decimal("20").ln(), 3)
4239 # log10
4240 self.assertEqual(Decimal("20").log10(), 1)
4241 # logb
4242 self.assertEqual(Decimal("580").logb(), 2)
4243 # logical_invert
4244 self.assertEqual(Decimal("10").logical_invert(), 1)
4245 # minus
4246 self.assertEqual(-Decimal("-10"), 10)
4247 # multiply
4248 self.assertEqual(Decimal("2") * 4, 8)
4249 # next_minus
4250 self.assertEqual(Decimal("10").next_minus(), 9)
4251 # next_plus
4252 self.assertEqual(Decimal("10").next_plus(), Decimal('2E+1'))
4253 # normalize
4254 self.assertEqual(Decimal("-10").normalize(), Decimal('-1E+1'))
4255 # number_class
4256 self.assertEqual(Decimal("10").number_class(), '+Normal')
4257 # plus
4258 self.assertEqual(+Decimal("-1"), -1)
4259 # remainder
4260 self.assertEqual(Decimal("10") % 7, 3)
4261 # subtract
4262 self.assertEqual(Decimal("10") - 7, 3)
4263 # to_integral_exact
4264 self.assertEqual(Decimal("1.12345").to_integral_exact(), 1)
4265
4266 # Boolean functions
4267 self.assertTrue(Decimal("1").is_canonical())
4268 self.assertTrue(Decimal("1").is_finite())
4269 self.assertTrue(Decimal("1").is_finite())
4270 self.assertTrue(Decimal("snan").is_snan())
4271 self.assertTrue(Decimal("-1").is_signed())
4272 self.assertTrue(Decimal("0").is_zero())
4273 self.assertTrue(Decimal("0").is_zero())
4274
4275 # Copy
4276 with localcontext() as c:
4277 c.prec = 10000
4278 x = 1228 ** 1523
4279 y = -Decimal(x)
4280
4281 z = y.copy_abs()
4282 self.assertEqual(z, x)
4283
4284 z = y.copy_negate()
4285 self.assertEqual(z, x)
4286
4287 z = y.copy_sign(Decimal(1))
4288 self.assertEqual(z, x)
4289
4290 def test_divmod(self):
4291 Decimal = self.decimal.Decimal
4292 localcontext = self.decimal.localcontext
4293 InvalidOperation = self.decimal.InvalidOperation
4294 DivisionByZero = self.decimal.DivisionByZero
4295
4296 with localcontext() as c:
4297 q, r = divmod(Decimal("10912837129"), 1001)
4298 self.assertEqual(q, Decimal('10901935'))
4299 self.assertEqual(r, Decimal('194'))
4300
4301 q, r = divmod(Decimal("NaN"), 7)
4302 self.assertTrue(q.is_nan() and r.is_nan())
4303
4304 c.traps[InvalidOperation] = False
4305 q, r = divmod(Decimal("NaN"), 7)
4306 self.assertTrue(q.is_nan() and r.is_nan())
4307
4308 c.traps[InvalidOperation] = False
4309 c.clear_flags()
4310 q, r = divmod(Decimal("inf"), Decimal("inf"))
4311 self.assertTrue(q.is_nan() and r.is_nan())
4312 self.assertTrue(c.flags[InvalidOperation])
4313
4314 c.clear_flags()
4315 q, r = divmod(Decimal("inf"), 101)
4316 self.assertTrue(q.is_infinite() and r.is_nan())
4317 self.assertTrue(c.flags[InvalidOperation])
4318
4319 c.clear_flags()
4320 q, r = divmod(Decimal(0), 0)
4321 self.assertTrue(q.is_nan() and r.is_nan())
4322 self.assertTrue(c.flags[InvalidOperation])
4323
4324 c.traps[DivisionByZero] = False
4325 c.clear_flags()
4326 q, r = divmod(Decimal(11), 0)
4327 self.assertTrue(q.is_infinite() and r.is_nan())
4328 self.assertTrue(c.flags[InvalidOperation] and
4329 c.flags[DivisionByZero])
4330
4331 def test_power(self):
4332 Decimal = self.decimal.Decimal
4333 localcontext = self.decimal.localcontext
4334 Overflow = self.decimal.Overflow
4335 Rounded = self.decimal.Rounded
4336
4337 with localcontext() as c:
4338 c.prec = 3
4339 c.clear_flags()
4340 self.assertEqual(Decimal("1.0") ** 100, Decimal('1.00'))
4341 self.assertTrue(c.flags[Rounded])
4342
4343 c.prec = 1
4344 c.Emax = 1
4345 c.Emin = -1
4346 c.clear_flags()
4347 c.traps[Overflow] = False
4348 self.assertEqual(Decimal(10000) ** Decimal("0.5"), Decimal('inf'))
4349 self.assertTrue(c.flags[Overflow])
4350
4351 def test_quantize(self):
4352 Decimal = self.decimal.Decimal
4353 localcontext = self.decimal.localcontext
4354 InvalidOperation = self.decimal.InvalidOperation
4355
4356 with localcontext() as c:
4357 c.prec = 1
4358 c.Emax = 1
4359 c.Emin = -1
4360 c.traps[InvalidOperation] = False
4361 x = Decimal(99).quantize(Decimal("1e1"))
4362 self.assertTrue(x.is_nan())
4363
4364 def test_radix(self):
4365 Decimal = self.decimal.Decimal
4366 getcontext = self.decimal.getcontext
4367
4368 c = getcontext()
4369 self.assertEqual(Decimal("1").radix(), 10)
4370 self.assertEqual(c.radix(), 10)
4371
4372 def test_rop(self):
4373 Decimal = self.decimal.Decimal
4374
4375 for attr in ('__radd__', '__rsub__', '__rmul__', '__rtruediv__',
4376 '__rdivmod__', '__rmod__', '__rfloordiv__', '__rpow__'):
4377 self.assertIs(getattr(Decimal("1"), attr)("xyz"), NotImplemented)
4378
4379 def test_round(self):
4380 # Python3 behavior: round() returns Decimal
4381 Decimal = self.decimal.Decimal
4382 getcontext = self.decimal.getcontext
4383
4384 c = getcontext()
4385 c.prec = 28
4386
4387 self.assertEqual(str(Decimal("9.99").__round__()), "10")
4388 self.assertEqual(str(Decimal("9.99e-5").__round__()), "0")
4389 self.assertEqual(str(Decimal("1.23456789").__round__(5)), "1.23457")
4390 self.assertEqual(str(Decimal("1.2345").__round__(10)), "1.2345000000")
4391 self.assertEqual(str(Decimal("1.2345").__round__(-10)), "0E+10")
4392
4393 self.assertRaises(TypeError, Decimal("1.23").__round__, "5")
4394 self.assertRaises(TypeError, Decimal("1.23").__round__, 5, 8)
4395
4396 def test_create_decimal(self):
4397 c = self.decimal.Context()
4398 self.assertRaises(ValueError, c.create_decimal, ["%"])
4399
4400 def test_int(self):
4401 Decimal = self.decimal.Decimal
4402 localcontext = self.decimal.localcontext
4403
4404 with localcontext() as c:
4405 c.prec = 9999
4406 x = Decimal(1221**1271) / 10**3923
4407 self.assertEqual(int(x), 1)
4408 self.assertEqual(x.to_integral(), 2)
4409
4410 def test_copy(self):
4411 Context = self.decimal.Context
4412
4413 c = Context()
4414 c.prec = 10000
4415 x = -(1172 ** 1712)
4416
4417 y = c.copy_abs(x)
4418 self.assertEqual(y, -x)
4419
4420 y = c.copy_negate(x)
4421 self.assertEqual(y, -x)
4422
4423 y = c.copy_sign(x, 1)
4424 self.assertEqual(y, -x)
4425
4426class CCoverage(Coverage):
4427 decimal = C
4428class PyCoverage(Coverage):
4429 decimal = P
4430
4431class PyFunctionality(unittest.TestCase):
4432 """Extra functionality in decimal.py"""
4433
4434 def test_py_quantize_watchexp(self):
4435 # watchexp functionality
4436 Decimal = P.Decimal
4437 localcontext = P.localcontext
4438
4439 with localcontext() as c:
4440 c.prec = 1
4441 c.Emax = 1
4442 c.Emin = -1
4443 x = Decimal(99999).quantize(Decimal("1e3"), watchexp=False)
4444 self.assertEqual(x, Decimal('1.00E+5'))
4445
4446 def test_py_alternate_formatting(self):
4447 # triples giving a format, a Decimal, and the expected result
4448 Decimal = P.Decimal
4449 localcontext = P.localcontext
4450
4451 test_values = [
4452 # Issue 7094: Alternate formatting (specified by #)
4453 ('.0e', '1.0', '1e+0'),
4454 ('#.0e', '1.0', '1.e+0'),
4455 ('.0f', '1.0', '1'),
4456 ('#.0f', '1.0', '1.'),
4457 ('g', '1.1', '1.1'),
4458 ('#g', '1.1', '1.1'),
4459 ('.0g', '1', '1'),
4460 ('#.0g', '1', '1.'),
4461 ('.0%', '1.0', '100%'),
4462 ('#.0%', '1.0', '100.%'),
4463 ]
4464 for fmt, d, result in test_values:
4465 self.assertEqual(format(Decimal(d), fmt), result)
4466
4467class PyWhitebox(unittest.TestCase):
4468 """White box testing for decimal.py"""
4469
4470 def test_py_exact_power(self):
4471 # Rarely exercised lines in _power_exact.
4472 Decimal = P.Decimal
4473 localcontext = P.localcontext
4474
4475 with localcontext() as c:
4476 c.prec = 8
4477 x = Decimal(2**16) ** Decimal("-0.5")
4478 self.assertEqual(x, Decimal('0.00390625'))
4479
4480 x = Decimal(2**16) ** Decimal("-0.6")
4481 self.assertEqual(x, Decimal('0.0012885819'))
4482
4483 x = Decimal("256e7") ** Decimal("-0.5")
4484
4485 x = Decimal(152587890625) ** Decimal('-0.0625')
4486 self.assertEqual(x, Decimal("0.2"))
4487
4488 x = Decimal("152587890625e7") ** Decimal('-0.0625')
4489
4490 x = Decimal(5**2659) ** Decimal('-0.0625')
4491
4492 c.prec = 1
4493 x = Decimal("152587890625") ** Decimal('-0.5')
4494 c.prec = 201
4495 x = Decimal(2**578) ** Decimal("-0.5")
4496
4497 def test_py_immutability_operations(self):
Terry Jan Reedy0f847642013-03-11 18:34:00 -04004498 # Do operations and check that it didn't change internal objects.
Stefan Krah1919b7e2012-03-21 18:25:23 +01004499 Decimal = P.Decimal
4500 DefaultContext = P.DefaultContext
4501 setcontext = P.setcontext
4502
4503 c = DefaultContext.copy()
4504 c.traps = dict((s, 0) for s in OrderedSignals[P])
4505 setcontext(c)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004506
4507 d1 = Decimal('-25e55')
4508 b1 = Decimal('-25e55')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004509 d2 = Decimal('33e+33')
4510 b2 = Decimal('33e+33')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004511
4512 def checkSameDec(operation, useOther=False):
4513 if useOther:
4514 eval("d1." + operation + "(d2)")
4515 self.assertEqual(d1._sign, b1._sign)
4516 self.assertEqual(d1._int, b1._int)
4517 self.assertEqual(d1._exp, b1._exp)
4518 self.assertEqual(d2._sign, b2._sign)
4519 self.assertEqual(d2._int, b2._int)
4520 self.assertEqual(d2._exp, b2._exp)
4521 else:
4522 eval("d1." + operation + "()")
4523 self.assertEqual(d1._sign, b1._sign)
4524 self.assertEqual(d1._int, b1._int)
4525 self.assertEqual(d1._exp, b1._exp)
4526 return
4527
4528 Decimal(d1)
4529 self.assertEqual(d1._sign, b1._sign)
4530 self.assertEqual(d1._int, b1._int)
4531 self.assertEqual(d1._exp, b1._exp)
4532
4533 checkSameDec("__abs__")
4534 checkSameDec("__add__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004535 checkSameDec("__divmod__", True)
Christian Heimes77c02eb2008-02-09 02:18:51 +00004536 checkSameDec("__eq__", True)
4537 checkSameDec("__ne__", True)
4538 checkSameDec("__le__", True)
4539 checkSameDec("__lt__", True)
4540 checkSameDec("__ge__", True)
4541 checkSameDec("__gt__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004542 checkSameDec("__float__")
4543 checkSameDec("__floordiv__", True)
4544 checkSameDec("__hash__")
4545 checkSameDec("__int__")
Christian Heimes969fe572008-01-25 11:23:10 +00004546 checkSameDec("__trunc__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004547 checkSameDec("__mod__", True)
4548 checkSameDec("__mul__", True)
4549 checkSameDec("__neg__")
Jack Diederich4dafcc42006-11-28 19:15:13 +00004550 checkSameDec("__bool__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004551 checkSameDec("__pos__")
4552 checkSameDec("__pow__", True)
4553 checkSameDec("__radd__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004554 checkSameDec("__rdivmod__", True)
4555 checkSameDec("__repr__")
4556 checkSameDec("__rfloordiv__", True)
4557 checkSameDec("__rmod__", True)
4558 checkSameDec("__rmul__", True)
4559 checkSameDec("__rpow__", True)
4560 checkSameDec("__rsub__", True)
4561 checkSameDec("__str__")
4562 checkSameDec("__sub__", True)
4563 checkSameDec("__truediv__", True)
4564 checkSameDec("adjusted")
4565 checkSameDec("as_tuple")
4566 checkSameDec("compare", True)
4567 checkSameDec("max", True)
4568 checkSameDec("min", True)
4569 checkSameDec("normalize")
4570 checkSameDec("quantize", True)
4571 checkSameDec("remainder_near", True)
4572 checkSameDec("same_quantum", True)
4573 checkSameDec("sqrt")
4574 checkSameDec("to_eng_string")
4575 checkSameDec("to_integral")
4576
Stefan Krah1919b7e2012-03-21 18:25:23 +01004577 def test_py_decimal_id(self):
4578 Decimal = P.Decimal
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004579
Stefan Krah1919b7e2012-03-21 18:25:23 +01004580 d = Decimal(45)
4581 e = Decimal(d)
4582 self.assertEqual(str(e), '45')
4583 self.assertNotEqual(id(d), id(e))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004584
Stefan Krah1919b7e2012-03-21 18:25:23 +01004585 def test_py_rescale(self):
4586 # Coverage
4587 Decimal = P.Decimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01004588 localcontext = P.localcontext
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004589
Stefan Krah1919b7e2012-03-21 18:25:23 +01004590 with localcontext() as c:
4591 x = Decimal("NaN")._rescale(3, ROUND_UP)
4592 self.assertTrue(x.is_nan())
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004593
Stefan Krah1919b7e2012-03-21 18:25:23 +01004594 def test_py__round(self):
4595 # Coverage
4596 Decimal = P.Decimal
Christian Heimes0348fb62008-03-26 12:55:56 +00004597
Stefan Krah1919b7e2012-03-21 18:25:23 +01004598 self.assertRaises(ValueError, Decimal("3.1234")._round, 0, ROUND_UP)
Mark Dickinsona2d1fe02009-10-29 12:23:02 +00004599
Stefan Krah1919b7e2012-03-21 18:25:23 +01004600class CFunctionality(unittest.TestCase):
4601 """Extra functionality in _decimal"""
Mark Dickinsona2d1fe02009-10-29 12:23:02 +00004602
Stefan Krah1919b7e2012-03-21 18:25:23 +01004603 @requires_extra_functionality
4604 def test_c_ieee_context(self):
4605 # issue 8786: Add support for IEEE 754 contexts to decimal module.
4606 IEEEContext = C.IEEEContext
4607 DECIMAL32 = C.DECIMAL32
4608 DECIMAL64 = C.DECIMAL64
4609 DECIMAL128 = C.DECIMAL128
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004610
Stefan Krah1919b7e2012-03-21 18:25:23 +01004611 def assert_rest(self, context):
4612 self.assertEqual(context.clamp, 1)
4613 assert_signals(self, context, 'traps', [])
4614 assert_signals(self, context, 'flags', [])
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004615
Stefan Krah1919b7e2012-03-21 18:25:23 +01004616 c = IEEEContext(DECIMAL32)
4617 self.assertEqual(c.prec, 7)
4618 self.assertEqual(c.Emax, 96)
4619 self.assertEqual(c.Emin, -95)
4620 assert_rest(self, c)
Raymond Hettinger82417ca2009-02-03 03:54:28 +00004621
Stefan Krah1919b7e2012-03-21 18:25:23 +01004622 c = IEEEContext(DECIMAL64)
4623 self.assertEqual(c.prec, 16)
4624 self.assertEqual(c.Emax, 384)
4625 self.assertEqual(c.Emin, -383)
4626 assert_rest(self, c)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004627
Stefan Krah1919b7e2012-03-21 18:25:23 +01004628 c = IEEEContext(DECIMAL128)
4629 self.assertEqual(c.prec, 34)
4630 self.assertEqual(c.Emax, 6144)
4631 self.assertEqual(c.Emin, -6143)
4632 assert_rest(self, c)
Raymond Hettinger5548be22004-07-05 18:49:38 +00004633
Stefan Krah1919b7e2012-03-21 18:25:23 +01004634 # Invalid values
4635 self.assertRaises(OverflowError, IEEEContext, 2**63)
4636 self.assertRaises(ValueError, IEEEContext, -1)
4637 self.assertRaises(ValueError, IEEEContext, 1024)
Mark Dickinson825fce32009-09-07 18:08:12 +00004638
Stefan Krah1919b7e2012-03-21 18:25:23 +01004639 @requires_extra_functionality
4640 def test_c_context(self):
4641 Context = C.Context
Christian Heimes969fe572008-01-25 11:23:10 +00004642
Stefan Krah1919b7e2012-03-21 18:25:23 +01004643 c = Context(flags=C.DecClamped, traps=C.DecRounded)
4644 self.assertEqual(c._flags, C.DecClamped)
4645 self.assertEqual(c._traps, C.DecRounded)
Raymond Hettinger771ed762009-01-03 19:20:32 +00004646
Stefan Krah1919b7e2012-03-21 18:25:23 +01004647 @requires_extra_functionality
4648 def test_constants(self):
4649 # Condition flags
4650 cond = (
4651 C.DecClamped, C.DecConversionSyntax, C.DecDivisionByZero,
4652 C.DecDivisionImpossible, C.DecDivisionUndefined,
4653 C.DecFpuError, C.DecInexact, C.DecInvalidContext,
4654 C.DecInvalidOperation, C.DecMallocError,
4655 C.DecFloatOperation, C.DecOverflow, C.DecRounded,
4656 C.DecSubnormal, C.DecUnderflow
Raymond Hettinger771ed762009-01-03 19:20:32 +00004657 )
Stefan Krah1919b7e2012-03-21 18:25:23 +01004658
4659 # IEEEContext
4660 self.assertEqual(C.DECIMAL32, 32)
4661 self.assertEqual(C.DECIMAL64, 64)
4662 self.assertEqual(C.DECIMAL128, 128)
4663 self.assertEqual(C.IEEE_CONTEXT_MAX_BITS, 512)
4664
Stefan Krah1919b7e2012-03-21 18:25:23 +01004665 # Conditions
4666 for i, v in enumerate(cond):
4667 self.assertEqual(v, 1<<i)
4668
4669 self.assertEqual(C.DecIEEEInvalidOperation,
4670 C.DecConversionSyntax|
4671 C.DecDivisionImpossible|
4672 C.DecDivisionUndefined|
4673 C.DecFpuError|
4674 C.DecInvalidContext|
4675 C.DecInvalidOperation|
4676 C.DecMallocError)
4677
4678 self.assertEqual(C.DecErrors,
4679 C.DecIEEEInvalidOperation|
4680 C.DecDivisionByZero)
4681
4682 self.assertEqual(C.DecTraps,
4683 C.DecErrors|C.DecOverflow|C.DecUnderflow)
4684
4685class CWhitebox(unittest.TestCase):
4686 """Whitebox testing for _decimal"""
4687
4688 def test_bignum(self):
4689 # Not exactly whitebox, but too slow with pydecimal.
4690
4691 Decimal = C.Decimal
4692 localcontext = C.localcontext
4693
4694 b1 = 10**35
4695 b2 = 10**36
4696 with localcontext() as c:
4697 c.prec = 1000000
4698 for i in range(5):
4699 a = random.randrange(b1, b2)
4700 b = random.randrange(1000, 1200)
4701 x = a ** b
4702 y = Decimal(a) ** Decimal(b)
4703 self.assertEqual(x, y)
4704
4705 def test_invalid_construction(self):
4706 self.assertRaises(TypeError, C.Decimal, 9, "xyz")
4707
4708 def test_c_input_restriction(self):
4709 # Too large for _decimal to be converted exactly
4710 Decimal = C.Decimal
4711 InvalidOperation = C.InvalidOperation
4712 Context = C.Context
4713 localcontext = C.localcontext
4714
4715 with localcontext(Context()):
4716 self.assertRaises(InvalidOperation, Decimal,
4717 "1e9999999999999999999")
4718
4719 def test_c_context_repr(self):
4720 # This test is _decimal-only because flags are not printed
4721 # in the same order.
4722 DefaultContext = C.DefaultContext
4723 FloatOperation = C.FloatOperation
Stefan Krah1919b7e2012-03-21 18:25:23 +01004724
4725 c = DefaultContext.copy()
4726
4727 c.prec = 425000000
4728 c.Emax = 425000000
4729 c.Emin = -425000000
4730 c.rounding = ROUND_HALF_DOWN
4731 c.capitals = 0
4732 c.clamp = 1
4733 for sig in OrderedSignals[C]:
4734 c.flags[sig] = True
4735 c.traps[sig] = True
4736 c.flags[FloatOperation] = True
4737 c.traps[FloatOperation] = True
4738
4739 s = c.__repr__()
4740 t = "Context(prec=425000000, rounding=ROUND_HALF_DOWN, " \
4741 "Emin=-425000000, Emax=425000000, capitals=0, clamp=1, " \
4742 "flags=[Clamped, InvalidOperation, DivisionByZero, Inexact, " \
4743 "FloatOperation, Overflow, Rounded, Subnormal, Underflow], " \
4744 "traps=[Clamped, InvalidOperation, DivisionByZero, Inexact, " \
4745 "FloatOperation, Overflow, Rounded, Subnormal, Underflow])"
4746 self.assertEqual(s, t)
4747
4748 def test_c_context_errors(self):
4749 Context = C.Context
4750 InvalidOperation = C.InvalidOperation
4751 Overflow = C.Overflow
4752 FloatOperation = C.FloatOperation
4753 localcontext = C.localcontext
4754 getcontext = C.getcontext
4755 setcontext = C.setcontext
4756 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
4757
4758 c = Context()
4759
4760 # SignalDict: input validation
4761 self.assertRaises(KeyError, c.flags.__setitem__, 801, 0)
4762 self.assertRaises(KeyError, c.traps.__setitem__, 801, 0)
4763 self.assertRaises(ValueError, c.flags.__delitem__, Overflow)
4764 self.assertRaises(ValueError, c.traps.__delitem__, InvalidOperation)
4765 self.assertRaises(TypeError, setattr, c, 'flags', ['x'])
4766 self.assertRaises(TypeError, setattr, c,'traps', ['y'])
4767 self.assertRaises(KeyError, setattr, c, 'flags', {0:1})
4768 self.assertRaises(KeyError, setattr, c, 'traps', {0:1})
4769
4770 # Test assignment from a signal dict with the correct length but
4771 # one invalid key.
4772 d = c.flags.copy()
4773 del d[FloatOperation]
4774 d["XYZ"] = 91283719
4775 self.assertRaises(KeyError, setattr, c, 'flags', d)
4776 self.assertRaises(KeyError, setattr, c, 'traps', d)
4777
4778 # Input corner cases
4779 int_max = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
4780 gt_max_emax = 10**18 if HAVE_CONFIG_64 else 10**9
4781
4782 # prec, Emax, Emin
4783 for attr in ['prec', 'Emax']:
4784 self.assertRaises(ValueError, setattr, c, attr, gt_max_emax)
4785 self.assertRaises(ValueError, setattr, c, 'Emin', -gt_max_emax)
4786
4787 # prec, Emax, Emin in context constructor
4788 self.assertRaises(ValueError, Context, prec=gt_max_emax)
4789 self.assertRaises(ValueError, Context, Emax=gt_max_emax)
4790 self.assertRaises(ValueError, Context, Emin=-gt_max_emax)
4791
4792 # Overflow in conversion
4793 self.assertRaises(OverflowError, Context, prec=int_max+1)
4794 self.assertRaises(OverflowError, Context, Emax=int_max+1)
4795 self.assertRaises(OverflowError, Context, Emin=-int_max-2)
Stefan Krah1919b7e2012-03-21 18:25:23 +01004796 self.assertRaises(OverflowError, Context, clamp=int_max+1)
4797 self.assertRaises(OverflowError, Context, capitals=int_max+1)
4798
4799 # OverflowError, general ValueError
4800 for attr in ('prec', 'Emin', 'Emax', 'capitals', 'clamp'):
4801 self.assertRaises(OverflowError, setattr, c, attr, int_max+1)
4802 self.assertRaises(OverflowError, setattr, c, attr, -int_max-2)
4803 if sys.platform != 'win32':
4804 self.assertRaises(ValueError, setattr, c, attr, int_max)
4805 self.assertRaises(ValueError, setattr, c, attr, -int_max-1)
4806
Stefan Krah1919b7e2012-03-21 18:25:23 +01004807 # OverflowError: _unsafe_setprec, _unsafe_setemin, _unsafe_setemax
4808 if C.MAX_PREC == 425000000:
4809 self.assertRaises(OverflowError, getattr(c, '_unsafe_setprec'),
4810 int_max+1)
4811 self.assertRaises(OverflowError, getattr(c, '_unsafe_setemax'),
4812 int_max+1)
4813 self.assertRaises(OverflowError, getattr(c, '_unsafe_setemin'),
4814 -int_max-2)
4815
4816 # ValueError: _unsafe_setprec, _unsafe_setemin, _unsafe_setemax
4817 if C.MAX_PREC == 425000000:
4818 self.assertRaises(ValueError, getattr(c, '_unsafe_setprec'), 0)
4819 self.assertRaises(ValueError, getattr(c, '_unsafe_setprec'),
4820 1070000001)
4821 self.assertRaises(ValueError, getattr(c, '_unsafe_setemax'), -1)
4822 self.assertRaises(ValueError, getattr(c, '_unsafe_setemax'),
4823 1070000001)
4824 self.assertRaises(ValueError, getattr(c, '_unsafe_setemin'),
4825 -1070000001)
4826 self.assertRaises(ValueError, getattr(c, '_unsafe_setemin'), 1)
4827
4828 # capitals, clamp
4829 for attr in ['capitals', 'clamp']:
4830 self.assertRaises(ValueError, setattr, c, attr, -1)
4831 self.assertRaises(ValueError, setattr, c, attr, 2)
4832 self.assertRaises(TypeError, setattr, c, attr, [1,2,3])
4833 if HAVE_CONFIG_64:
4834 self.assertRaises(ValueError, setattr, c, attr, 2**32)
4835 self.assertRaises(ValueError, setattr, c, attr, 2**32+1)
4836
4837 # Invalid local context
4838 self.assertRaises(TypeError, exec, 'with localcontext("xyz"): pass',
4839 locals())
Stefan Krah040e3112012-12-15 22:33:33 +01004840 self.assertRaises(TypeError, exec,
4841 'with localcontext(context=getcontext()): pass',
4842 locals())
Stefan Krah1919b7e2012-03-21 18:25:23 +01004843
4844 # setcontext
4845 saved_context = getcontext()
4846 self.assertRaises(TypeError, setcontext, "xyz")
4847 setcontext(saved_context)
4848
Stefan Krah59a4a932013-01-16 12:58:59 +01004849 def test_rounding_strings_interned(self):
4850
4851 self.assertIs(C.ROUND_UP, P.ROUND_UP)
4852 self.assertIs(C.ROUND_DOWN, P.ROUND_DOWN)
4853 self.assertIs(C.ROUND_CEILING, P.ROUND_CEILING)
4854 self.assertIs(C.ROUND_FLOOR, P.ROUND_FLOOR)
4855 self.assertIs(C.ROUND_HALF_UP, P.ROUND_HALF_UP)
4856 self.assertIs(C.ROUND_HALF_DOWN, P.ROUND_HALF_DOWN)
4857 self.assertIs(C.ROUND_HALF_EVEN, P.ROUND_HALF_EVEN)
4858 self.assertIs(C.ROUND_05UP, P.ROUND_05UP)
4859
Stefan Krah1919b7e2012-03-21 18:25:23 +01004860 @requires_extra_functionality
4861 def test_c_context_errors_extra(self):
4862 Context = C.Context
4863 InvalidOperation = C.InvalidOperation
4864 Overflow = C.Overflow
4865 localcontext = C.localcontext
4866 getcontext = C.getcontext
4867 setcontext = C.setcontext
4868 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
4869
4870 c = Context()
4871
4872 # Input corner cases
4873 int_max = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
4874
4875 # OverflowError, general ValueError
4876 self.assertRaises(OverflowError, setattr, c, '_allcr', int_max+1)
4877 self.assertRaises(OverflowError, setattr, c, '_allcr', -int_max-2)
4878 if sys.platform != 'win32':
4879 self.assertRaises(ValueError, setattr, c, '_allcr', int_max)
4880 self.assertRaises(ValueError, setattr, c, '_allcr', -int_max-1)
4881
4882 # OverflowError, general TypeError
4883 for attr in ('_flags', '_traps'):
4884 self.assertRaises(OverflowError, setattr, c, attr, int_max+1)
4885 self.assertRaises(OverflowError, setattr, c, attr, -int_max-2)
4886 if sys.platform != 'win32':
4887 self.assertRaises(TypeError, setattr, c, attr, int_max)
4888 self.assertRaises(TypeError, setattr, c, attr, -int_max-1)
4889
4890 # _allcr
4891 self.assertRaises(ValueError, setattr, c, '_allcr', -1)
4892 self.assertRaises(ValueError, setattr, c, '_allcr', 2)
4893 self.assertRaises(TypeError, setattr, c, '_allcr', [1,2,3])
4894 if HAVE_CONFIG_64:
4895 self.assertRaises(ValueError, setattr, c, '_allcr', 2**32)
4896 self.assertRaises(ValueError, setattr, c, '_allcr', 2**32+1)
4897
4898 # _flags, _traps
4899 for attr in ['_flags', '_traps']:
4900 self.assertRaises(TypeError, setattr, c, attr, 999999)
4901 self.assertRaises(TypeError, setattr, c, attr, 'x')
4902
4903 def test_c_valid_context(self):
4904 # These tests are for code coverage in _decimal.
4905 DefaultContext = C.DefaultContext
Stefan Krah1919b7e2012-03-21 18:25:23 +01004906 Clamped = C.Clamped
4907 Underflow = C.Underflow
4908 Inexact = C.Inexact
4909 Rounded = C.Rounded
4910 Subnormal = C.Subnormal
4911
4912 c = DefaultContext.copy()
4913
4914 # Exercise all getters and setters
4915 c.prec = 34
4916 c.rounding = ROUND_HALF_UP
4917 c.Emax = 3000
4918 c.Emin = -3000
4919 c.capitals = 1
4920 c.clamp = 0
4921
4922 self.assertEqual(c.prec, 34)
4923 self.assertEqual(c.rounding, ROUND_HALF_UP)
4924 self.assertEqual(c.Emin, -3000)
4925 self.assertEqual(c.Emax, 3000)
4926 self.assertEqual(c.capitals, 1)
4927 self.assertEqual(c.clamp, 0)
4928
4929 self.assertEqual(c.Etiny(), -3033)
4930 self.assertEqual(c.Etop(), 2967)
4931
4932 # Exercise all unsafe setters
4933 if C.MAX_PREC == 425000000:
4934 c._unsafe_setprec(999999999)
4935 c._unsafe_setemax(999999999)
4936 c._unsafe_setemin(-999999999)
4937 self.assertEqual(c.prec, 999999999)
4938 self.assertEqual(c.Emax, 999999999)
4939 self.assertEqual(c.Emin, -999999999)
4940
4941 @requires_extra_functionality
4942 def test_c_valid_context_extra(self):
4943 DefaultContext = C.DefaultContext
4944
4945 c = DefaultContext.copy()
4946 self.assertEqual(c._allcr, 1)
4947 c._allcr = 0
4948 self.assertEqual(c._allcr, 0)
4949
4950 def test_c_round(self):
4951 # Restricted input.
4952 Decimal = C.Decimal
4953 InvalidOperation = C.InvalidOperation
4954 localcontext = C.localcontext
4955 MAX_EMAX = C.MAX_EMAX
4956 MIN_ETINY = C.MIN_ETINY
4957 int_max = 2**63-1 if C.MAX_PREC > 425000000 else 2**31-1
4958
4959 with localcontext() as c:
4960 c.traps[InvalidOperation] = True
4961 self.assertRaises(InvalidOperation, Decimal("1.23").__round__,
4962 -int_max-1)
4963 self.assertRaises(InvalidOperation, Decimal("1.23").__round__,
4964 int_max)
4965 self.assertRaises(InvalidOperation, Decimal("1").__round__,
4966 int(MAX_EMAX+1))
4967 self.assertRaises(C.InvalidOperation, Decimal("1").__round__,
4968 -int(MIN_ETINY-1))
4969 self.assertRaises(OverflowError, Decimal("1.23").__round__,
4970 -int_max-2)
4971 self.assertRaises(OverflowError, Decimal("1.23").__round__,
4972 int_max+1)
4973
4974 def test_c_format(self):
4975 # Restricted input
4976 Decimal = C.Decimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01004977 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
4978
4979 self.assertRaises(TypeError, Decimal(1).__format__, "=10.10", [], 9)
4980 self.assertRaises(TypeError, Decimal(1).__format__, "=10.10", 9)
4981 self.assertRaises(TypeError, Decimal(1).__format__, [])
4982
Stefan Kraheb8c4512013-01-24 15:22:33 +01004983 self.assertRaises(ValueError, Decimal(1).__format__, "<>=10.10")
4984 maxsize = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
4985 self.assertRaises(ValueError, Decimal("1.23456789").__format__,
4986 "=%d.1" % maxsize)
Stefan Krah1919b7e2012-03-21 18:25:23 +01004987
4988 def test_c_integral(self):
4989 Decimal = C.Decimal
4990 Inexact = C.Inexact
Stefan Krah1919b7e2012-03-21 18:25:23 +01004991 localcontext = C.localcontext
4992
4993 x = Decimal(10)
4994 self.assertEqual(x.to_integral(), 10)
4995 self.assertRaises(TypeError, x.to_integral, '10')
4996 self.assertRaises(TypeError, x.to_integral, 10, 'x')
4997 self.assertRaises(TypeError, x.to_integral, 10)
4998
4999 self.assertEqual(x.to_integral_value(), 10)
5000 self.assertRaises(TypeError, x.to_integral_value, '10')
5001 self.assertRaises(TypeError, x.to_integral_value, 10, 'x')
5002 self.assertRaises(TypeError, x.to_integral_value, 10)
5003
5004 self.assertEqual(x.to_integral_exact(), 10)
5005 self.assertRaises(TypeError, x.to_integral_exact, '10')
5006 self.assertRaises(TypeError, x.to_integral_exact, 10, 'x')
5007 self.assertRaises(TypeError, x.to_integral_exact, 10)
5008
5009 with localcontext() as c:
5010 x = Decimal("99999999999999999999999999.9").to_integral_value(ROUND_UP)
5011 self.assertEqual(x, Decimal('100000000000000000000000000'))
5012
5013 x = Decimal("99999999999999999999999999.9").to_integral_exact(ROUND_UP)
5014 self.assertEqual(x, Decimal('100000000000000000000000000'))
5015
5016 c.traps[Inexact] = True
5017 self.assertRaises(Inexact, Decimal("999.9").to_integral_exact, ROUND_UP)
5018
5019 def test_c_funcs(self):
5020 # Invalid arguments
5021 Decimal = C.Decimal
5022 InvalidOperation = C.InvalidOperation
5023 DivisionByZero = C.DivisionByZero
Stefan Krah1919b7e2012-03-21 18:25:23 +01005024 getcontext = C.getcontext
5025 localcontext = C.localcontext
5026
5027 self.assertEqual(Decimal('9.99e10').to_eng_string(), '99.9E+9')
5028
5029 self.assertRaises(TypeError, pow, Decimal(1), 2, "3")
5030 self.assertRaises(TypeError, Decimal(9).number_class, "x", "y")
5031 self.assertRaises(TypeError, Decimal(9).same_quantum, 3, "x", "y")
5032
Raymond Hettinger771ed762009-01-03 19:20:32 +00005033 self.assertRaises(
Stefan Krah1919b7e2012-03-21 18:25:23 +01005034 TypeError,
5035 Decimal("1.23456789").quantize, Decimal('1e-100000'), []
Raymond Hettinger771ed762009-01-03 19:20:32 +00005036 )
Stefan Krah1919b7e2012-03-21 18:25:23 +01005037 self.assertRaises(
5038 TypeError,
5039 Decimal("1.23456789").quantize, Decimal('1e-100000'), getcontext()
5040 )
5041 self.assertRaises(
5042 TypeError,
5043 Decimal("1.23456789").quantize, Decimal('1e-100000'), 10
5044 )
5045 self.assertRaises(
5046 TypeError,
5047 Decimal("1.23456789").quantize, Decimal('1e-100000'), ROUND_UP, 1000
5048 )
Raymond Hettinger771ed762009-01-03 19:20:32 +00005049
Stefan Krah1919b7e2012-03-21 18:25:23 +01005050 with localcontext() as c:
5051 c.clear_traps()
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00005052
Stefan Krah1919b7e2012-03-21 18:25:23 +01005053 # Invalid arguments
5054 self.assertRaises(TypeError, c.copy_sign, Decimal(1), "x", "y")
5055 self.assertRaises(TypeError, c.canonical, 200)
5056 self.assertRaises(TypeError, c.is_canonical, 200)
5057 self.assertRaises(TypeError, c.divmod, 9, 8, "x", "y")
5058 self.assertRaises(TypeError, c.same_quantum, 9, 3, "x", "y")
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00005059
Stefan Krah1919b7e2012-03-21 18:25:23 +01005060 self.assertEqual(str(c.canonical(Decimal(200))), '200')
5061 self.assertEqual(c.radix(), 10)
Raymond Hettinger0aeac102004-07-05 22:53:03 +00005062
Stefan Krah1919b7e2012-03-21 18:25:23 +01005063 c.traps[DivisionByZero] = True
5064 self.assertRaises(DivisionByZero, Decimal(9).__divmod__, 0)
5065 self.assertRaises(DivisionByZero, c.divmod, 9, 0)
5066 self.assertTrue(c.flags[InvalidOperation])
Raymond Hettinger955d2b22004-08-08 20:17:45 +00005067
Stefan Krah1919b7e2012-03-21 18:25:23 +01005068 c.clear_flags()
5069 c.traps[InvalidOperation] = True
5070 self.assertRaises(InvalidOperation, Decimal(9).__divmod__, 0)
5071 self.assertRaises(InvalidOperation, c.divmod, 9, 0)
5072 self.assertTrue(c.flags[DivisionByZero])
Mark Dickinsonb1d8e322010-05-22 18:35:36 +00005073
Stefan Krah1919b7e2012-03-21 18:25:23 +01005074 c.traps[InvalidOperation] = True
5075 c.prec = 2
5076 self.assertRaises(InvalidOperation, pow, Decimal(1000), 1, 501)
Mark Dickinson84230a12010-02-18 14:49:50 +00005077
Stefan Krah040e3112012-12-15 22:33:33 +01005078 def test_va_args_exceptions(self):
5079 Decimal = C.Decimal
5080 Context = C.Context
5081
5082 x = Decimal("10001111111")
5083
5084 for attr in ['exp', 'is_normal', 'is_subnormal', 'ln', 'log10',
5085 'logb', 'logical_invert', 'next_minus', 'next_plus',
5086 'normalize', 'number_class', 'sqrt', 'to_eng_string']:
5087 func = getattr(x, attr)
5088 self.assertRaises(TypeError, func, context="x")
5089 self.assertRaises(TypeError, func, "x", context=None)
5090
5091 for attr in ['compare', 'compare_signal', 'logical_and',
5092 'logical_or', 'max', 'max_mag', 'min', 'min_mag',
5093 'remainder_near', 'rotate', 'scaleb', 'shift']:
5094 func = getattr(x, attr)
5095 self.assertRaises(TypeError, func, context="x")
5096 self.assertRaises(TypeError, func, "x", context=None)
5097
5098 self.assertRaises(TypeError, x.to_integral, rounding=None, context=[])
5099 self.assertRaises(TypeError, x.to_integral, rounding={}, context=[])
5100 self.assertRaises(TypeError, x.to_integral, [], [])
5101
5102 self.assertRaises(TypeError, x.to_integral_value, rounding=None, context=[])
5103 self.assertRaises(TypeError, x.to_integral_value, rounding={}, context=[])
5104 self.assertRaises(TypeError, x.to_integral_value, [], [])
5105
5106 self.assertRaises(TypeError, x.to_integral_exact, rounding=None, context=[])
5107 self.assertRaises(TypeError, x.to_integral_exact, rounding={}, context=[])
5108 self.assertRaises(TypeError, x.to_integral_exact, [], [])
5109
5110 self.assertRaises(TypeError, x.fma, 1, 2, context="x")
5111 self.assertRaises(TypeError, x.fma, 1, 2, "x", context=None)
5112
5113 self.assertRaises(TypeError, x.quantize, 1, [], context=None)
5114 self.assertRaises(TypeError, x.quantize, 1, [], rounding=None)
5115 self.assertRaises(TypeError, x.quantize, 1, [], [])
5116
5117 c = Context()
5118 self.assertRaises(TypeError, c.power, 1, 2, mod="x")
5119 self.assertRaises(TypeError, c.power, 1, "x", mod=None)
5120 self.assertRaises(TypeError, c.power, "x", 2, mod=None)
5121
Stefan Krah1919b7e2012-03-21 18:25:23 +01005122 @requires_extra_functionality
5123 def test_c_context_templates(self):
5124 self.assertEqual(
5125 C.BasicContext._traps,
5126 C.DecIEEEInvalidOperation|C.DecDivisionByZero|C.DecOverflow|
5127 C.DecUnderflow|C.DecClamped
5128 )
5129 self.assertEqual(
5130 C.DefaultContext._traps,
5131 C.DecIEEEInvalidOperation|C.DecDivisionByZero|C.DecOverflow
5132 )
Mark Dickinson84230a12010-02-18 14:49:50 +00005133
Stefan Krah1919b7e2012-03-21 18:25:23 +01005134 @requires_extra_functionality
5135 def test_c_signal_dict(self):
Mark Dickinson84230a12010-02-18 14:49:50 +00005136
Stefan Krah1919b7e2012-03-21 18:25:23 +01005137 # SignalDict coverage
5138 Context = C.Context
5139 DefaultContext = C.DefaultContext
Mark Dickinson84230a12010-02-18 14:49:50 +00005140
Stefan Krah1919b7e2012-03-21 18:25:23 +01005141 InvalidOperation = C.InvalidOperation
5142 DivisionByZero = C.DivisionByZero
5143 Overflow = C.Overflow
5144 Subnormal = C.Subnormal
5145 Underflow = C.Underflow
5146 Rounded = C.Rounded
5147 Inexact = C.Inexact
5148 Clamped = C.Clamped
Mark Dickinson84230a12010-02-18 14:49:50 +00005149
Stefan Krah1919b7e2012-03-21 18:25:23 +01005150 DecClamped = C.DecClamped
5151 DecInvalidOperation = C.DecInvalidOperation
5152 DecIEEEInvalidOperation = C.DecIEEEInvalidOperation
Mark Dickinson84230a12010-02-18 14:49:50 +00005153
Stefan Krah1919b7e2012-03-21 18:25:23 +01005154 def assertIsExclusivelySet(signal, signal_dict):
5155 for sig in signal_dict:
5156 if sig == signal:
5157 self.assertTrue(signal_dict[sig])
5158 else:
5159 self.assertFalse(signal_dict[sig])
Mark Dickinson84230a12010-02-18 14:49:50 +00005160
Stefan Krah1919b7e2012-03-21 18:25:23 +01005161 c = DefaultContext.copy()
Mark Dickinson84230a12010-02-18 14:49:50 +00005162
Stefan Krah1919b7e2012-03-21 18:25:23 +01005163 # Signal dict methods
5164 self.assertTrue(Overflow in c.traps)
5165 c.clear_traps()
5166 for k in c.traps.keys():
5167 c.traps[k] = True
5168 for v in c.traps.values():
5169 self.assertTrue(v)
5170 c.clear_traps()
5171 for k, v in c.traps.items():
5172 self.assertFalse(v)
Mark Dickinson84230a12010-02-18 14:49:50 +00005173
Stefan Krah1919b7e2012-03-21 18:25:23 +01005174 self.assertFalse(c.flags.get(Overflow))
5175 self.assertIs(c.flags.get("x"), None)
5176 self.assertEqual(c.flags.get("x", "y"), "y")
5177 self.assertRaises(TypeError, c.flags.get, "x", "y", "z")
Mark Dickinson84230a12010-02-18 14:49:50 +00005178
Stefan Krah1919b7e2012-03-21 18:25:23 +01005179 self.assertEqual(len(c.flags), len(c.traps))
5180 s = sys.getsizeof(c.flags)
5181 s = sys.getsizeof(c.traps)
5182 s = c.flags.__repr__()
Mark Dickinson84230a12010-02-18 14:49:50 +00005183
Stefan Krah1919b7e2012-03-21 18:25:23 +01005184 # Set flags/traps.
5185 c.clear_flags()
5186 c._flags = DecClamped
5187 self.assertTrue(c.flags[Clamped])
Mark Dickinson84230a12010-02-18 14:49:50 +00005188
Stefan Krah1919b7e2012-03-21 18:25:23 +01005189 c.clear_traps()
5190 c._traps = DecInvalidOperation
5191 self.assertTrue(c.traps[InvalidOperation])
Mark Dickinson84230a12010-02-18 14:49:50 +00005192
Stefan Krah1919b7e2012-03-21 18:25:23 +01005193 # Set flags/traps from dictionary.
5194 c.clear_flags()
5195 d = c.flags.copy()
5196 d[DivisionByZero] = True
5197 c.flags = d
5198 assertIsExclusivelySet(DivisionByZero, c.flags)
Mark Dickinson84230a12010-02-18 14:49:50 +00005199
Stefan Krah1919b7e2012-03-21 18:25:23 +01005200 c.clear_traps()
5201 d = c.traps.copy()
5202 d[Underflow] = True
5203 c.traps = d
5204 assertIsExclusivelySet(Underflow, c.traps)
Mark Dickinson84230a12010-02-18 14:49:50 +00005205
Stefan Krah1919b7e2012-03-21 18:25:23 +01005206 # Random constructors
5207 IntSignals = {
5208 Clamped: C.DecClamped,
5209 Rounded: C.DecRounded,
5210 Inexact: C.DecInexact,
5211 Subnormal: C.DecSubnormal,
5212 Underflow: C.DecUnderflow,
5213 Overflow: C.DecOverflow,
5214 DivisionByZero: C.DecDivisionByZero,
5215 InvalidOperation: C.DecIEEEInvalidOperation
5216 }
5217 IntCond = [
5218 C.DecDivisionImpossible, C.DecDivisionUndefined, C.DecFpuError,
5219 C.DecInvalidContext, C.DecInvalidOperation, C.DecMallocError,
5220 C.DecConversionSyntax,
5221 ]
Mark Dickinsonb455e582011-05-22 12:53:18 +01005222
Stefan Krah1919b7e2012-03-21 18:25:23 +01005223 lim = len(OrderedSignals[C])
5224 for r in range(lim):
5225 for t in range(lim):
Stefan Krah59a4a932013-01-16 12:58:59 +01005226 for round in RoundingModes:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005227 flags = random.sample(OrderedSignals[C], r)
5228 traps = random.sample(OrderedSignals[C], t)
5229 prec = random.randrange(1, 10000)
5230 emin = random.randrange(-10000, 0)
5231 emax = random.randrange(0, 10000)
5232 clamp = random.randrange(0, 2)
5233 caps = random.randrange(0, 2)
5234 cr = random.randrange(0, 2)
5235 c = Context(prec=prec, rounding=round, Emin=emin, Emax=emax,
5236 capitals=caps, clamp=clamp, flags=list(flags),
5237 traps=list(traps))
Mark Dickinson84230a12010-02-18 14:49:50 +00005238
Stefan Krah1919b7e2012-03-21 18:25:23 +01005239 self.assertEqual(c.prec, prec)
5240 self.assertEqual(c.rounding, round)
5241 self.assertEqual(c.Emin, emin)
5242 self.assertEqual(c.Emax, emax)
5243 self.assertEqual(c.capitals, caps)
5244 self.assertEqual(c.clamp, clamp)
Mark Dickinson84230a12010-02-18 14:49:50 +00005245
Stefan Krah1919b7e2012-03-21 18:25:23 +01005246 f = 0
5247 for x in flags:
5248 f |= IntSignals[x]
5249 self.assertEqual(c._flags, f)
Mark Dickinson84230a12010-02-18 14:49:50 +00005250
Stefan Krah1919b7e2012-03-21 18:25:23 +01005251 f = 0
5252 for x in traps:
5253 f |= IntSignals[x]
5254 self.assertEqual(c._traps, f)
Mark Dickinson84230a12010-02-18 14:49:50 +00005255
Stefan Krah1919b7e2012-03-21 18:25:23 +01005256 for cond in IntCond:
5257 c._flags = cond
5258 self.assertTrue(c._flags&DecIEEEInvalidOperation)
5259 assertIsExclusivelySet(InvalidOperation, c.flags)
Mark Dickinson84230a12010-02-18 14:49:50 +00005260
Stefan Krah1919b7e2012-03-21 18:25:23 +01005261 for cond in IntCond:
5262 c._traps = cond
5263 self.assertTrue(c._traps&DecIEEEInvalidOperation)
5264 assertIsExclusivelySet(InvalidOperation, c.traps)
Mark Dickinson84230a12010-02-18 14:49:50 +00005265
Stefan Krah1919b7e2012-03-21 18:25:23 +01005266 def test_invalid_override(self):
5267 Decimal = C.Decimal
Mark Dickinson84230a12010-02-18 14:49:50 +00005268
Stefan Krah1919b7e2012-03-21 18:25:23 +01005269 try:
5270 from locale import CHAR_MAX
5271 except ImportError:
5272 return
Mark Dickinson84230a12010-02-18 14:49:50 +00005273
Stefan Krah1919b7e2012-03-21 18:25:23 +01005274 def make_grouping(lst):
5275 return ''.join([chr(x) for x in lst])
Mark Dickinson84230a12010-02-18 14:49:50 +00005276
Stefan Krah1919b7e2012-03-21 18:25:23 +01005277 def get_fmt(x, override=None, fmt='n'):
5278 return Decimal(x).__format__(fmt, override)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005279
Stefan Krah1919b7e2012-03-21 18:25:23 +01005280 invalid_grouping = {
5281 'decimal_point' : ',',
5282 'grouping' : make_grouping([255, 255, 0]),
5283 'thousands_sep' : ','
5284 }
5285 invalid_dot = {
5286 'decimal_point' : 'xxxxx',
5287 'grouping' : make_grouping([3, 3, 0]),
5288 'thousands_sep' : ','
5289 }
5290 invalid_sep = {
5291 'decimal_point' : '.',
5292 'grouping' : make_grouping([3, 3, 0]),
5293 'thousands_sep' : 'yyyyy'
5294 }
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005295
Stefan Krah1919b7e2012-03-21 18:25:23 +01005296 if CHAR_MAX == 127: # negative grouping in override
5297 self.assertRaises(ValueError, get_fmt, 12345,
5298 invalid_grouping, 'g')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005299
Stefan Krah1919b7e2012-03-21 18:25:23 +01005300 self.assertRaises(ValueError, get_fmt, 12345, invalid_dot, 'g')
5301 self.assertRaises(ValueError, get_fmt, 12345, invalid_sep, 'g')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005302
Stefan Krah0774e9b2012-04-05 15:21:58 +02005303 def test_exact_conversion(self):
5304 Decimal = C.Decimal
5305 localcontext = C.localcontext
5306 InvalidOperation = C.InvalidOperation
5307
5308 with localcontext() as c:
5309
5310 c.traps[InvalidOperation] = True
5311
5312 # Clamped
5313 x = "0e%d" % sys.maxsize
5314 self.assertRaises(InvalidOperation, Decimal, x)
5315
5316 x = "0e%d" % (-sys.maxsize-1)
5317 self.assertRaises(InvalidOperation, Decimal, x)
5318
5319 # Overflow
5320 x = "1e%d" % sys.maxsize
5321 self.assertRaises(InvalidOperation, Decimal, x)
5322
5323 # Underflow
5324 x = "1e%d" % (-sys.maxsize-1)
5325 self.assertRaises(InvalidOperation, Decimal, x)
5326
Stefan Krahff3eca02012-04-05 15:46:19 +02005327 def test_from_tuple(self):
5328 Decimal = C.Decimal
5329 localcontext = C.localcontext
5330 InvalidOperation = C.InvalidOperation
5331 Overflow = C.Overflow
5332 Underflow = C.Underflow
5333
5334 with localcontext() as c:
5335
5336 c.traps[InvalidOperation] = True
5337 c.traps[Overflow] = True
5338 c.traps[Underflow] = True
5339
5340 # SSIZE_MAX
5341 x = (1, (), sys.maxsize)
5342 self.assertEqual(str(c.create_decimal(x)), '-0E+999999')
5343 self.assertRaises(InvalidOperation, Decimal, x)
5344
5345 x = (1, (0, 1, 2), sys.maxsize)
5346 self.assertRaises(Overflow, c.create_decimal, x)
5347 self.assertRaises(InvalidOperation, Decimal, x)
5348
5349 # SSIZE_MIN
5350 x = (1, (), -sys.maxsize-1)
5351 self.assertEqual(str(c.create_decimal(x)), '-0E-1000026')
5352 self.assertRaises(InvalidOperation, Decimal, x)
5353
5354 x = (1, (0, 1, 2), -sys.maxsize-1)
5355 self.assertRaises(Underflow, c.create_decimal, x)
5356 self.assertRaises(InvalidOperation, Decimal, x)
5357
5358 # OverflowError
5359 x = (1, (), sys.maxsize+1)
5360 self.assertRaises(OverflowError, c.create_decimal, x)
5361 self.assertRaises(OverflowError, Decimal, x)
5362
5363 x = (1, (), -sys.maxsize-2)
5364 self.assertRaises(OverflowError, c.create_decimal, x)
5365 self.assertRaises(OverflowError, Decimal, x)
5366
5367 # Specials
5368 x = (1, (), "N")
5369 self.assertEqual(str(Decimal(x)), '-sNaN')
5370 x = (1, (0,), "N")
5371 self.assertEqual(str(Decimal(x)), '-sNaN')
5372 x = (1, (0, 1), "N")
5373 self.assertEqual(str(Decimal(x)), '-sNaN1')
5374
Stefan Krah2e537f92013-05-29 18:50:06 +02005375 def test_sizeof(self):
5376 Decimal = C.Decimal
5377 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
5378
5379 self.assertGreater(Decimal(0).__sizeof__(), 0)
5380 if HAVE_CONFIG_64:
5381 x = Decimal(10**(19*24)).__sizeof__()
5382 y = Decimal(10**(19*25)).__sizeof__()
5383 self.assertEqual(y, x+8)
5384 else:
5385 x = Decimal(10**(9*24)).__sizeof__()
5386 y = Decimal(10**(9*25)).__sizeof__()
5387 self.assertEqual(y, x+4)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005388
Stefan Krah1919b7e2012-03-21 18:25:23 +01005389all_tests = [
5390 CExplicitConstructionTest, PyExplicitConstructionTest,
5391 CImplicitConstructionTest, PyImplicitConstructionTest,
5392 CFormatTest, PyFormatTest,
5393 CArithmeticOperatorsTest, PyArithmeticOperatorsTest,
5394 CThreadingTest, PyThreadingTest,
5395 CUsabilityTest, PyUsabilityTest,
5396 CPythonAPItests, PyPythonAPItests,
5397 CContextAPItests, PyContextAPItests,
5398 CContextWithStatement, PyContextWithStatement,
5399 CContextFlags, PyContextFlags,
5400 CSpecialContexts, PySpecialContexts,
5401 CContextInputValidation, PyContextInputValidation,
5402 CContextSubclassing, PyContextSubclassing,
5403 CCoverage, PyCoverage,
5404 CFunctionality, PyFunctionality,
5405 CWhitebox, PyWhitebox,
5406 CIBMTestCases, PyIBMTestCases,
5407]
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005408
Stefan Krah1919b7e2012-03-21 18:25:23 +01005409# Delete C tests if _decimal.so is not present.
5410if not C:
5411 all_tests = all_tests[1::2]
5412else:
5413 all_tests.insert(0, CheckAttributes)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005414
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005415
5416def test_main(arith=False, verbose=None, todo_tests=None, debug=None):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005417 """ Execute the tests.
5418
Raymond Hettingered20ad82004-09-04 20:09:13 +00005419 Runs all arithmetic tests if arith is True or if the "decimal" resource
5420 is enabled in regrtest.py
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005421 """
Raymond Hettingered20ad82004-09-04 20:09:13 +00005422
Stefan Krah1919b7e2012-03-21 18:25:23 +01005423 init(C)
5424 init(P)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005425 global TEST_ALL, DEBUG
Raymond Hettingered20ad82004-09-04 20:09:13 +00005426 TEST_ALL = arith or is_resource_enabled('decimal')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005427 DEBUG = debug
Raymond Hettingered20ad82004-09-04 20:09:13 +00005428
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005429 if todo_tests is None:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005430 test_classes = all_tests
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005431 else:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005432 test_classes = [CIBMTestCases, PyIBMTestCases]
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005433
5434 # Dynamically build custom test definition for each file in the test
5435 # directory and add the definitions to the DecimalTest class. This
5436 # procedure insures that new files do not get skipped.
5437 for filename in os.listdir(directory):
5438 if '.decTest' not in filename or filename.startswith("."):
5439 continue
5440 head, tail = filename.split('.')
5441 if todo_tests is not None and head not in todo_tests:
5442 continue
5443 tester = lambda self, f=filename: self.eval_file(directory + f)
Stefan Krah1919b7e2012-03-21 18:25:23 +01005444 setattr(CIBMTestCases, 'test_' + head, tester)
5445 setattr(PyIBMTestCases, 'test_' + head, tester)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005446 del filename, head, tail, tester
5447
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005448
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005449 try:
5450 run_unittest(*test_classes)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005451 if todo_tests is None:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005452 from doctest import IGNORE_EXCEPTION_DETAIL
5453 savedecimal = sys.modules['decimal']
5454 if C:
5455 sys.modules['decimal'] = C
5456 run_doctest(C, verbose, optionflags=IGNORE_EXCEPTION_DETAIL)
5457 sys.modules['decimal'] = P
5458 run_doctest(P, verbose)
5459 sys.modules['decimal'] = savedecimal
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005460 finally:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005461 if C: C.setcontext(ORIGINAL_CONTEXT[C])
5462 P.setcontext(ORIGINAL_CONTEXT[P])
5463 if not C:
5464 warnings.warn('C tests skipped: no module named _decimal.',
5465 UserWarning)
5466 if not orig_sys_decimal is sys.modules['decimal']:
5467 raise TestFailed("Internal error: unbalanced number of changes to "
5468 "sys.modules['decimal'].")
5469
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005470
5471if __name__ == '__main__':
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005472 import optparse
5473 p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]")
5474 p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test')
5475 p.add_option('--skip', '-s', action='store_true', help='skip over 90% of the arithmetic tests')
5476 (opt, args) = p.parse_args()
5477
5478 if opt.skip:
5479 test_main(arith=False, verbose=True)
5480 elif args:
5481 test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005482 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005483 test_main(arith=True, verbose=True)