blob: e8256a5c7f031f87b2d5b31560bb3817f258a44b [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
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000293 return
Antoine Pitrou92f60ed2010-10-14 22:11:44 +0000294 with open(file) as f:
295 for line in f:
296 line = line.replace('\r\n', '').replace('\n', '')
297 #print line
298 try:
299 t = self.eval_line(line)
Stefan Krah1919b7e2012-03-21 18:25:23 +0100300 except self.decimal.DecimalException as exception:
Ezio Melotti13925002011-03-16 11:05:33 +0200301 #Exception raised where there shouldn't have been one.
Antoine Pitrou92f60ed2010-10-14 22:11:44 +0000302 self.fail('Exception "'+exception.__class__.__name__ + '" raised on line '+line)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000303
304 return
305
306 def eval_line(self, s):
307 if s.find(' -> ') >= 0 and s[:2] != '--' and not s.startswith(' --'):
308 s = (s.split('->')[0] + '->' +
309 s.split('->')[1].split('--')[0]).strip()
310 else:
311 s = s.split('--')[0].strip()
312
313 for ignore in self.ignore_list:
314 if s.find(ignore) >= 0:
315 #print s.split()[0], 'NotImplemented--', ignore
316 return
317 if not s:
318 return
319 elif ':' in s:
320 return self.eval_directive(s)
321 else:
322 return self.eval_equation(s)
323
324 def eval_directive(self, s):
Guido van Rossumc1f779c2007-07-03 08:25:58 +0000325 funct, value = (x.strip().lower() for x in s.split(':'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000326 if funct == 'rounding':
Stefan Krah1919b7e2012-03-21 18:25:23 +0100327 value = self.RoundingDict[value]
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000328 else:
329 try:
330 value = int(value)
331 except ValueError:
332 pass
333
Stefan Krah1919b7e2012-03-21 18:25:23 +0100334 funct = self.ChangeDict.get(funct, (lambda *args: None))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000335 funct(value)
336
337 def eval_equation(self, s):
Raymond Hettingered20ad82004-09-04 20:09:13 +0000338
339 if not TEST_ALL and random.random() < 0.90:
340 return
341
Stefan Krah1919b7e2012-03-21 18:25:23 +0100342 self.context.clear_flags()
343
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000344 try:
345 Sides = s.split('->')
346 L = Sides[0].strip().split()
347 id = L[0]
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000348 if DEBUG:
349 print("Test ", id, end=" ")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000350 funct = L[1].lower()
351 valstemp = L[2:]
352 L = Sides[1].strip().split()
353 ans = L[0]
354 exceptions = L[1:]
355 except (TypeError, AttributeError, IndexError):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100356 raise self.decimal.InvalidOperation
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000357 def FixQuotes(val):
358 val = val.replace("''", 'SingleQuote').replace('""', 'DoubleQuote')
359 val = val.replace("'", '').replace('"', '')
360 val = val.replace('SingleQuote', "'").replace('DoubleQuote', '"')
361 return val
Mark Dickinson8a546532009-10-08 16:30:38 +0000362
Stefan Krah1919b7e2012-03-21 18:25:23 +0100363 if id in self.skipped_test_ids:
Mark Dickinson8a546532009-10-08 16:30:38 +0000364 return
365
Stefan Krah1919b7e2012-03-21 18:25:23 +0100366 fname = self.NameAdapter.get(funct, funct)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000367 if fname == 'rescale':
368 return
369 funct = getattr(self.context, fname)
370 vals = []
371 conglomerate = ''
372 quote = 0
Stefan Krah1919b7e2012-03-21 18:25:23 +0100373 theirexceptions = [self.ErrorNames[x.lower()] for x in exceptions]
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000374
Stefan Krah1919b7e2012-03-21 18:25:23 +0100375 for exception in Signals[self.decimal]:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000376 self.context.traps[exception] = 1 #Catch these bugs...
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000377 for exception in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000378 self.context.traps[exception] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000379 for i, val in enumerate(valstemp):
380 if val.count("'") % 2 == 1:
381 quote = 1 - quote
382 if quote:
383 conglomerate = conglomerate + ' ' + val
384 continue
385 else:
386 val = conglomerate + val
387 conglomerate = ''
388 v = FixQuotes(val)
389 if fname in ('to_sci_string', 'to_eng_string'):
390 if EXTENDEDERRORTEST:
391 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000392 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000393 try:
394 funct(self.context.create_decimal(v))
395 except error:
396 pass
Stefan Krah1919b7e2012-03-21 18:25:23 +0100397 except Signals[self.decimal] as e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000398 self.fail("Raised %s in %s when %s disabled" % \
399 (e, s, error))
400 else:
401 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000402 self.context.traps[error] = 0
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000403 v = self.context.create_decimal(v)
404 else:
Stefan Krah1919b7e2012-03-21 18:25:23 +0100405 v = self.read_unlimited(v, self.context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000406 vals.append(v)
407
408 ans = FixQuotes(ans)
409
410 if EXTENDEDERRORTEST and fname not in ('to_sci_string', 'to_eng_string'):
411 for error in theirexceptions:
Raymond Hettingerbf440692004-07-10 14:14:37 +0000412 self.context.traps[error] = 1
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000413 try:
414 funct(*vals)
415 except error:
416 pass
Stefan Krah1919b7e2012-03-21 18:25:23 +0100417 except Signals[self.decimal] as e:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000418 self.fail("Raised %s in %s when %s disabled" % \
419 (e, s, error))
420 else:
421 self.fail("Did not raise %s in %s" % (error, s))
Raymond Hettingerbf440692004-07-10 14:14:37 +0000422 self.context.traps[error] = 0
Mark Dickinsonc69160e2010-05-04 14:35:33 +0000423
424 # as above, but add traps cumulatively, to check precedence
Stefan Krah1919b7e2012-03-21 18:25:23 +0100425 ordered_errors = [e for e in OrderedSignals[self.decimal] if e in theirexceptions]
Mark Dickinsonc69160e2010-05-04 14:35:33 +0000426 for error in ordered_errors:
427 self.context.traps[error] = 1
428 try:
429 funct(*vals)
430 except error:
431 pass
Stefan Krah1919b7e2012-03-21 18:25:23 +0100432 except Signals[self.decimal] as e:
Mark Dickinsonc69160e2010-05-04 14:35:33 +0000433 self.fail("Raised %s in %s; expected %s" %
434 (type(e), s, error))
435 else:
436 self.fail("Did not raise %s in %s" % (error, s))
437 # reset traps
438 for error in ordered_errors:
439 self.context.traps[error] = 0
440
441
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000442 if DEBUG:
443 print("--", self.context)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000444 try:
445 result = str(funct(*vals))
Stefan Krah1919b7e2012-03-21 18:25:23 +0100446 if fname in self.LogicalFunctions:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000447 result = str(int(eval(result))) # 'True', 'False' -> '1', '0'
Stefan Krah1919b7e2012-03-21 18:25:23 +0100448 except Signals[self.decimal] as error:
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000449 self.fail("Raised %s in %s" % (error, s))
450 except: #Catch any error long enough to state the test case.
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000451 print("ERROR:", s)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000452 raise
453
454 myexceptions = self.getexceptions()
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000455
Guido van Rossum47b9ff62006-08-24 00:41:19 +0000456 myexceptions.sort(key=repr)
457 theirexceptions.sort(key=repr)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000458
459 self.assertEqual(result, ans,
460 'Incorrect answer for ' + s + ' -- got ' + result)
Stefan Krah1919b7e2012-03-21 18:25:23 +0100461
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000462 self.assertEqual(myexceptions, theirexceptions,
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000463 'Incorrect flags set in ' + s + ' -- got ' + str(myexceptions))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000464 return
465
466 def getexceptions(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100467 return [e for e in Signals[self.decimal] if self.context.flags[e]]
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000468
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000469 def change_precision(self, prec):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100470 if self.decimal == C and self.decimal.MAX_PREC == 425000000:
471 self.context._unsafe_setprec(prec)
472 else:
473 self.context.prec = prec
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000474 def change_rounding_method(self, rounding):
475 self.context.rounding = rounding
476 def change_min_exponent(self, exp):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100477 if self.decimal == C and self.decimal.MAX_PREC == 425000000:
478 self.context._unsafe_setemin(exp)
479 else:
480 self.context.Emin = exp
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000481 def change_max_exponent(self, exp):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100482 if self.decimal == C and self.decimal.MAX_PREC == 425000000:
483 self.context._unsafe_setemax(exp)
484 else:
485 self.context.Emax = exp
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000486 def change_clamp(self, clamp):
Mark Dickinsonb1d8e322010-05-22 18:35:36 +0000487 self.context.clamp = clamp
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000488
Stefan Krah1919b7e2012-03-21 18:25:23 +0100489class CIBMTestCases(IBMTestCases):
490 decimal = C
491class PyIBMTestCases(IBMTestCases):
492 decimal = P
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000493
494# The following classes test the behaviour of Decimal according to PEP 327
495
Stefan Krah1919b7e2012-03-21 18:25:23 +0100496class ExplicitConstructionTest(unittest.TestCase):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000497 '''Unit tests for Explicit Construction cases of Decimal.'''
498
499 def test_explicit_empty(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100500 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000501 self.assertEqual(Decimal(), Decimal("0"))
502
503 def test_explicit_from_None(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100504 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000505 self.assertRaises(TypeError, Decimal, None)
506
507 def test_explicit_from_int(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100508 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000509
510 #positive
511 d = Decimal(45)
512 self.assertEqual(str(d), '45')
513
514 #very large positive
515 d = Decimal(500000123)
516 self.assertEqual(str(d), '500000123')
517
518 #negative
519 d = Decimal(-45)
520 self.assertEqual(str(d), '-45')
521
522 #zero
523 d = Decimal(0)
524 self.assertEqual(str(d), '0')
525
Stefan Krah1919b7e2012-03-21 18:25:23 +0100526 # single word longs
527 for n in range(0, 32):
528 for sign in (-1, 1):
529 for x in range(-5, 5):
530 i = sign * (2**n + x)
531 d = Decimal(i)
532 self.assertEqual(str(d), str(i))
533
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000534 def test_explicit_from_string(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100535 Decimal = self.decimal.Decimal
536 InvalidOperation = self.decimal.InvalidOperation
537 localcontext = self.decimal.localcontext
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000538
539 #empty
540 self.assertEqual(str(Decimal('')), 'NaN')
541
542 #int
543 self.assertEqual(str(Decimal('45')), '45')
544
545 #float
546 self.assertEqual(str(Decimal('45.34')), '45.34')
547
548 #engineer notation
549 self.assertEqual(str(Decimal('45e2')), '4.5E+3')
550
551 #just not a number
552 self.assertEqual(str(Decimal('ugly')), 'NaN')
553
Christian Heimesa62da1d2008-01-12 19:39:10 +0000554 #leading and trailing whitespace permitted
555 self.assertEqual(str(Decimal('1.3E4 \n')), '1.3E+4')
556 self.assertEqual(str(Decimal(' -7.89')), '-7.89')
Stefan Krah1919b7e2012-03-21 18:25:23 +0100557 self.assertEqual(str(Decimal(" 3.45679 ")), '3.45679')
558
559 # unicode whitespace
560 for lead in ["", ' ', '\u00a0', '\u205f']:
561 for trail in ["", ' ', '\u00a0', '\u205f']:
562 self.assertEqual(str(Decimal(lead + '9.311E+28' + trail)),
563 '9.311E+28')
564
565 with localcontext() as c:
566 c.traps[InvalidOperation] = True
567 # Invalid string
568 self.assertRaises(InvalidOperation, Decimal, "xyz")
569 # Two arguments max
570 self.assertRaises(TypeError, Decimal, "1234", "x", "y")
571
572 # space within the numeric part
573 self.assertRaises(InvalidOperation, Decimal, "1\u00a02\u00a03")
574 self.assertRaises(InvalidOperation, Decimal, "\u00a01\u00a02\u00a0")
575
576 # unicode whitespace
577 self.assertRaises(InvalidOperation, Decimal, "\u00a0")
578 self.assertRaises(InvalidOperation, Decimal, "\u00a0\u00a0")
579
580 # embedded NUL
581 self.assertRaises(InvalidOperation, Decimal, "12\u00003")
582
Stefan Krah6e467042012-11-10 23:09:04 +0100583 @cpython_only
584 def test_from_legacy_strings(self):
585 import _testcapi
586 Decimal = self.decimal.Decimal
587 context = self.decimal.Context()
588
589 s = _testcapi.unicode_legacy_string('9.999999')
590 self.assertEqual(str(Decimal(s)), '9.999999')
591 self.assertEqual(str(context.create_decimal(s)), '9.999999')
Christian Heimesa62da1d2008-01-12 19:39:10 +0000592
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000593 def test_explicit_from_tuples(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100594 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000595
596 #zero
597 d = Decimal( (0, (0,), 0) )
598 self.assertEqual(str(d), '0')
599
600 #int
601 d = Decimal( (1, (4, 5), 0) )
602 self.assertEqual(str(d), '-45')
603
604 #float
605 d = Decimal( (0, (4, 5, 3, 4), -2) )
606 self.assertEqual(str(d), '45.34')
607
608 #weird
609 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
610 self.assertEqual(str(d), '-4.34913534E-17')
611
Stefan Krah1919b7e2012-03-21 18:25:23 +0100612 #inf
613 d = Decimal( (0, (), "F") )
614 self.assertEqual(str(d), 'Infinity')
615
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000616 #wrong number of items
617 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1)) )
618
619 #bad sign
620 self.assertRaises(ValueError, Decimal, (8, (4, 3, 4, 9, 1), 2) )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000621 self.assertRaises(ValueError, Decimal, (0., (4, 3, 4, 9, 1), 2) )
622 self.assertRaises(ValueError, Decimal, (Decimal(1), (4, 3, 4, 9, 1), 2))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000623
624 #bad exp
625 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 'wrong!') )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000626 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), 0.) )
627 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 9, 1), '1') )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000628
629 #bad coefficients
Stefan Krah1919b7e2012-03-21 18:25:23 +0100630 self.assertRaises(ValueError, Decimal, (1, "xyz", 2) )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000631 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, None, 1), 2) )
632 self.assertRaises(ValueError, Decimal, (1, (4, -3, 4, 9, 1), 2) )
Guido van Rossum8ce8a782007-11-01 19:42:39 +0000633 self.assertRaises(ValueError, Decimal, (1, (4, 10, 4, 9, 1), 2) )
Guido van Rossum0d3fb8a2007-11-26 23:23:18 +0000634 self.assertRaises(ValueError, Decimal, (1, (4, 3, 4, 'a', 1), 2) )
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000635
Stefan Krah1919b7e2012-03-21 18:25:23 +0100636 def test_explicit_from_list(self):
637 Decimal = self.decimal.Decimal
638
639 d = Decimal([0, [0], 0])
640 self.assertEqual(str(d), '0')
641
642 d = Decimal([1, [4, 3, 4, 9, 1, 3, 5, 3, 4], -25])
643 self.assertEqual(str(d), '-4.34913534E-17')
644
645 d = Decimal([1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25])
646 self.assertEqual(str(d), '-4.34913534E-17')
647
648 d = Decimal((1, [4, 3, 4, 9, 1, 3, 5, 3, 4], -25))
649 self.assertEqual(str(d), '-4.34913534E-17')
650
Antoine Pitrou503ab332010-03-30 18:56:19 +0000651 def test_explicit_from_bool(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100652 Decimal = self.decimal.Decimal
653
Antoine Pitrou503ab332010-03-30 18:56:19 +0000654 self.assertIs(bool(Decimal(0)), False)
655 self.assertIs(bool(Decimal(1)), True)
656 self.assertEqual(Decimal(False), Decimal(0))
657 self.assertEqual(Decimal(True), Decimal(1))
658
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000659 def test_explicit_from_Decimal(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100660 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000661
662 #positive
663 d = Decimal(45)
664 e = Decimal(d)
665 self.assertEqual(str(e), '45')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000666
667 #very large positive
668 d = Decimal(500000123)
669 e = Decimal(d)
670 self.assertEqual(str(e), '500000123')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000671
672 #negative
673 d = Decimal(-45)
674 e = Decimal(d)
675 self.assertEqual(str(e), '-45')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000676
677 #zero
678 d = Decimal(0)
679 e = Decimal(d)
680 self.assertEqual(str(e), '0')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000681
Raymond Hettinger96798592010-04-02 16:58:27 +0000682 @requires_IEEE_754
683 def test_explicit_from_float(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100684
685 Decimal = self.decimal.Decimal
686
Raymond Hettinger96798592010-04-02 16:58:27 +0000687 r = Decimal(0.1)
688 self.assertEqual(type(r), Decimal)
689 self.assertEqual(str(r),
690 '0.1000000000000000055511151231257827021181583404541015625')
691 self.assertTrue(Decimal(float('nan')).is_qnan())
692 self.assertTrue(Decimal(float('inf')).is_infinite())
693 self.assertTrue(Decimal(float('-inf')).is_infinite())
694 self.assertEqual(str(Decimal(float('nan'))),
695 str(Decimal('NaN')))
696 self.assertEqual(str(Decimal(float('inf'))),
697 str(Decimal('Infinity')))
698 self.assertEqual(str(Decimal(float('-inf'))),
699 str(Decimal('-Infinity')))
700 self.assertEqual(str(Decimal(float('-0.0'))),
701 str(Decimal('-0')))
702 for i in range(200):
703 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
704 self.assertEqual(x, float(Decimal(x))) # roundtrip
705
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000706 def test_explicit_context_create_decimal(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100707 Decimal = self.decimal.Decimal
708 InvalidOperation = self.decimal.InvalidOperation
709 Rounded = self.decimal.Rounded
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000710
Stefan Krah1919b7e2012-03-21 18:25:23 +0100711 nc = copy.copy(self.decimal.getcontext())
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000712 nc.prec = 3
713
714 # empty
Raymond Hettingerfed52962004-07-14 15:41:57 +0000715 d = Decimal()
716 self.assertEqual(str(d), '0')
717 d = nc.create_decimal()
718 self.assertEqual(str(d), '0')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000719
720 # from None
721 self.assertRaises(TypeError, nc.create_decimal, None)
722
723 # from int
724 d = nc.create_decimal(456)
Ezio Melottie9615932010-01-24 19:26:24 +0000725 self.assertIsInstance(d, Decimal)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000726 self.assertEqual(nc.create_decimal(45678),
727 nc.create_decimal('457E+2'))
728
729 # from string
730 d = Decimal('456789')
731 self.assertEqual(str(d), '456789')
732 d = nc.create_decimal('456789')
733 self.assertEqual(str(d), '4.57E+5')
Christian Heimesa62da1d2008-01-12 19:39:10 +0000734 # leading and trailing whitespace should result in a NaN;
735 # spaces are already checked in Cowlishaw's test-suite, so
736 # here we just check that a trailing newline results in a NaN
737 self.assertEqual(str(nc.create_decimal('3.14\n')), 'NaN')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000738
739 # from tuples
740 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
741 self.assertEqual(str(d), '-4.34913534E-17')
742 d = nc.create_decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
743 self.assertEqual(str(d), '-4.35E-17')
744
745 # from Decimal
746 prevdec = Decimal(500000123)
747 d = Decimal(prevdec)
748 self.assertEqual(str(d), '500000123')
749 d = nc.create_decimal(prevdec)
750 self.assertEqual(str(d), '5.00E+8')
751
Stefan Krah1919b7e2012-03-21 18:25:23 +0100752 # more integers
753 nc.prec = 28
754 nc.traps[InvalidOperation] = True
755
756 for v in [-2**63-1, -2**63, -2**31-1, -2**31, 0,
757 2**31-1, 2**31, 2**63-1, 2**63]:
758 d = nc.create_decimal(v)
759 self.assertTrue(isinstance(d, Decimal))
760 self.assertEqual(int(d), v)
761
762 nc.prec = 3
763 nc.traps[Rounded] = True
764 self.assertRaises(Rounded, nc.create_decimal, 1234)
765
766 # from string
767 nc.prec = 28
768 self.assertEqual(str(nc.create_decimal('0E-017')), '0E-17')
769 self.assertEqual(str(nc.create_decimal('45')), '45')
770 self.assertEqual(str(nc.create_decimal('-Inf')), '-Infinity')
771 self.assertEqual(str(nc.create_decimal('NaN123')), 'NaN123')
772
773 # invalid arguments
774 self.assertRaises(InvalidOperation, nc.create_decimal, "xyz")
775 self.assertRaises(ValueError, nc.create_decimal, (1, "xyz", -25))
776 self.assertRaises(TypeError, nc.create_decimal, "1234", "5678")
777
778 # too many NaN payload digits
779 nc.prec = 3
780 self.assertRaises(InvalidOperation, nc.create_decimal, 'NaN12345')
781 self.assertRaises(InvalidOperation, nc.create_decimal,
782 Decimal('NaN12345'))
783
784 nc.traps[InvalidOperation] = False
785 self.assertEqual(str(nc.create_decimal('NaN12345')), 'NaN')
786 self.assertTrue(nc.flags[InvalidOperation])
787
788 nc.flags[InvalidOperation] = False
789 self.assertEqual(str(nc.create_decimal(Decimal('NaN12345'))), 'NaN')
790 self.assertTrue(nc.flags[InvalidOperation])
791
792 def test_explicit_context_create_from_float(self):
793
794 Decimal = self.decimal.Decimal
795
796 nc = self.decimal.Context()
797 r = nc.create_decimal(0.1)
798 self.assertEqual(type(r), Decimal)
799 self.assertEqual(str(r), '0.1000000000000000055511151231')
800 self.assertTrue(nc.create_decimal(float('nan')).is_qnan())
801 self.assertTrue(nc.create_decimal(float('inf')).is_infinite())
802 self.assertTrue(nc.create_decimal(float('-inf')).is_infinite())
803 self.assertEqual(str(nc.create_decimal(float('nan'))),
804 str(nc.create_decimal('NaN')))
805 self.assertEqual(str(nc.create_decimal(float('inf'))),
806 str(nc.create_decimal('Infinity')))
807 self.assertEqual(str(nc.create_decimal(float('-inf'))),
808 str(nc.create_decimal('-Infinity')))
809 self.assertEqual(str(nc.create_decimal(float('-0.0'))),
810 str(nc.create_decimal('-0')))
811 nc.prec = 100
812 for i in range(200):
813 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
814 self.assertEqual(x, float(nc.create_decimal(x))) # roundtrip
815
Mark Dickinson345adc42009-08-02 10:14:23 +0000816 def test_unicode_digits(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100817 Decimal = self.decimal.Decimal
818
Mark Dickinson345adc42009-08-02 10:14:23 +0000819 test_values = {
820 '\uff11': '1',
821 '\u0660.\u0660\u0663\u0667\u0662e-\u0663' : '0.0000372',
822 '-nan\u0c68\u0c6a\u0c66\u0c66' : '-NaN2400',
823 }
824 for input, expected in test_values.items():
825 self.assertEqual(str(Decimal(input)), expected)
826
Stefan Krah1919b7e2012-03-21 18:25:23 +0100827class CExplicitConstructionTest(ExplicitConstructionTest):
828 decimal = C
829class PyExplicitConstructionTest(ExplicitConstructionTest):
830 decimal = P
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000831
Stefan Krah1919b7e2012-03-21 18:25:23 +0100832class ImplicitConstructionTest(unittest.TestCase):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000833 '''Unit tests for Implicit Construction cases of Decimal.'''
834
835 def test_implicit_from_None(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100836 Decimal = self.decimal.Decimal
837 self.assertRaises(TypeError, eval, 'Decimal(5) + None', locals())
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000838
839 def test_implicit_from_int(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100840 Decimal = self.decimal.Decimal
841
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000842 #normal
843 self.assertEqual(str(Decimal(5) + 45), '50')
844 #exceeding precision
845 self.assertEqual(Decimal(5) + 123456789000, Decimal(123456789000))
846
847 def test_implicit_from_string(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100848 Decimal = self.decimal.Decimal
849 self.assertRaises(TypeError, eval, 'Decimal(5) + "3"', locals())
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000850
851 def test_implicit_from_float(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100852 Decimal = self.decimal.Decimal
853 self.assertRaises(TypeError, eval, 'Decimal(5) + 2.2', locals())
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000854
855 def test_implicit_from_Decimal(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100856 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000857 self.assertEqual(Decimal(5) + Decimal(45), Decimal(50))
858
Raymond Hettinger267b8682005-03-27 10:47:39 +0000859 def test_rop(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100860 Decimal = self.decimal.Decimal
861
Raymond Hettinger267b8682005-03-27 10:47:39 +0000862 # Allow other classes to be trained to interact with Decimals
863 class E:
864 def __divmod__(self, other):
865 return 'divmod ' + str(other)
866 def __rdivmod__(self, other):
867 return str(other) + ' rdivmod'
868 def __lt__(self, other):
869 return 'lt ' + str(other)
870 def __gt__(self, other):
871 return 'gt ' + str(other)
872 def __le__(self, other):
873 return 'le ' + str(other)
874 def __ge__(self, other):
875 return 'ge ' + str(other)
876 def __eq__(self, other):
877 return 'eq ' + str(other)
878 def __ne__(self, other):
879 return 'ne ' + str(other)
880
881 self.assertEqual(divmod(E(), Decimal(10)), 'divmod 10')
882 self.assertEqual(divmod(Decimal(10), E()), '10 rdivmod')
883 self.assertEqual(eval('Decimal(10) < E()'), 'gt 10')
884 self.assertEqual(eval('Decimal(10) > E()'), 'lt 10')
885 self.assertEqual(eval('Decimal(10) <= E()'), 'ge 10')
886 self.assertEqual(eval('Decimal(10) >= E()'), 'le 10')
887 self.assertEqual(eval('Decimal(10) == E()'), 'eq 10')
888 self.assertEqual(eval('Decimal(10) != E()'), 'ne 10')
889
890 # insert operator methods and then exercise them
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000891 oplist = [
892 ('+', '__add__', '__radd__'),
893 ('-', '__sub__', '__rsub__'),
894 ('*', '__mul__', '__rmul__'),
Thomas Woutersdcc6d322006-04-21 11:30:52 +0000895 ('/', '__truediv__', '__rtruediv__'),
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000896 ('%', '__mod__', '__rmod__'),
897 ('//', '__floordiv__', '__rfloordiv__'),
898 ('**', '__pow__', '__rpow__')
899 ]
Raymond Hettinger267b8682005-03-27 10:47:39 +0000900
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000901 for sym, lop, rop in oplist:
Raymond Hettinger267b8682005-03-27 10:47:39 +0000902 setattr(E, lop, lambda self, other: 'str' + lop + str(other))
903 setattr(E, rop, lambda self, other: str(other) + rop + 'str')
904 self.assertEqual(eval('E()' + sym + 'Decimal(10)'),
905 'str' + lop + '10')
906 self.assertEqual(eval('Decimal(10)' + sym + 'E()'),
907 '10' + rop + 'str')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +0000908
Stefan Krah1919b7e2012-03-21 18:25:23 +0100909class CImplicitConstructionTest(ImplicitConstructionTest):
910 decimal = C
911class PyImplicitConstructionTest(ImplicitConstructionTest):
912 decimal = P
Mark Dickinson79f52032009-03-17 23:12:51 +0000913
Stefan Krah1919b7e2012-03-21 18:25:23 +0100914class FormatTest(unittest.TestCase):
Christian Heimesf16baeb2008-02-29 14:57:44 +0000915 '''Unit tests for the format function.'''
916 def test_formatting(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +0100917 Decimal = self.decimal.Decimal
918
Christian Heimesf16baeb2008-02-29 14:57:44 +0000919 # triples giving a format, a Decimal, and the expected result
920 test_values = [
921 ('e', '0E-15', '0e-15'),
922 ('e', '2.3E-15', '2.3e-15'),
923 ('e', '2.30E+2', '2.30e+2'), # preserve significant zeros
924 ('e', '2.30000E-15', '2.30000e-15'),
925 ('e', '1.23456789123456789e40', '1.23456789123456789e+40'),
926 ('e', '1.5', '1.5e+0'),
927 ('e', '0.15', '1.5e-1'),
928 ('e', '0.015', '1.5e-2'),
929 ('e', '0.0000000000015', '1.5e-12'),
930 ('e', '15.0', '1.50e+1'),
931 ('e', '-15', '-1.5e+1'),
932 ('e', '0', '0e+0'),
933 ('e', '0E1', '0e+1'),
934 ('e', '0.0', '0e-1'),
935 ('e', '0.00', '0e-2'),
936 ('.6e', '0E-15', '0.000000e-9'),
937 ('.6e', '0', '0.000000e+6'),
938 ('.6e', '9.999999', '9.999999e+0'),
939 ('.6e', '9.9999999', '1.000000e+1'),
940 ('.6e', '-1.23e5', '-1.230000e+5'),
941 ('.6e', '1.23456789e-3', '1.234568e-3'),
942 ('f', '0', '0'),
943 ('f', '0.0', '0.0'),
944 ('f', '0E-2', '0.00'),
945 ('f', '0.00E-8', '0.0000000000'),
946 ('f', '0E1', '0'), # loses exponent information
947 ('f', '3.2E1', '32'),
948 ('f', '3.2E2', '320'),
949 ('f', '3.20E2', '320'),
950 ('f', '3.200E2', '320.0'),
951 ('f', '3.2E-6', '0.0000032'),
952 ('.6f', '0E-15', '0.000000'), # all zeros treated equally
953 ('.6f', '0E1', '0.000000'),
954 ('.6f', '0', '0.000000'),
955 ('.0f', '0', '0'), # no decimal point
956 ('.0f', '0e-2', '0'),
957 ('.0f', '3.14159265', '3'),
958 ('.1f', '3.14159265', '3.1'),
959 ('.4f', '3.14159265', '3.1416'),
960 ('.6f', '3.14159265', '3.141593'),
961 ('.7f', '3.14159265', '3.1415926'), # round-half-even!
962 ('.8f', '3.14159265', '3.14159265'),
963 ('.9f', '3.14159265', '3.141592650'),
964
965 ('g', '0', '0'),
966 ('g', '0.0', '0.0'),
967 ('g', '0E1', '0e+1'),
968 ('G', '0E1', '0E+1'),
969 ('g', '0E-5', '0.00000'),
970 ('g', '0E-6', '0.000000'),
971 ('g', '0E-7', '0e-7'),
972 ('g', '-0E2', '-0e+2'),
973 ('.0g', '3.14159265', '3'), # 0 sig fig -> 1 sig fig
Stefan Krah1919b7e2012-03-21 18:25:23 +0100974 ('.0n', '3.14159265', '3'), # same for 'n'
Christian Heimesf16baeb2008-02-29 14:57:44 +0000975 ('.1g', '3.14159265', '3'),
976 ('.2g', '3.14159265', '3.1'),
977 ('.5g', '3.14159265', '3.1416'),
978 ('.7g', '3.14159265', '3.141593'),
979 ('.8g', '3.14159265', '3.1415926'), # round-half-even!
980 ('.9g', '3.14159265', '3.14159265'),
981 ('.10g', '3.14159265', '3.14159265'), # don't pad
982
983 ('%', '0E1', '0%'),
984 ('%', '0E0', '0%'),
985 ('%', '0E-1', '0%'),
986 ('%', '0E-2', '0%'),
987 ('%', '0E-3', '0.0%'),
988 ('%', '0E-4', '0.00%'),
989
990 ('.3%', '0', '0.000%'), # all zeros treated equally
991 ('.3%', '0E10', '0.000%'),
992 ('.3%', '0E-10', '0.000%'),
993 ('.3%', '2.34', '234.000%'),
994 ('.3%', '1.234567', '123.457%'),
995 ('.0%', '1.23', '123%'),
996
997 ('e', 'NaN', 'NaN'),
998 ('f', '-NaN123', '-NaN123'),
999 ('+g', 'NaN456', '+NaN456'),
1000 ('.3e', 'Inf', 'Infinity'),
1001 ('.16f', '-Inf', '-Infinity'),
1002 ('.0g', '-sNaN', '-sNaN'),
1003
1004 ('', '1.00', '1.00'),
Mark Dickinsonad416342009-03-17 18:10:15 +00001005
Mark Dickinson79f52032009-03-17 23:12:51 +00001006 # test alignment and padding
Mark Dickinson46ab5d02009-09-08 20:22:46 +00001007 ('6', '123', ' 123'),
Mark Dickinsonad416342009-03-17 18:10:15 +00001008 ('<6', '123', '123 '),
1009 ('>6', '123', ' 123'),
1010 ('^6', '123', ' 123 '),
1011 ('=+6', '123', '+ 123'),
Mark Dickinson79f52032009-03-17 23:12:51 +00001012 ('#<10', 'NaN', 'NaN#######'),
1013 ('#<10', '-4.3', '-4.3######'),
1014 ('#<+10', '0.0130', '+0.0130###'),
1015 ('#< 10', '0.0130', ' 0.0130###'),
1016 ('@>10', '-Inf', '@-Infinity'),
1017 ('#>5', '-Inf', '-Infinity'),
1018 ('?^5', '123', '?123?'),
1019 ('%^6', '123', '%123%%'),
1020 (' ^6', '-45.6', '-45.6 '),
1021 ('/=10', '-45.6', '-/////45.6'),
1022 ('/=+10', '45.6', '+/////45.6'),
1023 ('/= 10', '45.6', ' /////45.6'),
1024
1025 # thousands separator
1026 (',', '1234567', '1,234,567'),
1027 (',', '123456', '123,456'),
1028 (',', '12345', '12,345'),
1029 (',', '1234', '1,234'),
1030 (',', '123', '123'),
1031 (',', '12', '12'),
1032 (',', '1', '1'),
1033 (',', '0', '0'),
1034 (',', '-1234567', '-1,234,567'),
1035 (',', '-123456', '-123,456'),
1036 ('7,', '123456', '123,456'),
Mark Dickinson46ab5d02009-09-08 20:22:46 +00001037 ('8,', '123456', ' 123,456'),
Mark Dickinson79f52032009-03-17 23:12:51 +00001038 ('08,', '123456', '0,123,456'), # special case: extra 0 needed
1039 ('+08,', '123456', '+123,456'), # but not if there's a sign
1040 (' 08,', '123456', ' 123,456'),
1041 ('08,', '-123456', '-123,456'),
1042 ('+09,', '123456', '+0,123,456'),
1043 # ... with fractional part...
1044 ('07,', '1234.56', '1,234.56'),
1045 ('08,', '1234.56', '1,234.56'),
1046 ('09,', '1234.56', '01,234.56'),
1047 ('010,', '1234.56', '001,234.56'),
1048 ('011,', '1234.56', '0,001,234.56'),
1049 ('012,', '1234.56', '0,001,234.56'),
1050 ('08,.1f', '1234.5', '01,234.5'),
1051 # no thousands separators in fraction part
1052 (',', '1.23456789', '1.23456789'),
1053 (',%', '123.456789', '12,345.6789%'),
1054 (',e', '123456', '1.23456e+5'),
1055 (',E', '123456', '1.23456E+5'),
Mark Dickinson7718d2b2009-09-07 16:21:56 +00001056
1057 # issue 6850
1058 ('a=-7.0', '0.12345', 'aaaa0.1'),
Christian Heimesf16baeb2008-02-29 14:57:44 +00001059 ]
1060 for fmt, d, result in test_values:
1061 self.assertEqual(format(Decimal(d), fmt), result)
1062
Stefan Krah1919b7e2012-03-21 18:25:23 +01001063 # bytes format argument
1064 self.assertRaises(TypeError, Decimal(1).__format__, b'-020')
1065
Mark Dickinson79f52032009-03-17 23:12:51 +00001066 def test_n_format(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001067 Decimal = self.decimal.Decimal
1068
Mark Dickinson79f52032009-03-17 23:12:51 +00001069 try:
1070 from locale import CHAR_MAX
1071 except ImportError:
1072 return
1073
Stefan Krah1919b7e2012-03-21 18:25:23 +01001074 def make_grouping(lst):
1075 return ''.join([chr(x) for x in lst]) if self.decimal == C else lst
1076
1077 def get_fmt(x, override=None, fmt='n'):
1078 if self.decimal == C:
1079 return Decimal(x).__format__(fmt, override)
1080 else:
1081 return Decimal(x).__format__(fmt, _localeconv=override)
1082
Mark Dickinson79f52032009-03-17 23:12:51 +00001083 # Set up some localeconv-like dictionaries
1084 en_US = {
1085 'decimal_point' : '.',
Stefan Krah1919b7e2012-03-21 18:25:23 +01001086 'grouping' : make_grouping([3, 3, 0]),
1087 'thousands_sep' : ','
Mark Dickinson79f52032009-03-17 23:12:51 +00001088 }
1089
1090 fr_FR = {
1091 'decimal_point' : ',',
Stefan Krah1919b7e2012-03-21 18:25:23 +01001092 'grouping' : make_grouping([CHAR_MAX]),
Mark Dickinson79f52032009-03-17 23:12:51 +00001093 'thousands_sep' : ''
1094 }
1095
1096 ru_RU = {
1097 'decimal_point' : ',',
Stefan Krah1919b7e2012-03-21 18:25:23 +01001098 'grouping': make_grouping([3, 3, 0]),
Mark Dickinson79f52032009-03-17 23:12:51 +00001099 'thousands_sep' : ' '
1100 }
1101
1102 crazy = {
1103 'decimal_point' : '&',
Stefan Krah1919b7e2012-03-21 18:25:23 +01001104 'grouping': make_grouping([1, 4, 2, CHAR_MAX]),
Mark Dickinson79f52032009-03-17 23:12:51 +00001105 'thousands_sep' : '-'
1106 }
1107
Stefan Krah1919b7e2012-03-21 18:25:23 +01001108 dotsep_wide = {
1109 'decimal_point' : b'\xc2\xbf'.decode('utf-8'),
1110 'grouping': make_grouping([3, 3, 0]),
1111 'thousands_sep' : b'\xc2\xb4'.decode('utf-8')
1112 }
Mark Dickinson79f52032009-03-17 23:12:51 +00001113
1114 self.assertEqual(get_fmt(Decimal('12.7'), en_US), '12.7')
1115 self.assertEqual(get_fmt(Decimal('12.7'), fr_FR), '12,7')
1116 self.assertEqual(get_fmt(Decimal('12.7'), ru_RU), '12,7')
1117 self.assertEqual(get_fmt(Decimal('12.7'), crazy), '1-2&7')
1118
1119 self.assertEqual(get_fmt(123456789, en_US), '123,456,789')
1120 self.assertEqual(get_fmt(123456789, fr_FR), '123456789')
1121 self.assertEqual(get_fmt(123456789, ru_RU), '123 456 789')
1122 self.assertEqual(get_fmt(1234567890123, crazy), '123456-78-9012-3')
1123
1124 self.assertEqual(get_fmt(123456789, en_US, '.6n'), '1.23457e+8')
1125 self.assertEqual(get_fmt(123456789, fr_FR, '.6n'), '1,23457e+8')
1126 self.assertEqual(get_fmt(123456789, ru_RU, '.6n'), '1,23457e+8')
1127 self.assertEqual(get_fmt(123456789, crazy, '.6n'), '1&23457e+8')
1128
Mark Dickinson7303b592009-03-18 08:25:36 +00001129 # zero padding
1130 self.assertEqual(get_fmt(1234, fr_FR, '03n'), '1234')
1131 self.assertEqual(get_fmt(1234, fr_FR, '04n'), '1234')
1132 self.assertEqual(get_fmt(1234, fr_FR, '05n'), '01234')
1133 self.assertEqual(get_fmt(1234, fr_FR, '06n'), '001234')
1134
1135 self.assertEqual(get_fmt(12345, en_US, '05n'), '12,345')
1136 self.assertEqual(get_fmt(12345, en_US, '06n'), '12,345')
1137 self.assertEqual(get_fmt(12345, en_US, '07n'), '012,345')
1138 self.assertEqual(get_fmt(12345, en_US, '08n'), '0,012,345')
1139 self.assertEqual(get_fmt(12345, en_US, '09n'), '0,012,345')
1140 self.assertEqual(get_fmt(12345, en_US, '010n'), '00,012,345')
1141
1142 self.assertEqual(get_fmt(123456, crazy, '06n'), '1-2345-6')
1143 self.assertEqual(get_fmt(123456, crazy, '07n'), '1-2345-6')
1144 self.assertEqual(get_fmt(123456, crazy, '08n'), '1-2345-6')
1145 self.assertEqual(get_fmt(123456, crazy, '09n'), '01-2345-6')
1146 self.assertEqual(get_fmt(123456, crazy, '010n'), '0-01-2345-6')
1147 self.assertEqual(get_fmt(123456, crazy, '011n'), '0-01-2345-6')
1148 self.assertEqual(get_fmt(123456, crazy, '012n'), '00-01-2345-6')
1149 self.assertEqual(get_fmt(123456, crazy, '013n'), '000-01-2345-6')
1150
Stefan Krah1919b7e2012-03-21 18:25:23 +01001151 # wide char separator and decimal point
1152 self.assertEqual(get_fmt(Decimal('-1.5'), dotsep_wide, '020n'),
1153 '-0\u00b4000\u00b4000\u00b4000\u00b4001\u00bf5')
Mark Dickinson79f52032009-03-17 23:12:51 +00001154
Stefan Krah6fb204a2012-09-28 16:18:54 +02001155 @run_with_locale('LC_ALL', 'ps_AF')
Stefan Krah1919b7e2012-03-21 18:25:23 +01001156 def test_wide_char_separator_decimal_point(self):
1157 # locale with wide char separator and decimal point
Stefan Krah8a491a82012-09-28 17:17:11 +02001158 import locale
Stefan Krah1919b7e2012-03-21 18:25:23 +01001159 Decimal = self.decimal.Decimal
1160
Stefan Krah8a491a82012-09-28 17:17:11 +02001161 decimal_point = locale.localeconv()['decimal_point']
1162 thousands_sep = locale.localeconv()['thousands_sep']
1163 if decimal_point != '\u066b' or thousands_sep != '\u066c':
1164 return
1165
Stefan Krah1919b7e2012-03-21 18:25:23 +01001166 self.assertEqual(format(Decimal('100000000.123'), 'n'),
1167 '100\u066c000\u066c000\u066b123')
Stefan Krah1919b7e2012-03-21 18:25:23 +01001168
1169class CFormatTest(FormatTest):
1170 decimal = C
1171class PyFormatTest(FormatTest):
1172 decimal = P
1173
1174class ArithmeticOperatorsTest(unittest.TestCase):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001175 '''Unit tests for all arithmetic operators, binary and unary.'''
1176
1177 def test_addition(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001178 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001179
1180 d1 = Decimal('-11.1')
1181 d2 = Decimal('22.2')
1182
1183 #two Decimals
1184 self.assertEqual(d1+d2, Decimal('11.1'))
1185 self.assertEqual(d2+d1, Decimal('11.1'))
1186
1187 #with other type, left
1188 c = d1 + 5
1189 self.assertEqual(c, Decimal('-6.1'))
1190 self.assertEqual(type(c), type(d1))
1191
1192 #with other type, right
1193 c = 5 + d1
1194 self.assertEqual(c, Decimal('-6.1'))
1195 self.assertEqual(type(c), type(d1))
1196
1197 #inline with decimal
1198 d1 += d2
1199 self.assertEqual(d1, Decimal('11.1'))
1200
1201 #inline with other type
1202 d1 += 5
1203 self.assertEqual(d1, Decimal('16.1'))
1204
1205 def test_subtraction(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001206 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001207
1208 d1 = Decimal('-11.1')
1209 d2 = Decimal('22.2')
1210
1211 #two Decimals
1212 self.assertEqual(d1-d2, Decimal('-33.3'))
1213 self.assertEqual(d2-d1, Decimal('33.3'))
1214
1215 #with other type, left
1216 c = d1 - 5
1217 self.assertEqual(c, Decimal('-16.1'))
1218 self.assertEqual(type(c), type(d1))
1219
1220 #with other type, right
1221 c = 5 - d1
1222 self.assertEqual(c, Decimal('16.1'))
1223 self.assertEqual(type(c), type(d1))
1224
1225 #inline with decimal
1226 d1 -= d2
1227 self.assertEqual(d1, Decimal('-33.3'))
1228
1229 #inline with other type
1230 d1 -= 5
1231 self.assertEqual(d1, Decimal('-38.3'))
1232
1233 def test_multiplication(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001234 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001235
1236 d1 = Decimal('-5')
1237 d2 = Decimal('3')
1238
1239 #two Decimals
1240 self.assertEqual(d1*d2, Decimal('-15'))
1241 self.assertEqual(d2*d1, Decimal('-15'))
1242
1243 #with other type, left
1244 c = d1 * 5
1245 self.assertEqual(c, Decimal('-25'))
1246 self.assertEqual(type(c), type(d1))
1247
1248 #with other type, right
1249 c = 5 * d1
1250 self.assertEqual(c, Decimal('-25'))
1251 self.assertEqual(type(c), type(d1))
1252
1253 #inline with decimal
1254 d1 *= d2
1255 self.assertEqual(d1, Decimal('-15'))
1256
1257 #inline with other type
1258 d1 *= 5
1259 self.assertEqual(d1, Decimal('-75'))
1260
1261 def test_division(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001262 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001263
1264 d1 = Decimal('-5')
1265 d2 = Decimal('2')
1266
1267 #two Decimals
1268 self.assertEqual(d1/d2, Decimal('-2.5'))
1269 self.assertEqual(d2/d1, Decimal('-0.4'))
1270
1271 #with other type, left
1272 c = d1 / 4
1273 self.assertEqual(c, Decimal('-1.25'))
1274 self.assertEqual(type(c), type(d1))
1275
1276 #with other type, right
1277 c = 4 / d1
1278 self.assertEqual(c, Decimal('-0.8'))
1279 self.assertEqual(type(c), type(d1))
1280
1281 #inline with decimal
1282 d1 /= d2
1283 self.assertEqual(d1, Decimal('-2.5'))
1284
1285 #inline with other type
1286 d1 /= 4
1287 self.assertEqual(d1, Decimal('-0.625'))
1288
1289 def test_floor_division(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001290 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001291
1292 d1 = Decimal('5')
1293 d2 = Decimal('2')
1294
1295 #two Decimals
1296 self.assertEqual(d1//d2, Decimal('2'))
1297 self.assertEqual(d2//d1, Decimal('0'))
1298
1299 #with other type, left
1300 c = d1 // 4
1301 self.assertEqual(c, Decimal('1'))
1302 self.assertEqual(type(c), type(d1))
1303
1304 #with other type, right
1305 c = 7 // d1
1306 self.assertEqual(c, Decimal('1'))
1307 self.assertEqual(type(c), type(d1))
1308
1309 #inline with decimal
1310 d1 //= d2
1311 self.assertEqual(d1, Decimal('2'))
1312
1313 #inline with other type
1314 d1 //= 2
1315 self.assertEqual(d1, Decimal('1'))
1316
1317 def test_powering(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001318 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001319
1320 d1 = Decimal('5')
1321 d2 = Decimal('2')
1322
1323 #two Decimals
1324 self.assertEqual(d1**d2, Decimal('25'))
1325 self.assertEqual(d2**d1, Decimal('32'))
1326
1327 #with other type, left
1328 c = d1 ** 4
1329 self.assertEqual(c, Decimal('625'))
1330 self.assertEqual(type(c), type(d1))
1331
1332 #with other type, right
1333 c = 7 ** d1
1334 self.assertEqual(c, Decimal('16807'))
1335 self.assertEqual(type(c), type(d1))
1336
1337 #inline with decimal
1338 d1 **= d2
1339 self.assertEqual(d1, Decimal('25'))
1340
1341 #inline with other type
1342 d1 **= 4
1343 self.assertEqual(d1, Decimal('390625'))
1344
1345 def test_module(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001346 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001347
1348 d1 = Decimal('5')
1349 d2 = Decimal('2')
1350
1351 #two Decimals
1352 self.assertEqual(d1%d2, Decimal('1'))
1353 self.assertEqual(d2%d1, Decimal('2'))
1354
1355 #with other type, left
1356 c = d1 % 4
1357 self.assertEqual(c, Decimal('1'))
1358 self.assertEqual(type(c), type(d1))
1359
1360 #with other type, right
1361 c = 7 % d1
1362 self.assertEqual(c, Decimal('2'))
1363 self.assertEqual(type(c), type(d1))
1364
1365 #inline with decimal
1366 d1 %= d2
1367 self.assertEqual(d1, Decimal('1'))
1368
1369 #inline with other type
1370 d1 %= 4
1371 self.assertEqual(d1, Decimal('1'))
1372
1373 def test_floor_div_module(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001374 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001375
1376 d1 = Decimal('5')
1377 d2 = Decimal('2')
1378
1379 #two Decimals
1380 (p, q) = divmod(d1, d2)
1381 self.assertEqual(p, Decimal('2'))
1382 self.assertEqual(q, Decimal('1'))
1383 self.assertEqual(type(p), type(d1))
1384 self.assertEqual(type(q), type(d1))
1385
1386 #with other type, left
1387 (p, q) = divmod(d1, 4)
1388 self.assertEqual(p, Decimal('1'))
1389 self.assertEqual(q, Decimal('1'))
1390 self.assertEqual(type(p), type(d1))
1391 self.assertEqual(type(q), type(d1))
1392
1393 #with other type, right
1394 (p, q) = divmod(7, d1)
1395 self.assertEqual(p, Decimal('1'))
1396 self.assertEqual(q, Decimal('2'))
1397 self.assertEqual(type(p), type(d1))
1398 self.assertEqual(type(q), type(d1))
1399
1400 def test_unary_operators(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001401 Decimal = self.decimal.Decimal
1402
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001403 self.assertEqual(+Decimal(45), Decimal(+45)) # +
1404 self.assertEqual(-Decimal(45), Decimal(-45)) # -
1405 self.assertEqual(abs(Decimal(45)), abs(Decimal(-45))) # abs
1406
Christian Heimes77c02eb2008-02-09 02:18:51 +00001407 def test_nan_comparisons(self):
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001408 # comparisons involving signaling nans signal InvalidOperation
1409
1410 # order comparisons (<, <=, >, >=) involving only quiet nans
1411 # also signal InvalidOperation
1412
1413 # equality comparisons (==, !=) involving only quiet nans
1414 # don't signal, but return False or True respectively.
Stefan Krah1919b7e2012-03-21 18:25:23 +01001415 Decimal = self.decimal.Decimal
1416 InvalidOperation = self.decimal.InvalidOperation
1417 localcontext = self.decimal.localcontext
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001418
Christian Heimes77c02eb2008-02-09 02:18:51 +00001419 n = Decimal('NaN')
1420 s = Decimal('sNaN')
1421 i = Decimal('Inf')
1422 f = Decimal('2')
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001423
1424 qnan_pairs = (n, n), (n, i), (i, n), (n, f), (f, n)
1425 snan_pairs = (s, n), (n, s), (s, i), (i, s), (s, f), (f, s), (s, s)
1426 order_ops = operator.lt, operator.le, operator.gt, operator.ge
1427 equality_ops = operator.eq, operator.ne
1428
1429 # results when InvalidOperation is not trapped
1430 for x, y in qnan_pairs + snan_pairs:
1431 for op in order_ops + equality_ops:
1432 got = op(x, y)
1433 expected = True if op is operator.ne else False
1434 self.assertIs(expected, got,
1435 "expected {0!r} for operator.{1}({2!r}, {3!r}); "
1436 "got {4!r}".format(
1437 expected, op.__name__, x, y, got))
1438
1439 # repeat the above, but this time trap the InvalidOperation
1440 with localcontext() as ctx:
1441 ctx.traps[InvalidOperation] = 1
1442
1443 for x, y in qnan_pairs:
1444 for op in equality_ops:
1445 got = op(x, y)
1446 expected = True if op is operator.ne else False
1447 self.assertIs(expected, got,
1448 "expected {0!r} for "
1449 "operator.{1}({2!r}, {3!r}); "
1450 "got {4!r}".format(
1451 expected, op.__name__, x, y, got))
1452
1453 for x, y in snan_pairs:
1454 for op in equality_ops:
1455 self.assertRaises(InvalidOperation, operator.eq, x, y)
1456 self.assertRaises(InvalidOperation, operator.ne, x, y)
1457
1458 for x, y in qnan_pairs + snan_pairs:
1459 for op in order_ops:
1460 self.assertRaises(InvalidOperation, op, x, y)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001461
Mark Dickinson84230a12010-02-18 14:49:50 +00001462 def test_copy_sign(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001463 Decimal = self.decimal.Decimal
Mark Dickinson84230a12010-02-18 14:49:50 +00001464
Stefan Krah1919b7e2012-03-21 18:25:23 +01001465 d = Decimal(1).copy_sign(Decimal(-2))
Mark Dickinson84230a12010-02-18 14:49:50 +00001466 self.assertEqual(Decimal(1).copy_sign(-2), d)
1467 self.assertRaises(TypeError, Decimal(1).copy_sign, '-2')
1468
Stefan Krah1919b7e2012-03-21 18:25:23 +01001469class CArithmeticOperatorsTest(ArithmeticOperatorsTest):
1470 decimal = C
1471class PyArithmeticOperatorsTest(ArithmeticOperatorsTest):
1472 decimal = P
1473
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001474# The following are two functions used to test threading in the next class
1475
1476def thfunc1(cls):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001477 Decimal = cls.decimal.Decimal
1478 InvalidOperation = cls.decimal.InvalidOperation
1479 DivisionByZero = cls.decimal.DivisionByZero
1480 Overflow = cls.decimal.Overflow
1481 Underflow = cls.decimal.Underflow
1482 Inexact = cls.decimal.Inexact
1483 getcontext = cls.decimal.getcontext
1484 localcontext = cls.decimal.localcontext
1485
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001486 d1 = Decimal(1)
1487 d3 = Decimal(3)
Christian Heimesfe337bf2008-03-23 21:54:12 +00001488 test1 = d1/d3
Christian Heimesfe337bf2008-03-23 21:54:12 +00001489
Stefan Krah1919b7e2012-03-21 18:25:23 +01001490 cls.finish1.set()
1491 cls.synchro.wait()
1492
1493 test2 = d1/d3
1494 with localcontext() as c2:
1495 cls.assertTrue(c2.flags[Inexact])
1496 cls.assertRaises(DivisionByZero, c2.divide, d1, 0)
1497 cls.assertTrue(c2.flags[DivisionByZero])
1498 with localcontext() as c3:
1499 cls.assertTrue(c3.flags[Inexact])
1500 cls.assertTrue(c3.flags[DivisionByZero])
1501 cls.assertRaises(InvalidOperation, c3.compare, d1, Decimal('sNaN'))
1502 cls.assertTrue(c3.flags[InvalidOperation])
1503 del c3
1504 cls.assertFalse(c2.flags[InvalidOperation])
1505 del c2
1506
1507 cls.assertEqual(test1, Decimal('0.333333333333333333333333'))
1508 cls.assertEqual(test2, Decimal('0.333333333333333333333333'))
1509
1510 c1 = getcontext()
1511 cls.assertTrue(c1.flags[Inexact])
1512 for sig in Overflow, Underflow, DivisionByZero, InvalidOperation:
1513 cls.assertFalse(c1.flags[sig])
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001514 return
1515
1516def thfunc2(cls):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001517 Decimal = cls.decimal.Decimal
1518 InvalidOperation = cls.decimal.InvalidOperation
1519 DivisionByZero = cls.decimal.DivisionByZero
1520 Overflow = cls.decimal.Overflow
1521 Underflow = cls.decimal.Underflow
1522 Inexact = cls.decimal.Inexact
1523 getcontext = cls.decimal.getcontext
1524 localcontext = cls.decimal.localcontext
1525
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001526 d1 = Decimal(1)
1527 d3 = Decimal(3)
Christian Heimesfe337bf2008-03-23 21:54:12 +00001528 test1 = d1/d3
Stefan Krah1919b7e2012-03-21 18:25:23 +01001529
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001530 thiscontext = getcontext()
1531 thiscontext.prec = 18
Christian Heimesfe337bf2008-03-23 21:54:12 +00001532 test2 = d1/d3
Stefan Krah1919b7e2012-03-21 18:25:23 +01001533
1534 with localcontext() as c2:
1535 cls.assertTrue(c2.flags[Inexact])
1536 cls.assertRaises(Overflow, c2.multiply, Decimal('1e425000000'), 999)
1537 cls.assertTrue(c2.flags[Overflow])
1538 with localcontext(thiscontext) as c3:
1539 cls.assertTrue(c3.flags[Inexact])
1540 cls.assertFalse(c3.flags[Overflow])
1541 c3.traps[Underflow] = True
1542 cls.assertRaises(Underflow, c3.divide, Decimal('1e-425000000'), 999)
1543 cls.assertTrue(c3.flags[Underflow])
1544 del c3
1545 cls.assertFalse(c2.flags[Underflow])
1546 cls.assertFalse(c2.traps[Underflow])
1547 del c2
1548
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001549 cls.synchro.set()
1550 cls.finish2.set()
Christian Heimesfe337bf2008-03-23 21:54:12 +00001551
Stefan Krah1919b7e2012-03-21 18:25:23 +01001552 cls.assertEqual(test1, Decimal('0.333333333333333333333333'))
Christian Heimesfe337bf2008-03-23 21:54:12 +00001553 cls.assertEqual(test2, Decimal('0.333333333333333333'))
Stefan Krah1919b7e2012-03-21 18:25:23 +01001554
1555 cls.assertFalse(thiscontext.traps[Underflow])
1556 cls.assertTrue(thiscontext.flags[Inexact])
1557 for sig in Overflow, Underflow, DivisionByZero, InvalidOperation:
1558 cls.assertFalse(thiscontext.flags[sig])
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001559 return
1560
Stefan Krah1919b7e2012-03-21 18:25:23 +01001561class ThreadingTest(unittest.TestCase):
1562 '''Unit tests for thread local contexts in Decimal.'''
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001563
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001564 # Take care executing this test from IDLE, there's an issue in threading
1565 # that hangs IDLE and I couldn't find it
1566
1567 def test_threading(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001568 DefaultContext = self.decimal.DefaultContext
1569
1570 if self.decimal == C and not self.decimal.HAVE_THREADS:
1571 self.skipTest("compiled without threading")
1572 # Test the "threading isolation" of a Context. Also test changing
1573 # the DefaultContext, which acts as a template for the thread-local
1574 # contexts.
1575 save_prec = DefaultContext.prec
1576 save_emax = DefaultContext.Emax
1577 save_emin = DefaultContext.Emin
1578 DefaultContext.prec = 24
1579 DefaultContext.Emax = 425000000
1580 DefaultContext.Emin = -425000000
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001581
1582 self.synchro = threading.Event()
1583 self.finish1 = threading.Event()
1584 self.finish2 = threading.Event()
1585
1586 th1 = threading.Thread(target=thfunc1, args=(self,))
1587 th2 = threading.Thread(target=thfunc2, args=(self,))
1588
1589 th1.start()
1590 th2.start()
1591
1592 self.finish1.wait()
Thomas Wouters1b7f8912007-09-19 03:06:30 +00001593 self.finish2.wait()
Stefan Krah1919b7e2012-03-21 18:25:23 +01001594
1595 for sig in Signals[self.decimal]:
1596 self.assertFalse(DefaultContext.flags[sig])
1597
1598 DefaultContext.prec = save_prec
1599 DefaultContext.Emax = save_emax
1600 DefaultContext.Emin = save_emin
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001601 return
1602
Stefan Krah1919b7e2012-03-21 18:25:23 +01001603@unittest.skipUnless(threading, 'threading required')
1604class CThreadingTest(ThreadingTest):
1605 decimal = C
1606@unittest.skipUnless(threading, 'threading required')
1607class PyThreadingTest(ThreadingTest):
1608 decimal = P
Raymond Hettinger7e71fa52004-12-18 19:07:19 +00001609
Stefan Krah1919b7e2012-03-21 18:25:23 +01001610class UsabilityTest(unittest.TestCase):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001611 '''Unit tests for Usability cases of Decimal.'''
1612
1613 def test_comparison_operators(self):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001614
Stefan Krah1919b7e2012-03-21 18:25:23 +01001615 Decimal = self.decimal.Decimal
1616
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001617 da = Decimal('23.42')
1618 db = Decimal('23.42')
1619 dc = Decimal('45')
1620
1621 #two Decimals
Ezio Melotti6607d512010-04-03 14:59:49 +00001622 self.assertGreater(dc, da)
1623 self.assertGreaterEqual(dc, da)
1624 self.assertLess(da, dc)
1625 self.assertLessEqual(da, dc)
Guido van Rossume61fd5b2007-07-11 12:20:59 +00001626 self.assertEqual(da, db)
Ezio Melotti6607d512010-04-03 14:59:49 +00001627 self.assertNotEqual(da, dc)
1628 self.assertLessEqual(da, db)
1629 self.assertGreaterEqual(da, db)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001630
1631 #a Decimal and an int
Ezio Melotti6607d512010-04-03 14:59:49 +00001632 self.assertGreater(dc, 23)
1633 self.assertLess(23, dc)
Guido van Rossume61fd5b2007-07-11 12:20:59 +00001634 self.assertEqual(dc, 45)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001635
1636 #a Decimal and uncomparable
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001637 self.assertNotEqual(da, 'ugly')
1638 self.assertNotEqual(da, 32.7)
1639 self.assertNotEqual(da, object())
1640 self.assertNotEqual(da, object)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001641
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001642 # sortable
Guido van Rossumc1f779c2007-07-03 08:25:58 +00001643 a = list(map(Decimal, range(100)))
Raymond Hettinger0aeac102004-07-05 22:53:03 +00001644 b = a[:]
1645 random.shuffle(a)
1646 a.sort()
1647 self.assertEqual(a, b)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001648
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001649 def test_decimal_float_comparison(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001650 Decimal = self.decimal.Decimal
1651
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001652 da = Decimal('0.25')
1653 db = Decimal('3.0')
Ezio Melotti6607d512010-04-03 14:59:49 +00001654 self.assertLess(da, 3.0)
1655 self.assertLessEqual(da, 3.0)
1656 self.assertGreater(db, 0.25)
1657 self.assertGreaterEqual(db, 0.25)
1658 self.assertNotEqual(da, 1.5)
1659 self.assertEqual(da, 0.25)
1660 self.assertGreater(3.0, da)
1661 self.assertGreaterEqual(3.0, da)
1662 self.assertLess(0.25, db)
1663 self.assertLessEqual(0.25, db)
1664 self.assertNotEqual(0.25, db)
1665 self.assertEqual(3.0, db)
1666 self.assertNotEqual(0.1, Decimal('0.1'))
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001667
Stefan Krah1919b7e2012-03-21 18:25:23 +01001668 def test_decimal_complex_comparison(self):
1669 Decimal = self.decimal.Decimal
1670
1671 da = Decimal('0.25')
1672 db = Decimal('3.0')
1673 self.assertNotEqual(da, (1.5+0j))
1674 self.assertNotEqual((1.5+0j), da)
1675 self.assertEqual(da, (0.25+0j))
1676 self.assertEqual((0.25+0j), da)
1677 self.assertEqual((3.0+0j), db)
1678 self.assertEqual(db, (3.0+0j))
1679
1680 self.assertNotEqual(db, (3.0+1j))
1681 self.assertNotEqual((3.0+1j), db)
1682
1683 self.assertIs(db.__lt__(3.0+0j), NotImplemented)
1684 self.assertIs(db.__le__(3.0+0j), NotImplemented)
1685 self.assertIs(db.__gt__(3.0+0j), NotImplemented)
1686 self.assertIs(db.__le__(3.0+0j), NotImplemented)
1687
1688 def test_decimal_fraction_comparison(self):
1689 D = self.decimal.Decimal
1690 F = fractions[self.decimal].Fraction
1691 Context = self.decimal.Context
1692 localcontext = self.decimal.localcontext
1693 InvalidOperation = self.decimal.InvalidOperation
1694
1695
1696 emax = C.MAX_EMAX if C else 999999999
1697 emin = C.MIN_EMIN if C else -999999999
1698 etiny = C.MIN_ETINY if C else -1999999997
1699 c = Context(Emax=emax, Emin=emin)
1700
1701 with localcontext(c):
1702 c.prec = emax
1703 self.assertLess(D(0), F(1,9999999999999999999999999999999999999))
1704 self.assertLess(F(-1,9999999999999999999999999999999999999), D(0))
1705 self.assertLess(F(0,1), D("1e" + str(etiny)))
1706 self.assertLess(D("-1e" + str(etiny)), F(0,1))
1707 self.assertLess(F(0,9999999999999999999999999), D("1e" + str(etiny)))
1708 self.assertLess(D("-1e" + str(etiny)), F(0,9999999999999999999999999))
1709
1710 self.assertEqual(D("0.1"), F(1,10))
1711 self.assertEqual(F(1,10), D("0.1"))
1712
1713 c.prec = 300
1714 self.assertNotEqual(D(1)/3, F(1,3))
1715 self.assertNotEqual(F(1,3), D(1)/3)
1716
1717 self.assertLessEqual(F(120984237, 9999999999), D("9e" + str(emax)))
1718 self.assertGreaterEqual(D("9e" + str(emax)), F(120984237, 9999999999))
1719
1720 self.assertGreater(D('inf'), F(99999999999,123))
1721 self.assertGreater(D('inf'), F(-99999999999,123))
1722 self.assertLess(D('-inf'), F(99999999999,123))
1723 self.assertLess(D('-inf'), F(-99999999999,123))
1724
1725 self.assertRaises(InvalidOperation, D('nan').__gt__, F(-9,123))
1726 self.assertIs(NotImplemented, F(-9,123).__lt__(D('nan')))
1727 self.assertNotEqual(D('nan'), F(-9,123))
1728 self.assertNotEqual(F(-9,123), D('nan'))
1729
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001730 def test_copy_and_deepcopy_methods(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001731 Decimal = self.decimal.Decimal
1732
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001733 d = Decimal('43.24')
1734 c = copy.copy(d)
1735 self.assertEqual(id(c), id(d))
1736 dc = copy.deepcopy(d)
1737 self.assertEqual(id(dc), id(d))
1738
1739 def test_hash_method(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001740
1741 Decimal = self.decimal.Decimal
1742 localcontext = self.decimal.localcontext
1743
Stefan Krahdc817b22010-11-17 11:16:34 +00001744 def hashit(d):
1745 a = hash(d)
1746 b = d.__hash__()
1747 self.assertEqual(a, b)
1748 return a
1749
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001750 #just that it's hashable
Stefan Krahdc817b22010-11-17 11:16:34 +00001751 hashit(Decimal(23))
1752 hashit(Decimal('Infinity'))
1753 hashit(Decimal('-Infinity'))
1754 hashit(Decimal('nan123'))
1755 hashit(Decimal('-NaN'))
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001756
1757 test_values = [Decimal(sign*(2**m + n))
1758 for m in [0, 14, 15, 16, 17, 30, 31,
Stefan Krahdc817b22010-11-17 11:16:34 +00001759 32, 33, 61, 62, 63, 64, 65, 66]
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001760 for n in range(-10, 10)
1761 for sign in [-1, 1]]
1762 test_values.extend([
Stefan Krahdc817b22010-11-17 11:16:34 +00001763 Decimal("-1"), # ==> -2
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001764 Decimal("-0"), # zeros
1765 Decimal("0.00"),
1766 Decimal("-0.000"),
1767 Decimal("0E10"),
1768 Decimal("-0E12"),
1769 Decimal("10.0"), # negative exponent
1770 Decimal("-23.00000"),
1771 Decimal("1230E100"), # positive exponent
1772 Decimal("-4.5678E50"),
1773 # a value for which hash(n) != hash(n % (2**64-1))
1774 # in Python pre-2.6
1775 Decimal(2**64 + 2**32 - 1),
1776 # selection of values which fail with the old (before
1777 # version 2.6) long.__hash__
1778 Decimal("1.634E100"),
1779 Decimal("90.697E100"),
1780 Decimal("188.83E100"),
1781 Decimal("1652.9E100"),
1782 Decimal("56531E100"),
1783 ])
1784
1785 # check that hash(d) == hash(int(d)) for integral values
1786 for value in test_values:
Stefan Krahdc817b22010-11-17 11:16:34 +00001787 self.assertEqual(hashit(value), hashit(int(value)))
Thomas Wouters8ce81f72007-09-20 18:22:40 +00001788
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001789 #the same hash that to an int
Stefan Krahdc817b22010-11-17 11:16:34 +00001790 self.assertEqual(hashit(Decimal(23)), hashit(23))
Raymond Hettingerd325c4b2010-11-21 04:08:28 +00001791 self.assertRaises(TypeError, hash, Decimal('sNaN'))
Stefan Krahdc817b22010-11-17 11:16:34 +00001792 self.assertTrue(hashit(Decimal('Inf')))
1793 self.assertTrue(hashit(Decimal('-Inf')))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001794
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001795 # check that the hashes of a Decimal float match when they
1796 # represent exactly the same values
1797 test_strings = ['inf', '-Inf', '0.0', '-.0e1',
1798 '34.0', '2.5', '112390.625', '-0.515625']
1799 for s in test_strings:
1800 f = float(s)
1801 d = Decimal(s)
Stefan Krahdc817b22010-11-17 11:16:34 +00001802 self.assertEqual(hashit(f), hashit(d))
Mark Dickinsonac256ab2010-04-03 11:08:14 +00001803
Stefan Krah1919b7e2012-03-21 18:25:23 +01001804 with localcontext() as c:
1805 # check that the value of the hash doesn't depend on the
1806 # current context (issue #1757)
1807 x = Decimal("123456789.1")
Christian Heimes2380ac72008-01-09 00:17:24 +00001808
Stefan Krah1919b7e2012-03-21 18:25:23 +01001809 c.prec = 6
1810 h1 = hashit(x)
1811 c.prec = 10
1812 h2 = hashit(x)
1813 c.prec = 16
1814 h3 = hashit(x)
Christian Heimes2380ac72008-01-09 00:17:24 +00001815
Stefan Krah1919b7e2012-03-21 18:25:23 +01001816 self.assertEqual(h1, h2)
1817 self.assertEqual(h1, h3)
1818
1819 c.prec = 10000
1820 x = 1100 ** 1248
1821 self.assertEqual(hashit(Decimal(x)), hashit(x))
Christian Heimes2380ac72008-01-09 00:17:24 +00001822
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001823 def test_min_and_max_methods(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001824 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001825
1826 d1 = Decimal('15.32')
1827 d2 = Decimal('28.5')
1828 l1 = 15
1829 l2 = 28
1830
1831 #between Decimals
Ezio Melotti6607d512010-04-03 14:59:49 +00001832 self.assertIs(min(d1,d2), d1)
1833 self.assertIs(min(d2,d1), d1)
1834 self.assertIs(max(d1,d2), d2)
1835 self.assertIs(max(d2,d1), d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001836
1837 #between Decimal and long
Ezio Melotti6607d512010-04-03 14:59:49 +00001838 self.assertIs(min(d1,l2), d1)
1839 self.assertIs(min(l2,d1), d1)
1840 self.assertIs(max(l1,d2), d2)
1841 self.assertIs(max(d2,l1), d2)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001842
1843 def test_as_nonzero(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001844 Decimal = self.decimal.Decimal
1845
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001846 #as false
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001847 self.assertFalse(Decimal(0))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001848 #as true
Benjamin Petersonc9c0f202009-06-30 23:06:06 +00001849 self.assertTrue(Decimal('0.372'))
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001850
1851 def test_tostring_methods(self):
1852 #Test str and repr methods.
Stefan Krah1919b7e2012-03-21 18:25:23 +01001853 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001854
1855 d = Decimal('15.32')
1856 self.assertEqual(str(d), '15.32') # str
Christian Heimes68f5fbe2008-02-14 08:27:37 +00001857 self.assertEqual(repr(d), "Decimal('15.32')") # repr
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001858
1859 def test_tonum_methods(self):
Mark Dickinson5c2db372009-12-05 20:28:34 +00001860 #Test float and int methods.
Stefan Krah1919b7e2012-03-21 18:25:23 +01001861 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001862
1863 d1 = Decimal('66')
1864 d2 = Decimal('15.32')
1865
1866 #int
1867 self.assertEqual(int(d1), 66)
1868 self.assertEqual(int(d2), 15)
1869
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001870 #float
1871 self.assertEqual(float(d1), 66)
1872 self.assertEqual(float(d2), 15.32)
1873
Mark Dickinsonb27406c2008-05-09 13:42:33 +00001874 #floor
1875 test_pairs = [
1876 ('123.00', 123),
1877 ('3.2', 3),
1878 ('3.54', 3),
1879 ('3.899', 3),
1880 ('-2.3', -3),
1881 ('-11.0', -11),
1882 ('0.0', 0),
1883 ('-0E3', 0),
Stefan Krah1919b7e2012-03-21 18:25:23 +01001884 ('89891211712379812736.1', 89891211712379812736),
Mark Dickinsonb27406c2008-05-09 13:42:33 +00001885 ]
1886 for d, i in test_pairs:
1887 self.assertEqual(math.floor(Decimal(d)), i)
1888 self.assertRaises(ValueError, math.floor, Decimal('-NaN'))
1889 self.assertRaises(ValueError, math.floor, Decimal('sNaN'))
1890 self.assertRaises(ValueError, math.floor, Decimal('NaN123'))
1891 self.assertRaises(OverflowError, math.floor, Decimal('Inf'))
1892 self.assertRaises(OverflowError, math.floor, Decimal('-Inf'))
1893
1894 #ceiling
1895 test_pairs = [
1896 ('123.00', 123),
1897 ('3.2', 4),
1898 ('3.54', 4),
1899 ('3.899', 4),
1900 ('-2.3', -2),
1901 ('-11.0', -11),
1902 ('0.0', 0),
1903 ('-0E3', 0),
Stefan Krah1919b7e2012-03-21 18:25:23 +01001904 ('89891211712379812736.1', 89891211712379812737),
Mark Dickinsonb27406c2008-05-09 13:42:33 +00001905 ]
1906 for d, i in test_pairs:
1907 self.assertEqual(math.ceil(Decimal(d)), i)
1908 self.assertRaises(ValueError, math.ceil, Decimal('-NaN'))
1909 self.assertRaises(ValueError, math.ceil, Decimal('sNaN'))
1910 self.assertRaises(ValueError, math.ceil, Decimal('NaN123'))
1911 self.assertRaises(OverflowError, math.ceil, Decimal('Inf'))
1912 self.assertRaises(OverflowError, math.ceil, Decimal('-Inf'))
1913
1914 #round, single argument
1915 test_pairs = [
1916 ('123.00', 123),
1917 ('3.2', 3),
1918 ('3.54', 4),
1919 ('3.899', 4),
1920 ('-2.3', -2),
1921 ('-11.0', -11),
1922 ('0.0', 0),
1923 ('-0E3', 0),
1924 ('-3.5', -4),
1925 ('-2.5', -2),
1926 ('-1.5', -2),
1927 ('-0.5', 0),
1928 ('0.5', 0),
1929 ('1.5', 2),
1930 ('2.5', 2),
1931 ('3.5', 4),
1932 ]
1933 for d, i in test_pairs:
1934 self.assertEqual(round(Decimal(d)), i)
1935 self.assertRaises(ValueError, round, Decimal('-NaN'))
1936 self.assertRaises(ValueError, round, Decimal('sNaN'))
1937 self.assertRaises(ValueError, round, Decimal('NaN123'))
1938 self.assertRaises(OverflowError, round, Decimal('Inf'))
1939 self.assertRaises(OverflowError, round, Decimal('-Inf'))
1940
1941 #round, two arguments; this is essentially equivalent
1942 #to quantize, which is already extensively tested
1943 test_triples = [
1944 ('123.456', -4, '0E+4'),
1945 ('123.456', -3, '0E+3'),
1946 ('123.456', -2, '1E+2'),
1947 ('123.456', -1, '1.2E+2'),
1948 ('123.456', 0, '123'),
1949 ('123.456', 1, '123.5'),
1950 ('123.456', 2, '123.46'),
1951 ('123.456', 3, '123.456'),
1952 ('123.456', 4, '123.4560'),
1953 ('123.455', 2, '123.46'),
1954 ('123.445', 2, '123.44'),
1955 ('Inf', 4, 'NaN'),
1956 ('-Inf', -23, 'NaN'),
1957 ('sNaN314', 3, 'NaN314'),
1958 ]
1959 for d, n, r in test_triples:
1960 self.assertEqual(str(round(Decimal(d), n)), r)
1961
Mark Dickinsonfc33d4c2012-08-24 18:53:10 +01001962 def test_nan_to_float(self):
1963 # Test conversions of decimal NANs to float.
1964 # See http://bugs.python.org/issue15544
1965 Decimal = self.decimal.Decimal
1966 for s in ('nan', 'nan1234', '-nan', '-nan2468'):
1967 f = float(Decimal(s))
1968 self.assertTrue(math.isnan(f))
1969 sign = math.copysign(1.0, f)
1970 self.assertEqual(sign, -1.0 if s.startswith('-') else 1.0)
1971
1972 def test_snan_to_float(self):
1973 Decimal = self.decimal.Decimal
1974 for s in ('snan', '-snan', 'snan1357', '-snan1234'):
1975 d = Decimal(s)
1976 self.assertRaises(ValueError, float, d)
1977
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001978 def test_eval_round_trip(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001979 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001980
1981 #with zero
1982 d = Decimal( (0, (0,), 0) )
1983 self.assertEqual(d, eval(repr(d)))
1984
1985 #int
1986 d = Decimal( (1, (4, 5), 0) )
1987 self.assertEqual(d, eval(repr(d)))
1988
1989 #float
1990 d = Decimal( (0, (4, 5, 3, 4), -2) )
1991 self.assertEqual(d, eval(repr(d)))
1992
1993 #weird
1994 d = Decimal( (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
1995 self.assertEqual(d, eval(repr(d)))
1996
1997 def test_as_tuple(self):
Stefan Krah1919b7e2012-03-21 18:25:23 +01001998 Decimal = self.decimal.Decimal
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00001999
2000 #with zero
2001 d = Decimal(0)
2002 self.assertEqual(d.as_tuple(), (0, (0,), 0) )
2003
2004 #int
2005 d = Decimal(-45)
2006 self.assertEqual(d.as_tuple(), (1, (4, 5), 0) )
2007
2008 #complicated string
2009 d = Decimal("-4.34913534E-17")
2010 self.assertEqual(d.as_tuple(), (1, (4, 3, 4, 9, 1, 3, 5, 3, 4), -25) )
2011
Stefan Krah76e12172012-09-10 19:34:58 +02002012 # The '0' coefficient is implementation specific to decimal.py.
2013 # It has no meaning in the C-version and is ignored there.
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00002014 d = Decimal("Infinity")
2015 self.assertEqual(d.as_tuple(), (0, (0,), 'F') )
2016
Guido van Rossum8ce8a782007-11-01 19:42:39 +00002017 #leading zeros in coefficient should be stripped
2018 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), -2) )
2019 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), -2) )
2020 d = Decimal( (1, (0, 0, 0), 37) )
2021 self.assertEqual(d.as_tuple(), (1, (0,), 37))
2022 d = Decimal( (1, (), 37) )
2023 self.assertEqual(d.as_tuple(), (1, (0,), 37))
2024
2025 #leading zeros in NaN diagnostic info should be stripped
2026 d = Decimal( (0, (0, 0, 4, 0, 5, 3, 4), 'n') )
2027 self.assertEqual(d.as_tuple(), (0, (4, 0, 5, 3, 4), 'n') )
2028 d = Decimal( (1, (0, 0, 0), 'N') )
2029 self.assertEqual(d.as_tuple(), (1, (), 'N') )
2030 d = Decimal( (1, (), 'n') )
2031 self.assertEqual(d.as_tuple(), (1, (), 'n') )
2032
Stefan Krah76e12172012-09-10 19:34:58 +02002033 # For infinities, decimal.py has always silently accepted any
2034 # coefficient tuple.
2035 d = Decimal( (0, (0,), 'F') )
2036 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
2037 d = Decimal( (0, (4, 5, 3, 4), 'F') )
2038 self.assertEqual(d.as_tuple(), (0, (0,), 'F'))
2039 d = Decimal( (1, (0, 2, 7, 1), 'F') )
2040 self.assertEqual(d.as_tuple(), (1, (0,), 'F'))
Guido van Rossum8ce8a782007-11-01 19:42:39 +00002041
Stefan Krah1919b7e2012-03-21 18:25:23 +01002042 def test_subclassing(self):
2043 # Different behaviours when subclassing Decimal
2044 Decimal = self.decimal.Decimal
2045
2046 class MyDecimal(Decimal):
Stefan Krah0f82b762012-11-08 11:17:29 +01002047 y = None
Stefan Krah1919b7e2012-03-21 18:25:23 +01002048
2049 d1 = MyDecimal(1)
2050 d2 = MyDecimal(2)
2051 d = d1 + d2
2052 self.assertIs(type(d), Decimal)
2053
2054 d = d1.max(d2)
2055 self.assertIs(type(d), Decimal)
2056
2057 d = copy.copy(d1)
2058 self.assertIs(type(d), MyDecimal)
2059 self.assertEqual(d, d1)
2060
2061 d = copy.deepcopy(d1)
2062 self.assertIs(type(d), MyDecimal)
2063 self.assertEqual(d, d1)
2064
Stefan Krah0f82b762012-11-08 11:17:29 +01002065 # Decimal(Decimal)
2066 d = Decimal('1.0')
2067 x = Decimal(d)
2068 self.assertIs(type(x), Decimal)
2069 self.assertEqual(x, d)
Stefan Krahf4abc7b2012-11-07 23:12:25 +01002070
Stefan Krah0f82b762012-11-08 11:17:29 +01002071 # MyDecimal(Decimal)
2072 m = MyDecimal(d)
2073 self.assertIs(type(m), MyDecimal)
2074 self.assertEqual(m, d)
2075 self.assertIs(m.y, None)
2076
2077 # Decimal(MyDecimal)
2078 x = Decimal(m)
2079 self.assertIs(type(x), Decimal)
2080 self.assertEqual(x, d)
2081
2082 # MyDecimal(MyDecimal)
2083 m.y = 9
2084 x = MyDecimal(m)
2085 self.assertIs(type(x), MyDecimal)
2086 self.assertEqual(x, d)
2087 self.assertIs(x.y, None)
Stefan Krahed16eff2012-11-07 23:47:19 +01002088
Stefan Krah1919b7e2012-03-21 18:25:23 +01002089 def test_implicit_context(self):
2090 Decimal = self.decimal.Decimal
2091 getcontext = self.decimal.getcontext
2092
2093 # Check results when context given implicitly. (Issue 2478)
2094 c = getcontext()
2095 self.assertEqual(str(Decimal(0).sqrt()),
2096 str(c.sqrt(Decimal(0))))
2097
Stefan Krah040e3112012-12-15 22:33:33 +01002098 def test_none_args(self):
2099 Decimal = self.decimal.Decimal
2100 Context = self.decimal.Context
2101 localcontext = self.decimal.localcontext
2102 InvalidOperation = self.decimal.InvalidOperation
2103 DivisionByZero = self.decimal.DivisionByZero
2104 Overflow = self.decimal.Overflow
2105 Underflow = self.decimal.Underflow
2106 Subnormal = self.decimal.Subnormal
2107 Inexact = self.decimal.Inexact
2108 Rounded = self.decimal.Rounded
2109 Clamped = self.decimal.Clamped
Stefan Krah040e3112012-12-15 22:33:33 +01002110
2111 with localcontext(Context()) as c:
2112 c.prec = 7
2113 c.Emax = 999
2114 c.Emin = -999
2115
2116 x = Decimal("111")
2117 y = Decimal("1e9999")
2118 z = Decimal("1e-9999")
2119
2120 ##### Unary functions
2121 c.clear_flags()
2122 self.assertEqual(str(x.exp(context=None)), '1.609487E+48')
2123 self.assertTrue(c.flags[Inexact])
2124 self.assertTrue(c.flags[Rounded])
2125 c.clear_flags()
2126 self.assertRaises(Overflow, y.exp, context=None)
2127 self.assertTrue(c.flags[Overflow])
2128
2129 self.assertIs(z.is_normal(context=None), False)
2130 self.assertIs(z.is_subnormal(context=None), True)
2131
2132 c.clear_flags()
2133 self.assertEqual(str(x.ln(context=None)), '4.709530')
2134 self.assertTrue(c.flags[Inexact])
2135 self.assertTrue(c.flags[Rounded])
2136 c.clear_flags()
2137 self.assertRaises(InvalidOperation, Decimal(-1).ln, context=None)
2138 self.assertTrue(c.flags[InvalidOperation])
2139
2140 c.clear_flags()
2141 self.assertEqual(str(x.log10(context=None)), '2.045323')
2142 self.assertTrue(c.flags[Inexact])
2143 self.assertTrue(c.flags[Rounded])
2144 c.clear_flags()
2145 self.assertRaises(InvalidOperation, Decimal(-1).log10, context=None)
2146 self.assertTrue(c.flags[InvalidOperation])
2147
2148 c.clear_flags()
2149 self.assertEqual(str(x.logb(context=None)), '2')
2150 self.assertRaises(DivisionByZero, Decimal(0).logb, context=None)
2151 self.assertTrue(c.flags[DivisionByZero])
2152
2153 c.clear_flags()
2154 self.assertEqual(str(x.logical_invert(context=None)), '1111000')
2155 self.assertRaises(InvalidOperation, y.logical_invert, context=None)
2156 self.assertTrue(c.flags[InvalidOperation])
2157
2158 c.clear_flags()
2159 self.assertEqual(str(y.next_minus(context=None)), '9.999999E+999')
2160 self.assertRaises(InvalidOperation, Decimal('sNaN').next_minus, context=None)
2161 self.assertTrue(c.flags[InvalidOperation])
2162
2163 c.clear_flags()
2164 self.assertEqual(str(y.next_plus(context=None)), 'Infinity')
2165 self.assertRaises(InvalidOperation, Decimal('sNaN').next_plus, context=None)
2166 self.assertTrue(c.flags[InvalidOperation])
2167
2168 c.clear_flags()
2169 self.assertEqual(str(z.normalize(context=None)), '0')
2170 self.assertRaises(Overflow, y.normalize, context=None)
2171 self.assertTrue(c.flags[Overflow])
2172
2173 self.assertEqual(str(z.number_class(context=None)), '+Subnormal')
2174
2175 c.clear_flags()
2176 self.assertEqual(str(z.sqrt(context=None)), '0E-1005')
2177 self.assertTrue(c.flags[Clamped])
2178 self.assertTrue(c.flags[Inexact])
2179 self.assertTrue(c.flags[Rounded])
2180 self.assertTrue(c.flags[Subnormal])
2181 self.assertTrue(c.flags[Underflow])
2182 c.clear_flags()
2183 self.assertRaises(Overflow, y.sqrt, context=None)
2184 self.assertTrue(c.flags[Overflow])
2185
2186 c.capitals = 0
2187 self.assertEqual(str(z.to_eng_string(context=None)), '1e-9999')
2188 c.capitals = 1
2189
2190
2191 ##### Binary functions
2192 c.clear_flags()
2193 ans = str(x.compare(Decimal('Nan891287828'), context=None))
2194 self.assertEqual(ans, 'NaN1287828')
2195 self.assertRaises(InvalidOperation, x.compare, Decimal('sNaN'), context=None)
2196 self.assertTrue(c.flags[InvalidOperation])
2197
2198 c.clear_flags()
2199 ans = str(x.compare_signal(8224, context=None))
2200 self.assertEqual(ans, '-1')
2201 self.assertRaises(InvalidOperation, x.compare_signal, Decimal('NaN'), context=None)
2202 self.assertTrue(c.flags[InvalidOperation])
2203
2204 c.clear_flags()
2205 ans = str(x.logical_and(101, context=None))
2206 self.assertEqual(ans, '101')
2207 self.assertRaises(InvalidOperation, x.logical_and, 123, context=None)
2208 self.assertTrue(c.flags[InvalidOperation])
2209
2210 c.clear_flags()
2211 ans = str(x.logical_or(101, context=None))
2212 self.assertEqual(ans, '111')
2213 self.assertRaises(InvalidOperation, x.logical_or, 123, context=None)
2214 self.assertTrue(c.flags[InvalidOperation])
2215
2216 c.clear_flags()
2217 ans = str(x.logical_xor(101, context=None))
2218 self.assertEqual(ans, '10')
2219 self.assertRaises(InvalidOperation, x.logical_xor, 123, context=None)
2220 self.assertTrue(c.flags[InvalidOperation])
2221
2222 c.clear_flags()
2223 ans = str(x.max(101, context=None))
2224 self.assertEqual(ans, '111')
2225 self.assertRaises(InvalidOperation, x.max, Decimal('sNaN'), context=None)
2226 self.assertTrue(c.flags[InvalidOperation])
2227
2228 c.clear_flags()
2229 ans = str(x.max_mag(101, context=None))
2230 self.assertEqual(ans, '111')
2231 self.assertRaises(InvalidOperation, x.max_mag, Decimal('sNaN'), context=None)
2232 self.assertTrue(c.flags[InvalidOperation])
2233
2234 c.clear_flags()
2235 ans = str(x.min(101, context=None))
2236 self.assertEqual(ans, '101')
2237 self.assertRaises(InvalidOperation, x.min, Decimal('sNaN'), context=None)
2238 self.assertTrue(c.flags[InvalidOperation])
2239
2240 c.clear_flags()
2241 ans = str(x.min_mag(101, context=None))
2242 self.assertEqual(ans, '101')
2243 self.assertRaises(InvalidOperation, x.min_mag, Decimal('sNaN'), context=None)
2244 self.assertTrue(c.flags[InvalidOperation])
2245
2246 c.clear_flags()
2247 ans = str(x.remainder_near(101, context=None))
2248 self.assertEqual(ans, '10')
2249 self.assertRaises(InvalidOperation, y.remainder_near, 101, context=None)
2250 self.assertTrue(c.flags[InvalidOperation])
2251
2252 c.clear_flags()
2253 ans = str(x.rotate(2, context=None))
2254 self.assertEqual(ans, '11100')
2255 self.assertRaises(InvalidOperation, x.rotate, 101, context=None)
2256 self.assertTrue(c.flags[InvalidOperation])
2257
2258 c.clear_flags()
2259 ans = str(x.scaleb(7, context=None))
2260 self.assertEqual(ans, '1.11E+9')
2261 self.assertRaises(InvalidOperation, x.scaleb, 10000, context=None)
2262 self.assertTrue(c.flags[InvalidOperation])
2263
2264 c.clear_flags()
2265 ans = str(x.shift(2, context=None))
2266 self.assertEqual(ans, '11100')
2267 self.assertRaises(InvalidOperation, x.shift, 10000, context=None)
2268 self.assertTrue(c.flags[InvalidOperation])
2269
2270
2271 ##### Ternary functions
2272 c.clear_flags()
2273 ans = str(x.fma(2, 3, context=None))
2274 self.assertEqual(ans, '225')
2275 self.assertRaises(Overflow, x.fma, Decimal('1e9999'), 3, context=None)
2276 self.assertTrue(c.flags[Overflow])
2277
2278
2279 ##### Special cases
2280 c.rounding = ROUND_HALF_EVEN
2281 ans = str(Decimal('1.5').to_integral(rounding=None, context=None))
2282 self.assertEqual(ans, '2')
2283 c.rounding = ROUND_DOWN
2284 ans = str(Decimal('1.5').to_integral(rounding=None, context=None))
2285 self.assertEqual(ans, '1')
2286 ans = str(Decimal('1.5').to_integral(rounding=ROUND_UP, context=None))
2287 self.assertEqual(ans, '2')
2288 c.clear_flags()
2289 self.assertRaises(InvalidOperation, Decimal('sNaN').to_integral, context=None)
2290 self.assertTrue(c.flags[InvalidOperation])
2291
2292 c.rounding = ROUND_HALF_EVEN
2293 ans = str(Decimal('1.5').to_integral_value(rounding=None, context=None))
2294 self.assertEqual(ans, '2')
2295 c.rounding = ROUND_DOWN
2296 ans = str(Decimal('1.5').to_integral_value(rounding=None, context=None))
2297 self.assertEqual(ans, '1')
2298 ans = str(Decimal('1.5').to_integral_value(rounding=ROUND_UP, context=None))
2299 self.assertEqual(ans, '2')
2300 c.clear_flags()
2301 self.assertRaises(InvalidOperation, Decimal('sNaN').to_integral_value, context=None)
2302 self.assertTrue(c.flags[InvalidOperation])
2303
2304 c.rounding = ROUND_HALF_EVEN
2305 ans = str(Decimal('1.5').to_integral_exact(rounding=None, context=None))
2306 self.assertEqual(ans, '2')
2307 c.rounding = ROUND_DOWN
2308 ans = str(Decimal('1.5').to_integral_exact(rounding=None, context=None))
2309 self.assertEqual(ans, '1')
2310 ans = str(Decimal('1.5').to_integral_exact(rounding=ROUND_UP, context=None))
2311 self.assertEqual(ans, '2')
2312 c.clear_flags()
2313 self.assertRaises(InvalidOperation, Decimal('sNaN').to_integral_exact, context=None)
2314 self.assertTrue(c.flags[InvalidOperation])
2315
2316 c.rounding = ROUND_UP
2317 ans = str(Decimal('1.50001').quantize(exp=Decimal('1e-3'), rounding=None, context=None))
2318 self.assertEqual(ans, '1.501')
2319 c.rounding = ROUND_DOWN
2320 ans = str(Decimal('1.50001').quantize(exp=Decimal('1e-3'), rounding=None, context=None))
2321 self.assertEqual(ans, '1.500')
2322 ans = str(Decimal('1.50001').quantize(exp=Decimal('1e-3'), rounding=ROUND_UP, context=None))
2323 self.assertEqual(ans, '1.501')
2324 c.clear_flags()
2325 self.assertRaises(InvalidOperation, y.quantize, Decimal('1e-10'), rounding=ROUND_UP, context=None)
2326 self.assertTrue(c.flags[InvalidOperation])
2327
2328 with localcontext(Context()) as context:
2329 context.prec = 7
2330 context.Emax = 999
2331 context.Emin = -999
2332 with localcontext(ctx=None) as c:
2333 self.assertEqual(c.prec, 7)
2334 self.assertEqual(c.Emax, 999)
2335 self.assertEqual(c.Emin, -999)
2336
Stefan Krah1919b7e2012-03-21 18:25:23 +01002337 def test_conversions_from_int(self):
2338 # Check that methods taking a second Decimal argument will
2339 # always accept an integer in place of a Decimal.
2340 Decimal = self.decimal.Decimal
2341
2342 self.assertEqual(Decimal(4).compare(3),
2343 Decimal(4).compare(Decimal(3)))
2344 self.assertEqual(Decimal(4).compare_signal(3),
2345 Decimal(4).compare_signal(Decimal(3)))
2346 self.assertEqual(Decimal(4).compare_total(3),
2347 Decimal(4).compare_total(Decimal(3)))
2348 self.assertEqual(Decimal(4).compare_total_mag(3),
2349 Decimal(4).compare_total_mag(Decimal(3)))
2350 self.assertEqual(Decimal(10101).logical_and(1001),
2351 Decimal(10101).logical_and(Decimal(1001)))
2352 self.assertEqual(Decimal(10101).logical_or(1001),
2353 Decimal(10101).logical_or(Decimal(1001)))
2354 self.assertEqual(Decimal(10101).logical_xor(1001),
2355 Decimal(10101).logical_xor(Decimal(1001)))
2356 self.assertEqual(Decimal(567).max(123),
2357 Decimal(567).max(Decimal(123)))
2358 self.assertEqual(Decimal(567).max_mag(123),
2359 Decimal(567).max_mag(Decimal(123)))
2360 self.assertEqual(Decimal(567).min(123),
2361 Decimal(567).min(Decimal(123)))
2362 self.assertEqual(Decimal(567).min_mag(123),
2363 Decimal(567).min_mag(Decimal(123)))
2364 self.assertEqual(Decimal(567).next_toward(123),
2365 Decimal(567).next_toward(Decimal(123)))
2366 self.assertEqual(Decimal(1234).quantize(100),
2367 Decimal(1234).quantize(Decimal(100)))
2368 self.assertEqual(Decimal(768).remainder_near(1234),
2369 Decimal(768).remainder_near(Decimal(1234)))
2370 self.assertEqual(Decimal(123).rotate(1),
2371 Decimal(123).rotate(Decimal(1)))
2372 self.assertEqual(Decimal(1234).same_quantum(1000),
2373 Decimal(1234).same_quantum(Decimal(1000)))
2374 self.assertEqual(Decimal('9.123').scaleb(-100),
2375 Decimal('9.123').scaleb(Decimal(-100)))
2376 self.assertEqual(Decimal(456).shift(-1),
2377 Decimal(456).shift(Decimal(-1)))
2378
2379 self.assertEqual(Decimal(-12).fma(Decimal(45), 67),
2380 Decimal(-12).fma(Decimal(45), Decimal(67)))
2381 self.assertEqual(Decimal(-12).fma(45, 67),
2382 Decimal(-12).fma(Decimal(45), Decimal(67)))
2383 self.assertEqual(Decimal(-12).fma(45, Decimal(67)),
2384 Decimal(-12).fma(Decimal(45), Decimal(67)))
2385
2386class CUsabilityTest(UsabilityTest):
2387 decimal = C
2388class PyUsabilityTest(UsabilityTest):
2389 decimal = P
2390
2391class PythonAPItests(unittest.TestCase):
2392
2393 def test_abc(self):
2394 Decimal = self.decimal.Decimal
2395
2396 self.assertTrue(issubclass(Decimal, numbers.Number))
2397 self.assertFalse(issubclass(Decimal, numbers.Real))
2398 self.assertIsInstance(Decimal(0), numbers.Number)
2399 self.assertNotIsInstance(Decimal(0), numbers.Real)
2400
2401 def test_pickle(self):
2402 Decimal = self.decimal.Decimal
2403
2404 savedecimal = sys.modules['decimal']
2405
2406 # Round trip
2407 sys.modules['decimal'] = self.decimal
2408 d = Decimal('-3.141590000')
2409 p = pickle.dumps(d)
2410 e = pickle.loads(p)
2411 self.assertEqual(d, e)
2412
2413 if C:
2414 # Test interchangeability
2415 x = C.Decimal('-3.123e81723')
2416 y = P.Decimal('-3.123e81723')
2417
2418 sys.modules['decimal'] = C
2419 sx = pickle.dumps(x)
2420 sys.modules['decimal'] = P
2421 r = pickle.loads(sx)
2422 self.assertIsInstance(r, P.Decimal)
2423 self.assertEqual(r, y)
2424
2425 sys.modules['decimal'] = P
2426 sy = pickle.dumps(y)
2427 sys.modules['decimal'] = C
2428 r = pickle.loads(sy)
2429 self.assertIsInstance(r, C.Decimal)
2430 self.assertEqual(r, x)
2431
2432 sys.modules['decimal'] = savedecimal
2433
2434 def test_int(self):
2435 Decimal = self.decimal.Decimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01002436
2437 for x in range(-250, 250):
2438 s = '%0.2f' % (x / 100.0)
2439 # should work the same as for floats
2440 self.assertEqual(int(Decimal(s)), int(float(s)))
2441 # should work the same as to_integral in the ROUND_DOWN mode
2442 d = Decimal(s)
2443 r = d.to_integral(ROUND_DOWN)
2444 self.assertEqual(Decimal(int(d)), r)
2445
2446 self.assertRaises(ValueError, int, Decimal('-nan'))
2447 self.assertRaises(ValueError, int, Decimal('snan'))
2448 self.assertRaises(OverflowError, int, Decimal('inf'))
2449 self.assertRaises(OverflowError, int, Decimal('-inf'))
2450
2451 def test_trunc(self):
2452 Decimal = self.decimal.Decimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01002453
2454 for x in range(-250, 250):
2455 s = '%0.2f' % (x / 100.0)
2456 # should work the same as for floats
2457 self.assertEqual(int(Decimal(s)), int(float(s)))
2458 # should work the same as to_integral in the ROUND_DOWN mode
2459 d = Decimal(s)
2460 r = d.to_integral(ROUND_DOWN)
2461 self.assertEqual(Decimal(math.trunc(d)), r)
2462
2463 def test_from_float(self):
2464
2465 Decimal = self.decimal.Decimal
2466
2467 class MyDecimal(Decimal):
2468 pass
2469
2470 self.assertTrue(issubclass(MyDecimal, Decimal))
2471
2472 r = MyDecimal.from_float(0.1)
2473 self.assertEqual(type(r), MyDecimal)
2474 self.assertEqual(str(r),
2475 '0.1000000000000000055511151231257827021181583404541015625')
2476 bigint = 12345678901234567890123456789
2477 self.assertEqual(MyDecimal.from_float(bigint), MyDecimal(bigint))
2478 self.assertTrue(MyDecimal.from_float(float('nan')).is_qnan())
2479 self.assertTrue(MyDecimal.from_float(float('inf')).is_infinite())
2480 self.assertTrue(MyDecimal.from_float(float('-inf')).is_infinite())
2481 self.assertEqual(str(MyDecimal.from_float(float('nan'))),
2482 str(Decimal('NaN')))
2483 self.assertEqual(str(MyDecimal.from_float(float('inf'))),
2484 str(Decimal('Infinity')))
2485 self.assertEqual(str(MyDecimal.from_float(float('-inf'))),
2486 str(Decimal('-Infinity')))
2487 self.assertRaises(TypeError, MyDecimal.from_float, 'abc')
2488 for i in range(200):
2489 x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
2490 self.assertEqual(x, float(MyDecimal.from_float(x))) # roundtrip
2491
2492 def test_create_decimal_from_float(self):
2493 Decimal = self.decimal.Decimal
2494 Context = self.decimal.Context
Stefan Krah1919b7e2012-03-21 18:25:23 +01002495 Inexact = self.decimal.Inexact
2496
2497 context = Context(prec=5, rounding=ROUND_DOWN)
2498 self.assertEqual(
2499 context.create_decimal_from_float(math.pi),
2500 Decimal('3.1415')
2501 )
2502 context = Context(prec=5, rounding=ROUND_UP)
2503 self.assertEqual(
2504 context.create_decimal_from_float(math.pi),
2505 Decimal('3.1416')
2506 )
2507 context = Context(prec=5, traps=[Inexact])
2508 self.assertRaises(
2509 Inexact,
2510 context.create_decimal_from_float,
2511 math.pi
2512 )
2513 self.assertEqual(repr(context.create_decimal_from_float(-0.0)),
2514 "Decimal('-0')")
2515 self.assertEqual(repr(context.create_decimal_from_float(1.0)),
2516 "Decimal('1')")
2517 self.assertEqual(repr(context.create_decimal_from_float(10)),
2518 "Decimal('10')")
2519
2520 def test_quantize(self):
2521 Decimal = self.decimal.Decimal
2522 Context = self.decimal.Context
2523 InvalidOperation = self.decimal.InvalidOperation
Stefan Krah1919b7e2012-03-21 18:25:23 +01002524
2525 c = Context(Emax=99999, Emin=-99999)
2526 self.assertEqual(
2527 Decimal('7.335').quantize(Decimal('.01')),
2528 Decimal('7.34')
2529 )
2530 self.assertEqual(
2531 Decimal('7.335').quantize(Decimal('.01'), rounding=ROUND_DOWN),
2532 Decimal('7.33')
2533 )
2534 self.assertRaises(
2535 InvalidOperation,
2536 Decimal("10e99999").quantize, Decimal('1e100000'), context=c
2537 )
2538
2539 c = Context()
2540 d = Decimal("0.871831e800")
2541 x = d.quantize(context=c, exp=Decimal("1e797"), rounding=ROUND_DOWN)
2542 self.assertEqual(x, Decimal('8.71E+799'))
2543
2544 def test_complex(self):
2545 Decimal = self.decimal.Decimal
2546
2547 x = Decimal("9.8182731e181273")
2548 self.assertEqual(x.real, x)
2549 self.assertEqual(x.imag, 0)
2550 self.assertEqual(x.conjugate(), x)
2551
2552 x = Decimal("1")
2553 self.assertEqual(complex(x), complex(float(1)))
2554
2555 self.assertRaises(AttributeError, setattr, x, 'real', 100)
2556 self.assertRaises(AttributeError, setattr, x, 'imag', 100)
2557 self.assertRaises(AttributeError, setattr, x, 'conjugate', 100)
2558 self.assertRaises(AttributeError, setattr, x, '__complex__', 100)
2559
2560 def test_named_parameters(self):
2561 D = self.decimal.Decimal
2562 Context = self.decimal.Context
2563 localcontext = self.decimal.localcontext
2564 InvalidOperation = self.decimal.InvalidOperation
2565 Overflow = self.decimal.Overflow
2566
2567 xc = Context()
2568 xc.prec = 1
2569 xc.Emax = 1
2570 xc.Emin = -1
2571
2572 with localcontext() as c:
2573 c.clear_flags()
2574
2575 self.assertEqual(D(9, xc), 9)
2576 self.assertEqual(D(9, context=xc), 9)
2577 self.assertEqual(D(context=xc, value=9), 9)
2578 self.assertEqual(D(context=xc), 0)
2579 xc.clear_flags()
2580 self.assertRaises(InvalidOperation, D, "xyz", context=xc)
2581 self.assertTrue(xc.flags[InvalidOperation])
2582 self.assertFalse(c.flags[InvalidOperation])
2583
2584 xc.clear_flags()
2585 self.assertEqual(D(2).exp(context=xc), 7)
2586 self.assertRaises(Overflow, D(8).exp, context=xc)
2587 self.assertTrue(xc.flags[Overflow])
2588 self.assertFalse(c.flags[Overflow])
2589
2590 xc.clear_flags()
2591 self.assertEqual(D(2).ln(context=xc), D('0.7'))
2592 self.assertRaises(InvalidOperation, D(-1).ln, context=xc)
2593 self.assertTrue(xc.flags[InvalidOperation])
2594 self.assertFalse(c.flags[InvalidOperation])
2595
2596 self.assertEqual(D(0).log10(context=xc), D('-inf'))
2597 self.assertEqual(D(-1).next_minus(context=xc), -2)
2598 self.assertEqual(D(-1).next_plus(context=xc), D('-0.9'))
2599 self.assertEqual(D("9.73").normalize(context=xc), D('1E+1'))
2600 self.assertEqual(D("9999").to_integral(context=xc), 9999)
2601 self.assertEqual(D("-2000").to_integral_exact(context=xc), -2000)
2602 self.assertEqual(D("123").to_integral_value(context=xc), 123)
2603 self.assertEqual(D("0.0625").sqrt(context=xc), D('0.2'))
2604
2605 self.assertEqual(D("0.0625").compare(context=xc, other=3), -1)
2606 xc.clear_flags()
2607 self.assertRaises(InvalidOperation,
2608 D("0").compare_signal, D('nan'), context=xc)
2609 self.assertTrue(xc.flags[InvalidOperation])
2610 self.assertFalse(c.flags[InvalidOperation])
2611 self.assertEqual(D("0.01").max(D('0.0101'), context=xc), D('0.0'))
2612 self.assertEqual(D("0.01").max(D('0.0101'), context=xc), D('0.0'))
2613 self.assertEqual(D("0.2").max_mag(D('-0.3'), context=xc),
2614 D('-0.3'))
2615 self.assertEqual(D("0.02").min(D('-0.03'), context=xc), D('-0.0'))
2616 self.assertEqual(D("0.02").min_mag(D('-0.03'), context=xc),
2617 D('0.0'))
2618 self.assertEqual(D("0.2").next_toward(D('-1'), context=xc), D('0.1'))
2619 xc.clear_flags()
2620 self.assertRaises(InvalidOperation,
2621 D("0.2").quantize, D('1e10'), context=xc)
2622 self.assertTrue(xc.flags[InvalidOperation])
2623 self.assertFalse(c.flags[InvalidOperation])
2624 self.assertEqual(D("9.99").remainder_near(D('1.5'), context=xc),
2625 D('-0.5'))
2626
2627 self.assertEqual(D("9.9").fma(third=D('0.9'), context=xc, other=7),
2628 D('7E+1'))
2629
2630 self.assertRaises(TypeError, D(1).is_canonical, context=xc)
2631 self.assertRaises(TypeError, D(1).is_finite, context=xc)
2632 self.assertRaises(TypeError, D(1).is_infinite, context=xc)
2633 self.assertRaises(TypeError, D(1).is_nan, context=xc)
2634 self.assertRaises(TypeError, D(1).is_qnan, context=xc)
2635 self.assertRaises(TypeError, D(1).is_snan, context=xc)
2636 self.assertRaises(TypeError, D(1).is_signed, context=xc)
2637 self.assertRaises(TypeError, D(1).is_zero, context=xc)
2638
2639 self.assertFalse(D("0.01").is_normal(context=xc))
2640 self.assertTrue(D("0.01").is_subnormal(context=xc))
2641
2642 self.assertRaises(TypeError, D(1).adjusted, context=xc)
2643 self.assertRaises(TypeError, D(1).conjugate, context=xc)
2644 self.assertRaises(TypeError, D(1).radix, context=xc)
2645
2646 self.assertEqual(D(-111).logb(context=xc), 2)
2647 self.assertEqual(D(0).logical_invert(context=xc), 1)
2648 self.assertEqual(D('0.01').number_class(context=xc), '+Subnormal')
2649 self.assertEqual(D('0.21').to_eng_string(context=xc), '0.21')
2650
2651 self.assertEqual(D('11').logical_and(D('10'), context=xc), 0)
2652 self.assertEqual(D('11').logical_or(D('10'), context=xc), 1)
2653 self.assertEqual(D('01').logical_xor(D('10'), context=xc), 1)
2654 self.assertEqual(D('23').rotate(1, context=xc), 3)
2655 self.assertEqual(D('23').rotate(1, context=xc), 3)
2656 xc.clear_flags()
2657 self.assertRaises(Overflow,
2658 D('23').scaleb, 1, context=xc)
2659 self.assertTrue(xc.flags[Overflow])
2660 self.assertFalse(c.flags[Overflow])
2661 self.assertEqual(D('23').shift(-1, context=xc), 0)
2662
2663 self.assertRaises(TypeError, D.from_float, 1.1, context=xc)
2664 self.assertRaises(TypeError, D(0).as_tuple, context=xc)
2665
Stefan Krah040e3112012-12-15 22:33:33 +01002666 self.assertEqual(D(1).canonical(), 1)
2667 self.assertRaises(TypeError, D("-1").copy_abs, context=xc)
2668 self.assertRaises(TypeError, D("-1").copy_negate, context=xc)
2669 self.assertRaises(TypeError, D(1).canonical, context="x")
2670 self.assertRaises(TypeError, D(1).canonical, xyz="x")
Stefan Krah1919b7e2012-03-21 18:25:23 +01002671
Stefan Krahb6405ef2012-03-23 14:46:48 +01002672 def test_exception_hierarchy(self):
2673
2674 decimal = self.decimal
2675 DecimalException = decimal.DecimalException
2676 InvalidOperation = decimal.InvalidOperation
2677 FloatOperation = decimal.FloatOperation
2678 DivisionByZero = decimal.DivisionByZero
2679 Overflow = decimal.Overflow
2680 Underflow = decimal.Underflow
2681 Subnormal = decimal.Subnormal
2682 Inexact = decimal.Inexact
2683 Rounded = decimal.Rounded
2684 Clamped = decimal.Clamped
2685
2686 self.assertTrue(issubclass(DecimalException, ArithmeticError))
2687
2688 self.assertTrue(issubclass(InvalidOperation, DecimalException))
2689 self.assertTrue(issubclass(FloatOperation, DecimalException))
2690 self.assertTrue(issubclass(FloatOperation, TypeError))
2691 self.assertTrue(issubclass(DivisionByZero, DecimalException))
2692 self.assertTrue(issubclass(DivisionByZero, ZeroDivisionError))
2693 self.assertTrue(issubclass(Overflow, Rounded))
2694 self.assertTrue(issubclass(Overflow, Inexact))
2695 self.assertTrue(issubclass(Overflow, DecimalException))
2696 self.assertTrue(issubclass(Underflow, Inexact))
2697 self.assertTrue(issubclass(Underflow, Rounded))
2698 self.assertTrue(issubclass(Underflow, Subnormal))
2699 self.assertTrue(issubclass(Underflow, DecimalException))
2700
2701 self.assertTrue(issubclass(Subnormal, DecimalException))
2702 self.assertTrue(issubclass(Inexact, DecimalException))
2703 self.assertTrue(issubclass(Rounded, DecimalException))
2704 self.assertTrue(issubclass(Clamped, DecimalException))
2705
2706 self.assertTrue(issubclass(decimal.ConversionSyntax, InvalidOperation))
2707 self.assertTrue(issubclass(decimal.DivisionImpossible, InvalidOperation))
2708 self.assertTrue(issubclass(decimal.DivisionUndefined, InvalidOperation))
2709 self.assertTrue(issubclass(decimal.DivisionUndefined, ZeroDivisionError))
2710 self.assertTrue(issubclass(decimal.InvalidContext, InvalidOperation))
2711
Stefan Krah1919b7e2012-03-21 18:25:23 +01002712class CPythonAPItests(PythonAPItests):
2713 decimal = C
2714class PyPythonAPItests(PythonAPItests):
2715 decimal = P
2716
2717class ContextAPItests(unittest.TestCase):
2718
Stefan Krah9a4ff432012-12-16 21:10:35 +01002719 def test_none_args(self):
2720 Context = self.decimal.Context
2721 InvalidOperation = self.decimal.InvalidOperation
2722 DivisionByZero = self.decimal.DivisionByZero
2723 Overflow = self.decimal.Overflow
Stefan Krah9a4ff432012-12-16 21:10:35 +01002724
2725 c1 = Context()
2726 c2 = Context(prec=None, rounding=None, Emax=None, Emin=None,
2727 capitals=None, clamp=None, flags=None, traps=None)
2728 for c in [c1, c2]:
2729 self.assertEqual(c.prec, 28)
2730 self.assertEqual(c.rounding, ROUND_HALF_EVEN)
2731 self.assertEqual(c.Emax, 999999)
2732 self.assertEqual(c.Emin, -999999)
2733 self.assertEqual(c.capitals, 1)
2734 self.assertEqual(c.clamp, 0)
2735 assert_signals(self, c, 'flags', [])
2736 assert_signals(self, c, 'traps', [InvalidOperation, DivisionByZero,
2737 Overflow])
2738
Stefan Krah59a4a932013-01-16 12:58:59 +01002739 @cpython_only
2740 def test_from_legacy_strings(self):
2741 import _testcapi
2742 c = self.decimal.Context()
2743
2744 for rnd in RoundingModes:
2745 c.rounding = _testcapi.unicode_legacy_string(rnd)
2746 self.assertEqual(c.rounding, rnd)
2747
2748 s = _testcapi.unicode_legacy_string('')
2749 self.assertRaises(TypeError, setattr, c, 'rounding', s)
2750
2751 s = _testcapi.unicode_legacy_string('ROUND_\x00UP')
2752 self.assertRaises(TypeError, setattr, c, 'rounding', s)
2753
Stefan Krah1919b7e2012-03-21 18:25:23 +01002754 def test_pickle(self):
2755
2756 Context = self.decimal.Context
2757
2758 savedecimal = sys.modules['decimal']
2759
2760 # Round trip
2761 sys.modules['decimal'] = self.decimal
2762 c = Context()
2763 e = pickle.loads(pickle.dumps(c))
2764
2765 self.assertEqual(c.prec, e.prec)
2766 self.assertEqual(c.Emin, e.Emin)
2767 self.assertEqual(c.Emax, e.Emax)
2768 self.assertEqual(c.rounding, e.rounding)
2769 self.assertEqual(c.capitals, e.capitals)
2770 self.assertEqual(c.clamp, e.clamp)
2771 self.assertEqual(c.flags, e.flags)
2772 self.assertEqual(c.traps, e.traps)
2773
2774 # Test interchangeability
2775 combinations = [(C, P), (P, C)] if C else [(P, P)]
2776 for dumper, loader in combinations:
Stefan Krah59a4a932013-01-16 12:58:59 +01002777 for ri, _ in enumerate(RoundingModes):
Stefan Krah1919b7e2012-03-21 18:25:23 +01002778 for fi, _ in enumerate(OrderedSignals[dumper]):
2779 for ti, _ in enumerate(OrderedSignals[dumper]):
2780
2781 prec = random.randrange(1, 100)
2782 emin = random.randrange(-100, 0)
2783 emax = random.randrange(1, 100)
2784 caps = random.randrange(2)
2785 clamp = random.randrange(2)
2786
2787 # One module dumps
2788 sys.modules['decimal'] = dumper
2789 c = dumper.Context(
2790 prec=prec, Emin=emin, Emax=emax,
Stefan Krah59a4a932013-01-16 12:58:59 +01002791 rounding=RoundingModes[ri],
Stefan Krah1919b7e2012-03-21 18:25:23 +01002792 capitals=caps, clamp=clamp,
2793 flags=OrderedSignals[dumper][:fi],
2794 traps=OrderedSignals[dumper][:ti]
2795 )
2796 s = pickle.dumps(c)
2797
2798 # The other module loads
2799 sys.modules['decimal'] = loader
2800 d = pickle.loads(s)
2801 self.assertIsInstance(d, loader.Context)
2802
2803 self.assertEqual(d.prec, prec)
2804 self.assertEqual(d.Emin, emin)
2805 self.assertEqual(d.Emax, emax)
Stefan Krah59a4a932013-01-16 12:58:59 +01002806 self.assertEqual(d.rounding, RoundingModes[ri])
Stefan Krah1919b7e2012-03-21 18:25:23 +01002807 self.assertEqual(d.capitals, caps)
2808 self.assertEqual(d.clamp, clamp)
2809 assert_signals(self, d, 'flags', OrderedSignals[loader][:fi])
2810 assert_signals(self, d, 'traps', OrderedSignals[loader][:ti])
2811
2812 sys.modules['decimal'] = savedecimal
2813
2814 def test_equality_with_other_types(self):
2815 Decimal = self.decimal.Decimal
2816
2817 self.assertIn(Decimal(10), ['a', 1.0, Decimal(10), (1,2), {}])
2818 self.assertNotIn(Decimal(10), ['a', 1.0, (1,2), {}])
2819
2820 def test_copy(self):
2821 # All copies should be deep
2822 Decimal = self.decimal.Decimal
2823 Context = self.decimal.Context
2824
2825 c = Context()
2826 d = c.copy()
2827 self.assertNotEqual(id(c), id(d))
2828 self.assertNotEqual(id(c.flags), id(d.flags))
2829 self.assertNotEqual(id(c.traps), id(d.traps))
2830 k1 = set(c.flags.keys())
2831 k2 = set(d.flags.keys())
2832 self.assertEqual(k1, k2)
2833 self.assertEqual(c.flags, d.flags)
2834
2835 def test__clamp(self):
2836 # In Python 3.2, the private attribute `_clamp` was made
2837 # public (issue 8540), with the old `_clamp` becoming a
2838 # property wrapping `clamp`. For the duration of Python 3.2
2839 # only, the attribute should be gettable/settable via both
2840 # `clamp` and `_clamp`; in Python 3.3, `_clamp` should be
2841 # removed.
2842 Context = self.decimal.Context
2843 c = Context()
2844 self.assertRaises(AttributeError, getattr, c, '_clamp')
2845
2846 def test_abs(self):
2847 Decimal = self.decimal.Decimal
2848 Context = self.decimal.Context
2849
2850 c = Context()
2851 d = c.abs(Decimal(-1))
2852 self.assertEqual(c.abs(-1), d)
2853 self.assertRaises(TypeError, c.abs, '-1')
2854
2855 def test_add(self):
2856 Decimal = self.decimal.Decimal
2857 Context = self.decimal.Context
2858
2859 c = Context()
2860 d = c.add(Decimal(1), Decimal(1))
2861 self.assertEqual(c.add(1, 1), d)
2862 self.assertEqual(c.add(Decimal(1), 1), d)
2863 self.assertEqual(c.add(1, Decimal(1)), d)
2864 self.assertRaises(TypeError, c.add, '1', 1)
2865 self.assertRaises(TypeError, c.add, 1, '1')
2866
2867 def test_compare(self):
2868 Decimal = self.decimal.Decimal
2869 Context = self.decimal.Context
2870
2871 c = Context()
2872 d = c.compare(Decimal(1), Decimal(1))
2873 self.assertEqual(c.compare(1, 1), d)
2874 self.assertEqual(c.compare(Decimal(1), 1), d)
2875 self.assertEqual(c.compare(1, Decimal(1)), d)
2876 self.assertRaises(TypeError, c.compare, '1', 1)
2877 self.assertRaises(TypeError, c.compare, 1, '1')
2878
2879 def test_compare_signal(self):
2880 Decimal = self.decimal.Decimal
2881 Context = self.decimal.Context
2882
2883 c = Context()
2884 d = c.compare_signal(Decimal(1), Decimal(1))
2885 self.assertEqual(c.compare_signal(1, 1), d)
2886 self.assertEqual(c.compare_signal(Decimal(1), 1), d)
2887 self.assertEqual(c.compare_signal(1, Decimal(1)), d)
2888 self.assertRaises(TypeError, c.compare_signal, '1', 1)
2889 self.assertRaises(TypeError, c.compare_signal, 1, '1')
2890
2891 def test_compare_total(self):
2892 Decimal = self.decimal.Decimal
2893 Context = self.decimal.Context
2894
2895 c = Context()
2896 d = c.compare_total(Decimal(1), Decimal(1))
2897 self.assertEqual(c.compare_total(1, 1), d)
2898 self.assertEqual(c.compare_total(Decimal(1), 1), d)
2899 self.assertEqual(c.compare_total(1, Decimal(1)), d)
2900 self.assertRaises(TypeError, c.compare_total, '1', 1)
2901 self.assertRaises(TypeError, c.compare_total, 1, '1')
2902
2903 def test_compare_total_mag(self):
2904 Decimal = self.decimal.Decimal
2905 Context = self.decimal.Context
2906
2907 c = Context()
2908 d = c.compare_total_mag(Decimal(1), Decimal(1))
2909 self.assertEqual(c.compare_total_mag(1, 1), d)
2910 self.assertEqual(c.compare_total_mag(Decimal(1), 1), d)
2911 self.assertEqual(c.compare_total_mag(1, Decimal(1)), d)
2912 self.assertRaises(TypeError, c.compare_total_mag, '1', 1)
2913 self.assertRaises(TypeError, c.compare_total_mag, 1, '1')
2914
2915 def test_copy_abs(self):
2916 Decimal = self.decimal.Decimal
2917 Context = self.decimal.Context
2918
2919 c = Context()
2920 d = c.copy_abs(Decimal(-1))
2921 self.assertEqual(c.copy_abs(-1), d)
2922 self.assertRaises(TypeError, c.copy_abs, '-1')
2923
2924 def test_copy_decimal(self):
2925 Decimal = self.decimal.Decimal
2926 Context = self.decimal.Context
2927
2928 c = Context()
2929 d = c.copy_decimal(Decimal(-1))
2930 self.assertEqual(c.copy_decimal(-1), d)
2931 self.assertRaises(TypeError, c.copy_decimal, '-1')
2932
2933 def test_copy_negate(self):
2934 Decimal = self.decimal.Decimal
2935 Context = self.decimal.Context
2936
2937 c = Context()
2938 d = c.copy_negate(Decimal(-1))
2939 self.assertEqual(c.copy_negate(-1), d)
2940 self.assertRaises(TypeError, c.copy_negate, '-1')
2941
2942 def test_copy_sign(self):
2943 Decimal = self.decimal.Decimal
2944 Context = self.decimal.Context
2945
2946 c = Context()
2947 d = c.copy_sign(Decimal(1), Decimal(-2))
2948 self.assertEqual(c.copy_sign(1, -2), d)
2949 self.assertEqual(c.copy_sign(Decimal(1), -2), d)
2950 self.assertEqual(c.copy_sign(1, Decimal(-2)), d)
2951 self.assertRaises(TypeError, c.copy_sign, '1', -2)
2952 self.assertRaises(TypeError, c.copy_sign, 1, '-2')
2953
2954 def test_divide(self):
2955 Decimal = self.decimal.Decimal
2956 Context = self.decimal.Context
2957
2958 c = Context()
2959 d = c.divide(Decimal(1), Decimal(2))
2960 self.assertEqual(c.divide(1, 2), d)
2961 self.assertEqual(c.divide(Decimal(1), 2), d)
2962 self.assertEqual(c.divide(1, Decimal(2)), d)
2963 self.assertRaises(TypeError, c.divide, '1', 2)
2964 self.assertRaises(TypeError, c.divide, 1, '2')
2965
2966 def test_divide_int(self):
2967 Decimal = self.decimal.Decimal
2968 Context = self.decimal.Context
2969
2970 c = Context()
2971 d = c.divide_int(Decimal(1), Decimal(2))
2972 self.assertEqual(c.divide_int(1, 2), d)
2973 self.assertEqual(c.divide_int(Decimal(1), 2), d)
2974 self.assertEqual(c.divide_int(1, Decimal(2)), d)
2975 self.assertRaises(TypeError, c.divide_int, '1', 2)
2976 self.assertRaises(TypeError, c.divide_int, 1, '2')
2977
2978 def test_divmod(self):
2979 Decimal = self.decimal.Decimal
2980 Context = self.decimal.Context
2981
2982 c = Context()
2983 d = c.divmod(Decimal(1), Decimal(2))
2984 self.assertEqual(c.divmod(1, 2), d)
2985 self.assertEqual(c.divmod(Decimal(1), 2), d)
2986 self.assertEqual(c.divmod(1, Decimal(2)), d)
2987 self.assertRaises(TypeError, c.divmod, '1', 2)
2988 self.assertRaises(TypeError, c.divmod, 1, '2')
2989
2990 def test_exp(self):
2991 Decimal = self.decimal.Decimal
2992 Context = self.decimal.Context
2993
2994 c = Context()
2995 d = c.exp(Decimal(10))
2996 self.assertEqual(c.exp(10), d)
2997 self.assertRaises(TypeError, c.exp, '10')
2998
2999 def test_fma(self):
3000 Decimal = self.decimal.Decimal
3001 Context = self.decimal.Context
3002
3003 c = Context()
3004 d = c.fma(Decimal(2), Decimal(3), Decimal(4))
3005 self.assertEqual(c.fma(2, 3, 4), d)
3006 self.assertEqual(c.fma(Decimal(2), 3, 4), d)
3007 self.assertEqual(c.fma(2, Decimal(3), 4), d)
3008 self.assertEqual(c.fma(2, 3, Decimal(4)), d)
3009 self.assertEqual(c.fma(Decimal(2), Decimal(3), 4), d)
3010 self.assertRaises(TypeError, c.fma, '2', 3, 4)
3011 self.assertRaises(TypeError, c.fma, 2, '3', 4)
3012 self.assertRaises(TypeError, c.fma, 2, 3, '4')
3013
3014 # Issue 12079 for Context.fma ...
3015 self.assertRaises(TypeError, c.fma,
3016 Decimal('Infinity'), Decimal(0), "not a decimal")
3017 self.assertRaises(TypeError, c.fma,
3018 Decimal(1), Decimal('snan'), 1.222)
3019 # ... and for Decimal.fma.
3020 self.assertRaises(TypeError, Decimal('Infinity').fma,
3021 Decimal(0), "not a decimal")
3022 self.assertRaises(TypeError, Decimal(1).fma,
3023 Decimal('snan'), 1.222)
3024
3025 def test_is_finite(self):
3026 Decimal = self.decimal.Decimal
3027 Context = self.decimal.Context
3028
3029 c = Context()
3030 d = c.is_finite(Decimal(10))
3031 self.assertEqual(c.is_finite(10), d)
3032 self.assertRaises(TypeError, c.is_finite, '10')
3033
3034 def test_is_infinite(self):
3035 Decimal = self.decimal.Decimal
3036 Context = self.decimal.Context
3037
3038 c = Context()
3039 d = c.is_infinite(Decimal(10))
3040 self.assertEqual(c.is_infinite(10), d)
3041 self.assertRaises(TypeError, c.is_infinite, '10')
3042
3043 def test_is_nan(self):
3044 Decimal = self.decimal.Decimal
3045 Context = self.decimal.Context
3046
3047 c = Context()
3048 d = c.is_nan(Decimal(10))
3049 self.assertEqual(c.is_nan(10), d)
3050 self.assertRaises(TypeError, c.is_nan, '10')
3051
3052 def test_is_normal(self):
3053 Decimal = self.decimal.Decimal
3054 Context = self.decimal.Context
3055
3056 c = Context()
3057 d = c.is_normal(Decimal(10))
3058 self.assertEqual(c.is_normal(10), d)
3059 self.assertRaises(TypeError, c.is_normal, '10')
3060
3061 def test_is_qnan(self):
3062 Decimal = self.decimal.Decimal
3063 Context = self.decimal.Context
3064
3065 c = Context()
3066 d = c.is_qnan(Decimal(10))
3067 self.assertEqual(c.is_qnan(10), d)
3068 self.assertRaises(TypeError, c.is_qnan, '10')
3069
3070 def test_is_signed(self):
3071 Decimal = self.decimal.Decimal
3072 Context = self.decimal.Context
3073
3074 c = Context()
3075 d = c.is_signed(Decimal(10))
3076 self.assertEqual(c.is_signed(10), d)
3077 self.assertRaises(TypeError, c.is_signed, '10')
3078
3079 def test_is_snan(self):
3080 Decimal = self.decimal.Decimal
3081 Context = self.decimal.Context
3082
3083 c = Context()
3084 d = c.is_snan(Decimal(10))
3085 self.assertEqual(c.is_snan(10), d)
3086 self.assertRaises(TypeError, c.is_snan, '10')
3087
3088 def test_is_subnormal(self):
3089 Decimal = self.decimal.Decimal
3090 Context = self.decimal.Context
3091
3092 c = Context()
3093 d = c.is_subnormal(Decimal(10))
3094 self.assertEqual(c.is_subnormal(10), d)
3095 self.assertRaises(TypeError, c.is_subnormal, '10')
3096
3097 def test_is_zero(self):
3098 Decimal = self.decimal.Decimal
3099 Context = self.decimal.Context
3100
3101 c = Context()
3102 d = c.is_zero(Decimal(10))
3103 self.assertEqual(c.is_zero(10), d)
3104 self.assertRaises(TypeError, c.is_zero, '10')
3105
3106 def test_ln(self):
3107 Decimal = self.decimal.Decimal
3108 Context = self.decimal.Context
3109
3110 c = Context()
3111 d = c.ln(Decimal(10))
3112 self.assertEqual(c.ln(10), d)
3113 self.assertRaises(TypeError, c.ln, '10')
3114
3115 def test_log10(self):
3116 Decimal = self.decimal.Decimal
3117 Context = self.decimal.Context
3118
3119 c = Context()
3120 d = c.log10(Decimal(10))
3121 self.assertEqual(c.log10(10), d)
3122 self.assertRaises(TypeError, c.log10, '10')
3123
3124 def test_logb(self):
3125 Decimal = self.decimal.Decimal
3126 Context = self.decimal.Context
3127
3128 c = Context()
3129 d = c.logb(Decimal(10))
3130 self.assertEqual(c.logb(10), d)
3131 self.assertRaises(TypeError, c.logb, '10')
3132
3133 def test_logical_and(self):
3134 Decimal = self.decimal.Decimal
3135 Context = self.decimal.Context
3136
3137 c = Context()
3138 d = c.logical_and(Decimal(1), Decimal(1))
3139 self.assertEqual(c.logical_and(1, 1), d)
3140 self.assertEqual(c.logical_and(Decimal(1), 1), d)
3141 self.assertEqual(c.logical_and(1, Decimal(1)), d)
3142 self.assertRaises(TypeError, c.logical_and, '1', 1)
3143 self.assertRaises(TypeError, c.logical_and, 1, '1')
3144
3145 def test_logical_invert(self):
3146 Decimal = self.decimal.Decimal
3147 Context = self.decimal.Context
3148
3149 c = Context()
3150 d = c.logical_invert(Decimal(1000))
3151 self.assertEqual(c.logical_invert(1000), d)
3152 self.assertRaises(TypeError, c.logical_invert, '1000')
3153
3154 def test_logical_or(self):
3155 Decimal = self.decimal.Decimal
3156 Context = self.decimal.Context
3157
3158 c = Context()
3159 d = c.logical_or(Decimal(1), Decimal(1))
3160 self.assertEqual(c.logical_or(1, 1), d)
3161 self.assertEqual(c.logical_or(Decimal(1), 1), d)
3162 self.assertEqual(c.logical_or(1, Decimal(1)), d)
3163 self.assertRaises(TypeError, c.logical_or, '1', 1)
3164 self.assertRaises(TypeError, c.logical_or, 1, '1')
3165
3166 def test_logical_xor(self):
3167 Decimal = self.decimal.Decimal
3168 Context = self.decimal.Context
3169
3170 c = Context()
3171 d = c.logical_xor(Decimal(1), Decimal(1))
3172 self.assertEqual(c.logical_xor(1, 1), d)
3173 self.assertEqual(c.logical_xor(Decimal(1), 1), d)
3174 self.assertEqual(c.logical_xor(1, Decimal(1)), d)
3175 self.assertRaises(TypeError, c.logical_xor, '1', 1)
3176 self.assertRaises(TypeError, c.logical_xor, 1, '1')
3177
3178 def test_max(self):
3179 Decimal = self.decimal.Decimal
3180 Context = self.decimal.Context
3181
3182 c = Context()
3183 d = c.max(Decimal(1), Decimal(2))
3184 self.assertEqual(c.max(1, 2), d)
3185 self.assertEqual(c.max(Decimal(1), 2), d)
3186 self.assertEqual(c.max(1, Decimal(2)), d)
3187 self.assertRaises(TypeError, c.max, '1', 2)
3188 self.assertRaises(TypeError, c.max, 1, '2')
3189
3190 def test_max_mag(self):
3191 Decimal = self.decimal.Decimal
3192 Context = self.decimal.Context
3193
3194 c = Context()
3195 d = c.max_mag(Decimal(1), Decimal(2))
3196 self.assertEqual(c.max_mag(1, 2), d)
3197 self.assertEqual(c.max_mag(Decimal(1), 2), d)
3198 self.assertEqual(c.max_mag(1, Decimal(2)), d)
3199 self.assertRaises(TypeError, c.max_mag, '1', 2)
3200 self.assertRaises(TypeError, c.max_mag, 1, '2')
3201
3202 def test_min(self):
3203 Decimal = self.decimal.Decimal
3204 Context = self.decimal.Context
3205
3206 c = Context()
3207 d = c.min(Decimal(1), Decimal(2))
3208 self.assertEqual(c.min(1, 2), d)
3209 self.assertEqual(c.min(Decimal(1), 2), d)
3210 self.assertEqual(c.min(1, Decimal(2)), d)
3211 self.assertRaises(TypeError, c.min, '1', 2)
3212 self.assertRaises(TypeError, c.min, 1, '2')
3213
3214 def test_min_mag(self):
3215 Decimal = self.decimal.Decimal
3216 Context = self.decimal.Context
3217
3218 c = Context()
3219 d = c.min_mag(Decimal(1), Decimal(2))
3220 self.assertEqual(c.min_mag(1, 2), d)
3221 self.assertEqual(c.min_mag(Decimal(1), 2), d)
3222 self.assertEqual(c.min_mag(1, Decimal(2)), d)
3223 self.assertRaises(TypeError, c.min_mag, '1', 2)
3224 self.assertRaises(TypeError, c.min_mag, 1, '2')
3225
3226 def test_minus(self):
3227 Decimal = self.decimal.Decimal
3228 Context = self.decimal.Context
3229
3230 c = Context()
3231 d = c.minus(Decimal(10))
3232 self.assertEqual(c.minus(10), d)
3233 self.assertRaises(TypeError, c.minus, '10')
3234
3235 def test_multiply(self):
3236 Decimal = self.decimal.Decimal
3237 Context = self.decimal.Context
3238
3239 c = Context()
3240 d = c.multiply(Decimal(1), Decimal(2))
3241 self.assertEqual(c.multiply(1, 2), d)
3242 self.assertEqual(c.multiply(Decimal(1), 2), d)
3243 self.assertEqual(c.multiply(1, Decimal(2)), d)
3244 self.assertRaises(TypeError, c.multiply, '1', 2)
3245 self.assertRaises(TypeError, c.multiply, 1, '2')
3246
3247 def test_next_minus(self):
3248 Decimal = self.decimal.Decimal
3249 Context = self.decimal.Context
3250
3251 c = Context()
3252 d = c.next_minus(Decimal(10))
3253 self.assertEqual(c.next_minus(10), d)
3254 self.assertRaises(TypeError, c.next_minus, '10')
3255
3256 def test_next_plus(self):
3257 Decimal = self.decimal.Decimal
3258 Context = self.decimal.Context
3259
3260 c = Context()
3261 d = c.next_plus(Decimal(10))
3262 self.assertEqual(c.next_plus(10), d)
3263 self.assertRaises(TypeError, c.next_plus, '10')
3264
3265 def test_next_toward(self):
3266 Decimal = self.decimal.Decimal
3267 Context = self.decimal.Context
3268
3269 c = Context()
3270 d = c.next_toward(Decimal(1), Decimal(2))
3271 self.assertEqual(c.next_toward(1, 2), d)
3272 self.assertEqual(c.next_toward(Decimal(1), 2), d)
3273 self.assertEqual(c.next_toward(1, Decimal(2)), d)
3274 self.assertRaises(TypeError, c.next_toward, '1', 2)
3275 self.assertRaises(TypeError, c.next_toward, 1, '2')
3276
3277 def test_normalize(self):
3278 Decimal = self.decimal.Decimal
3279 Context = self.decimal.Context
3280
3281 c = Context()
3282 d = c.normalize(Decimal(10))
3283 self.assertEqual(c.normalize(10), d)
3284 self.assertRaises(TypeError, c.normalize, '10')
3285
3286 def test_number_class(self):
3287 Decimal = self.decimal.Decimal
3288 Context = self.decimal.Context
3289
3290 c = Context()
3291 self.assertEqual(c.number_class(123), c.number_class(Decimal(123)))
3292 self.assertEqual(c.number_class(0), c.number_class(Decimal(0)))
3293 self.assertEqual(c.number_class(-45), c.number_class(Decimal(-45)))
3294
3295 def test_plus(self):
3296 Decimal = self.decimal.Decimal
3297 Context = self.decimal.Context
3298
3299 c = Context()
3300 d = c.plus(Decimal(10))
3301 self.assertEqual(c.plus(10), d)
3302 self.assertRaises(TypeError, c.plus, '10')
3303
3304 def test_power(self):
3305 Decimal = self.decimal.Decimal
3306 Context = self.decimal.Context
3307
3308 c = Context()
3309 d = c.power(Decimal(1), Decimal(4))
3310 self.assertEqual(c.power(1, 4), d)
3311 self.assertEqual(c.power(Decimal(1), 4), d)
3312 self.assertEqual(c.power(1, Decimal(4)), d)
3313 self.assertEqual(c.power(Decimal(1), Decimal(4)), d)
3314 self.assertRaises(TypeError, c.power, '1', 4)
3315 self.assertRaises(TypeError, c.power, 1, '4')
3316 self.assertEqual(c.power(modulo=5, b=8, a=2), 1)
3317
3318 def test_quantize(self):
3319 Decimal = self.decimal.Decimal
3320 Context = self.decimal.Context
3321
3322 c = Context()
3323 d = c.quantize(Decimal(1), Decimal(2))
3324 self.assertEqual(c.quantize(1, 2), d)
3325 self.assertEqual(c.quantize(Decimal(1), 2), d)
3326 self.assertEqual(c.quantize(1, Decimal(2)), d)
3327 self.assertRaises(TypeError, c.quantize, '1', 2)
3328 self.assertRaises(TypeError, c.quantize, 1, '2')
3329
3330 def test_remainder(self):
3331 Decimal = self.decimal.Decimal
3332 Context = self.decimal.Context
3333
3334 c = Context()
3335 d = c.remainder(Decimal(1), Decimal(2))
3336 self.assertEqual(c.remainder(1, 2), d)
3337 self.assertEqual(c.remainder(Decimal(1), 2), d)
3338 self.assertEqual(c.remainder(1, Decimal(2)), d)
3339 self.assertRaises(TypeError, c.remainder, '1', 2)
3340 self.assertRaises(TypeError, c.remainder, 1, '2')
3341
3342 def test_remainder_near(self):
3343 Decimal = self.decimal.Decimal
3344 Context = self.decimal.Context
3345
3346 c = Context()
3347 d = c.remainder_near(Decimal(1), Decimal(2))
3348 self.assertEqual(c.remainder_near(1, 2), d)
3349 self.assertEqual(c.remainder_near(Decimal(1), 2), d)
3350 self.assertEqual(c.remainder_near(1, Decimal(2)), d)
3351 self.assertRaises(TypeError, c.remainder_near, '1', 2)
3352 self.assertRaises(TypeError, c.remainder_near, 1, '2')
3353
3354 def test_rotate(self):
3355 Decimal = self.decimal.Decimal
3356 Context = self.decimal.Context
3357
3358 c = Context()
3359 d = c.rotate(Decimal(1), Decimal(2))
3360 self.assertEqual(c.rotate(1, 2), d)
3361 self.assertEqual(c.rotate(Decimal(1), 2), d)
3362 self.assertEqual(c.rotate(1, Decimal(2)), d)
3363 self.assertRaises(TypeError, c.rotate, '1', 2)
3364 self.assertRaises(TypeError, c.rotate, 1, '2')
3365
3366 def test_sqrt(self):
3367 Decimal = self.decimal.Decimal
3368 Context = self.decimal.Context
3369
3370 c = Context()
3371 d = c.sqrt(Decimal(10))
3372 self.assertEqual(c.sqrt(10), d)
3373 self.assertRaises(TypeError, c.sqrt, '10')
3374
3375 def test_same_quantum(self):
3376 Decimal = self.decimal.Decimal
3377 Context = self.decimal.Context
3378
3379 c = Context()
3380 d = c.same_quantum(Decimal(1), Decimal(2))
3381 self.assertEqual(c.same_quantum(1, 2), d)
3382 self.assertEqual(c.same_quantum(Decimal(1), 2), d)
3383 self.assertEqual(c.same_quantum(1, Decimal(2)), d)
3384 self.assertRaises(TypeError, c.same_quantum, '1', 2)
3385 self.assertRaises(TypeError, c.same_quantum, 1, '2')
3386
3387 def test_scaleb(self):
3388 Decimal = self.decimal.Decimal
3389 Context = self.decimal.Context
3390
3391 c = Context()
3392 d = c.scaleb(Decimal(1), Decimal(2))
3393 self.assertEqual(c.scaleb(1, 2), d)
3394 self.assertEqual(c.scaleb(Decimal(1), 2), d)
3395 self.assertEqual(c.scaleb(1, Decimal(2)), d)
3396 self.assertRaises(TypeError, c.scaleb, '1', 2)
3397 self.assertRaises(TypeError, c.scaleb, 1, '2')
3398
3399 def test_shift(self):
3400 Decimal = self.decimal.Decimal
3401 Context = self.decimal.Context
3402
3403 c = Context()
3404 d = c.shift(Decimal(1), Decimal(2))
3405 self.assertEqual(c.shift(1, 2), d)
3406 self.assertEqual(c.shift(Decimal(1), 2), d)
3407 self.assertEqual(c.shift(1, Decimal(2)), d)
3408 self.assertRaises(TypeError, c.shift, '1', 2)
3409 self.assertRaises(TypeError, c.shift, 1, '2')
3410
3411 def test_subtract(self):
3412 Decimal = self.decimal.Decimal
3413 Context = self.decimal.Context
3414
3415 c = Context()
3416 d = c.subtract(Decimal(1), Decimal(2))
3417 self.assertEqual(c.subtract(1, 2), d)
3418 self.assertEqual(c.subtract(Decimal(1), 2), d)
3419 self.assertEqual(c.subtract(1, Decimal(2)), d)
3420 self.assertRaises(TypeError, c.subtract, '1', 2)
3421 self.assertRaises(TypeError, c.subtract, 1, '2')
3422
3423 def test_to_eng_string(self):
3424 Decimal = self.decimal.Decimal
3425 Context = self.decimal.Context
3426
3427 c = Context()
3428 d = c.to_eng_string(Decimal(10))
3429 self.assertEqual(c.to_eng_string(10), d)
3430 self.assertRaises(TypeError, c.to_eng_string, '10')
3431
3432 def test_to_sci_string(self):
3433 Decimal = self.decimal.Decimal
3434 Context = self.decimal.Context
3435
3436 c = Context()
3437 d = c.to_sci_string(Decimal(10))
3438 self.assertEqual(c.to_sci_string(10), d)
3439 self.assertRaises(TypeError, c.to_sci_string, '10')
3440
3441 def test_to_integral_exact(self):
3442 Decimal = self.decimal.Decimal
3443 Context = self.decimal.Context
3444
3445 c = Context()
3446 d = c.to_integral_exact(Decimal(10))
3447 self.assertEqual(c.to_integral_exact(10), d)
3448 self.assertRaises(TypeError, c.to_integral_exact, '10')
3449
3450 def test_to_integral_value(self):
3451 Decimal = self.decimal.Decimal
3452 Context = self.decimal.Context
3453
3454 c = Context()
3455 d = c.to_integral_value(Decimal(10))
3456 self.assertEqual(c.to_integral_value(10), d)
3457 self.assertRaises(TypeError, c.to_integral_value, '10')
3458 self.assertRaises(TypeError, c.to_integral_value, 10, 'x')
3459
3460class CContextAPItests(ContextAPItests):
3461 decimal = C
3462class PyContextAPItests(ContextAPItests):
3463 decimal = P
3464
3465class ContextWithStatement(unittest.TestCase):
3466 # Can't do these as docstrings until Python 2.6
3467 # as doctest can't handle __future__ statements
3468
3469 def test_localcontext(self):
3470 # Use a copy of the current context in the block
3471 getcontext = self.decimal.getcontext
3472 localcontext = self.decimal.localcontext
3473
3474 orig_ctx = getcontext()
3475 with localcontext() as enter_ctx:
3476 set_ctx = getcontext()
3477 final_ctx = getcontext()
3478 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
3479 self.assertIsNot(orig_ctx, set_ctx, 'did not copy the context')
3480 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
3481
3482 def test_localcontextarg(self):
3483 # Use a copy of the supplied context in the block
3484 Context = self.decimal.Context
3485 getcontext = self.decimal.getcontext
3486 localcontext = self.decimal.localcontext
3487
3488 localcontext = self.decimal.localcontext
3489 orig_ctx = getcontext()
3490 new_ctx = Context(prec=42)
3491 with localcontext(new_ctx) as enter_ctx:
3492 set_ctx = getcontext()
3493 final_ctx = getcontext()
3494 self.assertIs(orig_ctx, final_ctx, 'did not restore context correctly')
3495 self.assertEqual(set_ctx.prec, new_ctx.prec, 'did not set correct context')
3496 self.assertIsNot(new_ctx, set_ctx, 'did not copy the context')
3497 self.assertIs(set_ctx, enter_ctx, '__enter__ returned wrong context')
3498
3499 def test_nested_with_statements(self):
3500 # Use a copy of the supplied context in the block
3501 Decimal = self.decimal.Decimal
3502 Context = self.decimal.Context
3503 getcontext = self.decimal.getcontext
3504 localcontext = self.decimal.localcontext
3505 Clamped = self.decimal.Clamped
3506 Overflow = self.decimal.Overflow
3507
3508 orig_ctx = getcontext()
3509 orig_ctx.clear_flags()
3510 new_ctx = Context(Emax=384)
3511 with localcontext() as c1:
3512 self.assertEqual(c1.flags, orig_ctx.flags)
3513 self.assertEqual(c1.traps, orig_ctx.traps)
3514 c1.traps[Clamped] = True
3515 c1.Emin = -383
3516 self.assertNotEqual(orig_ctx.Emin, -383)
3517 self.assertRaises(Clamped, c1.create_decimal, '0e-999')
3518 self.assertTrue(c1.flags[Clamped])
3519 with localcontext(new_ctx) as c2:
3520 self.assertEqual(c2.flags, new_ctx.flags)
3521 self.assertEqual(c2.traps, new_ctx.traps)
3522 self.assertRaises(Overflow, c2.power, Decimal('3.4e200'), 2)
3523 self.assertFalse(c2.flags[Clamped])
3524 self.assertTrue(c2.flags[Overflow])
3525 del c2
3526 self.assertFalse(c1.flags[Overflow])
3527 del c1
3528 self.assertNotEqual(orig_ctx.Emin, -383)
3529 self.assertFalse(orig_ctx.flags[Clamped])
3530 self.assertFalse(orig_ctx.flags[Overflow])
3531 self.assertFalse(new_ctx.flags[Clamped])
3532 self.assertFalse(new_ctx.flags[Overflow])
3533
3534 def test_with_statements_gc1(self):
3535 localcontext = self.decimal.localcontext
3536
3537 with localcontext() as c1:
3538 del c1
3539 with localcontext() as c2:
3540 del c2
3541 with localcontext() as c3:
3542 del c3
3543 with localcontext() as c4:
3544 del c4
3545
3546 def test_with_statements_gc2(self):
3547 localcontext = self.decimal.localcontext
3548
3549 with localcontext() as c1:
3550 with localcontext(c1) as c2:
3551 del c1
3552 with localcontext(c2) as c3:
3553 del c2
3554 with localcontext(c3) as c4:
3555 del c3
3556 del c4
3557
3558 def test_with_statements_gc3(self):
3559 Context = self.decimal.Context
3560 localcontext = self.decimal.localcontext
3561 getcontext = self.decimal.getcontext
3562 setcontext = self.decimal.setcontext
3563
3564 with localcontext() as c1:
3565 del c1
3566 n1 = Context(prec=1)
3567 setcontext(n1)
3568 with localcontext(n1) as c2:
3569 del n1
3570 self.assertEqual(c2.prec, 1)
3571 del c2
3572 n2 = Context(prec=2)
3573 setcontext(n2)
3574 del n2
3575 self.assertEqual(getcontext().prec, 2)
3576 n3 = Context(prec=3)
3577 setcontext(n3)
3578 self.assertEqual(getcontext().prec, 3)
3579 with localcontext(n3) as c3:
3580 del n3
3581 self.assertEqual(c3.prec, 3)
3582 del c3
3583 n4 = Context(prec=4)
3584 setcontext(n4)
3585 del n4
3586 self.assertEqual(getcontext().prec, 4)
3587 with localcontext() as c4:
3588 self.assertEqual(c4.prec, 4)
3589 del c4
3590
3591class CContextWithStatement(ContextWithStatement):
3592 decimal = C
3593class PyContextWithStatement(ContextWithStatement):
3594 decimal = P
3595
3596class ContextFlags(unittest.TestCase):
3597
3598 def test_flags_irrelevant(self):
3599 # check that the result (numeric result + flags raised) of an
3600 # arithmetic operation doesn't depend on the current flags
3601 Decimal = self.decimal.Decimal
3602 Context = self.decimal.Context
3603 Inexact = self.decimal.Inexact
3604 Rounded = self.decimal.Rounded
3605 Underflow = self.decimal.Underflow
3606 Clamped = self.decimal.Clamped
3607 Subnormal = self.decimal.Subnormal
Stefan Krah1919b7e2012-03-21 18:25:23 +01003608
3609 def raise_error(context, flag):
3610 if self.decimal == C:
3611 context.flags[flag] = True
3612 if context.traps[flag]:
3613 raise flag
3614 else:
3615 context._raise_error(flag)
3616
3617 context = Context(prec=9, Emin = -425000000, Emax = 425000000,
3618 rounding=ROUND_HALF_EVEN, traps=[], flags=[])
3619
3620 # operations that raise various flags, in the form (function, arglist)
3621 operations = [
3622 (context._apply, [Decimal("100E-425000010")]),
3623 (context.sqrt, [Decimal(2)]),
3624 (context.add, [Decimal("1.23456789"), Decimal("9.87654321")]),
3625 (context.multiply, [Decimal("1.23456789"), Decimal("9.87654321")]),
3626 (context.subtract, [Decimal("1.23456789"), Decimal("9.87654321")]),
3627 ]
3628
3629 # try various flags individually, then a whole lot at once
3630 flagsets = [[Inexact], [Rounded], [Underflow], [Clamped], [Subnormal],
3631 [Inexact, Rounded, Underflow, Clamped, Subnormal]]
3632
3633 for fn, args in operations:
3634 # find answer and flags raised using a clean context
3635 context.clear_flags()
3636 ans = fn(*args)
3637 flags = [k for k, v in context.flags.items() if v]
3638
3639 for extra_flags in flagsets:
3640 # set flags, before calling operation
3641 context.clear_flags()
3642 for flag in extra_flags:
3643 raise_error(context, flag)
3644 new_ans = fn(*args)
3645
3646 # flags that we expect to be set after the operation
3647 expected_flags = list(flags)
3648 for flag in extra_flags:
3649 if flag not in expected_flags:
3650 expected_flags.append(flag)
3651 expected_flags.sort(key=id)
3652
3653 # flags we actually got
3654 new_flags = [k for k,v in context.flags.items() if v]
3655 new_flags.sort(key=id)
3656
3657 self.assertEqual(ans, new_ans,
3658 "operation produces different answers depending on flags set: " +
3659 "expected %s, got %s." % (ans, new_ans))
3660 self.assertEqual(new_flags, expected_flags,
3661 "operation raises different flags depending on flags set: " +
3662 "expected %s, got %s" % (expected_flags, new_flags))
3663
3664 def test_flag_comparisons(self):
3665 Context = self.decimal.Context
3666 Inexact = self.decimal.Inexact
3667 Rounded = self.decimal.Rounded
3668
3669 c = Context()
3670
3671 # Valid SignalDict
3672 self.assertNotEqual(c.flags, c.traps)
3673 self.assertNotEqual(c.traps, c.flags)
3674
3675 c.flags = c.traps
3676 self.assertEqual(c.flags, c.traps)
3677 self.assertEqual(c.traps, c.flags)
3678
3679 c.flags[Rounded] = True
3680 c.traps = c.flags
3681 self.assertEqual(c.flags, c.traps)
3682 self.assertEqual(c.traps, c.flags)
3683
3684 d = {}
3685 d.update(c.flags)
3686 self.assertEqual(d, c.flags)
3687 self.assertEqual(c.flags, d)
3688
3689 d[Inexact] = True
3690 self.assertNotEqual(d, c.flags)
3691 self.assertNotEqual(c.flags, d)
3692
3693 # Invalid SignalDict
3694 d = {Inexact:False}
3695 self.assertNotEqual(d, c.flags)
3696 self.assertNotEqual(c.flags, d)
3697
3698 d = ["xyz"]
3699 self.assertNotEqual(d, c.flags)
3700 self.assertNotEqual(c.flags, d)
3701
3702 @requires_IEEE_754
3703 def test_float_operation(self):
3704 Decimal = self.decimal.Decimal
3705 FloatOperation = self.decimal.FloatOperation
3706 localcontext = self.decimal.localcontext
3707
3708 with localcontext() as c:
3709 ##### trap is off by default
3710 self.assertFalse(c.traps[FloatOperation])
3711
3712 # implicit conversion sets the flag
3713 c.clear_flags()
3714 self.assertEqual(Decimal(7.5), 7.5)
3715 self.assertTrue(c.flags[FloatOperation])
3716
3717 c.clear_flags()
3718 self.assertEqual(c.create_decimal(7.5), 7.5)
3719 self.assertTrue(c.flags[FloatOperation])
3720
3721 # explicit conversion does not set the flag
3722 c.clear_flags()
3723 x = Decimal.from_float(7.5)
3724 self.assertFalse(c.flags[FloatOperation])
3725 # comparison sets the flag
3726 self.assertEqual(x, 7.5)
3727 self.assertTrue(c.flags[FloatOperation])
3728
3729 c.clear_flags()
3730 x = c.create_decimal_from_float(7.5)
3731 self.assertFalse(c.flags[FloatOperation])
3732 self.assertEqual(x, 7.5)
3733 self.assertTrue(c.flags[FloatOperation])
3734
3735 ##### set the trap
3736 c.traps[FloatOperation] = True
3737
3738 # implicit conversion raises
3739 c.clear_flags()
3740 self.assertRaises(FloatOperation, Decimal, 7.5)
3741 self.assertTrue(c.flags[FloatOperation])
3742
3743 c.clear_flags()
3744 self.assertRaises(FloatOperation, c.create_decimal, 7.5)
3745 self.assertTrue(c.flags[FloatOperation])
3746
3747 # explicit conversion is silent
3748 c.clear_flags()
3749 x = Decimal.from_float(7.5)
3750 self.assertFalse(c.flags[FloatOperation])
3751
3752 c.clear_flags()
3753 x = c.create_decimal_from_float(7.5)
3754 self.assertFalse(c.flags[FloatOperation])
3755
3756 def test_float_comparison(self):
3757 Decimal = self.decimal.Decimal
3758 Context = self.decimal.Context
3759 FloatOperation = self.decimal.FloatOperation
3760 localcontext = self.decimal.localcontext
3761
3762 def assert_attr(a, b, attr, context, signal=None):
3763 context.clear_flags()
3764 f = getattr(a, attr)
3765 if signal == FloatOperation:
3766 self.assertRaises(signal, f, b)
3767 else:
3768 self.assertIs(f(b), True)
3769 self.assertTrue(context.flags[FloatOperation])
3770
3771 small_d = Decimal('0.25')
3772 big_d = Decimal('3.0')
3773 small_f = 0.25
3774 big_f = 3.0
3775
3776 zero_d = Decimal('0.0')
3777 neg_zero_d = Decimal('-0.0')
3778 zero_f = 0.0
3779 neg_zero_f = -0.0
3780
3781 inf_d = Decimal('Infinity')
3782 neg_inf_d = Decimal('-Infinity')
3783 inf_f = float('inf')
3784 neg_inf_f = float('-inf')
3785
3786 def doit(c, signal=None):
3787 # Order
3788 for attr in '__lt__', '__le__':
3789 assert_attr(small_d, big_f, attr, c, signal)
3790
3791 for attr in '__gt__', '__ge__':
3792 assert_attr(big_d, small_f, attr, c, signal)
3793
3794 # Equality
3795 assert_attr(small_d, small_f, '__eq__', c, None)
3796
3797 assert_attr(neg_zero_d, neg_zero_f, '__eq__', c, None)
3798 assert_attr(neg_zero_d, zero_f, '__eq__', c, None)
3799
3800 assert_attr(zero_d, neg_zero_f, '__eq__', c, None)
3801 assert_attr(zero_d, zero_f, '__eq__', c, None)
3802
3803 assert_attr(neg_inf_d, neg_inf_f, '__eq__', c, None)
3804 assert_attr(inf_d, inf_f, '__eq__', c, None)
3805
3806 # Inequality
3807 assert_attr(small_d, big_f, '__ne__', c, None)
3808
3809 assert_attr(Decimal('0.1'), 0.1, '__ne__', c, None)
3810
3811 assert_attr(neg_inf_d, inf_f, '__ne__', c, None)
3812 assert_attr(inf_d, neg_inf_f, '__ne__', c, None)
3813
3814 assert_attr(Decimal('NaN'), float('nan'), '__ne__', c, None)
3815
3816 def test_containers(c, signal=None):
3817 c.clear_flags()
3818 s = set([100.0, Decimal('100.0')])
3819 self.assertEqual(len(s), 1)
3820 self.assertTrue(c.flags[FloatOperation])
3821
3822 c.clear_flags()
3823 if signal:
3824 self.assertRaises(signal, sorted, [1.0, Decimal('10.0')])
3825 else:
3826 s = sorted([10.0, Decimal('10.0')])
3827 self.assertTrue(c.flags[FloatOperation])
3828
3829 c.clear_flags()
3830 b = 10.0 in [Decimal('10.0'), 1.0]
3831 self.assertTrue(c.flags[FloatOperation])
3832
3833 c.clear_flags()
3834 b = 10.0 in {Decimal('10.0'):'a', 1.0:'b'}
3835 self.assertTrue(c.flags[FloatOperation])
3836
3837 nc = Context()
3838 with localcontext(nc) as c:
3839 self.assertFalse(c.traps[FloatOperation])
3840 doit(c, signal=None)
3841 test_containers(c, signal=None)
3842
3843 c.traps[FloatOperation] = True
3844 doit(c, signal=FloatOperation)
3845 test_containers(c, signal=FloatOperation)
3846
3847 def test_float_operation_default(self):
3848 Decimal = self.decimal.Decimal
3849 Context = self.decimal.Context
3850 Inexact = self.decimal.Inexact
3851 FloatOperation= self.decimal.FloatOperation
3852
3853 context = Context()
3854 self.assertFalse(context.flags[FloatOperation])
3855 self.assertFalse(context.traps[FloatOperation])
3856
3857 context.clear_traps()
3858 context.traps[Inexact] = True
3859 context.traps[FloatOperation] = True
3860 self.assertTrue(context.traps[FloatOperation])
3861 self.assertTrue(context.traps[Inexact])
3862
3863class CContextFlags(ContextFlags):
3864 decimal = C
3865class PyContextFlags(ContextFlags):
3866 decimal = P
3867
3868class SpecialContexts(unittest.TestCase):
3869 """Test the context templates."""
3870
3871 def test_context_templates(self):
3872 BasicContext = self.decimal.BasicContext
3873 ExtendedContext = self.decimal.ExtendedContext
3874 getcontext = self.decimal.getcontext
3875 setcontext = self.decimal.setcontext
3876 InvalidOperation = self.decimal.InvalidOperation
3877 DivisionByZero = self.decimal.DivisionByZero
3878 Overflow = self.decimal.Overflow
3879 Underflow = self.decimal.Underflow
3880 Clamped = self.decimal.Clamped
3881
3882 assert_signals(self, BasicContext, 'traps',
3883 [InvalidOperation, DivisionByZero, Overflow, Underflow, Clamped]
3884 )
3885
3886 savecontext = getcontext().copy()
3887 basic_context_prec = BasicContext.prec
3888 extended_context_prec = ExtendedContext.prec
3889
3890 ex = None
3891 try:
3892 BasicContext.prec = ExtendedContext.prec = 441
3893 for template in BasicContext, ExtendedContext:
3894 setcontext(template)
3895 c = getcontext()
3896 self.assertIsNot(c, template)
3897 self.assertEqual(c.prec, 441)
3898 except Exception as e:
3899 ex = e.__class__
3900 finally:
3901 BasicContext.prec = basic_context_prec
3902 ExtendedContext.prec = extended_context_prec
3903 setcontext(savecontext)
3904 if ex:
3905 raise ex
3906
3907 def test_default_context(self):
3908 DefaultContext = self.decimal.DefaultContext
3909 BasicContext = self.decimal.BasicContext
3910 ExtendedContext = self.decimal.ExtendedContext
3911 getcontext = self.decimal.getcontext
3912 setcontext = self.decimal.setcontext
3913 InvalidOperation = self.decimal.InvalidOperation
3914 DivisionByZero = self.decimal.DivisionByZero
3915 Overflow = self.decimal.Overflow
3916
3917 self.assertEqual(BasicContext.prec, 9)
3918 self.assertEqual(ExtendedContext.prec, 9)
3919
3920 assert_signals(self, DefaultContext, 'traps',
3921 [InvalidOperation, DivisionByZero, Overflow]
3922 )
3923
3924 savecontext = getcontext().copy()
3925 default_context_prec = DefaultContext.prec
3926
3927 ex = None
3928 try:
3929 c = getcontext()
3930 saveprec = c.prec
3931
3932 DefaultContext.prec = 961
3933 c = getcontext()
3934 self.assertEqual(c.prec, saveprec)
3935
3936 setcontext(DefaultContext)
3937 c = getcontext()
3938 self.assertIsNot(c, DefaultContext)
3939 self.assertEqual(c.prec, 961)
3940 except Exception as e:
3941 ex = e.__class__
3942 finally:
3943 DefaultContext.prec = default_context_prec
3944 setcontext(savecontext)
3945 if ex:
3946 raise ex
3947
3948class CSpecialContexts(SpecialContexts):
3949 decimal = C
3950class PySpecialContexts(SpecialContexts):
3951 decimal = P
3952
3953class ContextInputValidation(unittest.TestCase):
3954
3955 def test_invalid_context(self):
3956 Context = self.decimal.Context
3957 DefaultContext = self.decimal.DefaultContext
3958
3959 c = DefaultContext.copy()
3960
3961 # prec, Emax
3962 for attr in ['prec', 'Emax']:
3963 setattr(c, attr, 999999)
3964 self.assertEqual(getattr(c, attr), 999999)
3965 self.assertRaises(ValueError, setattr, c, attr, -1)
3966 self.assertRaises(TypeError, setattr, c, attr, 'xyz')
3967
3968 # Emin
3969 setattr(c, 'Emin', -999999)
3970 self.assertEqual(getattr(c, 'Emin'), -999999)
3971 self.assertRaises(ValueError, setattr, c, 'Emin', 1)
3972 self.assertRaises(TypeError, setattr, c, 'Emin', (1,2,3))
3973
Stefan Krah1919b7e2012-03-21 18:25:23 +01003974 self.assertRaises(TypeError, setattr, c, 'rounding', -1)
3975 self.assertRaises(TypeError, setattr, c, 'rounding', 9)
3976 self.assertRaises(TypeError, setattr, c, 'rounding', 1.0)
3977 self.assertRaises(TypeError, setattr, c, 'rounding', 'xyz')
3978
3979 # capitals, clamp
3980 for attr in ['capitals', 'clamp']:
3981 self.assertRaises(ValueError, setattr, c, attr, -1)
3982 self.assertRaises(ValueError, setattr, c, attr, 2)
3983 self.assertRaises(TypeError, setattr, c, attr, [1,2,3])
3984
3985 # Invalid attribute
3986 self.assertRaises(AttributeError, setattr, c, 'emax', 100)
3987
3988 # Invalid signal dict
3989 self.assertRaises(TypeError, setattr, c, 'flags', [])
3990 self.assertRaises(KeyError, setattr, c, 'flags', {})
3991 self.assertRaises(KeyError, setattr, c, 'traps',
3992 {'InvalidOperation':0})
3993
3994 # Attributes cannot be deleted
3995 for attr in ['prec', 'Emax', 'Emin', 'rounding', 'capitals', 'clamp',
3996 'flags', 'traps']:
3997 self.assertRaises(AttributeError, c.__delattr__, attr)
3998
3999 # Invalid attributes
4000 self.assertRaises(TypeError, getattr, c, 9)
4001 self.assertRaises(TypeError, setattr, c, 9)
4002
4003 # Invalid values in constructor
4004 self.assertRaises(TypeError, Context, rounding=999999)
4005 self.assertRaises(TypeError, Context, rounding='xyz')
4006 self.assertRaises(ValueError, Context, clamp=2)
4007 self.assertRaises(ValueError, Context, capitals=-1)
4008 self.assertRaises(KeyError, Context, flags=["P"])
4009 self.assertRaises(KeyError, Context, traps=["Q"])
4010
4011 # Type error in conversion
4012 self.assertRaises(TypeError, Context, flags=(0,1))
4013 self.assertRaises(TypeError, Context, traps=(1,0))
4014
4015class CContextInputValidation(ContextInputValidation):
4016 decimal = C
4017class PyContextInputValidation(ContextInputValidation):
4018 decimal = P
4019
4020class ContextSubclassing(unittest.TestCase):
4021
4022 def test_context_subclassing(self):
4023 decimal = self.decimal
4024 Decimal = decimal.Decimal
4025 Context = decimal.Context
Stefan Krah1919b7e2012-03-21 18:25:23 +01004026 Clamped = decimal.Clamped
4027 DivisionByZero = decimal.DivisionByZero
4028 Inexact = decimal.Inexact
4029 Overflow = decimal.Overflow
4030 Rounded = decimal.Rounded
4031 Subnormal = decimal.Subnormal
4032 Underflow = decimal.Underflow
4033 InvalidOperation = decimal.InvalidOperation
4034
4035 class MyContext(Context):
4036 def __init__(self, prec=None, rounding=None, Emin=None, Emax=None,
4037 capitals=None, clamp=None, flags=None,
4038 traps=None):
4039 Context.__init__(self)
4040 if prec is not None:
4041 self.prec = prec
4042 if rounding is not None:
4043 self.rounding = rounding
4044 if Emin is not None:
4045 self.Emin = Emin
4046 if Emax is not None:
4047 self.Emax = Emax
4048 if capitals is not None:
4049 self.capitals = capitals
4050 if clamp is not None:
4051 self.clamp = clamp
4052 if flags is not None:
4053 if isinstance(flags, list):
4054 flags = {v:(v in flags) for v in OrderedSignals[decimal] + flags}
4055 self.flags = flags
4056 if traps is not None:
4057 if isinstance(traps, list):
4058 traps = {v:(v in traps) for v in OrderedSignals[decimal] + traps}
4059 self.traps = traps
4060
4061 c = Context()
4062 d = MyContext()
4063 for attr in ('prec', 'rounding', 'Emin', 'Emax', 'capitals', 'clamp',
4064 'flags', 'traps'):
4065 self.assertEqual(getattr(c, attr), getattr(d, attr))
4066
4067 # prec
4068 self.assertRaises(ValueError, MyContext, **{'prec':-1})
4069 c = MyContext(prec=1)
4070 self.assertEqual(c.prec, 1)
4071 self.assertRaises(InvalidOperation, c.quantize, Decimal('9e2'), 0)
4072
4073 # rounding
4074 self.assertRaises(TypeError, MyContext, **{'rounding':'XYZ'})
4075 c = MyContext(rounding=ROUND_DOWN, prec=1)
4076 self.assertEqual(c.rounding, ROUND_DOWN)
4077 self.assertEqual(c.plus(Decimal('9.9')), 9)
4078
4079 # Emin
4080 self.assertRaises(ValueError, MyContext, **{'Emin':5})
4081 c = MyContext(Emin=-1, prec=1)
4082 self.assertEqual(c.Emin, -1)
4083 x = c.add(Decimal('1e-99'), Decimal('2.234e-2000'))
4084 self.assertEqual(x, Decimal('0.0'))
4085 for signal in (Inexact, Underflow, Subnormal, Rounded, Clamped):
4086 self.assertTrue(c.flags[signal])
4087
4088 # Emax
4089 self.assertRaises(ValueError, MyContext, **{'Emax':-1})
4090 c = MyContext(Emax=1, prec=1)
4091 self.assertEqual(c.Emax, 1)
4092 self.assertRaises(Overflow, c.add, Decimal('1e99'), Decimal('2.234e2000'))
4093 if self.decimal == C:
4094 for signal in (Inexact, Overflow, Rounded):
4095 self.assertTrue(c.flags[signal])
4096
4097 # capitals
4098 self.assertRaises(ValueError, MyContext, **{'capitals':-1})
4099 c = MyContext(capitals=0)
4100 self.assertEqual(c.capitals, 0)
4101 x = c.create_decimal('1E222')
4102 self.assertEqual(c.to_sci_string(x), '1e+222')
4103
4104 # clamp
4105 self.assertRaises(ValueError, MyContext, **{'clamp':2})
4106 c = MyContext(clamp=1, Emax=99)
4107 self.assertEqual(c.clamp, 1)
4108 x = c.plus(Decimal('1e99'))
4109 self.assertEqual(str(x), '1.000000000000000000000000000E+99')
4110
4111 # flags
4112 self.assertRaises(TypeError, MyContext, **{'flags':'XYZ'})
4113 c = MyContext(flags=[Rounded, DivisionByZero])
4114 for signal in (Rounded, DivisionByZero):
4115 self.assertTrue(c.flags[signal])
4116 c.clear_flags()
4117 for signal in OrderedSignals[decimal]:
4118 self.assertFalse(c.flags[signal])
4119
4120 # traps
4121 self.assertRaises(TypeError, MyContext, **{'traps':'XYZ'})
4122 c = MyContext(traps=[Rounded, DivisionByZero])
4123 for signal in (Rounded, DivisionByZero):
4124 self.assertTrue(c.traps[signal])
4125 c.clear_traps()
4126 for signal in OrderedSignals[decimal]:
4127 self.assertFalse(c.traps[signal])
4128
4129class CContextSubclassing(ContextSubclassing):
4130 decimal = C
4131class PyContextSubclassing(ContextSubclassing):
4132 decimal = P
4133
4134@skip_if_extra_functionality
4135class CheckAttributes(unittest.TestCase):
4136
4137 def test_module_attributes(self):
4138
4139 # Architecture dependent context limits
4140 self.assertEqual(C.MAX_PREC, P.MAX_PREC)
4141 self.assertEqual(C.MAX_EMAX, P.MAX_EMAX)
4142 self.assertEqual(C.MIN_EMIN, P.MIN_EMIN)
4143 self.assertEqual(C.MIN_ETINY, P.MIN_ETINY)
4144
4145 self.assertTrue(C.HAVE_THREADS is True or C.HAVE_THREADS is False)
4146 self.assertTrue(P.HAVE_THREADS is True or P.HAVE_THREADS is False)
4147
4148 self.assertEqual(C.__version__, P.__version__)
4149
4150 x = dir(C)
4151 y = [s for s in dir(P) if '__' in s or not s.startswith('_')]
Stefan Krahfe17b2b2012-03-25 18:59:21 +02004152 self.assertEqual(set(x) - set(y), set())
Stefan Krah1919b7e2012-03-21 18:25:23 +01004153
4154 def test_context_attributes(self):
4155
4156 x = [s for s in dir(C.Context()) if '__' in s or not s.startswith('_')]
4157 y = [s for s in dir(P.Context()) if '__' in s or not s.startswith('_')]
4158 self.assertEqual(set(x) - set(y), set())
4159
4160 def test_decimal_attributes(self):
4161
4162 x = [s for s in dir(C.Decimal(9)) if '__' in s or not s.startswith('_')]
4163 y = [s for s in dir(C.Decimal(9)) if '__' in s or not s.startswith('_')]
4164 self.assertEqual(set(x) - set(y), set())
4165
4166class Coverage(unittest.TestCase):
4167
4168 def test_adjusted(self):
4169 Decimal = self.decimal.Decimal
4170
4171 self.assertEqual(Decimal('1234e9999').adjusted(), 10002)
4172 # XXX raise?
4173 self.assertEqual(Decimal('nan').adjusted(), 0)
4174 self.assertEqual(Decimal('inf').adjusted(), 0)
4175
4176 def test_canonical(self):
4177 Decimal = self.decimal.Decimal
4178 getcontext = self.decimal.getcontext
4179
4180 x = Decimal(9).canonical()
4181 self.assertEqual(x, 9)
4182
4183 c = getcontext()
4184 x = c.canonical(Decimal(9))
4185 self.assertEqual(x, 9)
4186
4187 def test_context_repr(self):
4188 c = self.decimal.DefaultContext.copy()
4189
4190 c.prec = 425000000
4191 c.Emax = 425000000
4192 c.Emin = -425000000
Stefan Krah59a4a932013-01-16 12:58:59 +01004193 c.rounding = ROUND_HALF_DOWN
Stefan Krah1919b7e2012-03-21 18:25:23 +01004194 c.capitals = 0
4195 c.clamp = 1
4196 for sig in OrderedSignals[self.decimal]:
4197 c.flags[sig] = False
4198 c.traps[sig] = False
4199
4200 s = c.__repr__()
4201 t = "Context(prec=425000000, rounding=ROUND_HALF_DOWN, " \
4202 "Emin=-425000000, Emax=425000000, capitals=0, clamp=1, " \
4203 "flags=[], traps=[])"
4204 self.assertEqual(s, t)
4205
4206 def test_implicit_context(self):
4207 Decimal = self.decimal.Decimal
4208 localcontext = self.decimal.localcontext
4209
4210 with localcontext() as c:
4211 c.prec = 1
4212 c.Emax = 1
4213 c.Emin = -1
4214
4215 # abs
4216 self.assertEqual(abs(Decimal("-10")), 10)
4217 # add
4218 self.assertEqual(Decimal("7") + 1, 8)
4219 # divide
4220 self.assertEqual(Decimal("10") / 5, 2)
4221 # divide_int
4222 self.assertEqual(Decimal("10") // 7, 1)
4223 # fma
4224 self.assertEqual(Decimal("1.2").fma(Decimal("0.01"), 1), 1)
4225 self.assertIs(Decimal("NaN").fma(7, 1).is_nan(), True)
4226 # three arg power
4227 self.assertEqual(pow(Decimal(10), 2, 7), 2)
4228 # exp
4229 self.assertEqual(Decimal("1.01").exp(), 3)
4230 # is_normal
4231 self.assertIs(Decimal("0.01").is_normal(), False)
4232 # is_subnormal
4233 self.assertIs(Decimal("0.01").is_subnormal(), True)
4234 # ln
4235 self.assertEqual(Decimal("20").ln(), 3)
4236 # log10
4237 self.assertEqual(Decimal("20").log10(), 1)
4238 # logb
4239 self.assertEqual(Decimal("580").logb(), 2)
4240 # logical_invert
4241 self.assertEqual(Decimal("10").logical_invert(), 1)
4242 # minus
4243 self.assertEqual(-Decimal("-10"), 10)
4244 # multiply
4245 self.assertEqual(Decimal("2") * 4, 8)
4246 # next_minus
4247 self.assertEqual(Decimal("10").next_minus(), 9)
4248 # next_plus
4249 self.assertEqual(Decimal("10").next_plus(), Decimal('2E+1'))
4250 # normalize
4251 self.assertEqual(Decimal("-10").normalize(), Decimal('-1E+1'))
4252 # number_class
4253 self.assertEqual(Decimal("10").number_class(), '+Normal')
4254 # plus
4255 self.assertEqual(+Decimal("-1"), -1)
4256 # remainder
4257 self.assertEqual(Decimal("10") % 7, 3)
4258 # subtract
4259 self.assertEqual(Decimal("10") - 7, 3)
4260 # to_integral_exact
4261 self.assertEqual(Decimal("1.12345").to_integral_exact(), 1)
4262
4263 # Boolean functions
4264 self.assertTrue(Decimal("1").is_canonical())
4265 self.assertTrue(Decimal("1").is_finite())
4266 self.assertTrue(Decimal("1").is_finite())
4267 self.assertTrue(Decimal("snan").is_snan())
4268 self.assertTrue(Decimal("-1").is_signed())
4269 self.assertTrue(Decimal("0").is_zero())
4270 self.assertTrue(Decimal("0").is_zero())
4271
4272 # Copy
4273 with localcontext() as c:
4274 c.prec = 10000
4275 x = 1228 ** 1523
4276 y = -Decimal(x)
4277
4278 z = y.copy_abs()
4279 self.assertEqual(z, x)
4280
4281 z = y.copy_negate()
4282 self.assertEqual(z, x)
4283
4284 z = y.copy_sign(Decimal(1))
4285 self.assertEqual(z, x)
4286
4287 def test_divmod(self):
4288 Decimal = self.decimal.Decimal
4289 localcontext = self.decimal.localcontext
4290 InvalidOperation = self.decimal.InvalidOperation
4291 DivisionByZero = self.decimal.DivisionByZero
4292
4293 with localcontext() as c:
4294 q, r = divmod(Decimal("10912837129"), 1001)
4295 self.assertEqual(q, Decimal('10901935'))
4296 self.assertEqual(r, Decimal('194'))
4297
4298 q, r = divmod(Decimal("NaN"), 7)
4299 self.assertTrue(q.is_nan() and r.is_nan())
4300
4301 c.traps[InvalidOperation] = False
4302 q, r = divmod(Decimal("NaN"), 7)
4303 self.assertTrue(q.is_nan() and r.is_nan())
4304
4305 c.traps[InvalidOperation] = False
4306 c.clear_flags()
4307 q, r = divmod(Decimal("inf"), Decimal("inf"))
4308 self.assertTrue(q.is_nan() and r.is_nan())
4309 self.assertTrue(c.flags[InvalidOperation])
4310
4311 c.clear_flags()
4312 q, r = divmod(Decimal("inf"), 101)
4313 self.assertTrue(q.is_infinite() and r.is_nan())
4314 self.assertTrue(c.flags[InvalidOperation])
4315
4316 c.clear_flags()
4317 q, r = divmod(Decimal(0), 0)
4318 self.assertTrue(q.is_nan() and r.is_nan())
4319 self.assertTrue(c.flags[InvalidOperation])
4320
4321 c.traps[DivisionByZero] = False
4322 c.clear_flags()
4323 q, r = divmod(Decimal(11), 0)
4324 self.assertTrue(q.is_infinite() and r.is_nan())
4325 self.assertTrue(c.flags[InvalidOperation] and
4326 c.flags[DivisionByZero])
4327
4328 def test_power(self):
4329 Decimal = self.decimal.Decimal
4330 localcontext = self.decimal.localcontext
4331 Overflow = self.decimal.Overflow
4332 Rounded = self.decimal.Rounded
4333
4334 with localcontext() as c:
4335 c.prec = 3
4336 c.clear_flags()
4337 self.assertEqual(Decimal("1.0") ** 100, Decimal('1.00'))
4338 self.assertTrue(c.flags[Rounded])
4339
4340 c.prec = 1
4341 c.Emax = 1
4342 c.Emin = -1
4343 c.clear_flags()
4344 c.traps[Overflow] = False
4345 self.assertEqual(Decimal(10000) ** Decimal("0.5"), Decimal('inf'))
4346 self.assertTrue(c.flags[Overflow])
4347
4348 def test_quantize(self):
4349 Decimal = self.decimal.Decimal
4350 localcontext = self.decimal.localcontext
4351 InvalidOperation = self.decimal.InvalidOperation
4352
4353 with localcontext() as c:
4354 c.prec = 1
4355 c.Emax = 1
4356 c.Emin = -1
4357 c.traps[InvalidOperation] = False
4358 x = Decimal(99).quantize(Decimal("1e1"))
4359 self.assertTrue(x.is_nan())
4360
4361 def test_radix(self):
4362 Decimal = self.decimal.Decimal
4363 getcontext = self.decimal.getcontext
4364
4365 c = getcontext()
4366 self.assertEqual(Decimal("1").radix(), 10)
4367 self.assertEqual(c.radix(), 10)
4368
4369 def test_rop(self):
4370 Decimal = self.decimal.Decimal
4371
4372 for attr in ('__radd__', '__rsub__', '__rmul__', '__rtruediv__',
4373 '__rdivmod__', '__rmod__', '__rfloordiv__', '__rpow__'):
4374 self.assertIs(getattr(Decimal("1"), attr)("xyz"), NotImplemented)
4375
4376 def test_round(self):
4377 # Python3 behavior: round() returns Decimal
4378 Decimal = self.decimal.Decimal
4379 getcontext = self.decimal.getcontext
4380
4381 c = getcontext()
4382 c.prec = 28
4383
4384 self.assertEqual(str(Decimal("9.99").__round__()), "10")
4385 self.assertEqual(str(Decimal("9.99e-5").__round__()), "0")
4386 self.assertEqual(str(Decimal("1.23456789").__round__(5)), "1.23457")
4387 self.assertEqual(str(Decimal("1.2345").__round__(10)), "1.2345000000")
4388 self.assertEqual(str(Decimal("1.2345").__round__(-10)), "0E+10")
4389
4390 self.assertRaises(TypeError, Decimal("1.23").__round__, "5")
4391 self.assertRaises(TypeError, Decimal("1.23").__round__, 5, 8)
4392
4393 def test_create_decimal(self):
4394 c = self.decimal.Context()
4395 self.assertRaises(ValueError, c.create_decimal, ["%"])
4396
4397 def test_int(self):
4398 Decimal = self.decimal.Decimal
4399 localcontext = self.decimal.localcontext
4400
4401 with localcontext() as c:
4402 c.prec = 9999
4403 x = Decimal(1221**1271) / 10**3923
4404 self.assertEqual(int(x), 1)
4405 self.assertEqual(x.to_integral(), 2)
4406
4407 def test_copy(self):
4408 Context = self.decimal.Context
4409
4410 c = Context()
4411 c.prec = 10000
4412 x = -(1172 ** 1712)
4413
4414 y = c.copy_abs(x)
4415 self.assertEqual(y, -x)
4416
4417 y = c.copy_negate(x)
4418 self.assertEqual(y, -x)
4419
4420 y = c.copy_sign(x, 1)
4421 self.assertEqual(y, -x)
4422
4423class CCoverage(Coverage):
4424 decimal = C
4425class PyCoverage(Coverage):
4426 decimal = P
4427
4428class PyFunctionality(unittest.TestCase):
4429 """Extra functionality in decimal.py"""
4430
4431 def test_py_quantize_watchexp(self):
4432 # watchexp functionality
4433 Decimal = P.Decimal
4434 localcontext = P.localcontext
4435
4436 with localcontext() as c:
4437 c.prec = 1
4438 c.Emax = 1
4439 c.Emin = -1
4440 x = Decimal(99999).quantize(Decimal("1e3"), watchexp=False)
4441 self.assertEqual(x, Decimal('1.00E+5'))
4442
4443 def test_py_alternate_formatting(self):
4444 # triples giving a format, a Decimal, and the expected result
4445 Decimal = P.Decimal
4446 localcontext = P.localcontext
4447
4448 test_values = [
4449 # Issue 7094: Alternate formatting (specified by #)
4450 ('.0e', '1.0', '1e+0'),
4451 ('#.0e', '1.0', '1.e+0'),
4452 ('.0f', '1.0', '1'),
4453 ('#.0f', '1.0', '1.'),
4454 ('g', '1.1', '1.1'),
4455 ('#g', '1.1', '1.1'),
4456 ('.0g', '1', '1'),
4457 ('#.0g', '1', '1.'),
4458 ('.0%', '1.0', '100%'),
4459 ('#.0%', '1.0', '100.%'),
4460 ]
4461 for fmt, d, result in test_values:
4462 self.assertEqual(format(Decimal(d), fmt), result)
4463
4464class PyWhitebox(unittest.TestCase):
4465 """White box testing for decimal.py"""
4466
4467 def test_py_exact_power(self):
4468 # Rarely exercised lines in _power_exact.
4469 Decimal = P.Decimal
4470 localcontext = P.localcontext
4471
4472 with localcontext() as c:
4473 c.prec = 8
4474 x = Decimal(2**16) ** Decimal("-0.5")
4475 self.assertEqual(x, Decimal('0.00390625'))
4476
4477 x = Decimal(2**16) ** Decimal("-0.6")
4478 self.assertEqual(x, Decimal('0.0012885819'))
4479
4480 x = Decimal("256e7") ** Decimal("-0.5")
4481
4482 x = Decimal(152587890625) ** Decimal('-0.0625')
4483 self.assertEqual(x, Decimal("0.2"))
4484
4485 x = Decimal("152587890625e7") ** Decimal('-0.0625')
4486
4487 x = Decimal(5**2659) ** Decimal('-0.0625')
4488
4489 c.prec = 1
4490 x = Decimal("152587890625") ** Decimal('-0.5')
4491 c.prec = 201
4492 x = Decimal(2**578) ** Decimal("-0.5")
4493
4494 def test_py_immutability_operations(self):
Terry Jan Reedy0f847642013-03-11 18:34:00 -04004495 # Do operations and check that it didn't change internal objects.
Stefan Krah1919b7e2012-03-21 18:25:23 +01004496 Decimal = P.Decimal
4497 DefaultContext = P.DefaultContext
4498 setcontext = P.setcontext
4499
4500 c = DefaultContext.copy()
4501 c.traps = dict((s, 0) for s in OrderedSignals[P])
4502 setcontext(c)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004503
4504 d1 = Decimal('-25e55')
4505 b1 = Decimal('-25e55')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004506 d2 = Decimal('33e+33')
4507 b2 = Decimal('33e+33')
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004508
4509 def checkSameDec(operation, useOther=False):
4510 if useOther:
4511 eval("d1." + operation + "(d2)")
4512 self.assertEqual(d1._sign, b1._sign)
4513 self.assertEqual(d1._int, b1._int)
4514 self.assertEqual(d1._exp, b1._exp)
4515 self.assertEqual(d2._sign, b2._sign)
4516 self.assertEqual(d2._int, b2._int)
4517 self.assertEqual(d2._exp, b2._exp)
4518 else:
4519 eval("d1." + operation + "()")
4520 self.assertEqual(d1._sign, b1._sign)
4521 self.assertEqual(d1._int, b1._int)
4522 self.assertEqual(d1._exp, b1._exp)
4523 return
4524
4525 Decimal(d1)
4526 self.assertEqual(d1._sign, b1._sign)
4527 self.assertEqual(d1._int, b1._int)
4528 self.assertEqual(d1._exp, b1._exp)
4529
4530 checkSameDec("__abs__")
4531 checkSameDec("__add__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004532 checkSameDec("__divmod__", True)
Christian Heimes77c02eb2008-02-09 02:18:51 +00004533 checkSameDec("__eq__", True)
4534 checkSameDec("__ne__", True)
4535 checkSameDec("__le__", True)
4536 checkSameDec("__lt__", True)
4537 checkSameDec("__ge__", True)
4538 checkSameDec("__gt__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004539 checkSameDec("__float__")
4540 checkSameDec("__floordiv__", True)
4541 checkSameDec("__hash__")
4542 checkSameDec("__int__")
Christian Heimes969fe572008-01-25 11:23:10 +00004543 checkSameDec("__trunc__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004544 checkSameDec("__mod__", True)
4545 checkSameDec("__mul__", True)
4546 checkSameDec("__neg__")
Jack Diederich4dafcc42006-11-28 19:15:13 +00004547 checkSameDec("__bool__")
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004548 checkSameDec("__pos__")
4549 checkSameDec("__pow__", True)
4550 checkSameDec("__radd__", True)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004551 checkSameDec("__rdivmod__", True)
4552 checkSameDec("__repr__")
4553 checkSameDec("__rfloordiv__", True)
4554 checkSameDec("__rmod__", True)
4555 checkSameDec("__rmul__", True)
4556 checkSameDec("__rpow__", True)
4557 checkSameDec("__rsub__", True)
4558 checkSameDec("__str__")
4559 checkSameDec("__sub__", True)
4560 checkSameDec("__truediv__", True)
4561 checkSameDec("adjusted")
4562 checkSameDec("as_tuple")
4563 checkSameDec("compare", True)
4564 checkSameDec("max", True)
4565 checkSameDec("min", True)
4566 checkSameDec("normalize")
4567 checkSameDec("quantize", True)
4568 checkSameDec("remainder_near", True)
4569 checkSameDec("same_quantum", True)
4570 checkSameDec("sqrt")
4571 checkSameDec("to_eng_string")
4572 checkSameDec("to_integral")
4573
Stefan Krah1919b7e2012-03-21 18:25:23 +01004574 def test_py_decimal_id(self):
4575 Decimal = P.Decimal
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004576
Stefan Krah1919b7e2012-03-21 18:25:23 +01004577 d = Decimal(45)
4578 e = Decimal(d)
4579 self.assertEqual(str(e), '45')
4580 self.assertNotEqual(id(d), id(e))
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004581
Stefan Krah1919b7e2012-03-21 18:25:23 +01004582 def test_py_rescale(self):
4583 # Coverage
4584 Decimal = P.Decimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01004585 localcontext = P.localcontext
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004586
Stefan Krah1919b7e2012-03-21 18:25:23 +01004587 with localcontext() as c:
4588 x = Decimal("NaN")._rescale(3, ROUND_UP)
4589 self.assertTrue(x.is_nan())
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004590
Stefan Krah1919b7e2012-03-21 18:25:23 +01004591 def test_py__round(self):
4592 # Coverage
4593 Decimal = P.Decimal
Christian Heimes0348fb62008-03-26 12:55:56 +00004594
Stefan Krah1919b7e2012-03-21 18:25:23 +01004595 self.assertRaises(ValueError, Decimal("3.1234")._round, 0, ROUND_UP)
Mark Dickinsona2d1fe02009-10-29 12:23:02 +00004596
Stefan Krah1919b7e2012-03-21 18:25:23 +01004597class CFunctionality(unittest.TestCase):
4598 """Extra functionality in _decimal"""
Mark Dickinsona2d1fe02009-10-29 12:23:02 +00004599
Stefan Krah1919b7e2012-03-21 18:25:23 +01004600 @requires_extra_functionality
4601 def test_c_ieee_context(self):
4602 # issue 8786: Add support for IEEE 754 contexts to decimal module.
4603 IEEEContext = C.IEEEContext
4604 DECIMAL32 = C.DECIMAL32
4605 DECIMAL64 = C.DECIMAL64
4606 DECIMAL128 = C.DECIMAL128
Thomas Wouters1b7f8912007-09-19 03:06:30 +00004607
Stefan Krah1919b7e2012-03-21 18:25:23 +01004608 def assert_rest(self, context):
4609 self.assertEqual(context.clamp, 1)
4610 assert_signals(self, context, 'traps', [])
4611 assert_signals(self, context, 'flags', [])
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004612
Stefan Krah1919b7e2012-03-21 18:25:23 +01004613 c = IEEEContext(DECIMAL32)
4614 self.assertEqual(c.prec, 7)
4615 self.assertEqual(c.Emax, 96)
4616 self.assertEqual(c.Emin, -95)
4617 assert_rest(self, c)
Raymond Hettinger82417ca2009-02-03 03:54:28 +00004618
Stefan Krah1919b7e2012-03-21 18:25:23 +01004619 c = IEEEContext(DECIMAL64)
4620 self.assertEqual(c.prec, 16)
4621 self.assertEqual(c.Emax, 384)
4622 self.assertEqual(c.Emin, -383)
4623 assert_rest(self, c)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00004624
Stefan Krah1919b7e2012-03-21 18:25:23 +01004625 c = IEEEContext(DECIMAL128)
4626 self.assertEqual(c.prec, 34)
4627 self.assertEqual(c.Emax, 6144)
4628 self.assertEqual(c.Emin, -6143)
4629 assert_rest(self, c)
Raymond Hettinger5548be22004-07-05 18:49:38 +00004630
Stefan Krah1919b7e2012-03-21 18:25:23 +01004631 # Invalid values
4632 self.assertRaises(OverflowError, IEEEContext, 2**63)
4633 self.assertRaises(ValueError, IEEEContext, -1)
4634 self.assertRaises(ValueError, IEEEContext, 1024)
Mark Dickinson825fce32009-09-07 18:08:12 +00004635
Stefan Krah1919b7e2012-03-21 18:25:23 +01004636 @requires_extra_functionality
4637 def test_c_context(self):
4638 Context = C.Context
Christian Heimes969fe572008-01-25 11:23:10 +00004639
Stefan Krah1919b7e2012-03-21 18:25:23 +01004640 c = Context(flags=C.DecClamped, traps=C.DecRounded)
4641 self.assertEqual(c._flags, C.DecClamped)
4642 self.assertEqual(c._traps, C.DecRounded)
Raymond Hettinger771ed762009-01-03 19:20:32 +00004643
Stefan Krah1919b7e2012-03-21 18:25:23 +01004644 @requires_extra_functionality
4645 def test_constants(self):
4646 # Condition flags
4647 cond = (
4648 C.DecClamped, C.DecConversionSyntax, C.DecDivisionByZero,
4649 C.DecDivisionImpossible, C.DecDivisionUndefined,
4650 C.DecFpuError, C.DecInexact, C.DecInvalidContext,
4651 C.DecInvalidOperation, C.DecMallocError,
4652 C.DecFloatOperation, C.DecOverflow, C.DecRounded,
4653 C.DecSubnormal, C.DecUnderflow
Raymond Hettinger771ed762009-01-03 19:20:32 +00004654 )
Stefan Krah1919b7e2012-03-21 18:25:23 +01004655
4656 # IEEEContext
4657 self.assertEqual(C.DECIMAL32, 32)
4658 self.assertEqual(C.DECIMAL64, 64)
4659 self.assertEqual(C.DECIMAL128, 128)
4660 self.assertEqual(C.IEEE_CONTEXT_MAX_BITS, 512)
4661
Stefan Krah1919b7e2012-03-21 18:25:23 +01004662 # Conditions
4663 for i, v in enumerate(cond):
4664 self.assertEqual(v, 1<<i)
4665
4666 self.assertEqual(C.DecIEEEInvalidOperation,
4667 C.DecConversionSyntax|
4668 C.DecDivisionImpossible|
4669 C.DecDivisionUndefined|
4670 C.DecFpuError|
4671 C.DecInvalidContext|
4672 C.DecInvalidOperation|
4673 C.DecMallocError)
4674
4675 self.assertEqual(C.DecErrors,
4676 C.DecIEEEInvalidOperation|
4677 C.DecDivisionByZero)
4678
4679 self.assertEqual(C.DecTraps,
4680 C.DecErrors|C.DecOverflow|C.DecUnderflow)
4681
4682class CWhitebox(unittest.TestCase):
4683 """Whitebox testing for _decimal"""
4684
4685 def test_bignum(self):
4686 # Not exactly whitebox, but too slow with pydecimal.
4687
4688 Decimal = C.Decimal
4689 localcontext = C.localcontext
4690
4691 b1 = 10**35
4692 b2 = 10**36
4693 with localcontext() as c:
4694 c.prec = 1000000
4695 for i in range(5):
4696 a = random.randrange(b1, b2)
4697 b = random.randrange(1000, 1200)
4698 x = a ** b
4699 y = Decimal(a) ** Decimal(b)
4700 self.assertEqual(x, y)
4701
4702 def test_invalid_construction(self):
4703 self.assertRaises(TypeError, C.Decimal, 9, "xyz")
4704
4705 def test_c_input_restriction(self):
4706 # Too large for _decimal to be converted exactly
4707 Decimal = C.Decimal
4708 InvalidOperation = C.InvalidOperation
4709 Context = C.Context
4710 localcontext = C.localcontext
4711
4712 with localcontext(Context()):
4713 self.assertRaises(InvalidOperation, Decimal,
4714 "1e9999999999999999999")
4715
4716 def test_c_context_repr(self):
4717 # This test is _decimal-only because flags are not printed
4718 # in the same order.
4719 DefaultContext = C.DefaultContext
4720 FloatOperation = C.FloatOperation
Stefan Krah1919b7e2012-03-21 18:25:23 +01004721
4722 c = DefaultContext.copy()
4723
4724 c.prec = 425000000
4725 c.Emax = 425000000
4726 c.Emin = -425000000
4727 c.rounding = ROUND_HALF_DOWN
4728 c.capitals = 0
4729 c.clamp = 1
4730 for sig in OrderedSignals[C]:
4731 c.flags[sig] = True
4732 c.traps[sig] = True
4733 c.flags[FloatOperation] = True
4734 c.traps[FloatOperation] = True
4735
4736 s = c.__repr__()
4737 t = "Context(prec=425000000, rounding=ROUND_HALF_DOWN, " \
4738 "Emin=-425000000, Emax=425000000, capitals=0, clamp=1, " \
4739 "flags=[Clamped, InvalidOperation, DivisionByZero, Inexact, " \
4740 "FloatOperation, Overflow, Rounded, Subnormal, Underflow], " \
4741 "traps=[Clamped, InvalidOperation, DivisionByZero, Inexact, " \
4742 "FloatOperation, Overflow, Rounded, Subnormal, Underflow])"
4743 self.assertEqual(s, t)
4744
4745 def test_c_context_errors(self):
4746 Context = C.Context
4747 InvalidOperation = C.InvalidOperation
4748 Overflow = C.Overflow
4749 FloatOperation = C.FloatOperation
4750 localcontext = C.localcontext
4751 getcontext = C.getcontext
4752 setcontext = C.setcontext
4753 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
4754
4755 c = Context()
4756
4757 # SignalDict: input validation
4758 self.assertRaises(KeyError, c.flags.__setitem__, 801, 0)
4759 self.assertRaises(KeyError, c.traps.__setitem__, 801, 0)
4760 self.assertRaises(ValueError, c.flags.__delitem__, Overflow)
4761 self.assertRaises(ValueError, c.traps.__delitem__, InvalidOperation)
4762 self.assertRaises(TypeError, setattr, c, 'flags', ['x'])
4763 self.assertRaises(TypeError, setattr, c,'traps', ['y'])
4764 self.assertRaises(KeyError, setattr, c, 'flags', {0:1})
4765 self.assertRaises(KeyError, setattr, c, 'traps', {0:1})
4766
4767 # Test assignment from a signal dict with the correct length but
4768 # one invalid key.
4769 d = c.flags.copy()
4770 del d[FloatOperation]
4771 d["XYZ"] = 91283719
4772 self.assertRaises(KeyError, setattr, c, 'flags', d)
4773 self.assertRaises(KeyError, setattr, c, 'traps', d)
4774
4775 # Input corner cases
4776 int_max = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
4777 gt_max_emax = 10**18 if HAVE_CONFIG_64 else 10**9
4778
4779 # prec, Emax, Emin
4780 for attr in ['prec', 'Emax']:
4781 self.assertRaises(ValueError, setattr, c, attr, gt_max_emax)
4782 self.assertRaises(ValueError, setattr, c, 'Emin', -gt_max_emax)
4783
4784 # prec, Emax, Emin in context constructor
4785 self.assertRaises(ValueError, Context, prec=gt_max_emax)
4786 self.assertRaises(ValueError, Context, Emax=gt_max_emax)
4787 self.assertRaises(ValueError, Context, Emin=-gt_max_emax)
4788
4789 # Overflow in conversion
4790 self.assertRaises(OverflowError, Context, prec=int_max+1)
4791 self.assertRaises(OverflowError, Context, Emax=int_max+1)
4792 self.assertRaises(OverflowError, Context, Emin=-int_max-2)
Stefan Krah1919b7e2012-03-21 18:25:23 +01004793 self.assertRaises(OverflowError, Context, clamp=int_max+1)
4794 self.assertRaises(OverflowError, Context, capitals=int_max+1)
4795
4796 # OverflowError, general ValueError
4797 for attr in ('prec', 'Emin', 'Emax', 'capitals', 'clamp'):
4798 self.assertRaises(OverflowError, setattr, c, attr, int_max+1)
4799 self.assertRaises(OverflowError, setattr, c, attr, -int_max-2)
4800 if sys.platform != 'win32':
4801 self.assertRaises(ValueError, setattr, c, attr, int_max)
4802 self.assertRaises(ValueError, setattr, c, attr, -int_max-1)
4803
Stefan Krah1919b7e2012-03-21 18:25:23 +01004804 # OverflowError: _unsafe_setprec, _unsafe_setemin, _unsafe_setemax
4805 if C.MAX_PREC == 425000000:
4806 self.assertRaises(OverflowError, getattr(c, '_unsafe_setprec'),
4807 int_max+1)
4808 self.assertRaises(OverflowError, getattr(c, '_unsafe_setemax'),
4809 int_max+1)
4810 self.assertRaises(OverflowError, getattr(c, '_unsafe_setemin'),
4811 -int_max-2)
4812
4813 # ValueError: _unsafe_setprec, _unsafe_setemin, _unsafe_setemax
4814 if C.MAX_PREC == 425000000:
4815 self.assertRaises(ValueError, getattr(c, '_unsafe_setprec'), 0)
4816 self.assertRaises(ValueError, getattr(c, '_unsafe_setprec'),
4817 1070000001)
4818 self.assertRaises(ValueError, getattr(c, '_unsafe_setemax'), -1)
4819 self.assertRaises(ValueError, getattr(c, '_unsafe_setemax'),
4820 1070000001)
4821 self.assertRaises(ValueError, getattr(c, '_unsafe_setemin'),
4822 -1070000001)
4823 self.assertRaises(ValueError, getattr(c, '_unsafe_setemin'), 1)
4824
4825 # capitals, clamp
4826 for attr in ['capitals', 'clamp']:
4827 self.assertRaises(ValueError, setattr, c, attr, -1)
4828 self.assertRaises(ValueError, setattr, c, attr, 2)
4829 self.assertRaises(TypeError, setattr, c, attr, [1,2,3])
4830 if HAVE_CONFIG_64:
4831 self.assertRaises(ValueError, setattr, c, attr, 2**32)
4832 self.assertRaises(ValueError, setattr, c, attr, 2**32+1)
4833
4834 # Invalid local context
4835 self.assertRaises(TypeError, exec, 'with localcontext("xyz"): pass',
4836 locals())
Stefan Krah040e3112012-12-15 22:33:33 +01004837 self.assertRaises(TypeError, exec,
4838 'with localcontext(context=getcontext()): pass',
4839 locals())
Stefan Krah1919b7e2012-03-21 18:25:23 +01004840
4841 # setcontext
4842 saved_context = getcontext()
4843 self.assertRaises(TypeError, setcontext, "xyz")
4844 setcontext(saved_context)
4845
Stefan Krah59a4a932013-01-16 12:58:59 +01004846 def test_rounding_strings_interned(self):
4847
4848 self.assertIs(C.ROUND_UP, P.ROUND_UP)
4849 self.assertIs(C.ROUND_DOWN, P.ROUND_DOWN)
4850 self.assertIs(C.ROUND_CEILING, P.ROUND_CEILING)
4851 self.assertIs(C.ROUND_FLOOR, P.ROUND_FLOOR)
4852 self.assertIs(C.ROUND_HALF_UP, P.ROUND_HALF_UP)
4853 self.assertIs(C.ROUND_HALF_DOWN, P.ROUND_HALF_DOWN)
4854 self.assertIs(C.ROUND_HALF_EVEN, P.ROUND_HALF_EVEN)
4855 self.assertIs(C.ROUND_05UP, P.ROUND_05UP)
4856
Stefan Krah1919b7e2012-03-21 18:25:23 +01004857 @requires_extra_functionality
4858 def test_c_context_errors_extra(self):
4859 Context = C.Context
4860 InvalidOperation = C.InvalidOperation
4861 Overflow = C.Overflow
4862 localcontext = C.localcontext
4863 getcontext = C.getcontext
4864 setcontext = C.setcontext
4865 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
4866
4867 c = Context()
4868
4869 # Input corner cases
4870 int_max = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
4871
4872 # OverflowError, general ValueError
4873 self.assertRaises(OverflowError, setattr, c, '_allcr', int_max+1)
4874 self.assertRaises(OverflowError, setattr, c, '_allcr', -int_max-2)
4875 if sys.platform != 'win32':
4876 self.assertRaises(ValueError, setattr, c, '_allcr', int_max)
4877 self.assertRaises(ValueError, setattr, c, '_allcr', -int_max-1)
4878
4879 # OverflowError, general TypeError
4880 for attr in ('_flags', '_traps'):
4881 self.assertRaises(OverflowError, setattr, c, attr, int_max+1)
4882 self.assertRaises(OverflowError, setattr, c, attr, -int_max-2)
4883 if sys.platform != 'win32':
4884 self.assertRaises(TypeError, setattr, c, attr, int_max)
4885 self.assertRaises(TypeError, setattr, c, attr, -int_max-1)
4886
4887 # _allcr
4888 self.assertRaises(ValueError, setattr, c, '_allcr', -1)
4889 self.assertRaises(ValueError, setattr, c, '_allcr', 2)
4890 self.assertRaises(TypeError, setattr, c, '_allcr', [1,2,3])
4891 if HAVE_CONFIG_64:
4892 self.assertRaises(ValueError, setattr, c, '_allcr', 2**32)
4893 self.assertRaises(ValueError, setattr, c, '_allcr', 2**32+1)
4894
4895 # _flags, _traps
4896 for attr in ['_flags', '_traps']:
4897 self.assertRaises(TypeError, setattr, c, attr, 999999)
4898 self.assertRaises(TypeError, setattr, c, attr, 'x')
4899
4900 def test_c_valid_context(self):
4901 # These tests are for code coverage in _decimal.
4902 DefaultContext = C.DefaultContext
Stefan Krah1919b7e2012-03-21 18:25:23 +01004903 Clamped = C.Clamped
4904 Underflow = C.Underflow
4905 Inexact = C.Inexact
4906 Rounded = C.Rounded
4907 Subnormal = C.Subnormal
4908
4909 c = DefaultContext.copy()
4910
4911 # Exercise all getters and setters
4912 c.prec = 34
4913 c.rounding = ROUND_HALF_UP
4914 c.Emax = 3000
4915 c.Emin = -3000
4916 c.capitals = 1
4917 c.clamp = 0
4918
4919 self.assertEqual(c.prec, 34)
4920 self.assertEqual(c.rounding, ROUND_HALF_UP)
4921 self.assertEqual(c.Emin, -3000)
4922 self.assertEqual(c.Emax, 3000)
4923 self.assertEqual(c.capitals, 1)
4924 self.assertEqual(c.clamp, 0)
4925
4926 self.assertEqual(c.Etiny(), -3033)
4927 self.assertEqual(c.Etop(), 2967)
4928
4929 # Exercise all unsafe setters
4930 if C.MAX_PREC == 425000000:
4931 c._unsafe_setprec(999999999)
4932 c._unsafe_setemax(999999999)
4933 c._unsafe_setemin(-999999999)
4934 self.assertEqual(c.prec, 999999999)
4935 self.assertEqual(c.Emax, 999999999)
4936 self.assertEqual(c.Emin, -999999999)
4937
4938 @requires_extra_functionality
4939 def test_c_valid_context_extra(self):
4940 DefaultContext = C.DefaultContext
4941
4942 c = DefaultContext.copy()
4943 self.assertEqual(c._allcr, 1)
4944 c._allcr = 0
4945 self.assertEqual(c._allcr, 0)
4946
4947 def test_c_round(self):
4948 # Restricted input.
4949 Decimal = C.Decimal
4950 InvalidOperation = C.InvalidOperation
4951 localcontext = C.localcontext
4952 MAX_EMAX = C.MAX_EMAX
4953 MIN_ETINY = C.MIN_ETINY
4954 int_max = 2**63-1 if C.MAX_PREC > 425000000 else 2**31-1
4955
4956 with localcontext() as c:
4957 c.traps[InvalidOperation] = True
4958 self.assertRaises(InvalidOperation, Decimal("1.23").__round__,
4959 -int_max-1)
4960 self.assertRaises(InvalidOperation, Decimal("1.23").__round__,
4961 int_max)
4962 self.assertRaises(InvalidOperation, Decimal("1").__round__,
4963 int(MAX_EMAX+1))
4964 self.assertRaises(C.InvalidOperation, Decimal("1").__round__,
4965 -int(MIN_ETINY-1))
4966 self.assertRaises(OverflowError, Decimal("1.23").__round__,
4967 -int_max-2)
4968 self.assertRaises(OverflowError, Decimal("1.23").__round__,
4969 int_max+1)
4970
4971 def test_c_format(self):
4972 # Restricted input
4973 Decimal = C.Decimal
Stefan Krah1919b7e2012-03-21 18:25:23 +01004974 HAVE_CONFIG_64 = (C.MAX_PREC > 425000000)
4975
4976 self.assertRaises(TypeError, Decimal(1).__format__, "=10.10", [], 9)
4977 self.assertRaises(TypeError, Decimal(1).__format__, "=10.10", 9)
4978 self.assertRaises(TypeError, Decimal(1).__format__, [])
4979
Stefan Kraheb8c4512013-01-24 15:22:33 +01004980 self.assertRaises(ValueError, Decimal(1).__format__, "<>=10.10")
4981 maxsize = 2**63-1 if HAVE_CONFIG_64 else 2**31-1
4982 self.assertRaises(ValueError, Decimal("1.23456789").__format__,
4983 "=%d.1" % maxsize)
Stefan Krah1919b7e2012-03-21 18:25:23 +01004984
4985 def test_c_integral(self):
4986 Decimal = C.Decimal
4987 Inexact = C.Inexact
Stefan Krah1919b7e2012-03-21 18:25:23 +01004988 localcontext = C.localcontext
4989
4990 x = Decimal(10)
4991 self.assertEqual(x.to_integral(), 10)
4992 self.assertRaises(TypeError, x.to_integral, '10')
4993 self.assertRaises(TypeError, x.to_integral, 10, 'x')
4994 self.assertRaises(TypeError, x.to_integral, 10)
4995
4996 self.assertEqual(x.to_integral_value(), 10)
4997 self.assertRaises(TypeError, x.to_integral_value, '10')
4998 self.assertRaises(TypeError, x.to_integral_value, 10, 'x')
4999 self.assertRaises(TypeError, x.to_integral_value, 10)
5000
5001 self.assertEqual(x.to_integral_exact(), 10)
5002 self.assertRaises(TypeError, x.to_integral_exact, '10')
5003 self.assertRaises(TypeError, x.to_integral_exact, 10, 'x')
5004 self.assertRaises(TypeError, x.to_integral_exact, 10)
5005
5006 with localcontext() as c:
5007 x = Decimal("99999999999999999999999999.9").to_integral_value(ROUND_UP)
5008 self.assertEqual(x, Decimal('100000000000000000000000000'))
5009
5010 x = Decimal("99999999999999999999999999.9").to_integral_exact(ROUND_UP)
5011 self.assertEqual(x, Decimal('100000000000000000000000000'))
5012
5013 c.traps[Inexact] = True
5014 self.assertRaises(Inexact, Decimal("999.9").to_integral_exact, ROUND_UP)
5015
5016 def test_c_funcs(self):
5017 # Invalid arguments
5018 Decimal = C.Decimal
5019 InvalidOperation = C.InvalidOperation
5020 DivisionByZero = C.DivisionByZero
Stefan Krah1919b7e2012-03-21 18:25:23 +01005021 getcontext = C.getcontext
5022 localcontext = C.localcontext
5023
5024 self.assertEqual(Decimal('9.99e10').to_eng_string(), '99.9E+9')
5025
5026 self.assertRaises(TypeError, pow, Decimal(1), 2, "3")
5027 self.assertRaises(TypeError, Decimal(9).number_class, "x", "y")
5028 self.assertRaises(TypeError, Decimal(9).same_quantum, 3, "x", "y")
5029
Raymond Hettinger771ed762009-01-03 19:20:32 +00005030 self.assertRaises(
Stefan Krah1919b7e2012-03-21 18:25:23 +01005031 TypeError,
5032 Decimal("1.23456789").quantize, Decimal('1e-100000'), []
Raymond Hettinger771ed762009-01-03 19:20:32 +00005033 )
Stefan Krah1919b7e2012-03-21 18:25:23 +01005034 self.assertRaises(
5035 TypeError,
5036 Decimal("1.23456789").quantize, Decimal('1e-100000'), getcontext()
5037 )
5038 self.assertRaises(
5039 TypeError,
5040 Decimal("1.23456789").quantize, Decimal('1e-100000'), 10
5041 )
5042 self.assertRaises(
5043 TypeError,
5044 Decimal("1.23456789").quantize, Decimal('1e-100000'), ROUND_UP, 1000
5045 )
Raymond Hettinger771ed762009-01-03 19:20:32 +00005046
Stefan Krah1919b7e2012-03-21 18:25:23 +01005047 with localcontext() as c:
5048 c.clear_traps()
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00005049
Stefan Krah1919b7e2012-03-21 18:25:23 +01005050 # Invalid arguments
5051 self.assertRaises(TypeError, c.copy_sign, Decimal(1), "x", "y")
5052 self.assertRaises(TypeError, c.canonical, 200)
5053 self.assertRaises(TypeError, c.is_canonical, 200)
5054 self.assertRaises(TypeError, c.divmod, 9, 8, "x", "y")
5055 self.assertRaises(TypeError, c.same_quantum, 9, 3, "x", "y")
Raymond Hettingerd9c0a7a2004-07-03 10:02:28 +00005056
Stefan Krah1919b7e2012-03-21 18:25:23 +01005057 self.assertEqual(str(c.canonical(Decimal(200))), '200')
5058 self.assertEqual(c.radix(), 10)
Raymond Hettinger0aeac102004-07-05 22:53:03 +00005059
Stefan Krah1919b7e2012-03-21 18:25:23 +01005060 c.traps[DivisionByZero] = True
5061 self.assertRaises(DivisionByZero, Decimal(9).__divmod__, 0)
5062 self.assertRaises(DivisionByZero, c.divmod, 9, 0)
5063 self.assertTrue(c.flags[InvalidOperation])
Raymond Hettinger955d2b22004-08-08 20:17:45 +00005064
Stefan Krah1919b7e2012-03-21 18:25:23 +01005065 c.clear_flags()
5066 c.traps[InvalidOperation] = True
5067 self.assertRaises(InvalidOperation, Decimal(9).__divmod__, 0)
5068 self.assertRaises(InvalidOperation, c.divmod, 9, 0)
5069 self.assertTrue(c.flags[DivisionByZero])
Mark Dickinsonb1d8e322010-05-22 18:35:36 +00005070
Stefan Krah1919b7e2012-03-21 18:25:23 +01005071 c.traps[InvalidOperation] = True
5072 c.prec = 2
5073 self.assertRaises(InvalidOperation, pow, Decimal(1000), 1, 501)
Mark Dickinson84230a12010-02-18 14:49:50 +00005074
Stefan Krah040e3112012-12-15 22:33:33 +01005075 def test_va_args_exceptions(self):
5076 Decimal = C.Decimal
5077 Context = C.Context
5078
5079 x = Decimal("10001111111")
5080
5081 for attr in ['exp', 'is_normal', 'is_subnormal', 'ln', 'log10',
5082 'logb', 'logical_invert', 'next_minus', 'next_plus',
5083 'normalize', 'number_class', 'sqrt', 'to_eng_string']:
5084 func = getattr(x, attr)
5085 self.assertRaises(TypeError, func, context="x")
5086 self.assertRaises(TypeError, func, "x", context=None)
5087
5088 for attr in ['compare', 'compare_signal', 'logical_and',
5089 'logical_or', 'max', 'max_mag', 'min', 'min_mag',
5090 'remainder_near', 'rotate', 'scaleb', 'shift']:
5091 func = getattr(x, attr)
5092 self.assertRaises(TypeError, func, context="x")
5093 self.assertRaises(TypeError, func, "x", context=None)
5094
5095 self.assertRaises(TypeError, x.to_integral, rounding=None, context=[])
5096 self.assertRaises(TypeError, x.to_integral, rounding={}, context=[])
5097 self.assertRaises(TypeError, x.to_integral, [], [])
5098
5099 self.assertRaises(TypeError, x.to_integral_value, rounding=None, context=[])
5100 self.assertRaises(TypeError, x.to_integral_value, rounding={}, context=[])
5101 self.assertRaises(TypeError, x.to_integral_value, [], [])
5102
5103 self.assertRaises(TypeError, x.to_integral_exact, rounding=None, context=[])
5104 self.assertRaises(TypeError, x.to_integral_exact, rounding={}, context=[])
5105 self.assertRaises(TypeError, x.to_integral_exact, [], [])
5106
5107 self.assertRaises(TypeError, x.fma, 1, 2, context="x")
5108 self.assertRaises(TypeError, x.fma, 1, 2, "x", context=None)
5109
5110 self.assertRaises(TypeError, x.quantize, 1, [], context=None)
5111 self.assertRaises(TypeError, x.quantize, 1, [], rounding=None)
5112 self.assertRaises(TypeError, x.quantize, 1, [], [])
5113
5114 c = Context()
5115 self.assertRaises(TypeError, c.power, 1, 2, mod="x")
5116 self.assertRaises(TypeError, c.power, 1, "x", mod=None)
5117 self.assertRaises(TypeError, c.power, "x", 2, mod=None)
5118
Stefan Krah1919b7e2012-03-21 18:25:23 +01005119 @requires_extra_functionality
5120 def test_c_context_templates(self):
5121 self.assertEqual(
5122 C.BasicContext._traps,
5123 C.DecIEEEInvalidOperation|C.DecDivisionByZero|C.DecOverflow|
5124 C.DecUnderflow|C.DecClamped
5125 )
5126 self.assertEqual(
5127 C.DefaultContext._traps,
5128 C.DecIEEEInvalidOperation|C.DecDivisionByZero|C.DecOverflow
5129 )
Mark Dickinson84230a12010-02-18 14:49:50 +00005130
Stefan Krah1919b7e2012-03-21 18:25:23 +01005131 @requires_extra_functionality
5132 def test_c_signal_dict(self):
Mark Dickinson84230a12010-02-18 14:49:50 +00005133
Stefan Krah1919b7e2012-03-21 18:25:23 +01005134 # SignalDict coverage
5135 Context = C.Context
5136 DefaultContext = C.DefaultContext
Mark Dickinson84230a12010-02-18 14:49:50 +00005137
Stefan Krah1919b7e2012-03-21 18:25:23 +01005138 InvalidOperation = C.InvalidOperation
5139 DivisionByZero = C.DivisionByZero
5140 Overflow = C.Overflow
5141 Subnormal = C.Subnormal
5142 Underflow = C.Underflow
5143 Rounded = C.Rounded
5144 Inexact = C.Inexact
5145 Clamped = C.Clamped
Mark Dickinson84230a12010-02-18 14:49:50 +00005146
Stefan Krah1919b7e2012-03-21 18:25:23 +01005147 DecClamped = C.DecClamped
5148 DecInvalidOperation = C.DecInvalidOperation
5149 DecIEEEInvalidOperation = C.DecIEEEInvalidOperation
Mark Dickinson84230a12010-02-18 14:49:50 +00005150
Stefan Krah1919b7e2012-03-21 18:25:23 +01005151 def assertIsExclusivelySet(signal, signal_dict):
5152 for sig in signal_dict:
5153 if sig == signal:
5154 self.assertTrue(signal_dict[sig])
5155 else:
5156 self.assertFalse(signal_dict[sig])
Mark Dickinson84230a12010-02-18 14:49:50 +00005157
Stefan Krah1919b7e2012-03-21 18:25:23 +01005158 c = DefaultContext.copy()
Mark Dickinson84230a12010-02-18 14:49:50 +00005159
Stefan Krah1919b7e2012-03-21 18:25:23 +01005160 # Signal dict methods
5161 self.assertTrue(Overflow in c.traps)
5162 c.clear_traps()
5163 for k in c.traps.keys():
5164 c.traps[k] = True
5165 for v in c.traps.values():
5166 self.assertTrue(v)
5167 c.clear_traps()
5168 for k, v in c.traps.items():
5169 self.assertFalse(v)
Mark Dickinson84230a12010-02-18 14:49:50 +00005170
Stefan Krah1919b7e2012-03-21 18:25:23 +01005171 self.assertFalse(c.flags.get(Overflow))
5172 self.assertIs(c.flags.get("x"), None)
5173 self.assertEqual(c.flags.get("x", "y"), "y")
5174 self.assertRaises(TypeError, c.flags.get, "x", "y", "z")
Mark Dickinson84230a12010-02-18 14:49:50 +00005175
Stefan Krah1919b7e2012-03-21 18:25:23 +01005176 self.assertEqual(len(c.flags), len(c.traps))
5177 s = sys.getsizeof(c.flags)
5178 s = sys.getsizeof(c.traps)
5179 s = c.flags.__repr__()
Mark Dickinson84230a12010-02-18 14:49:50 +00005180
Stefan Krah1919b7e2012-03-21 18:25:23 +01005181 # Set flags/traps.
5182 c.clear_flags()
5183 c._flags = DecClamped
5184 self.assertTrue(c.flags[Clamped])
Mark Dickinson84230a12010-02-18 14:49:50 +00005185
Stefan Krah1919b7e2012-03-21 18:25:23 +01005186 c.clear_traps()
5187 c._traps = DecInvalidOperation
5188 self.assertTrue(c.traps[InvalidOperation])
Mark Dickinson84230a12010-02-18 14:49:50 +00005189
Stefan Krah1919b7e2012-03-21 18:25:23 +01005190 # Set flags/traps from dictionary.
5191 c.clear_flags()
5192 d = c.flags.copy()
5193 d[DivisionByZero] = True
5194 c.flags = d
5195 assertIsExclusivelySet(DivisionByZero, c.flags)
Mark Dickinson84230a12010-02-18 14:49:50 +00005196
Stefan Krah1919b7e2012-03-21 18:25:23 +01005197 c.clear_traps()
5198 d = c.traps.copy()
5199 d[Underflow] = True
5200 c.traps = d
5201 assertIsExclusivelySet(Underflow, c.traps)
Mark Dickinson84230a12010-02-18 14:49:50 +00005202
Stefan Krah1919b7e2012-03-21 18:25:23 +01005203 # Random constructors
5204 IntSignals = {
5205 Clamped: C.DecClamped,
5206 Rounded: C.DecRounded,
5207 Inexact: C.DecInexact,
5208 Subnormal: C.DecSubnormal,
5209 Underflow: C.DecUnderflow,
5210 Overflow: C.DecOverflow,
5211 DivisionByZero: C.DecDivisionByZero,
5212 InvalidOperation: C.DecIEEEInvalidOperation
5213 }
5214 IntCond = [
5215 C.DecDivisionImpossible, C.DecDivisionUndefined, C.DecFpuError,
5216 C.DecInvalidContext, C.DecInvalidOperation, C.DecMallocError,
5217 C.DecConversionSyntax,
5218 ]
Mark Dickinsonb455e582011-05-22 12:53:18 +01005219
Stefan Krah1919b7e2012-03-21 18:25:23 +01005220 lim = len(OrderedSignals[C])
5221 for r in range(lim):
5222 for t in range(lim):
Stefan Krah59a4a932013-01-16 12:58:59 +01005223 for round in RoundingModes:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005224 flags = random.sample(OrderedSignals[C], r)
5225 traps = random.sample(OrderedSignals[C], t)
5226 prec = random.randrange(1, 10000)
5227 emin = random.randrange(-10000, 0)
5228 emax = random.randrange(0, 10000)
5229 clamp = random.randrange(0, 2)
5230 caps = random.randrange(0, 2)
5231 cr = random.randrange(0, 2)
5232 c = Context(prec=prec, rounding=round, Emin=emin, Emax=emax,
5233 capitals=caps, clamp=clamp, flags=list(flags),
5234 traps=list(traps))
Mark Dickinson84230a12010-02-18 14:49:50 +00005235
Stefan Krah1919b7e2012-03-21 18:25:23 +01005236 self.assertEqual(c.prec, prec)
5237 self.assertEqual(c.rounding, round)
5238 self.assertEqual(c.Emin, emin)
5239 self.assertEqual(c.Emax, emax)
5240 self.assertEqual(c.capitals, caps)
5241 self.assertEqual(c.clamp, clamp)
Mark Dickinson84230a12010-02-18 14:49:50 +00005242
Stefan Krah1919b7e2012-03-21 18:25:23 +01005243 f = 0
5244 for x in flags:
5245 f |= IntSignals[x]
5246 self.assertEqual(c._flags, f)
Mark Dickinson84230a12010-02-18 14:49:50 +00005247
Stefan Krah1919b7e2012-03-21 18:25:23 +01005248 f = 0
5249 for x in traps:
5250 f |= IntSignals[x]
5251 self.assertEqual(c._traps, f)
Mark Dickinson84230a12010-02-18 14:49:50 +00005252
Stefan Krah1919b7e2012-03-21 18:25:23 +01005253 for cond in IntCond:
5254 c._flags = cond
5255 self.assertTrue(c._flags&DecIEEEInvalidOperation)
5256 assertIsExclusivelySet(InvalidOperation, c.flags)
Mark Dickinson84230a12010-02-18 14:49:50 +00005257
Stefan Krah1919b7e2012-03-21 18:25:23 +01005258 for cond in IntCond:
5259 c._traps = cond
5260 self.assertTrue(c._traps&DecIEEEInvalidOperation)
5261 assertIsExclusivelySet(InvalidOperation, c.traps)
Mark Dickinson84230a12010-02-18 14:49:50 +00005262
Stefan Krah1919b7e2012-03-21 18:25:23 +01005263 def test_invalid_override(self):
5264 Decimal = C.Decimal
Mark Dickinson84230a12010-02-18 14:49:50 +00005265
Stefan Krah1919b7e2012-03-21 18:25:23 +01005266 try:
5267 from locale import CHAR_MAX
5268 except ImportError:
5269 return
Mark Dickinson84230a12010-02-18 14:49:50 +00005270
Stefan Krah1919b7e2012-03-21 18:25:23 +01005271 def make_grouping(lst):
5272 return ''.join([chr(x) for x in lst])
Mark Dickinson84230a12010-02-18 14:49:50 +00005273
Stefan Krah1919b7e2012-03-21 18:25:23 +01005274 def get_fmt(x, override=None, fmt='n'):
5275 return Decimal(x).__format__(fmt, override)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005276
Stefan Krah1919b7e2012-03-21 18:25:23 +01005277 invalid_grouping = {
5278 'decimal_point' : ',',
5279 'grouping' : make_grouping([255, 255, 0]),
5280 'thousands_sep' : ','
5281 }
5282 invalid_dot = {
5283 'decimal_point' : 'xxxxx',
5284 'grouping' : make_grouping([3, 3, 0]),
5285 'thousands_sep' : ','
5286 }
5287 invalid_sep = {
5288 'decimal_point' : '.',
5289 'grouping' : make_grouping([3, 3, 0]),
5290 'thousands_sep' : 'yyyyy'
5291 }
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005292
Stefan Krah1919b7e2012-03-21 18:25:23 +01005293 if CHAR_MAX == 127: # negative grouping in override
5294 self.assertRaises(ValueError, get_fmt, 12345,
5295 invalid_grouping, 'g')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005296
Stefan Krah1919b7e2012-03-21 18:25:23 +01005297 self.assertRaises(ValueError, get_fmt, 12345, invalid_dot, 'g')
5298 self.assertRaises(ValueError, get_fmt, 12345, invalid_sep, 'g')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005299
Stefan Krah0774e9b2012-04-05 15:21:58 +02005300 def test_exact_conversion(self):
5301 Decimal = C.Decimal
5302 localcontext = C.localcontext
5303 InvalidOperation = C.InvalidOperation
5304
5305 with localcontext() as c:
5306
5307 c.traps[InvalidOperation] = True
5308
5309 # Clamped
5310 x = "0e%d" % sys.maxsize
5311 self.assertRaises(InvalidOperation, Decimal, x)
5312
5313 x = "0e%d" % (-sys.maxsize-1)
5314 self.assertRaises(InvalidOperation, Decimal, x)
5315
5316 # Overflow
5317 x = "1e%d" % sys.maxsize
5318 self.assertRaises(InvalidOperation, Decimal, x)
5319
5320 # Underflow
5321 x = "1e%d" % (-sys.maxsize-1)
5322 self.assertRaises(InvalidOperation, Decimal, x)
5323
Stefan Krahff3eca02012-04-05 15:46:19 +02005324 def test_from_tuple(self):
5325 Decimal = C.Decimal
5326 localcontext = C.localcontext
5327 InvalidOperation = C.InvalidOperation
5328 Overflow = C.Overflow
5329 Underflow = C.Underflow
5330
5331 with localcontext() as c:
5332
5333 c.traps[InvalidOperation] = True
5334 c.traps[Overflow] = True
5335 c.traps[Underflow] = True
5336
5337 # SSIZE_MAX
5338 x = (1, (), sys.maxsize)
5339 self.assertEqual(str(c.create_decimal(x)), '-0E+999999')
5340 self.assertRaises(InvalidOperation, Decimal, x)
5341
5342 x = (1, (0, 1, 2), sys.maxsize)
5343 self.assertRaises(Overflow, c.create_decimal, x)
5344 self.assertRaises(InvalidOperation, Decimal, x)
5345
5346 # SSIZE_MIN
5347 x = (1, (), -sys.maxsize-1)
5348 self.assertEqual(str(c.create_decimal(x)), '-0E-1000026')
5349 self.assertRaises(InvalidOperation, Decimal, x)
5350
5351 x = (1, (0, 1, 2), -sys.maxsize-1)
5352 self.assertRaises(Underflow, c.create_decimal, x)
5353 self.assertRaises(InvalidOperation, Decimal, x)
5354
5355 # OverflowError
5356 x = (1, (), sys.maxsize+1)
5357 self.assertRaises(OverflowError, c.create_decimal, x)
5358 self.assertRaises(OverflowError, Decimal, x)
5359
5360 x = (1, (), -sys.maxsize-2)
5361 self.assertRaises(OverflowError, c.create_decimal, x)
5362 self.assertRaises(OverflowError, Decimal, x)
5363
5364 # Specials
5365 x = (1, (), "N")
5366 self.assertEqual(str(Decimal(x)), '-sNaN')
5367 x = (1, (0,), "N")
5368 self.assertEqual(str(Decimal(x)), '-sNaN')
5369 x = (1, (0, 1), "N")
5370 self.assertEqual(str(Decimal(x)), '-sNaN1')
5371
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005372
Stefan Krah1919b7e2012-03-21 18:25:23 +01005373all_tests = [
5374 CExplicitConstructionTest, PyExplicitConstructionTest,
5375 CImplicitConstructionTest, PyImplicitConstructionTest,
5376 CFormatTest, PyFormatTest,
5377 CArithmeticOperatorsTest, PyArithmeticOperatorsTest,
5378 CThreadingTest, PyThreadingTest,
5379 CUsabilityTest, PyUsabilityTest,
5380 CPythonAPItests, PyPythonAPItests,
5381 CContextAPItests, PyContextAPItests,
5382 CContextWithStatement, PyContextWithStatement,
5383 CContextFlags, PyContextFlags,
5384 CSpecialContexts, PySpecialContexts,
5385 CContextInputValidation, PyContextInputValidation,
5386 CContextSubclassing, PyContextSubclassing,
5387 CCoverage, PyCoverage,
5388 CFunctionality, PyFunctionality,
5389 CWhitebox, PyWhitebox,
5390 CIBMTestCases, PyIBMTestCases,
5391]
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005392
Stefan Krah1919b7e2012-03-21 18:25:23 +01005393# Delete C tests if _decimal.so is not present.
5394if not C:
5395 all_tests = all_tests[1::2]
5396else:
5397 all_tests.insert(0, CheckAttributes)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005398
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005399
5400def test_main(arith=False, verbose=None, todo_tests=None, debug=None):
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005401 """ Execute the tests.
5402
Raymond Hettingered20ad82004-09-04 20:09:13 +00005403 Runs all arithmetic tests if arith is True or if the "decimal" resource
5404 is enabled in regrtest.py
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005405 """
Raymond Hettingered20ad82004-09-04 20:09:13 +00005406
Stefan Krah1919b7e2012-03-21 18:25:23 +01005407 init(C)
5408 init(P)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005409 global TEST_ALL, DEBUG
Raymond Hettingered20ad82004-09-04 20:09:13 +00005410 TEST_ALL = arith or is_resource_enabled('decimal')
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005411 DEBUG = debug
Raymond Hettingered20ad82004-09-04 20:09:13 +00005412
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005413 if todo_tests is None:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005414 test_classes = all_tests
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005415 else:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005416 test_classes = [CIBMTestCases, PyIBMTestCases]
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005417
5418 # Dynamically build custom test definition for each file in the test
5419 # directory and add the definitions to the DecimalTest class. This
5420 # procedure insures that new files do not get skipped.
5421 for filename in os.listdir(directory):
5422 if '.decTest' not in filename or filename.startswith("."):
5423 continue
5424 head, tail = filename.split('.')
5425 if todo_tests is not None and head not in todo_tests:
5426 continue
5427 tester = lambda self, f=filename: self.eval_file(directory + f)
Stefan Krah1919b7e2012-03-21 18:25:23 +01005428 setattr(CIBMTestCases, 'test_' + head, tester)
5429 setattr(PyIBMTestCases, 'test_' + head, tester)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005430 del filename, head, tail, tester
5431
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005432
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005433 try:
5434 run_unittest(*test_classes)
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005435 if todo_tests is None:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005436 from doctest import IGNORE_EXCEPTION_DETAIL
5437 savedecimal = sys.modules['decimal']
5438 if C:
5439 sys.modules['decimal'] = C
5440 run_doctest(C, verbose, optionflags=IGNORE_EXCEPTION_DETAIL)
5441 sys.modules['decimal'] = P
5442 run_doctest(P, verbose)
5443 sys.modules['decimal'] = savedecimal
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00005444 finally:
Stefan Krah1919b7e2012-03-21 18:25:23 +01005445 if C: C.setcontext(ORIGINAL_CONTEXT[C])
5446 P.setcontext(ORIGINAL_CONTEXT[P])
5447 if not C:
5448 warnings.warn('C tests skipped: no module named _decimal.',
5449 UserWarning)
5450 if not orig_sys_decimal is sys.modules['decimal']:
5451 raise TestFailed("Internal error: unbalanced number of changes to "
5452 "sys.modules['decimal'].")
5453
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005454
5455if __name__ == '__main__':
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005456 import optparse
5457 p = optparse.OptionParser("test_decimal.py [--debug] [{--skip | test1 [test2 [...]]}]")
5458 p.add_option('--debug', '-d', action='store_true', help='shows the test number and context before each test')
5459 p.add_option('--skip', '-s', action='store_true', help='skip over 90% of the arithmetic tests')
5460 (opt, args) = p.parse_args()
5461
5462 if opt.skip:
5463 test_main(arith=False, verbose=True)
5464 elif args:
5465 test_main(arith=True, verbose=True, todo_tests=args, debug=opt.debug)
Raymond Hettinger7c85fa42004-07-01 11:01:35 +00005466 else:
Thomas Wouters1b7f8912007-09-19 03:06:30 +00005467 test_main(arith=True, verbose=True)