blob: 7fcd2a82cb3fc4648ba36c13d2182aed1cfb0bc8 [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'),
1023
1024 # thousands separator
1025 (',', '1234567', '1,234,567'),
1026 (',', '123456', '123,456'),
1027 (',', '12345', '12,345'),
1028 (',', '1234', '1,234'),
1029 (',', '123', '123'),
1030 (',', '12', '12'),
1031 (',', '1', '1'),
1032 (',', '0', '0'),
1033 (',', '-1234567', '-1,234,567'),
1034 (',', '-123456', '-123,456'),
1035 ('7,', '123456', '123,456'),
Mark Dickinson46ab5d02009-09-08 20:22:46 +00001036 ('8,', '123456', ' 123,456'),
Mark Dickinson79f52032009-03-17 23:12:51 +00001037 ('08,', '123456', '0,123,456'), # special case: extra 0 needed
1038 ('+08,', '123456', '+123,456'), # but not if there's a sign
1039 (' 08,', '123456', ' 123,456'),
1040 ('08,', '-123456', '-123,456'),
1041 ('+09,', '123456', '+0,123,456'),
1042 # ... with fractional part...
1043 ('07,', '1234.56', '1,234.56'),
1044 ('08,', '1234.56', '1,234.56'),
1045 ('09,', '1234.56', '01,234.56'),
1046 ('010,', '1234.56', '001,234.56'),
1047 ('011,', '1234.56', '0,001,234.56'),
1048 ('012,', '1234.56', '0,001,234.56'),
1049 ('08,.1f', '1234.5', '01,234.5'),
1050 # no thousands separators in fraction part
1051 (',', '1.23456789', '1.23456789'),
1052 (',%', '123.456789', '12,345.6789%'),
1053 (',e', '123456', '1.23456e+5'),
1054 (',E', '123456', '1.23456E+5'),
Mark Dickinson7718d2b2009-09-07 16:21:56 +00001055
1056 # issue 6850
1057 ('a=-7.0', '0.12345', 'aaaa0.1'),
Christian Heimesf16baeb2008-02-29 14:57:44 +00001058 ]
1059 for fmt, d, result in test_values:
1060 self.assertEqual(format(Decimal(d), fmt), result)
1061
Stefan Krah1919b7e2012-03-21 18:25:23 +01001062 # bytes format argument
1063 self.assertRaises(TypeError, Decimal(1).__format__, b'-020')
1064
Mark Dickinson79f52032009-03-17 23:12:51 +00001065 def test_n_format(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001066 Decimal = self.decimal.Decimal
1067
Mark Dickinson79f52032009-03-17 23:12:51 +00001068 try:
1069 from locale import CHAR_MAX
1070 except ImportError:
1071 return
1072
Stefan Krah1919b7e2012-03-21 18:25:23 +01001073 def make_grouping(lst):
1074 return ''.join([chr(x) for x in lst]) if self.decimal == C else lst
1075
1076 def get_fmt(x, override=None, fmt='n'):
1077 if self.decimal == C:
1078 return Decimal(x).__format__(fmt, override)
1079 else:
1080 return Decimal(x).__format__(fmt, _localeconv=override)
1081
Mark Dickinson79f52032009-03-17 23:12:51 +00001082 # Set up some localeconv-like dictionaries
1083 en_US = {
1084 'decimal_point' : '.',
Stefan Krah1919b7e2012-03-21 18:25:23 +01001085 'grouping' : make_grouping([3, 3, 0]),
1086 'thousands_sep' : ','
Mark Dickinson79f52032009-03-17 23:12:51 +00001087 }
1088
1089 fr_FR = {
1090 'decimal_point' : ',',
Stefan Krah1919b7e2012-03-21 18:25:23 +01001091 'grouping' : make_grouping([CHAR_MAX]),
Mark Dickinson79f52032009-03-17 23:12:51 +00001092 'thousands_sep' : ''
1093 }
1094
1095 ru_RU = {
1096 'decimal_point' : ',',
Stefan Krah1919b7e2012-03-21 18:25:23 +01001097 'grouping': make_grouping([3, 3, 0]),
Mark Dickinson79f52032009-03-17 23:12:51 +00001098 'thousands_sep' : ' '
1099 }
1100
1101 crazy = {
1102 'decimal_point' : '&',
Stefan Krah1919b7e2012-03-21 18:25:23 +01001103 'grouping': make_grouping([1, 4, 2, CHAR_MAX]),
Mark Dickinson79f52032009-03-17 23:12:51 +00001104 'thousands_sep' : '-'
1105 }
1106
Stefan Krah1919b7e2012-03-21 18:25:23 +01001107 dotsep_wide = {
1108 'decimal_point' : b'\xc2\xbf'.decode('utf-8'),
1109 'grouping': make_grouping([3, 3, 0]),
1110 'thousands_sep' : b'\xc2\xb4'.decode('utf-8')
1111 }
Mark Dickinson79f52032009-03-17 23:12:51 +00001112
1113 self.assertEqual(get_fmt(Decimal('12.7'), en_US), '12.7')
1114 self.assertEqual(get_fmt(Decimal('12.7'), fr_FR), '12,7')
1115 self.assertEqual(get_fmt(Decimal('12.7'), ru_RU), '12,7')
1116 self.assertEqual(get_fmt(Decimal('12.7'), crazy), '1-2&7')
1117
1118 self.assertEqual(get_fmt(123456789, en_US), '123,456,789')
1119 self.assertEqual(get_fmt(123456789, fr_FR), '123456789')
1120 self.assertEqual(get_fmt(123456789, ru_RU), '123 456 789')
1121 self.assertEqual(get_fmt(1234567890123, crazy), '123456-78-9012-3')
1122
1123 self.assertEqual(get_fmt(123456789, en_US, '.6n'), '1.23457e+8')
1124 self.assertEqual(get_fmt(123456789, fr_FR, '.6n'), '1,23457e+8')
1125 self.assertEqual(get_fmt(123456789, ru_RU, '.6n'), '1,23457e+8')
1126 self.assertEqual(get_fmt(123456789, crazy, '.6n'), '1&23457e+8')
1127
Mark Dickinson7303b592009-03-18 08:25:36 +00001128 # zero padding
1129 self.assertEqual(get_fmt(1234, fr_FR, '03n'), '1234')
1130 self.assertEqual(get_fmt(1234, fr_FR, '04n'), '1234')
1131 self.assertEqual(get_fmt(1234, fr_FR, '05n'), '01234')
1132 self.assertEqual(get_fmt(1234, fr_FR, '06n'), '001234')
1133
1134 self.assertEqual(get_fmt(12345, en_US, '05n'), '12,345')
1135 self.assertEqual(get_fmt(12345, en_US, '06n'), '12,345')
1136 self.assertEqual(get_fmt(12345, en_US, '07n'), '012,345')
1137 self.assertEqual(get_fmt(12345, en_US, '08n'), '0,012,345')
1138 self.assertEqual(get_fmt(12345, en_US, '09n'), '0,012,345')
1139 self.assertEqual(get_fmt(12345, en_US, '010n'), '00,012,345')
1140
1141 self.assertEqual(get_fmt(123456, crazy, '06n'), '1-2345-6')
1142 self.assertEqual(get_fmt(123456, crazy, '07n'), '1-2345-6')
1143 self.assertEqual(get_fmt(123456, crazy, '08n'), '1-2345-6')
1144 self.assertEqual(get_fmt(123456, crazy, '09n'), '01-2345-6')
1145 self.assertEqual(get_fmt(123456, crazy, '010n'), '0-01-2345-6')
1146 self.assertEqual(get_fmt(123456, crazy, '011n'), '0-01-2345-6')
1147 self.assertEqual(get_fmt(123456, crazy, '012n'), '00-01-2345-6')
1148 self.assertEqual(get_fmt(123456, crazy, '013n'), '000-01-2345-6')
1149
Stefan Krah1919b7e2012-03-21 18:25:23 +01001150 # wide char separator and decimal point
1151 self.assertEqual(get_fmt(Decimal('-1.5'), dotsep_wide, '020n'),
1152 '-0\u00b4000\u00b4000\u00b4000\u00b4001\u00bf5')
Mark Dickinson79f52032009-03-17 23:12:51 +00001153
Stefan Krah6fb204a2012-09-28 16:18:54 +02001154 @run_with_locale('LC_ALL', 'ps_AF')
Stefan Krah1919b7e2012-03-21 18:25:23 +01001155 def test_wide_char_separator_decimal_point(self):
1156 # locale with wide char separator and decimal point
Stefan Krah8a491a82012-09-28 17:17:11 +02001157 import locale
Stefan Krah1919b7e2012-03-21 18:25:23 +01001158 Decimal = self.decimal.Decimal
1159
Stefan Krah8a491a82012-09-28 17:17:11 +02001160 decimal_point = locale.localeconv()['decimal_point']
1161 thousands_sep = locale.localeconv()['thousands_sep']
1162 if decimal_point != '\u066b' or thousands_sep != '\u066c':
1163 return
1164
Stefan Krah1919b7e2012-03-21 18:25:23 +01001165 self.assertEqual(format(Decimal('100000000.123'), 'n'),
1166 '100\u066c000\u066c000\u066b123')
Stefan Krah1919b7e2012-03-21 18:25:23 +01001167
1168class CFormatTest(FormatTest):
1169 decimal = C
1170class PyFormatTest(FormatTest):
1171 decimal = P
1172
1173class ArithmeticOperatorsTest(unittest.TestCase):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001174 '''Unit tests for all arithmetic operators, binary and unary.'''
1175
1176 def test_addition(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001177 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001178
1179 d1 = Decimal('-11.1')
1180 d2 = Decimal('22.2')
1181
1182 #two Decimals
1183 self.assertEqual(d1+d2, Decimal('11.1'))
1184 self.assertEqual(d2+d1, Decimal('11.1'))
1185
1186 #with other type, left
1187 c = d1 + 5
1188 self.assertEqual(c, Decimal('-6.1'))
1189 self.assertEqual(type(c), type(d1))
1190
1191 #with other type, right
1192 c = 5 + d1
1193 self.assertEqual(c, Decimal('-6.1'))
1194 self.assertEqual(type(c), type(d1))
1195
1196 #inline with decimal
1197 d1 += d2
1198 self.assertEqual(d1, Decimal('11.1'))
1199
1200 #inline with other type
1201 d1 += 5
1202 self.assertEqual(d1, Decimal('16.1'))
1203
1204 def test_subtraction(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001205 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001206
1207 d1 = Decimal('-11.1')
1208 d2 = Decimal('22.2')
1209
1210 #two Decimals
1211 self.assertEqual(d1-d2, Decimal('-33.3'))
1212 self.assertEqual(d2-d1, Decimal('33.3'))
1213
1214 #with other type, left
1215 c = d1 - 5
1216 self.assertEqual(c, Decimal('-16.1'))
1217 self.assertEqual(type(c), type(d1))
1218
1219 #with other type, right
1220 c = 5 - d1
1221 self.assertEqual(c, Decimal('16.1'))
1222 self.assertEqual(type(c), type(d1))
1223
1224 #inline with decimal
1225 d1 -= d2
1226 self.assertEqual(d1, Decimal('-33.3'))
1227
1228 #inline with other type
1229 d1 -= 5
1230 self.assertEqual(d1, Decimal('-38.3'))
1231
1232 def test_multiplication(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001233 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001234
1235 d1 = Decimal('-5')
1236 d2 = Decimal('3')
1237
1238 #two Decimals
1239 self.assertEqual(d1*d2, Decimal('-15'))
1240 self.assertEqual(d2*d1, Decimal('-15'))
1241
1242 #with other type, left
1243 c = d1 * 5
1244 self.assertEqual(c, Decimal('-25'))
1245 self.assertEqual(type(c), type(d1))
1246
1247 #with other type, right
1248 c = 5 * d1
1249 self.assertEqual(c, Decimal('-25'))
1250 self.assertEqual(type(c), type(d1))
1251
1252 #inline with decimal
1253 d1 *= d2
1254 self.assertEqual(d1, Decimal('-15'))
1255
1256 #inline with other type
1257 d1 *= 5
1258 self.assertEqual(d1, Decimal('-75'))
1259
1260 def test_division(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001261 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001262
1263 d1 = Decimal('-5')
1264 d2 = Decimal('2')
1265
1266 #two Decimals
1267 self.assertEqual(d1/d2, Decimal('-2.5'))
1268 self.assertEqual(d2/d1, Decimal('-0.4'))
1269
1270 #with other type, left
1271 c = d1 / 4
1272 self.assertEqual(c, Decimal('-1.25'))
1273 self.assertEqual(type(c), type(d1))
1274
1275 #with other type, right
1276 c = 4 / d1
1277 self.assertEqual(c, Decimal('-0.8'))
1278 self.assertEqual(type(c), type(d1))
1279
1280 #inline with decimal
1281 d1 /= d2
1282 self.assertEqual(d1, Decimal('-2.5'))
1283
1284 #inline with other type
1285 d1 /= 4
1286 self.assertEqual(d1, Decimal('-0.625'))
1287
1288 def test_floor_division(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001289 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001290
1291 d1 = Decimal('5')
1292 d2 = Decimal('2')
1293
1294 #two Decimals
1295 self.assertEqual(d1//d2, Decimal('2'))
1296 self.assertEqual(d2//d1, Decimal('0'))
1297
1298 #with other type, left
1299 c = d1 // 4
1300 self.assertEqual(c, Decimal('1'))
1301 self.assertEqual(type(c), type(d1))
1302
1303 #with other type, right
1304 c = 7 // d1
1305 self.assertEqual(c, Decimal('1'))
1306 self.assertEqual(type(c), type(d1))
1307
1308 #inline with decimal
1309 d1 //= d2
1310 self.assertEqual(d1, Decimal('2'))
1311
1312 #inline with other type
1313 d1 //= 2
1314 self.assertEqual(d1, Decimal('1'))
1315
1316 def test_powering(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001317 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001318
1319 d1 = Decimal('5')
1320 d2 = Decimal('2')
1321
1322 #two Decimals
1323 self.assertEqual(d1**d2, Decimal('25'))
1324 self.assertEqual(d2**d1, Decimal('32'))
1325
1326 #with other type, left
1327 c = d1 ** 4
1328 self.assertEqual(c, Decimal('625'))
1329 self.assertEqual(type(c), type(d1))
1330
1331 #with other type, right
1332 c = 7 ** d1
1333 self.assertEqual(c, Decimal('16807'))
1334 self.assertEqual(type(c), type(d1))
1335
1336 #inline with decimal
1337 d1 **= d2
1338 self.assertEqual(d1, Decimal('25'))
1339
1340 #inline with other type
1341 d1 **= 4
1342 self.assertEqual(d1, Decimal('390625'))
1343
1344 def test_module(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001345 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001346
1347 d1 = Decimal('5')
1348 d2 = Decimal('2')
1349
1350 #two Decimals
1351 self.assertEqual(d1%d2, Decimal('1'))
1352 self.assertEqual(d2%d1, Decimal('2'))
1353
1354 #with other type, left
1355 c = d1 % 4
1356 self.assertEqual(c, Decimal('1'))
1357 self.assertEqual(type(c), type(d1))
1358
1359 #with other type, right
1360 c = 7 % d1
1361 self.assertEqual(c, Decimal('2'))
1362 self.assertEqual(type(c), type(d1))
1363
1364 #inline with decimal
1365 d1 %= d2
1366 self.assertEqual(d1, Decimal('1'))
1367
1368 #inline with other type
1369 d1 %= 4
1370 self.assertEqual(d1, Decimal('1'))
1371
1372 def test_floor_div_module(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001373 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001374
1375 d1 = Decimal('5')
1376 d2 = Decimal('2')
1377
1378 #two Decimals
1379 (p, q) = divmod(d1, d2)
1380 self.assertEqual(p, Decimal('2'))
1381 self.assertEqual(q, Decimal('1'))
1382 self.assertEqual(type(p), type(d1))
1383 self.assertEqual(type(q), type(d1))
1384
1385 #with other type, left
1386 (p, q) = divmod(d1, 4)
1387 self.assertEqual(p, Decimal('1'))
1388 self.assertEqual(q, Decimal('1'))
1389 self.assertEqual(type(p), type(d1))
1390 self.assertEqual(type(q), type(d1))
1391
1392 #with other type, right
1393 (p, q) = divmod(7, d1)
1394 self.assertEqual(p, Decimal('1'))
1395 self.assertEqual(q, Decimal('2'))
1396 self.assertEqual(type(p), type(d1))
1397 self.assertEqual(type(q), type(d1))
1398
1399 def test_unary_operators(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001400 Decimal = self.decimal.Decimal
1401
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001402 self.assertEqual(+Decimal(45), Decimal(+45)) # +
1403 self.assertEqual(-Decimal(45), Decimal(-45)) # -
1404 self.assertEqual(abs(Decimal(45)), abs(Decimal(-45))) # abs
1405
Christian Heimes77c02eb2008-02-09 02:18:51 +00001406 def test_nan_comparisons(self):
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001407 # comparisons involving signaling nans signal InvalidOperation
1408
1409 # order comparisons (<, <=, >, >=) involving only quiet nans
1410 # also signal InvalidOperation
1411
1412 # equality comparisons (==, !=) involving only quiet nans
1413 # don't signal, but return False or True respectively.
Stefan Krah1919b7e2012-03-21 18:25:23 +01001414 Decimal = self.decimal.Decimal
1415 InvalidOperation = self.decimal.InvalidOperation
1416 localcontext = self.decimal.localcontext
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001417
Christian Heimes77c02eb2008-02-09 02:18:51 +00001418 n = Decimal('NaN')
1419 s = Decimal('sNaN')
1420 i = Decimal('Inf')
1421 f = Decimal('2')
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001422
1423 qnan_pairs = (n, n), (n, i), (i, n), (n, f), (f, n)
1424 snan_pairs = (s, n), (n, s), (s, i), (i, s), (s, f), (f, s), (s, s)
1425 order_ops = operator.lt, operator.le, operator.gt, operator.ge
1426 equality_ops = operator.eq, operator.ne
1427
1428 # results when InvalidOperation is not trapped
1429 for x, y in qnan_pairs + snan_pairs:
1430 for op in order_ops + equality_ops:
1431 got = op(x, y)
1432 expected = True if op is operator.ne else False
1433 self.assertIs(expected, got,
1434 "expected {0!r} for operator.{1}({2!r}, {3!r}); "
1435 "got {4!r}".format(
1436 expected, op.__name__, x, y, got))
1437
1438 # repeat the above, but this time trap the InvalidOperation
1439 with localcontext() as ctx:
1440 ctx.traps[InvalidOperation] = 1
1441
1442 for x, y in qnan_pairs:
1443 for op in equality_ops:
1444 got = op(x, y)
1445 expected = True if op is operator.ne else False
1446 self.assertIs(expected, got,
1447 "expected {0!r} for "
1448 "operator.{1}({2!r}, {3!r}); "
1449 "got {4!r}".format(
1450 expected, op.__name__, x, y, got))
1451
1452 for x, y in snan_pairs:
1453 for op in equality_ops:
1454 self.assertRaises(InvalidOperation, operator.eq, x, y)
1455 self.assertRaises(InvalidOperation, operator.ne, x, y)
1456
1457 for x, y in qnan_pairs + snan_pairs:
1458 for op in order_ops:
1459 self.assertRaises(InvalidOperation, op, x, y)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001460
Mark Dickinson84230a12010-02-18 14:49:50 +00001461 def test_copy_sign(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001462 Decimal = self.decimal.Decimal
Mark Dickinson84230a12010-02-18 14:49:50 +00001463
Stefan Krah1919b7e2012-03-21 18:25:23 +01001464 d = Decimal(1).copy_sign(Decimal(-2))
Mark Dickinson84230a12010-02-18 14:49:50 +00001465 self.assertEqual(Decimal(1).copy_sign(-2), d)
1466 self.assertRaises(TypeError, Decimal(1).copy_sign, '-2')
1467
Stefan Krah1919b7e2012-03-21 18:25:23 +01001468class CArithmeticOperatorsTest(ArithmeticOperatorsTest):
1469 decimal = C
1470class PyArithmeticOperatorsTest(ArithmeticOperatorsTest):
1471 decimal = P
1472
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001473# The following are two functions used to test threading in the next class
1474
1475def thfunc1(cls):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001476 Decimal = cls.decimal.Decimal
1477 InvalidOperation = cls.decimal.InvalidOperation
1478 DivisionByZero = cls.decimal.DivisionByZero
1479 Overflow = cls.decimal.Overflow
1480 Underflow = cls.decimal.Underflow
1481 Inexact = cls.decimal.Inexact
1482 getcontext = cls.decimal.getcontext
1483 localcontext = cls.decimal.localcontext
1484
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001485 d1 = Decimal(1)
1486 d3 = Decimal(3)
Christian Heimesfe337bf2008-03-23 21:54:12 +00001487 test1 = d1/d3
Christian Heimesfe337bf2008-03-23 21:54:12 +00001488
Stefan Krah1919b7e2012-03-21 18:25:23 +01001489 cls.finish1.set()
1490 cls.synchro.wait()
1491
1492 test2 = d1/d3
1493 with localcontext() as c2:
1494 cls.assertTrue(c2.flags[Inexact])
1495 cls.assertRaises(DivisionByZero, c2.divide, d1, 0)
1496 cls.assertTrue(c2.flags[DivisionByZero])
1497 with localcontext() as c3:
1498 cls.assertTrue(c3.flags[Inexact])
1499 cls.assertTrue(c3.flags[DivisionByZero])
1500 cls.assertRaises(InvalidOperation, c3.compare, d1, Decimal('sNaN'))
1501 cls.assertTrue(c3.flags[InvalidOperation])
1502 del c3
1503 cls.assertFalse(c2.flags[InvalidOperation])
1504 del c2
1505
1506 cls.assertEqual(test1, Decimal('0.333333333333333333333333'))
1507 cls.assertEqual(test2, Decimal('0.333333333333333333333333'))
1508
1509 c1 = getcontext()
1510 cls.assertTrue(c1.flags[Inexact])
1511 for sig in Overflow, Underflow, DivisionByZero, InvalidOperation:
1512 cls.assertFalse(c1.flags[sig])
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001513 return
1514
1515def thfunc2(cls):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001516 Decimal = cls.decimal.Decimal
1517 InvalidOperation = cls.decimal.InvalidOperation
1518 DivisionByZero = cls.decimal.DivisionByZero
1519 Overflow = cls.decimal.Overflow
1520 Underflow = cls.decimal.Underflow
1521 Inexact = cls.decimal.Inexact
1522 getcontext = cls.decimal.getcontext
1523 localcontext = cls.decimal.localcontext
1524
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001525 d1 = Decimal(1)
1526 d3 = Decimal(3)
Christian Heimesfe337bf2008-03-23 21:54:12 +00001527 test1 = d1/d3
Stefan Krah1919b7e2012-03-21 18:25:23 +01001528
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001529 thiscontext = getcontext()
1530 thiscontext.prec = 18
Christian Heimesfe337bf2008-03-23 21:54:12 +00001531 test2 = d1/d3
Stefan Krah1919b7e2012-03-21 18:25:23 +01001532
1533 with localcontext() as c2:
1534 cls.assertTrue(c2.flags[Inexact])
1535 cls.assertRaises(Overflow, c2.multiply, Decimal('1e425000000'), 999)
1536 cls.assertTrue(c2.flags[Overflow])
1537 with localcontext(thiscontext) as c3:
1538 cls.assertTrue(c3.flags[Inexact])
1539 cls.assertFalse(c3.flags[Overflow])
1540 c3.traps[Underflow] = True
1541 cls.assertRaises(Underflow, c3.divide, Decimal('1e-425000000'), 999)
1542 cls.assertTrue(c3.flags[Underflow])
1543 del c3
1544 cls.assertFalse(c2.flags[Underflow])
1545 cls.assertFalse(c2.traps[Underflow])
1546 del c2
1547
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001548 cls.synchro.set()
1549 cls.finish2.set()
Christian Heimesfe337bf2008-03-23 21:54:12 +00001550
Stefan Krah1919b7e2012-03-21 18:25:23 +01001551 cls.assertEqual(test1, Decimal('0.333333333333333333333333'))
Christian Heimesfe337bf2008-03-23 21:54:12 +00001552 cls.assertEqual(test2, Decimal('0.333333333333333333'))
Stefan Krah1919b7e2012-03-21 18:25:23 +01001553
1554 cls.assertFalse(thiscontext.traps[Underflow])
1555 cls.assertTrue(thiscontext.flags[Inexact])
1556 for sig in Overflow, Underflow, DivisionByZero, InvalidOperation:
1557 cls.assertFalse(thiscontext.flags[sig])
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001558 return
1559
Stefan Krah1919b7e2012-03-21 18:25:23 +01001560class ThreadingTest(unittest.TestCase):
1561 '''Unit tests for thread local contexts in Decimal.'''
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001562
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001563 # Take care executing this test from IDLE, there's an issue in threading
1564 # that hangs IDLE and I couldn't find it
1565
1566 def test_threading(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001567 DefaultContext = self.decimal.DefaultContext
1568
1569 if self.decimal == C and not self.decimal.HAVE_THREADS:
1570 self.skipTest("compiled without threading")
1571 # Test the "threading isolation" of a Context. Also test changing
1572 # the DefaultContext, which acts as a template for the thread-local
1573 # contexts.
1574 save_prec = DefaultContext.prec
1575 save_emax = DefaultContext.Emax
1576 save_emin = DefaultContext.Emin
1577 DefaultContext.prec = 24
1578 DefaultContext.Emax = 425000000
1579 DefaultContext.Emin = -425000000
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001580
1581 self.synchro = threading.Event()
1582 self.finish1 = threading.Event()
1583 self.finish2 = threading.Event()
1584
1585 th1 = threading.Thread(target=thfunc1, args=(self,))
1586 th2 = threading.Thread(target=thfunc2, args=(self,))
1587
1588 th1.start()
1589 th2.start()
1590
1591 self.finish1.wait()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001592 self.finish2.wait()
Stefan Krah1919b7e2012-03-21 18:25:23 +01001593
1594 for sig in Signals[self.decimal]:
1595 self.assertFalse(DefaultContext.flags[sig])
1596
1597 DefaultContext.prec = save_prec
1598 DefaultContext.Emax = save_emax
1599 DefaultContext.Emin = save_emin
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001600 return
1601
Stefan Krah1919b7e2012-03-21 18:25:23 +01001602@unittest.skipUnless(threading, 'threading required')
1603class CThreadingTest(ThreadingTest):
1604 decimal = C
1605@unittest.skipUnless(threading, 'threading required')
1606class PyThreadingTest(ThreadingTest):
1607 decimal = P
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001608
Stefan Krah1919b7e2012-03-21 18:25:23 +01001609class UsabilityTest(unittest.TestCase):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001610 '''Unit tests for Usability cases of Decimal.'''
1611
1612 def test_comparison_operators(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001613
Stefan Krah1919b7e2012-03-21 18:25:23 +01001614 Decimal = self.decimal.Decimal
1615
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001616 da = Decimal('23.42')
1617 db = Decimal('23.42')
1618 dc = Decimal('45')
1619
1620 #two Decimals
Ezio Melotti6607d512010-04-03 14:59:49 +00001621 self.assertGreater(dc, da)
1622 self.assertGreaterEqual(dc, da)
1623 self.assertLess(da, dc)
1624 self.assertLessEqual(da, dc)
Guido van Rossume61fd5b2007-07-11 12:20:59 +00001625 self.assertEqual(da, db)
Ezio Melotti6607d512010-04-03 14:59:49 +00001626 self.assertNotEqual(da, dc)
1627 self.assertLessEqual(da, db)
1628 self.assertGreaterEqual(da, db)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001629
1630 #a Decimal and an int
Ezio Melotti6607d512010-04-03 14:59:49 +00001631 self.assertGreater(dc, 23)
1632 self.assertLess(23, dc)
Guido van Rossume61fd5b2007-07-11 12:20:59 +00001633 self.assertEqual(dc, 45)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001634
1635 #a Decimal and uncomparable
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001636 self.assertNotEqual(da, 'ugly')
1637 self.assertNotEqual(da, 32.7)
1638 self.assertNotEqual(da, object())
1639 self.assertNotEqual(da, object)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001640
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001641 # sortable
Guido van Rossumc1f779c2007-07-03 08:25:58 +00001642 a = list(map(Decimal, range(100)))
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001643 b = a[:]
1644 random.shuffle(a)
1645 a.sort()
1646 self.assertEqual(a, b)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001647
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001648 def test_decimal_float_comparison(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001649 Decimal = self.decimal.Decimal
1650
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001651 da = Decimal('0.25')
1652 db = Decimal('3.0')
Ezio Melotti6607d512010-04-03 14:59:49 +00001653 self.assertLess(da, 3.0)
1654 self.assertLessEqual(da, 3.0)
1655 self.assertGreater(db, 0.25)
1656 self.assertGreaterEqual(db, 0.25)
1657 self.assertNotEqual(da, 1.5)
1658 self.assertEqual(da, 0.25)
1659 self.assertGreater(3.0, da)
1660 self.assertGreaterEqual(3.0, da)
1661 self.assertLess(0.25, db)
1662 self.assertLessEqual(0.25, db)
1663 self.assertNotEqual(0.25, db)
1664 self.assertEqual(3.0, db)
1665 self.assertNotEqual(0.1, Decimal('0.1'))
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001666
Stefan Krah1919b7e2012-03-21 18:25:23 +01001667 def test_decimal_complex_comparison(self):
1668 Decimal = self.decimal.Decimal
1669
1670 da = Decimal('0.25')
1671 db = Decimal('3.0')
1672 self.assertNotEqual(da, (1.5+0j))
1673 self.assertNotEqual((1.5+0j), da)
1674 self.assertEqual(da, (0.25+0j))
1675 self.assertEqual((0.25+0j), da)
1676 self.assertEqual((3.0+0j), db)
1677 self.assertEqual(db, (3.0+0j))
1678
1679 self.assertNotEqual(db, (3.0+1j))
1680 self.assertNotEqual((3.0+1j), db)
1681
1682 self.assertIs(db.__lt__(3.0+0j), NotImplemented)
1683 self.assertIs(db.__le__(3.0+0j), NotImplemented)
1684 self.assertIs(db.__gt__(3.0+0j), NotImplemented)
1685 self.assertIs(db.__le__(3.0+0j), NotImplemented)
1686
1687 def test_decimal_fraction_comparison(self):
1688 D = self.decimal.Decimal
1689 F = fractions[self.decimal].Fraction
1690 Context = self.decimal.Context
1691 localcontext = self.decimal.localcontext
1692 InvalidOperation = self.decimal.InvalidOperation
1693
1694
1695 emax = C.MAX_EMAX if C else 999999999
1696 emin = C.MIN_EMIN if C else -999999999
1697 etiny = C.MIN_ETINY if C else -1999999997
1698 c = Context(Emax=emax, Emin=emin)
1699
1700 with localcontext(c):
1701 c.prec = emax
1702 self.assertLess(D(0), F(1,9999999999999999999999999999999999999))
1703 self.assertLess(F(-1,9999999999999999999999999999999999999), D(0))
1704 self.assertLess(F(0,1), D("1e" + str(etiny)))
1705 self.assertLess(D("-1e" + str(etiny)), F(0,1))
1706 self.assertLess(F(0,9999999999999999999999999), D("1e" + str(etiny)))
1707 self.assertLess(D("-1e" + str(etiny)), F(0,9999999999999999999999999))
1708
1709 self.assertEqual(D("0.1"), F(1,10))
1710 self.assertEqual(F(1,10), D("0.1"))
1711
1712 c.prec = 300
1713 self.assertNotEqual(D(1)/3, F(1,3))
1714 self.assertNotEqual(F(1,3), D(1)/3)
1715
1716 self.assertLessEqual(F(120984237, 9999999999), D("9e" + str(emax)))
1717 self.assertGreaterEqual(D("9e" + str(emax)), F(120984237, 9999999999))
1718
1719 self.assertGreater(D('inf'), F(99999999999,123))
1720 self.assertGreater(D('inf'), F(-99999999999,123))
1721 self.assertLess(D('-inf'), F(99999999999,123))
1722 self.assertLess(D('-inf'), F(-99999999999,123))
1723
1724 self.assertRaises(InvalidOperation, D('nan').__gt__, F(-9,123))
1725 self.assertIs(NotImplemented, F(-9,123).__lt__(D('nan')))
1726 self.assertNotEqual(D('nan'), F(-9,123))
1727 self.assertNotEqual(F(-9,123), D('nan'))
1728
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001729 def test_copy_and_deepcopy_methods(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001730 Decimal = self.decimal.Decimal
1731
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001732 d = Decimal('43.24')
1733 c = copy.copy(d)
1734 self.assertEqual(id(c), id(d))
1735 dc = copy.deepcopy(d)
1736 self.assertEqual(id(dc), id(d))
1737
1738 def test_hash_method(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001739
1740 Decimal = self.decimal.Decimal
1741 localcontext = self.decimal.localcontext
1742
Stefan Krahdc817b22010-11-17 11:16:34 +00001743 def hashit(d):
1744 a = hash(d)
1745 b = d.__hash__()
1746 self.assertEqual(a, b)
1747 return a
1748
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001749 #just that it's hashable
Stefan Krahdc817b22010-11-17 11:16:34 +00001750 hashit(Decimal(23))
1751 hashit(Decimal('Infinity'))
1752 hashit(Decimal('-Infinity'))
1753 hashit(Decimal('nan123'))
1754 hashit(Decimal('-NaN'))
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001755
1756 test_values = [Decimal(sign*(2**m + n))
1757 for m in [0, 14, 15, 16, 17, 30, 31,
Stefan Krahdc817b22010-11-17 11:16:34 +00001758 32, 33, 61, 62, 63, 64, 65, 66]
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001759 for n in range(-10, 10)
1760 for sign in [-1, 1]]
1761 test_values.extend([
Stefan Krahdc817b22010-11-17 11:16:34 +00001762 Decimal("-1"), # ==> -2
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001763 Decimal("-0"), # zeros
1764 Decimal("0.00"),
1765 Decimal("-0.000"),
1766 Decimal("0E10"),
1767 Decimal("-0E12"),
1768 Decimal("10.0"), # negative exponent
1769 Decimal("-23.00000"),
1770 Decimal("1230E100"), # positive exponent
1771 Decimal("-4.5678E50"),
1772 # a value for which hash(n) != hash(n % (2**64-1))
1773 # in Python pre-2.6
1774 Decimal(2**64 + 2**32 - 1),
1775 # selection of values which fail with the old (before
1776 # version 2.6) long.__hash__
1777 Decimal("1.634E100"),
1778 Decimal("90.697E100"),
1779 Decimal("188.83E100"),
1780 Decimal("1652.9E100"),
1781 Decimal("56531E100"),
1782 ])
1783
1784 # check that hash(d) == hash(int(d)) for integral values
1785 for value in test_values:
Stefan Krahdc817b22010-11-17 11:16:34 +00001786 self.assertEqual(hashit(value), hashit(int(value)))
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001787
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001788 #the same hash that to an int
Stefan Krahdc817b22010-11-17 11:16:34 +00001789 self.assertEqual(hashit(Decimal(23)), hashit(23))
Raymond Hettingerd325c4b2010-11-21 04:08:28 +00001790 self.assertRaises(TypeError, hash, Decimal('sNaN'))
Stefan Krahdc817b22010-11-17 11:16:34 +00001791 self.assertTrue(hashit(Decimal('Inf')))
1792 self.assertTrue(hashit(Decimal('-Inf')))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001793
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001794 # check that the hashes of a Decimal float match when they
1795 # represent exactly the same values
1796 test_strings = ['inf', '-Inf', '0.0', '-.0e1',
1797 '34.0', '2.5', '112390.625', '-0.515625']
1798 for s in test_strings:
1799 f = float(s)
1800 d = Decimal(s)
Stefan Krahdc817b22010-11-17 11:16:34 +00001801 self.assertEqual(hashit(f), hashit(d))
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001802
Stefan Krah1919b7e2012-03-21 18:25:23 +01001803 with localcontext() as c:
1804 # check that the value of the hash doesn't depend on the
1805 # current context (issue #1757)
1806 x = Decimal("123456789.1")
Christian Heimes2380ac72008-01-09 00:17:24 +00001807
Stefan Krah1919b7e2012-03-21 18:25:23 +01001808 c.prec = 6
1809 h1 = hashit(x)
1810 c.prec = 10
1811 h2 = hashit(x)
1812 c.prec = 16
1813 h3 = hashit(x)
Christian Heimes2380ac72008-01-09 00:17:24 +00001814
Stefan Krah1919b7e2012-03-21 18:25:23 +01001815 self.assertEqual(h1, h2)
1816 self.assertEqual(h1, h3)
1817
1818 c.prec = 10000
1819 x = 1100 ** 1248
1820 self.assertEqual(hashit(Decimal(x)), hashit(x))
Christian Heimes2380ac72008-01-09 00:17:24 +00001821
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001822 def test_min_and_max_methods(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001823 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001824
1825 d1 = Decimal('15.32')
1826 d2 = Decimal('28.5')
1827 l1 = 15
1828 l2 = 28
1829
1830 #between Decimals
Ezio Melotti6607d512010-04-03 14:59:49 +00001831 self.assertIs(min(d1,d2), d1)
1832 self.assertIs(min(d2,d1), d1)
1833 self.assertIs(max(d1,d2), d2)
1834 self.assertIs(max(d2,d1), d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001835
1836 #between Decimal and long
Ezio Melotti6607d512010-04-03 14:59:49 +00001837 self.assertIs(min(d1,l2), d1)
1838 self.assertIs(min(l2,d1), d1)
1839 self.assertIs(max(l1,d2), d2)
1840 self.assertIs(max(d2,l1), d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001841
1842 def test_as_nonzero(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001843 Decimal = self.decimal.Decimal
1844
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001845 #as false
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001846 self.assertFalse(Decimal(0))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001847 #as true
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001848 self.assertTrue(Decimal('0.372'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001849
1850 def test_tostring_methods(self):
1851 #Test str and repr methods.
Stefan Krah1919b7e2012-03-21 18:25:23 +01001852 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001853
1854 d = Decimal('15.32')
1855 self.assertEqual(str(d), '15.32') # str
Christian Heimes68f5fbe2008-02-14 08:27:37 +00001856 self.assertEqual(repr(d), "Decimal('15.32')") # repr
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001857
1858 def test_tonum_methods(self):
Mark Dickinson5c2db372009-12-05 20:28:34 +00001859 #Test float and int methods.
Stefan Krah1919b7e2012-03-21 18:25:23 +01001860 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001861
1862 d1 = Decimal('66')
1863 d2 = Decimal('15.32')
1864
1865 #int
1866 self.assertEqual(int(d1), 66)
1867 self.assertEqual(int(d2), 15)
1868
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001869 #float
1870 self.assertEqual(float(d1), 66)
1871 self.assertEqual(float(d2), 15.32)
1872
Mark Dickinsonb27406c2008-05-09 13:42:33 +00001873 #floor
1874 test_pairs = [
1875 ('123.00', 123),
1876 ('3.2', 3),
1877 ('3.54', 3),
1878 ('3.899', 3),
1879 ('-2.3', -3),
1880 ('-11.0', -11),
1881 ('0.0', 0),
1882 ('-0E3', 0),
Stefan Krah1919b7e2012-03-21 18:25:23 +01001883 ('89891211712379812736.1', 89891211712379812736),
Mark Dickinsonb27406c2008-05-09 13:42:33 +00001884 ]
1885 for d, i in test_pairs:
1886 self.assertEqual(math.floor(Decimal(d)), i)
1887 self.assertRaises(ValueError, math.floor, Decimal('-NaN'))
1888 self.assertRaises(ValueError, math.floor, Decimal('sNaN'))
1889 self.assertRaises(ValueError, math.floor, Decimal('NaN123'))
1890 self.assertRaises(OverflowError, math.floor, Decimal('Inf'))
1891 self.assertRaises(OverflowError, math.floor, Decimal('-Inf'))
1892
1893 #ceiling
1894 test_pairs = [
1895 ('123.00', 123),
1896 ('3.2', 4),
1897 ('3.54', 4),
1898 ('3.899', 4),
1899 ('-2.3', -2),
1900 ('-11.0', -11),
1901 ('0.0', 0),
1902 ('-0E3', 0),
Stefan Krah1919b7e2012-03-21 18:25:23 +01001903 ('89891211712379812736.1', 89891211712379812737),
Mark Dickinsonb27406c2008-05-09 13:42:33 +00001904 ]
1905 for d, i in test_pairs:
1906 self.assertEqual(math.ceil(Decimal(d)), i)
1907 self.assertRaises(ValueError, math.ceil, Decimal('-NaN'))
1908 self.assertRaises(ValueError, math.ceil, Decimal('sNaN'))
1909 self.assertRaises(ValueError, math.ceil, Decimal('NaN123'))
1910 self.assertRaises(OverflowError, math.ceil, Decimal('Inf'))
1911 self.assertRaises(OverflowError, math.ceil, Decimal('-Inf'))
1912
1913 #round, single argument
1914 test_pairs = [
1915 ('123.00', 123),
1916 ('3.2', 3),
1917 ('3.54', 4),
1918 ('3.899', 4),
1919 ('-2.3', -2),
1920 ('-11.0', -11),
1921 ('0.0', 0),
1922 ('-0E3', 0),
1923 ('-3.5', -4),
1924 ('-2.5', -2),
1925 ('-1.5', -2),
1926 ('-0.5', 0),
1927 ('0.5', 0),
1928 ('1.5', 2),
1929 ('2.5', 2),
1930 ('3.5', 4),
1931 ]
1932 for d, i in test_pairs:
1933 self.assertEqual(round(Decimal(d)), i)
1934 self.assertRaises(ValueError, round, Decimal('-NaN'))
1935 self.assertRaises(ValueError, round, Decimal('sNaN'))
1936 self.assertRaises(ValueError, round, Decimal('NaN123'))
1937 self.assertRaises(OverflowError, round, Decimal('Inf'))
1938 self.assertRaises(OverflowError, round, Decimal('-Inf'))
1939
1940 #round, two arguments; this is essentially equivalent
1941 #to quantize, which is already extensively tested
1942 test_triples = [
1943 ('123.456', -4, '0E+4'),
1944 ('123.456', -3, '0E+3'),
1945 ('123.456', -2, '1E+2'),
1946 ('123.456', -1, '1.2E+2'),
1947 ('123.456', 0, '123'),
1948 ('123.456', 1, '123.5'),
1949 ('123.456', 2, '123.46'),
1950 ('123.456', 3, '123.456'),
1951 ('123.456', 4, '123.4560'),
1952 ('123.455', 2, '123.46'),
1953 ('123.445', 2, '123.44'),
1954 ('Inf', 4, 'NaN'),
1955 ('-Inf', -23, 'NaN'),
1956 ('sNaN314', 3, 'NaN314'),
1957 ]
1958 for d, n, r in test_triples:
1959 self.assertEqual(str(round(Decimal(d), n)), r)
1960
Mark Dickinsonfc33d4c2012-08-24 18:53:10 +01001961 def test_nan_to_float(self):
1962 # Test conversions of decimal NANs to float.
1963 # See http://bugs.python.org/issue15544
1964 Decimal = self.decimal.Decimal
1965 for s in ('nan', 'nan1234', '-nan', '-nan2468'):
1966 f = float(Decimal(s))
1967 self.assertTrue(math.isnan(f))
1968 sign = math.copysign(1.0, f)
1969 self.assertEqual(sign, -1.0 if s.startswith('-') else 1.0)
1970
1971 def test_snan_to_float(self):
1972 Decimal = self.decimal.Decimal
1973 for s in ('snan', '-snan', 'snan1357', '-snan1234'):
1974 d = Decimal(s)
1975 self.assertRaises(ValueError, float, d)
1976
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001977 def test_eval_round_trip(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001978 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001979
1980 #with zero
1981 d = Decimal( (0, (0,), 0) )
1982 self.assertEqual(d, eval(repr(d)))
1983
1984 #int
1985 d = Decimal( (1, (4, 5), 0) )
1986 self.assertEqual(d, eval(repr(d)))
1987
1988 #float
1989 d = Decimal( (0, (4, 5, 3, 4), -2) )
1990 self.assertEqual(d, eval(repr(d)))
1991
1992 #weird
1993 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1994 self.assertEqual(d, eval(repr(d)))
1995
1996 def test_as_tuple(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001997 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001998
1999 #with zero
2000 d = Decimal(0)
2001 self.assertEqual(d.as_tuple(), (0, (0,), 0) )
2002
2003 #int
2004 d = Decimal(-45)
2005 self.assertEqual(d.as_tuple(), (1, (4, 5), 0) )
2006
2007 #complicated string
2008 d = Decimal("-4.34913534E-17")
2009 self.assertEqual(d.as_tuple(), (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
2010
Stefan Krah76e12172012-09-10 19:34:58 +02002011 # The '0' coefficient is implementation specific to decimal.py.
2012 # It has no meaning in the C-version and is ignored there.
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002013 d = Decimal("Infinity")
2014 self.assertEqual(d.as_tuple(), (0, (0,), 'F') )
2015
Guido van Rossum8ce8a782007-11-01 19:42:39 +00002016 #leading zeros in coefficient should be stripped
2017 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), -2) )
2018 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), -2) )
2019 d = Decimal( (1, (0, 0, 0), 37) )
2020 self.assertEqual(d.as_tuple(), (1, (0,), 37))
2021 d = Decimal( (1, (), 37) )
2022 self.assertEqual(d.as_tuple(), (1, (0,), 37))
2023
2024 #leading zeros in NaN diagnostic info should be stripped
2025 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), 'n') )
2026 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), 'n') )
2027 d = Decimal( (1, (0, 0, 0), 'N') )
2028 self.assertEqual(d.as_tuple(), (1, (), 'N') )
2029 d = Decimal( (1, (), 'n') )
2030 self.assertEqual(d.as_tuple(), (1, (), 'n') )
2031
Stefan Krah76e12172012-09-10 19:34:58 +02002032 # For infinities, decimal.py has always silently accepted any
2033 # coefficient tuple.
2034 d = Decimal( (0, (0,), 'F') )
2035 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
2036 d = Decimal( (0, (4, 5, 3, 4), 'F') )
2037 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
2038 d = Decimal( (1, (0, 2, 7, 1), 'F') )
2039 self.assertEqual(d.as_tuple(), (1, (0,), 'F'))
Guido van Rossum8ce8a782007-11-01 19:42:39 +00002040
Stefan Krah1919b7e2012-03-21 18:25:23 +01002041 def test_subclassing(self):
2042 # Different behaviours when subclassing Decimal
2043 Decimal = self.decimal.Decimal
2044
2045 class MyDecimal(Decimal):
Stefan Krah0f82b762012-11-08 11:17:29 +01002046 y = None
Stefan Krah1919b7e2012-03-21 18:25:23 +01002047
2048 d1 = MyDecimal(1)
2049 d2 = MyDecimal(2)
2050 d = d1 + d2
2051 self.assertIs(type(d), Decimal)
2052
2053 d = d1.max(d2)
2054 self.assertIs(type(d), Decimal)
2055
2056 d = copy.copy(d1)
2057 self.assertIs(type(d), MyDecimal)
2058 self.assertEqual(d, d1)
2059
2060 d = copy.deepcopy(d1)
2061 self.assertIs(type(d), MyDecimal)
2062 self.assertEqual(d, d1)
2063
Stefan Krah0f82b762012-11-08 11:17:29 +01002064 # Decimal(Decimal)
2065 d = Decimal('1.0')
2066 x = Decimal(d)
2067 self.assertIs(type(x), Decimal)
2068 self.assertEqual(x, d)
Stefan Krahf4abc7b2012-11-07 23:12:25 +01002069
Stefan Krah0f82b762012-11-08 11:17:29 +01002070 # MyDecimal(Decimal)
2071 m = MyDecimal(d)
2072 self.assertIs(type(m), MyDecimal)
2073 self.assertEqual(m, d)
2074 self.assertIs(m.y, None)
2075
2076 # Decimal(MyDecimal)
2077 x = Decimal(m)
2078 self.assertIs(type(x), Decimal)
2079 self.assertEqual(x, d)
2080
2081 # MyDecimal(MyDecimal)
2082 m.y = 9
2083 x = MyDecimal(m)
2084 self.assertIs(type(x), MyDecimal)
2085 self.assertEqual(x, d)
2086 self.assertIs(x.y, None)
Stefan Krahed16eff2012-11-07 23:47:19 +01002087
Stefan Krah1919b7e2012-03-21 18:25:23 +01002088 def test_implicit_context(self):
2089 Decimal = self.decimal.Decimal
2090 getcontext = self.decimal.getcontext
2091
2092 # Check results when context given implicitly. (Issue 2478)
2093 c = getcontext()
2094 self.assertEqual(str(Decimal(0).sqrt()),
2095 str(c.sqrt(Decimal(0))))
2096
Stefan Krah040e3112012-12-15 22:33:33 +01002097 def test_none_args(self):
2098 Decimal = self.decimal.Decimal
2099 Context = self.decimal.Context
2100 localcontext = self.decimal.localcontext
2101 InvalidOperation = self.decimal.InvalidOperation
2102 DivisionByZero = self.decimal.DivisionByZero
2103 Overflow = self.decimal.Overflow
2104 Underflow = self.decimal.Underflow
2105 Subnormal = self.decimal.Subnormal
2106 Inexact = self.decimal.Inexact
2107 Rounded = self.decimal.Rounded
2108 Clamped = self.decimal.Clamped
Stefan Krah040e3112012-12-15 22:33:33 +01002109
2110 with localcontext(Context()) as c:
2111 c.prec = 7
2112 c.Emax = 999
2113 c.Emin = -999
2114
2115 x = Decimal("111")
2116 y = Decimal("1e9999")
2117 z = Decimal("1e-9999")
2118
2119 ##### Unary functions
2120 c.clear_flags()
2121 self.assertEqual(str(x.exp(context=None)), '1.609487E+48')
2122 self.assertTrue(c.flags[Inexact])
2123 self.assertTrue(c.flags[Rounded])
2124 c.clear_flags()
2125 self.assertRaises(Overflow, y.exp, context=None)
2126 self.assertTrue(c.flags[Overflow])
2127
2128 self.assertIs(z.is_normal(context=None), False)
2129 self.assertIs(z.is_subnormal(context=None), True)
2130
2131 c.clear_flags()
2132 self.assertEqual(str(x.ln(context=None)), '4.709530')
2133 self.assertTrue(c.flags[Inexact])
2134 self.assertTrue(c.flags[Rounded])
2135 c.clear_flags()
2136 self.assertRaises(InvalidOperation, Decimal(-1).ln, context=None)
2137 self.assertTrue(c.flags[InvalidOperation])
2138
2139 c.clear_flags()
2140 self.assertEqual(str(x.log10(context=None)), '2.045323')
2141 self.assertTrue(c.flags[Inexact])
2142 self.assertTrue(c.flags[Rounded])
2143 c.clear_flags()
2144 self.assertRaises(InvalidOperation, Decimal(-1).log10, context=None)
2145 self.assertTrue(c.flags[InvalidOperation])
2146
2147 c.clear_flags()
2148 self.assertEqual(str(x.logb(context=None)), '2')
2149 self.assertRaises(DivisionByZero, Decimal(0).logb, context=None)
2150 self.assertTrue(c.flags[DivisionByZero])
2151
2152 c.clear_flags()
2153 self.assertEqual(str(x.logical_invert(context=None)), '1111000')
2154 self.assertRaises(InvalidOperation, y.logical_invert, context=None)
2155 self.assertTrue(c.flags[InvalidOperation])
2156
2157 c.clear_flags()
2158 self.assertEqual(str(y.next_minus(context=None)), '9.999999E+999')
2159 self.assertRaises(InvalidOperation, Decimal('sNaN').next_minus, context=None)
2160 self.assertTrue(c.flags[InvalidOperation])
2161
2162 c.clear_flags()
2163 self.assertEqual(str(y.next_plus(context=None)), 'Infinity')
2164 self.assertRaises(InvalidOperation, Decimal('sNaN').next_plus, context=None)
2165 self.assertTrue(c.flags[InvalidOperation])
2166
2167 c.clear_flags()
2168 self.assertEqual(str(z.normalize(context=None)), '0')
2169 self.assertRaises(Overflow, y.normalize, context=None)
2170 self.assertTrue(c.flags[Overflow])
2171
2172 self.assertEqual(str(z.number_class(context=None)), '+Subnormal')
2173
2174 c.clear_flags()
2175 self.assertEqual(str(z.sqrt(context=None)), '0E-1005')
2176 self.assertTrue(c.flags[Clamped])
2177 self.assertTrue(c.flags[Inexact])
2178 self.assertTrue(c.flags[Rounded])
2179 self.assertTrue(c.flags[Subnormal])
2180 self.assertTrue(c.flags[Underflow])
2181 c.clear_flags()
2182 self.assertRaises(Overflow, y.sqrt, context=None)
2183 self.assertTrue(c.flags[Overflow])
2184
2185 c.capitals = 0
2186 self.assertEqual(str(z.to_eng_string(context=None)), '1e-9999')
2187 c.capitals = 1
2188
2189
2190 ##### Binary functions
2191 c.clear_flags()
2192 ans = str(x.compare(Decimal('Nan891287828'), context=None))
2193 self.assertEqual(ans, 'NaN1287828')
2194 self.assertRaises(InvalidOperation, x.compare, Decimal('sNaN'), context=None)
2195 self.assertTrue(c.flags[InvalidOperation])
2196
2197 c.clear_flags()
2198 ans = str(x.compare_signal(8224, context=None))
2199 self.assertEqual(ans, '-1')
2200 self.assertRaises(InvalidOperation, x.compare_signal, Decimal('NaN'), context=None)
2201 self.assertTrue(c.flags[InvalidOperation])
2202
2203 c.clear_flags()
2204 ans = str(x.logical_and(101, context=None))
2205 self.assertEqual(ans, '101')
2206 self.assertRaises(InvalidOperation, x.logical_and, 123, context=None)
2207 self.assertTrue(c.flags[InvalidOperation])
2208
2209 c.clear_flags()
2210 ans = str(x.logical_or(101, context=None))
2211 self.assertEqual(ans, '111')
2212 self.assertRaises(InvalidOperation, x.logical_or, 123, context=None)
2213 self.assertTrue(c.flags[InvalidOperation])
2214
2215 c.clear_flags()
2216 ans = str(x.logical_xor(101, context=None))
2217 self.assertEqual(ans, '10')
2218 self.assertRaises(InvalidOperation, x.logical_xor, 123, context=None)
2219 self.assertTrue(c.flags[InvalidOperation])
2220
2221 c.clear_flags()
2222 ans = str(x.max(101, context=None))
2223 self.assertEqual(ans, '111')
2224 self.assertRaises(InvalidOperation, x.max, Decimal('sNaN'), context=None)
2225 self.assertTrue(c.flags[InvalidOperation])
2226
2227 c.clear_flags()
2228 ans = str(x.max_mag(101, context=None))
2229 self.assertEqual(ans, '111')
2230 self.assertRaises(InvalidOperation, x.max_mag, Decimal('sNaN'), context=None)
2231 self.assertTrue(c.flags[InvalidOperation])
2232
2233 c.clear_flags()
2234 ans = str(x.min(101, context=None))
2235 self.assertEqual(ans, '101')
2236 self.assertRaises(InvalidOperation, x.min, Decimal('sNaN'), context=None)
2237 self.assertTrue(c.flags[InvalidOperation])
2238
2239 c.clear_flags()
2240 ans = str(x.min_mag(101, context=None))
2241 self.assertEqual(ans, '101')
2242 self.assertRaises(InvalidOperation, x.min_mag, Decimal('sNaN'), context=None)
2243 self.assertTrue(c.flags[InvalidOperation])
2244
2245 c.clear_flags()
2246 ans = str(x.remainder_near(101, context=None))
2247 self.assertEqual(ans, '10')
2248 self.assertRaises(InvalidOperation, y.remainder_near, 101, context=None)
2249 self.assertTrue(c.flags[InvalidOperation])
2250
2251 c.clear_flags()
2252 ans = str(x.rotate(2, context=None))
2253 self.assertEqual(ans, '11100')
2254 self.assertRaises(InvalidOperation, x.rotate, 101, context=None)
2255 self.assertTrue(c.flags[InvalidOperation])
2256
2257 c.clear_flags()
2258 ans = str(x.scaleb(7, context=None))
2259 self.assertEqual(ans, '1.11E+9')
2260 self.assertRaises(InvalidOperation, x.scaleb, 10000, context=None)
2261 self.assertTrue(c.flags[InvalidOperation])
2262
2263 c.clear_flags()
2264 ans = str(x.shift(2, context=None))
2265 self.assertEqual(ans, '11100')
2266 self.assertRaises(InvalidOperation, x.shift, 10000, context=None)
2267 self.assertTrue(c.flags[InvalidOperation])
2268
2269
2270 ##### Ternary functions
2271 c.clear_flags()
2272 ans = str(x.fma(2, 3, context=None))
2273 self.assertEqual(ans, '225')
2274 self.assertRaises(Overflow, x.fma, Decimal('1e9999'), 3, context=None)
2275 self.assertTrue(c.flags[Overflow])
2276
2277
2278 ##### Special cases
2279 c.rounding = ROUND_HALF_EVEN
2280 ans = str(Decimal('1.5').to_integral(rounding=None, context=None))
2281 self.assertEqual(ans, '2')
2282 c.rounding = ROUND_DOWN
2283 ans = str(Decimal('1.5').to_integral(rounding=None, context=None))
2284 self.assertEqual(ans, '1')
2285 ans = str(Decimal('1.5').to_integral(rounding=ROUND_UP, context=None))
2286 self.assertEqual(ans, '2')
2287 c.clear_flags()
2288 self.assertRaises(InvalidOperation, Decimal('sNaN').to_integral, context=None)
2289 self.assertTrue(c.flags[InvalidOperation])
2290
2291 c.rounding = ROUND_HALF_EVEN
2292 ans = str(Decimal('1.5').to_integral_value(rounding=None, context=None))
2293 self.assertEqual(ans, '2')
2294 c.rounding = ROUND_DOWN
2295 ans = str(Decimal('1.5').to_integral_value(rounding=None, context=None))
2296 self.assertEqual(ans, '1')
2297 ans = str(Decimal('1.5').to_integral_value(rounding=ROUND_UP, context=None))
2298 self.assertEqual(ans, '2')
2299 c.clear_flags()
2300 self.assertRaises(InvalidOperation, Decimal('sNaN').to_integral_value, context=None)
2301 self.assertTrue(c.flags[InvalidOperation])
2302
2303 c.rounding = ROUND_HALF_EVEN
2304 ans = str(Decimal('1.5').to_integral_exact(rounding=None, context=None))
2305 self.assertEqual(ans, '2')
2306 c.rounding = ROUND_DOWN
2307 ans = str(Decimal('1.5').to_integral_exact(rounding=None, context=None))
2308 self.assertEqual(ans, '1')
2309 ans = str(Decimal('1.5').to_integral_exact(rounding=ROUND_UP, context=None))
2310 self.assertEqual(ans, '2')
2311 c.clear_flags()
2312 self.assertRaises(InvalidOperation, Decimal('sNaN').to_integral_exact, context=None)
2313 self.assertTrue(c.flags[InvalidOperation])
2314
2315 c.rounding = ROUND_UP
2316 ans = str(Decimal('1.50001').quantize(exp=Decimal('1e-3'), rounding=None, context=None))
2317 self.assertEqual(ans, '1.501')
2318 c.rounding = ROUND_DOWN
2319 ans = str(Decimal('1.50001').quantize(exp=Decimal('1e-3'), rounding=None, context=None))
2320 self.assertEqual(ans, '1.500')
2321 ans = str(Decimal('1.50001').quantize(exp=Decimal('1e-3'), rounding=ROUND_UP, context=None))
2322 self.assertEqual(ans, '1.501')
2323 c.clear_flags()
2324 self.assertRaises(InvalidOperation, y.quantize, Decimal('1e-10'), rounding=ROUND_UP, context=None)
2325 self.assertTrue(c.flags[InvalidOperation])
2326
2327 with localcontext(Context()) as context:
2328 context.prec = 7
2329 context.Emax = 999
2330 context.Emin = -999
2331 with localcontext(ctx=None) as c:
2332 self.assertEqual(c.prec, 7)
2333 self.assertEqual(c.Emax, 999)
2334 self.assertEqual(c.Emin, -999)
2335
Stefan Krah1919b7e2012-03-21 18:25:23 +01002336 def test_conversions_from_int(self):
2337 # Check that methods taking a second Decimal argument will
2338 # always accept an integer in place of a Decimal.
2339 Decimal = self.decimal.Decimal
2340
2341 self.assertEqual(Decimal(4).compare(3),
2342 Decimal(4).compare(Decimal(3)))
2343 self.assertEqual(Decimal(4).compare_signal(3),
2344 Decimal(4).compare_signal(Decimal(3)))
2345 self.assertEqual(Decimal(4).compare_total(3),
2346 Decimal(4).compare_total(Decimal(3)))
2347 self.assertEqual(Decimal(4).compare_total_mag(3),
2348 Decimal(4).compare_total_mag(Decimal(3)))
2349 self.assertEqual(Decimal(10101).logical_and(1001),
2350 Decimal(10101).logical_and(Decimal(1001)))
2351 self.assertEqual(Decimal(10101).logical_or(1001),
2352 Decimal(10101).logical_or(Decimal(1001)))
2353 self.assertEqual(Decimal(10101).logical_xor(1001),
2354 Decimal(10101).logical_xor(Decimal(1001)))
2355 self.assertEqual(Decimal(567).max(123),
2356 Decimal(567).max(Decimal(123)))
2357 self.assertEqual(Decimal(567).max_mag(123),
2358 Decimal(567).max_mag(Decimal(123)))
2359 self.assertEqual(Decimal(567).min(123),
2360 Decimal(567).min(Decimal(123)))
2361 self.assertEqual(Decimal(567).min_mag(123),
2362 Decimal(567).min_mag(Decimal(123)))
2363 self.assertEqual(Decimal(567).next_toward(123),
2364 Decimal(567).next_toward(Decimal(123)))
2365 self.assertEqual(Decimal(1234).quantize(100),
2366 Decimal(1234).quantize(Decimal(100)))
2367 self.assertEqual(Decimal(768).remainder_near(1234),
2368 Decimal(768).remainder_near(Decimal(1234)))
2369 self.assertEqual(Decimal(123).rotate(1),
2370 Decimal(123).rotate(Decimal(1)))
2371 self.assertEqual(Decimal(1234).same_quantum(1000),
2372 Decimal(1234).same_quantum(Decimal(1000)))
2373 self.assertEqual(Decimal('9.123').scaleb(-100),
2374 Decimal('9.123').scaleb(Decimal(-100)))
2375 self.assertEqual(Decimal(456).shift(-1),
2376 Decimal(456).shift(Decimal(-1)))
2377
2378 self.assertEqual(Decimal(-12).fma(Decimal(45), 67),
2379 Decimal(-12).fma(Decimal(45), Decimal(67)))
2380 self.assertEqual(Decimal(-12).fma(45, 67),
2381 Decimal(-12).fma(Decimal(45), Decimal(67)))
2382 self.assertEqual(Decimal(-12).fma(45, Decimal(67)),
2383 Decimal(-12).fma(Decimal(45), Decimal(67)))
2384
2385class CUsabilityTest(UsabilityTest):
2386 decimal = C
2387class PyUsabilityTest(UsabilityTest):
2388 decimal = P
2389
2390class PythonAPItests(unittest.TestCase):
2391
2392 def test_abc(self):
2393 Decimal = self.decimal.Decimal
2394
2395 self.assertTrue(issubclass(Decimal, numbers.Number))
2396 self.assertFalse(issubclass(Decimal, numbers.Real))
2397 self.assertIsInstance(Decimal(0), numbers.Number)
2398 self.assertNotIsInstance(Decimal(0), numbers.Real)
2399
2400 def test_pickle(self):
2401 Decimal = self.decimal.Decimal
2402
2403 savedecimal = sys.modules['decimal']
2404
2405 # Round trip
2406 sys.modules['decimal'] = self.decimal
2407 d = Decimal('-3.141590000')
2408 p = pickle.dumps(d)
2409 e = pickle.loads(p)
2410 self.assertEqual(d, e)
2411
2412 if C:
2413 # Test interchangeability
2414 x = C.Decimal('-3.123e81723')
2415 y = P.Decimal('-3.123e81723')
2416
2417 sys.modules['decimal'] = C
2418 sx = pickle.dumps(x)
2419 sys.modules['decimal'] = P
2420 r = pickle.loads(sx)
2421 self.assertIsInstance(r, P.Decimal)
2422 self.assertEqual(r, y)
2423
2424 sys.modules['decimal'] = P
2425 sy = pickle.dumps(y)
2426 sys.modules['decimal'] = C
2427 r = pickle.loads(sy)
2428 self.assertIsInstance(r, C.Decimal)
2429 self.assertEqual(r, x)
2430
2431 sys.modules['decimal'] = savedecimal
2432
2433 def test_int(self):
2434 Decimal = self.decimal.Decimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01002435
2436 for x in range(-250, 250):
2437 s = '%0.2f' % (x / 100.0)
2438 # should work the same as for floats
2439 self.assertEqual(int(Decimal(s)), int(float(s)))
2440 # should work the same as to_integral in the ROUND_DOWN mode
2441 d = Decimal(s)
2442 r = d.to_integral(ROUND_DOWN)
2443 self.assertEqual(Decimal(int(d)), r)
2444
2445 self.assertRaises(ValueError, int, Decimal('-nan'))
2446 self.assertRaises(ValueError, int, Decimal('snan'))
2447 self.assertRaises(OverflowError, int, Decimal('inf'))
2448 self.assertRaises(OverflowError, int, Decimal('-inf'))
2449
2450 def test_trunc(self):
2451 Decimal = self.decimal.Decimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01002452
2453 for x in range(-250, 250):
2454 s = '%0.2f' % (x / 100.0)
2455 # should work the same as for floats
2456 self.assertEqual(int(Decimal(s)), int(float(s)))
2457 # should work the same as to_integral in the ROUND_DOWN mode
2458 d = Decimal(s)
2459 r = d.to_integral(ROUND_DOWN)
2460 self.assertEqual(Decimal(math.trunc(d)), r)
2461
2462 def test_from_float(self):
2463
2464 Decimal = self.decimal.Decimal
2465
2466 class MyDecimal(Decimal):
2467 pass
2468
2469 self.assertTrue(issubclass(MyDecimal, Decimal))
2470
2471 r = MyDecimal.from_float(0.1)
2472 self.assertEqual(type(r), MyDecimal)
2473 self.assertEqual(str(r),
2474 '0.1000000000000000055511151231257827021181583404541015625')
2475 bigint = 12345678901234567890123456789
2476 self.assertEqual(MyDecimal.from_float(bigint), MyDecimal(bigint))
2477 self.assertTrue(MyDecimal.from_float(float('nan')).is_qnan())
2478 self.assertTrue(MyDecimal.from_float(float('inf')).is_infinite())
2479 self.assertTrue(MyDecimal.from_float(float('-inf')).is_infinite())
2480 self.assertEqual(str(MyDecimal.from_float(float('nan'))),
2481 str(Decimal('NaN')))
2482 self.assertEqual(str(MyDecimal.from_float(float('inf'))),
2483 str(Decimal('Infinity')))
2484 self.assertEqual(str(MyDecimal.from_float(float('-inf'))),
2485 str(Decimal('-Infinity')))
2486 self.assertRaises(TypeError, MyDecimal.from_float, 'abc')
2487 for i in range(200):
2488 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
2489 self.assertEqual(x, float(MyDecimal.from_float(x))) # roundtrip
2490
2491 def test_create_decimal_from_float(self):
2492 Decimal = self.decimal.Decimal
2493 Context = self.decimal.Context
Stefan Krah1919b7e2012-03-21 18:25:23 +01002494 Inexact = self.decimal.Inexact
2495
2496 context = Context(prec=5, rounding=ROUND_DOWN)
2497 self.assertEqual(
2498 context.create_decimal_from_float(math.pi),
2499 Decimal('3.1415')
2500 )
2501 context = Context(prec=5, rounding=ROUND_UP)
2502 self.assertEqual(
2503 context.create_decimal_from_float(math.pi),
2504 Decimal('3.1416')
2505 )
2506 context = Context(prec=5, traps=[Inexact])
2507 self.assertRaises(
2508 Inexact,
2509 context.create_decimal_from_float,
2510 math.pi
2511 )
2512 self.assertEqual(repr(context.create_decimal_from_float(-0.0)),
2513 "Decimal('-0')")
2514 self.assertEqual(repr(context.create_decimal_from_float(1.0)),
2515 "Decimal('1')")
2516 self.assertEqual(repr(context.create_decimal_from_float(10)),
2517 "Decimal('10')")
2518
2519 def test_quantize(self):
2520 Decimal = self.decimal.Decimal
2521 Context = self.decimal.Context
2522 InvalidOperation = self.decimal.InvalidOperation
Stefan Krah1919b7e2012-03-21 18:25:23 +01002523
2524 c = Context(Emax=99999, Emin=-99999)
2525 self.assertEqual(
2526 Decimal('7.335').quantize(Decimal('.01')),
2527 Decimal('7.34')
2528 )
2529 self.assertEqual(
2530 Decimal('7.335').quantize(Decimal('.01'), rounding=ROUND_DOWN),
2531 Decimal('7.33')
2532 )
2533 self.assertRaises(
2534 InvalidOperation,
2535 Decimal("10e99999").quantize, Decimal('1e100000'), context=c
2536 )
2537
2538 c = Context()
2539 d = Decimal("0.871831e800")
2540 x = d.quantize(context=c, exp=Decimal("1e797"), rounding=ROUND_DOWN)
2541 self.assertEqual(x, Decimal('8.71E+799'))
2542
2543 def test_complex(self):
2544 Decimal = self.decimal.Decimal
2545
2546 x = Decimal("9.8182731e181273")
2547 self.assertEqual(x.real, x)
2548 self.assertEqual(x.imag, 0)
2549 self.assertEqual(x.conjugate(), x)
2550
2551 x = Decimal("1")
2552 self.assertEqual(complex(x), complex(float(1)))
2553
2554 self.assertRaises(AttributeError, setattr, x, 'real', 100)
2555 self.assertRaises(AttributeError, setattr, x, 'imag', 100)
2556 self.assertRaises(AttributeError, setattr, x, 'conjugate', 100)
2557 self.assertRaises(AttributeError, setattr, x, '__complex__', 100)
2558
2559 def test_named_parameters(self):
2560 D = self.decimal.Decimal
2561 Context = self.decimal.Context
2562 localcontext = self.decimal.localcontext
2563 InvalidOperation = self.decimal.InvalidOperation
2564 Overflow = self.decimal.Overflow
2565
2566 xc = Context()
2567 xc.prec = 1
2568 xc.Emax = 1
2569 xc.Emin = -1
2570
2571 with localcontext() as c:
2572 c.clear_flags()
2573
2574 self.assertEqual(D(9, xc), 9)
2575 self.assertEqual(D(9, context=xc), 9)
2576 self.assertEqual(D(context=xc, value=9), 9)
2577 self.assertEqual(D(context=xc), 0)
2578 xc.clear_flags()
2579 self.assertRaises(InvalidOperation, D, "xyz", context=xc)
2580 self.assertTrue(xc.flags[InvalidOperation])
2581 self.assertFalse(c.flags[InvalidOperation])
2582
2583 xc.clear_flags()
2584 self.assertEqual(D(2).exp(context=xc), 7)
2585 self.assertRaises(Overflow, D(8).exp, context=xc)
2586 self.assertTrue(xc.flags[Overflow])
2587 self.assertFalse(c.flags[Overflow])
2588
2589 xc.clear_flags()
2590 self.assertEqual(D(2).ln(context=xc), D('0.7'))
2591 self.assertRaises(InvalidOperation, D(-1).ln, context=xc)
2592 self.assertTrue(xc.flags[InvalidOperation])
2593 self.assertFalse(c.flags[InvalidOperation])
2594
2595 self.assertEqual(D(0).log10(context=xc), D('-inf'))
2596 self.assertEqual(D(-1).next_minus(context=xc), -2)
2597 self.assertEqual(D(-1).next_plus(context=xc), D('-0.9'))
2598 self.assertEqual(D("9.73").normalize(context=xc), D('1E+1'))
2599 self.assertEqual(D("9999").to_integral(context=xc), 9999)
2600 self.assertEqual(D("-2000").to_integral_exact(context=xc), -2000)
2601 self.assertEqual(D("123").to_integral_value(context=xc), 123)
2602 self.assertEqual(D("0.0625").sqrt(context=xc), D('0.2'))
2603
2604 self.assertEqual(D("0.0625").compare(context=xc, other=3), -1)
2605 xc.clear_flags()
2606 self.assertRaises(InvalidOperation,
2607 D("0").compare_signal, D('nan'), context=xc)
2608 self.assertTrue(xc.flags[InvalidOperation])
2609 self.assertFalse(c.flags[InvalidOperation])
2610 self.assertEqual(D("0.01").max(D('0.0101'), context=xc), D('0.0'))
2611 self.assertEqual(D("0.01").max(D('0.0101'), context=xc), D('0.0'))
2612 self.assertEqual(D("0.2").max_mag(D('-0.3'), context=xc),
2613 D('-0.3'))
2614 self.assertEqual(D("0.02").min(D('-0.03'), context=xc), D('-0.0'))
2615 self.assertEqual(D("0.02").min_mag(D('-0.03'), context=xc),
2616 D('0.0'))
2617 self.assertEqual(D("0.2").next_toward(D('-1'), context=xc), D('0.1'))
2618 xc.clear_flags()
2619 self.assertRaises(InvalidOperation,
2620 D("0.2").quantize, D('1e10'), context=xc)
2621 self.assertTrue(xc.flags[InvalidOperation])
2622 self.assertFalse(c.flags[InvalidOperation])
2623 self.assertEqual(D("9.99").remainder_near(D('1.5'), context=xc),
2624 D('-0.5'))
2625
2626 self.assertEqual(D("9.9").fma(third=D('0.9'), context=xc, other=7),
2627 D('7E+1'))
2628
2629 self.assertRaises(TypeError, D(1).is_canonical, context=xc)
2630 self.assertRaises(TypeError, D(1).is_finite, context=xc)
2631 self.assertRaises(TypeError, D(1).is_infinite, context=xc)
2632 self.assertRaises(TypeError, D(1).is_nan, context=xc)
2633 self.assertRaises(TypeError, D(1).is_qnan, context=xc)
2634 self.assertRaises(TypeError, D(1).is_snan, context=xc)
2635 self.assertRaises(TypeError, D(1).is_signed, context=xc)
2636 self.assertRaises(TypeError, D(1).is_zero, context=xc)
2637
2638 self.assertFalse(D("0.01").is_normal(context=xc))
2639 self.assertTrue(D("0.01").is_subnormal(context=xc))
2640
2641 self.assertRaises(TypeError, D(1).adjusted, context=xc)
2642 self.assertRaises(TypeError, D(1).conjugate, context=xc)
2643 self.assertRaises(TypeError, D(1).radix, context=xc)
2644
2645 self.assertEqual(D(-111).logb(context=xc), 2)
2646 self.assertEqual(D(0).logical_invert(context=xc), 1)
2647 self.assertEqual(D('0.01').number_class(context=xc), '+Subnormal')
2648 self.assertEqual(D('0.21').to_eng_string(context=xc), '0.21')
2649
2650 self.assertEqual(D('11').logical_and(D('10'), context=xc), 0)
2651 self.assertEqual(D('11').logical_or(D('10'), context=xc), 1)
2652 self.assertEqual(D('01').logical_xor(D('10'), context=xc), 1)
2653 self.assertEqual(D('23').rotate(1, context=xc), 3)
2654 self.assertEqual(D('23').rotate(1, context=xc), 3)
2655 xc.clear_flags()
2656 self.assertRaises(Overflow,
2657 D('23').scaleb, 1, context=xc)
2658 self.assertTrue(xc.flags[Overflow])
2659 self.assertFalse(c.flags[Overflow])
2660 self.assertEqual(D('23').shift(-1, context=xc), 0)
2661
2662 self.assertRaises(TypeError, D.from_float, 1.1, context=xc)
2663 self.assertRaises(TypeError, D(0).as_tuple, context=xc)
2664
Stefan Krah040e3112012-12-15 22:33:33 +01002665 self.assertEqual(D(1).canonical(), 1)
2666 self.assertRaises(TypeError, D("-1").copy_abs, context=xc)
2667 self.assertRaises(TypeError, D("-1").copy_negate, context=xc)
2668 self.assertRaises(TypeError, D(1).canonical, context="x")
2669 self.assertRaises(TypeError, D(1).canonical, xyz="x")
Stefan Krah1919b7e2012-03-21 18:25:23 +01002670
Stefan Krahb6405ef2012-03-23 14:46:48 +01002671 def test_exception_hierarchy(self):
2672
2673 decimal = self.decimal
2674 DecimalException = decimal.DecimalException
2675 InvalidOperation = decimal.InvalidOperation
2676 FloatOperation = decimal.FloatOperation
2677 DivisionByZero = decimal.DivisionByZero
2678 Overflow = decimal.Overflow
2679 Underflow = decimal.Underflow
2680 Subnormal = decimal.Subnormal
2681 Inexact = decimal.Inexact
2682 Rounded = decimal.Rounded
2683 Clamped = decimal.Clamped
2684
2685 self.assertTrue(issubclass(DecimalException, ArithmeticError))
2686
2687 self.assertTrue(issubclass(InvalidOperation, DecimalException))
2688 self.assertTrue(issubclass(FloatOperation, DecimalException))
2689 self.assertTrue(issubclass(FloatOperation, TypeError))
2690 self.assertTrue(issubclass(DivisionByZero, DecimalException))
2691 self.assertTrue(issubclass(DivisionByZero, ZeroDivisionError))
2692 self.assertTrue(issubclass(Overflow, Rounded))
2693 self.assertTrue(issubclass(Overflow, Inexact))
2694 self.assertTrue(issubclass(Overflow, DecimalException))
2695 self.assertTrue(issubclass(Underflow, Inexact))
2696 self.assertTrue(issubclass(Underflow, Rounded))
2697 self.assertTrue(issubclass(Underflow, Subnormal))
2698 self.assertTrue(issubclass(Underflow, DecimalException))
2699
2700 self.assertTrue(issubclass(Subnormal, DecimalException))
2701 self.assertTrue(issubclass(Inexact, DecimalException))
2702 self.assertTrue(issubclass(Rounded, DecimalException))
2703 self.assertTrue(issubclass(Clamped, DecimalException))
2704
2705 self.assertTrue(issubclass(decimal.ConversionSyntax, InvalidOperation))
2706 self.assertTrue(issubclass(decimal.DivisionImpossible, InvalidOperation))
2707 self.assertTrue(issubclass(decimal.DivisionUndefined, InvalidOperation))
2708 self.assertTrue(issubclass(decimal.DivisionUndefined, ZeroDivisionError))
2709 self.assertTrue(issubclass(decimal.InvalidContext, InvalidOperation))
2710
Stefan Krah1919b7e2012-03-21 18:25:23 +01002711class CPythonAPItests(PythonAPItests):
2712 decimal = C
2713class PyPythonAPItests(PythonAPItests):
2714 decimal = P
2715
2716class ContextAPItests(unittest.TestCase):
2717
Stefan Krah9a4ff432012-12-16 21:10:35 +01002718 def test_none_args(self):
2719 Context = self.decimal.Context
2720 InvalidOperation = self.decimal.InvalidOperation
2721 DivisionByZero = self.decimal.DivisionByZero
2722 Overflow = self.decimal.Overflow
Stefan Krah9a4ff432012-12-16 21:10:35 +01002723
2724 c1 = Context()
2725 c2 = Context(prec=None, rounding=None, Emax=None, Emin=None,
2726 capitals=None, clamp=None, flags=None, traps=None)
2727 for c in [c1, c2]:
2728 self.assertEqual(c.prec, 28)
2729 self.assertEqual(c.rounding, ROUND_HALF_EVEN)
2730 self.assertEqual(c.Emax, 999999)
2731 self.assertEqual(c.Emin, -999999)
2732 self.assertEqual(c.capitals, 1)
2733 self.assertEqual(c.clamp, 0)
2734 assert_signals(self, c, 'flags', [])
2735 assert_signals(self, c, 'traps', [InvalidOperation, DivisionByZero,
2736 Overflow])
2737
Stefan Krah59a4a932013-01-16 12:58:59 +01002738 @cpython_only
2739 def test_from_legacy_strings(self):
2740 import _testcapi
2741 c = self.decimal.Context()
2742
2743 for rnd in RoundingModes:
2744 c.rounding = _testcapi.unicode_legacy_string(rnd)
2745 self.assertEqual(c.rounding, rnd)
2746
2747 s = _testcapi.unicode_legacy_string('')
2748 self.assertRaises(TypeError, setattr, c, 'rounding', s)
2749
2750 s = _testcapi.unicode_legacy_string('ROUND_\x00UP')
2751 self.assertRaises(TypeError, setattr, c, 'rounding', s)
2752
Stefan Krah1919b7e2012-03-21 18:25:23 +01002753 def test_pickle(self):
2754
2755 Context = self.decimal.Context
2756
2757 savedecimal = sys.modules['decimal']
2758
2759 # Round trip
2760 sys.modules['decimal'] = self.decimal
2761 c = Context()
2762 e = pickle.loads(pickle.dumps(c))
2763
2764 self.assertEqual(c.prec, e.prec)
2765 self.assertEqual(c.Emin, e.Emin)
2766 self.assertEqual(c.Emax, e.Emax)
2767 self.assertEqual(c.rounding, e.rounding)
2768 self.assertEqual(c.capitals, e.capitals)
2769 self.assertEqual(c.clamp, e.clamp)
2770 self.assertEqual(c.flags, e.flags)
2771 self.assertEqual(c.traps, e.traps)
2772
2773 # Test interchangeability
2774 combinations = [(C, P), (P, C)] if C else [(P, P)]
2775 for dumper, loader in combinations:
Stefan Krah59a4a932013-01-16 12:58:59 +01002776 for ri, _ in enumerate(RoundingModes):
Stefan Krah1919b7e2012-03-21 18:25:23 +01002777 for fi, _ in enumerate(OrderedSignals[dumper]):
2778 for ti, _ in enumerate(OrderedSignals[dumper]):
2779
2780 prec = random.randrange(1, 100)
2781 emin = random.randrange(-100, 0)
2782 emax = random.randrange(1, 100)
2783 caps = random.randrange(2)
2784 clamp = random.randrange(2)
2785
2786 # One module dumps
2787 sys.modules['decimal'] = dumper
2788 c = dumper.Context(
2789 prec=prec, Emin=emin, Emax=emax,
Stefan Krah59a4a932013-01-16 12:58:59 +01002790 rounding=RoundingModes[ri],
Stefan Krah1919b7e2012-03-21 18:25:23 +01002791 capitals=caps, clamp=clamp,
2792 flags=OrderedSignals[dumper][:fi],
2793 traps=OrderedSignals[dumper][:ti]
2794 )
2795 s = pickle.dumps(c)
2796
2797 # The other module loads
2798 sys.modules['decimal'] = loader
2799 d = pickle.loads(s)
2800 self.assertIsInstance(d, loader.Context)
2801
2802 self.assertEqual(d.prec, prec)
2803 self.assertEqual(d.Emin, emin)
2804 self.assertEqual(d.Emax, emax)
Stefan Krah59a4a932013-01-16 12:58:59 +01002805 self.assertEqual(d.rounding, RoundingModes[ri])
Stefan Krah1919b7e2012-03-21 18:25:23 +01002806 self.assertEqual(d.capitals, caps)
2807 self.assertEqual(d.clamp, clamp)
2808 assert_signals(self, d, 'flags', OrderedSignals[loader][:fi])
2809 assert_signals(self, d, 'traps', OrderedSignals[loader][:ti])
2810
2811 sys.modules['decimal'] = savedecimal
2812
2813 def test_equality_with_other_types(self):
2814 Decimal = self.decimal.Decimal
2815
2816 self.assertIn(Decimal(10), ['a', 1.0, Decimal(10), (1,2), {}])
2817 self.assertNotIn(Decimal(10), ['a', 1.0, (1,2), {}])
2818
2819 def test_copy(self):
2820 # All copies should be deep
2821 Decimal = self.decimal.Decimal
2822 Context = self.decimal.Context
2823
2824 c = Context()
2825 d = c.copy()
2826 self.assertNotEqual(id(c), id(d))
2827 self.assertNotEqual(id(c.flags), id(d.flags))
2828 self.assertNotEqual(id(c.traps), id(d.traps))
2829 k1 = set(c.flags.keys())
2830 k2 = set(d.flags.keys())
2831 self.assertEqual(k1, k2)
2832 self.assertEqual(c.flags, d.flags)
2833
2834 def test__clamp(self):
2835 # In Python 3.2, the private attribute `_clamp` was made
2836 # public (issue 8540), with the old `_clamp` becoming a
2837 # property wrapping `clamp`. For the duration of Python 3.2
2838 # only, the attribute should be gettable/settable via both
2839 # `clamp` and `_clamp`; in Python 3.3, `_clamp` should be
2840 # removed.
2841 Context = self.decimal.Context
2842 c = Context()
2843 self.assertRaises(AttributeError, getattr, c, '_clamp')
2844
2845 def test_abs(self):
2846 Decimal = self.decimal.Decimal
2847 Context = self.decimal.Context
2848
2849 c = Context()
2850 d = c.abs(Decimal(-1))
2851 self.assertEqual(c.abs(-1), d)
2852 self.assertRaises(TypeError, c.abs, '-1')
2853
2854 def test_add(self):
2855 Decimal = self.decimal.Decimal
2856 Context = self.decimal.Context
2857
2858 c = Context()
2859 d = c.add(Decimal(1), Decimal(1))
2860 self.assertEqual(c.add(1, 1), d)
2861 self.assertEqual(c.add(Decimal(1), 1), d)
2862 self.assertEqual(c.add(1, Decimal(1)), d)
2863 self.assertRaises(TypeError, c.add, '1', 1)
2864 self.assertRaises(TypeError, c.add, 1, '1')
2865
2866 def test_compare(self):
2867 Decimal = self.decimal.Decimal
2868 Context = self.decimal.Context
2869
2870 c = Context()
2871 d = c.compare(Decimal(1), Decimal(1))
2872 self.assertEqual(c.compare(1, 1), d)
2873 self.assertEqual(c.compare(Decimal(1), 1), d)
2874 self.assertEqual(c.compare(1, Decimal(1)), d)
2875 self.assertRaises(TypeError, c.compare, '1', 1)
2876 self.assertRaises(TypeError, c.compare, 1, '1')
2877
2878 def test_compare_signal(self):
2879 Decimal = self.decimal.Decimal
2880 Context = self.decimal.Context
2881
2882 c = Context()
2883 d = c.compare_signal(Decimal(1), Decimal(1))
2884 self.assertEqual(c.compare_signal(1, 1), d)
2885 self.assertEqual(c.compare_signal(Decimal(1), 1), d)
2886 self.assertEqual(c.compare_signal(1, Decimal(1)), d)
2887 self.assertRaises(TypeError, c.compare_signal, '1', 1)
2888 self.assertRaises(TypeError, c.compare_signal, 1, '1')
2889
2890 def test_compare_total(self):
2891 Decimal = self.decimal.Decimal
2892 Context = self.decimal.Context
2893
2894 c = Context()
2895 d = c.compare_total(Decimal(1), Decimal(1))
2896 self.assertEqual(c.compare_total(1, 1), d)
2897 self.assertEqual(c.compare_total(Decimal(1), 1), d)
2898 self.assertEqual(c.compare_total(1, Decimal(1)), d)
2899 self.assertRaises(TypeError, c.compare_total, '1', 1)
2900 self.assertRaises(TypeError, c.compare_total, 1, '1')
2901
2902 def test_compare_total_mag(self):
2903 Decimal = self.decimal.Decimal
2904 Context = self.decimal.Context
2905
2906 c = Context()
2907 d = c.compare_total_mag(Decimal(1), Decimal(1))
2908 self.assertEqual(c.compare_total_mag(1, 1), d)
2909 self.assertEqual(c.compare_total_mag(Decimal(1), 1), d)
2910 self.assertEqual(c.compare_total_mag(1, Decimal(1)), d)
2911 self.assertRaises(TypeError, c.compare_total_mag, '1', 1)
2912 self.assertRaises(TypeError, c.compare_total_mag, 1, '1')
2913
2914 def test_copy_abs(self):
2915 Decimal = self.decimal.Decimal
2916 Context = self.decimal.Context
2917
2918 c = Context()
2919 d = c.copy_abs(Decimal(-1))
2920 self.assertEqual(c.copy_abs(-1), d)
2921 self.assertRaises(TypeError, c.copy_abs, '-1')
2922
2923 def test_copy_decimal(self):
2924 Decimal = self.decimal.Decimal
2925 Context = self.decimal.Context
2926
2927 c = Context()
2928 d = c.copy_decimal(Decimal(-1))
2929 self.assertEqual(c.copy_decimal(-1), d)
2930 self.assertRaises(TypeError, c.copy_decimal, '-1')
2931
2932 def test_copy_negate(self):
2933 Decimal = self.decimal.Decimal
2934 Context = self.decimal.Context
2935
2936 c = Context()
2937 d = c.copy_negate(Decimal(-1))
2938 self.assertEqual(c.copy_negate(-1), d)
2939 self.assertRaises(TypeError, c.copy_negate, '-1')
2940
2941 def test_copy_sign(self):
2942 Decimal = self.decimal.Decimal
2943 Context = self.decimal.Context
2944
2945 c = Context()
2946 d = c.copy_sign(Decimal(1), Decimal(-2))
2947 self.assertEqual(c.copy_sign(1, -2), d)
2948 self.assertEqual(c.copy_sign(Decimal(1), -2), d)
2949 self.assertEqual(c.copy_sign(1, Decimal(-2)), d)
2950 self.assertRaises(TypeError, c.copy_sign, '1', -2)
2951 self.assertRaises(TypeError, c.copy_sign, 1, '-2')
2952
2953 def test_divide(self):
2954 Decimal = self.decimal.Decimal
2955 Context = self.decimal.Context
2956
2957 c = Context()
2958 d = c.divide(Decimal(1), Decimal(2))
2959 self.assertEqual(c.divide(1, 2), d)
2960 self.assertEqual(c.divide(Decimal(1), 2), d)
2961 self.assertEqual(c.divide(1, Decimal(2)), d)
2962 self.assertRaises(TypeError, c.divide, '1', 2)
2963 self.assertRaises(TypeError, c.divide, 1, '2')
2964
2965 def test_divide_int(self):
2966 Decimal = self.decimal.Decimal
2967 Context = self.decimal.Context
2968
2969 c = Context()
2970 d = c.divide_int(Decimal(1), Decimal(2))
2971 self.assertEqual(c.divide_int(1, 2), d)
2972 self.assertEqual(c.divide_int(Decimal(1), 2), d)
2973 self.assertEqual(c.divide_int(1, Decimal(2)), d)
2974 self.assertRaises(TypeError, c.divide_int, '1', 2)
2975 self.assertRaises(TypeError, c.divide_int, 1, '2')
2976
2977 def test_divmod(self):
2978 Decimal = self.decimal.Decimal
2979 Context = self.decimal.Context
2980
2981 c = Context()
2982 d = c.divmod(Decimal(1), Decimal(2))
2983 self.assertEqual(c.divmod(1, 2), d)
2984 self.assertEqual(c.divmod(Decimal(1), 2), d)
2985 self.assertEqual(c.divmod(1, Decimal(2)), d)
2986 self.assertRaises(TypeError, c.divmod, '1', 2)
2987 self.assertRaises(TypeError, c.divmod, 1, '2')
2988
2989 def test_exp(self):
2990 Decimal = self.decimal.Decimal
2991 Context = self.decimal.Context
2992
2993 c = Context()
2994 d = c.exp(Decimal(10))
2995 self.assertEqual(c.exp(10), d)
2996 self.assertRaises(TypeError, c.exp, '10')
2997
2998 def test_fma(self):
2999 Decimal = self.decimal.Decimal
3000 Context = self.decimal.Context
3001
3002 c = Context()
3003 d = c.fma(Decimal(2), Decimal(3), Decimal(4))
3004 self.assertEqual(c.fma(2, 3, 4), d)
3005 self.assertEqual(c.fma(Decimal(2), 3, 4), d)
3006 self.assertEqual(c.fma(2, Decimal(3), 4), d)
3007 self.assertEqual(c.fma(2, 3, Decimal(4)), d)
3008 self.assertEqual(c.fma(Decimal(2), Decimal(3), 4), d)
3009 self.assertRaises(TypeError, c.fma, '2', 3, 4)
3010 self.assertRaises(TypeError, c.fma, 2, '3', 4)
3011 self.assertRaises(TypeError, c.fma, 2, 3, '4')
3012
3013 # Issue 12079 for Context.fma ...
3014 self.assertRaises(TypeError, c.fma,
3015 Decimal('Infinity'), Decimal(0), "not a decimal")
3016 self.assertRaises(TypeError, c.fma,
3017 Decimal(1), Decimal('snan'), 1.222)
3018 # ... and for Decimal.fma.
3019 self.assertRaises(TypeError, Decimal('Infinity').fma,
3020 Decimal(0), "not a decimal")
3021 self.assertRaises(TypeError, Decimal(1).fma,
3022 Decimal('snan'), 1.222)
3023
3024 def test_is_finite(self):
3025 Decimal = self.decimal.Decimal
3026 Context = self.decimal.Context
3027
3028 c = Context()
3029 d = c.is_finite(Decimal(10))
3030 self.assertEqual(c.is_finite(10), d)
3031 self.assertRaises(TypeError, c.is_finite, '10')
3032
3033 def test_is_infinite(self):
3034 Decimal = self.decimal.Decimal
3035 Context = self.decimal.Context
3036
3037 c = Context()
3038 d = c.is_infinite(Decimal(10))
3039 self.assertEqual(c.is_infinite(10), d)
3040 self.assertRaises(TypeError, c.is_infinite, '10')
3041
3042 def test_is_nan(self):
3043 Decimal = self.decimal.Decimal
3044 Context = self.decimal.Context
3045
3046 c = Context()
3047 d = c.is_nan(Decimal(10))
3048 self.assertEqual(c.is_nan(10), d)
3049 self.assertRaises(TypeError, c.is_nan, '10')
3050
3051 def test_is_normal(self):
3052 Decimal = self.decimal.Decimal
3053 Context = self.decimal.Context
3054
3055 c = Context()
3056 d = c.is_normal(Decimal(10))
3057 self.assertEqual(c.is_normal(10), d)
3058 self.assertRaises(TypeError, c.is_normal, '10')
3059
3060 def test_is_qnan(self):
3061 Decimal = self.decimal.Decimal
3062 Context = self.decimal.Context
3063
3064 c = Context()
3065 d = c.is_qnan(Decimal(10))
3066 self.assertEqual(c.is_qnan(10), d)
3067 self.assertRaises(TypeError, c.is_qnan, '10')
3068
3069 def test_is_signed(self):
3070 Decimal = self.decimal.Decimal
3071 Context = self.decimal.Context
3072
3073 c = Context()
3074 d = c.is_signed(Decimal(10))
3075 self.assertEqual(c.is_signed(10), d)
3076 self.assertRaises(TypeError, c.is_signed, '10')
3077
3078 def test_is_snan(self):
3079 Decimal = self.decimal.Decimal
3080 Context = self.decimal.Context
3081
3082 c = Context()
3083 d = c.is_snan(Decimal(10))
3084 self.assertEqual(c.is_snan(10), d)
3085 self.assertRaises(TypeError, c.is_snan, '10')
3086
3087 def test_is_subnormal(self):
3088 Decimal = self.decimal.Decimal
3089 Context = self.decimal.Context
3090
3091 c = Context()
3092 d = c.is_subnormal(Decimal(10))
3093 self.assertEqual(c.is_subnormal(10), d)
3094 self.assertRaises(TypeError, c.is_subnormal, '10')
3095
3096 def test_is_zero(self):
3097 Decimal = self.decimal.Decimal
3098 Context = self.decimal.Context
3099
3100 c = Context()
3101 d = c.is_zero(Decimal(10))
3102 self.assertEqual(c.is_zero(10), d)
3103 self.assertRaises(TypeError, c.is_zero, '10')
3104
3105 def test_ln(self):
3106 Decimal = self.decimal.Decimal
3107 Context = self.decimal.Context
3108
3109 c = Context()
3110 d = c.ln(Decimal(10))
3111 self.assertEqual(c.ln(10), d)
3112 self.assertRaises(TypeError, c.ln, '10')
3113
3114 def test_log10(self):
3115 Decimal = self.decimal.Decimal
3116 Context = self.decimal.Context
3117
3118 c = Context()
3119 d = c.log10(Decimal(10))
3120 self.assertEqual(c.log10(10), d)
3121 self.assertRaises(TypeError, c.log10, '10')
3122
3123 def test_logb(self):
3124 Decimal = self.decimal.Decimal
3125 Context = self.decimal.Context
3126
3127 c = Context()
3128 d = c.logb(Decimal(10))
3129 self.assertEqual(c.logb(10), d)
3130 self.assertRaises(TypeError, c.logb, '10')
3131
3132 def test_logical_and(self):
3133 Decimal = self.decimal.Decimal
3134 Context = self.decimal.Context
3135
3136 c = Context()
3137 d = c.logical_and(Decimal(1), Decimal(1))
3138 self.assertEqual(c.logical_and(1, 1), d)
3139 self.assertEqual(c.logical_and(Decimal(1), 1), d)
3140 self.assertEqual(c.logical_and(1, Decimal(1)), d)
3141 self.assertRaises(TypeError, c.logical_and, '1', 1)
3142 self.assertRaises(TypeError, c.logical_and, 1, '1')
3143
3144 def test_logical_invert(self):
3145 Decimal = self.decimal.Decimal
3146 Context = self.decimal.Context
3147
3148 c = Context()
3149 d = c.logical_invert(Decimal(1000))
3150 self.assertEqual(c.logical_invert(1000), d)
3151 self.assertRaises(TypeError, c.logical_invert, '1000')
3152
3153 def test_logical_or(self):
3154 Decimal = self.decimal.Decimal
3155 Context = self.decimal.Context
3156
3157 c = Context()
3158 d = c.logical_or(Decimal(1), Decimal(1))
3159 self.assertEqual(c.logical_or(1, 1), d)
3160 self.assertEqual(c.logical_or(Decimal(1), 1), d)
3161 self.assertEqual(c.logical_or(1, Decimal(1)), d)
3162 self.assertRaises(TypeError, c.logical_or, '1', 1)
3163 self.assertRaises(TypeError, c.logical_or, 1, '1')
3164
3165 def test_logical_xor(self):
3166 Decimal = self.decimal.Decimal
3167 Context = self.decimal.Context
3168
3169 c = Context()
3170 d = c.logical_xor(Decimal(1), Decimal(1))
3171 self.assertEqual(c.logical_xor(1, 1), d)
3172 self.assertEqual(c.logical_xor(Decimal(1), 1), d)
3173 self.assertEqual(c.logical_xor(1, Decimal(1)), d)
3174 self.assertRaises(TypeError, c.logical_xor, '1', 1)
3175 self.assertRaises(TypeError, c.logical_xor, 1, '1')
3176
3177 def test_max(self):
3178 Decimal = self.decimal.Decimal
3179 Context = self.decimal.Context
3180
3181 c = Context()
3182 d = c.max(Decimal(1), Decimal(2))
3183 self.assertEqual(c.max(1, 2), d)
3184 self.assertEqual(c.max(Decimal(1), 2), d)
3185 self.assertEqual(c.max(1, Decimal(2)), d)
3186 self.assertRaises(TypeError, c.max, '1', 2)
3187 self.assertRaises(TypeError, c.max, 1, '2')
3188
3189 def test_max_mag(self):
3190 Decimal = self.decimal.Decimal
3191 Context = self.decimal.Context
3192
3193 c = Context()
3194 d = c.max_mag(Decimal(1), Decimal(2))
3195 self.assertEqual(c.max_mag(1, 2), d)
3196 self.assertEqual(c.max_mag(Decimal(1), 2), d)
3197 self.assertEqual(c.max_mag(1, Decimal(2)), d)
3198 self.assertRaises(TypeError, c.max_mag, '1', 2)
3199 self.assertRaises(TypeError, c.max_mag, 1, '2')
3200
3201 def test_min(self):
3202 Decimal = self.decimal.Decimal
3203 Context = self.decimal.Context
3204
3205 c = Context()
3206 d = c.min(Decimal(1), Decimal(2))
3207 self.assertEqual(c.min(1, 2), d)
3208 self.assertEqual(c.min(Decimal(1), 2), d)
3209 self.assertEqual(c.min(1, Decimal(2)), d)
3210 self.assertRaises(TypeError, c.min, '1', 2)
3211 self.assertRaises(TypeError, c.min, 1, '2')
3212
3213 def test_min_mag(self):
3214 Decimal = self.decimal.Decimal
3215 Context = self.decimal.Context
3216
3217 c = Context()
3218 d = c.min_mag(Decimal(1), Decimal(2))
3219 self.assertEqual(c.min_mag(1, 2), d)
3220 self.assertEqual(c.min_mag(Decimal(1), 2), d)
3221 self.assertEqual(c.min_mag(1, Decimal(2)), d)
3222 self.assertRaises(TypeError, c.min_mag, '1', 2)
3223 self.assertRaises(TypeError, c.min_mag, 1, '2')
3224
3225 def test_minus(self):
3226 Decimal = self.decimal.Decimal
3227 Context = self.decimal.Context
3228
3229 c = Context()
3230 d = c.minus(Decimal(10))
3231 self.assertEqual(c.minus(10), d)
3232 self.assertRaises(TypeError, c.minus, '10')
3233
3234 def test_multiply(self):
3235 Decimal = self.decimal.Decimal
3236 Context = self.decimal.Context
3237
3238 c = Context()
3239 d = c.multiply(Decimal(1), Decimal(2))
3240 self.assertEqual(c.multiply(1, 2), d)
3241 self.assertEqual(c.multiply(Decimal(1), 2), d)
3242 self.assertEqual(c.multiply(1, Decimal(2)), d)
3243 self.assertRaises(TypeError, c.multiply, '1', 2)
3244 self.assertRaises(TypeError, c.multiply, 1, '2')
3245
3246 def test_next_minus(self):
3247 Decimal = self.decimal.Decimal
3248 Context = self.decimal.Context
3249
3250 c = Context()
3251 d = c.next_minus(Decimal(10))
3252 self.assertEqual(c.next_minus(10), d)
3253 self.assertRaises(TypeError, c.next_minus, '10')
3254
3255 def test_next_plus(self):
3256 Decimal = self.decimal.Decimal
3257 Context = self.decimal.Context
3258
3259 c = Context()
3260 d = c.next_plus(Decimal(10))
3261 self.assertEqual(c.next_plus(10), d)
3262 self.assertRaises(TypeError, c.next_plus, '10')
3263
3264 def test_next_toward(self):
3265 Decimal = self.decimal.Decimal
3266 Context = self.decimal.Context
3267
3268 c = Context()
3269 d = c.next_toward(Decimal(1), Decimal(2))
3270 self.assertEqual(c.next_toward(1, 2), d)
3271 self.assertEqual(c.next_toward(Decimal(1), 2), d)
3272 self.assertEqual(c.next_toward(1, Decimal(2)), d)
3273 self.assertRaises(TypeError, c.next_toward, '1', 2)
3274 self.assertRaises(TypeError, c.next_toward, 1, '2')
3275
3276 def test_normalize(self):
3277 Decimal = self.decimal.Decimal
3278 Context = self.decimal.Context
3279
3280 c = Context()
3281 d = c.normalize(Decimal(10))
3282 self.assertEqual(c.normalize(10), d)
3283 self.assertRaises(TypeError, c.normalize, '10')
3284
3285 def test_number_class(self):
3286 Decimal = self.decimal.Decimal
3287 Context = self.decimal.Context
3288
3289 c = Context()
3290 self.assertEqual(c.number_class(123), c.number_class(Decimal(123)))
3291 self.assertEqual(c.number_class(0), c.number_class(Decimal(0)))
3292 self.assertEqual(c.number_class(-45), c.number_class(Decimal(-45)))
3293
3294 def test_plus(self):
3295 Decimal = self.decimal.Decimal
3296 Context = self.decimal.Context
3297
3298 c = Context()
3299 d = c.plus(Decimal(10))
3300 self.assertEqual(c.plus(10), d)
3301 self.assertRaises(TypeError, c.plus, '10')
3302
3303 def test_power(self):
3304 Decimal = self.decimal.Decimal
3305 Context = self.decimal.Context
3306
3307 c = Context()
3308 d = c.power(Decimal(1), Decimal(4))
3309 self.assertEqual(c.power(1, 4), d)
3310 self.assertEqual(c.power(Decimal(1), 4), d)
3311 self.assertEqual(c.power(1, Decimal(4)), d)
3312 self.assertEqual(c.power(Decimal(1), Decimal(4)), d)
3313 self.assertRaises(TypeError, c.power, '1', 4)
3314 self.assertRaises(TypeError, c.power, 1, '4')
3315 self.assertEqual(c.power(modulo=5, b=8, a=2), 1)
3316
3317 def test_quantize(self):
3318 Decimal = self.decimal.Decimal
3319 Context = self.decimal.Context
3320
3321 c = Context()
3322 d = c.quantize(Decimal(1), Decimal(2))
3323 self.assertEqual(c.quantize(1, 2), d)
3324 self.assertEqual(c.quantize(Decimal(1), 2), d)
3325 self.assertEqual(c.quantize(1, Decimal(2)), d)
3326 self.assertRaises(TypeError, c.quantize, '1', 2)
3327 self.assertRaises(TypeError, c.quantize, 1, '2')
3328
3329 def test_remainder(self):
3330 Decimal = self.decimal.Decimal
3331 Context = self.decimal.Context
3332
3333 c = Context()
3334 d = c.remainder(Decimal(1), Decimal(2))
3335 self.assertEqual(c.remainder(1, 2), d)
3336 self.assertEqual(c.remainder(Decimal(1), 2), d)
3337 self.assertEqual(c.remainder(1, Decimal(2)), d)
3338 self.assertRaises(TypeError, c.remainder, '1', 2)
3339 self.assertRaises(TypeError, c.remainder, 1, '2')
3340
3341 def test_remainder_near(self):
3342 Decimal = self.decimal.Decimal
3343 Context = self.decimal.Context
3344
3345 c = Context()
3346 d = c.remainder_near(Decimal(1), Decimal(2))
3347 self.assertEqual(c.remainder_near(1, 2), d)
3348 self.assertEqual(c.remainder_near(Decimal(1), 2), d)
3349 self.assertEqual(c.remainder_near(1, Decimal(2)), d)
3350 self.assertRaises(TypeError, c.remainder_near, '1', 2)
3351 self.assertRaises(TypeError, c.remainder_near, 1, '2')
3352
3353 def test_rotate(self):
3354 Decimal = self.decimal.Decimal
3355 Context = self.decimal.Context
3356
3357 c = Context()
3358 d = c.rotate(Decimal(1), Decimal(2))
3359 self.assertEqual(c.rotate(1, 2), d)
3360 self.assertEqual(c.rotate(Decimal(1), 2), d)
3361 self.assertEqual(c.rotate(1, Decimal(2)), d)
3362 self.assertRaises(TypeError, c.rotate, '1', 2)
3363 self.assertRaises(TypeError, c.rotate, 1, '2')
3364
3365 def test_sqrt(self):
3366 Decimal = self.decimal.Decimal
3367 Context = self.decimal.Context
3368
3369 c = Context()
3370 d = c.sqrt(Decimal(10))
3371 self.assertEqual(c.sqrt(10), d)
3372 self.assertRaises(TypeError, c.sqrt, '10')
3373
3374 def test_same_quantum(self):
3375 Decimal = self.decimal.Decimal
3376 Context = self.decimal.Context
3377
3378 c = Context()
3379 d = c.same_quantum(Decimal(1), Decimal(2))
3380 self.assertEqual(c.same_quantum(1, 2), d)
3381 self.assertEqual(c.same_quantum(Decimal(1), 2), d)
3382 self.assertEqual(c.same_quantum(1, Decimal(2)), d)
3383 self.assertRaises(TypeError, c.same_quantum, '1', 2)
3384 self.assertRaises(TypeError, c.same_quantum, 1, '2')
3385
3386 def test_scaleb(self):
3387 Decimal = self.decimal.Decimal
3388 Context = self.decimal.Context
3389
3390 c = Context()
3391 d = c.scaleb(Decimal(1), Decimal(2))
3392 self.assertEqual(c.scaleb(1, 2), d)
3393 self.assertEqual(c.scaleb(Decimal(1), 2), d)
3394 self.assertEqual(c.scaleb(1, Decimal(2)), d)
3395 self.assertRaises(TypeError, c.scaleb, '1', 2)
3396 self.assertRaises(TypeError, c.scaleb, 1, '2')
3397
3398 def test_shift(self):
3399 Decimal = self.decimal.Decimal
3400 Context = self.decimal.Context
3401
3402 c = Context()
3403 d = c.shift(Decimal(1), Decimal(2))
3404 self.assertEqual(c.shift(1, 2), d)
3405 self.assertEqual(c.shift(Decimal(1), 2), d)
3406 self.assertEqual(c.shift(1, Decimal(2)), d)
3407 self.assertRaises(TypeError, c.shift, '1', 2)
3408 self.assertRaises(TypeError, c.shift, 1, '2')
3409
3410 def test_subtract(self):
3411 Decimal = self.decimal.Decimal
3412 Context = self.decimal.Context
3413
3414 c = Context()
3415 d = c.subtract(Decimal(1), Decimal(2))
3416 self.assertEqual(c.subtract(1, 2), d)
3417 self.assertEqual(c.subtract(Decimal(1), 2), d)
3418 self.assertEqual(c.subtract(1, Decimal(2)), d)
3419 self.assertRaises(TypeError, c.subtract, '1', 2)
3420 self.assertRaises(TypeError, c.subtract, 1, '2')
3421
3422 def test_to_eng_string(self):
3423 Decimal = self.decimal.Decimal
3424 Context = self.decimal.Context
3425
3426 c = Context()
3427 d = c.to_eng_string(Decimal(10))
3428 self.assertEqual(c.to_eng_string(10), d)
3429 self.assertRaises(TypeError, c.to_eng_string, '10')
3430
3431 def test_to_sci_string(self):
3432 Decimal = self.decimal.Decimal
3433 Context = self.decimal.Context
3434
3435 c = Context()
3436 d = c.to_sci_string(Decimal(10))
3437 self.assertEqual(c.to_sci_string(10), d)
3438 self.assertRaises(TypeError, c.to_sci_string, '10')
3439
3440 def test_to_integral_exact(self):
3441 Decimal = self.decimal.Decimal
3442 Context = self.decimal.Context
3443
3444 c = Context()
3445 d = c.to_integral_exact(Decimal(10))
3446 self.assertEqual(c.to_integral_exact(10), d)
3447 self.assertRaises(TypeError, c.to_integral_exact, '10')
3448
3449 def test_to_integral_value(self):
3450 Decimal = self.decimal.Decimal
3451 Context = self.decimal.Context
3452
3453 c = Context()
3454 d = c.to_integral_value(Decimal(10))
3455 self.assertEqual(c.to_integral_value(10), d)
3456 self.assertRaises(TypeError, c.to_integral_value, '10')
3457 self.assertRaises(TypeError, c.to_integral_value, 10, 'x')
3458
3459class CContextAPItests(ContextAPItests):
3460 decimal = C
3461class PyContextAPItests(ContextAPItests):
3462 decimal = P
3463
3464class ContextWithStatement(unittest.TestCase):
3465 # Can't do these as docstrings until Python 2.6
3466 # as doctest can't handle __future__ statements
3467
3468 def test_localcontext(self):
3469 # Use a copy of the current context in the block
3470 getcontext = self.decimal.getcontext
3471 localcontext = self.decimal.localcontext
3472
3473 orig_ctx = getcontext()
3474 with localcontext() as enter_ctx:
3475 set_ctx = getcontext()
3476 final_ctx = getcontext()
3477 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
3478 self.assertIsNot(orig_ctx, set_ctx, 'did not copy the context')
3479 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
3480
3481 def test_localcontextarg(self):
3482 # Use a copy of the supplied context in the block
3483 Context = self.decimal.Context
3484 getcontext = self.decimal.getcontext
3485 localcontext = self.decimal.localcontext
3486
3487 localcontext = self.decimal.localcontext
3488 orig_ctx = getcontext()
3489 new_ctx = Context(prec=42)
3490 with localcontext(new_ctx) as enter_ctx:
3491 set_ctx = getcontext()
3492 final_ctx = getcontext()
3493 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
3494 self.assertEqual(set_ctx.prec, new_ctx.prec, 'did not set correct context')
3495 self.assertIsNot(new_ctx, set_ctx, 'did not copy the context')
3496 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
3497
3498 def test_nested_with_statements(self):
3499 # Use a copy of the supplied context in the block
3500 Decimal = self.decimal.Decimal
3501 Context = self.decimal.Context
3502 getcontext = self.decimal.getcontext
3503 localcontext = self.decimal.localcontext
3504 Clamped = self.decimal.Clamped
3505 Overflow = self.decimal.Overflow
3506
3507 orig_ctx = getcontext()
3508 orig_ctx.clear_flags()
3509 new_ctx = Context(Emax=384)
3510 with localcontext() as c1:
3511 self.assertEqual(c1.flags, orig_ctx.flags)
3512 self.assertEqual(c1.traps, orig_ctx.traps)
3513 c1.traps[Clamped] = True
3514 c1.Emin = -383
3515 self.assertNotEqual(orig_ctx.Emin, -383)
3516 self.assertRaises(Clamped, c1.create_decimal, '0e-999')
3517 self.assertTrue(c1.flags[Clamped])
3518 with localcontext(new_ctx) as c2:
3519 self.assertEqual(c2.flags, new_ctx.flags)
3520 self.assertEqual(c2.traps, new_ctx.traps)
3521 self.assertRaises(Overflow, c2.power, Decimal('3.4e200'), 2)
3522 self.assertFalse(c2.flags[Clamped])
3523 self.assertTrue(c2.flags[Overflow])
3524 del c2
3525 self.assertFalse(c1.flags[Overflow])
3526 del c1
3527 self.assertNotEqual(orig_ctx.Emin, -383)
3528 self.assertFalse(orig_ctx.flags[Clamped])
3529 self.assertFalse(orig_ctx.flags[Overflow])
3530 self.assertFalse(new_ctx.flags[Clamped])
3531 self.assertFalse(new_ctx.flags[Overflow])
3532
3533 def test_with_statements_gc1(self):
3534 localcontext = self.decimal.localcontext
3535
3536 with localcontext() as c1:
3537 del c1
3538 with localcontext() as c2:
3539 del c2
3540 with localcontext() as c3:
3541 del c3
3542 with localcontext() as c4:
3543 del c4
3544
3545 def test_with_statements_gc2(self):
3546 localcontext = self.decimal.localcontext
3547
3548 with localcontext() as c1:
3549 with localcontext(c1) as c2:
3550 del c1
3551 with localcontext(c2) as c3:
3552 del c2
3553 with localcontext(c3) as c4:
3554 del c3
3555 del c4
3556
3557 def test_with_statements_gc3(self):
3558 Context = self.decimal.Context
3559 localcontext = self.decimal.localcontext
3560 getcontext = self.decimal.getcontext
3561 setcontext = self.decimal.setcontext
3562
3563 with localcontext() as c1:
3564 del c1
3565 n1 = Context(prec=1)
3566 setcontext(n1)
3567 with localcontext(n1) as c2:
3568 del n1
3569 self.assertEqual(c2.prec, 1)
3570 del c2
3571 n2 = Context(prec=2)
3572 setcontext(n2)
3573 del n2
3574 self.assertEqual(getcontext().prec, 2)
3575 n3 = Context(prec=3)
3576 setcontext(n3)
3577 self.assertEqual(getcontext().prec, 3)
3578 with localcontext(n3) as c3:
3579 del n3
3580 self.assertEqual(c3.prec, 3)
3581 del c3
3582 n4 = Context(prec=4)
3583 setcontext(n4)
3584 del n4
3585 self.assertEqual(getcontext().prec, 4)
3586 with localcontext() as c4:
3587 self.assertEqual(c4.prec, 4)
3588 del c4
3589
3590class CContextWithStatement(ContextWithStatement):
3591 decimal = C
3592class PyContextWithStatement(ContextWithStatement):
3593 decimal = P
3594
3595class ContextFlags(unittest.TestCase):
3596
3597 def test_flags_irrelevant(self):
3598 # check that the result (numeric result + flags raised) of an
3599 # arithmetic operation doesn't depend on the current flags
3600 Decimal = self.decimal.Decimal
3601 Context = self.decimal.Context
3602 Inexact = self.decimal.Inexact
3603 Rounded = self.decimal.Rounded
3604 Underflow = self.decimal.Underflow
3605 Clamped = self.decimal.Clamped
3606 Subnormal = self.decimal.Subnormal
Stefan Krah1919b7e2012-03-21 18:25:23 +01003607
3608 def raise_error(context, flag):
3609 if self.decimal == C:
3610 context.flags[flag] = True
3611 if context.traps[flag]:
3612 raise flag
3613 else:
3614 context._raise_error(flag)
3615
3616 context = Context(prec=9, Emin = -425000000, Emax = 425000000,
3617 rounding=ROUND_HALF_EVEN, traps=[], flags=[])
3618
3619 # operations that raise various flags, in the form (function, arglist)
3620 operations = [
3621 (context._apply, [Decimal("100E-425000010")]),
3622 (context.sqrt, [Decimal(2)]),
3623 (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]),
3624 (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]),
3625 (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]),
3626 ]
3627
3628 # try various flags individually, then a whole lot at once
3629 flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal],
3630 [Inexact, Rounded, Underflow, Clamped, Subnormal]]
3631
3632 for fn, args in operations:
3633 # find answer and flags raised using a clean context
3634 context.clear_flags()
3635 ans = fn(*args)
3636 flags = [k for k, v in context.flags.items() if v]
3637
3638 for extra_flags in flagsets:
3639 # set flags, before calling operation
3640 context.clear_flags()
3641 for flag in extra_flags:
3642 raise_error(context, flag)
3643 new_ans = fn(*args)
3644
3645 # flags that we expect to be set after the operation
3646 expected_flags = list(flags)
3647 for flag in extra_flags:
3648 if flag not in expected_flags:
3649 expected_flags.append(flag)
3650 expected_flags.sort(key=id)
3651
3652 # flags we actually got
3653 new_flags = [k for k,v in context.flags.items() if v]
3654 new_flags.sort(key=id)
3655
3656 self.assertEqual(ans, new_ans,
3657 "operation produces different answers depending on flags set: " +
3658 "expected %s, got %s." % (ans, new_ans))
3659 self.assertEqual(new_flags, expected_flags,
3660 "operation raises different flags depending on flags set: " +
3661 "expected %s, got %s" % (expected_flags, new_flags))
3662
3663 def test_flag_comparisons(self):
3664 Context = self.decimal.Context
3665 Inexact = self.decimal.Inexact
3666 Rounded = self.decimal.Rounded
3667
3668 c = Context()
3669
3670 # Valid SignalDict
3671 self.assertNotEqual(c.flags, c.traps)
3672 self.assertNotEqual(c.traps, c.flags)
3673
3674 c.flags = c.traps
3675 self.assertEqual(c.flags, c.traps)
3676 self.assertEqual(c.traps, c.flags)
3677
3678 c.flags[Rounded] = True
3679 c.traps = c.flags
3680 self.assertEqual(c.flags, c.traps)
3681 self.assertEqual(c.traps, c.flags)
3682
3683 d = {}
3684 d.update(c.flags)
3685 self.assertEqual(d, c.flags)
3686 self.assertEqual(c.flags, d)
3687
3688 d[Inexact] = True
3689 self.assertNotEqual(d, c.flags)
3690 self.assertNotEqual(c.flags, d)
3691
3692 # Invalid SignalDict
3693 d = {Inexact:False}
3694 self.assertNotEqual(d, c.flags)
3695 self.assertNotEqual(c.flags, d)
3696
3697 d = ["xyz"]
3698 self.assertNotEqual(d, c.flags)
3699 self.assertNotEqual(c.flags, d)
3700
3701 @requires_IEEE_754
3702 def test_float_operation(self):
3703 Decimal = self.decimal.Decimal
3704 FloatOperation = self.decimal.FloatOperation
3705 localcontext = self.decimal.localcontext
3706
3707 with localcontext() as c:
3708 ##### trap is off by default
3709 self.assertFalse(c.traps[FloatOperation])
3710
3711 # implicit conversion sets the flag
3712 c.clear_flags()
3713 self.assertEqual(Decimal(7.5), 7.5)
3714 self.assertTrue(c.flags[FloatOperation])
3715
3716 c.clear_flags()
3717 self.assertEqual(c.create_decimal(7.5), 7.5)
3718 self.assertTrue(c.flags[FloatOperation])
3719
3720 # explicit conversion does not set the flag
3721 c.clear_flags()
3722 x = Decimal.from_float(7.5)
3723 self.assertFalse(c.flags[FloatOperation])
3724 # comparison sets the flag
3725 self.assertEqual(x, 7.5)
3726 self.assertTrue(c.flags[FloatOperation])
3727
3728 c.clear_flags()
3729 x = c.create_decimal_from_float(7.5)
3730 self.assertFalse(c.flags[FloatOperation])
3731 self.assertEqual(x, 7.5)
3732 self.assertTrue(c.flags[FloatOperation])
3733
3734 ##### set the trap
3735 c.traps[FloatOperation] = True
3736
3737 # implicit conversion raises
3738 c.clear_flags()
3739 self.assertRaises(FloatOperation, Decimal, 7.5)
3740 self.assertTrue(c.flags[FloatOperation])
3741
3742 c.clear_flags()
3743 self.assertRaises(FloatOperation, c.create_decimal, 7.5)
3744 self.assertTrue(c.flags[FloatOperation])
3745
3746 # explicit conversion is silent
3747 c.clear_flags()
3748 x = Decimal.from_float(7.5)
3749 self.assertFalse(c.flags[FloatOperation])
3750
3751 c.clear_flags()
3752 x = c.create_decimal_from_float(7.5)
3753 self.assertFalse(c.flags[FloatOperation])
3754
3755 def test_float_comparison(self):
3756 Decimal = self.decimal.Decimal
3757 Context = self.decimal.Context
3758 FloatOperation = self.decimal.FloatOperation
3759 localcontext = self.decimal.localcontext
3760
3761 def assert_attr(a, b, attr, context, signal=None):
3762 context.clear_flags()
3763 f = getattr(a, attr)
3764 if signal == FloatOperation:
3765 self.assertRaises(signal, f, b)
3766 else:
3767 self.assertIs(f(b), True)
3768 self.assertTrue(context.flags[FloatOperation])
3769
3770 small_d = Decimal('0.25')
3771 big_d = Decimal('3.0')
3772 small_f = 0.25
3773 big_f = 3.0
3774
3775 zero_d = Decimal('0.0')
3776 neg_zero_d = Decimal('-0.0')
3777 zero_f = 0.0
3778 neg_zero_f = -0.0
3779
3780 inf_d = Decimal('Infinity')
3781 neg_inf_d = Decimal('-Infinity')
3782 inf_f = float('inf')
3783 neg_inf_f = float('-inf')
3784
3785 def doit(c, signal=None):
3786 # Order
3787 for attr in '__lt__', '__le__':
3788 assert_attr(small_d, big_f, attr, c, signal)
3789
3790 for attr in '__gt__', '__ge__':
3791 assert_attr(big_d, small_f, attr, c, signal)
3792
3793 # Equality
3794 assert_attr(small_d, small_f, '__eq__', c, None)
3795
3796 assert_attr(neg_zero_d, neg_zero_f, '__eq__', c, None)
3797 assert_attr(neg_zero_d, zero_f, '__eq__', c, None)
3798
3799 assert_attr(zero_d, neg_zero_f, '__eq__', c, None)
3800 assert_attr(zero_d, zero_f, '__eq__', c, None)
3801
3802 assert_attr(neg_inf_d, neg_inf_f, '__eq__', c, None)
3803 assert_attr(inf_d, inf_f, '__eq__', c, None)
3804
3805 # Inequality
3806 assert_attr(small_d, big_f, '__ne__', c, None)
3807
3808 assert_attr(Decimal('0.1'), 0.1, '__ne__', c, None)
3809
3810 assert_attr(neg_inf_d, inf_f, '__ne__', c, None)
3811 assert_attr(inf_d, neg_inf_f, '__ne__', c, None)
3812
3813 assert_attr(Decimal('NaN'), float('nan'), '__ne__', c, None)
3814
3815 def test_containers(c, signal=None):
3816 c.clear_flags()
3817 s = set([100.0, Decimal('100.0')])
3818 self.assertEqual(len(s), 1)
3819 self.assertTrue(c.flags[FloatOperation])
3820
3821 c.clear_flags()
3822 if signal:
3823 self.assertRaises(signal, sorted, [1.0, Decimal('10.0')])
3824 else:
3825 s = sorted([10.0, Decimal('10.0')])
3826 self.assertTrue(c.flags[FloatOperation])
3827
3828 c.clear_flags()
3829 b = 10.0 in [Decimal('10.0'), 1.0]
3830 self.assertTrue(c.flags[FloatOperation])
3831
3832 c.clear_flags()
3833 b = 10.0 in {Decimal('10.0'):'a', 1.0:'b'}
3834 self.assertTrue(c.flags[FloatOperation])
3835
3836 nc = Context()
3837 with localcontext(nc) as c:
3838 self.assertFalse(c.traps[FloatOperation])
3839 doit(c, signal=None)
3840 test_containers(c, signal=None)
3841
3842 c.traps[FloatOperation] = True
3843 doit(c, signal=FloatOperation)
3844 test_containers(c, signal=FloatOperation)
3845
3846 def test_float_operation_default(self):
3847 Decimal = self.decimal.Decimal
3848 Context = self.decimal.Context
3849 Inexact = self.decimal.Inexact
3850 FloatOperation= self.decimal.FloatOperation
3851
3852 context = Context()
3853 self.assertFalse(context.flags[FloatOperation])
3854 self.assertFalse(context.traps[FloatOperation])
3855
3856 context.clear_traps()
3857 context.traps[Inexact] = True
3858 context.traps[FloatOperation] = True
3859 self.assertTrue(context.traps[FloatOperation])
3860 self.assertTrue(context.traps[Inexact])
3861
3862class CContextFlags(ContextFlags):
3863 decimal = C
3864class PyContextFlags(ContextFlags):
3865 decimal = P
3866
3867class SpecialContexts(unittest.TestCase):
3868 """Test the context templates."""
3869
3870 def test_context_templates(self):
3871 BasicContext = self.decimal.BasicContext
3872 ExtendedContext = self.decimal.ExtendedContext
3873 getcontext = self.decimal.getcontext
3874 setcontext = self.decimal.setcontext
3875 InvalidOperation = self.decimal.InvalidOperation
3876 DivisionByZero = self.decimal.DivisionByZero
3877 Overflow = self.decimal.Overflow
3878 Underflow = self.decimal.Underflow
3879 Clamped = self.decimal.Clamped
3880
3881 assert_signals(self, BasicContext, 'traps',
3882 [InvalidOperation, DivisionByZero, Overflow, Underflow, Clamped]
3883 )
3884
3885 savecontext = getcontext().copy()
3886 basic_context_prec = BasicContext.prec
3887 extended_context_prec = ExtendedContext.prec
3888
3889 ex = None
3890 try:
3891 BasicContext.prec = ExtendedContext.prec = 441
3892 for template in BasicContext, ExtendedContext:
3893 setcontext(template)
3894 c = getcontext()
3895 self.assertIsNot(c, template)
3896 self.assertEqual(c.prec, 441)
3897 except Exception as e:
3898 ex = e.__class__
3899 finally:
3900 BasicContext.prec = basic_context_prec
3901 ExtendedContext.prec = extended_context_prec
3902 setcontext(savecontext)
3903 if ex:
3904 raise ex
3905
3906 def test_default_context(self):
3907 DefaultContext = self.decimal.DefaultContext
3908 BasicContext = self.decimal.BasicContext
3909 ExtendedContext = self.decimal.ExtendedContext
3910 getcontext = self.decimal.getcontext
3911 setcontext = self.decimal.setcontext
3912 InvalidOperation = self.decimal.InvalidOperation
3913 DivisionByZero = self.decimal.DivisionByZero
3914 Overflow = self.decimal.Overflow
3915
3916 self.assertEqual(BasicContext.prec, 9)
3917 self.assertEqual(ExtendedContext.prec, 9)
3918
3919 assert_signals(self, DefaultContext, 'traps',
3920 [InvalidOperation, DivisionByZero, Overflow]
3921 )
3922
3923 savecontext = getcontext().copy()
3924 default_context_prec = DefaultContext.prec
3925
3926 ex = None
3927 try:
3928 c = getcontext()
3929 saveprec = c.prec
3930
3931 DefaultContext.prec = 961
3932 c = getcontext()
3933 self.assertEqual(c.prec, saveprec)
3934
3935 setcontext(DefaultContext)
3936 c = getcontext()
3937 self.assertIsNot(c, DefaultContext)
3938 self.assertEqual(c.prec, 961)
3939 except Exception as e:
3940 ex = e.__class__
3941 finally:
3942 DefaultContext.prec = default_context_prec
3943 setcontext(savecontext)
3944 if ex:
3945 raise ex
3946
3947class CSpecialContexts(SpecialContexts):
3948 decimal = C
3949class PySpecialContexts(SpecialContexts):
3950 decimal = P
3951
3952class ContextInputValidation(unittest.TestCase):
3953
3954 def test_invalid_context(self):
3955 Context = self.decimal.Context
3956 DefaultContext = self.decimal.DefaultContext
3957
3958 c = DefaultContext.copy()
3959
3960 # prec, Emax
3961 for attr in ['prec', 'Emax']:
3962 setattr(c, attr, 999999)
3963 self.assertEqual(getattr(c, attr), 999999)
3964 self.assertRaises(ValueError, setattr, c, attr, -1)
3965 self.assertRaises(TypeError, setattr, c, attr, 'xyz')
3966
3967 # Emin
3968 setattr(c, 'Emin', -999999)
3969 self.assertEqual(getattr(c, 'Emin'), -999999)
3970 self.assertRaises(ValueError, setattr, c, 'Emin', 1)
3971 self.assertRaises(TypeError, setattr, c, 'Emin', (1,2,3))
3972
Stefan Krah1919b7e2012-03-21 18:25:23 +01003973 self.assertRaises(TypeError, setattr, c, 'rounding', -1)
3974 self.assertRaises(TypeError, setattr, c, 'rounding', 9)
3975 self.assertRaises(TypeError, setattr, c, 'rounding', 1.0)
3976 self.assertRaises(TypeError, setattr, c, 'rounding', 'xyz')
3977
3978 # capitals, clamp
3979 for attr in ['capitals', 'clamp']:
3980 self.assertRaises(ValueError, setattr, c, attr, -1)
3981 self.assertRaises(ValueError, setattr, c, attr, 2)
3982 self.assertRaises(TypeError, setattr, c, attr, [1,2,3])
3983
3984 # Invalid attribute
3985 self.assertRaises(AttributeError, setattr, c, 'emax', 100)
3986
3987 # Invalid signal dict
3988 self.assertRaises(TypeError, setattr, c, 'flags', [])
3989 self.assertRaises(KeyError, setattr, c, 'flags', {})
3990 self.assertRaises(KeyError, setattr, c, 'traps',
3991 {'InvalidOperation':0})
3992
3993 # Attributes cannot be deleted
3994 for attr in ['prec', 'Emax', 'Emin', 'rounding', 'capitals', 'clamp',
3995 'flags', 'traps']:
3996 self.assertRaises(AttributeError, c.__delattr__, attr)
3997
3998 # Invalid attributes
3999 self.assertRaises(TypeError, getattr, c, 9)
4000 self.assertRaises(TypeError, setattr, c, 9)
4001
4002 # Invalid values in constructor
4003 self.assertRaises(TypeError, Context, rounding=999999)
4004 self.assertRaises(TypeError, Context, rounding='xyz')
4005 self.assertRaises(ValueError, Context, clamp=2)
4006 self.assertRaises(ValueError, Context, capitals=-1)
4007 self.assertRaises(KeyError, Context, flags=["P"])
4008 self.assertRaises(KeyError, Context, traps=["Q"])
4009
4010 # Type error in conversion
4011 self.assertRaises(TypeError, Context, flags=(0,1))
4012 self.assertRaises(TypeError, Context, traps=(1,0))
4013
4014class CContextInputValidation(ContextInputValidation):
4015 decimal = C
4016class PyContextInputValidation(ContextInputValidation):
4017 decimal = P
4018
4019class ContextSubclassing(unittest.TestCase):
4020
4021 def test_context_subclassing(self):
4022 decimal = self.decimal
4023 Decimal = decimal.Decimal
4024 Context = decimal.Context
Stefan Krah1919b7e2012-03-21 18:25:23 +01004025 Clamped = decimal.Clamped
4026 DivisionByZero = decimal.DivisionByZero
4027 Inexact = decimal.Inexact
4028 Overflow = decimal.Overflow
4029 Rounded = decimal.Rounded
4030 Subnormal = decimal.Subnormal
4031 Underflow = decimal.Underflow
4032 InvalidOperation = decimal.InvalidOperation
4033
4034 class MyContext(Context):
4035 def __init__(self, prec=None, rounding=None, Emin=None, Emax=None,
4036 capitals=None, clamp=None, flags=None,
4037 traps=None):
4038 Context.__init__(self)
4039 if prec is not None:
4040 self.prec = prec
4041 if rounding is not None:
4042 self.rounding = rounding
4043 if Emin is not None:
4044 self.Emin = Emin
4045 if Emax is not None:
4046 self.Emax = Emax
4047 if capitals is not None:
4048 self.capitals = capitals
4049 if clamp is not None:
4050 self.clamp = clamp
4051 if flags is not None:
4052 if isinstance(flags, list):
4053 flags = {v:(v in flags) for v in OrderedSignals[decimal] + flags}
4054 self.flags = flags
4055 if traps is not None:
4056 if isinstance(traps, list):
4057 traps = {v:(v in traps) for v in OrderedSignals[decimal] + traps}
4058 self.traps = traps
4059
4060 c = Context()
4061 d = MyContext()
4062 for attr in ('prec', 'rounding', 'Emin', 'Emax', 'capitals', 'clamp',
4063 'flags', 'traps'):
4064 self.assertEqual(getattr(c, attr), getattr(d, attr))
4065
4066 # prec
4067 self.assertRaises(ValueError, MyContext, **{'prec':-1})
4068 c = MyContext(prec=1)
4069 self.assertEqual(c.prec, 1)
4070 self.assertRaises(InvalidOperation, c.quantize, Decimal('9e2'), 0)
4071
4072 # rounding
4073 self.assertRaises(TypeError, MyContext, **{'rounding':'XYZ'})
4074 c = MyContext(rounding=ROUND_DOWN, prec=1)
4075 self.assertEqual(c.rounding, ROUND_DOWN)
4076 self.assertEqual(c.plus(Decimal('9.9')), 9)
4077
4078 # Emin
4079 self.assertRaises(ValueError, MyContext, **{'Emin':5})
4080 c = MyContext(Emin=-1, prec=1)
4081 self.assertEqual(c.Emin, -1)
4082 x = c.add(Decimal('1e-99'), Decimal('2.234e-2000'))
4083 self.assertEqual(x, Decimal('0.0'))
4084 for signal in (Inexact, Underflow, Subnormal, Rounded, Clamped):
4085 self.assertTrue(c.flags[signal])
4086
4087 # Emax
4088 self.assertRaises(ValueError, MyContext, **{'Emax':-1})
4089 c = MyContext(Emax=1, prec=1)
4090 self.assertEqual(c.Emax, 1)
4091 self.assertRaises(Overflow, c.add, Decimal('1e99'), Decimal('2.234e2000'))
4092 if self.decimal == C:
4093 for signal in (Inexact, Overflow, Rounded):
4094 self.assertTrue(c.flags[signal])
4095
4096 # capitals
4097 self.assertRaises(ValueError, MyContext, **{'capitals':-1})
4098 c = MyContext(capitals=0)
4099 self.assertEqual(c.capitals, 0)
4100 x = c.create_decimal('1E222')
4101 self.assertEqual(c.to_sci_string(x), '1e+222')
4102
4103 # clamp
4104 self.assertRaises(ValueError, MyContext, **{'clamp':2})
4105 c = MyContext(clamp=1, Emax=99)
4106 self.assertEqual(c.clamp, 1)
4107 x = c.plus(Decimal('1e99'))
4108 self.assertEqual(str(x), '1.000000000000000000000000000E+99')
4109
4110 # flags
4111 self.assertRaises(TypeError, MyContext, **{'flags':'XYZ'})
4112 c = MyContext(flags=[Rounded, DivisionByZero])
4113 for signal in (Rounded, DivisionByZero):
4114 self.assertTrue(c.flags[signal])
4115 c.clear_flags()
4116 for signal in OrderedSignals[decimal]:
4117 self.assertFalse(c.flags[signal])
4118
4119 # traps
4120 self.assertRaises(TypeError, MyContext, **{'traps':'XYZ'})
4121 c = MyContext(traps=[Rounded, DivisionByZero])
4122 for signal in (Rounded, DivisionByZero):
4123 self.assertTrue(c.traps[signal])
4124 c.clear_traps()
4125 for signal in OrderedSignals[decimal]:
4126 self.assertFalse(c.traps[signal])
4127
4128class CContextSubclassing(ContextSubclassing):
4129 decimal = C
4130class PyContextSubclassing(ContextSubclassing):
4131 decimal = P
4132
4133@skip_if_extra_functionality
4134class CheckAttributes(unittest.TestCase):
4135
4136 def test_module_attributes(self):
4137
4138 # Architecture dependent context limits
4139 self.assertEqual(C.MAX_PREC, P.MAX_PREC)
4140 self.assertEqual(C.MAX_EMAX, P.MAX_EMAX)
4141 self.assertEqual(C.MIN_EMIN, P.MIN_EMIN)
4142 self.assertEqual(C.MIN_ETINY, P.MIN_ETINY)
4143
4144 self.assertTrue(C.HAVE_THREADS is True or C.HAVE_THREADS is False)
4145 self.assertTrue(P.HAVE_THREADS is True or P.HAVE_THREADS is False)
4146
4147 self.assertEqual(C.__version__, P.__version__)
4148
4149 x = dir(C)
4150 y = [s for s in dir(P) if '__' in s or not s.startswith('_')]
Stefan Krahfe17b2b2012-03-25 18:59:21 +02004151 self.assertEqual(set(x) - set(y), set())
Stefan Krah1919b7e2012-03-21 18:25:23 +01004152
4153 def test_context_attributes(self):
4154
4155 x = [s for s in dir(C.Context()) if '__' in s or not s.startswith('_')]
4156 y = [s for s in dir(P.Context()) if '__' in s or not s.startswith('_')]
4157 self.assertEqual(set(x) - set(y), set())
4158
4159 def test_decimal_attributes(self):
4160
4161 x = [s for s in dir(C.Decimal(9)) if '__' in s or not s.startswith('_')]
4162 y = [s for s in dir(C.Decimal(9)) if '__' in s or not s.startswith('_')]
4163 self.assertEqual(set(x) - set(y), set())
4164
4165class Coverage(unittest.TestCase):
4166
4167 def test_adjusted(self):
4168 Decimal = self.decimal.Decimal
4169
4170 self.assertEqual(Decimal('1234e9999').adjusted(), 10002)
4171 # XXX raise?
4172 self.assertEqual(Decimal('nan').adjusted(), 0)
4173 self.assertEqual(Decimal('inf').adjusted(), 0)
4174
4175 def test_canonical(self):
4176 Decimal = self.decimal.Decimal
4177 getcontext = self.decimal.getcontext
4178
4179 x = Decimal(9).canonical()
4180 self.assertEqual(x, 9)
4181
4182 c = getcontext()
4183 x = c.canonical(Decimal(9))
4184 self.assertEqual(x, 9)
4185
4186 def test_context_repr(self):
4187 c = self.decimal.DefaultContext.copy()
4188
4189 c.prec = 425000000
4190 c.Emax = 425000000
4191 c.Emin = -425000000
Stefan Krah59a4a932013-01-16 12:58:59 +01004192 c.rounding = ROUND_HALF_DOWN
Stefan Krah1919b7e2012-03-21 18:25:23 +01004193 c.capitals = 0
4194 c.clamp = 1
4195 for sig in OrderedSignals[self.decimal]:
4196 c.flags[sig] = False
4197 c.traps[sig] = False
4198
4199 s = c.__repr__()
4200 t = "Context(prec=425000000, rounding=ROUND_HALF_DOWN, " \
4201 "Emin=-425000000, Emax=425000000, capitals=0, clamp=1, " \
4202 "flags=[], traps=[])"
4203 self.assertEqual(s, t)
4204
4205 def test_implicit_context(self):
4206 Decimal = self.decimal.Decimal
4207 localcontext = self.decimal.localcontext
4208
4209 with localcontext() as c:
4210 c.prec = 1
4211 c.Emax = 1
4212 c.Emin = -1
4213
4214 # abs
4215 self.assertEqual(abs(Decimal("-10")), 10)
4216 # add
4217 self.assertEqual(Decimal("7") + 1, 8)
4218 # divide
4219 self.assertEqual(Decimal("10") / 5, 2)
4220 # divide_int
4221 self.assertEqual(Decimal("10") // 7, 1)
4222 # fma
4223 self.assertEqual(Decimal("1.2").fma(Decimal("0.01"), 1), 1)
4224 self.assertIs(Decimal("NaN").fma(7, 1).is_nan(), True)
4225 # three arg power
4226 self.assertEqual(pow(Decimal(10), 2, 7), 2)
4227 # exp
4228 self.assertEqual(Decimal("1.01").exp(), 3)
4229 # is_normal
4230 self.assertIs(Decimal("0.01").is_normal(), False)
4231 # is_subnormal
4232 self.assertIs(Decimal("0.01").is_subnormal(), True)
4233 # ln
4234 self.assertEqual(Decimal("20").ln(), 3)
4235 # log10
4236 self.assertEqual(Decimal("20").log10(), 1)
4237 # logb
4238 self.assertEqual(Decimal("580").logb(), 2)
4239 # logical_invert
4240 self.assertEqual(Decimal("10").logical_invert(), 1)
4241 # minus
4242 self.assertEqual(-Decimal("-10"), 10)
4243 # multiply
4244 self.assertEqual(Decimal("2") * 4, 8)
4245 # next_minus
4246 self.assertEqual(Decimal("10").next_minus(), 9)
4247 # next_plus
4248 self.assertEqual(Decimal("10").next_plus(), Decimal('2E+1'))
4249 # normalize
4250 self.assertEqual(Decimal("-10").normalize(), Decimal('-1E+1'))
4251 # number_class
4252 self.assertEqual(Decimal("10").number_class(), '+Normal')
4253 # plus
4254 self.assertEqual(+Decimal("-1"), -1)
4255 # remainder
4256 self.assertEqual(Decimal("10") % 7, 3)
4257 # subtract
4258 self.assertEqual(Decimal("10") - 7, 3)
4259 # to_integral_exact
4260 self.assertEqual(Decimal("1.12345").to_integral_exact(), 1)
4261
4262 # Boolean functions
4263 self.assertTrue(Decimal("1").is_canonical())
4264 self.assertTrue(Decimal("1").is_finite())
4265 self.assertTrue(Decimal("1").is_finite())
4266 self.assertTrue(Decimal("snan").is_snan())
4267 self.assertTrue(Decimal("-1").is_signed())
4268 self.assertTrue(Decimal("0").is_zero())
4269 self.assertTrue(Decimal("0").is_zero())
4270
4271 # Copy
4272 with localcontext() as c:
4273 c.prec = 10000
4274 x = 1228 ** 1523
4275 y = -Decimal(x)
4276
4277 z = y.copy_abs()
4278 self.assertEqual(z, x)
4279
4280 z = y.copy_negate()
4281 self.assertEqual(z, x)
4282
4283 z = y.copy_sign(Decimal(1))
4284 self.assertEqual(z, x)
4285
4286 def test_divmod(self):
4287 Decimal = self.decimal.Decimal
4288 localcontext = self.decimal.localcontext
4289 InvalidOperation = self.decimal.InvalidOperation
4290 DivisionByZero = self.decimal.DivisionByZero
4291
4292 with localcontext() as c:
4293 q, r = divmod(Decimal("10912837129"), 1001)
4294 self.assertEqual(q, Decimal('10901935'))
4295 self.assertEqual(r, Decimal('194'))
4296
4297 q, r = divmod(Decimal("NaN"), 7)
4298 self.assertTrue(q.is_nan() and r.is_nan())
4299
4300 c.traps[InvalidOperation] = False
4301 q, r = divmod(Decimal("NaN"), 7)
4302 self.assertTrue(q.is_nan() and r.is_nan())
4303
4304 c.traps[InvalidOperation] = False
4305 c.clear_flags()
4306 q, r = divmod(Decimal("inf"), Decimal("inf"))
4307 self.assertTrue(q.is_nan() and r.is_nan())
4308 self.assertTrue(c.flags[InvalidOperation])
4309
4310 c.clear_flags()
4311 q, r = divmod(Decimal("inf"), 101)
4312 self.assertTrue(q.is_infinite() and r.is_nan())
4313 self.assertTrue(c.flags[InvalidOperation])
4314
4315 c.clear_flags()
4316 q, r = divmod(Decimal(0), 0)
4317 self.assertTrue(q.is_nan() and r.is_nan())
4318 self.assertTrue(c.flags[InvalidOperation])
4319
4320 c.traps[DivisionByZero] = False
4321 c.clear_flags()
4322 q, r = divmod(Decimal(11), 0)
4323 self.assertTrue(q.is_infinite() and r.is_nan())
4324 self.assertTrue(c.flags[InvalidOperation] and
4325 c.flags[DivisionByZero])
4326
4327 def test_power(self):
4328 Decimal = self.decimal.Decimal
4329 localcontext = self.decimal.localcontext
4330 Overflow = self.decimal.Overflow
4331 Rounded = self.decimal.Rounded
4332
4333 with localcontext() as c:
4334 c.prec = 3
4335 c.clear_flags()
4336 self.assertEqual(Decimal("1.0") ** 100, Decimal('1.00'))
4337 self.assertTrue(c.flags[Rounded])
4338
4339 c.prec = 1
4340 c.Emax = 1
4341 c.Emin = -1
4342 c.clear_flags()
4343 c.traps[Overflow] = False
4344 self.assertEqual(Decimal(10000) ** Decimal("0.5"), Decimal('inf'))
4345 self.assertTrue(c.flags[Overflow])
4346
4347 def test_quantize(self):
4348 Decimal = self.decimal.Decimal
4349 localcontext = self.decimal.localcontext
4350 InvalidOperation = self.decimal.InvalidOperation
4351
4352 with localcontext() as c:
4353 c.prec = 1
4354 c.Emax = 1
4355 c.Emin = -1
4356 c.traps[InvalidOperation] = False
4357 x = Decimal(99).quantize(Decimal("1e1"))
4358 self.assertTrue(x.is_nan())
4359
4360 def test_radix(self):
4361 Decimal = self.decimal.Decimal
4362 getcontext = self.decimal.getcontext
4363
4364 c = getcontext()
4365 self.assertEqual(Decimal("1").radix(), 10)
4366 self.assertEqual(c.radix(), 10)
4367
4368 def test_rop(self):
4369 Decimal = self.decimal.Decimal
4370
4371 for attr in ('__radd__', '__rsub__', '__rmul__', '__rtruediv__',
4372 '__rdivmod__', '__rmod__', '__rfloordiv__', '__rpow__'):
4373 self.assertIs(getattr(Decimal("1"), attr)("xyz"), NotImplemented)
4374
4375 def test_round(self):
4376 # Python3 behavior: round() returns Decimal
4377 Decimal = self.decimal.Decimal
4378 getcontext = self.decimal.getcontext
4379
4380 c = getcontext()
4381 c.prec = 28
4382
4383 self.assertEqual(str(Decimal("9.99").__round__()), "10")
4384 self.assertEqual(str(Decimal("9.99e-5").__round__()), "0")
4385 self.assertEqual(str(Decimal("1.23456789").__round__(5)), "1.23457")
4386 self.assertEqual(str(Decimal("1.2345").__round__(10)), "1.2345000000")
4387 self.assertEqual(str(Decimal("1.2345").__round__(-10)), "0E+10")
4388
4389 self.assertRaises(TypeError, Decimal("1.23").__round__, "5")
4390 self.assertRaises(TypeError, Decimal("1.23").__round__, 5, 8)
4391
4392 def test_create_decimal(self):
4393 c = self.decimal.Context()
4394 self.assertRaises(ValueError, c.create_decimal, ["%"])
4395
4396 def test_int(self):
4397 Decimal = self.decimal.Decimal
4398 localcontext = self.decimal.localcontext
4399
4400 with localcontext() as c:
4401 c.prec = 9999
4402 x = Decimal(1221**1271) / 10**3923
4403 self.assertEqual(int(x), 1)
4404 self.assertEqual(x.to_integral(), 2)
4405
4406 def test_copy(self):
4407 Context = self.decimal.Context
4408
4409 c = Context()
4410 c.prec = 10000
4411 x = -(1172 ** 1712)
4412
4413 y = c.copy_abs(x)
4414 self.assertEqual(y, -x)
4415
4416 y = c.copy_negate(x)
4417 self.assertEqual(y, -x)
4418
4419 y = c.copy_sign(x, 1)
4420 self.assertEqual(y, -x)
4421
4422class CCoverage(Coverage):
4423 decimal = C
4424class PyCoverage(Coverage):
4425 decimal = P
4426
4427class PyFunctionality(unittest.TestCase):
4428 """Extra functionality in decimal.py"""
4429
4430 def test_py_quantize_watchexp(self):
4431 # watchexp functionality
4432 Decimal = P.Decimal
4433 localcontext = P.localcontext
4434
4435 with localcontext() as c:
4436 c.prec = 1
4437 c.Emax = 1
4438 c.Emin = -1
4439 x = Decimal(99999).quantize(Decimal("1e3"), watchexp=False)
4440 self.assertEqual(x, Decimal('1.00E+5'))
4441
4442 def test_py_alternate_formatting(self):
4443 # triples giving a format, a Decimal, and the expected result
4444 Decimal = P.Decimal
4445 localcontext = P.localcontext
4446
4447 test_values = [
4448 # Issue 7094: Alternate formatting (specified by #)
4449 ('.0e', '1.0', '1e+0'),
4450 ('#.0e', '1.0', '1.e+0'),
4451 ('.0f', '1.0', '1'),
4452 ('#.0f', '1.0', '1.'),
4453 ('g', '1.1', '1.1'),
4454 ('#g', '1.1', '1.1'),
4455 ('.0g', '1', '1'),
4456 ('#.0g', '1', '1.'),
4457 ('.0%', '1.0', '100%'),
4458 ('#.0%', '1.0', '100.%'),
4459 ]
4460 for fmt, d, result in test_values:
4461 self.assertEqual(format(Decimal(d), fmt), result)
4462
4463class PyWhitebox(unittest.TestCase):
4464 """White box testing for decimal.py"""
4465
4466 def test_py_exact_power(self):
4467 # Rarely exercised lines in _power_exact.
4468 Decimal = P.Decimal
4469 localcontext = P.localcontext
4470
4471 with localcontext() as c:
4472 c.prec = 8
4473 x = Decimal(2**16) ** Decimal("-0.5")
4474 self.assertEqual(x, Decimal('0.00390625'))
4475
4476 x = Decimal(2**16) ** Decimal("-0.6")
4477 self.assertEqual(x, Decimal('0.0012885819'))
4478
4479 x = Decimal("256e7") ** Decimal("-0.5")
4480
4481 x = Decimal(152587890625) ** Decimal('-0.0625')
4482 self.assertEqual(x, Decimal("0.2"))
4483
4484 x = Decimal("152587890625e7") ** Decimal('-0.0625')
4485
4486 x = Decimal(5**2659) ** Decimal('-0.0625')
4487
4488 c.prec = 1
4489 x = Decimal("152587890625") ** Decimal('-0.5')
4490 c.prec = 201
4491 x = Decimal(2**578) ** Decimal("-0.5")
4492
4493 def test_py_immutability_operations(self):
Terry Jan Reedy0f847642013-03-11 18:34:00 -04004494 # Do operations and check that it didn't change internal objects.
Stefan Krah1919b7e2012-03-21 18:25:23 +01004495 Decimal = P.Decimal
4496 DefaultContext = P.DefaultContext
4497 setcontext = P.setcontext
4498
4499 c = DefaultContext.copy()
4500 c.traps = dict((s, 0) for s in OrderedSignals[P])
4501 setcontext(c)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004502
4503 d1 = Decimal('-25e55')
4504 b1 = Decimal('-25e55')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004505 d2 = Decimal('33e+33')
4506 b2 = Decimal('33e+33')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004507
4508 def checkSameDec(operation, useOther=False):
4509 if useOther:
4510 eval("d1." + operation + "(d2)")
4511 self.assertEqual(d1._sign, b1._sign)
4512 self.assertEqual(d1._int, b1._int)
4513 self.assertEqual(d1._exp, b1._exp)
4514 self.assertEqual(d2._sign, b2._sign)
4515 self.assertEqual(d2._int, b2._int)
4516 self.assertEqual(d2._exp, b2._exp)
4517 else:
4518 eval("d1." + operation + "()")
4519 self.assertEqual(d1._sign, b1._sign)
4520 self.assertEqual(d1._int, b1._int)
4521 self.assertEqual(d1._exp, b1._exp)
4522 return
4523
4524 Decimal(d1)
4525 self.assertEqual(d1._sign, b1._sign)
4526 self.assertEqual(d1._int, b1._int)
4527 self.assertEqual(d1._exp, b1._exp)
4528
4529 checkSameDec("__abs__")
4530 checkSameDec("__add__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004531 checkSameDec("__divmod__", True)
Christian Heimes77c02eb2008-02-09 02:18:51 +00004532 checkSameDec("__eq__", True)
4533 checkSameDec("__ne__", True)
4534 checkSameDec("__le__", True)
4535 checkSameDec("__lt__", True)
4536 checkSameDec("__ge__", True)
4537 checkSameDec("__gt__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004538 checkSameDec("__float__")
4539 checkSameDec("__floordiv__", True)
4540 checkSameDec("__hash__")
4541 checkSameDec("__int__")
Christian Heimes969fe572008-01-25 11:23:10 +00004542 checkSameDec("__trunc__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004543 checkSameDec("__mod__", True)
4544 checkSameDec("__mul__", True)
4545 checkSameDec("__neg__")
Jack Diederich4dafcc42006-11-28 19:15:13 +00004546 checkSameDec("__bool__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004547 checkSameDec("__pos__")
4548 checkSameDec("__pow__", True)
4549 checkSameDec("__radd__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004550 checkSameDec("__rdivmod__", True)
4551 checkSameDec("__repr__")
4552 checkSameDec("__rfloordiv__", True)
4553 checkSameDec("__rmod__", True)
4554 checkSameDec("__rmul__", True)
4555 checkSameDec("__rpow__", True)
4556 checkSameDec("__rsub__", True)
4557 checkSameDec("__str__")
4558 checkSameDec("__sub__", True)
4559 checkSameDec("__truediv__", True)
4560 checkSameDec("adjusted")
4561 checkSameDec("as_tuple")
4562 checkSameDec("compare", True)
4563 checkSameDec("max", True)
4564 checkSameDec("min", True)
4565 checkSameDec("normalize")
4566 checkSameDec("quantize", True)
4567 checkSameDec("remainder_near", True)
4568 checkSameDec("same_quantum", True)
4569 checkSameDec("sqrt")
4570 checkSameDec("to_eng_string")
4571 checkSameDec("to_integral")
4572
Stefan Krah1919b7e2012-03-21 18:25:23 +01004573 def test_py_decimal_id(self):
4574 Decimal = P.Decimal
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004575
Stefan Krah1919b7e2012-03-21 18:25:23 +01004576 d = Decimal(45)
4577 e = Decimal(d)
4578 self.assertEqual(str(e), '45')
4579 self.assertNotEqual(id(d), id(e))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004580
Stefan Krah1919b7e2012-03-21 18:25:23 +01004581 def test_py_rescale(self):
4582 # Coverage
4583 Decimal = P.Decimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01004584 localcontext = P.localcontext
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004585
Stefan Krah1919b7e2012-03-21 18:25:23 +01004586 with localcontext() as c:
4587 x = Decimal("NaN")._rescale(3, ROUND_UP)
4588 self.assertTrue(x.is_nan())
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004589
Stefan Krah1919b7e2012-03-21 18:25:23 +01004590 def test_py__round(self):
4591 # Coverage
4592 Decimal = P.Decimal
Christian Heimes0348fb62008-03-26 12:55:56 +00004593
Stefan Krah1919b7e2012-03-21 18:25:23 +01004594 self.assertRaises(ValueError, Decimal("3.1234")._round, 0, ROUND_UP)
Mark Dickinsona2d1fe02009-10-29 12:23:02 +00004595
Stefan Krah1919b7e2012-03-21 18:25:23 +01004596class CFunctionality(unittest.TestCase):
4597 """Extra functionality in _decimal"""
Mark Dickinsona2d1fe02009-10-29 12:23:02 +00004598
Stefan Krah1919b7e2012-03-21 18:25:23 +01004599 @requires_extra_functionality
4600 def test_c_ieee_context(self):
4601 # issue 8786: Add support for IEEE 754 contexts to decimal module.
4602 IEEEContext = C.IEEEContext
4603 DECIMAL32 = C.DECIMAL32
4604 DECIMAL64 = C.DECIMAL64
4605 DECIMAL128 = C.DECIMAL128
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004606
Stefan Krah1919b7e2012-03-21 18:25:23 +01004607 def assert_rest(self, context):
4608 self.assertEqual(context.clamp, 1)
4609 assert_signals(self, context, 'traps', [])
4610 assert_signals(self, context, 'flags', [])
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004611
Stefan Krah1919b7e2012-03-21 18:25:23 +01004612 c = IEEEContext(DECIMAL32)
4613 self.assertEqual(c.prec, 7)
4614 self.assertEqual(c.Emax, 96)
4615 self.assertEqual(c.Emin, -95)
4616 assert_rest(self, c)
Raymond Hettinger82417ca2009-02-03 03:54:28 +00004617
Stefan Krah1919b7e2012-03-21 18:25:23 +01004618 c = IEEEContext(DECIMAL64)
4619 self.assertEqual(c.prec, 16)
4620 self.assertEqual(c.Emax, 384)
4621 self.assertEqual(c.Emin, -383)
4622 assert_rest(self, c)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004623
Stefan Krah1919b7e2012-03-21 18:25:23 +01004624 c = IEEEContext(DECIMAL128)
4625 self.assertEqual(c.prec, 34)
4626 self.assertEqual(c.Emax, 6144)
4627 self.assertEqual(c.Emin, -6143)
4628 assert_rest(self, c)
Raymond Hettinger5548be22004-07-05 18:49:38 +00004629
Stefan Krah1919b7e2012-03-21 18:25:23 +01004630 # Invalid values
4631 self.assertRaises(OverflowError, IEEEContext, 2**63)
4632 self.assertRaises(ValueError, IEEEContext, -1)
4633 self.assertRaises(ValueError, IEEEContext, 1024)
Mark Dickinson825fce32009-09-07 18:08:12 +00004634
Stefan Krah1919b7e2012-03-21 18:25:23 +01004635 @requires_extra_functionality
4636 def test_c_context(self):
4637 Context = C.Context
Christian Heimes969fe572008-01-25 11:23:10 +00004638
Stefan Krah1919b7e2012-03-21 18:25:23 +01004639 c = Context(flags=C.DecClamped, traps=C.DecRounded)
4640 self.assertEqual(c._flags, C.DecClamped)
4641 self.assertEqual(c._traps, C.DecRounded)
Raymond Hettinger771ed762009-01-03 19:20:32 +00004642
Stefan Krah1919b7e2012-03-21 18:25:23 +01004643 @requires_extra_functionality
4644 def test_constants(self):
4645 # Condition flags
4646 cond = (
4647 C.DecClamped, C.DecConversionSyntax, C.DecDivisionByZero,
4648 C.DecDivisionImpossible, C.DecDivisionUndefined,
4649 C.DecFpuError, C.DecInexact, C.DecInvalidContext,
4650 C.DecInvalidOperation, C.DecMallocError,
4651 C.DecFloatOperation, C.DecOverflow, C.DecRounded,
4652 C.DecSubnormal, C.DecUnderflow
Raymond Hettinger771ed762009-01-03 19:20:32 +00004653 )
Stefan Krah1919b7e2012-03-21 18:25:23 +01004654
4655 # IEEEContext
4656 self.assertEqual(C.DECIMAL32, 32)
4657 self.assertEqual(C.DECIMAL64, 64)
4658 self.assertEqual(C.DECIMAL128, 128)
4659 self.assertEqual(C.IEEE_CONTEXT_MAX_BITS, 512)
4660
Stefan Krah1919b7e2012-03-21 18:25:23 +01004661 # Conditions
4662 for i, v in enumerate(cond):
4663 self.assertEqual(v, 1<<i)
4664
4665 self.assertEqual(C.DecIEEEInvalidOperation,
4666 C.DecConversionSyntax|
4667 C.DecDivisionImpossible|
4668 C.DecDivisionUndefined|
4669 C.DecFpuError|
4670 C.DecInvalidContext|
4671 C.DecInvalidOperation|
4672 C.DecMallocError)
4673
4674 self.assertEqual(C.DecErrors,
4675 C.DecIEEEInvalidOperation|
4676 C.DecDivisionByZero)
4677
4678 self.assertEqual(C.DecTraps,
4679 C.DecErrors|C.DecOverflow|C.DecUnderflow)
4680
4681class CWhitebox(unittest.TestCase):
4682 """Whitebox testing for _decimal"""
4683
4684 def test_bignum(self):
4685 # Not exactly whitebox, but too slow with pydecimal.
4686
4687 Decimal = C.Decimal
4688 localcontext = C.localcontext
4689
4690 b1 = 10**35
4691 b2 = 10**36
4692 with localcontext() as c:
4693 c.prec = 1000000
4694 for i in range(5):
4695 a = random.randrange(b1, b2)
4696 b = random.randrange(1000, 1200)
4697 x = a ** b
4698 y = Decimal(a) ** Decimal(b)
4699 self.assertEqual(x, y)
4700
4701 def test_invalid_construction(self):
4702 self.assertRaises(TypeError, C.Decimal, 9, "xyz")
4703
4704 def test_c_input_restriction(self):
4705 # Too large for _decimal to be converted exactly
4706 Decimal = C.Decimal
4707 InvalidOperation = C.InvalidOperation
4708 Context = C.Context
4709 localcontext = C.localcontext
4710
4711 with localcontext(Context()):
4712 self.assertRaises(InvalidOperation, Decimal,
4713 "1e9999999999999999999")
4714
4715 def test_c_context_repr(self):
4716 # This test is _decimal-only because flags are not printed
4717 # in the same order.
4718 DefaultContext = C.DefaultContext
4719 FloatOperation = C.FloatOperation
Stefan Krah1919b7e2012-03-21 18:25:23 +01004720
4721 c = DefaultContext.copy()
4722
4723 c.prec = 425000000
4724 c.Emax = 425000000
4725 c.Emin = -425000000
4726 c.rounding = ROUND_HALF_DOWN
4727 c.capitals = 0
4728 c.clamp = 1
4729 for sig in OrderedSignals[C]:
4730 c.flags[sig] = True
4731 c.traps[sig] = True
4732 c.flags[FloatOperation] = True
4733 c.traps[FloatOperation] = True
4734
4735 s = c.__repr__()
4736 t = "Context(prec=425000000, rounding=ROUND_HALF_DOWN, " \
4737 "Emin=-425000000, Emax=425000000, capitals=0, clamp=1, " \
4738 "flags=[Clamped, InvalidOperation, DivisionByZero, Inexact, " \
4739 "FloatOperation, Overflow, Rounded, Subnormal, Underflow], " \
4740 "traps=[Clamped, InvalidOperation, DivisionByZero, Inexact, " \
4741 "FloatOperation, Overflow, Rounded, Subnormal, Underflow])"
4742 self.assertEqual(s, t)
4743
4744 def test_c_context_errors(self):
4745 Context = C.Context
4746 InvalidOperation = C.InvalidOperation
4747 Overflow = C.Overflow
4748 FloatOperation = C.FloatOperation
4749 localcontext = C.localcontext
4750 getcontext = C.getcontext
4751 setcontext = C.setcontext
4752 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
4753
4754 c = Context()
4755
4756 # SignalDict: input validation
4757 self.assertRaises(KeyError, c.flags.__setitem__, 801, 0)
4758 self.assertRaises(KeyError, c.traps.__setitem__, 801, 0)
4759 self.assertRaises(ValueError, c.flags.__delitem__, Overflow)
4760 self.assertRaises(ValueError, c.traps.__delitem__, InvalidOperation)
4761 self.assertRaises(TypeError, setattr, c, 'flags', ['x'])
4762 self.assertRaises(TypeError, setattr, c,'traps', ['y'])
4763 self.assertRaises(KeyError, setattr, c, 'flags', {0:1})
4764 self.assertRaises(KeyError, setattr, c, 'traps', {0:1})
4765
4766 # Test assignment from a signal dict with the correct length but
4767 # one invalid key.
4768 d = c.flags.copy()
4769 del d[FloatOperation]
4770 d["XYZ"] = 91283719
4771 self.assertRaises(KeyError, setattr, c, 'flags', d)
4772 self.assertRaises(KeyError, setattr, c, 'traps', d)
4773
4774 # Input corner cases
4775 int_max = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
4776 gt_max_emax = 10**18 if HAVE_CONFIG_64 else 10**9
4777
4778 # prec, Emax, Emin
4779 for attr in ['prec', 'Emax']:
4780 self.assertRaises(ValueError, setattr, c, attr, gt_max_emax)
4781 self.assertRaises(ValueError, setattr, c, 'Emin', -gt_max_emax)
4782
4783 # prec, Emax, Emin in context constructor
4784 self.assertRaises(ValueError, Context, prec=gt_max_emax)
4785 self.assertRaises(ValueError, Context, Emax=gt_max_emax)
4786 self.assertRaises(ValueError, Context, Emin=-gt_max_emax)
4787
4788 # Overflow in conversion
4789 self.assertRaises(OverflowError, Context, prec=int_max+1)
4790 self.assertRaises(OverflowError, Context, Emax=int_max+1)
4791 self.assertRaises(OverflowError, Context, Emin=-int_max-2)
Stefan Krah1919b7e2012-03-21 18:25:23 +01004792 self.assertRaises(OverflowError, Context, clamp=int_max+1)
4793 self.assertRaises(OverflowError, Context, capitals=int_max+1)
4794
4795 # OverflowError, general ValueError
4796 for attr in ('prec', 'Emin', 'Emax', 'capitals', 'clamp'):
4797 self.assertRaises(OverflowError, setattr, c, attr, int_max+1)
4798 self.assertRaises(OverflowError, setattr, c, attr, -int_max-2)
4799 if sys.platform != 'win32':
4800 self.assertRaises(ValueError, setattr, c, attr, int_max)
4801 self.assertRaises(ValueError, setattr, c, attr, -int_max-1)
4802
Stefan Krah1919b7e2012-03-21 18:25:23 +01004803 # OverflowError: _unsafe_setprec, _unsafe_setemin, _unsafe_setemax
4804 if C.MAX_PREC == 425000000:
4805 self.assertRaises(OverflowError, getattr(c, '_unsafe_setprec'),
4806 int_max+1)
4807 self.assertRaises(OverflowError, getattr(c, '_unsafe_setemax'),
4808 int_max+1)
4809 self.assertRaises(OverflowError, getattr(c, '_unsafe_setemin'),
4810 -int_max-2)
4811
4812 # ValueError: _unsafe_setprec, _unsafe_setemin, _unsafe_setemax
4813 if C.MAX_PREC == 425000000:
4814 self.assertRaises(ValueError, getattr(c, '_unsafe_setprec'), 0)
4815 self.assertRaises(ValueError, getattr(c, '_unsafe_setprec'),
4816 1070000001)
4817 self.assertRaises(ValueError, getattr(c, '_unsafe_setemax'), -1)
4818 self.assertRaises(ValueError, getattr(c, '_unsafe_setemax'),
4819 1070000001)
4820 self.assertRaises(ValueError, getattr(c, '_unsafe_setemin'),
4821 -1070000001)
4822 self.assertRaises(ValueError, getattr(c, '_unsafe_setemin'), 1)
4823
4824 # capitals, clamp
4825 for attr in ['capitals', 'clamp']:
4826 self.assertRaises(ValueError, setattr, c, attr, -1)
4827 self.assertRaises(ValueError, setattr, c, attr, 2)
4828 self.assertRaises(TypeError, setattr, c, attr, [1,2,3])
4829 if HAVE_CONFIG_64:
4830 self.assertRaises(ValueError, setattr, c, attr, 2**32)
4831 self.assertRaises(ValueError, setattr, c, attr, 2**32+1)
4832
4833 # Invalid local context
4834 self.assertRaises(TypeError, exec, 'with localcontext("xyz"): pass',
4835 locals())
Stefan Krah040e3112012-12-15 22:33:33 +01004836 self.assertRaises(TypeError, exec,
4837 'with localcontext(context=getcontext()): pass',
4838 locals())
Stefan Krah1919b7e2012-03-21 18:25:23 +01004839
4840 # setcontext
4841 saved_context = getcontext()
4842 self.assertRaises(TypeError, setcontext, "xyz")
4843 setcontext(saved_context)
4844
Stefan Krah59a4a932013-01-16 12:58:59 +01004845 def test_rounding_strings_interned(self):
4846
4847 self.assertIs(C.ROUND_UP, P.ROUND_UP)
4848 self.assertIs(C.ROUND_DOWN, P.ROUND_DOWN)
4849 self.assertIs(C.ROUND_CEILING, P.ROUND_CEILING)
4850 self.assertIs(C.ROUND_FLOOR, P.ROUND_FLOOR)
4851 self.assertIs(C.ROUND_HALF_UP, P.ROUND_HALF_UP)
4852 self.assertIs(C.ROUND_HALF_DOWN, P.ROUND_HALF_DOWN)
4853 self.assertIs(C.ROUND_HALF_EVEN, P.ROUND_HALF_EVEN)
4854 self.assertIs(C.ROUND_05UP, P.ROUND_05UP)
4855
Stefan Krah1919b7e2012-03-21 18:25:23 +01004856 @requires_extra_functionality
4857 def test_c_context_errors_extra(self):
4858 Context = C.Context
4859 InvalidOperation = C.InvalidOperation
4860 Overflow = C.Overflow
4861 localcontext = C.localcontext
4862 getcontext = C.getcontext
4863 setcontext = C.setcontext
4864 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
4865
4866 c = Context()
4867
4868 # Input corner cases
4869 int_max = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
4870
4871 # OverflowError, general ValueError
4872 self.assertRaises(OverflowError, setattr, c, '_allcr', int_max+1)
4873 self.assertRaises(OverflowError, setattr, c, '_allcr', -int_max-2)
4874 if sys.platform != 'win32':
4875 self.assertRaises(ValueError, setattr, c, '_allcr', int_max)
4876 self.assertRaises(ValueError, setattr, c, '_allcr', -int_max-1)
4877
4878 # OverflowError, general TypeError
4879 for attr in ('_flags', '_traps'):
4880 self.assertRaises(OverflowError, setattr, c, attr, int_max+1)
4881 self.assertRaises(OverflowError, setattr, c, attr, -int_max-2)
4882 if sys.platform != 'win32':
4883 self.assertRaises(TypeError, setattr, c, attr, int_max)
4884 self.assertRaises(TypeError, setattr, c, attr, -int_max-1)
4885
4886 # _allcr
4887 self.assertRaises(ValueError, setattr, c, '_allcr', -1)
4888 self.assertRaises(ValueError, setattr, c, '_allcr', 2)
4889 self.assertRaises(TypeError, setattr, c, '_allcr', [1,2,3])
4890 if HAVE_CONFIG_64:
4891 self.assertRaises(ValueError, setattr, c, '_allcr', 2**32)
4892 self.assertRaises(ValueError, setattr, c, '_allcr', 2**32+1)
4893
4894 # _flags, _traps
4895 for attr in ['_flags', '_traps']:
4896 self.assertRaises(TypeError, setattr, c, attr, 999999)
4897 self.assertRaises(TypeError, setattr, c, attr, 'x')
4898
4899 def test_c_valid_context(self):
4900 # These tests are for code coverage in _decimal.
4901 DefaultContext = C.DefaultContext
Stefan Krah1919b7e2012-03-21 18:25:23 +01004902 Clamped = C.Clamped
4903 Underflow = C.Underflow
4904 Inexact = C.Inexact
4905 Rounded = C.Rounded
4906 Subnormal = C.Subnormal
4907
4908 c = DefaultContext.copy()
4909
4910 # Exercise all getters and setters
4911 c.prec = 34
4912 c.rounding = ROUND_HALF_UP
4913 c.Emax = 3000
4914 c.Emin = -3000
4915 c.capitals = 1
4916 c.clamp = 0
4917
4918 self.assertEqual(c.prec, 34)
4919 self.assertEqual(c.rounding, ROUND_HALF_UP)
4920 self.assertEqual(c.Emin, -3000)
4921 self.assertEqual(c.Emax, 3000)
4922 self.assertEqual(c.capitals, 1)
4923 self.assertEqual(c.clamp, 0)
4924
4925 self.assertEqual(c.Etiny(), -3033)
4926 self.assertEqual(c.Etop(), 2967)
4927
4928 # Exercise all unsafe setters
4929 if C.MAX_PREC == 425000000:
4930 c._unsafe_setprec(999999999)
4931 c._unsafe_setemax(999999999)
4932 c._unsafe_setemin(-999999999)
4933 self.assertEqual(c.prec, 999999999)
4934 self.assertEqual(c.Emax, 999999999)
4935 self.assertEqual(c.Emin, -999999999)
4936
4937 @requires_extra_functionality
4938 def test_c_valid_context_extra(self):
4939 DefaultContext = C.DefaultContext
4940
4941 c = DefaultContext.copy()
4942 self.assertEqual(c._allcr, 1)
4943 c._allcr = 0
4944 self.assertEqual(c._allcr, 0)
4945
4946 def test_c_round(self):
4947 # Restricted input.
4948 Decimal = C.Decimal
4949 InvalidOperation = C.InvalidOperation
4950 localcontext = C.localcontext
4951 MAX_EMAX = C.MAX_EMAX
4952 MIN_ETINY = C.MIN_ETINY
4953 int_max = 2**63-1 if C.MAX_PREC > 425000000 else 2**31-1
4954
4955 with localcontext() as c:
4956 c.traps[InvalidOperation] = True
4957 self.assertRaises(InvalidOperation, Decimal("1.23").__round__,
4958 -int_max-1)
4959 self.assertRaises(InvalidOperation, Decimal("1.23").__round__,
4960 int_max)
4961 self.assertRaises(InvalidOperation, Decimal("1").__round__,
4962 int(MAX_EMAX+1))
4963 self.assertRaises(C.InvalidOperation, Decimal("1").__round__,
4964 -int(MIN_ETINY-1))
4965 self.assertRaises(OverflowError, Decimal("1.23").__round__,
4966 -int_max-2)
4967 self.assertRaises(OverflowError, Decimal("1.23").__round__,
4968 int_max+1)
4969
4970 def test_c_format(self):
4971 # Restricted input
4972 Decimal = C.Decimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01004973 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
4974
4975 self.assertRaises(TypeError, Decimal(1).__format__, "=10.10", [], 9)
4976 self.assertRaises(TypeError, Decimal(1).__format__, "=10.10", 9)
4977 self.assertRaises(TypeError, Decimal(1).__format__, [])
4978
Stefan Kraheb8c4512013-01-24 15:22:33 +01004979 self.assertRaises(ValueError, Decimal(1).__format__, "<>=10.10")
4980 maxsize = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
4981 self.assertRaises(ValueError, Decimal("1.23456789").__format__,
4982 "=%d.1" % maxsize)
Stefan Krah1919b7e2012-03-21 18:25:23 +01004983
4984 def test_c_integral(self):
4985 Decimal = C.Decimal
4986 Inexact = C.Inexact
Stefan Krah1919b7e2012-03-21 18:25:23 +01004987 localcontext = C.localcontext
4988
4989 x = Decimal(10)
4990 self.assertEqual(x.to_integral(), 10)
4991 self.assertRaises(TypeError, x.to_integral, '10')
4992 self.assertRaises(TypeError, x.to_integral, 10, 'x')
4993 self.assertRaises(TypeError, x.to_integral, 10)
4994
4995 self.assertEqual(x.to_integral_value(), 10)
4996 self.assertRaises(TypeError, x.to_integral_value, '10')
4997 self.assertRaises(TypeError, x.to_integral_value, 10, 'x')
4998 self.assertRaises(TypeError, x.to_integral_value, 10)
4999
5000 self.assertEqual(x.to_integral_exact(), 10)
5001 self.assertRaises(TypeError, x.to_integral_exact, '10')
5002 self.assertRaises(TypeError, x.to_integral_exact, 10, 'x')
5003 self.assertRaises(TypeError, x.to_integral_exact, 10)
5004
5005 with localcontext() as c:
5006 x = Decimal("99999999999999999999999999.9").to_integral_value(ROUND_UP)
5007 self.assertEqual(x, Decimal('100000000000000000000000000'))
5008
5009 x = Decimal("99999999999999999999999999.9").to_integral_exact(ROUND_UP)
5010 self.assertEqual(x, Decimal('100000000000000000000000000'))
5011
5012 c.traps[Inexact] = True
5013 self.assertRaises(Inexact, Decimal("999.9").to_integral_exact, ROUND_UP)
5014
5015 def test_c_funcs(self):
5016 # Invalid arguments
5017 Decimal = C.Decimal
5018 InvalidOperation = C.InvalidOperation
5019 DivisionByZero = C.DivisionByZero
Stefan Krah1919b7e2012-03-21 18:25:23 +01005020 getcontext = C.getcontext
5021 localcontext = C.localcontext
5022
5023 self.assertEqual(Decimal('9.99e10').to_eng_string(), '99.9E+9')
5024
5025 self.assertRaises(TypeError, pow, Decimal(1), 2, "3")
5026 self.assertRaises(TypeError, Decimal(9).number_class, "x", "y")
5027 self.assertRaises(TypeError, Decimal(9).same_quantum, 3, "x", "y")
5028
Raymond Hettinger771ed762009-01-03 19:20:32 +00005029 self.assertRaises(
Stefan Krah1919b7e2012-03-21 18:25:23 +01005030 TypeError,
5031 Decimal("1.23456789").quantize, Decimal('1e-100000'), []
Raymond Hettinger771ed762009-01-03 19:20:32 +00005032 )
Stefan Krah1919b7e2012-03-21 18:25:23 +01005033 self.assertRaises(
5034 TypeError,
5035 Decimal("1.23456789").quantize, Decimal('1e-100000'), getcontext()
5036 )
5037 self.assertRaises(
5038 TypeError,
5039 Decimal("1.23456789").quantize, Decimal('1e-100000'), 10
5040 )
5041 self.assertRaises(
5042 TypeError,
5043 Decimal("1.23456789").quantize, Decimal('1e-100000'), ROUND_UP, 1000
5044 )
Raymond Hettinger771ed762009-01-03 19:20:32 +00005045
Stefan Krah1919b7e2012-03-21 18:25:23 +01005046 with localcontext() as c:
5047 c.clear_traps()
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00005048
Stefan Krah1919b7e2012-03-21 18:25:23 +01005049 # Invalid arguments
5050 self.assertRaises(TypeError, c.copy_sign, Decimal(1), "x", "y")
5051 self.assertRaises(TypeError, c.canonical, 200)
5052 self.assertRaises(TypeError, c.is_canonical, 200)
5053 self.assertRaises(TypeError, c.divmod, 9, 8, "x", "y")
5054 self.assertRaises(TypeError, c.same_quantum, 9, 3, "x", "y")
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00005055
Stefan Krah1919b7e2012-03-21 18:25:23 +01005056 self.assertEqual(str(c.canonical(Decimal(200))), '200')
5057 self.assertEqual(c.radix(), 10)
Raymond Hettinger0aeac102004-07-05 22:53:03 +00005058
Stefan Krah1919b7e2012-03-21 18:25:23 +01005059 c.traps[DivisionByZero] = True
5060 self.assertRaises(DivisionByZero, Decimal(9).__divmod__, 0)
5061 self.assertRaises(DivisionByZero, c.divmod, 9, 0)
5062 self.assertTrue(c.flags[InvalidOperation])
Raymond Hettinger955d2b22004-08-08 20:17:45 +00005063
Stefan Krah1919b7e2012-03-21 18:25:23 +01005064 c.clear_flags()
5065 c.traps[InvalidOperation] = True
5066 self.assertRaises(InvalidOperation, Decimal(9).__divmod__, 0)
5067 self.assertRaises(InvalidOperation, c.divmod, 9, 0)
5068 self.assertTrue(c.flags[DivisionByZero])
Mark Dickinsonb1d8e322010-05-22 18:35:36 +00005069
Stefan Krah1919b7e2012-03-21 18:25:23 +01005070 c.traps[InvalidOperation] = True
5071 c.prec = 2
5072 self.assertRaises(InvalidOperation, pow, Decimal(1000), 1, 501)
Mark Dickinson84230a12010-02-18 14:49:50 +00005073
Stefan Krah040e3112012-12-15 22:33:33 +01005074 def test_va_args_exceptions(self):
5075 Decimal = C.Decimal
5076 Context = C.Context
5077
5078 x = Decimal("10001111111")
5079
5080 for attr in ['exp', 'is_normal', 'is_subnormal', 'ln', 'log10',
5081 'logb', 'logical_invert', 'next_minus', 'next_plus',
5082 'normalize', 'number_class', 'sqrt', 'to_eng_string']:
5083 func = getattr(x, attr)
5084 self.assertRaises(TypeError, func, context="x")
5085 self.assertRaises(TypeError, func, "x", context=None)
5086
5087 for attr in ['compare', 'compare_signal', 'logical_and',
5088 'logical_or', 'max', 'max_mag', 'min', 'min_mag',
5089 'remainder_near', 'rotate', 'scaleb', 'shift']:
5090 func = getattr(x, attr)
5091 self.assertRaises(TypeError, func, context="x")
5092 self.assertRaises(TypeError, func, "x", context=None)
5093
5094 self.assertRaises(TypeError, x.to_integral, rounding=None, context=[])
5095 self.assertRaises(TypeError, x.to_integral, rounding={}, context=[])
5096 self.assertRaises(TypeError, x.to_integral, [], [])
5097
5098 self.assertRaises(TypeError, x.to_integral_value, rounding=None, context=[])
5099 self.assertRaises(TypeError, x.to_integral_value, rounding={}, context=[])
5100 self.assertRaises(TypeError, x.to_integral_value, [], [])
5101
5102 self.assertRaises(TypeError, x.to_integral_exact, rounding=None, context=[])
5103 self.assertRaises(TypeError, x.to_integral_exact, rounding={}, context=[])
5104 self.assertRaises(TypeError, x.to_integral_exact, [], [])
5105
5106 self.assertRaises(TypeError, x.fma, 1, 2, context="x")
5107 self.assertRaises(TypeError, x.fma, 1, 2, "x", context=None)
5108
5109 self.assertRaises(TypeError, x.quantize, 1, [], context=None)
5110 self.assertRaises(TypeError, x.quantize, 1, [], rounding=None)
5111 self.assertRaises(TypeError, x.quantize, 1, [], [])
5112
5113 c = Context()
5114 self.assertRaises(TypeError, c.power, 1, 2, mod="x")
5115 self.assertRaises(TypeError, c.power, 1, "x", mod=None)
5116 self.assertRaises(TypeError, c.power, "x", 2, mod=None)
5117
Stefan Krah1919b7e2012-03-21 18:25:23 +01005118 @requires_extra_functionality
5119 def test_c_context_templates(self):
5120 self.assertEqual(
5121 C.BasicContext._traps,
5122 C.DecIEEEInvalidOperation|C.DecDivisionByZero|C.DecOverflow|
5123 C.DecUnderflow|C.DecClamped
5124 )
5125 self.assertEqual(
5126 C.DefaultContext._traps,
5127 C.DecIEEEInvalidOperation|C.DecDivisionByZero|C.DecOverflow
5128 )
Mark Dickinson84230a12010-02-18 14:49:50 +00005129
Stefan Krah1919b7e2012-03-21 18:25:23 +01005130 @requires_extra_functionality
5131 def test_c_signal_dict(self):
Mark Dickinson84230a12010-02-18 14:49:50 +00005132
Stefan Krah1919b7e2012-03-21 18:25:23 +01005133 # SignalDict coverage
5134 Context = C.Context
5135 DefaultContext = C.DefaultContext
Mark Dickinson84230a12010-02-18 14:49:50 +00005136
Stefan Krah1919b7e2012-03-21 18:25:23 +01005137 InvalidOperation = C.InvalidOperation
5138 DivisionByZero = C.DivisionByZero
5139 Overflow = C.Overflow
5140 Subnormal = C.Subnormal
5141 Underflow = C.Underflow
5142 Rounded = C.Rounded
5143 Inexact = C.Inexact
5144 Clamped = C.Clamped
Mark Dickinson84230a12010-02-18 14:49:50 +00005145
Stefan Krah1919b7e2012-03-21 18:25:23 +01005146 DecClamped = C.DecClamped
5147 DecInvalidOperation = C.DecInvalidOperation
5148 DecIEEEInvalidOperation = C.DecIEEEInvalidOperation
Mark Dickinson84230a12010-02-18 14:49:50 +00005149
Stefan Krah1919b7e2012-03-21 18:25:23 +01005150 def assertIsExclusivelySet(signal, signal_dict):
5151 for sig in signal_dict:
5152 if sig == signal:
5153 self.assertTrue(signal_dict[sig])
5154 else:
5155 self.assertFalse(signal_dict[sig])
Mark Dickinson84230a12010-02-18 14:49:50 +00005156
Stefan Krah1919b7e2012-03-21 18:25:23 +01005157 c = DefaultContext.copy()
Mark Dickinson84230a12010-02-18 14:49:50 +00005158
Stefan Krah1919b7e2012-03-21 18:25:23 +01005159 # Signal dict methods
5160 self.assertTrue(Overflow in c.traps)
5161 c.clear_traps()
5162 for k in c.traps.keys():
5163 c.traps[k] = True
5164 for v in c.traps.values():
5165 self.assertTrue(v)
5166 c.clear_traps()
5167 for k, v in c.traps.items():
5168 self.assertFalse(v)
Mark Dickinson84230a12010-02-18 14:49:50 +00005169
Stefan Krah1919b7e2012-03-21 18:25:23 +01005170 self.assertFalse(c.flags.get(Overflow))
5171 self.assertIs(c.flags.get("x"), None)
5172 self.assertEqual(c.flags.get("x", "y"), "y")
5173 self.assertRaises(TypeError, c.flags.get, "x", "y", "z")
Mark Dickinson84230a12010-02-18 14:49:50 +00005174
Stefan Krah1919b7e2012-03-21 18:25:23 +01005175 self.assertEqual(len(c.flags), len(c.traps))
5176 s = sys.getsizeof(c.flags)
5177 s = sys.getsizeof(c.traps)
5178 s = c.flags.__repr__()
Mark Dickinson84230a12010-02-18 14:49:50 +00005179
Stefan Krah1919b7e2012-03-21 18:25:23 +01005180 # Set flags/traps.
5181 c.clear_flags()
5182 c._flags = DecClamped
5183 self.assertTrue(c.flags[Clamped])
Mark Dickinson84230a12010-02-18 14:49:50 +00005184
Stefan Krah1919b7e2012-03-21 18:25:23 +01005185 c.clear_traps()
5186 c._traps = DecInvalidOperation
5187 self.assertTrue(c.traps[InvalidOperation])
Mark Dickinson84230a12010-02-18 14:49:50 +00005188
Stefan Krah1919b7e2012-03-21 18:25:23 +01005189 # Set flags/traps from dictionary.
5190 c.clear_flags()
5191 d = c.flags.copy()
5192 d[DivisionByZero] = True
5193 c.flags = d
5194 assertIsExclusivelySet(DivisionByZero, c.flags)
Mark Dickinson84230a12010-02-18 14:49:50 +00005195
Stefan Krah1919b7e2012-03-21 18:25:23 +01005196 c.clear_traps()
5197 d = c.traps.copy()
5198 d[Underflow] = True
5199 c.traps = d
5200 assertIsExclusivelySet(Underflow, c.traps)
Mark Dickinson84230a12010-02-18 14:49:50 +00005201
Stefan Krah1919b7e2012-03-21 18:25:23 +01005202 # Random constructors
5203 IntSignals = {
5204 Clamped: C.DecClamped,
5205 Rounded: C.DecRounded,
5206 Inexact: C.DecInexact,
5207 Subnormal: C.DecSubnormal,
5208 Underflow: C.DecUnderflow,
5209 Overflow: C.DecOverflow,
5210 DivisionByZero: C.DecDivisionByZero,
5211 InvalidOperation: C.DecIEEEInvalidOperation
5212 }
5213 IntCond = [
5214 C.DecDivisionImpossible, C.DecDivisionUndefined, C.DecFpuError,
5215 C.DecInvalidContext, C.DecInvalidOperation, C.DecMallocError,
5216 C.DecConversionSyntax,
5217 ]
Mark Dickinsonb455e582011-05-22 12:53:18 +01005218
Stefan Krah1919b7e2012-03-21 18:25:23 +01005219 lim = len(OrderedSignals[C])
5220 for r in range(lim):
5221 for t in range(lim):
Stefan Krah59a4a932013-01-16 12:58:59 +01005222 for round in RoundingModes:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005223 flags = random.sample(OrderedSignals[C], r)
5224 traps = random.sample(OrderedSignals[C], t)
5225 prec = random.randrange(1, 10000)
5226 emin = random.randrange(-10000, 0)
5227 emax = random.randrange(0, 10000)
5228 clamp = random.randrange(0, 2)
5229 caps = random.randrange(0, 2)
5230 cr = random.randrange(0, 2)
5231 c = Context(prec=prec, rounding=round, Emin=emin, Emax=emax,
5232 capitals=caps, clamp=clamp, flags=list(flags),
5233 traps=list(traps))
Mark Dickinson84230a12010-02-18 14:49:50 +00005234
Stefan Krah1919b7e2012-03-21 18:25:23 +01005235 self.assertEqual(c.prec, prec)
5236 self.assertEqual(c.rounding, round)
5237 self.assertEqual(c.Emin, emin)
5238 self.assertEqual(c.Emax, emax)
5239 self.assertEqual(c.capitals, caps)
5240 self.assertEqual(c.clamp, clamp)
Mark Dickinson84230a12010-02-18 14:49:50 +00005241
Stefan Krah1919b7e2012-03-21 18:25:23 +01005242 f = 0
5243 for x in flags:
5244 f |= IntSignals[x]
5245 self.assertEqual(c._flags, f)
Mark Dickinson84230a12010-02-18 14:49:50 +00005246
Stefan Krah1919b7e2012-03-21 18:25:23 +01005247 f = 0
5248 for x in traps:
5249 f |= IntSignals[x]
5250 self.assertEqual(c._traps, f)
Mark Dickinson84230a12010-02-18 14:49:50 +00005251
Stefan Krah1919b7e2012-03-21 18:25:23 +01005252 for cond in IntCond:
5253 c._flags = cond
5254 self.assertTrue(c._flags&DecIEEEInvalidOperation)
5255 assertIsExclusivelySet(InvalidOperation, c.flags)
Mark Dickinson84230a12010-02-18 14:49:50 +00005256
Stefan Krah1919b7e2012-03-21 18:25:23 +01005257 for cond in IntCond:
5258 c._traps = cond
5259 self.assertTrue(c._traps&DecIEEEInvalidOperation)
5260 assertIsExclusivelySet(InvalidOperation, c.traps)
Mark Dickinson84230a12010-02-18 14:49:50 +00005261
Stefan Krah1919b7e2012-03-21 18:25:23 +01005262 def test_invalid_override(self):
5263 Decimal = C.Decimal
Mark Dickinson84230a12010-02-18 14:49:50 +00005264
Stefan Krah1919b7e2012-03-21 18:25:23 +01005265 try:
5266 from locale import CHAR_MAX
5267 except ImportError:
5268 return
Mark Dickinson84230a12010-02-18 14:49:50 +00005269
Stefan Krah1919b7e2012-03-21 18:25:23 +01005270 def make_grouping(lst):
5271 return ''.join([chr(x) for x in lst])
Mark Dickinson84230a12010-02-18 14:49:50 +00005272
Stefan Krah1919b7e2012-03-21 18:25:23 +01005273 def get_fmt(x, override=None, fmt='n'):
5274 return Decimal(x).__format__(fmt, override)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005275
Stefan Krah1919b7e2012-03-21 18:25:23 +01005276 invalid_grouping = {
5277 'decimal_point' : ',',
5278 'grouping' : make_grouping([255, 255, 0]),
5279 'thousands_sep' : ','
5280 }
5281 invalid_dot = {
5282 'decimal_point' : 'xxxxx',
5283 'grouping' : make_grouping([3, 3, 0]),
5284 'thousands_sep' : ','
5285 }
5286 invalid_sep = {
5287 'decimal_point' : '.',
5288 'grouping' : make_grouping([3, 3, 0]),
5289 'thousands_sep' : 'yyyyy'
5290 }
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005291
Stefan Krah1919b7e2012-03-21 18:25:23 +01005292 if CHAR_MAX == 127: # negative grouping in override
5293 self.assertRaises(ValueError, get_fmt, 12345,
5294 invalid_grouping, 'g')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005295
Stefan Krah1919b7e2012-03-21 18:25:23 +01005296 self.assertRaises(ValueError, get_fmt, 12345, invalid_dot, 'g')
5297 self.assertRaises(ValueError, get_fmt, 12345, invalid_sep, 'g')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005298
Stefan Krah0774e9b2012-04-05 15:21:58 +02005299 def test_exact_conversion(self):
5300 Decimal = C.Decimal
5301 localcontext = C.localcontext
5302 InvalidOperation = C.InvalidOperation
5303
5304 with localcontext() as c:
5305
5306 c.traps[InvalidOperation] = True
5307
5308 # Clamped
5309 x = "0e%d" % sys.maxsize
5310 self.assertRaises(InvalidOperation, Decimal, x)
5311
5312 x = "0e%d" % (-sys.maxsize-1)
5313 self.assertRaises(InvalidOperation, Decimal, x)
5314
5315 # Overflow
5316 x = "1e%d" % sys.maxsize
5317 self.assertRaises(InvalidOperation, Decimal, x)
5318
5319 # Underflow
5320 x = "1e%d" % (-sys.maxsize-1)
5321 self.assertRaises(InvalidOperation, Decimal, x)
5322
Stefan Krahff3eca02012-04-05 15:46:19 +02005323 def test_from_tuple(self):
5324 Decimal = C.Decimal
5325 localcontext = C.localcontext
5326 InvalidOperation = C.InvalidOperation
5327 Overflow = C.Overflow
5328 Underflow = C.Underflow
5329
5330 with localcontext() as c:
5331
5332 c.traps[InvalidOperation] = True
5333 c.traps[Overflow] = True
5334 c.traps[Underflow] = True
5335
5336 # SSIZE_MAX
5337 x = (1, (), sys.maxsize)
5338 self.assertEqual(str(c.create_decimal(x)), '-0E+999999')
5339 self.assertRaises(InvalidOperation, Decimal, x)
5340
5341 x = (1, (0, 1, 2), sys.maxsize)
5342 self.assertRaises(Overflow, c.create_decimal, x)
5343 self.assertRaises(InvalidOperation, Decimal, x)
5344
5345 # SSIZE_MIN
5346 x = (1, (), -sys.maxsize-1)
5347 self.assertEqual(str(c.create_decimal(x)), '-0E-1000026')
5348 self.assertRaises(InvalidOperation, Decimal, x)
5349
5350 x = (1, (0, 1, 2), -sys.maxsize-1)
5351 self.assertRaises(Underflow, c.create_decimal, x)
5352 self.assertRaises(InvalidOperation, Decimal, x)
5353
5354 # OverflowError
5355 x = (1, (), sys.maxsize+1)
5356 self.assertRaises(OverflowError, c.create_decimal, x)
5357 self.assertRaises(OverflowError, Decimal, x)
5358
5359 x = (1, (), -sys.maxsize-2)
5360 self.assertRaises(OverflowError, c.create_decimal, x)
5361 self.assertRaises(OverflowError, Decimal, x)
5362
5363 # Specials
5364 x = (1, (), "N")
5365 self.assertEqual(str(Decimal(x)), '-sNaN')
5366 x = (1, (0,), "N")
5367 self.assertEqual(str(Decimal(x)), '-sNaN')
5368 x = (1, (0, 1), "N")
5369 self.assertEqual(str(Decimal(x)), '-sNaN1')
5370
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005371
Stefan Krah1919b7e2012-03-21 18:25:23 +01005372all_tests = [
5373 CExplicitConstructionTest, PyExplicitConstructionTest,
5374 CImplicitConstructionTest, PyImplicitConstructionTest,
5375 CFormatTest, PyFormatTest,
5376 CArithmeticOperatorsTest, PyArithmeticOperatorsTest,
5377 CThreadingTest, PyThreadingTest,
5378 CUsabilityTest, PyUsabilityTest,
5379 CPythonAPItests, PyPythonAPItests,
5380 CContextAPItests, PyContextAPItests,
5381 CContextWithStatement, PyContextWithStatement,
5382 CContextFlags, PyContextFlags,
5383 CSpecialContexts, PySpecialContexts,
5384 CContextInputValidation, PyContextInputValidation,
5385 CContextSubclassing, PyContextSubclassing,
5386 CCoverage, PyCoverage,
5387 CFunctionality, PyFunctionality,
5388 CWhitebox, PyWhitebox,
5389 CIBMTestCases, PyIBMTestCases,
5390]
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005391
Stefan Krah1919b7e2012-03-21 18:25:23 +01005392# Delete C tests if _decimal.so is not present.
5393if not C:
5394 all_tests = all_tests[1::2]
5395else:
5396 all_tests.insert(0, CheckAttributes)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005397
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005398
5399def test_main(arith=False, verbose=None, todo_tests=None, debug=None):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005400 """ Execute the tests.
5401
Raymond Hettingered20ad82004-09-04 20:09:13 +00005402 Runs all arithmetic tests if arith is True or if the "decimal" resource
5403 is enabled in regrtest.py
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005404 """
Raymond Hettingered20ad82004-09-04 20:09:13 +00005405
Stefan Krah1919b7e2012-03-21 18:25:23 +01005406 init(C)
5407 init(P)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005408 global TEST_ALL, DEBUG
Raymond Hettingered20ad82004-09-04 20:09:13 +00005409 TEST_ALL = arith or is_resource_enabled('decimal')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005410 DEBUG = debug
Raymond Hettingered20ad82004-09-04 20:09:13 +00005411
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005412 if todo_tests is None:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005413 test_classes = all_tests
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005414 else:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005415 test_classes = [CIBMTestCases, PyIBMTestCases]
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005416
5417 # Dynamically build custom test definition for each file in the test
5418 # directory and add the definitions to the DecimalTest class. This
5419 # procedure insures that new files do not get skipped.
5420 for filename in os.listdir(directory):
5421 if '.decTest' not in filename or filename.startswith("."):
5422 continue
5423 head, tail = filename.split('.')
5424 if todo_tests is not None and head not in todo_tests:
5425 continue
5426 tester = lambda self, f=filename: self.eval_file(directory + f)
Stefan Krah1919b7e2012-03-21 18:25:23 +01005427 setattr(CIBMTestCases, 'test_' + head, tester)
5428 setattr(PyIBMTestCases, 'test_' + head, tester)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005429 del filename, head, tail, tester
5430
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005431
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005432 try:
5433 run_unittest(*test_classes)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005434 if todo_tests is None:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005435 from doctest import IGNORE_EXCEPTION_DETAIL
5436 savedecimal = sys.modules['decimal']
5437 if C:
5438 sys.modules['decimal'] = C
5439 run_doctest(C, verbose, optionflags=IGNORE_EXCEPTION_DETAIL)
5440 sys.modules['decimal'] = P
5441 run_doctest(P, verbose)
5442 sys.modules['decimal'] = savedecimal
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005443 finally:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005444 if C: C.setcontext(ORIGINAL_CONTEXT[C])
5445 P.setcontext(ORIGINAL_CONTEXT[P])
5446 if not C:
5447 warnings.warn('C tests skipped: no module named _decimal.',
5448 UserWarning)
5449 if not orig_sys_decimal is sys.modules['decimal']:
5450 raise TestFailed("Internal error: unbalanced number of changes to "
5451 "sys.modules['decimal'].")
5452
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005453
5454if __name__ == '__main__':
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005455 import optparse
5456 p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]")
5457 p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test')
5458 p.add_option('--skip', '-s', action='store_true', help='skip over 90% of the arithmetic tests')
5459 (opt, args) = p.parse_args()
5460
5461 if opt.skip:
5462 test_main(arith=False, verbose=True)
5463 elif args:
5464 test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005465 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005466 test_main(arith=True, verbose=True)